From 6e42afcea50dc5f5aae33cc25309f6894295c32a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=AD=A3=E8=B6=85?= Date: Sun, 21 Jun 2026 15:21:25 +0800 Subject: [PATCH] refactor: prune admin config compat aliases (#3688) --- docs/architecture/crate-boundaries.md | 3 ++ docs/architecture/migration-progress.md | 46 +++++++++++++++---- .../admin/handlers/audit_runtime_config.rs | 7 +-- rustfs/src/admin/handlers/config_admin.rs | 39 ++++++++-------- rustfs/src/admin/handlers/kms_dynamic.rs | 6 +-- rustfs/src/admin/handlers/oidc.rs | 6 +-- rustfs/src/admin/handlers/site_replication.rs | 8 ++-- rustfs/src/admin/router.rs | 4 +- rustfs/src/admin/service/config.rs | 14 +++--- rustfs/src/admin/service/site_replication.rs | 6 +-- rustfs/src/admin/storage_compat.rs | 7 ++- scripts/check_architecture_migration_rules.sh | 11 +++++ 12 files changed, 101 insertions(+), 56 deletions(-) diff --git a/docs/architecture/crate-boundaries.md b/docs/architecture/crate-boundaries.md index 9c097f013..268c92274 100644 --- a/docs/architecture/crate-boundaries.md +++ b/docs/architecture/crate-boundaries.md @@ -149,6 +149,9 @@ boundaries that still need module-local owner cleanup. Root runtime storage config initialization and disk endpoint contracts must also stay explicit aliases. The root compatibility boundary must not restore `com`, bare `init`, or grouped `endpoint::Endpoint` passthroughs. +RustFS admin `storage_compat.rs` must expose config IO and default +initialization through explicit aliases. The admin compatibility boundary must +not restore broad `com` or bare `init` passthroughs. ECStore ClusterControlPlane read models must stay owned by the crate-private `cluster` module. Public access goes through `rustfs_ecstore::api::cluster` so diff --git a/docs/architecture/migration-progress.md b/docs/architecture/migration-progress.md index 9ffa6d6c6..67f551e9f 100644 --- a/docs/architecture/migration-progress.md +++ b/docs/architecture/migration-progress.md @@ -5,17 +5,17 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block ## Current Context - Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660) -- Branch: `overtrue/arch-root-runtime-compat-aliases` -- Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079`. -- Stacked on: API-079 root runtime bucket compatibility pruning. +- Branch: `overtrue/arch-admin-config-compat-aliases` +- Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079/API-080`. +- Stacked on: API-080 root runtime compatibility alias pruning. - PR type for this branch: `pure-move` - Runtime behavior changes: none. -- Rust code changes: prune root config read/write, config initialization, and - disk endpoint compatibility passthroughs into explicit aliases for startup - and runtime consumers. -- CI/script changes: guard against restoring broad root config and disk endpoint +- Rust code changes: prune admin config read/write/delete, server-config read, + server-config save, and config-default initialization passthroughs into + explicit aliases for admin handlers and services. +- CI/script changes: guard against restoring broad admin config compatibility module passthroughs. -- Docs changes: record the API-080 root runtime compatibility alias boundary. +- Docs changes: record the API-081 admin config compatibility alias boundary. ## Phase 0 Tasks @@ -142,6 +142,21 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block readiness marking, and all app/admin/storage compatibility paths. - Verification: RustFS compile coverage, formatting, diff hygiene, risk scan, architecture guard, pre-commit quality gate, and three-expert review. +- [x] `API-081` Prune admin config compatibility aliases. + - Completed slice: replace admin config `com` and `init` passthroughs with + explicit aliases for config object read/write/delete, server-config + read/write, storage-class subsystem access, and config-default + initialization. + - Acceptance: admin config handlers, dynamic KMS/OIDC/audit handlers, site + replication state, router notification reads, and dynamic config reload + paths use direct admin compatibility aliases while preserving their + existing storage keys and config defaults. + - Must preserve: admin auth/authorization behavior, config history object + names, KMS/OIDC/audit runtime persistence, site-replication state + persistence, storage-class subsystem semantics, and admin route contracts. + - Verification: RustFS compile coverage, admin focused compile coverage, + formatting, diff hygiene, risk scan, architecture guard, pre-commit quality + gate, and three-expert review. - [x] `G-012` Inventory placement and repair invariants. - Acceptance: [`placement-repair-invariants.md`](placement-repair-invariants.md) records @@ -3175,14 +3190,25 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block | Expert | Status | Notes | |---|---|---| -| Quality/architecture | passed | API-080 narrows root runtime config and disk endpoint compatibility to explicit aliases without adding new ECStore ownership cycles. | -| Migration preservation | passed | Startup config initialization, module switch persistence, endpoint handling, local disk/lock setup, readiness, and app/admin/storage compatibility paths remain preserved. | +| Quality/architecture | passed | API-081 narrows admin config compatibility to explicit aliases without adding new ECStore ownership cycles. | +| Migration preservation | passed | Admin config history, dynamic KMS/OIDC/audit config, site-replication state, router notification reads, storage-class defaults, and route contracts remain preserved. | | Testing/verification | passed | RustFS compile coverage, migration guard, formatting, diff hygiene, added-line risk scan, full pre-commit, and three-expert review passed. | ## Verification Notes Passed before push: +- Issue #660 API-081 current slice: + - `cargo check -p rustfs --lib`: passed. + - `cargo fmt --all --check`: passed. + - `git diff --check`: passed. + - `bash -n scripts/check_architecture_migration_rules.sh`: passed. + - `./scripts/check_architecture_migration_rules.sh`: passed. + - Admin compatibility residual scan for broad `com`, bare `init`, and old + config IO call paths: passed. + - Rust added-line risk scan on changed Rust files and guard script: passed. + - `make pre-commit`: passed. + - Issue #660 API-080 current slice: - `cargo check -p rustfs --lib`: passed. - `cargo fmt --all --check`: passed. diff --git a/rustfs/src/admin/handlers/audit_runtime_config.rs b/rustfs/src/admin/handlers/audit_runtime_config.rs index c7df1352e..1e913d42d 100644 --- a/rustfs/src/admin/handlers/audit_runtime_config.rs +++ b/rustfs/src/admin/handlers/audit_runtime_config.rs @@ -13,6 +13,7 @@ // limitations under the License. use crate::admin::handlers::target_descriptor::AdminTargetSpec; +use crate::admin::storage_compat::{read_admin_config_without_migrate, save_admin_server_config}; use crate::app::context::resolve_object_store_handle; use rustfs_audit::{audit_system, start_audit_system as start_global_audit_system, system::AuditSystemState}; use rustfs_config::DEFAULT_DELIMITER; @@ -24,7 +25,7 @@ pub(crate) async fn load_server_config_from_store() -> S3Result { return Ok(Config::new()); }; - crate::admin::storage_compat::com::read_config_without_migrate(store) + read_admin_config_without_migrate(store) .await .map_err(|e| s3_error!(InternalError, "failed to read server config: {}", e)) } @@ -82,7 +83,7 @@ where return Err(s3_error!(InternalError, "server storage not initialized")); }; - let mut config = crate::admin::storage_compat::com::read_config_without_migrate(store.clone()) + let mut config = read_admin_config_without_migrate(store.clone()) .await .map_err(|e| s3_error!(InternalError, "failed to read server config: {}", e))?; @@ -90,7 +91,7 @@ where return Ok(()); } - crate::admin::storage_compat::com::save_server_config(store, &config) + save_admin_server_config(store, &config) .await .map_err(|e| s3_error!(InternalError, "failed to save audit config: {}", e))?; diff --git a/rustfs/src/admin/handlers/config_admin.rs b/rustfs/src/admin/handlers/config_admin.rs index 9d1053cd8..47b380bc3 100644 --- a/rustfs/src/admin/handlers/config_admin.rs +++ b/rustfs/src/admin/handlers/config_admin.rs @@ -18,12 +18,11 @@ use crate::admin::service::config::{ apply_dynamic_config_for_subsystem, is_dynamic_config_subsystem, signal_config_snapshot_reload, signal_dynamic_config_reload, validate_server_config, }; -use crate::admin::storage_compat::RUSTFS_META_BUCKET; -use crate::admin::storage_compat::com::STORAGE_CLASS_SUB_SYS; -use crate::admin::storage_compat::com::{ - delete_config, read_config, read_config_without_migrate, save_config, save_server_config, -}; use crate::admin::storage_compat::storageclass::{INLINE_BLOCK_ENV, OPTIMIZE_ENV, RRS_ENV, STANDARD_ENV}; +use crate::admin::storage_compat::{ + RUSTFS_META_BUCKET, STORAGE_CLASS_SUB_SYS, delete_admin_config, read_admin_config, read_admin_config_without_migrate, + save_admin_config, save_admin_server_config, +}; use crate::admin::utils::{encode_compatible_admin_payload, is_compat_admin_request, read_compatible_admin_body}; use crate::app::context::resolve_object_store_handle; use crate::auth::{check_key_valid, get_session_token}; @@ -717,7 +716,7 @@ fn object_store() -> S3Result S3Result { let store = object_store()?; - read_config_without_migrate(store) + read_admin_config_without_migrate(store) .await .map_err(ApiError::from) .map_err(Into::into) @@ -733,7 +732,7 @@ async fn load_active_server_config() -> S3Result { async fn save_server_config_to_store(config: &ServerConfig) -> S3Result<()> { let store = object_store()?; - save_server_config(store, config) + save_admin_server_config(store, config) .await .map_err(ApiError::from) .map_err(Into::into) @@ -756,7 +755,7 @@ fn config_update_sub_system(directives: &[ConfigDirective]) -> S3Result S3Result<()> { if DEFAULT_KVS.get().is_none() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); } let Some(defaults) = DEFAULT_KVS.get() else { return Err(s3_error!(InternalError, "config defaults are not initialized")); @@ -804,7 +803,7 @@ fn trim_history_entries(mut entries: Vec, count: Option S3Result { let restore_id = Uuid::new_v4().to_string(); let store = object_store()?; - save_config(store, &history_object_name(&restore_id), data.to_vec()) + save_admin_config(store, &history_object_name(&restore_id), data.to_vec()) .await .map_err(ApiError::from) .map_err(S3Error::from)?; @@ -813,7 +812,7 @@ async fn save_server_config_history(data: &[u8]) -> S3Result { async fn read_server_config_history(restore_id: &str) -> S3Result> { let store = object_store()?; - read_config(store, &history_object_name(restore_id)) + read_admin_config(store, &history_object_name(restore_id)) .await .map_err(ApiError::from) .map_err(Into::into) @@ -821,7 +820,7 @@ async fn read_server_config_history(restore_id: &str) -> S3Result> { async fn delete_server_config_history(restore_id: &str) -> S3Result<()> { let store = object_store()?; - delete_config(store, &history_object_name(restore_id)) + delete_admin_config(store, &history_object_name(restore_id)) .await .map_err(ApiError::from) .map_err(Into::into) @@ -861,7 +860,7 @@ async fn list_server_config_history(with_data: bool, count: Option) -> S3 let data = if with_data { Some( String::from_utf8( - read_config(store.clone(), &object.name) + read_admin_config(store.clone(), &object.name) .await .map_err(ApiError::from) .map_err(S3Error::from)?, @@ -1410,7 +1409,7 @@ fn env_help_key(sub_system: &str, key: &str) -> String { fn default_help_postfix(sub_system: &str, key: &str) -> String { if DEFAULT_KVS.get().is_none() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); } DEFAULT_KVS @@ -1897,7 +1896,7 @@ mod tests { #[test] fn full_config_export_can_be_reapplied() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); let mut original = ServerConfig::new(); apply_set_directives( &mut original, @@ -1944,7 +1943,7 @@ identity_openid config_url="https://issuer.example" client_id="console""#, #[test] fn build_help_response_appends_default_value_postfix() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); let response = build_help_response(Some("identity_openid"), Some("scopes"), false).expect("help response"); assert_eq!(response.keys_help.len(), 2); @@ -2057,7 +2056,7 @@ identity_openid config_url="https://issuer.example" client_id="console""#, #[test] fn render_selected_config_includes_env_override_lines() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); temp_env::with_vars( [ ("RUSTFS_NOTIFY_WEBHOOK_ENDPOINT_PRIMARY", Some("http://env.example")), @@ -2093,7 +2092,7 @@ identity_openid config_url="https://issuer.example" client_id="console""#, #[test] fn render_selected_config_lists_env_only_targets() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); temp_env::with_vars([("RUSTFS_NOTIFY_WEBHOOK_ENDPOINT_PRIMARY", Some("http://env.example"))], || { let config = ServerConfig::new(); let rendered = String::from_utf8( @@ -2116,7 +2115,7 @@ identity_openid config_url="https://issuer.example" client_id="console""#, #[test] fn render_selected_config_supports_specific_env_only_target_queries() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); temp_env::with_vars([("RUSTFS_NOTIFY_WEBHOOK_ENDPOINT_PRIMARY", Some("http://env.example"))], || { let config = ServerConfig::new(); let rendered = String::from_utf8( @@ -2139,7 +2138,7 @@ identity_openid config_url="https://issuer.example" client_id="console""#, #[test] fn render_selected_config_orders_default_before_named_targets() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); temp_env::with_vars([("RUSTFS_NOTIFY_WEBHOOK_ENDPOINT_ALPHA", Some("http://alpha.example"))], || { let mut config = ServerConfig::new(); apply_set_directives( @@ -2320,7 +2319,7 @@ identity_openid client_id="existing-client""#, #[test] fn storage_class_get_target_none_matches_full_export() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); let mut config = ServerConfig::new(); apply_set_directives( &mut config, diff --git a/rustfs/src/admin/handlers/kms_dynamic.rs b/rustfs/src/admin/handlers/kms_dynamic.rs index 999a4bf50..ca829ddc5 100644 --- a/rustfs/src/admin/handlers/kms_dynamic.rs +++ b/rustfs/src/admin/handlers/kms_dynamic.rs @@ -16,7 +16,7 @@ use crate::admin::auth::validate_admin_request; use crate::admin::router::{AdminOperation, Operation, S3Router}; -use crate::admin::storage_compat::com::{read_config, save_config}; +use crate::admin::storage_compat::{read_admin_config, save_admin_config}; use crate::app::context::{resolve_kms_runtime_service_manager, resolve_object_store_handle}; use crate::auth::{check_key_valid, get_session_token}; use crate::server::{ADMIN_PREFIX, RemoteAddr}; @@ -109,7 +109,7 @@ async fn save_kms_config(config: &KmsConfig) -> Result<(), String> { let data = serde_json::to_vec(config).map_err(|e| format!("Failed to serialize KMS config: {e}"))?; - save_config(store, KMS_CONFIG_PATH, data) + save_admin_config(store, KMS_CONFIG_PATH, data) .await .map_err(|e| format!("Failed to save KMS config to storage: {e}"))?; @@ -139,7 +139,7 @@ pub async fn load_kms_config() -> Option { return None; }; - match read_config(store, KMS_CONFIG_PATH).await { + match read_admin_config(store, KMS_CONFIG_PATH).await { Ok(data) => match serde_json::from_slice::(&data) { Ok(config) => { info!( diff --git a/rustfs/src/admin/handlers/oidc.rs b/rustfs/src/admin/handlers/oidc.rs index 79668fdbb..33d1b07c9 100644 --- a/rustfs/src/admin/handlers/oidc.rs +++ b/rustfs/src/admin/handlers/oidc.rs @@ -15,7 +15,7 @@ use super::sts::create_oidc_sts_credentials; use crate::admin::auth::validate_admin_request; use crate::admin::router::{AdminOperation, Operation, S3Router}; -use crate::admin::storage_compat::com::{read_config_without_migrate, save_server_config}; +use crate::admin::storage_compat::{read_admin_config_without_migrate, save_admin_server_config}; use crate::app::context::resolve_object_store_handle; use crate::auth::{check_key_valid, get_session_token}; use crate::server::{ADMIN_PREFIX, MINIO_ADMIN_PREFIX, RemoteAddr}; @@ -797,7 +797,7 @@ async fn load_server_config_from_store() -> S3Result { return Err(s3_error!(InternalError, "storage layer not initialized")); }; - read_config_without_migrate(store) + read_admin_config_without_migrate(store) .await .map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("failed to load server config: {e}"))) } @@ -807,7 +807,7 @@ async fn save_server_config_to_store(config: &ServerConfig) -> S3Result<()> { return Err(s3_error!(InternalError, "storage layer not initialized")); }; - save_server_config(store, config) + save_admin_server_config(store, config) .await .map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("failed to save server config: {e}"))) } diff --git a/rustfs/src/admin/handlers/site_replication.rs b/rustfs/src/admin/handlers/site_replication.rs index e008c9aae..adab64335 100644 --- a/rustfs/src/admin/handlers/site_replication.rs +++ b/rustfs/src/admin/handlers/site_replication.rs @@ -20,7 +20,6 @@ use crate::admin::site_replication_identity::{ }; use crate::admin::storage_compat::Error as StorageError; use crate::admin::storage_compat::bucket_target_sys::BucketTargetSys; -use crate::admin::storage_compat::com::{delete_config, read_config, save_config}; use crate::admin::storage_compat::metadata::{ BUCKET_CORS_CONFIG, BUCKET_LIFECYCLE_CONFIG, BUCKET_POLICY_CONFIG, BUCKET_QUOTA_CONFIG_FILE, BUCKET_REPLICATION_CONFIG, BUCKET_SSECONFIG, BUCKET_TAGGING_CONFIG, BUCKET_TARGETS_FILE, BUCKET_VERSIONING_CONFIG, OBJECT_LOCK_CONFIG, @@ -31,6 +30,7 @@ use crate::admin::storage_compat::replication::{ReplicationConfigurationExt, Res use crate::admin::storage_compat::target::{ARN, BucketTarget, BucketTargetType, BucketTargets, Credentials}; use crate::admin::storage_compat::utils::{deserialize, serialize}; use crate::admin::storage_compat::versioning::VersioningApi; +use crate::admin::storage_compat::{delete_admin_config, read_admin_config, save_admin_config}; use crate::admin::storage_compat::{get_global_deployment_id, get_global_endpoints_opt, get_global_region, global_rustfs_port}; use crate::admin::utils::{encode_compatible_admin_payload, read_compatible_admin_body}; use crate::app::context::resolve_object_store_handle; @@ -541,7 +541,7 @@ async fn load_site_replication_state() -> S3Result { return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string())); }; - match read_config(store, SITE_REPLICATION_STATE_PATH).await { + match read_admin_config(store, SITE_REPLICATION_STATE_PATH).await { Ok(data) => { let mut state: SiteReplicationState = serde_json::from_slice(&data) .map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("invalid site replication state: {e}")))?; @@ -566,7 +566,7 @@ async fn save_site_replication_state(state: &SiteReplicationState) -> S3Result<( let data = serde_json::to_vec(&normalized) .map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("serialize state failed: {e}")))?; - save_config(store, SITE_REPLICATION_STATE_PATH, data) + save_admin_config(store, SITE_REPLICATION_STATE_PATH, data) .await .map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("save state failed: {e}")))?; Ok(()) @@ -577,7 +577,7 @@ async fn clear_site_replication_state() -> S3Result<()> { return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string())); }; - match delete_config(store, SITE_REPLICATION_STATE_PATH).await { + match delete_admin_config(store, SITE_REPLICATION_STATE_PATH).await { Ok(()) | Err(StorageError::ConfigNotFound) => Ok(()), Err(err) => Err(S3Error::with_message(S3ErrorCode::InternalError, format!("clear state failed: {err}"))), } diff --git a/rustfs/src/admin/router.rs b/rustfs/src/admin/router.rs index c8ed5a9de..631987a7c 100644 --- a/rustfs/src/admin/router.rs +++ b/rustfs/src/admin/router.rs @@ -20,10 +20,10 @@ use crate::admin::storage_compat::bandwidth::monitor::BandwidthDetails; use crate::admin::storage_compat::bucket_target_sys::{ BucketTargetSys, PutObjectOptions, RemoveObjectOptions, S3ClientError, TargetClient, }; -use crate::admin::storage_compat::com::read_config_without_migrate; use crate::admin::storage_compat::get_global_notification_sys; use crate::admin::storage_compat::metadata::BUCKET_TARGETS_FILE; use crate::admin::storage_compat::metadata_sys; +use crate::admin::storage_compat::read_admin_config_without_migrate; use crate::admin::storage_compat::replication::{ BucketReplicationResyncStatus, BucketStats, GLOBAL_REPLICATION_STATS, ObjectOpts, ReplicationConfigurationExt, ResyncOpts, get_global_replication_pool, @@ -636,7 +636,7 @@ async fn load_current_server_config() -> S3Result { } if let Some(store) = resolve_object_store_handle() { - match read_config_without_migrate(store).await { + match read_admin_config_without_migrate(store).await { Ok(config) => return Ok(config), Err(err) => { warn!( diff --git a/rustfs/src/admin/service/config.rs b/rustfs/src/admin/service/config.rs index 64d380029..d259347d4 100644 --- a/rustfs/src/admin/service/config.rs +++ b/rustfs/src/admin/service/config.rs @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::admin::storage_compat::com::{STORAGE_CLASS_SUB_SYS, read_config_without_migrate}; use crate::admin::storage_compat::get_global_notification_sys; use crate::admin::storage_compat::set_global_storage_class; use crate::admin::storage_compat::storageclass; +use crate::admin::storage_compat::{STORAGE_CLASS_SUB_SYS, read_admin_config_without_migrate}; use crate::app::context::resolve_object_store_handle; use rustfs_audit::reload_audit_config; use rustfs_config::audit::{AUDIT_MQTT_SUB_SYS, AUDIT_REDIS_DEFAULT_CHANNEL, AUDIT_WEBHOOK_SUB_SYS}; @@ -301,7 +301,7 @@ pub async fn reload_dynamic_config_runtime_state(sub_system: &str) -> S3Result<( return Err(internal_error("storage layer not initialized")); }; - let config = read_config_without_migrate(store).await.map_err(|err| { + let config = read_admin_config_without_migrate(store).await.map_err(|err| { warn!("peer reload_dynamic_config: failed to load server config for {sub_system}: {err}"); internal_error(format!("failed to load server config: {err}")) })?; @@ -317,7 +317,7 @@ pub async fn reload_runtime_config_snapshot() -> S3Result<()> { return Err(internal_error("storage layer not initialized")); }; - let config = read_config_without_migrate(store).await.map_err(|err| { + let config = read_admin_config_without_migrate(store).await.map_err(|err| { warn!("peer reload_runtime_config_snapshot: failed to load server config: {err}"); internal_error(format!("failed to load server config: {err}")) })?; @@ -427,7 +427,7 @@ mod tests { #[test] fn validate_notify_subsystem_config_rejects_invalid_webhook_endpoint() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); let mut config = ServerConfig::new(); let targets = config.0.get_mut(NOTIFY_WEBHOOK_SUB_SYS).expect("notify webhook defaults"); let kvs = targets.get_mut(DEFAULT_DELIMITER).expect("default target"); @@ -441,7 +441,7 @@ mod tests { #[test] fn validate_audit_subsystem_config_rejects_relative_queue_dir() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); let mut config = ServerConfig::new(); let targets = config.0.get_mut(AUDIT_MQTT_SUB_SYS).expect("audit mqtt defaults"); let kvs = targets.get_mut(DEFAULT_DELIMITER).expect("default target"); @@ -456,7 +456,7 @@ mod tests { #[test] fn validate_identity_openid_config_rejects_missing_openid_scope() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); let mut config = ServerConfig::new(); let targets = config.0.get_mut(IDENTITY_OPENID_SUB_SYS).expect("openid defaults"); let kvs = targets.get_mut(DEFAULT_DELIMITER).expect("default target"); @@ -473,7 +473,7 @@ mod tests { #[test] fn validate_identity_openid_config_rejects_invalid_named_provider_id() { - crate::admin::storage_compat::init(); + crate::admin::storage_compat::init_admin_config_defaults(); let mut config = ServerConfig::new(); let targets = config.0.get_mut(IDENTITY_OPENID_SUB_SYS).expect("openid defaults"); let default_kvs = targets.get(DEFAULT_DELIMITER).cloned().expect("default target"); diff --git a/rustfs/src/admin/service/site_replication.rs b/rustfs/src/admin/service/site_replication.rs index 9fb3fa9ff..ddad748aa 100644 --- a/rustfs/src/admin/service/site_replication.rs +++ b/rustfs/src/admin/service/site_replication.rs @@ -14,7 +14,7 @@ use crate::admin::site_replication_identity::{deployment_id_for_endpoint, normalize_peer_map_by_identity_with}; use crate::admin::storage_compat::Error as StorageError; -use crate::admin::storage_compat::com::{read_config, save_config}; +use crate::admin::storage_compat::{read_admin_config, save_admin_config}; use crate::app::context::resolve_object_store_handle; use rustfs_madmin::PeerInfo; use s3s::{S3Error, S3ErrorCode, S3Result}; @@ -95,12 +95,12 @@ pub async fn reload_site_replication_runtime_state() -> S3Result<()> { return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string())); }; - match read_config(store.clone(), SITE_REPLICATION_STATE_PATH).await { + match read_admin_config(store.clone(), SITE_REPLICATION_STATE_PATH).await { Ok(data) => { if let Some(normalized) = normalize_site_replication_state_json(&data).map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, e))? { - save_config(store, SITE_REPLICATION_STATE_PATH, normalized) + save_admin_config(store, SITE_REPLICATION_STATE_PATH, normalized) .await .map_err(|e| { S3Error::with_message(S3ErrorCode::InternalError, format!("normalize site replication state failed: {e}")) diff --git a/rustfs/src/admin/storage_compat.rs b/rustfs/src/admin/storage_compat.rs index d8ea691a8..84790f6a6 100644 --- a/rustfs/src/admin/storage_compat.rs +++ b/rustfs/src/admin/storage_compat.rs @@ -19,7 +19,12 @@ pub(crate) use rustfs_ecstore::api::bucket::{ }; pub(crate) use rustfs_ecstore::api::capacity::is_reserved_or_invalid_bucket; pub(crate) use rustfs_ecstore::api::client::admin_handler_utils::AdminError; -pub(crate) use rustfs_ecstore::api::config::{com, init, set_global_storage_class, storageclass}; +pub(crate) use rustfs_ecstore::api::config::com::{ + STORAGE_CLASS_SUB_SYS, delete_config as delete_admin_config, read_config as read_admin_config, + read_config_without_migrate as read_admin_config_without_migrate, save_config as save_admin_config, + save_server_config as save_admin_server_config, +}; +pub(crate) use rustfs_ecstore::api::config::{init as init_admin_config_defaults, set_global_storage_class, storageclass}; pub(crate) use rustfs_ecstore::api::data_usage::load_data_usage_from_backend; pub(crate) use rustfs_ecstore::api::disk::RUSTFS_META_BUCKET; #[cfg(test)] diff --git a/scripts/check_architecture_migration_rules.sh b/scripts/check_architecture_migration_rules.sh index c497d8724..8f4a536b1 100755 --- a/scripts/check_architecture_migration_rules.sh +++ b/scripts/check_architecture_migration_rules.sh @@ -80,6 +80,7 @@ RUSTFS_RUNTIME_SCALAR_STORAGE_COMPAT_HITS_FILE="${TMP_DIR}/rustfs_runtime_scalar RUSTFS_RUNTIME_SECONDARY_STORAGE_COMPAT_HITS_FILE="${TMP_DIR}/rustfs_runtime_secondary_storage_compat_hits.txt" RUSTFS_ROOT_BUCKET_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/rustfs_root_bucket_storage_compat_module_hits.txt" RUSTFS_ROOT_RUNTIME_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/rustfs_root_runtime_storage_compat_module_hits.txt" +RUSTFS_ADMIN_CONFIG_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/rustfs_admin_config_storage_compat_module_hits.txt" PRODUCTION_UNUSED_COMPAT_ALLOW_HITS_FILE="${TMP_DIR}/production_unused_compat_allow_hits.txt" BROAD_STORE_API_COMPAT_REEXPORT_HITS_FILE="${TMP_DIR}/broad_store_api_compat_reexport_hits.txt" NESTED_STORE_API_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/nested_store_api_compat_module_hits.txt" @@ -787,6 +788,16 @@ if [[ -s "$RUSTFS_ROOT_RUNTIME_STORAGE_COMPAT_MODULE_HITS_FILE" ]]; then report_failure "RustFS root storage compatibility must expose config init and disk endpoint contracts as explicit aliases: $(paste -sd '; ' "$RUSTFS_ROOT_RUNTIME_STORAGE_COMPAT_MODULE_HITS_FILE")" fi +( + cd "$ROOT_DIR" + rg -n --no-heading 'pub\(crate\)\s+use rustfs_ecstore::api::config::\{[^}]*\bcom\b[^}]*\}\s*;|pub\(crate\)\s+use rustfs_ecstore::api::config::\{[^}]*\binit\s*(?:,|})[^}]*\}\s*;' \ + rustfs/src/admin/storage_compat.rs || true +) >"$RUSTFS_ADMIN_CONFIG_STORAGE_COMPAT_MODULE_HITS_FILE" + +if [[ -s "$RUSTFS_ADMIN_CONFIG_STORAGE_COMPAT_MODULE_HITS_FILE" ]]; then + report_failure "RustFS admin storage compatibility must expose config IO and default initialization as explicit aliases: $(paste -sd '; ' "$RUSTFS_ADMIN_CONFIG_STORAGE_COMPAT_MODULE_HITS_FILE")" +fi + ( cd "$ROOT_DIR" rg -n --no-heading '#!\[allow\(unused_imports\)\]' \