use crate::command::{CommandExecutor, CommandOutput, DockerCommand};
use crate::error::Result;
use async_trait::async_trait;
#[derive(Debug, Clone)]
pub struct ManifestAnnotateResult {
pub manifest_list: String,
pub manifest: String,
pub output: String,
pub success: bool,
}
impl ManifestAnnotateResult {
fn parse(manifest_list: &str, manifest: &str, output: &CommandOutput) -> Self {
Self {
manifest_list: manifest_list.to_string(),
manifest: manifest.to_string(),
output: output.stdout.clone(),
success: output.success,
}
}
}
#[derive(Debug, Clone)]
pub struct ManifestAnnotateCommand {
manifest_list: String,
manifest: String,
arch: Option<String>,
os: Option<String>,
os_features: Vec<String>,
os_version: Option<String>,
variant: Option<String>,
pub executor: CommandExecutor,
}
impl ManifestAnnotateCommand {
#[must_use]
pub fn new(manifest_list: impl Into<String>, manifest: impl Into<String>) -> Self {
Self {
manifest_list: manifest_list.into(),
manifest: manifest.into(),
arch: None,
os: None,
os_features: Vec::new(),
os_version: None,
variant: None,
executor: CommandExecutor::new(),
}
}
#[must_use]
pub fn arch(mut self, arch: impl Into<String>) -> Self {
self.arch = Some(arch.into());
self
}
#[must_use]
pub fn os(mut self, os: impl Into<String>) -> Self {
self.os = Some(os.into());
self
}
#[must_use]
pub fn os_feature(mut self, feature: impl Into<String>) -> Self {
self.os_features.push(feature.into());
self
}
#[must_use]
pub fn os_version(mut self, version: impl Into<String>) -> Self {
self.os_version = Some(version.into());
self
}
#[must_use]
pub fn variant(mut self, variant: impl Into<String>) -> Self {
self.variant = Some(variant.into());
self
}
fn build_args(&self) -> Vec<String> {
let mut args = vec!["manifest".to_string(), "annotate".to_string()];
if let Some(ref arch) = self.arch {
args.push("--arch".to_string());
args.push(arch.clone());
}
if let Some(ref os) = self.os {
args.push("--os".to_string());
args.push(os.clone());
}
for feature in &self.os_features {
args.push("--os-features".to_string());
args.push(feature.clone());
}
if let Some(ref version) = self.os_version {
args.push("--os-version".to_string());
args.push(version.clone());
}
if let Some(ref variant) = self.variant {
args.push("--variant".to_string());
args.push(variant.clone());
}
args.push(self.manifest_list.clone());
args.push(self.manifest.clone());
args.extend(self.executor.raw_args.clone());
args
}
}
#[async_trait]
impl DockerCommand for ManifestAnnotateCommand {
type Output = ManifestAnnotateResult;
fn get_executor(&self) -> &CommandExecutor {
&self.executor
}
fn get_executor_mut(&mut self) -> &mut CommandExecutor {
&mut self.executor
}
fn build_command_args(&self) -> Vec<String> {
self.build_args()
}
async fn execute(&self) -> Result<Self::Output> {
let args = self.build_args();
let output = self.execute_command(args).await?;
Ok(ManifestAnnotateResult::parse(
&self.manifest_list,
&self.manifest,
&output,
))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_manifest_annotate_basic() {
let cmd = ManifestAnnotateCommand::new("myapp:latest", "myapp:latest-amd64");
let args = cmd.build_args();
assert_eq!(
args,
vec!["manifest", "annotate", "myapp:latest", "myapp:latest-amd64"]
);
}
#[test]
fn test_manifest_annotate_with_arch() {
let cmd = ManifestAnnotateCommand::new("myapp:latest", "myapp:latest-arm64").arch("arm64");
let args = cmd.build_args();
assert!(args.contains(&"--arch".to_string()));
assert!(args.contains(&"arm64".to_string()));
}
#[test]
fn test_manifest_annotate_with_os() {
let cmd = ManifestAnnotateCommand::new("myapp:latest", "myapp:latest-amd64").os("linux");
let args = cmd.build_args();
assert!(args.contains(&"--os".to_string()));
assert!(args.contains(&"linux".to_string()));
}
#[test]
fn test_manifest_annotate_with_variant() {
let cmd = ManifestAnnotateCommand::new("myapp:latest", "myapp:latest-arm64").variant("v8");
let args = cmd.build_args();
assert!(args.contains(&"--variant".to_string()));
assert!(args.contains(&"v8".to_string()));
}
#[test]
fn test_manifest_annotate_all_options() {
let cmd = ManifestAnnotateCommand::new("myapp:latest", "myapp:latest-arm64")
.arch("arm64")
.os("linux")
.os_feature("sse4")
.os_version("1.0")
.variant("v8");
let args = cmd.build_args();
assert!(args.contains(&"--arch".to_string()));
assert!(args.contains(&"--os".to_string()));
assert!(args.contains(&"--os-features".to_string()));
assert!(args.contains(&"--os-version".to_string()));
assert!(args.contains(&"--variant".to_string()));
}
}