refactor: route admin config writes through app context (#3782)

This commit is contained in:
Zhengchao An
2026-06-23 13:46:13 +08:00
committed by GitHub
parent 4ef899dd5c
commit 825c01060c
9 changed files with 179 additions and 28 deletions
+41 -7
View File
@@ -5,14 +5,14 @@ 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-admin-kms-manager-context` - Branch: `overtrue/arch-admin-config-writes-context`
- Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079/API-080/API-081/API-082/API-083/API-084/API-085/API-086/API-087/API-088/API-089/API-090/API-091/API-092/API-093/API-094/API-095/API-096/API-097/API-098/API-099/API-100/API-101/API-102/API-103/API-104/API-105/API-106/API-107/API-108/API-109/API-110/API-111/API-112/API-113/API-114/API-115/API-116/API-117/API-118/API-119/API-120/API-121/API-122/API-123/API-124/API-125/API-126/API-127/API-128/API-129/API-130/API-131/API-132/API-133/API-134/API-135/API-136/API-137/API-138/API-139/API-140/API-141/API-142/API-143/API-144/API-145/API-146/API-147/API-148/API-149/API-150/API-151/API-152/API-153/API-154/API-155/API-156/API-157/API-158/API-159/API-160/API-161/API-162/API-163/API-164/API-165/API-166/API-167/API-168`. - Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079/API-080/API-081/API-082/API-083/API-084/API-085/API-086/API-087/API-088/API-089/API-090/API-091/API-092/API-093/API-094/API-095/API-096/API-097/API-098/API-099/API-100/API-101/API-102/API-103/API-104/API-105/API-106/API-107/API-108/API-109/API-110/API-111/API-112/API-113/API-114/API-115/API-116/API-117/API-118/API-119/API-120/API-121/API-122/API-123/API-124/API-125/API-126/API-127/API-128/API-129/API-130/API-131/API-132/API-133/API-134/API-135/API-136/API-137/API-138/API-139/API-140/API-141/API-142/API-143/API-144/API-145/API-146/API-147/API-148/API-149/API-150/API-151/API-152/API-153/API-154/API-155/API-156/API-157/API-158/API-159/API-160/API-161/API-162/API-163/API-164/API-165/API-166/API-167/API-168/API-169`.
- Based on: API-168 local branch stacked on API-167 local branch after API-163 PR #3777 merged. - Based on: API-169 local branch after API-168 PR #3781 merged.
- PR type for this branch: `consumer-migration` - PR type for this branch: `consumer-migration`
- Runtime behavior changes: none. - Runtime behavior changes: none.
- Rust code changes: route admin KMS service-manager initialization fallback - Rust code changes: route admin server-config and storage-class runtime
through an AppContext-first resolver with legacy global initialization publication through AppContext-first publish helpers, with legacy global
preserved when no manager is available. setters preserved as default adapters.
- CI/script changes: lock completed owner and test/fuzz boundaries against - CI/script changes: lock completed owner and test/fuzz boundaries against
bare/glob imports, scattered raw ECStore facade subpaths, and startup bare/glob imports, scattered raw ECStore facade subpaths, and startup
runtime/root-server/table/S3/app shared/app bucket/app ECStore/admin facade runtime/root-server/table/S3/app shared/app bucket/app ECStore/admin facade
@@ -21,7 +21,7 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
and storage owner thin bridge regressions, plus app context and notify and storage owner thin bridge regressions, plus app context and notify
event-bridge thin module regressions; accept the reviewed AppContext resolver event-bridge thin module regressions; accept the reviewed AppContext resolver
reverse dependencies in the layer baseline. reverse dependencies in the layer baseline.
- Docs changes: record the API-136/API-137/API-138/API-139/API-140/API-141/API-142/API-143/API-144/API-145/API-146/API-147/API-148/API-149/API-150/API-151/API-152/API-153/API-154/API-155/API-156/API-157/API-158/API-159/API-160/API-161/API-162/API-163/API-164/API-165/API-166/API-167/API-168 owner facade cleanup. - Docs changes: record the API-136/API-137/API-138/API-139/API-140/API-141/API-142/API-143/API-144/API-145/API-146/API-147/API-148/API-149/API-150/API-151/API-152/API-153/API-154/API-155/API-156/API-157/API-158/API-159/API-160/API-161/API-162/API-163/API-164/API-165/API-166/API-167/API-168/API-169 owner facade cleanup.
## Phase 0 Tasks ## Phase 0 Tasks
@@ -4431,6 +4431,21 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
migration guard, layer guard, formatting, diff hygiene, residual admin KMS migration guard, layer guard, formatting, diff hygiene, residual admin KMS
init scan, Rust risk scan, branch freshness check, and three-expert review. init scan, Rust risk scan, branch freshness check, and three-expert review.
- [x] `API-169` Route admin config publication through AppContext.
- Do: add AppContext-first publish helpers for server config and storage
class config, then route admin config write/reload publication through
those helpers.
- Acceptance: admin production handlers and services no longer directly call
`set_global_server_config` or the admin storage-class global setter, while
AppContext default adapters preserve the legacy global-setter fallback.
- Must preserve: config validation, config history persistence, runtime
snapshot reload semantics, dynamic subsystem application, storage-class
parsing, and store persistence behavior.
- Verification: RustFS compile coverage, targeted context resolver tests,
migration guard, layer guard, formatting, diff hygiene, residual admin
config publication scan, Rust risk scan, branch freshness check, and
three-expert review.
## Next PRs ## Next PRs
1. `consumer-migration`: continue reducing direct global reads behind AppContext resolver boundaries. 1. `consumer-migration`: continue reducing direct global reads behind AppContext resolver boundaries.
@@ -4491,11 +4506,30 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
| Quality/architecture | pass | API-168 keeps admin KMS service-manager initialization behind the AppContext resolver boundary. | | Quality/architecture | pass | API-168 keeps admin KMS service-manager initialization behind the AppContext resolver boundary. |
| Migration preservation | pass | KMS key, management, and dynamic handlers preserve legacy initialization fallback and existing fallback logs. | | Migration preservation | pass | KMS key, management, and dynamic handlers preserve legacy initialization fallback and existing fallback logs. |
| Testing/verification | pass | RustFS focused compile, targeted context tests, formatting, migration/layer guards, diff hygiene, residual KMS init scan, and Rust risk scan passed for API-168. | | Testing/verification | pass | RustFS focused compile, targeted context tests, formatting, migration/layer guards, diff hygiene, residual KMS init scan, and Rust risk scan passed for API-168. |
| Quality/architecture | pass | API-169 keeps admin config runtime publication behind AppContext publish helpers with default global-setter adapters. |
| Migration preservation | pass | Config writes, runtime reload, dynamic subsystem application, and storage-class parsing preserve existing persistence and runtime side effects. |
| Testing/verification | pass | RustFS focused compile, targeted context tests, formatting, migration/layer guards, diff hygiene, residual config publication scan, and Rust risk scan passed for API-169. |
## Verification Notes ## Verification Notes
Passed before push: Passed before push:
- Issue #660 API-169 current slice:
- `cargo check --tests -p rustfs`: passed.
- `cargo test -p rustfs resolver_helpers_are_context_first_and_fallback_when_context_is_absent --lib`:
passed.
- `cargo fmt --all`: 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.
- `./scripts/check_layer_dependencies.sh`: passed.
- AppContext admin config publication scan: passed; direct admin production
`set_global_server_config` and storage-class global setter calls are
removed.
- Rust risk scan: no new production unwrap/expect, panic/todo/unsafe, or cast
risks added.
- Issue #660 API-164 current slice: - Issue #660 API-164 current slice:
- `cargo check --tests -p rustfs`: passed. - `cargo check --tests -p rustfs`: passed.
- `cargo test -p rustfs resolver_helpers_are_context_first_and_fallback_when_context_is_absent --lib`: - `cargo test -p rustfs resolver_helpers_are_context_first_and_fallback_when_context_is_absent --lib`:
+6 -6
View File
@@ -24,7 +24,7 @@ use crate::admin::service::config::{
validate_server_config, validate_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, resolve_server_config}; use crate::app::context::{publish_server_config, resolve_object_store_handle, resolve_server_config};
use crate::auth::{check_key_valid, get_session_token}; use crate::auth::{check_key_valid, get_session_token};
use crate::error::ApiError; use crate::error::ApiError;
use crate::server::{ADMIN_PREFIX, RemoteAddr}; use crate::server::{ADMIN_PREFIX, RemoteAddr};
@@ -54,7 +54,7 @@ use rustfs_config::oidc::{
OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_CONFIG_URL, OIDC_DISPLAY_NAME, OIDC_EMAIL_CLAIM, OIDC_GROUPS_CLAIM, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_CONFIG_URL, OIDC_DISPLAY_NAME, OIDC_EMAIL_CLAIM, OIDC_GROUPS_CLAIM,
OIDC_REDIRECT_URI, OIDC_REDIRECT_URI_DYNAMIC, OIDC_ROLE_POLICY, OIDC_SCOPES, OIDC_USERNAME_CLAIM, OIDC_REDIRECT_URI, OIDC_REDIRECT_URI_DYNAMIC, OIDC_ROLE_POLICY, OIDC_SCOPES, OIDC_USERNAME_CLAIM,
}; };
use rustfs_config::server_config::{Config as ServerConfig, DEFAULT_KVS, KV, KVS, set_global_server_config}; use rustfs_config::server_config::{Config as ServerConfig, DEFAULT_KVS, KV, KVS};
use rustfs_config::{ use rustfs_config::{
COMMENT_KEY, DEFAULT_DELIMITER, ENABLE_KEY, ENV_PREFIX, ENV_SCANNER_ALERT_EXCESS_FOLDERS, COMMENT_KEY, DEFAULT_DELIMITER, ENABLE_KEY, ENV_PREFIX, ENV_SCANNER_ALERT_EXCESS_FOLDERS,
ENV_SCANNER_ALERT_EXCESS_VERSION_SIZE, ENV_SCANNER_ALERT_EXCESS_VERSIONS, ENV_SCANNER_BITROT_CYCLE_SECS, ENV_SCANNER_ALERT_EXCESS_VERSION_SIZE, ENV_SCANNER_ALERT_EXCESS_VERSIONS, ENV_SCANNER_BITROT_CYCLE_SECS,
@@ -1592,7 +1592,7 @@ impl Operation for SetConfigKVHandler {
validate_server_config(&config, sub_system).await?; validate_server_config(&config, sub_system).await?;
save_server_config_history(&body).await?; save_server_config_history(&body).await?;
save_server_config_to_store(&config).await?; save_server_config_to_store(&config).await?;
set_global_server_config(config.clone()); publish_server_config(config.clone());
let mut config_applied = false; let mut config_applied = false;
if let Some(sub_system) = sub_system if let Some(sub_system) = sub_system
&& is_dynamic_config_subsystem(sub_system) && is_dynamic_config_subsystem(sub_system)
@@ -1628,7 +1628,7 @@ impl Operation for DelConfigKVHandler {
validate_server_config(&config, sub_system).await?; validate_server_config(&config, sub_system).await?;
save_server_config_history(&body).await?; save_server_config_history(&body).await?;
save_server_config_to_store(&config).await?; save_server_config_to_store(&config).await?;
set_global_server_config(config.clone()); publish_server_config(config.clone());
let mut config_applied = false; let mut config_applied = false;
if let Some(sub_system) = sub_system if let Some(sub_system) = sub_system
&& is_dynamic_config_subsystem(sub_system) && is_dynamic_config_subsystem(sub_system)
@@ -1726,7 +1726,7 @@ impl Operation for RestoreConfigHistoryKVHandler {
apply_set_directives(&mut config, &directives)?; apply_set_directives(&mut config, &directives)?;
validate_server_config(&config, None).await?; validate_server_config(&config, None).await?;
save_server_config_to_store(&config).await?; save_server_config_to_store(&config).await?;
set_global_server_config(config.clone()); publish_server_config(config.clone());
apply_and_signal_dynamic_subsystems(&config).await; apply_and_signal_dynamic_subsystems(&config).await;
signal_config_snapshot_reload().await; signal_config_snapshot_reload().await;
@@ -1765,7 +1765,7 @@ impl Operation for SetConfigHandler {
validate_server_config(&config, None).await?; validate_server_config(&config, None).await?;
save_server_config_history(&body).await?; save_server_config_history(&body).await?;
save_server_config_to_store(&config).await?; save_server_config_to_store(&config).await?;
set_global_server_config(config.clone()); publish_server_config(config.clone());
apply_and_signal_dynamic_subsystems(&config).await; apply_and_signal_dynamic_subsystems(&config).await;
signal_config_snapshot_reload().await; signal_config_snapshot_reload().await;
+1 -5
View File
@@ -119,7 +119,7 @@ mod ecstore_client {
} }
mod ecstore_config { mod ecstore_config {
pub(crate) use crate::storage::ecstore_config::{com, init, set_global_storage_class, storageclass}; pub(crate) use crate::storage::ecstore_config::{com, init, storageclass};
} }
mod ecstore_data_usage { mod ecstore_data_usage {
@@ -462,10 +462,6 @@ pub(crate) fn init_admin_config_defaults() {
ecstore_config::init(); ecstore_config::init();
} }
pub(crate) fn set_global_storage_class(cfg: storageclass::Config) {
ecstore_config::set_global_storage_class(cfg);
}
pub(crate) async fn load_data_usage_from_backend( pub(crate) async fn load_data_usage_from_backend(
store: Arc<ECStore>, store: Arc<ECStore>,
) -> std::result::Result<rustfs_data_usage::DataUsageInfo, Error> { ) -> std::result::Result<rustfs_data_usage::DataUsageInfo, Error> {
+6 -5
View File
@@ -12,15 +12,16 @@
// 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 super::super::set_global_storage_class;
use super::super::storageclass; use super::super::storageclass;
use super::super::{STORAGE_CLASS_SUB_SYS, read_admin_config_without_migrate}; use super::super::{STORAGE_CLASS_SUB_SYS, read_admin_config_without_migrate};
use crate::app::context::{resolve_notification_system, resolve_object_store_handle}; use crate::app::context::{
publish_server_config, publish_storage_class_config, resolve_notification_system, 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};
use rustfs_config::notify::{NOTIFY_MQTT_SUB_SYS, NOTIFY_REDIS_DEFAULT_CHANNEL, NOTIFY_WEBHOOK_SUB_SYS}; use rustfs_config::notify::{NOTIFY_MQTT_SUB_SYS, NOTIFY_REDIS_DEFAULT_CHANNEL, NOTIFY_WEBHOOK_SUB_SYS};
use rustfs_config::oidc::IDENTITY_OPENID_SUB_SYS; use rustfs_config::oidc::IDENTITY_OPENID_SUB_SYS;
use rustfs_config::server_config::{Config as ServerConfig, KVS, set_global_server_config}; use rustfs_config::server_config::{Config as ServerConfig, KVS};
use rustfs_config::{AUDIT_DEFAULT_DIR, EVENT_DEFAULT_DIR}; use rustfs_config::{AUDIT_DEFAULT_DIR, EVENT_DEFAULT_DIR};
use rustfs_config::{DEFAULT_DELIMITER, ENABLE_KEY, EnableState}; use rustfs_config::{DEFAULT_DELIMITER, ENABLE_KEY, EnableState};
use rustfs_config::{HEAL_SUB_SYS, SCANNER_SUB_SYS}; use rustfs_config::{HEAL_SUB_SYS, SCANNER_SUB_SYS};
@@ -77,7 +78,7 @@ async fn apply_storage_class_runtime_config(config: &ServerConfig) -> S3Result<(
.unwrap_or(1); .unwrap_or(1);
let parsed = storageclass::lookup_config(&kvs, set_drive_count) let parsed = storageclass::lookup_config(&kvs, set_drive_count)
.map_err(|err| internal_error(format!("failed to apply storage class config: {err}")))?; .map_err(|err| internal_error(format!("failed to apply storage class config: {err}")))?;
set_global_storage_class(parsed); publish_storage_class_config(parsed);
Ok(()) Ok(())
} }
@@ -335,7 +336,7 @@ pub async fn reload_runtime_config_snapshot() -> S3Result<()> {
} }
} }
set_global_server_config(config); publish_server_config(config);
Ok(()) Ok(())
} }
+80 -1
View File
@@ -29,6 +29,7 @@ use super::DailyAllTierStats;
use super::ECStore; use super::ECStore;
use super::EndpointServerPools; use super::EndpointServerPools;
use super::ScannerMetricsReport; use super::ScannerMetricsReport;
use super::StorageClassConfig;
use super::TierConfigMgr; use super::TierConfigMgr;
use super::metadata_sys::BucketMetadataSys; use super::metadata_sys::BucketMetadataSys;
use super::new_object_layer_fn; use super::new_object_layer_fn;
@@ -179,6 +180,18 @@ pub fn resolve_server_config() -> Option<Config> {
resolve_server_config_with(get_global_app_context(), || default_server_config_interface().get()) resolve_server_config_with(get_global_app_context(), || default_server_config_interface().get())
} }
/// Publish server config using AppContext-first precedence.
pub fn publish_server_config(config: Config) {
publish_server_config_with(get_global_app_context(), config, |config| default_server_config_interface().set(config));
}
/// Publish storage class config using AppContext-first precedence.
pub fn publish_storage_class_config(config: StorageClassConfig) {
publish_storage_class_config_with(get_global_app_context(), config, |config| {
default_storage_class_interface().set(config);
});
}
/// Resolve buffer profile config using AppContext-first precedence. /// Resolve buffer profile config using AppContext-first precedence.
pub fn resolve_buffer_config() -> RustFSBufferConfig { pub fn resolve_buffer_config() -> RustFSBufferConfig {
resolve_buffer_config_with(get_global_app_context(), || default_buffer_config_interface().get()) resolve_buffer_config_with(get_global_app_context(), || default_buffer_config_interface().get())
@@ -365,6 +378,26 @@ fn resolve_server_config_with(context: Option<Arc<AppContext>>, fallback: impl F
context.map_or_else(fallback, |context| context.server_config().get()) context.map_or_else(fallback, |context| context.server_config().get())
} }
fn publish_server_config_with(context: Option<Arc<AppContext>>, config: Config, fallback: impl FnOnce(Config)) {
if let Some(context) = context {
context.server_config().set(config);
} else {
fallback(config);
}
}
fn publish_storage_class_config_with(
context: Option<Arc<AppContext>>,
config: StorageClassConfig,
fallback: impl FnOnce(StorageClassConfig),
) {
if let Some(context) = context {
context.storage_class().set(config);
} else {
fallback(config);
}
}
fn resolve_buffer_config_with( fn resolve_buffer_config_with(
context: Option<Arc<AppContext>>, context: Option<Arc<AppContext>>,
fallback: impl FnOnce() -> RustFSBufferConfig, fallback: impl FnOnce() -> RustFSBufferConfig,
@@ -388,13 +421,14 @@ mod tests {
ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BufferConfigInterface, DeploymentIdInterface, ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BufferConfigInterface, DeploymentIdInterface,
EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface, EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface,
OutboundTlsRuntimeInterface, RegionInterface, ReplicationStatsInterface, RuntimePortInterface, ScannerMetricsInterface, OutboundTlsRuntimeInterface, RegionInterface, ReplicationStatsInterface, RuntimePortInterface, ScannerMetricsInterface,
ServerConfigInterface, TierConfigInterface, TierStatsInterface, ServerConfigInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface,
}; };
use crate::config::{RustFSBufferConfig, WorkloadProfile}; use crate::config::{RustFSBufferConfig, WorkloadProfile};
use async_trait::async_trait; use async_trait::async_trait;
use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; use rustfs_iam::{store::object::ObjectStore, sys::IamSys};
use rustfs_lock::{LocalClient, LockClient}; use rustfs_lock::{LocalClient, LockClient};
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
use tempfile::TempDir; use tempfile::TempDir;
use tokio_util::sync::CancellationToken; use tokio_util::sync::CancellationToken;
@@ -582,12 +616,27 @@ mod tests {
struct TestServerConfigInterface { struct TestServerConfigInterface {
config: Option<Config>, config: Option<Config>,
published: Arc<AtomicUsize>,
} }
impl ServerConfigInterface for TestServerConfigInterface { impl ServerConfigInterface for TestServerConfigInterface {
fn get(&self) -> Option<Config> { fn get(&self) -> Option<Config> {
self.config.clone() self.config.clone()
} }
fn set(&self, _config: Config) {
self.published.fetch_add(1, Ordering::SeqCst);
}
}
struct TestStorageClassInterface {
published: Arc<AtomicUsize>,
}
impl StorageClassInterface for TestStorageClassInterface {
fn set(&self, _config: StorageClassConfig) {
self.published.fetch_add(1, Ordering::SeqCst);
}
} }
struct TestBufferConfigInterface { struct TestBufferConfigInterface {
@@ -674,6 +723,10 @@ mod tests {
}; };
let tier_config = TierConfigMgr::new(); let tier_config = TierConfigMgr::new();
let server_config = Config::new(); let server_config = Config::new();
let context_server_config_published = Arc::new(AtomicUsize::new(0));
let fallback_server_config_published = Arc::new(AtomicUsize::new(0));
let context_storage_class_published = Arc::new(AtomicUsize::new(0));
let fallback_storage_class_published = Arc::new(AtomicUsize::new(0));
let buffer_config = RustFSBufferConfig::new(WorkloadProfile::AiTraining); let buffer_config = RustFSBufferConfig::new(WorkloadProfile::AiTraining);
let context_lock_client: Arc<dyn LockClient> = Arc::new(LocalClient::new()); let context_lock_client: Arc<dyn LockClient> = Arc::new(LocalClient::new());
let fallback_lock_client: Arc<dyn LockClient> = Arc::new(LocalClient::new()); let fallback_lock_client: Arc<dyn LockClient> = Arc::new(LocalClient::new());
@@ -757,6 +810,10 @@ mod tests {
}), }),
server_config: Arc::new(TestServerConfigInterface { server_config: Arc::new(TestServerConfigInterface {
config: Some(server_config.clone()), config: Some(server_config.clone()),
published: context_server_config_published.clone(),
}),
storage_class: Arc::new(TestStorageClassInterface {
published: context_storage_class_published.clone(),
}), }),
buffer_config: Arc::new(TestBufferConfigInterface { config: buffer_config }), buffer_config: Arc::new(TestBufferConfigInterface { config: buffer_config }),
}, },
@@ -847,6 +904,18 @@ mod tests {
resolve_server_config_with(Some(context.clone()), || None).expect("context server config"), resolve_server_config_with(Some(context.clone()), || None).expect("context server config"),
server_config server_config
); );
publish_server_config_with(Some(context.clone()), Config::new(), |config| {
drop(config);
fallback_server_config_published.fetch_add(1, Ordering::SeqCst);
});
assert_eq!(context_server_config_published.load(Ordering::SeqCst), 1);
assert_eq!(fallback_server_config_published.load(Ordering::SeqCst), 0);
publish_storage_class_config_with(Some(context.clone()), StorageClassConfig::default(), |config| {
drop(config);
fallback_storage_class_published.fetch_add(1, Ordering::SeqCst);
});
assert_eq!(context_storage_class_published.load(Ordering::SeqCst), 1);
assert_eq!(fallback_storage_class_published.load(Ordering::SeqCst), 0);
assert_eq!( assert_eq!(
resolve_buffer_config_with(Some(context), || RustFSBufferConfig::new(WorkloadProfile::GeneralPurpose)).workload, resolve_buffer_config_with(Some(context), || RustFSBufferConfig::new(WorkloadProfile::GeneralPurpose)).workload,
WorkloadProfile::AiTraining WorkloadProfile::AiTraining
@@ -922,6 +991,16 @@ mod tests {
resolve_server_config_with(None, || Some(server_config.clone())).expect("fallback server config"), resolve_server_config_with(None, || Some(server_config.clone())).expect("fallback server config"),
server_config server_config
); );
publish_server_config_with(None, Config::new(), |config| {
drop(config);
fallback_server_config_published.fetch_add(1, Ordering::SeqCst);
});
assert_eq!(fallback_server_config_published.load(Ordering::SeqCst), 1);
publish_storage_class_config_with(None, StorageClassConfig::default(), |config| {
drop(config);
fallback_storage_class_published.fetch_add(1, Ordering::SeqCst);
});
assert_eq!(fallback_storage_class_published.load(Ordering::SeqCst), 1);
assert_eq!( assert_eq!(
resolve_buffer_config_with(None, || RustFSBufferConfig::new(WorkloadProfile::DataAnalytics)).workload, resolve_buffer_config_with(None, || RustFSBufferConfig::new(WorkloadProfile::DataAnalytics)).workload,
WorkloadProfile::DataAnalytics WorkloadProfile::DataAnalytics
+10 -2
View File
@@ -20,14 +20,14 @@ use super::handles::{
default_notification_system_interface, default_notify_interface, default_outbound_tls_runtime_interface, default_notification_system_interface, default_notify_interface, default_outbound_tls_runtime_interface,
default_region_interface, default_replication_pool_interface, default_replication_stats_interface, default_region_interface, default_replication_pool_interface, default_replication_stats_interface,
default_runtime_port_interface, default_scanner_metrics_interface, default_server_config_interface, default_runtime_port_interface, default_scanner_metrics_interface, default_server_config_interface,
default_tier_config_interface, default_tier_stats_interface, default_storage_class_interface, default_tier_config_interface, default_tier_stats_interface,
}; };
use super::interfaces::{ use super::interfaces::{
ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface, ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface,
DeploymentIdInterface, EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface, DeploymentIdInterface, EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface,
LockClientInterface, NotificationSystemInterface, NotifyInterface, OutboundTlsRuntimeInterface, RegionInterface, LockClientInterface, NotificationSystemInterface, NotifyInterface, OutboundTlsRuntimeInterface, RegionInterface,
ReplicationPoolInterface, ReplicationStatsInterface, RuntimePortInterface, ScannerMetricsInterface, ServerConfigInterface, ReplicationPoolInterface, ReplicationStatsInterface, RuntimePortInterface, ScannerMetricsInterface, ServerConfigInterface,
TierConfigInterface, TierStatsInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface,
}; };
use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; use rustfs_iam::{store::object::ObjectStore, sys::IamSys};
use rustfs_kms::KmsServiceManager; use rustfs_kms::KmsServiceManager;
@@ -60,6 +60,7 @@ pub struct AppContext {
region: Arc<dyn RegionInterface>, region: Arc<dyn RegionInterface>,
tier_config: Arc<dyn TierConfigInterface>, tier_config: Arc<dyn TierConfigInterface>,
server_config: Arc<dyn ServerConfigInterface>, server_config: Arc<dyn ServerConfigInterface>,
storage_class: Arc<dyn StorageClassInterface>,
buffer_config: Arc<dyn BufferConfigInterface>, buffer_config: Arc<dyn BufferConfigInterface>,
} }
@@ -89,6 +90,7 @@ impl AppContext {
region: default_region_interface(), region: default_region_interface(),
tier_config: default_tier_config_interface(), tier_config: default_tier_config_interface(),
server_config: default_server_config_interface(), server_config: default_server_config_interface(),
storage_class: default_storage_class_interface(),
buffer_config: default_buffer_config_interface(), buffer_config: default_buffer_config_interface(),
} }
} }
@@ -194,6 +196,10 @@ impl AppContext {
self.server_config.clone() self.server_config.clone()
} }
pub fn storage_class(&self) -> Arc<dyn StorageClassInterface> {
self.storage_class.clone()
}
pub fn buffer_config(&self) -> Arc<dyn BufferConfigInterface> { pub fn buffer_config(&self) -> Arc<dyn BufferConfigInterface> {
self.buffer_config.clone() self.buffer_config.clone()
} }
@@ -223,6 +229,7 @@ pub(super) struct AppContextTestInterfaces {
pub(super) region: Arc<dyn RegionInterface>, pub(super) region: Arc<dyn RegionInterface>,
pub(super) tier_config: Arc<dyn TierConfigInterface>, pub(super) tier_config: Arc<dyn TierConfigInterface>,
pub(super) server_config: Arc<dyn ServerConfigInterface>, pub(super) server_config: Arc<dyn ServerConfigInterface>,
pub(super) storage_class: Arc<dyn StorageClassInterface>,
pub(super) buffer_config: Arc<dyn BufferConfigInterface>, pub(super) buffer_config: Arc<dyn BufferConfigInterface>,
} }
@@ -253,6 +260,7 @@ impl AppContext {
region: interfaces.region, region: interfaces.region,
tier_config: interfaces.tier_config, tier_config: interfaces.tier_config,
server_config: interfaces.server_config, server_config: interfaces.server_config,
storage_class: interfaces.storage_class,
buffer_config: interfaces.buffer_config, buffer_config: interfaces.buffer_config,
} }
} }
+22 -2
View File
@@ -13,25 +13,27 @@
// limitations under the License. // limitations under the License.
use super::super::EndpointServerPools; use super::super::EndpointServerPools;
use super::super::StorageClassConfig;
use super::super::TierConfigMgr; use super::super::TierConfigMgr;
use super::super::metadata_sys::{BucketMetadataSys, get_global_bucket_metadata_sys}; use super::super::metadata_sys::{BucketMetadataSys, get_global_bucket_metadata_sys};
use super::super::{ use super::super::{
collect_scanner_metrics_report, get_daily_all_tier_stats, get_global_boot_time, get_global_bucket_monitor, collect_scanner_metrics_report, get_daily_all_tier_stats, get_global_boot_time, get_global_bucket_monitor,
get_global_deployment_id, get_global_endpoints_opt, get_global_lock_client, get_global_notification_sys, get_global_region, get_global_deployment_id, get_global_endpoints_opt, get_global_lock_client, get_global_notification_sys, get_global_region,
get_global_replication_pool, get_global_replication_stats, get_global_tier_config_mgr, global_rustfs_port, get_global_replication_pool, get_global_replication_stats, get_global_tier_config_mgr, global_rustfs_port,
set_global_storage_class,
}; };
use super::interfaces::{ use super::interfaces::{
ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface, ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface,
DeploymentIdInterface, EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface, DeploymentIdInterface, EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface,
LockClientInterface, NotificationSystemInterface, NotifyInterface, OutboundTlsRuntimeInterface, RegionInterface, LockClientInterface, NotificationSystemInterface, NotifyInterface, OutboundTlsRuntimeInterface, RegionInterface,
ReplicationPoolInterface, ReplicationStatsInterface, RuntimePortInterface, ScannerMetricsInterface, ServerConfigInterface, ReplicationPoolInterface, ReplicationStatsInterface, RuntimePortInterface, ScannerMetricsInterface, ServerConfigInterface,
TierConfigInterface, TierStatsInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface,
}; };
use crate::config::{RustFSBufferConfig, get_global_buffer_config}; use crate::config::{RustFSBufferConfig, get_global_buffer_config};
use async_trait::async_trait; use async_trait::async_trait;
use rustfs_common::get_global_local_node_name; use rustfs_common::get_global_local_node_name;
use rustfs_config::server_config::Config; use rustfs_config::server_config::Config;
use rustfs_config::server_config::get_global_server_config; use rustfs_config::server_config::{get_global_server_config, set_global_server_config};
use rustfs_credentials::{Credentials, get_global_action_cred}; use rustfs_credentials::{Credentials, get_global_action_cred};
use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; use rustfs_iam::{store::object::ObjectStore, sys::IamSys};
use rustfs_kms::{KmsServiceManager, get_global_kms_service_manager}; use rustfs_kms::{KmsServiceManager, get_global_kms_service_manager};
@@ -303,6 +305,20 @@ impl ServerConfigInterface for ServerConfigHandle {
fn get(&self) -> Option<Config> { fn get(&self) -> Option<Config> {
get_global_server_config() get_global_server_config()
} }
fn set(&self, config: Config) {
set_global_server_config(config);
}
}
/// Default storage class config interface adapter.
#[derive(Default)]
pub struct StorageClassHandle;
impl StorageClassInterface for StorageClassHandle {
fn set(&self, config: StorageClassConfig) {
set_global_storage_class(config);
}
} }
/// Default buffer profile config interface adapter. /// Default buffer profile config interface adapter.
@@ -395,6 +411,10 @@ pub fn default_server_config_interface() -> Arc<dyn ServerConfigInterface> {
Arc::new(ServerConfigHandle) Arc::new(ServerConfigHandle)
} }
pub fn default_storage_class_interface() -> Arc<dyn StorageClassInterface> {
Arc::new(StorageClassHandle)
}
pub fn default_buffer_config_interface() -> Arc<dyn BufferConfigInterface> { pub fn default_buffer_config_interface() -> Arc<dyn BufferConfigInterface> {
Arc::new(BufferConfigHandle) Arc::new(BufferConfigHandle)
} }
+7
View File
@@ -15,6 +15,7 @@
use super::super::DailyAllTierStats; use super::super::DailyAllTierStats;
use super::super::EndpointServerPools; use super::super::EndpointServerPools;
use super::super::ScannerMetricsReport; use super::super::ScannerMetricsReport;
use super::super::StorageClassConfig;
use super::super::TierConfigMgr; use super::super::TierConfigMgr;
use super::super::metadata_sys::BucketMetadataSys; use super::super::metadata_sys::BucketMetadataSys;
use super::super::{BucketBandwidthMonitor, DynReplicationPool, NotificationSys, ReplicationStats}; use super::super::{BucketBandwidthMonitor, DynReplicationPool, NotificationSys, ReplicationStats};
@@ -156,6 +157,12 @@ pub trait TierConfigInterface: Send + Sync {
/// Server config interface for application-layer and server modules. /// Server config interface for application-layer and server modules.
pub trait ServerConfigInterface: Send + Sync { pub trait ServerConfigInterface: Send + Sync {
fn get(&self) -> Option<Config>; fn get(&self) -> Option<Config>;
fn set(&self, config: Config);
}
/// Storage class config interface for admin runtime config publication.
pub trait StorageClassInterface: Send + Sync {
fn set(&self, config: StorageClassConfig);
} }
/// Buffer profile config interface for application-layer use-cases. /// Buffer profile config interface for application-layer use-cases.
+6
View File
@@ -566,6 +566,12 @@ pub(crate) mod storageclass {
pub(crate) const STANDARD_IA: &str = super::ecstore_config::storageclass::STANDARD_IA; pub(crate) const STANDARD_IA: &str = super::ecstore_config::storageclass::STANDARD_IA;
} }
pub(crate) type StorageClassConfig = crate::storage::ecstore_config::storageclass::Config;
pub(crate) fn set_global_storage_class(cfg: StorageClassConfig) {
crate::storage::ecstore_config::set_global_storage_class(cfg);
}
pub(crate) fn get_total_usable_capacity(disks: &[rustfs_madmin::Disk], info: &rustfs_madmin::StorageInfo) -> usize { pub(crate) fn get_total_usable_capacity(disks: &[rustfs_madmin::Disk], info: &rustfs_madmin::StorageInfo) -> usize {
ecstore_capacity::get_total_usable_capacity(disks, info) ecstore_capacity::get_total_usable_capacity(disks, info)
} }