seaplane_cli/cli/cmds/flight/
common.rs

1use clap::{value_parser, Arg, ArgMatches};
2use seaplane::api::compute::v1::Architecture as ArchitectureModel;
3
4use crate::cli::validator::{validate_flight_name, validate_u64};
5
6static LONG_IMAGE: &str =
7    "The container image registry reference that this Flight will use (See IMAGE SPEC below)
8
9NOTE at this time the if the registry is omitted, such as `nginxdemos/hello:latest` a default
10registry of `registry.cplane.cloud` will be used. This may change in the future, so it is
11recommended to always specify a full image reference path.";
12
13static LONG_NAME: &str =
14    "A human readable name for the Flight (must be unique within any Formation it
15
16Rules for a valid name are as follows:
17
18  - may only include 0-9, a-z, A-Z, and '-' (hyphen)
19  - hyphens ('-') may not be repeated (i.e. '--')
20  - no more than three (3) total hyphens
21  - the total length must be <= 27
22
23Some of these restrictions may be lifted in the future.";
24
25static LONG_ARCHITECTURE: &str = "The architectures this flight is capable of running on. No value means it will be auto detected from the image definition
26
27Multiple items can be passed as a comma separated list, or by using the argument
28multiple times.";
29
30// We have to go through this routine of re-implementing to get around Rust's rule about not being
31// allowed to implement traits on types not defined in the local crate.
32/// Supported Architectures
33#[derive(Debug, Copy, Clone, PartialEq, Eq, strum::EnumString, clap::ValueEnum)]
34#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
35pub enum Architecture {
36    Amd64,
37    Arm64,
38}
39
40impl Architecture {
41    pub fn into_model(&self) -> ArchitectureModel { self.into() }
42}
43
44#[allow(clippy::from_over_into)]
45impl<'a> Into<ArchitectureModel> for &'a Architecture {
46    fn into(self) -> ArchitectureModel {
47        use Architecture::*;
48        match self {
49            Arm64 => ArchitectureModel::ARM64,
50            Amd64 => ArchitectureModel::AMD64,
51        }
52    }
53}
54
55/// A newtype wrapper to enforce where the ArgMatches came from which reduces errors in checking if
56/// values of arguments were used or not. i.e. `seaplane formation plan` may not have the same
57/// arguments as `seaplane account token` even though both produce an `ArgMatches`.
58#[allow(missing_debug_implementations)]
59pub struct SeaplaneFlightCommonArgMatches<'a>(pub &'a ArgMatches);
60
61pub fn args(image_required: bool) -> Vec<Arg> {
62    #[cfg_attr(not(feature = "unstable"), allow(unused_mut))]
63    let mut hide = true;
64    let _ = hide;
65    #[cfg(feature = "unstable")]
66    {
67        hide = false;
68    }
69    vec![
70        // TODO: allow omitting of USER (TENANT) portion of image spec too...but this requires an API
71        // call to determine the TENANT id (at least until the `seaplane account login` command is done)
72        arg!(--image|img =["SPEC"])
73            .required(image_required)
74            .help("The container image registry reference that this Flight will use (See IMAGE SPEC below)")
75            .long_help(LONG_IMAGE),
76        arg!(--name -('n') =["STRING"])
77            .value_parser(validate_flight_name)
78            .help("A human readable name for the Flight (must be unique within any Formation it is a part of) if omitted a pseudo random name will be assigned")
79            .long_help(LONG_NAME),
80        arg!(--minimum|min =["NUM"=>"1"])
81            .value_parser(validate_u64)
82            .help("The minimum number of container instances that should ever be running"),
83        arg!(--maximum|max =["NUM"])
84            .overrides_with("no-maximum")
85            .value_parser(validate_u64)
86            .help("The maximum number of container instances that should ever be running (default: autoscale as needed)"),
87        arg!(--architecture|arch|arches|architectures ignore_case =["ARCH"]...)
88            .value_parser(value_parser!(Architecture))
89            .help("The architectures this flight is capable of running on. No value means it will be auto detected from the image definition (supports comma separated list, or multiple uses)")
90            .long_help(LONG_ARCHITECTURE),
91        arg!(--("no-maximum")|("no-max"))
92            .overrides_with("maximum")
93            .help("There is no maximum number of instances"),
94        arg!(--("api-permission")|("api-permissions"))
95            .overrides_with("no-api-permission")
96            .help("This Flight should be allowed to hit Seaplane API endpoints and will be provided a 'SEAPLANE_API_TOKEN' environment variable at runtime")
97            .hide(hide), // hidden on feature = unstable
98        arg!(--("no-api-permission")|("no-api-permissions"))
99            .overrides_with("api-permission")
100            .help("This Flight should NOT be allowed to hit Seaplane API endpoints and will NOT be provided a 'SEAPLANE_API_TOKEN' environment variable at runtime")
101            .hide(hide), // hidden on feature = unstable
102    ]
103}