Skip to content

Commit 345b342

Browse files
kaovilaiclaude
andcommitted
feat: Add CloudStorage config and region fallback to BSL
When a DataProtectionApplication references a CloudStorage CR, the BSL now inherits configuration values from the CloudStorage CR as fallback, similar to the credential fallback mechanism. Changes: - BSL now uses CloudStorage CR's Config field as base configuration - CloudStorage CR's Region field is automatically added to BSL config - DPA's CloudStorageLocation.Config values override CloudStorage values - Added comprehensive test coverage for config fallback behavior This enhancement allows users to define provider-specific settings once in the CloudStorage CR without needing to duplicate them in the DPA, while still maintaining the ability to override specific values at the DPA level when needed. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent aa93572 commit 345b342

File tree

2 files changed

+113
-3
lines changed

2 files changed

+113
-3
lines changed

internal/controller/bsl.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,32 @@ func (r *DataProtectionApplicationReconciler) ReconcileBackupStorageLocations(lo
175175
return err
176176
}
177177
bsl.Spec.BackupSyncPeriod = bslSpec.CloudStorage.BackupSyncPeriod
178-
bsl.Spec.Config = bslSpec.CloudStorage.Config
178+
179+
// Start with CloudStorage CR's config as base (fallback)
180+
if bucket.Spec.Config != nil {
181+
bsl.Spec.Config = make(map[string]string)
182+
for k, v := range bucket.Spec.Config {
183+
bsl.Spec.Config[k] = v
184+
}
185+
}
186+
187+
// Add region from CloudStorage CR if specified
188+
if bucket.Spec.Region != "" && bsl.Spec.Config == nil {
189+
bsl.Spec.Config = make(map[string]string)
190+
}
191+
if bucket.Spec.Region != "" {
192+
bsl.Spec.Config["region"] = bucket.Spec.Region
193+
}
194+
195+
// Override with DPA's CloudStorageLocation config (higher priority)
196+
for k, v := range bslSpec.CloudStorage.Config {
197+
if bsl.Spec.Config == nil {
198+
bsl.Spec.Config = make(map[string]string)
199+
}
200+
bsl.Spec.Config[k] = v
201+
}
202+
203+
// Handle enableSharedConfig from CloudStorage CR
179204
if bucket.Spec.EnableSharedConfig != nil && *bucket.Spec.EnableSharedConfig {
180205
if bsl.Spec.Config == nil {
181206
bsl.Spec.Config = map[string]string{}

internal/controller/bsl_test.go

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2953,6 +2953,7 @@ func TestDPAReconciler_ReconcileBackupStorageLocations(t *testing.T) {
29532953
},
29542954
Spec: velerov1.BackupStorageLocationSpec{
29552955
Provider: "aws",
2956+
Config: map[string]string{"region": "test-region"},
29562957
StorageType: velerov1.StorageType{
29572958
ObjectStorage: &velerov1.ObjectStorageLocation{
29582959
Bucket: "test-bucket",
@@ -3027,6 +3028,7 @@ func TestDPAReconciler_ReconcileBackupStorageLocations(t *testing.T) {
30273028
Provider: "aws",
30283029
Config: map[string]string{
30293030
"enableSharedConfig": "true",
3031+
"region": "us-east-1",
30303032
},
30313033
StorageType: velerov1.StorageType{
30323034
ObjectStorage: &velerov1.ObjectStorageLocation{
@@ -3043,6 +3045,88 @@ func TestDPAReconciler_ReconcileBackupStorageLocations(t *testing.T) {
30433045
},
30443046
},
30453047
},
3048+
{
3049+
name: "CloudStorage with config and region fallback",
3050+
objects: []client.Object{
3051+
&oadpv1alpha1.DataProtectionApplication{
3052+
ObjectMeta: metav1.ObjectMeta{
3053+
Name: "test-dpa",
3054+
Namespace: "test-ns",
3055+
},
3056+
Spec: oadpv1alpha1.DataProtectionApplicationSpec{
3057+
BackupLocations: []oadpv1alpha1.BackupLocation{
3058+
{
3059+
CloudStorage: &oadpv1alpha1.CloudStorageLocation{
3060+
CloudStorageRef: corev1.LocalObjectReference{
3061+
Name: "config-fallback-cs",
3062+
},
3063+
Credential: &corev1.SecretKeySelector{
3064+
LocalObjectReference: corev1.LocalObjectReference{
3065+
Name: "cloud-credentials",
3066+
},
3067+
Key: "credentials",
3068+
},
3069+
Config: map[string]string{
3070+
"profile": "custom-profile", // This should override CloudStorage's config
3071+
},
3072+
},
3073+
},
3074+
},
3075+
},
3076+
},
3077+
&corev1.Secret{
3078+
ObjectMeta: metav1.ObjectMeta{
3079+
Name: "cloud-credentials",
3080+
Namespace: "test-ns",
3081+
},
3082+
Data: map[string][]byte{"credentials": {}},
3083+
},
3084+
&oadpv1alpha1.CloudStorage{
3085+
ObjectMeta: metav1.ObjectMeta{
3086+
Name: "config-fallback-cs",
3087+
Namespace: "test-ns",
3088+
},
3089+
Spec: oadpv1alpha1.CloudStorageSpec{
3090+
Provider: oadpv1alpha1.AWSBucketProvider,
3091+
Name: "config-test-bucket",
3092+
Region: "us-west-2",
3093+
Config: map[string]string{
3094+
"profile": "default",
3095+
"s3ForcePathStyle": "true",
3096+
"serverSideEncryption": "AES256",
3097+
},
3098+
},
3099+
},
3100+
},
3101+
want: true,
3102+
wantErr: false,
3103+
wantBSL: velerov1.BackupStorageLocation{
3104+
ObjectMeta: metav1.ObjectMeta{
3105+
Name: "test-dpa-1",
3106+
Namespace: "test-ns",
3107+
},
3108+
Spec: velerov1.BackupStorageLocationSpec{
3109+
Provider: "aws",
3110+
Config: map[string]string{
3111+
"region": "us-west-2", // From CloudStorage CR
3112+
"profile": "custom-profile", // Overridden by DPA
3113+
"s3ForcePathStyle": "true", // From CloudStorage CR
3114+
"serverSideEncryption": "AES256", // From CloudStorage CR
3115+
},
3116+
StorageType: velerov1.StorageType{
3117+
ObjectStorage: &velerov1.ObjectStorageLocation{
3118+
Bucket: "config-test-bucket",
3119+
},
3120+
},
3121+
Credential: &corev1.SecretKeySelector{
3122+
LocalObjectReference: corev1.LocalObjectReference{
3123+
Name: "cloud-credentials",
3124+
},
3125+
Key: "credentials",
3126+
},
3127+
},
3128+
},
3129+
},
30463130
{
30473131
name: "CloudStorage with Azure provider",
30483132
objects: []client.Object{
@@ -3105,6 +3189,7 @@ func TestDPAReconciler_ReconcileBackupStorageLocations(t *testing.T) {
31053189
Config: map[string]string{
31063190
"storageAccount": "mystorageaccount",
31073191
"resourceGroup": "myresourcegroup",
3192+
"region": "eastus",
31083193
},
31093194
StorageType: velerov1.StorageType{
31103195
ObjectStorage: &velerov1.ObjectStorageLocation{
@@ -3282,7 +3367,7 @@ func TestDPAReconciler_ReconcileBackupStorageLocations(t *testing.T) {
32823367
},
32833368
Spec: velerov1.BackupStorageLocationSpec{
32843369
Provider: "aws",
3285-
Config: map[string]string(nil),
3370+
Config: map[string]string{"region": "us-west-2"},
32863371
StorageType: velerov1.StorageType{
32873372
ObjectStorage: &velerov1.ObjectStorageLocation{
32883373
Bucket: "aws-bucket-1",
@@ -3355,7 +3440,7 @@ func TestDPAReconciler_ReconcileBackupStorageLocations(t *testing.T) {
33553440
},
33563441
Spec: velerov1.BackupStorageLocationSpec{
33573442
Provider: "aws",
3358-
Config: map[string]string(nil),
3443+
Config: map[string]string{"region": "eu-west-1"},
33593444
StorageType: velerov1.StorageType{
33603445
ObjectStorage: &velerov1.ObjectStorageLocation{
33613446
Bucket: "sync-test-bucket",

0 commit comments

Comments
 (0)