isoloom_spec/syntax/
step.rs1macro_rules! schema_as {
14 ($ty:ident, $written:ident) => {
15 impl schemars::JsonSchema for $ty {
16 fn schema_name() -> std::borrow::Cow<'static, str> {
17 stringify!($ty).into()
18 }
19
20 fn json_schema(g: &mut schemars::SchemaGenerator) -> schemars::Schema {
21 <$written as schemars::JsonSchema>::json_schema(g)
22 }
23 }
24 };
25}
26
27mod accounts;
28mod files;
29mod input;
30mod services;
31mod software;
32mod words;
33
34pub use accounts::{GroupStep, Password, UserStep};
35pub use files::{Copy, FileState, FileStep, Template};
36pub use services::{Argv, CommandStep, Firewall, FirewallPort, Guard, Invocation, Service};
37pub use software::{Package, Repository, RepositoryKey};
38pub use words::{AbsPath, AptWord, GroupName, HttpsUrl, PackageName, PackageVersion, ProjectPath, RepositoryName, Sha256, UnitName, UserName};
39
40use serde::Deserialize;
41
42#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize)]
46#[serde(try_from = "input::StepSchema")]
47#[non_exhaustive]
48pub enum Step {
49 Run {
51 script: ProjectPath,
53 creates: Option<AbsPath>,
55 },
56 Copy(Copy),
58 Packages(Vec<Package>),
61 Reboot,
63 Playbook(ProjectPath),
65 Repository(Repository),
67 File(FileStep),
69 Template(Template),
71 User(UserStep),
73 Group(GroupStep),
75 Service(Service),
77 Command(CommandStep),
79 Firewall(Firewall),
81}
82
83impl Step {
84 #[must_use]
86 pub fn kind(&self) -> &'static str {
87 match self {
88 Step::Run { .. } => "run",
89 Step::Copy(_) => "copy",
90 Step::Packages(_) => "packages",
91 Step::Reboot => "reboot",
92 Step::Playbook(_) => "playbook",
93 Step::Repository(_) => "repository",
94 Step::File(_) => "file",
95 Step::Template(_) => "template",
96 Step::User(_) => "user",
97 Step::Group(_) => "group",
98 Step::Service(_) => "service",
99 Step::Command(_) => "command",
100 Step::Firewall(_) => "firewall",
101 }
102 }
103
104 #[must_use]
106 pub fn container_refusal(&self) -> Option<&'static str> {
107 match self {
108 Step::Reboot => Some("a reboot needs a machine with its own kernel and boot: a container has neither"),
109 Step::Playbook(_) => Some("a playbook step runs in a VM only in 1.0"),
110 Step::Run { script, .. } if has_extension(script.as_str(), "ps1") => Some("a PowerShell script means Windows, which has no container form in 1.0"),
111 _ => None,
112 }
113 }
114}
115
116pub(crate) fn has_extension(path: &str, extension: &str) -> bool {
118 std::path::Path::new(path).extension().is_some_and(|e| e.eq_ignore_ascii_case(extension))
119}
120
121impl schemars::JsonSchema for Step {
122 fn schema_name() -> std::borrow::Cow<'static, str> {
123 "Step".into()
124 }
125
126 fn json_schema(g: &mut schemars::SchemaGenerator) -> schemars::Schema {
127 <input::StepSchema as schemars::JsonSchema>::json_schema(g)
128 }
129}
130
131#[cfg(test)]
132mod tests;