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
4 changes: 4 additions & 0 deletions crates/aisix-admin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,7 @@ mod tests {
rejected: vec![],
partially_compatible: Vec::new(),
partially_compatible_rows_by_kind: Default::default(),
stale_served_rows_by_kind: Default::default(),
is_reload: true,
wholly_rejected: false,
});
Expand Down Expand Up @@ -837,13 +838,15 @@ mod tests {
last_error_kind: "schema_failed".into(),
last_error: "schema validation failed at `/display_name`".into(),
seen_at: chrono::Utc::now(),
serving_stale_since: None,
}],
partially_compatible: vec![aisix_core::config_status::PartialCompatResource {
resource_kind: "api_keys".into(),
field: "quota_profile".into(),
count: 2,
}],
partially_compatible_rows_by_kind: [("api_keys".to_string(), 2)].into_iter().collect(),
stale_served_rows_by_kind: Default::default(),
is_reload: true,
wholly_rejected: false,
});
Expand Down Expand Up @@ -899,6 +902,7 @@ mod tests {
rejected: vec![],
partially_compatible: Vec::new(),
partially_compatible_rows_by_kind: Default::default(),
stale_served_rows_by_kind: Default::default(),
is_reload: true,
wholly_rejected: false,
});
Expand Down
75 changes: 65 additions & 10 deletions crates/aisix-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,16 @@ pub struct ManagedConfig {
/// so the proxy can serve traffic from cached config across CP
/// outages and full container restarts.
///
/// Empty string disables persistence — useful for ephemeral test
/// runs where you don't want a stale cache to mask a real failure.
#[serde(default = "ManagedConfig::default_snapshot_cache_path")]
pub snapshot_cache_path: String,
/// When the field is omitted, managed mode uses
/// `/var/lib/aisix/config_cache.json` and self-hosted etcd mode
/// leaves persistence off (unchanged defaults). Setting a path
/// enables the cache in either mode — self-hosted etcd deployments
/// gain the same offline resilience by opting in. Empty string
/// disables persistence everywhere — useful for ephemeral test runs
/// where you don't want a stale cache to mask a real failure. A
/// bare `snapshot_cache_path:` (YAML null) is treated as omitted.
#[serde(default)]
pub snapshot_cache_path: Option<String>,

/// Heartbeat interval, in seconds. The DP POSTs a heartbeat to
/// dp-manager every `heartbeat_interval_secs`; CP surfaces a DP as
Expand Down Expand Up @@ -296,15 +302,28 @@ impl ManagedConfig {
has_pem || has_file
}

/// Resolve the snapshot-cache path per the field docs: an explicit
/// path wins in any mode, an explicit empty string disables, and an
/// omitted field means "the default path in managed mode, disabled
/// in self-hosted etcd mode".
pub fn effective_snapshot_cache_path(&self) -> Option<&str> {
match self.snapshot_cache_path.as_deref() {
Some("") => None,
Some(path) => Some(path),
None if self.is_managed() => Some(Self::DEFAULT_SNAPSHOT_CACHE_PATH),
None => None,
}
}

/// Default on-disk snapshot cache location for managed mode.
pub const DEFAULT_SNAPSHOT_CACHE_PATH: &'static str = "/var/lib/aisix/config_cache.json";

fn default_mtls_dir() -> String {
"/var/lib/aisix/mtls".into()
}
fn default_dp_id_file() -> String {
"/var/lib/aisix/dp_id".into()
}
fn default_snapshot_cache_path() -> String {
"/var/lib/aisix/config_cache.json".into()
}
const fn default_heartbeat_interval_secs() -> u64 {
15
}
Expand Down Expand Up @@ -2091,15 +2110,51 @@ managed:
assert_eq!(cfg.managed.mtls_dir, "/var/lib/aisix/mtls");
assert_eq!(cfg.managed.dp_id_file, "/var/lib/aisix/dp_id");
// Default snapshot cache path keeps offline-resilience on by
// default; operators opt out by setting the field to "".
// default in managed mode; operators opt out by setting the
// field to "".
assert_eq!(
cfg.managed.snapshot_cache_path,
"/var/lib/aisix/config_cache.json",
cfg.managed.effective_snapshot_cache_path(),
Some("/var/lib/aisix/config_cache.json"),
);
// CP URL comes from env at runtime — empty here is fine.
assert!(cfg.managed.cp_base_url.is_none());
}

/// #871: the snapshot cache resolves per mode — managed defaults on,
/// self-hosted etcd defaults off, an explicit path enables either,
/// an explicit "" disables either.
#[test]
fn snapshot_cache_path_resolution_per_mode() {
let mut managed = ManagedConfig {
enabled: true,
..Default::default()
};
assert_eq!(
managed.effective_snapshot_cache_path(),
Some(ManagedConfig::DEFAULT_SNAPSHOT_CACHE_PATH),
);
managed.snapshot_cache_path = Some(String::new());
assert_eq!(managed.effective_snapshot_cache_path(), None);
managed.snapshot_cache_path = Some("/tmp/cache.json".into());
assert_eq!(
managed.effective_snapshot_cache_path(),
Some("/tmp/cache.json"),
);

let mut self_hosted = ManagedConfig {
enabled: false,
..Default::default()
};
assert_eq!(self_hosted.effective_snapshot_cache_path(), None);
self_hosted.snapshot_cache_path = Some("/tmp/cache.json".into());
assert_eq!(
self_hosted.effective_snapshot_cache_path(),
Some("/tmp/cache.json"),
);
self_hosted.snapshot_cache_path = Some(String::new());
assert_eq!(self_hosted.effective_snapshot_cache_path(), None);
}

#[test]
fn rejects_legacy_registration_token_field() {
let f = write_yaml(
Expand Down
Loading
Loading