intermodal_rs/cmd/image/inspect/
mod.rs1use std::collections::HashMap;
4use std::io;
5use std::string::String;
6
7use serde::Serialize;
8
9use crate::cmd::image::ImageCommands;
10use crate::image::{oci::digest::Digest, transports};
11
12#[derive(Serialize)]
16struct InspectOutput<'a> {
17 #[serde(rename = "Name", skip_serializing_if = "Option::is_none")]
18 name: Option<String>,
19
20 #[serde(rename = "Tag", skip_serializing_if = "Option::is_none")]
21 tag: Option<String>,
22
23 #[serde(rename = "Digest")]
24 digest: &'a str,
25
26 #[serde(rename = "RepoTags")]
27 repo_tags: &'a Vec<String>,
28
29 #[serde(rename = "Created")]
30 created: &'a str,
31
32 #[serde(rename = "DockerVersion")]
33 docker_version: &'a str,
34
35 #[serde(rename = "Labels")]
36 labels: &'a HashMap<String, String>,
37
38 #[serde(rename = "Architecture")]
39 architecture: &'a str,
40
41 #[serde(rename = "Os")]
42 os: &'a str,
43
44 #[serde(rename = "Layers")]
45 layers: &'a Vec<String>,
46
47 #[serde(rename = "Env")]
48 env: &'a Vec<String>,
49}
50
51pub async fn run_subcmd_inspect(cmd: ImageCommands) -> io::Result<()> {
53 if let ImageCommands::Inspect {
54 name: ref image_name,
55 config,
56 raw,
57 } = cmd
58 {
59 log::debug!("Image Name: {}", image_name);
60
61 if let Ok(image_ref) = transports::parse_image_name(image_name) {
62 log::debug!(
63 "Valid Reference found! {}",
64 image_ref.string_within_transport()
65 );
66
67 let mut image = image_ref.new_image()?;
68
69 log::debug!("calling get_manifest");
70 let manifest = image.manifest().await?;
71
72 let digeststr = Digest::from_bytes(&manifest.manifest).to_string();
73
74 if raw {
75 println!(
76 "Manifest for {}: {}",
77 image_name,
78 std::str::from_utf8(&manifest.manifest).unwrap()
79 );
80 }
81
82 if config {
83 log::debug!("Getting Config for the image.");
84 if raw {
85 println!(
86 "Config Blob for Image '{}' : {}",
87 image_name,
88 std::str::from_utf8(&image.config_blob().await?).unwrap()
89 );
90 } else {
91 let inspect_data = image.inspect().await?;
92 let tags = image.source_ref().get_repo_tags().await?;
93 log::debug!("Tags: {:#?}", tags);
94
95 let docker_ref = image_ref.docker_reference();
96
97 let mut reference_name: Option<String> = None;
98 let mut reference_tag: Option<String> = None;
99 if docker_ref.is_some() {
100 reference_name = Some(docker_ref.as_ref().unwrap().name());
101 reference_tag = Some(docker_ref.as_ref().unwrap().tag());
102 }
103
104 let output = InspectOutput {
105 name: reference_name,
106 tag: reference_tag,
107 digest: &digeststr,
108 repo_tags: &tags,
109 created: &inspect_data.created,
110 docker_version: &inspect_data.docker_version,
111 labels: &inspect_data.labels,
112 architecture: &inspect_data.architecture,
113 os: &inspect_data.os,
114 layers: &inspect_data.layers,
115 env: &inspect_data.env,
116 };
117 println!("{}", serde_json::to_string_pretty(&output).unwrap());
118 }
119 }
120
121 Ok(())
122 } else {
123 let err = format!("Invalid Image Name: {}", image_name);
124 log::error!("{}", &err);
125 Err(io::Error::new(io::ErrorKind::InvalidInput, err))
126 }
127 } else {
128 let err = format!("Invalid Command: {:?}", cmd);
129 log::error!("{}", &err);
130 Err(io::Error::new(io::ErrorKind::InvalidInput, err))
131 }
132}
133
134#[cfg(test)]
135mod tests {
136
137 use super::*;
138 use crate::image::transports;
139
140 #[test]
141 fn test_subcommand_inspect_no_name() {
142 let m = add_subcmd_inspect().get_matches_from_safe(vec!["inspect"]);
143 assert!(m.is_err());
144 }
145
146 #[test]
147 fn test_subcommand_image_name() {
148 let m = add_subcmd_inspect()
149 .get_matches_from_safe(vec!["inspect", "fedora"])
150 .unwrap();
151
152 assert_eq!(m.value_of("name"), Some("fedora"));
153 }
154
155 #[test]
156 fn test_unsupported_flag() {
157 let m = add_subcmd_inspect().get_matches_from_safe(vec!["inspect", "--war"]);
158
159 assert!(m.is_err());
160 }
161
162 #[tokio::test]
163 async fn test_subcommand_run_success() {
164 transports::init_transports();
165 let m = add_subcmd_inspect()
166 .get_matches_from_safe(vec!["inspec", "docker://fedora"])
167 .unwrap();
168 let name = m.value_of("name").unwrap();
169
170 assert_eq!(name, "docker://fedora");
171
172 let result = run_subcmd_inspect(&m).await;
173 assert!(result.is_ok());
174 }
175}