Skip to main content

isoloom_spec/model/
target.rs

1//! The targets an environment can be rendered for, and the shapes of machine they accept.
2
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6/// Where an environment can run.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, JsonSchema)]
8#[serde(rename_all = "kebab-case")]
9pub enum Target {
10    /// Containers on the user's Docker.
11    Docker,
12    /// A hosting service runs the Docker shape for the user.
13    Hosted,
14    /// Docker on one VM: on this machine, an ESXi host or a Proxmox server.
15    DockerVm,
16    /// Docker on one cloud VM.
17    CloudDocker,
18    /// The containers on a Kubernetes cluster.
19    Kubernetes,
20    /// Containers and VMs together on the same networks (local VMs): each machine as a
21    /// container when it can be one, else as a VM.
22    Hybrid,
23    /// One local VM per machine (Vagrant).
24    Vagrant,
25    /// One VM per machine on the user's Proxmox.
26    Proxmox,
27    /// One VM per machine on the user's standalone ESXi host (Terraform, no vCenter).
28    Esxi,
29    /// One cloud VM per machine.
30    CloudVm,
31    /// Machines that already exist, reached over SSH at the addresses the spec gives
32    /// (`machines.*.external`): nothing is created, everything else applies.
33    External,
34    /// The spec's cloud services (`cloud:`): its Terraform module applied into the user's own
35    /// cloud account.
36    CloudServices,
37}
38
39impl Target {
40    /// Every target, in the order they are listed (`isoloom targets`, the snapshot).
41    pub const ALL: [Target; 12] = [
42        Target::Docker,
43        Target::Hosted,
44        Target::DockerVm,
45        Target::CloudDocker,
46        Target::Kubernetes,
47        Target::Hybrid,
48        Target::Vagrant,
49        Target::Proxmox,
50        Target::Esxi,
51        Target::CloudVm,
52        Target::External,
53        Target::CloudServices,
54    ];
55
56    /// The implementation every machine needs for this target.
57    #[must_use]
58    pub fn needs(self) -> Shape {
59        match self {
60            Target::Docker | Target::Hosted | Target::DockerVm | Target::CloudDocker | Target::Kubernetes => Shape::Docker,
61            Target::Vagrant | Target::Esxi | Target::CloudVm => Shape::Vm,
62            Target::Proxmox => Shape::VmOrLxc,
63            Target::Hybrid => Shape::Either,
64            Target::External => Shape::External,
65            Target::CloudServices => Shape::Cloud,
66        }
67    }
68
69    /// The target's name on the command line and in its folder under `.isoloom/`.
70    #[must_use]
71    pub fn id(self) -> &'static str {
72        match self {
73            Target::Docker => "docker",
74            Target::Hosted => "hosted",
75            Target::DockerVm => "docker-vm",
76            Target::CloudDocker => "cloud-docker",
77            Target::Kubernetes => "kubernetes",
78            Target::Hybrid => "hybrid",
79            Target::Vagrant => "vagrant",
80            Target::Proxmox => "proxmox",
81            Target::Esxi => "esxi",
82            Target::CloudVm => "cloud-vm",
83            Target::External => "external",
84            Target::CloudServices => "cloud-services",
85        }
86    }
87}
88
89/// The two ways a machine can be produced.
90#[derive(Debug, Clone, Copy, PartialEq, Eq)]
91pub enum Shape {
92    /// A `docker:` block: a container.
93    Docker,
94    /// A `vm:` block: a virtual machine.
95    Vm,
96    /// Either implementation, machine by machine.
97    Either,
98    /// A `vm:` block, or a `docker:` one that may run as an LXC container (`docker.lxc`).
99    VmOrLxc,
100    /// An `external` block: the machine exists already.
101    External,
102    /// No machines: the spec's `cloud:` services.
103    Cloud,
104}
105
106impl Shape {
107    /// The spec key that gives a machine this shape, as a refusal names it (`docker`, `vm`).
108    #[must_use]
109    pub fn key(self) -> &'static str {
110        match self {
111            Shape::Docker => "docker",
112            Shape::Vm => "vm",
113            Shape::Either => "docker` or `vm",
114            Shape::VmOrLxc => "docker.lxc` or `vm",
115            Shape::External => "external",
116            Shape::Cloud => "cloud",
117        }
118    }
119}
120
121#[cfg(test)]
122mod tests {
123    use super::*;
124
125    #[test]
126    fn a_shape_names_the_keys_a_refusal_quotes() {
127        let quoted = [Shape::Docker, Shape::Vm, Shape::Either, Shape::VmOrLxc, Shape::External, Shape::Cloud].map(|s| format!("`{}`", s.key()));
128        assert_eq!(
129            quoted,
130            ["`docker`", "`vm`", "`docker` or `vm`", "`docker.lxc` or `vm`", "`external`", "`cloud`"]
131        );
132    }
133}