Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions lib/bolt/cli/src/commands/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,8 @@ impl SubCommand {

// Load namespace config
let ns_config = if fs::metadata(&namespace_path).await.is_ok() {
// TODO (RVT-3747): Parse as plain toml
let ns_config =
ProjectContextData::read_ns(project_root.as_path(), &ns_id).await;
ProjectContextData::read_partial_ns(project_root.as_path(), &ns_id).await;

// Try to read op paths from ns config
if let Some(_1password) = &ns_config.secrets._1password {
Expand Down Expand Up @@ -187,14 +186,17 @@ impl SubCommand {
};

// Determine local secrets path
let secrets_path =
ProjectContextData::get_secrets_path(ns_config.as_ref(), &project_root, &ns_id);
let secrets_path = ProjectContextData::get_secrets_path(
ns_config.as_ref().map(|ns| &ns.secrets),
&project_root,
&ns_id,
);

// Load secrets
let secrets = if fs::metadata(&secrets_path).await.is_ok() {
Some(
ProjectContextData::read_secrets(
ns_config.as_ref(),
ns_config.as_ref().map(|ns| &ns.secrets),
project_root.as_path(),
&ns_id,
)
Expand Down Expand Up @@ -429,7 +431,8 @@ impl SubCommand {
.context("failed to read namespace config")?;
let local_secrets_str = fs::read_to_string(&secrets_path).await?;
let secrets =
ProjectContextData::read_secrets(Some(ctx.ns()), ctx.path(), ns_id).await;
ProjectContextData::read_secrets(Some(&ctx.ns().secrets), ctx.path(), ns_id)
.await;

let ns_patches = json_patch::diff(&op_namespace, &namespace);
if !ns_patches.is_empty() {
Expand Down
7 changes: 7 additions & 0 deletions lib/bolt/config/src/ns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -766,3 +766,10 @@ fn default_tunnel_port() -> u16 {
fn default_job_server_provision_margin() -> u32 {
2
}

// Used for parsing from 1password
#[derive(Deserialize, Debug)]
pub struct PartialNamespace {
#[serde(default)]
pub secrets: Secrets,
}
58 changes: 45 additions & 13 deletions lib/bolt/core/src/context/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,12 @@ impl ProjectContextData {
let ns_config = ProjectContextData::read_ns(project_root.as_path(), &ns_id).await;

// Load secrets
let secrets =
ProjectContextData::read_secrets(Some(&ns_config), project_root.as_path(), &ns_id)
.await;
let secrets = ProjectContextData::read_secrets(
Some(&ns_config.secrets),
project_root.as_path(),
&ns_id,
)
.await;

let mut svc_ctxs_map = HashMap::new();

Expand Down Expand Up @@ -358,14 +361,15 @@ impl ProjectContextData {
}

pub fn get_secrets_path(
ns: Option<&config::ns::Namespace>,
ns_secrets: Option<&config::ns::Secrets>,
project_path: &Path,
ns_id: &str,
) -> PathBuf {
ns.and_then(|ns| ns.secrets.path.as_ref()).map_or_else(
|| project_path.join("secrets").join(format!("{}.toml", ns_id)),
|v| v.clone(),
)
if let Some(path) = ns_secrets.and_then(|s| s.path.as_ref()) {
path.clone()
} else {
project_path.join("secrets").join(format!("{}.toml", ns_id))
}
}
}

Expand Down Expand Up @@ -481,7 +485,7 @@ impl ProjectContextData {
}
}

pub async fn read_ns(project_path: &Path, ns_id: &str) -> config::ns::Namespace {
async fn read_ns(project_path: &Path, ns_id: &str) -> config::ns::Namespace {
let path = project_path
.join("namespaces")
.join(format!("{ns_id}.toml"));
Expand All @@ -496,7 +500,7 @@ impl ProjectContextData {
"failed to parse namespace config ({:?}): {}\n\n{}\n",
&span,
err.message(),
&config_str[span.clone()]
&config_str[span.clone()],
);
} else {
panic!("failed to parse namespace config: {}", err.message());
Expand All @@ -515,12 +519,40 @@ impl ProjectContextData {
config
}

pub async fn read_partial_ns(project_path: &Path, ns_id: &str) -> config::ns::PartialNamespace {
let path = project_path
.join("namespaces")
.join(format!("{ns_id}.toml"));
let config_str = fs::read_to_string(&path)
.await
.unwrap_or_else(|_| panic!("failed to read namespace config: {}", path.display()));

match toml::from_str::<config::ns::PartialNamespace>(&config_str) {
Result::Ok(x) => x,
Result::Err(err) => {
if let Some(span) = err.span().filter(|span| span.start != span.end) {
panic!(
"failed to partially parse namespace config ({:?}): {}\n\n{}\n",
&span,
err.message(),
&config_str[span.clone()],
);
} else {
panic!(
"failed to partially parse namespace config: {}",
err.message()
);
}
}
}
}

pub async fn read_secrets(
ns: Option<&config::ns::Namespace>,
ns_secrets: Option<&config::ns::Secrets>,
project_path: &Path,
ns_id: &str,
) -> serde_json::Value {
let secrets_path = ProjectContextData::get_secrets_path(ns, project_path, ns_id);
let secrets_path = ProjectContextData::get_secrets_path(ns_secrets, project_path, ns_id);
// Read the config
let config_str = fs::read_to_string(&secrets_path)
.await
Expand Down Expand Up @@ -692,7 +724,7 @@ impl ProjectContextData {
}

pub fn secrets_path(&self) -> PathBuf {
ProjectContextData::get_secrets_path(Some(self.ns()), self.path(), self.ns_id())
ProjectContextData::get_secrets_path(Some(&self.ns().secrets), self.path(), self.ns_id())
}

pub fn gen_path(&self) -> PathBuf {
Expand Down
3 changes: 2 additions & 1 deletion lib/bolt/core/src/tasks/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,8 @@ pub async fn check_config_sync(ctx: &ProjectContext) {
let local_namespace_str = fs::read_to_string(&namespace_path).await.unwrap();
let namespace = toml::from_str::<serde_json::Value>(&local_namespace_str)
.expect("failed to read namespace config");
let secrets = ProjectContextData::read_secrets(Some(ctx.ns()), ctx.path(), &ns_id).await;
let secrets =
ProjectContextData::read_secrets(Some(&ctx.ns().secrets), ctx.path(), &ns_id).await;

let ns_patches = json_patch::diff(&op_namespace, &namespace);
if !ns_patches.is_empty() {
Expand Down