diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 108fa6ab..37dc394c 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -844,6 +844,7 @@ impl Display for PolicyReloadError { #[derive(Deserialize, Serialize, Debug, Clone)] pub struct PolicyChanges { pub changes: Vec<(String, PolicyChange)>, + pub warnings: Vec, } #[derive(Deserialize, Serialize, Debug, Clone)] diff --git a/crates/cli/src/commands/policy.rs b/crates/cli/src/commands/policy.rs index a51e9354..fbb3c820 100644 --- a/crates/cli/src/commands/policy.rs +++ b/crates/cli/src/commands/policy.rs @@ -102,6 +102,14 @@ impl Policy { reset = ansi::RESET ); } + + if !res.warnings.is_empty() { + println!(); + } + + for w in res.warnings { + println!("{}WARNING{}: {w}", ansi::YELLOW, ansi::RESET); + } } } Ok(()) diff --git a/src/main.rs b/src/main.rs index 9a205110..16cd2aa3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -223,6 +223,8 @@ fn main() -> ExitCode { } } + let mut warnings = Vec::new(); + // Load all policies. let mut updates = Vec::new(); let res = policy::reload_all( @@ -232,8 +234,13 @@ fn main() -> ExitCode { |name, _| { updates.push(name.clone()); }, + &mut warnings, ); + for w in warnings { + warn!("{w}"); + } + if let Err(err) = res { error!("Cascade couldn't load all policies: {err}"); return ExitCode::FAILURE; diff --git a/src/policy/mod.rs b/src/policy/mod.rs index 01ca1d34..37ac61f9 100644 --- a/src/policy/mod.rs +++ b/src/policy/mod.rs @@ -11,7 +11,7 @@ use domain::base::Name; use domain::base::Ttl; use domain::tsig::KeyName; use serde::{Deserialize, Serialize}; -use tracing::{debug, error, info, warn}; +use tracing::info; use crate::tsig::TsigStore; use crate::{api::PolicyReloadError, config::Config}; @@ -61,8 +61,9 @@ pub fn reload_all( config: &Config, tsig_store: &TsigStore, mut on_change: impl FnMut(&Box, PolicyChange), + warnings: &mut Vec, ) -> Result<(), PolicyReloadError> { - let new_versions = load_all(policies, config, tsig_store)?; + let new_versions = load_all(policies, config, tsig_store, warnings)?; let mut new_policies = foldhash::HashMap::default(); @@ -96,9 +97,9 @@ pub fn reload_all( for (name, policy) in policies.drain() { // If any zones are using this policy, keep it. if !policy.zones.is_empty() { - error!( + warnings.push(format!( "The file backing policy '{name}' has been removed, but some zones are still using it; Cascade will preserve its internal copy" - ); + )); let prev = new_policies.insert(name, policy); assert!( prev.is_none(), @@ -131,6 +132,7 @@ pub fn load_all( policies: &foldhash::HashMap, Policy>, config: &Config, tsig_store: &TsigStore, + warnings: &mut Vec, ) -> Result, PolicyVersion>, PolicyReloadError> { // Write the loaded policies to a new hashmap, so policies that no longer // exist can be detected easily. @@ -145,10 +147,10 @@ pub fn load_all( // Filter for UTF-8 paths. let Ok(path) = Utf8PathBuf::from_path_buf(entry.path()) else { - warn!( + warnings.push(format!( "Ignoring potential policy '{}' as the path is non-UTF-8", entry.path().display() - ); + )); continue; }; @@ -158,7 +160,7 @@ pub fn load_all( .expect("this path has a known parent directory") .starts_with('.') { - debug!("Ignoring hidden file '{path}' among policies"); + warnings.push(format!("Ignoring hidden file '{path}' among policies")); continue; } @@ -167,7 +169,9 @@ pub fn load_all( .extension() .is_none_or(|e| !e.eq_ignore_ascii_case("toml")) { - warn!("Ignoring potential policy '{path}'; policies must end in '.toml'"); + warnings.push(format!( + "Ignoring potential policy '{path}'; policies must end in '.toml'" + )); continue; } @@ -179,7 +183,9 @@ pub fn load_all( Ok(spec) => spec, // Ignore a directory ending in '.toml'. Err(err) if err.kind() == io::ErrorKind::IsADirectory => { - warn!("Ignoring potential policy '{path}'; policies must be files"); + warnings.push(format!( + "Ignoring potential policy '{path}'; policies must be files" + )); continue; } Err(err) => return Err(PolicyReloadError::Io(path, err.to_string())), diff --git a/src/units/http_server.rs b/src/units/http_server.rs index c624f4e4..2a92c9af 100644 --- a/src/units/http_server.rs +++ b/src/units/http_server.rs @@ -905,6 +905,7 @@ impl HttpServer { .collect::>(); let mut changed = false; let mut updates = Vec::new(); + let mut warnings = Vec::new(); let res = crate::policy::reload_all( &mut state.policies, ¢er.config, @@ -923,6 +924,7 @@ impl HttpServer { updates.push((name.clone(), change)); }, + &mut warnings, ); if let Err(err) = res { @@ -971,7 +973,7 @@ impl HttpServer { changes.into_iter().map(|(p, c)| (p.into(), c)).collect(); changes.sort_unstable_by(|l, r| l.0.cmp(&r.0)); - Json(Ok(PolicyChanges { changes })) + Json(Ok(PolicyChanges { changes, warnings })) } async fn policy_show(