docker_pose/
args.rs

1/// Types to parse the command line arguments with the clap crate.
2use crate::{Verbosity, header, positive_less_than_32, string_no_empty, string_script};
3use clap::{Parser, Subcommand, ValueEnum};
4use std::cmp::Ord;
5
6#[derive(Parser)]
7#[command(author, version, about, long_about = None)]
8pub struct Args {
9    #[command(subcommand)]
10    pub command: Commands,
11
12    #[arg(short, long = "file", value_name = "FILENAME")]
13    pub filenames: Vec<String>,
14
15    /// Increase verbosity
16    #[arg(long, conflicts_with = "quiet")]
17    pub verbose: bool,
18
19    /// Only display relevant information or errors
20    #[arg(long, short, conflicts_with = "verbose")]
21    pub quiet: bool,
22
23    /// Don't call docker compose to parse compose model
24    #[arg(long)]
25    pub no_docker: bool,
26
27    /// Don't check model consistency - warning: may produce invalid Compose output
28    #[arg(long, conflicts_with = "no_docker")]
29    pub no_consistency: bool,
30
31    /// Don't interpolate environment variables
32    #[arg(long, conflicts_with = "no_docker")]
33    pub no_interpolate: bool,
34}
35
36impl Args {
37    pub fn get_verbosity(&self) -> Verbosity {
38        match self.verbose {
39            true => Verbosity::Verbose,
40            false => match self.quiet {
41                true => Verbosity::Quiet,
42                false => Verbosity::Info,
43            },
44        }
45    }
46}
47
48#[derive(Subcommand)]
49pub enum Commands {
50    /// List objects found in the compose file: services, volumes, ...
51    List {
52        #[command(subcommand)]
53        object: Objects,
54
55        #[arg(short, long, value_enum, default_value_t = Formats::Full, value_name = "FORMAT")]
56        pretty: Formats,
57    },
58    /// Parse, resolve and render compose file in canonical format
59    Config {
60        /// Save to file (default to stdout)
61        #[arg(short, long, value_name = "FILE")]
62        output: Option<String>,
63        /// output image attributes in services with a tag passed instead of the one set in the file
64        /// if they exist locally or in the remote docker registry
65        #[arg(short, long, value_name = "TAG", value_parser = string_no_empty)]
66        tag: Option<String>,
67        /// use with --tag to filter which images should be checked whether the
68        /// tag exists or not locally or remotely.
69        /// Currently only regex=EXPR or regex!=EXPR (invert match) are supported
70        #[arg(long, value_name = "FILTER", requires("tag"), value_parser = string_no_empty)]
71        tag_filter: Option<String>,
72        /// ignore unauthorized errors from docker when fetching remote tags info
73        #[arg(long, requires("tag"))]
74        ignore_unauthorized: bool,
75        /// Don't slugify the value from --tag
76        #[arg(long, requires("tag"))]
77        no_slug: bool,
78        /// only check --tag TAG with the local docker registry
79        #[arg(long, requires("tag"))]
80        offline: bool,
81        /// outputs in stderr the progress of fetching the tags info, similar to --verbose,
82        /// but without all the other details --verbose adds
83        #[arg(long, requires("tag"))]
84        progress: bool,
85        /// max number of threads used to fetch remote images info
86        #[arg(long, value_name = "NUM", default_value_t = 8, value_parser = positive_less_than_32, requires("tag"))]
87        threads: u8,
88    },
89    /// Outputs a slug version of the text passed, or the slug version of the
90    /// current branch.
91    ///
92    /// It's the same slug used with the --tag value in other commands.
93    /// The output is a lowercase version with all no-alphanumeric
94    /// characters translated into the "-" symbol, except for the char ".", to make it
95    /// compatible with a valid docker tag name.
96    Slug {
97        /// text to slugify, if not provided the current branch name is used
98        #[arg(value_parser = string_no_empty)]
99        text: Option<String>,
100    },
101
102    /// Download a file from an HTTP URL. If the resource doesn't exist, fallback
103    /// to another URL generated editing the URL given with a script provided in the
104    /// form of "text-to-replace:replacer".
105    Get {
106        /// The URL where the file is located
107        #[arg(value_parser = string_no_empty)]
108        url: String,
109        /// if request to URL responds back with HTTP 404, create a second URL
110        /// replacing any occurrence of the left part of the script with the right
111        /// part. Each part of the script has to be separated with the symbol `:`.
112        /// E.g. `pose get https://server.com/repo/feature-a/compose.yml feature-a:master`
113        /// will try to first download the resource from https://server.com/repo/feature-a/compose.yml,
114        /// if not found, will try at https://server.com/repo/master/compose.yml
115        #[arg(value_parser = string_script)]
116        script: Option<(String, String)>,
117        /// Save to file (default use the same filename set in the url)
118        #[arg(short, long, value_name = "FILE")]
119        output: Option<String>,
120        /// Maximum time in seconds that you allow pose's connection to take.
121        /// This only limits the connection phase, so if pose connects within the
122        /// given period, it will continue, if not, it will exit with error.
123        #[arg(long, value_name = "SECONDS", default_value_t = 10)]
124        timeout_connect: u16,
125        /// Maximum time in seconds that you allow the whole operation to take.
126        #[arg(short, long, value_name = "SECONDS", default_value_t = 300)]
127        max_time: u16,
128        /// HTTP header to include in the request
129        #[arg(short = 'H', long = "header", value_name = "HEADER", value_parser = header)]
130        headers: Vec<(String, String)>,
131    },
132}
133
134#[derive(Subcommand, strum_macros::Display, PartialEq)]
135pub enum Objects {
136    /// List services
137    Services {
138        /// filter by a property, currently only tag=TAG is supported
139        #[arg(short, long)]
140        filter: Option<String>,
141    },
142    /// List images
143    Images {
144        /// filter by a property, if --tag is used as well,
145        /// this filter is applied first, filtering out images that
146        /// don't match the filter. Currently only tag=TAG is supported
147        #[arg(short, long)]
148        filter: Option<String>,
149        /// print images with the tag passed instead of the one set in the file if they exist
150        /// locally or in the remote docker registry
151        #[arg(short, long, value_name = "TAG", value_parser = string_no_empty)]
152        tag: Option<String>,
153        /// use with --tag to filter which images should be checked whether the tag exists
154        /// or not, but images that don't match the filter are not filtered out from the list
155        /// printed, only printed with the tag they have in the compose file.
156        /// Currently only regex=EXPR or regex!=EXPR are supported
157        #[arg(long, value_name = "FILTER", requires("tag"), value_parser = string_no_empty)]
158        tag_filter: Option<String>,
159        /// ignore unauthorized errors from docker when fetching remote tags info
160        #[arg(long, requires("tag"))]
161        ignore_unauthorized: bool,
162        /// Don't slugify the value from --tag
163        #[arg(long, requires("tag"))]
164        no_slug: bool,
165        /// only check --tag TAG with the local docker registry
166        #[arg(long, requires("tag"))]
167        offline: bool,
168        /// outputs in stderr the progress of fetching the tags info, similar to --verbose
169        /// but without all the other details --verbose adds
170        #[arg(long, requires("tag"))]
171        progress: bool,
172        /// max number of threads used to fetch images info
173        #[arg(long, value_name = "NUM", default_value_t = 8, value_parser = positive_less_than_32, requires("tag"))]
174        threads: u8,
175    },
176    /// List service's depends_on services
177    Depends {
178        #[arg(required = true)]
179        services: Vec<String>,
180    },
181    /// List services that are dependants of the given services
182    Dependents {
183        #[arg(required = true)]
184        services: Vec<String>,
185    },
186    /// List volumes
187    Volumes,
188    /// List networks
189    Networks,
190    /// List configs
191    Configs,
192    /// List secrets
193    Secrets,
194    /// List profiles
195    Profiles,
196    /// List service's environment variables
197    Envs {
198        #[arg(value_parser = string_no_empty)]
199        service: String,
200    },
201}
202
203#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, strum_macros::Display)]
204pub enum Formats {
205    Full,
206    Oneline,
207}