Skip to content

Commit cdd6d74

Browse files
committed
feat(boil): Properly support multi-registry image checks
1 parent a91a5b9 commit cdd6d74

3 files changed

Lines changed: 57 additions & 46 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ license = "Apache-2.0"
99

1010
[workspace.dependencies]
1111
cap-std = "4.0.2"
12-
clap = { version = "4.5.41", features = ["derive", "env"] }
12+
clap = { version = "4.5.41", features = ["derive"] }
1313
clap_complete = "4.5.55"
1414
clap_complete_nushell = "4.5.8"
1515
git2 = { version = "0.20.1", features = ["vendored-openssl"] }

rust/boil/src/cmd/image.rs

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
config::Config,
99
core::bakefile::{self, Targets, TargetsOptions},
1010
models::TagList,
11-
utils::format_image_index_manifest_tag,
11+
utils::{format_image_index_manifest_tag, format_registry_token_env_var_name},
1212
};
1313

1414
#[derive(Debug, Snafu)]
@@ -95,55 +95,58 @@ pub async fn check_images(arguments: ImageCheckArguments, config: Config) -> Res
9595
.context(BuildTargetsSnafu)?
9696
};
9797

98-
let registry_token = std::env::var("REGISTRY_TOKEN").ok().map(SecretString::from);
98+
let mut registry_tokens = BTreeMap::new();
9999
let client = reqwest::ClientBuilder::new()
100100
.build()
101101
.context(BuildClientSnafu)?;
102102

103103
for (image_name, (image_config, _)) in targets {
104-
// TODO (@Techassi): Do these checks for all registries
105-
let Some((registry, registry_options)) = image_config.metadata.registries.first_key_value()
106-
else {
107-
continue;
108-
};
109-
110-
println!(
111-
"Checking for {registry}/{registry_namespace}/{image_name}",
112-
registry_namespace = registry_options.namespace,
113-
);
114-
115-
let url = format!(
116-
"https://{registry}/v2/{registry_namespace}/{image_name}/tags/list",
117-
registry_namespace = registry_options.namespace,
118-
);
119-
let request = client.get(url);
120-
121-
let request = match &registry_token {
122-
Some(registry_token) => request.bearer_auth(registry_token.expose_secret()),
123-
None => request,
124-
};
125-
126-
let tag_list: TagList = request
127-
.send()
128-
.await
129-
.context(SendRequestSnafu)?
130-
.json()
131-
.await
132-
.context(DeserializeResponseSnafu)?;
133-
134-
ensure!(
135-
image_config.versions.iter().all(|(image_version, _)| {
136-
let index_manifest_tag = format_image_index_manifest_tag(
137-
image_version,
138-
&config.metadata.vendor_tag_prefix,
139-
&arguments.image_version,
140-
);
141-
142-
println!("- {image_name}:{index_manifest_tag}");
143-
tag_list.tags.contains(&index_manifest_tag)
144-
}),
145-
MissingVersionSnafu { image_name }
146-
);
104+
for (registry, registry_options) in image_config.metadata.registries {
105+
// Add tokens to a map so that we don't need construct the key and retrieve the value
106+
// over and over again.
107+
let registry_token = registry_tokens.entry(registry.clone()).or_insert_with(|| {
108+
let name = format_registry_token_env_var_name(&registry);
109+
std::env::var(name).ok().map(SecretString::from)
110+
});
111+
112+
println!(
113+
"Checking for {registry}/{registry_namespace}/{image_name}",
114+
registry_namespace = registry_options.namespace,
115+
);
116+
117+
let url = format!(
118+
"https://{registry}/v2/{registry_namespace}/{image_name}/tags/list",
119+
registry_namespace = registry_options.namespace,
120+
);
121+
let request = client.get(url);
122+
123+
let request = match &registry_token {
124+
Some(registry_token) => request.bearer_auth(registry_token.expose_secret()),
125+
None => request,
126+
};
127+
128+
let tag_list: TagList = request
129+
.send()
130+
.await
131+
.context(SendRequestSnafu)?
132+
.json()
133+
.await
134+
.context(DeserializeResponseSnafu)?;
135+
136+
ensure!(
137+
image_config.versions.iter().all(|(image_version, _)| {
138+
let index_manifest_tag = format_image_index_manifest_tag(
139+
image_version,
140+
&config.metadata.vendor_tag_prefix,
141+
&arguments.image_version,
142+
);
143+
144+
println!("- {image_name}:{index_manifest_tag}");
145+
tag_list.tags.contains(&index_manifest_tag)
146+
}),
147+
MissingVersionSnafu { image_name }
148+
);
149+
}
147150
}
148151

149152
Ok(())

rust/boil/src/utils.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ pub fn format_image_manifest_tag(
4343
}
4444
}
4545

46+
/// Formats and returns the registry-specific env var name, eg. `BOIL_REGISTRY_TOKEN_OCI_STACKABLE_TECH`.
47+
pub fn format_registry_token_env_var_name(registry_uri: &str) -> String {
48+
format!(
49+
"BOIL_REGISTRY_TOKEN_{registry_uri}",
50+
registry_uri = registry_uri.replace(['.', '#'], "_").to_uppercase()
51+
)
52+
}
53+
4654
pub trait CommandExt {
4755
/// Adds an argument to the command if the `predicate` is `true`.
4856
fn arg_if<S>(&mut self, predicate: bool, arg: S) -> &mut Self

0 commit comments

Comments
 (0)