mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-21 11:56:38 +00:00
Add env variable alias compatibility warnings (#2044)
This commit is contained in:
@@ -71,8 +71,10 @@ Co-locate unit tests with their modules and give behavior-led names. Integration
|
|||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|
||||||
- `RUSTFS_ENABLE_SCANNER` - Enable/disable background data scanner (default: true)
|
- Global configuration environment variables must use flat `RUSTFS_*` names (no module segments), such as `RUSTFS_REGION`, `RUSTFS_ADDRESS`, `RUSTFS_VOLUMES`, and `RUSTFS_LICENSE`.
|
||||||
- `RUSTFS_ENABLE_HEAL` - Enable/disable auto-heal functionality (default: true)
|
- `RUSTFS_SCANNER_ENABLED` - Enable/disable background data scanner (default: true)
|
||||||
|
- `RUSTFS_HEAL_ENABLED` - Enable/disable auto-heal functionality (default: true)
|
||||||
|
- Deprecated aliases (for pre-beta compatibility) are documented in [the config module README](crates/config/README.md#environment-variable-naming-conventions) and must log warnings when used.
|
||||||
- For KMS tests: `NO_PROXY=127.0.0.1,localhost` and clear proxy environment variables
|
- For KMS tests: `NO_PROXY=127.0.0.1,localhost` and clear proxy environment variables
|
||||||
|
|
||||||
## Commit & Pull Request Guidelines
|
## Commit & Pull Request Guidelines
|
||||||
|
|||||||
@@ -32,6 +32,24 @@
|
|||||||
|
|
||||||
For comprehensive documentation, examples, and usage guides, please visit the main [RustFS repository](https://github.com/rustfs/rustfs).
|
For comprehensive documentation, examples, and usage guides, please visit the main [RustFS repository](https://github.com/rustfs/rustfs).
|
||||||
|
|
||||||
|
## Environment Variable Naming Conventions
|
||||||
|
|
||||||
|
RustFS uses a flat naming style for top-level configuration: environment variables are `RUSTFS_*` without nested module segments.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
- `RUSTFS_REGION`
|
||||||
|
- `RUSTFS_ADDRESS`
|
||||||
|
- `RUSTFS_VOLUMES`
|
||||||
|
- `RUSTFS_LICENSE`
|
||||||
|
|
||||||
|
Current guidance:
|
||||||
|
- Prefer module-specific names only when they are not top-level product configuration.
|
||||||
|
- Renamed variables must keep backward-compatible aliases until before beta.
|
||||||
|
- Alias usage must emit deprecation warnings and be treated as transitional only.
|
||||||
|
- Deprecated example:
|
||||||
|
- `RUSTFS_ENABLE_SCANNER` -> `RUSTFS_SCANNER_ENABLED`
|
||||||
|
- `RUSTFS_ENABLE_HEAL` -> `RUSTFS_HEAL_ENABLED`
|
||||||
|
|
||||||
## 📄 License
|
## 📄 License
|
||||||
|
|
||||||
This project is licensed under the Apache License 2.0 - see the [LICENSE](../../LICENSE) file for details.
|
This project is licensed under the Apache License 2.0 - see the [LICENSE](../../LICENSE) file for details.
|
||||||
|
|||||||
@@ -128,6 +128,9 @@ pub const RUSTFS_LICENSE_URL: &str = "https://www.apache.org/licenses/LICENSE-2.
|
|||||||
/// Example: RUSTFS_ADDRESS=":9000"
|
/// Example: RUSTFS_ADDRESS=":9000"
|
||||||
pub const ENV_RUSTFS_ADDRESS: &str = "RUSTFS_ADDRESS";
|
pub const ENV_RUSTFS_ADDRESS: &str = "RUSTFS_ADDRESS";
|
||||||
|
|
||||||
|
/// Environment variable for server volumes.
|
||||||
|
pub const ENV_RUSTFS_VOLUMES: &str = "RUSTFS_VOLUMES";
|
||||||
|
|
||||||
/// Default port for rustfs
|
/// Default port for rustfs
|
||||||
/// This is the default port for rustfs.
|
/// This is the default port for rustfs.
|
||||||
/// This is used to bind the server to a specific port.
|
/// This is used to bind the server to a specific port.
|
||||||
@@ -153,6 +156,12 @@ pub const DEFAULT_CONSOLE_ADDRESS: &str = concat!(":", DEFAULT_CONSOLE_PORT);
|
|||||||
/// Default value: us-east-1
|
/// Default value: us-east-1
|
||||||
pub const RUSTFS_REGION: &str = "us-east-1";
|
pub const RUSTFS_REGION: &str = "us-east-1";
|
||||||
|
|
||||||
|
/// Environment variable for server region.
|
||||||
|
pub const ENV_RUSTFS_REGION: &str = "RUSTFS_REGION";
|
||||||
|
|
||||||
|
/// Environment variable for server license.
|
||||||
|
pub const ENV_RUSTFS_LICENSE: &str = "RUSTFS_LICENSE";
|
||||||
|
|
||||||
/// Default log filename for rustfs
|
/// Default log filename for rustfs
|
||||||
/// This is the default log filename for rustfs.
|
/// This is the default log filename for rustfs.
|
||||||
/// It is used to store the logs of the application.
|
/// It is used to store the logs of the application.
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
//! Disabled lock manager that bypasses all locking operations
|
//! Disabled lock manager that bypasses all locking operations
|
||||||
//! Used when RUSTFS_ENABLE_LOCKS environment variable is set to false
|
//! Used when the lock feature is disabled via RUSTFS_LOCK_ENABLED
|
||||||
|
//! (or deprecated RUSTFS_ENABLE_LOCKS).
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
|||||||
+25
-5
@@ -69,8 +69,12 @@ pub const BUILD_TIMESTAMP: &str = "unknown";
|
|||||||
/// Maximum number of items in delete list
|
/// Maximum number of items in delete list
|
||||||
pub const MAX_DELETE_LIST: usize = 1000;
|
pub const MAX_DELETE_LIST: usize = 1000;
|
||||||
|
|
||||||
/// Default setting for RUSTFS_ENABLE_LOCKS environment variable
|
/// Default setting for lock enablement.
|
||||||
|
/// Canonical variable: RUSTFS_LOCK_ENABLED
|
||||||
|
/// Deprecated compatibility alias: RUSTFS_ENABLE_LOCKS
|
||||||
const DEFAULT_RUSTFS_LOCKS_ENABLED: bool = true;
|
const DEFAULT_RUSTFS_LOCKS_ENABLED: bool = true;
|
||||||
|
const ENV_LOCK_ENABLED: &str = "RUSTFS_LOCK_ENABLED";
|
||||||
|
const ENV_LOCK_ENABLED_DEPRECATED: &str = "RUSTFS_ENABLE_LOCKS";
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Global FastLock Manager
|
// Global FastLock Manager
|
||||||
@@ -97,10 +101,26 @@ impl Default for GlobalLockManager {
|
|||||||
impl GlobalLockManager {
|
impl GlobalLockManager {
|
||||||
/// Create a lock manager based on environment variable configuration
|
/// Create a lock manager based on environment variable configuration
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
// Check RUSTFS_ENABLE_LOCKS environment variable
|
// Check lock enablement env vars with deprecated compatibility support.
|
||||||
let locks_enabled = rustfs_utils::get_env_bool("RUSTFS_ENABLE_LOCKS", DEFAULT_RUSTFS_LOCKS_ENABLED);
|
let locks_enabled = rustfs_utils::get_env_bool_with_aliases(
|
||||||
|
ENV_LOCK_ENABLED,
|
||||||
|
&[ENV_LOCK_ENABLED_DEPRECATED],
|
||||||
|
DEFAULT_RUSTFS_LOCKS_ENABLED,
|
||||||
|
);
|
||||||
if !locks_enabled {
|
if !locks_enabled {
|
||||||
tracing::info!("Lock system disabled via RUSTFS_ENABLE_LOCKS environment variable");
|
let disabled_by = if std::env::var(ENV_LOCK_ENABLED).is_ok() {
|
||||||
|
ENV_LOCK_ENABLED
|
||||||
|
} else if std::env::var(ENV_LOCK_ENABLED_DEPRECATED).is_ok() {
|
||||||
|
ENV_LOCK_ENABLED_DEPRECATED
|
||||||
|
} else {
|
||||||
|
"default setting"
|
||||||
|
};
|
||||||
|
|
||||||
|
if disabled_by == "default setting" {
|
||||||
|
tracing::info!("Lock system disabled via default setting");
|
||||||
|
} else {
|
||||||
|
tracing::info!("Lock system disabled via {} environment variable", disabled_by);
|
||||||
|
}
|
||||||
return Self::Disabled(DisabledLockManager::new());
|
return Self::Disabled(DisabledLockManager::new());
|
||||||
}
|
}
|
||||||
tracing::info!("Lock system enabled");
|
tracing::info!("Lock system enabled");
|
||||||
@@ -248,7 +268,7 @@ static GLOBAL_LOCK_MANAGER: OnceLock<Arc<GlobalLockManager>> = OnceLock::new();
|
|||||||
/// Get the global shared lock manager instance
|
/// Get the global shared lock manager instance
|
||||||
///
|
///
|
||||||
/// Returns either FastObjectLockManager or DisabledLockManager based on
|
/// Returns either FastObjectLockManager or DisabledLockManager based on
|
||||||
/// the RUSTFS_ENABLE_LOCKS environment variable.
|
/// the RUSTFS_LOCK_ENABLED environment variable.
|
||||||
pub fn get_global_lock_manager() -> Arc<GlobalLockManager> {
|
pub fn get_global_lock_manager() -> Arc<GlobalLockManager> {
|
||||||
GLOBAL_LOCK_MANAGER.get_or_init(|| Arc::new(GlobalLockManager::new())).clone()
|
GLOBAL_LOCK_MANAGER.get_or_init(|| Arc::new(GlobalLockManager::new())).clone()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,12 @@
|
|||||||
// 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 std::env;
|
use std::{
|
||||||
|
collections::HashSet,
|
||||||
|
env,
|
||||||
|
sync::{Mutex, OnceLock},
|
||||||
|
};
|
||||||
|
use tracing::warn;
|
||||||
|
|
||||||
/// Retrieve an environment variable as a specific type, with a default value if not set or parsing fails.
|
/// Retrieve an environment variable as a specific type, with a default value if not set or parsing fails.
|
||||||
/// 8-bit type: signed i8
|
/// 8-bit type: signed i8
|
||||||
@@ -68,6 +73,56 @@ pub fn get_env_opt_u8(key: &str) -> Option<u8> {
|
|||||||
env::var(key).ok().and_then(|v| v.parse().ok())
|
env::var(key).ok().and_then(|v| v.parse().ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WARNED_ENV_MESSAGES: OnceLock<Mutex<HashSet<String>>> = OnceLock::new();
|
||||||
|
|
||||||
|
fn log_once(key: &str, message: impl FnOnce() -> String) {
|
||||||
|
let seen = WARNED_ENV_MESSAGES.get_or_init(|| Mutex::new(HashSet::new()));
|
||||||
|
let mut seen = match seen.lock() {
|
||||||
|
Ok(seen) => seen,
|
||||||
|
Err(poisoned) => poisoned.into_inner(),
|
||||||
|
};
|
||||||
|
if seen.insert(key.to_string()) {
|
||||||
|
warn!("{}", message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_env_with_aliases(key: &str, deprecated: &[&str]) -> Option<(String, String)> {
|
||||||
|
if let Ok(value) = env::var(key) {
|
||||||
|
return Some((key.to_string(), value));
|
||||||
|
}
|
||||||
|
|
||||||
|
let (alias, value) = deprecated
|
||||||
|
.iter()
|
||||||
|
.find_map(|alias| env::var(alias).ok().map(|value| (*alias, value)))?;
|
||||||
|
let deprecated_key = format!("env_alias:{alias}->{key}");
|
||||||
|
log_once(&deprecated_key, || {
|
||||||
|
format!("Environment variable {alias} is deprecated, use {key} instead")
|
||||||
|
});
|
||||||
|
Some((alias.to_string(), value))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_env_str_with_aliases(key: &str, deprecated: &[&str], default: &str) -> String {
|
||||||
|
resolve_env_with_aliases(key, deprecated).map_or_else(|| default.to_string(), |(_, value)| value)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_env_bool_with_aliases(key: &str, deprecated: &[&str], default: bool) -> bool {
|
||||||
|
let Some((used_key, value)) = resolve_env_with_aliases(key, deprecated) else {
|
||||||
|
return default;
|
||||||
|
};
|
||||||
|
|
||||||
|
parse_bool_str(&value).unwrap_or_else(|| {
|
||||||
|
log_once(
|
||||||
|
&format!("env_invalid_bool:{used_key}"),
|
||||||
|
|| {
|
||||||
|
format!(
|
||||||
|
"Invalid bool value for {used_key}: {value}. Supported values are true/false,1/0,yes/no,on/off. Treating as unset."
|
||||||
|
)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
default
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Retrieve an environment variable as a specific type, with a default value if not set or parsing fails.
|
/// Retrieve an environment variable as a specific type, with a default value if not set or parsing fails.
|
||||||
/// 16-bit type: signed i16
|
/// 16-bit type: signed i16
|
||||||
///
|
///
|
||||||
@@ -338,7 +393,7 @@ pub fn get_env_opt_usize(key: &str) -> Option<usize> {
|
|||||||
/// - `String`: The environment variable value if set, otherwise the default value.
|
/// - `String`: The environment variable value if set, otherwise the default value.
|
||||||
///
|
///
|
||||||
pub fn get_env_str(key: &str, default: &str) -> String {
|
pub fn get_env_str(key: &str, default: &str) -> String {
|
||||||
env::var(key).unwrap_or_else(|_| default.to_string())
|
get_env_str_with_aliases(key, &[], default)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve an environment variable as a String, returning None if not set.
|
/// Retrieve an environment variable as a String, returning None if not set.
|
||||||
@@ -363,7 +418,7 @@ pub fn get_env_opt_str(key: &str) -> Option<String> {
|
|||||||
/// - `bool`: The parsed boolean value if successful, otherwise the default value.
|
/// - `bool`: The parsed boolean value if successful, otherwise the default value.
|
||||||
///
|
///
|
||||||
pub fn get_env_bool(key: &str, default: bool) -> bool {
|
pub fn get_env_bool(key: &str, default: bool) -> bool {
|
||||||
env::var(key).ok().and_then(|v| parse_bool_str(&v)).unwrap_or(default)
|
get_env_bool_with_aliases(key, &[], default)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a string into a boolean value.
|
/// Parse a string into a boolean value.
|
||||||
@@ -391,5 +446,11 @@ fn parse_bool_str(s: &str) -> Option<bool> {
|
|||||||
/// - `Option<bool>`: The parsed boolean value if successful, otherwise None.
|
/// - `Option<bool>`: The parsed boolean value if successful, otherwise None.
|
||||||
///
|
///
|
||||||
pub fn get_env_opt_bool(key: &str) -> Option<bool> {
|
pub fn get_env_opt_bool(key: &str) -> Option<bool> {
|
||||||
env::var(key).ok().and_then(|v| parse_bool_str(&v))
|
let (used_key, value) = resolve_env_with_aliases(key, &[])?;
|
||||||
|
parse_bool_str(&value).or_else(|| {
|
||||||
|
log_once(&format!("env_invalid_bool_optional:{used_key}"), || {
|
||||||
|
format!("Invalid bool value for {used_key}: {value}. Supported values are true/false,1/0,yes/no,on/off.")
|
||||||
|
});
|
||||||
|
None
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-5
@@ -66,12 +66,17 @@ use rustfs_iam::{init_iam_sys, init_oidc_sys};
|
|||||||
use rustfs_metrics::init_metrics_system;
|
use rustfs_metrics::init_metrics_system;
|
||||||
use rustfs_obs::{init_obs, set_global_guard};
|
use rustfs_obs::{init_obs, set_global_guard};
|
||||||
use rustfs_scanner::init_data_scanner;
|
use rustfs_scanner::init_data_scanner;
|
||||||
use rustfs_utils::net::parse_and_resolve_address;
|
use rustfs_utils::{get_env_bool_with_aliases, net::parse_and_resolve_address};
|
||||||
use std::io::{Error, Result};
|
use std::io::{Error, Result};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
use tracing::{debug, error, info, instrument, warn};
|
use tracing::{debug, error, info, instrument, warn};
|
||||||
|
|
||||||
|
const ENV_SCANNER_ENABLED: &str = "RUSTFS_SCANNER_ENABLED";
|
||||||
|
const ENV_SCANNER_ENABLED_DEPRECATED: &str = "RUSTFS_ENABLE_SCANNER";
|
||||||
|
const ENV_HEAL_ENABLED: &str = "RUSTFS_HEAL_ENABLED";
|
||||||
|
const ENV_HEAL_ENABLED_DEPRECATED: &str = "RUSTFS_ENABLE_HEAL";
|
||||||
|
|
||||||
#[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))]
|
#[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))]
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
|
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
|
||||||
@@ -404,8 +409,8 @@ async fn run(config: config::Config) -> Result<()> {
|
|||||||
let _ = create_ahm_services_cancel_token();
|
let _ = create_ahm_services_cancel_token();
|
||||||
|
|
||||||
// Check environment variables to determine if scanner and heal should be enabled
|
// Check environment variables to determine if scanner and heal should be enabled
|
||||||
let enable_scanner = rustfs_utils::get_env_bool("RUSTFS_ENABLE_SCANNER", true);
|
let enable_scanner = get_env_bool_with_aliases(ENV_SCANNER_ENABLED, &[ENV_SCANNER_ENABLED_DEPRECATED], true);
|
||||||
let enable_heal = rustfs_utils::get_env_bool("RUSTFS_ENABLE_HEAL", true);
|
let enable_heal = get_env_bool_with_aliases(ENV_HEAL_ENABLED, &[ENV_HEAL_ENABLED_DEPRECATED], true);
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
target: "rustfs::main::run",
|
target: "rustfs::main::run",
|
||||||
@@ -501,8 +506,8 @@ async fn handle_shutdown(
|
|||||||
state_manager.update(ServiceState::Stopping);
|
state_manager.update(ServiceState::Stopping);
|
||||||
|
|
||||||
// Check environment variables to determine what services need to be stopped
|
// Check environment variables to determine what services need to be stopped
|
||||||
let enable_scanner = rustfs_utils::get_env_bool("RUSTFS_ENABLE_SCANNER", true);
|
let enable_scanner = get_env_bool_with_aliases(ENV_SCANNER_ENABLED, &[ENV_SCANNER_ENABLED_DEPRECATED], true);
|
||||||
let enable_heal = rustfs_utils::get_env_bool("RUSTFS_ENABLE_HEAL", true);
|
let enable_heal = get_env_bool_with_aliases(ENV_HEAL_ENABLED, &[ENV_HEAL_ENABLED_DEPRECATED], true);
|
||||||
|
|
||||||
// Stop background services based on what was enabled
|
// Stop background services based on what was enabled
|
||||||
if enable_scanner || enable_heal {
|
if enable_scanner || enable_heal {
|
||||||
|
|||||||
+3
-3
@@ -156,8 +156,8 @@ $env:RUSTFS_NS_SCANNER_INTERVAL = "60"
|
|||||||
|
|
||||||
# $env:RUSTFS_REGION = "us-east-1"
|
# $env:RUSTFS_REGION = "us-east-1"
|
||||||
|
|
||||||
$env:RUSTFS_ENABLE_SCANNER = "false"
|
$env:RUSTFS_SCANNER_ENABLED = "false"
|
||||||
$env:RUSTFS_ENABLE_HEAL = "false"
|
$env:RUSTFS_HEAL_ENABLED = "false"
|
||||||
|
|
||||||
# Object cache configuration
|
# Object cache configuration
|
||||||
$env:RUSTFS_OBJECT_CACHE_ENABLE = "true"
|
$env:RUSTFS_OBJECT_CACHE_ENABLE = "true"
|
||||||
@@ -198,4 +198,4 @@ if (-not $env:MALLOC_CONF) {
|
|||||||
# To run in release mode:
|
# To run in release mode:
|
||||||
# cargo run --profile release --bin rustfs
|
# cargo run --profile release --bin rustfs
|
||||||
# To run in debug mode:
|
# To run in debug mode:
|
||||||
cargo run --bin rustfs
|
cargo run --bin rustfs
|
||||||
|
|||||||
+3
-3
@@ -178,9 +178,9 @@ export RUSTFS_NS_SCANNER_INTERVAL=60 # Object scanning interval in seconds
|
|||||||
|
|
||||||
#export RUSTFS_REGION="us-east-1"
|
#export RUSTFS_REGION="us-east-1"
|
||||||
|
|
||||||
export RUSTFS_ENABLE_SCANNER=true
|
export RUSTFS_SCANNER_ENABLED=true
|
||||||
|
|
||||||
export RUSTFS_ENABLE_HEAL=true
|
export RUSTFS_HEAL_ENABLED=true
|
||||||
|
|
||||||
# Object cache configuration
|
# Object cache configuration
|
||||||
export RUSTFS_OBJECT_CACHE_ENABLE=true
|
export RUSTFS_OBJECT_CACHE_ENABLE=true
|
||||||
@@ -252,4 +252,4 @@ fi
|
|||||||
# To run in release mode, use the following line
|
# To run in release mode, use the following line
|
||||||
#cargo run --profile release --bin rustfs
|
#cargo run --profile release --bin rustfs
|
||||||
# To run in debug mode, use the following line
|
# To run in debug mode, use the following line
|
||||||
cargo run --bin rustfs
|
cargo run --bin rustfs
|
||||||
|
|||||||
Reference in New Issue
Block a user