support_kit/deployments/
image_deployment_context.rs

1use std::path::PathBuf;
2
3use crate::{shell, Configuration, ImageDefinition, Registry, ShellCommand};
4
5#[derive(Debug, Clone, bon::Builder)]
6pub struct ImageDeploymentContext {
7    pub config: Configuration,
8    pub image: ImageDefinition,
9    pub registry: Registry,
10}
11
12impl ImageDeploymentContext {
13    #[tracing::instrument(skip(self), level = "trace")]
14    fn volume_name(&self, volume: &str) -> String {
15        format!(
16            "{namespace}-{name}-{volume}",
17            name = self.image.name,
18            namespace = self.image.namespace,
19            volume = volume
20        )
21    }
22
23    #[tracing::instrument(skip(self), level = "trace")]
24    fn descriptor(&self) -> String {
25        format!(
26            "{repo}/{namespace}/{name}:{label}",
27            name = self.image.name,
28            namespace = self.image.namespace,
29            repo = self.registry.host,
30            label = self.image.label
31        )
32    }
33
34    #[tracing::instrument(skip(self), level = "trace")]
35    fn name(&self) -> String {
36        format!(
37            "{namespace}-{name}-deployment",
38            name = self.image.name,
39            namespace = self.image.namespace,
40        )
41    }
42
43    #[tracing::instrument(skip(self), level = "trace")]
44    pub fn setup_volume(&self, volume: &str) -> crate::Result<ShellCommand> {
45        shell(format!(
46            "docker volume create {volume_name}",
47            volume_name = self.volume_name(volume)
48        ))
49    }
50
51    #[tracing::instrument(skip(self), level = "trace")]
52    pub fn setup_data_volume(&self) -> crate::Result<ShellCommand> {
53        self.setup_volume("data")
54    }
55
56    #[tracing::instrument(skip(self), level = "trace")]
57    pub fn setup_log_volume(&self) -> crate::Result<ShellCommand> {
58        self.setup_volume("logs")
59    }
60
61    #[tracing::instrument(skip(self), level = "trace")]
62    pub fn setup_config_volume(&self) -> crate::Result<ShellCommand> {
63        self.setup_volume("config")
64    }
65
66    #[tracing::instrument(skip(self), level = "trace")]
67    pub fn kill_all(&self) -> crate::Result<ShellCommand> {
68        shell(format!("docker kill {name}", name = self.name()))
69    }
70
71    #[tracing::instrument(skip(self), level = "trace")]
72    pub fn push(&self) -> crate::Result<ShellCommand> {
73        shell(format!(
74            "docker push {descriptor}",
75            descriptor = self.descriptor()
76        ))
77    }
78
79    #[tracing::instrument(skip(self), level = "trace")]
80    pub fn build(&self) -> crate::Result<ShellCommand> {
81        let label = format!(
82            "org.opencontainers.image.source={repo}",
83            repo = self.image.repo
84        );
85
86        shell(format!(
87            "docker build -f {definition} --label {label} -t {descriptor} .",
88            definition = self.image.definition,
89            descriptor = self.descriptor(),
90        ))
91    }
92
93    #[tracing::instrument(skip(self), level = "trace")]
94    pub fn pull(&self) -> crate::Result<ShellCommand> {
95        shell(format!(
96            "docker pull {descriptor}",
97            descriptor = self.descriptor()
98        ))
99    }
100
101    #[tracing::instrument(skip(self, config_path), level = "trace")]
102    pub fn start(&self, config_path: impl Into<PathBuf>) -> crate::Result<ShellCommand> {
103        let config_path = config_path.into();
104
105        let operation = shell(format!(
106            r#"
107            docker run
108              --rm
109              -d 
110              -p 443:{port}
111              -e RUST_LOG=debug,support_kit=debug
112              -v {config_path}:/{app_name}.json
113              --mount source={certs},target=/certs
114              --mount source={logs},target=/logs
115              --mount source={data},target=/data
116              --name {name}
117              {descriptor}
118              -vvvv
119              --config-file {app_name}
120              --port {port}
121            "#,
122            descriptor = self.descriptor(),
123            app_name = self.config.name(),
124            name = self.name(),
125            port = self.config.server.port,
126            config_path = config_path.display(),
127            certs = self.volume_name("certs"),
128            logs = self.volume_name("logs"),
129            data = self.volume_name("data"),
130        ));
131
132        println!("{:?}", operation);
133
134        operation
135    }
136}