mirror of
https://github.com/moghtech/komodo.git
synced 2026-06-04 07:56:08 -05:00
183 lines
5.1 KiB
Rust
183 lines
5.1 KiB
Rust
use std::collections::{HashMap, HashSet};
|
|
|
|
use anyhow::Context;
|
|
use komodo_client::entities::{
|
|
EnvironmentVar, build::Build, deployment::Deployment, repo::Repo,
|
|
stack::Stack, update::Log,
|
|
};
|
|
|
|
pub struct Interpolator<'a> {
|
|
variables: Option<&'a HashMap<String, String>>,
|
|
secrets: &'a HashMap<String, String>,
|
|
variable_replacers: HashSet<(String, String)>,
|
|
pub secret_replacers: HashSet<(String, String)>,
|
|
}
|
|
|
|
impl<'a> Interpolator<'a> {
|
|
pub fn new(
|
|
variables: Option<&'a HashMap<String, String>>,
|
|
secrets: &'a HashMap<String, String>,
|
|
) -> Interpolator<'a> {
|
|
Interpolator {
|
|
variables,
|
|
secrets,
|
|
variable_replacers: Default::default(),
|
|
secret_replacers: Default::default(),
|
|
}
|
|
}
|
|
|
|
pub fn interpolate_stack(
|
|
&mut self,
|
|
stack: &mut Stack,
|
|
) -> anyhow::Result<&mut Self> {
|
|
if stack.config.skip_secret_interp {
|
|
return Ok(self);
|
|
}
|
|
self
|
|
.interpolate_string(&mut stack.config.file_contents)?
|
|
.interpolate_string(&mut stack.config.environment)?
|
|
.interpolate_string(&mut stack.config.pre_deploy.command)?
|
|
.interpolate_string(&mut stack.config.post_deploy.command)?
|
|
.interpolate_string(&mut stack.config.compose_cmd_wrapper)?
|
|
.interpolate_extra_args(&mut stack.config.extra_args)?
|
|
.interpolate_extra_args(&mut stack.config.build_extra_args)
|
|
}
|
|
|
|
pub fn interpolate_repo(
|
|
&mut self,
|
|
repo: &mut Repo,
|
|
) -> anyhow::Result<&mut Self> {
|
|
if repo.config.skip_secret_interp {
|
|
return Ok(self);
|
|
}
|
|
self
|
|
.interpolate_string(&mut repo.config.environment)?
|
|
.interpolate_string(&mut repo.config.on_clone.command)?
|
|
.interpolate_string(&mut repo.config.on_pull.command)
|
|
}
|
|
|
|
pub fn interpolate_build(
|
|
&mut self,
|
|
build: &mut Build,
|
|
) -> anyhow::Result<&mut Self> {
|
|
if build.config.skip_secret_interp {
|
|
return Ok(self);
|
|
}
|
|
self
|
|
.interpolate_string(&mut build.config.build_args)?
|
|
.interpolate_string(&mut build.config.secret_args)?
|
|
.interpolate_string(&mut build.config.labels)?
|
|
.interpolate_string(&mut build.config.pre_build.command)?
|
|
.interpolate_string(&mut build.config.dockerfile)?
|
|
.interpolate_extra_args(&mut build.config.extra_args)
|
|
}
|
|
|
|
pub fn interpolate_deployment(
|
|
&mut self,
|
|
deployment: &mut Deployment,
|
|
) -> anyhow::Result<&mut Self> {
|
|
if deployment.config.skip_secret_interp {
|
|
return Ok(self);
|
|
}
|
|
self
|
|
.interpolate_string(&mut deployment.config.environment)?
|
|
.interpolate_string(&mut deployment.config.ports)?
|
|
.interpolate_string(&mut deployment.config.volumes)?
|
|
.interpolate_string(&mut deployment.config.labels)?
|
|
.interpolate_string(&mut deployment.config.command)?
|
|
.interpolate_extra_args(&mut deployment.config.extra_args)
|
|
}
|
|
|
|
pub fn interpolate_string(
|
|
&mut self,
|
|
target: &mut String,
|
|
) -> anyhow::Result<&mut Self> {
|
|
if target.is_empty() {
|
|
return Ok(self);
|
|
}
|
|
|
|
// first pass - variables
|
|
let res = if let Some(variables) = self.variables {
|
|
let (res, more_replacers) = svi::interpolate_variables(
|
|
target,
|
|
variables,
|
|
svi::Interpolator::DoubleBrackets,
|
|
false,
|
|
)
|
|
.with_context(|| {
|
|
format!(
|
|
"failed to interpolate variables into target '{target}'",
|
|
)
|
|
})?;
|
|
self.variable_replacers.extend(more_replacers);
|
|
res
|
|
} else {
|
|
target.to_string()
|
|
};
|
|
|
|
// second pass - secrets
|
|
let (res, more_replacers) = svi::interpolate_variables(
|
|
&res,
|
|
self.secrets,
|
|
svi::Interpolator::DoubleBrackets,
|
|
false,
|
|
)
|
|
.with_context(|| {
|
|
format!("failed to interpolate secrets into target '{target}'",)
|
|
})?;
|
|
self.secret_replacers.extend(more_replacers);
|
|
|
|
// Set with result
|
|
*target = res;
|
|
|
|
Ok(self)
|
|
}
|
|
|
|
pub fn interpolate_extra_args(
|
|
&mut self,
|
|
extra_args: &mut Vec<String>,
|
|
) -> anyhow::Result<&mut Self> {
|
|
for arg in extra_args {
|
|
self
|
|
.interpolate_string(arg)
|
|
.context("failed interpolation into extra arg")?;
|
|
}
|
|
Ok(self)
|
|
}
|
|
|
|
pub fn interpolate_env_vars(
|
|
&mut self,
|
|
env_vars: &mut Vec<EnvironmentVar>,
|
|
) -> anyhow::Result<&mut Self> {
|
|
for var in env_vars {
|
|
self
|
|
.interpolate_string(&mut var.value)
|
|
.context("failed interpolation into variable value")?;
|
|
}
|
|
Ok(self)
|
|
}
|
|
|
|
pub fn push_logs(&self, logs: &mut Vec<Log>) {
|
|
// Show which variables / values were interpolated
|
|
if !self.variable_replacers.is_empty() {
|
|
logs.push(Log::simple("Interpolate Variables", self.variable_replacers
|
|
.iter()
|
|
.map(|(value, variable)| format!("<span class=\"text-muted-foreground\">{variable} =></span> {value}"))
|
|
.collect::<Vec<_>>()
|
|
.join("\n")));
|
|
}
|
|
|
|
// Only show names of interpolated secrets
|
|
if !self.secret_replacers.is_empty() {
|
|
logs.push(
|
|
Log::simple("Interpolate Secrets",
|
|
self.secret_replacers
|
|
.iter()
|
|
.map(|(_, variable)| format!("<span class=\"text-muted-foreground\">replaced:</span> {variable}"))
|
|
.collect::<Vec<_>>()
|
|
.join("\n"),)
|
|
);
|
|
}
|
|
}
|
|
}
|