refactor: prune admin config compat aliases (#3688)

This commit is contained in:
安正超
2026-06-21 15:21:25 +08:00
committed by GitHub
parent f4f303a773
commit 6e42afcea5
12 changed files with 101 additions and 56 deletions
+3
View File
@@ -149,6 +149,9 @@ boundaries that still need module-local owner cleanup.
Root runtime storage config initialization and disk endpoint contracts must also Root runtime storage config initialization and disk endpoint contracts must also
stay explicit aliases. The root compatibility boundary must not restore `com`, stay explicit aliases. The root compatibility boundary must not restore `com`,
bare `init`, or grouped `endpoint::Endpoint` passthroughs. 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 ECStore ClusterControlPlane read models must stay owned by the crate-private
`cluster` module. Public access goes through `rustfs_ecstore::api::cluster` so `cluster` module. Public access goes through `rustfs_ecstore::api::cluster` so
+36 -10
View File
@@ -5,17 +5,17 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
## Current Context ## Current Context
- Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660) - Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660)
- Branch: `overtrue/arch-root-runtime-compat-aliases` - Branch: `overtrue/arch-admin-config-compat-aliases`
- Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079`. - Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079/API-080`.
- Stacked on: API-079 root runtime bucket compatibility pruning. - Stacked on: API-080 root runtime compatibility alias pruning.
- PR type for this branch: `pure-move` - PR type for this branch: `pure-move`
- Runtime behavior changes: none. - Runtime behavior changes: none.
- Rust code changes: prune root config read/write, config initialization, and - Rust code changes: prune admin config read/write/delete, server-config read,
disk endpoint compatibility passthroughs into explicit aliases for startup server-config save, and config-default initialization passthroughs into
and runtime consumers. explicit aliases for admin handlers and services.
- CI/script changes: guard against restoring broad root config and disk endpoint - CI/script changes: guard against restoring broad admin config compatibility
module passthroughs. 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 ## 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. readiness marking, and all app/admin/storage compatibility paths.
- Verification: RustFS compile coverage, formatting, diff hygiene, risk - Verification: RustFS compile coverage, formatting, diff hygiene, risk
scan, architecture guard, pre-commit quality gate, and three-expert review. 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. - [x] `G-012` Inventory placement and repair invariants.
- Acceptance: - Acceptance:
[`placement-repair-invariants.md`](placement-repair-invariants.md) records [`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 | | 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. | | Quality/architecture | passed | API-081 narrows admin config 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. | | 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. | | 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 ## Verification Notes
Passed before push: 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: - Issue #660 API-080 current slice:
- `cargo check -p rustfs --lib`: passed. - `cargo check -p rustfs --lib`: passed.
- `cargo fmt --all --check`: passed. - `cargo fmt --all --check`: passed.
@@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
use crate::admin::handlers::target_descriptor::AdminTargetSpec; 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 crate::app::context::resolve_object_store_handle;
use rustfs_audit::{audit_system, start_audit_system as start_global_audit_system, system::AuditSystemState}; use rustfs_audit::{audit_system, start_audit_system as start_global_audit_system, system::AuditSystemState};
use rustfs_config::DEFAULT_DELIMITER; use rustfs_config::DEFAULT_DELIMITER;
@@ -24,7 +25,7 @@ pub(crate) async fn load_server_config_from_store() -> S3Result<Config> {
return Ok(Config::new()); return Ok(Config::new());
}; };
crate::admin::storage_compat::com::read_config_without_migrate(store) read_admin_config_without_migrate(store)
.await .await
.map_err(|e| s3_error!(InternalError, "failed to read server config: {}", e)) .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")); 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 .await
.map_err(|e| s3_error!(InternalError, "failed to read server config: {}", e))?; .map_err(|e| s3_error!(InternalError, "failed to read server config: {}", e))?;
@@ -90,7 +91,7 @@ where
return Ok(()); return Ok(());
} }
crate::admin::storage_compat::com::save_server_config(store, &config) save_admin_server_config(store, &config)
.await .await
.map_err(|e| s3_error!(InternalError, "failed to save audit config: {}", e))?; .map_err(|e| s3_error!(InternalError, "failed to save audit config: {}", e))?;
+19 -20
View File
@@ -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, apply_dynamic_config_for_subsystem, is_dynamic_config_subsystem, signal_config_snapshot_reload, signal_dynamic_config_reload,
validate_server_config, 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::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::admin::utils::{encode_compatible_admin_payload, is_compat_admin_request, read_compatible_admin_body};
use crate::app::context::resolve_object_store_handle; use crate::app::context::resolve_object_store_handle;
use crate::auth::{check_key_valid, get_session_token}; use crate::auth::{check_key_valid, get_session_token};
@@ -717,7 +716,7 @@ fn object_store() -> S3Result<std::sync::Arc<crate::admin::storage_compat::ECSto
async fn load_server_config_from_store() -> S3Result<ServerConfig> { async fn load_server_config_from_store() -> S3Result<ServerConfig> {
let store = object_store()?; let store = object_store()?;
read_config_without_migrate(store) read_admin_config_without_migrate(store)
.await .await
.map_err(ApiError::from) .map_err(ApiError::from)
.map_err(Into::into) .map_err(Into::into)
@@ -733,7 +732,7 @@ async fn load_active_server_config() -> S3Result<ServerConfig> {
async fn save_server_config_to_store(config: &ServerConfig) -> S3Result<()> { async fn save_server_config_to_store(config: &ServerConfig) -> S3Result<()> {
let store = object_store()?; let store = object_store()?;
save_server_config(store, config) save_admin_server_config(store, config)
.await .await
.map_err(ApiError::from) .map_err(ApiError::from)
.map_err(Into::into) .map_err(Into::into)
@@ -756,7 +755,7 @@ fn config_update_sub_system(directives: &[ConfigDirective]) -> S3Result<Option<&
fn validate_config_directives(directives: &[ConfigDirective]) -> S3Result<()> { fn validate_config_directives(directives: &[ConfigDirective]) -> S3Result<()> {
if DEFAULT_KVS.get().is_none() { 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 { let Some(defaults) = DEFAULT_KVS.get() else {
return Err(s3_error!(InternalError, "config defaults are not initialized")); return Err(s3_error!(InternalError, "config defaults are not initialized"));
@@ -804,7 +803,7 @@ fn trim_history_entries(mut entries: Vec<ConfigHistoryEntry>, count: Option<usiz
async fn save_server_config_history(data: &[u8]) -> S3Result<String> { async fn save_server_config_history(data: &[u8]) -> S3Result<String> {
let restore_id = Uuid::new_v4().to_string(); let restore_id = Uuid::new_v4().to_string();
let store = object_store()?; 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 .await
.map_err(ApiError::from) .map_err(ApiError::from)
.map_err(S3Error::from)?; .map_err(S3Error::from)?;
@@ -813,7 +812,7 @@ async fn save_server_config_history(data: &[u8]) -> S3Result<String> {
async fn read_server_config_history(restore_id: &str) -> S3Result<Vec<u8>> { async fn read_server_config_history(restore_id: &str) -> S3Result<Vec<u8>> {
let store = object_store()?; let store = object_store()?;
read_config(store, &history_object_name(restore_id)) read_admin_config(store, &history_object_name(restore_id))
.await .await
.map_err(ApiError::from) .map_err(ApiError::from)
.map_err(Into::into) .map_err(Into::into)
@@ -821,7 +820,7 @@ async fn read_server_config_history(restore_id: &str) -> S3Result<Vec<u8>> {
async fn delete_server_config_history(restore_id: &str) -> S3Result<()> { async fn delete_server_config_history(restore_id: &str) -> S3Result<()> {
let store = object_store()?; let store = object_store()?;
delete_config(store, &history_object_name(restore_id)) delete_admin_config(store, &history_object_name(restore_id))
.await .await
.map_err(ApiError::from) .map_err(ApiError::from)
.map_err(Into::into) .map_err(Into::into)
@@ -861,7 +860,7 @@ async fn list_server_config_history(with_data: bool, count: Option<usize>) -> S3
let data = if with_data { let data = if with_data {
Some( Some(
String::from_utf8( String::from_utf8(
read_config(store.clone(), &object.name) read_admin_config(store.clone(), &object.name)
.await .await
.map_err(ApiError::from) .map_err(ApiError::from)
.map_err(S3Error::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 { fn default_help_postfix(sub_system: &str, key: &str) -> String {
if DEFAULT_KVS.get().is_none() { if DEFAULT_KVS.get().is_none() {
crate::admin::storage_compat::init(); crate::admin::storage_compat::init_admin_config_defaults();
} }
DEFAULT_KVS DEFAULT_KVS
@@ -1897,7 +1896,7 @@ mod tests {
#[test] #[test]
fn full_config_export_can_be_reapplied() { 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(); let mut original = ServerConfig::new();
apply_set_directives( apply_set_directives(
&mut original, &mut original,
@@ -1944,7 +1943,7 @@ identity_openid config_url="https://issuer.example" client_id="console""#,
#[test] #[test]
fn build_help_response_appends_default_value_postfix() { 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"); let response = build_help_response(Some("identity_openid"), Some("scopes"), false).expect("help response");
assert_eq!(response.keys_help.len(), 2); assert_eq!(response.keys_help.len(), 2);
@@ -2057,7 +2056,7 @@ identity_openid config_url="https://issuer.example" client_id="console""#,
#[test] #[test]
fn render_selected_config_includes_env_override_lines() { 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( temp_env::with_vars(
[ [
("RUSTFS_NOTIFY_WEBHOOK_ENDPOINT_PRIMARY", Some("http://env.example")), ("RUSTFS_NOTIFY_WEBHOOK_ENDPOINT_PRIMARY", Some("http://env.example")),
@@ -2093,7 +2092,7 @@ identity_openid config_url="https://issuer.example" client_id="console""#,
#[test] #[test]
fn render_selected_config_lists_env_only_targets() { 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"))], || { temp_env::with_vars([("RUSTFS_NOTIFY_WEBHOOK_ENDPOINT_PRIMARY", Some("http://env.example"))], || {
let config = ServerConfig::new(); let config = ServerConfig::new();
let rendered = String::from_utf8( let rendered = String::from_utf8(
@@ -2116,7 +2115,7 @@ identity_openid config_url="https://issuer.example" client_id="console""#,
#[test] #[test]
fn render_selected_config_supports_specific_env_only_target_queries() { 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"))], || { temp_env::with_vars([("RUSTFS_NOTIFY_WEBHOOK_ENDPOINT_PRIMARY", Some("http://env.example"))], || {
let config = ServerConfig::new(); let config = ServerConfig::new();
let rendered = String::from_utf8( let rendered = String::from_utf8(
@@ -2139,7 +2138,7 @@ identity_openid config_url="https://issuer.example" client_id="console""#,
#[test] #[test]
fn render_selected_config_orders_default_before_named_targets() { 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"))], || { temp_env::with_vars([("RUSTFS_NOTIFY_WEBHOOK_ENDPOINT_ALPHA", Some("http://alpha.example"))], || {
let mut config = ServerConfig::new(); let mut config = ServerConfig::new();
apply_set_directives( apply_set_directives(
@@ -2320,7 +2319,7 @@ identity_openid client_id="existing-client""#,
#[test] #[test]
fn storage_class_get_target_none_matches_full_export() { 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(); let mut config = ServerConfig::new();
apply_set_directives( apply_set_directives(
&mut config, &mut config,
+3 -3
View File
@@ -16,7 +16,7 @@
use crate::admin::auth::validate_admin_request; use crate::admin::auth::validate_admin_request;
use crate::admin::router::{AdminOperation, Operation, S3Router}; 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::app::context::{resolve_kms_runtime_service_manager, resolve_object_store_handle};
use crate::auth::{check_key_valid, get_session_token}; use crate::auth::{check_key_valid, get_session_token};
use crate::server::{ADMIN_PREFIX, RemoteAddr}; 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}"))?; 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 .await
.map_err(|e| format!("Failed to save KMS config to storage: {e}"))?; .map_err(|e| format!("Failed to save KMS config to storage: {e}"))?;
@@ -139,7 +139,7 @@ pub async fn load_kms_config() -> Option<KmsConfig> {
return None; 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::<KmsConfig>(&data) { Ok(data) => match serde_json::from_slice::<KmsConfig>(&data) {
Ok(config) => { Ok(config) => {
info!( info!(
+3 -3
View File
@@ -15,7 +15,7 @@
use super::sts::create_oidc_sts_credentials; use super::sts::create_oidc_sts_credentials;
use crate::admin::auth::validate_admin_request; use crate::admin::auth::validate_admin_request;
use crate::admin::router::{AdminOperation, Operation, S3Router}; 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::app::context::resolve_object_store_handle;
use crate::auth::{check_key_valid, get_session_token}; use crate::auth::{check_key_valid, get_session_token};
use crate::server::{ADMIN_PREFIX, MINIO_ADMIN_PREFIX, RemoteAddr}; use crate::server::{ADMIN_PREFIX, MINIO_ADMIN_PREFIX, RemoteAddr};
@@ -797,7 +797,7 @@ async fn load_server_config_from_store() -> S3Result<ServerConfig> {
return Err(s3_error!(InternalError, "storage layer not initialized")); return Err(s3_error!(InternalError, "storage layer not initialized"));
}; };
read_config_without_migrate(store) read_admin_config_without_migrate(store)
.await .await
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("failed to load server config: {e}"))) .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")); return Err(s3_error!(InternalError, "storage layer not initialized"));
}; };
save_server_config(store, config) save_admin_server_config(store, config)
.await .await
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("failed to save server config: {e}"))) .map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("failed to save server config: {e}")))
} }
@@ -20,7 +20,6 @@ use crate::admin::site_replication_identity::{
}; };
use crate::admin::storage_compat::Error as StorageError; use crate::admin::storage_compat::Error as StorageError;
use crate::admin::storage_compat::bucket_target_sys::BucketTargetSys; 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::{ use crate::admin::storage_compat::metadata::{
BUCKET_CORS_CONFIG, BUCKET_LIFECYCLE_CONFIG, BUCKET_POLICY_CONFIG, BUCKET_QUOTA_CONFIG_FILE, BUCKET_REPLICATION_CONFIG, 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, 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::target::{ARN, BucketTarget, BucketTargetType, BucketTargets, Credentials};
use crate::admin::storage_compat::utils::{deserialize, serialize}; use crate::admin::storage_compat::utils::{deserialize, serialize};
use crate::admin::storage_compat::versioning::VersioningApi; 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::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::admin::utils::{encode_compatible_admin_payload, read_compatible_admin_body};
use crate::app::context::resolve_object_store_handle; use crate::app::context::resolve_object_store_handle;
@@ -541,7 +541,7 @@ async fn load_site_replication_state() -> S3Result<SiteReplicationState> {
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string())); 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) => { Ok(data) => {
let mut state: SiteReplicationState = serde_json::from_slice(&data) let mut state: SiteReplicationState = serde_json::from_slice(&data)
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("invalid site replication state: {e}")))?; .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) let data = serde_json::to_vec(&normalized)
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("serialize state failed: {e}")))?; .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 .await
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("save state failed: {e}")))?; .map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("save state failed: {e}")))?;
Ok(()) Ok(())
@@ -577,7 +577,7 @@ async fn clear_site_replication_state() -> S3Result<()> {
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string())); 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(()), Ok(()) | Err(StorageError::ConfigNotFound) => Ok(()),
Err(err) => Err(S3Error::with_message(S3ErrorCode::InternalError, format!("clear state failed: {err}"))), Err(err) => Err(S3Error::with_message(S3ErrorCode::InternalError, format!("clear state failed: {err}"))),
} }
+2 -2
View File
@@ -20,10 +20,10 @@ use crate::admin::storage_compat::bandwidth::monitor::BandwidthDetails;
use crate::admin::storage_compat::bucket_target_sys::{ use crate::admin::storage_compat::bucket_target_sys::{
BucketTargetSys, PutObjectOptions, RemoveObjectOptions, S3ClientError, TargetClient, 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::get_global_notification_sys;
use crate::admin::storage_compat::metadata::BUCKET_TARGETS_FILE; use crate::admin::storage_compat::metadata::BUCKET_TARGETS_FILE;
use crate::admin::storage_compat::metadata_sys; use crate::admin::storage_compat::metadata_sys;
use crate::admin::storage_compat::read_admin_config_without_migrate;
use crate::admin::storage_compat::replication::{ use crate::admin::storage_compat::replication::{
BucketReplicationResyncStatus, BucketStats, GLOBAL_REPLICATION_STATS, ObjectOpts, ReplicationConfigurationExt, ResyncOpts, BucketReplicationResyncStatus, BucketStats, GLOBAL_REPLICATION_STATS, ObjectOpts, ReplicationConfigurationExt, ResyncOpts,
get_global_replication_pool, get_global_replication_pool,
@@ -636,7 +636,7 @@ async fn load_current_server_config() -> S3Result<Config> {
} }
if let Some(store) = resolve_object_store_handle() { 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), Ok(config) => return Ok(config),
Err(err) => { Err(err) => {
warn!( warn!(
+7 -7
View File
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // 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::get_global_notification_sys;
use crate::admin::storage_compat::set_global_storage_class; use crate::admin::storage_compat::set_global_storage_class;
use crate::admin::storage_compat::storageclass; 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 crate::app::context::resolve_object_store_handle;
use rustfs_audit::reload_audit_config; use rustfs_audit::reload_audit_config;
use rustfs_config::audit::{AUDIT_MQTT_SUB_SYS, AUDIT_REDIS_DEFAULT_CHANNEL, AUDIT_WEBHOOK_SUB_SYS}; 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")); 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}"); warn!("peer reload_dynamic_config: failed to load server config for {sub_system}: {err}");
internal_error(format!("failed to load server config: {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")); 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}"); warn!("peer reload_runtime_config_snapshot: failed to load server config: {err}");
internal_error(format!("failed to load server config: {err}")) internal_error(format!("failed to load server config: {err}"))
})?; })?;
@@ -427,7 +427,7 @@ mod tests {
#[test] #[test]
fn validate_notify_subsystem_config_rejects_invalid_webhook_endpoint() { 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 mut config = ServerConfig::new();
let targets = config.0.get_mut(NOTIFY_WEBHOOK_SUB_SYS).expect("notify webhook defaults"); let targets = config.0.get_mut(NOTIFY_WEBHOOK_SUB_SYS).expect("notify webhook defaults");
let kvs = targets.get_mut(DEFAULT_DELIMITER).expect("default target"); let kvs = targets.get_mut(DEFAULT_DELIMITER).expect("default target");
@@ -441,7 +441,7 @@ mod tests {
#[test] #[test]
fn validate_audit_subsystem_config_rejects_relative_queue_dir() { 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 mut config = ServerConfig::new();
let targets = config.0.get_mut(AUDIT_MQTT_SUB_SYS).expect("audit mqtt defaults"); let targets = config.0.get_mut(AUDIT_MQTT_SUB_SYS).expect("audit mqtt defaults");
let kvs = targets.get_mut(DEFAULT_DELIMITER).expect("default target"); let kvs = targets.get_mut(DEFAULT_DELIMITER).expect("default target");
@@ -456,7 +456,7 @@ mod tests {
#[test] #[test]
fn validate_identity_openid_config_rejects_missing_openid_scope() { 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 mut config = ServerConfig::new();
let targets = config.0.get_mut(IDENTITY_OPENID_SUB_SYS).expect("openid defaults"); let targets = config.0.get_mut(IDENTITY_OPENID_SUB_SYS).expect("openid defaults");
let kvs = targets.get_mut(DEFAULT_DELIMITER).expect("default target"); let kvs = targets.get_mut(DEFAULT_DELIMITER).expect("default target");
@@ -473,7 +473,7 @@ mod tests {
#[test] #[test]
fn validate_identity_openid_config_rejects_invalid_named_provider_id() { 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 mut config = ServerConfig::new();
let targets = config.0.get_mut(IDENTITY_OPENID_SUB_SYS).expect("openid defaults"); let targets = config.0.get_mut(IDENTITY_OPENID_SUB_SYS).expect("openid defaults");
let default_kvs = targets.get(DEFAULT_DELIMITER).cloned().expect("default target"); let default_kvs = targets.get(DEFAULT_DELIMITER).cloned().expect("default target");
+3 -3
View File
@@ -14,7 +14,7 @@
use crate::admin::site_replication_identity::{deployment_id_for_endpoint, normalize_peer_map_by_identity_with}; 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::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 crate::app::context::resolve_object_store_handle;
use rustfs_madmin::PeerInfo; use rustfs_madmin::PeerInfo;
use s3s::{S3Error, S3ErrorCode, S3Result}; 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())); 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) => { Ok(data) => {
if let Some(normalized) = if let Some(normalized) =
normalize_site_replication_state_json(&data).map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, e))? 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 .await
.map_err(|e| { .map_err(|e| {
S3Error::with_message(S3ErrorCode::InternalError, format!("normalize site replication state failed: {e}")) S3Error::with_message(S3ErrorCode::InternalError, format!("normalize site replication state failed: {e}"))
+6 -1
View File
@@ -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::capacity::is_reserved_or_invalid_bucket;
pub(crate) use rustfs_ecstore::api::client::admin_handler_utils::AdminError; 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::data_usage::load_data_usage_from_backend;
pub(crate) use rustfs_ecstore::api::disk::RUSTFS_META_BUCKET; pub(crate) use rustfs_ecstore::api::disk::RUSTFS_META_BUCKET;
#[cfg(test)] #[cfg(test)]
@@ -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_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_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_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" 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" 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" 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")" 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 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" cd "$ROOT_DIR"
rg -n --no-heading '#!\[allow\(unused_imports\)\]' \ rg -n --no-heading '#!\[allow\(unused_imports\)\]' \