support_kit/deployments/
image_deployment_context.rs1use 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}