From 735c2c1eb9cfdf9ae016832bad871d997250b98c Mon Sep 17 00:00:00 2001 From: Nathan Flurry Date: Sat, 13 Jan 2024 19:32:01 +0000 Subject: [PATCH] Add bolt secret set command (#340) ## Changes --- CHANGELOG.md | 1 + infra/tf/modules/write_secret/main.tf | 10 ++++++++++ infra/tf/modules/write_secret/vars.tf | 11 +++++++++++ lib/bolt/Cargo.lock | 2 ++ lib/bolt/cli/Cargo.toml | 2 ++ lib/bolt/cli/src/commands/secret.rs | 15 +++++++++++++++ lib/bolt/core/src/tasks/config/generate.rs | 13 ++++++++++--- lib/bolt/core/src/tasks/config/mod.rs | 2 +- 8 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 infra/tf/modules/write_secret/main.tf create mode 100644 infra/tf/modules/write_secret/vars.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index 447f57f5be..290aab63a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Infra** New `job-runner` crate responsible for managing the OCI bundle runtime & log shipping on the machine - **Infra** Jobs now log an explicit rate message when logs are rate limited & truncated - **Infra** `infra-artifacts` Terraform plan & S3 bucket used for automating building & uploading internal binaries, etc. +- **Bolt** `bolt secret set ` command ### Changed diff --git a/infra/tf/modules/write_secret/main.tf b/infra/tf/modules/write_secret/main.tf new file mode 100644 index 0000000000..1c1bf376dc --- /dev/null +++ b/infra/tf/modules/write_secret/main.tf @@ -0,0 +1,10 @@ +resource "null_resource" "example" { + triggers = var.triggers + + provisioner "local-exec" { + # HACK: jsonencode is an imperfect encoding of strings to safe encoding in bash + command = "bolt secret set ${jsonencode(var.path)} ${jsonencode(var.value)}" + } +} + + diff --git a/infra/tf/modules/write_secret/vars.tf b/infra/tf/modules/write_secret/vars.tf new file mode 100644 index 0000000000..065209dc6c --- /dev/null +++ b/infra/tf/modules/write_secret/vars.tf @@ -0,0 +1,11 @@ +variable "triggers" { + type = map(string) +} + +variable "path" { + type = string +} + +variable "value" { + type = string +} diff --git a/lib/bolt/Cargo.lock b/lib/bolt/Cargo.lock index 7ca18f92b8..3910f0d407 100644 --- a/lib/bolt/Cargo.lock +++ b/lib/bolt/Cargo.lock @@ -442,9 +442,11 @@ dependencies = [ "chrono", "clap", "duct", + "rivet-term", "serde_json", "tempfile", "tokio", + "toml_edit", ] [[package]] diff --git a/lib/bolt/cli/Cargo.toml b/lib/bolt/cli/Cargo.toml index e4f2c37958..0bb4562f9a 100644 --- a/lib/bolt/cli/Cargo.toml +++ b/lib/bolt/cli/Cargo.toml @@ -11,6 +11,8 @@ bolt-core = { path = "../core" } chrono = "0.4" clap = { version = "4.3", features = ["derive", "env"] } duct = "0.13" +rivet-term = { git = "https://github.com/rivet-gg/rivet-term.git", rev = "7cf60c225f00eb40d212cec673f09ac47d13d295" } serde_json = "1.0" tempfile = "3.2" tokio = { version = "1.29", features = ["full"] } +toml_edit = "0.19.0" diff --git a/lib/bolt/cli/src/commands/secret.rs b/lib/bolt/cli/src/commands/secret.rs index 69312e5085..52f7d72413 100644 --- a/lib/bolt/cli/src/commands/secret.rs +++ b/lib/bolt/cli/src/commands/secret.rs @@ -1,5 +1,6 @@ use anyhow::*; use bolt_core::context::ProjectContext; +use bolt_core::tasks::config::ConfigGenerator; use clap::{Parser, ValueEnum}; use serde_json::json; @@ -18,6 +19,12 @@ pub enum SubCommand { #[clap(long, value_parser)] format: Option, }, + Set { + #[clap(index = 1)] + path: String, + #[clap(index = 2)] + value: String, + }, } impl SubCommand { @@ -49,6 +56,14 @@ impl SubCommand { Some(Format::Json) => println!("{}", json!({ "value": value })), } } + Self::Set { path, value } => { + let path = path.split("/").collect::>(); + + let mut generator = + ConfigGenerator::new(rivet_term::terminal(), ctx.path(), ctx.ns_id()).await?; + generator.set_secret(&path, toml_edit::value(value)).await?; + generator.write().await?; + } } Ok(()) diff --git a/lib/bolt/core/src/tasks/config/generate.rs b/lib/bolt/core/src/tasks/config/generate.rs index 955bafc6f3..f85ce745b2 100644 --- a/lib/bolt/core/src/tasks/config/generate.rs +++ b/lib/bolt/core/src/tasks/config/generate.rs @@ -23,7 +23,7 @@ const NS_CONFIG_COMMENT: &str = r#"# Documentation: doc/bolt/config/NAMESPACE.md "#; /// Helper for generating configs. -struct ConfigGenerator { +pub struct ConfigGenerator { term: rivet_term::console::Term, #[allow(unused)] @@ -41,7 +41,7 @@ struct ConfigGenerator { } impl ConfigGenerator { - async fn new( + pub async fn new( term: rivet_term::console::Term, project_path: &Path, ns_id: impl ToString, @@ -80,7 +80,7 @@ impl ConfigGenerator { } // Writes the config to the respective files. - async fn write(&mut self) -> Result<()> { + pub async fn write(&mut self) -> Result<()> { // Prepend comment let mut ns_str = self.ns.to_string(); if self.is_new { @@ -145,6 +145,13 @@ impl ConfigGenerator { // Ok(()) // } + /// Sets & overrides a secret. + pub async fn set_secret(&mut self, path: &[&str], value: toml_edit::Item) -> Result<()> { + write_value(self.secrets.as_item_mut(), path, value); + + Ok(()) + } + /// Inserts a secret value if does not exist. async fn generate_secret( &mut self, diff --git a/lib/bolt/core/src/tasks/config/mod.rs b/lib/bolt/core/src/tasks/config/mod.rs index 4d07fea30a..0c2aca58b7 100644 --- a/lib/bolt/core/src/tasks/config/mod.rs +++ b/lib/bolt/core/src/tasks/config/mod.rs @@ -7,7 +7,7 @@ use crate::context; mod generate; mod generate_default_regions; -pub use generate::generate; +pub use generate::{generate, ConfigGenerator}; pub use generate_default_regions::generate_default_regions; /// Updates the namespace in `Bolt.local.toml`.