style: cargo fmt the workspace (release-gate cargo-fmt was red)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
412251ac9a
commit
db4de0ac96
@@ -400,10 +400,7 @@ pub async fn refresh_catalog(data_dir: &Path) -> anyhow::Result<CatalogRefresh>
|
||||
Err(last_err.unwrap_or_else(|| anyhow::anyhow!("no catalog mirrors reachable")))
|
||||
}
|
||||
|
||||
async fn fetch_one(
|
||||
client: &reqwest::Client,
|
||||
url: &str,
|
||||
) -> anyhow::Result<(AppCatalog, String)> {
|
||||
async fn fetch_one(client: &reqwest::Client, url: &str) -> anyhow::Result<(AppCatalog, String)> {
|
||||
let resp = client.get(url).send().await?;
|
||||
if !resp.status().is_success() {
|
||||
anyhow::bail!("HTTP {}", resp.status());
|
||||
@@ -510,7 +507,10 @@ mod tests {
|
||||
// on the apps HashMap's nondeterministic key order (seen live on .228).
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let body = r#"{"schema":1,"apps":{"demo":{"version":"1.0.0"}}}"#;
|
||||
assert!(write_cache(dir.path(), body).unwrap(), "first write is a change");
|
||||
assert!(
|
||||
write_cache(dir.path(), body).unwrap(),
|
||||
"first write is a change"
|
||||
);
|
||||
assert!(
|
||||
!write_cache(dir.path(), body).unwrap(),
|
||||
"identical rewrite is not a change"
|
||||
|
||||
@@ -7,12 +7,8 @@
|
||||
/// Registries images may be pulled from with an explicit host part.
|
||||
/// (git.tx1138.com was removed 2026-07-10: the host is retired and must
|
||||
/// never be pulled through again.)
|
||||
pub const TRUSTED_REGISTRIES: &[&str] = &[
|
||||
"docker.io",
|
||||
"ghcr.io",
|
||||
"localhost",
|
||||
"146.59.87.168:3000",
|
||||
];
|
||||
pub const TRUSTED_REGISTRIES: &[&str] =
|
||||
&["docker.io", "ghcr.io", "localhost", "146.59.87.168:3000"];
|
||||
|
||||
/// Validate a container image reference.
|
||||
///
|
||||
|
||||
@@ -727,14 +727,12 @@ pub async fn ensure_btcpay_lnd_connection_secret(secrets_dir: &std::path::Path)
|
||||
Ok(s) => s,
|
||||
Err(_) => return Ok(()), // LND not installed/provisioned yet
|
||||
};
|
||||
let thumbprint =
|
||||
cert_sha256_thumbprint(&pem).context("computing LND tls.cert thumbprint")?;
|
||||
let thumbprint = cert_sha256_thumbprint(&pem).context("computing LND tls.cert thumbprint")?;
|
||||
|
||||
let target = secrets_dir.join(BTCPAY_LND_CONNECTION_SECRET);
|
||||
// Fast path (no sudo): existing secret already pins the current cert.
|
||||
if let Ok(existing) = fs::read_to_string(&target).await {
|
||||
if !existing.trim().is_empty()
|
||||
&& existing.contains(&format!("certthumbprint={thumbprint}"))
|
||||
if !existing.trim().is_empty() && existing.contains(&format!("certthumbprint={thumbprint}"))
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
@@ -782,7 +780,9 @@ mod tests {
|
||||
conf_path: tmp.path().join("lnd/lnd.conf"),
|
||||
};
|
||||
|
||||
let out = ensure_config(&paths, "secret", "bitcoin-knots").await.unwrap();
|
||||
let out = ensure_config(&paths, "secret", "bitcoin-knots")
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(out, EnsureOutcome::Written);
|
||||
let conf = fs::read_to_string(&paths.conf_path).await.unwrap();
|
||||
assert!(conf.contains("bitcoin.active=true"));
|
||||
@@ -801,11 +801,15 @@ mod tests {
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
ensure_config(&paths, "first", "bitcoin-knots").await.unwrap(),
|
||||
ensure_config(&paths, "first", "bitcoin-knots")
|
||||
.await
|
||||
.unwrap(),
|
||||
EnsureOutcome::Written
|
||||
);
|
||||
assert_eq!(
|
||||
ensure_config(&paths, "second", "bitcoin-knots").await.unwrap(),
|
||||
ensure_config(&paths, "second", "bitcoin-knots")
|
||||
.await
|
||||
.unwrap(),
|
||||
EnsureOutcome::Written
|
||||
);
|
||||
let conf = fs::read_to_string(&paths.conf_path).await.unwrap();
|
||||
@@ -854,7 +858,9 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
ensure_config(&paths, "repaired", "bitcoin-knots").await.unwrap(),
|
||||
ensure_config(&paths, "repaired", "bitcoin-knots")
|
||||
.await
|
||||
.unwrap(),
|
||||
EnsureOutcome::Written
|
||||
);
|
||||
let conf = fs::read_to_string(&paths.conf_path).await.unwrap();
|
||||
|
||||
@@ -1468,9 +1468,7 @@ impl ProdContainerOrchestrator {
|
||||
);
|
||||
}
|
||||
}
|
||||
for (port, a, b) in
|
||||
host_port_collisions(state.manifests.values().map(|lm| &lm.manifest))
|
||||
{
|
||||
for (port, a, b) in host_port_collisions(state.manifests.values().map(|lm| &lm.manifest)) {
|
||||
tracing::error!(
|
||||
port,
|
||||
app_a = %a,
|
||||
@@ -1666,7 +1664,10 @@ impl ProdContainerOrchestrator {
|
||||
// and left the unit down for minutes (.228 mempool frontend, gate
|
||||
// 2026-07-09). Skip this cycle; the worker owns the outcome.
|
||||
if crate::app_ops::lifecycle_op_in_flight(&app_id) {
|
||||
report.record(&app_id, ReconcileAction::Left("lifecycle-op-in-flight".into()));
|
||||
report.record(
|
||||
&app_id,
|
||||
ReconcileAction::Left("lifecycle-op-in-flight".into()),
|
||||
);
|
||||
crate::crash_recovery::pending_boot_start_done(&app_id);
|
||||
crate::crash_recovery::pending_boot_start_done(&container_name);
|
||||
continue;
|
||||
@@ -1773,10 +1774,9 @@ impl ProdContainerOrchestrator {
|
||||
|
||||
{
|
||||
let state = self.state.read().await;
|
||||
for (app, dep) in degraded_running_apps(
|
||||
&report,
|
||||
state.manifests.values().map(|lm| &lm.manifest),
|
||||
) {
|
||||
for (app, dep) in
|
||||
degraded_running_apps(&report, state.manifests.values().map(|lm| &lm.manifest))
|
||||
{
|
||||
tracing::error!(
|
||||
app_id = %app,
|
||||
dependency = %dep,
|
||||
@@ -3184,8 +3184,7 @@ impl ProdContainerOrchestrator {
|
||||
// `optional` secret_env — btcpay must still start when LND is
|
||||
// absent or the derivation fails, so log-and-continue.
|
||||
if let Err(e) =
|
||||
crate::container::lnd::ensure_btcpay_lnd_connection_secret(&self.secrets_dir)
|
||||
.await
|
||||
crate::container::lnd::ensure_btcpay_lnd_connection_secret(&self.secrets_dir).await
|
||||
{
|
||||
tracing::warn!(error = %e, "btcpay-lnd-connection secret not generated; btcpay will run without the internal LND node");
|
||||
}
|
||||
@@ -3260,20 +3259,17 @@ impl ProdContainerOrchestrator {
|
||||
manifest.app.container.secret_env_refs = Vec::new();
|
||||
manifest.app.container.secret_env_hash = None;
|
||||
} else {
|
||||
let hash =
|
||||
archipelago_container::manifest::secret_env_content_hash(&secret_bearing);
|
||||
let hash = archipelago_container::manifest::secret_env_content_hash(&secret_bearing);
|
||||
let app_id = manifest.app.id.clone();
|
||||
manifest.app.container.secret_env_refs = secret_bearing
|
||||
.into_iter()
|
||||
.map(|(key, value)| archipelago_container::manifest::SecretEnvRef {
|
||||
secret_name: format!(
|
||||
"archy-env-{}-{}",
|
||||
app_id,
|
||||
key.to_ascii_lowercase()
|
||||
),
|
||||
env_key: key,
|
||||
value,
|
||||
})
|
||||
.map(
|
||||
|(key, value)| archipelago_container::manifest::SecretEnvRef {
|
||||
secret_name: format!("archy-env-{}-{}", app_id, key.to_ascii_lowercase()),
|
||||
env_key: key,
|
||||
value,
|
||||
},
|
||||
)
|
||||
.collect();
|
||||
manifest.app.container.secret_env_hash = Some(hash.clone());
|
||||
|
||||
@@ -3281,12 +3277,7 @@ impl ProdContainerOrchestrator {
|
||||
// the steady-state reconcile free: podman is only consulted when
|
||||
// the resolved content actually changed (or on first touch after
|
||||
// boot). Mock runtimes no-op via the trait default.
|
||||
let cached = self
|
||||
.env_secret_cache
|
||||
.lock()
|
||||
.await
|
||||
.get(&app_id)
|
||||
.cloned();
|
||||
let cached = self.env_secret_cache.lock().await.get(&app_id).cloned();
|
||||
if cached.as_deref() != Some(hash.as_str()) {
|
||||
self.runtime
|
||||
.ensure_env_secrets(&manifest.app.container.secret_env_refs)
|
||||
@@ -3926,7 +3917,10 @@ impl ContainerOrchestrator for ProdContainerOrchestrator {
|
||||
|
||||
async fn start(&self, app_id: &str) -> Result<()> {
|
||||
if let Some(members) = self.mempool_umbrella_members(app_id).await {
|
||||
tracing::info!(app_id, "starting legacy umbrella id via split-stack members");
|
||||
tracing::info!(
|
||||
app_id,
|
||||
"starting legacy umbrella id via split-stack members"
|
||||
);
|
||||
for (i, member) in members.iter().enumerate() {
|
||||
if i > 0 {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
|
||||
@@ -3969,7 +3963,10 @@ impl ContainerOrchestrator for ProdContainerOrchestrator {
|
||||
|
||||
async fn stop(&self, app_id: &str) -> Result<()> {
|
||||
if let Some(members) = self.mempool_umbrella_members(app_id).await {
|
||||
tracing::info!(app_id, "stopping legacy umbrella id via split-stack members");
|
||||
tracing::info!(
|
||||
app_id,
|
||||
"stopping legacy umbrella id via split-stack members"
|
||||
);
|
||||
for member in members.iter().rev() {
|
||||
Box::pin(self.stop(member))
|
||||
.await
|
||||
@@ -4036,7 +4033,10 @@ impl ContainerOrchestrator for ProdContainerOrchestrator {
|
||||
|
||||
async fn restart(&self, app_id: &str) -> Result<()> {
|
||||
if let Some(members) = self.mempool_umbrella_members(app_id).await {
|
||||
tracing::info!(app_id, "restarting legacy umbrella id via split-stack members");
|
||||
tracing::info!(
|
||||
app_id,
|
||||
"restarting legacy umbrella id via split-stack members"
|
||||
);
|
||||
for (i, member) in members.iter().enumerate() {
|
||||
if i > 0 {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
|
||||
@@ -4239,9 +4239,8 @@ fn command_argv_drifted(
|
||||
// therefore Config.Cmd) has them as spaces. Normalize both sides so the
|
||||
// same script never reads as drift over line breaks alone (bitcoin-knots
|
||||
// and fedimint-gateway on .228, 2026-07-08).
|
||||
let norm = |v: &[String]| -> Vec<String> {
|
||||
v.iter().map(|s| s.replace(['\r', '\n'], " ")).collect()
|
||||
};
|
||||
let norm =
|
||||
|v: &[String]| -> Vec<String> { v.iter().map(|s| s.replace(['\r', '\n'], " ")).collect() };
|
||||
let current_cmd = norm(current_cmd);
|
||||
let expected_args = norm(expected_args);
|
||||
let Some(expected_entry) = expected_entry else {
|
||||
@@ -5508,14 +5507,20 @@ app:
|
||||
("bitcoin-knots", ReconcileAction::Installed),
|
||||
("lnd", ReconcileAction::NoOp),
|
||||
]);
|
||||
assert_eq!(cascade_pairs_for_report(&r, &none), vec![("bitcoin-knots", "lnd")]);
|
||||
assert_eq!(
|
||||
cascade_pairs_for_report(&r, &none),
|
||||
vec![("bitcoin-knots", "lnd")]
|
||||
);
|
||||
|
||||
// Backend merely started from stopped also moves the IP → cascade.
|
||||
let r = report(vec![
|
||||
("bitcoin-core", ReconcileAction::Started),
|
||||
("lnd", ReconcileAction::NoOp),
|
||||
]);
|
||||
assert_eq!(cascade_pairs_for_report(&r, &none), vec![("bitcoin-core", "lnd")]);
|
||||
assert_eq!(
|
||||
cascade_pairs_for_report(&r, &none),
|
||||
vec![("bitcoin-core", "lnd")]
|
||||
);
|
||||
|
||||
// Backend untouched → no cascade.
|
||||
let r = report(vec![
|
||||
@@ -6016,7 +6021,9 @@ app:
|
||||
let calls = rt.calls();
|
||||
for name in ["archy-mempool-db", "mempool-api", "archy-mempool-web"] {
|
||||
assert!(
|
||||
calls.iter().any(|c| c == &format!("start_container:{name}")),
|
||||
calls
|
||||
.iter()
|
||||
.any(|c| c == &format!("start_container:{name}")),
|
||||
"{name} not started: {calls:?}"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1258,7 +1258,10 @@ app:
|
||||
assert!(u.read_only_root);
|
||||
assert!(u.no_new_privileges);
|
||||
assert_eq!(u.cap_add, vec!["NET_BIND_SERVICE"]);
|
||||
assert_eq!(u.ports, vec![(8332, 8332, "tcp".to_string(), String::new())]);
|
||||
assert_eq!(
|
||||
u.ports,
|
||||
vec![(8332, 8332, "tcp".to_string(), String::new())]
|
||||
);
|
||||
assert_eq!(u.environment, vec!["BITCOIN_NETWORK=mainnet"]);
|
||||
assert_eq!(u.bind_mounts.len(), 1);
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user