* update easy deps

* update otel deps

* implement template in types + update resource meta

* ts types

* dev-2

* dev-3 default template query is include

* Toggle resource is template in resource header

* dev-4 support CopyServer

* gen ts

* style template selector in New Resource menu

* fix new menu show 0

* add template market in omni search bar

* fix some dynamic import behavior

* template badge on dashboard

* dev-5

* standardize interpolation methods with nice api

* core use new interpolation methods

* refactor git usage

* dev-6 refactor interpolation / git methods

* fix pull stack passed replacers

*  new types

* remove redundant interpolation for build secret args

* clean up periphery docker client

* dev-7 include ports in container summary, see if they actually come through

* show container ports in container table

* refresh processes without tasks (more efficient)

* dev-8 keep container stats cache, include with ContainerListItem

* gen types

* display more container ports

* dev-9 fix repo clone when repo doesn't exist initially

* Add ports display to more spots

* fix function name

* add Periphery full container stats api, may be used later

* server container stats list

* dev-10

* 1.18.4 release

* Use reset instead of invalidate to fix GetUser spam on token expiry (#618)

---------

Co-authored-by: Jacky Fong <hello@huzky.dev>
This commit is contained in:
Maxwell Becker
2025-06-24 16:32:39 -07:00
committed by GitHub
parent 2205a81e79
commit 118ae9b92c
141 changed files with 5896 additions and 4453 deletions

View File

@@ -0,0 +1,15 @@
[package]
name = "interpolate"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
[dependencies]
komodo_client.workspace = true
#
svi.workspace = true
#
anyhow.workspace = true

181
lib/interpolate/src/lib.rs Normal file
View File

@@ -0,0 +1,181 @@
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_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"),)
);
}
}
}