feat(build): make native GCS backends optional (#7223)

* feat(build): make native GCS backends optional

* test(odm): cover native Azure runtime credentials
This commit is contained in:
Zhengchao An
2026-09-06 01:27:36 +08:00
committed by GitHub
parent 1c4e9f1b65
commit 955d491174
11 changed files with 136 additions and 9 deletions
+3 -2
View File
@@ -57,7 +57,8 @@ name = "swift_object_integration_test"
required-features = ["swift"]
[features]
default = ["ftps", "webdav"]
default = ["ftps", "webdav", "gcs"]
gcs = ["rustfs-ecstore/gcs"]
metrics-gpu = ["rustfs-obs/gpu"]
ftps = ["rustfs-protocols/ftps"]
swift = ["rustfs-protocols/swift"]
@@ -66,7 +67,7 @@ sftp = ["rustfs-protocols/sftp"]
license = []
io-scheduler-debug = [] # Enable debug information in I/O scheduler
tracing-chunk-debug = [] # Enable per-chunk tracing in data plane (high noise, for debugging only)
full = ["metrics-gpu", "ftps", "swift", "webdav", "sftp", "pyroscope"]
full = ["metrics-gpu", "ftps", "swift", "webdav", "sftp", "pyroscope", "gcs"]
e2e-test-hooks = []
# Shortens Connect credentials only in debug E2E builds.
connect-e2e-short-credentials = []
@@ -90,6 +90,8 @@ const BACKFILL_OP_CANCEL: &str = "cancel";
pub(crate) const ERR_CODE_MODULE_DISABLED: &str = "OnDemandMigrationDisabled";
/// Error code returned when the source bucket did not answer the probe.
pub(crate) const ERR_CODE_SOURCE_UNREACHABLE: &str = "OnDemandMigrationSourceUnreachable";
/// Error code returned when the configured provider was excluded at build time.
pub(crate) const ERR_CODE_BACKEND_NOT_COMPILED: &str = "OnDemandMigrationBackendNotCompiled";
/// Error code returned by `GET` when the bucket has no configuration.
pub(crate) const ERR_CODE_NO_SUCH_CONFIGURATION: &str = "NoSuchConfiguration";
/// Error code (409) returned by `start` while a backfill job holds the lease.
@@ -630,12 +632,17 @@ pub(crate) fn source_client_spec(config: &OnDemandMigrationConfig) -> SourceClie
}
}
/// Builder failures are input errors: the endpoint policy, the CA PEM or the
/// credentials the operator supplied. Anonymous sources are not wired yet
/// Distinguishes excluded backends from invalid endpoint, CA or credentials.
/// Anonymous S3 sources are not wired yet
/// (ODM-05 adds the credential-less path), so `MissingCredentials` is a 400
/// naming the field instead of an opaque internal error.
fn client_build_error(err: RemoteS3ClientError) -> S3Error {
match err {
RemoteS3ClientError::BackendNotCompiled(provider) => custom_error(
ERR_CODE_BACKEND_NOT_COMPILED,
StatusCode::NOT_IMPLEMENTED,
format!("the {provider} backend is not included in this build; rebuild with the gcs feature"),
),
RemoteS3ClientError::MissingCredentials => admin_s3_error(
S3ErrorCode::InvalidArgument,
"source.credentials is required: anonymous sources are not supported yet",
@@ -1288,6 +1295,14 @@ mod tests {
assert!(err.message().unwrap_or_default().contains("source.credentials"));
}
#[test]
fn backend_not_compiled_is_distinct_from_invalid_credentials() {
let err = client_build_error(RemoteS3ClientError::BackendNotCompiled("gcs_native"));
assert_eq!(err.code(), &S3ErrorCode::Custom(ERR_CODE_BACKEND_NOT_COMPILED.into()));
assert_eq!(err.status_code(), Some(StatusCode::NOT_IMPLEMENTED));
assert!(err.message().unwrap_or_default().contains("gcs feature"));
}
#[test]
fn module_switch_defaults_on_and_reads_the_env() {
temp_env::with_var(ENV_ON_DEMAND_MIGRATION_ENABLED, None::<&str>, || assert!(module_enabled()));
+2 -1
View File
@@ -992,7 +992,7 @@ pub(crate) fn odm_source_error_response(policy: &PolicyConfig, class: &'static s
/// Metrics/message label for a bucket whose source client could not be built.
pub(crate) fn odm_state_error_class(error: &OdmStateError) -> &'static str {
match error {
OdmStateError::AnonymousUnsupported => "unsupported",
OdmStateError::AnonymousUnsupported | OdmStateError::BackendNotCompiled(_) => "unsupported",
OdmStateError::ClientBuild(_) => "client_build",
}
}
@@ -2035,6 +2035,7 @@ mod on_demand_migration_tests {
#[test]
fn odm_state_error_class_is_stable() {
assert_eq!(odm_state_error_class(&OdmStateError::AnonymousUnsupported), "unsupported");
assert_eq!(odm_state_error_class(&OdmStateError::BackendNotCompiled("gcs_native")), "unsupported");
assert_eq!(odm_state_error_class(&OdmStateError::ClientBuild("tls".to_string())), "client_build");
}