Skip to main content

moon_pdk_api/
host.rs

1use crate::{is_false, is_zero};
2use derive_setters::*;
3use warpgate_api::{ExecCommandInput, VirtualPath, api_enum, api_struct};
4
5api_struct!(
6    #[derive(Setters)]
7    #[serde(default)]
8    pub struct ExecCommand {
9        /// When enabled, failed command executions will
10        /// not abort the moon process, and allow it to
11        /// continue running.
12        #[serde(skip_serializing_if = "is_false")]
13        #[setters(bool)]
14        pub allow_failure: bool,
15
16        /// Cache the command based on its inputs/params and
17        /// avoid re-executing until they change. Enabling
18        /// this cache requires a label for debug purposes.
19        #[serde(skip_serializing_if = "Option::is_none")]
20        #[setters(into, strip_option)]
21        pub cache: Option<String>,
22
23        /// The command parameters.
24        #[setters(skip)]
25        pub command: ExecCommandInput,
26
27        /// List of additional inputs to gather when generating
28        /// the cache key/hash.
29        #[serde(skip_serializing_if = "Vec::is_empty")]
30        pub inputs: Vec<CacheInput>,
31
32        /// Checkpoint label to print to the console. If not
33        /// provided, will default to the command + arguments.
34        #[serde(skip_serializing_if = "Option::is_none")]
35        #[setters(into, strip_option)]
36        pub label: Option<String>,
37
38        /// Execute the command in parallel.
39        #[serde(skip_serializing_if = "is_false")]
40        #[setters(bool)]
41        pub parallel: bool,
42
43        /// A count of how many times to retry the command
44        /// if it fails to execute.
45        #[serde(skip_serializing_if = "is_zero")]
46        pub retry_count: u8,
47    }
48);
49
50impl ExecCommand {
51    /// Create a new command with the provided input.
52    pub fn new(command: ExecCommandInput) -> Self {
53        Self {
54            allow_failure: false,
55            cache: None,
56            command,
57            inputs: vec![],
58            label: None,
59            parallel: false,
60            retry_count: 0,
61        }
62    }
63
64    /// Return the label, or the command + arguments.
65    pub fn get_label(&self) -> String {
66        self.label.clone().unwrap_or_else(|| {
67            format!("{} {}", self.command.command, self.command.args.join(" "))
68                .trim()
69                .into()
70        })
71    }
72}
73
74impl From<ExecCommandInput> for ExecCommand {
75    fn from(input: ExecCommandInput) -> Self {
76        Self::new(input)
77    }
78}
79
80api_enum!(
81    /// Types of inputs that can be cached.
82    #[serde(tag = "type", content = "value", rename_all = "kebab-case")]
83    pub enum CacheInput {
84        /// Environment variable.
85        EnvVar(String),
86
87        /// SHA256 file hash.
88        FileHash(VirtualPath),
89
90        /// File size in bytes.
91        FileSize(VirtualPath),
92
93        /// File modified or created at timestamp.
94        FileTimestamp(VirtualPath),
95    }
96);