use crate::command::{CommandExecutor, CommandOutput, DockerCommand};
use crate::error::Result;
use async_trait::async_trait;
use serde_json::Value;
#[derive(Debug, Clone)]
pub struct NetworkInspectCommand {
networks: Vec<String>,
format: Option<String>,
verbose: bool,
pub executor: CommandExecutor,
}
impl NetworkInspectCommand {
#[must_use]
pub fn new(network: impl Into<String>) -> Self {
Self {
networks: vec![network.into()],
format: None,
verbose: false,
executor: CommandExecutor::new(),
}
}
#[must_use]
pub fn new_multiple(networks: Vec<String>) -> Self {
Self {
networks,
format: None,
verbose: false,
executor: CommandExecutor::new(),
}
}
#[must_use]
pub fn add_network(mut self, network: impl Into<String>) -> Self {
self.networks.push(network.into());
self
}
#[must_use]
pub fn format(mut self, format: impl Into<String>) -> Self {
self.format = Some(format.into());
self
}
#[must_use]
pub fn verbose(mut self) -> Self {
self.verbose = true;
self
}
pub async fn run(&self) -> Result<NetworkInspectOutput> {
self.execute().await.map(NetworkInspectOutput::from)
}
}
#[async_trait]
impl DockerCommand for NetworkInspectCommand {
type Output = CommandOutput;
fn build_command_args(&self) -> Vec<String> {
let mut args = vec!["network".to_string(), "inspect".to_string()];
if let Some(ref format) = self.format {
args.push("--format".to_string());
args.push(format.clone());
}
if self.verbose {
args.push("--verbose".to_string());
}
for network in &self.networks {
args.push(network.clone());
}
args.extend(self.executor.raw_args.clone());
args
}
fn get_executor(&self) -> &CommandExecutor {
&self.executor
}
fn get_executor_mut(&mut self) -> &mut CommandExecutor {
&mut self.executor
}
async fn execute(&self) -> Result<Self::Output> {
let args = self.build_command_args();
let command_name = args[0].clone();
let command_args = args[1..].to_vec();
self.executor
.execute_command(&command_name, command_args)
.await
}
}
#[derive(Debug, Clone)]
pub struct NetworkInspectOutput {
pub json: Option<Value>,
pub raw_output: CommandOutput,
}
impl From<CommandOutput> for NetworkInspectOutput {
fn from(output: CommandOutput) -> Self {
let json = if output.stdout.starts_with('[') || output.stdout.starts_with('{') {
serde_json::from_str(&output.stdout).ok()
} else {
None
};
Self {
json,
raw_output: output,
}
}
}
impl NetworkInspectOutput {
#[must_use]
pub fn is_success(&self) -> bool {
self.raw_output.success
}
#[must_use]
pub fn json(&self) -> Option<&Value> {
self.json.as_ref()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_network_inspect_single() {
let cmd = NetworkInspectCommand::new("my-network");
let args = cmd.build_command_args();
assert_eq!(args, vec!["network", "inspect", "my-network"]);
}
#[test]
fn test_network_inspect_multiple() {
let cmd = NetworkInspectCommand::new_multiple(vec![
"network1".to_string(),
"network2".to_string(),
]);
let args = cmd.build_command_args();
assert_eq!(args, vec!["network", "inspect", "network1", "network2"]);
}
#[test]
fn test_network_inspect_with_format() {
let cmd = NetworkInspectCommand::new("my-network").format("{{.Driver}}");
let args = cmd.build_command_args();
assert_eq!(
args,
vec![
"network",
"inspect",
"--format",
"{{.Driver}}",
"my-network"
]
);
}
#[test]
fn test_network_inspect_verbose() {
let cmd = NetworkInspectCommand::new("my-network").verbose();
let args = cmd.build_command_args();
assert_eq!(args, vec!["network", "inspect", "--verbose", "my-network"]);
}
}