gr/cli/
docker.rs

1use clap::Parser;
2
3use crate::cmds::docker::{DockerImageCliArgs, DockerListCliArgs};
4
5use super::common::{GetArgs, ListArgs};
6
7#[derive(Parser)]
8pub struct DockerCommand {
9    #[clap(subcommand)]
10    subcommand: DockerSubCommand,
11}
12
13#[derive(Parser)]
14enum DockerSubCommand {
15    #[clap(about = "List Docker images")]
16    List(ListDockerImages),
17    #[clap(about = "Get docker image metadata")]
18    Image(DockerImageMetadata),
19}
20
21#[derive(Parser)]
22struct DockerImageMetadata {
23    /// Tag name
24    #[clap()]
25    tag: String,
26    /// Repository ID the image belongs to
27    #[clap(long, help_heading = "Docker options")]
28    repo_id: i64,
29    #[clap(flatten)]
30    get_args: GetArgs,
31}
32
33#[derive(Parser)]
34#[clap(next_help_heading = "Docker options")]
35struct ListDockerImages {
36    /// List image repositories in this projects' registry
37    #[clap(long, default_value = "false", group = "list")]
38    repos: bool,
39    /// List all image tags for a given repository id
40    #[clap(long, default_value = "false", group = "list", requires = "repo_id")]
41    tags: bool,
42    /// Repository ID to pull image tags from
43    #[clap(long)]
44    repo_id: Option<i64>,
45    #[command(flatten)]
46    list_args: ListArgs,
47}
48
49impl From<DockerCommand> for DockerOptions {
50    fn from(options: DockerCommand) -> Self {
51        match options.subcommand {
52            DockerSubCommand::List(options) => options.into(),
53            DockerSubCommand::Image(options) => options.into(),
54        }
55    }
56}
57
58impl From<DockerImageMetadata> for DockerOptions {
59    fn from(options: DockerImageMetadata) -> Self {
60        DockerOptions::Get(
61            DockerImageCliArgs::builder()
62                .repo_id(options.repo_id)
63                .tag(options.tag)
64                .get_args(options.get_args.into())
65                .build()
66                .unwrap(),
67        )
68    }
69}
70
71impl From<ListDockerImages> for DockerOptions {
72    fn from(options: ListDockerImages) -> Self {
73        DockerOptions::List(
74            DockerListCliArgs::builder()
75                .repos(options.repos)
76                .tags(options.tags)
77                .repo_id(options.repo_id)
78                .list_args(options.list_args.into())
79                .build()
80                .unwrap(),
81        )
82    }
83}
84
85pub enum DockerOptions {
86    List(DockerListCliArgs),
87    Get(DockerImageCliArgs),
88}
89
90#[cfg(test)]
91mod test {
92    use crate::cli::{Args, Command};
93
94    use super::*;
95
96    #[test]
97    fn test_docker_cli_repos() {
98        let args = Args::parse_from(vec!["gr", "dk", "list", "--repos"]);
99        let list_images = match args.command {
100            Command::Docker(DockerCommand {
101                subcommand: DockerSubCommand::List(options),
102            }) => {
103                assert!(options.repos);
104                assert!(!options.tags);
105                options
106            }
107            _ => panic!("Expected DockerCommand"),
108        };
109        let options: DockerOptions = list_images.into();
110        match options {
111            DockerOptions::List(args) => {
112                assert!(args.repos);
113                assert!(!args.tags);
114            }
115            _ => panic!("Expected DockerOptions::List"),
116        }
117    }
118
119    #[test]
120    fn test_docker_cli_tags() {
121        let args = Args::parse_from(vec!["gr", "dk", "list", "--tags", "--repo-id", "12"]);
122        match args.command {
123            Command::Docker(DockerCommand {
124                subcommand: DockerSubCommand::List(options),
125            }) => {
126                assert!(!options.repos);
127                assert!(options.tags);
128                assert_eq!(options.repo_id, Some(12));
129            }
130            _ => panic!("Expected DockerCommand"),
131        }
132    }
133
134    #[test]
135    fn test_docker_get_image_metadata_cli_args() {
136        let args = Args::parse_from(vec![
137            "gr",
138            "dk",
139            "image",
140            "--refresh",
141            "--no-headers",
142            "--repo-id",
143            "123",
144            "v0.0.1",
145        ]);
146        let image_metadata = match args.command {
147            Command::Docker(DockerCommand {
148                subcommand: DockerSubCommand::Image(options),
149            }) => {
150                assert_eq!(options.repo_id, 123);
151                assert_eq!(options.tag, "v0.0.1");
152                assert!(options.get_args.cache_args.refresh);
153                assert!(options.get_args.format_args.no_headers);
154                options
155            }
156            _ => panic!("Expected DockerCommand"),
157        };
158        // check all options are set
159        let options: DockerOptions = image_metadata.into();
160        match options {
161            DockerOptions::Get(args) => {
162                assert_eq!(args.repo_id, 123);
163                assert_eq!(args.tag, "v0.0.1");
164                assert!(args.get_args.cache_args.refresh);
165                assert!(args.get_args.no_headers);
166            }
167            _ => panic!("Expected DockerOptions::Get"),
168        }
169    }
170}