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
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
+36 -10
View File
@@ -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.
@@ -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<Config> {
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))?;
+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,
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<std::sync::Arc<crate::admin::storage_compat::ECSto
async fn load_server_config_from_store() -> S3Result<ServerConfig> {
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<ServerConfig> {
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<Option<&
fn validate_config_directives(directives: &[ConfigDirective]) -> 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<ConfigHistoryEntry>, count: Option<usiz
async fn save_server_config_history(data: &[u8]) -> S3Result<String> {
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<String> {
async fn read_server_config_history(restore_id: &str) -> S3Result<Vec<u8>> {
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<Vec<u8>> {
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<usize>) -> 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,
+3 -3
View File
@@ -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<KmsConfig> {
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(config) => {
info!(
+3 -3
View File
@@ -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<ServerConfig> {
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}")))
}
@@ -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<SiteReplicationState> {
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}"))),
}
+2 -2
View File
@@ -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<Config> {
}
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!(
+7 -7
View File
@@ -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");
+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::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}"))
+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::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)]
@@ -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\)\]' \