Skip to content

Commit 317a215

Browse files
kaovilaiclaude
andcommitted
OADP-3307: Add Azure and GCP CloudStorage API provider implementations
Signed-off-by: Tiger Kaovilai <[email protected]> Co-Authored-By: Claude <[email protected]>
1 parent c354db6 commit 317a215

File tree

15 files changed

+2460
-29
lines changed

15 files changed

+2460
-29
lines changed

api/v1alpha1/cloudstorage_types.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,11 @@ type CloudStorageSpec struct {
4242
// region for the bucket to be in, will be us-east-1 if not set.
4343
Region string `json:"region,omitempty"`
4444
// provider is the provider of the cloud storage
45-
// +kubebuilder:validation:Enum=aws
45+
// +kubebuilder:validation:Enum=aws;azure;gcp
4646
Provider CloudStorageProvider `json:"provider"`
47+
// config is provider-specific configuration options
48+
// +kubebuilder:validation:Optional
49+
Config map[string]string `json:"config,omitempty"`
4750

4851
// https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/storage/[email protected]#section-readme
4952
// azure blob primary endpoint

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bundle/manifests/oadp.openshift.io_cloudstorages.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ spec:
3939
type: object
4040
spec:
4141
properties:
42+
config:
43+
additionalProperties:
44+
type: string
45+
description: config is provider-specific configuration options
46+
type: object
4247
creationSecret:
4348
description: creationSecret is the secret that is needed to be used
4449
while creating the bucket.
@@ -75,6 +80,8 @@ spec:
7580
description: provider is the provider of the cloud storage
7681
enum:
7782
- aws
83+
- azure
84+
- gcp
7885
type: string
7986
region:
8087
description: region for the bucket to be in, will be us-east-1 if

config/crd/bases/oadp.openshift.io_cloudstorages.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ spec:
3939
type: object
4040
spec:
4141
properties:
42+
config:
43+
additionalProperties:
44+
type: string
45+
description: config is provider-specific configuration options
46+
type: object
4247
creationSecret:
4348
description: creationSecret is the secret that is needed to be used
4449
while creating the bucket.
@@ -75,6 +80,8 @@ spec:
7580
description: provider is the provider of the cloud storage
7681
enum:
7782
- aws
83+
- azure
84+
- gcp
7885
type: string
7986
region:
8087
description: region for the bucket to be in, will be us-east-1 if

internal/controller/stsflow.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ import (
1919
// - AZURE_CLIENT_ID
2020
// - AZURE_TENANT_ID
2121
// - AZURE_FEDERATED_TOKEN_FILE
22+
//
23+
// Unlike AWS and GCP which use credential files, Azure uses environment variables for
24+
// workload identity authentication. This design choice is driven by compatibility with
25+
// the Velero project's Azure credential handling, avoiding the need for upstream changes.
26+
// The Velero project expects these specific environment variables for Azure authentication,
27+
// and by providing them directly, we maintain seamless integration.
28+
//
29+
// The secret created here is injected into both Velero and NodeAgent pods via envFrom,
30+
// eliminating the need for temporary credential files as used by AWS/GCP providers.
2231
func (r *DataProtectionApplicationReconciler) ReconcileAzureWorkloadIdentitySecret(log logr.Logger) (bool, error) {
2332
dpa := r.dpa
2433
azureClientID := os.Getenv(stsflow.ClientIDEnvKey)

internal/controller/velero_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2559,6 +2559,22 @@ func TestDPAReconciler_buildVeleroDeploymentWithAzureWorkloadIdentity(t *testing
25592559
if !foundAzureSecretRef {
25602560
t.Errorf("Expected %s secret reference in envFrom", stsflow.AzureWorkloadIdentitySecretName)
25612561
}
2562+
2563+
// Check that Azure environment variables are NOT set directly
2564+
// They should come from the secret referenced in envFrom
2565+
for _, container := range tt.veleroDeployment.Spec.Template.Spec.Containers {
2566+
if container.Name == common.Velero {
2567+
for _, env := range container.Env {
2568+
if env.Name == "AZURE_CLIENT_ID" {
2569+
t.Errorf("AZURE_CLIENT_ID should not be set directly, it should come from the secret")
2570+
}
2571+
if env.Name == "AZURE_FEDERATED_TOKEN_FILE" {
2572+
t.Errorf("AZURE_FEDERATED_TOKEN_FILE should not be set directly, it should come from the secret")
2573+
}
2574+
}
2575+
break
2576+
}
2577+
}
25622578
} else {
25632579
}
25642580
})

pkg/bucket/aws.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,6 @@ func (a awsBucketClient) getS3Client() (s3iface.S3API, error) {
147147
return s3.New(s), nil
148148
}
149149

150-
func (a awsBucketClient) ForceCredentialRefresh() error {
151-
return fmt.Errorf("force credential refresh is not yet implemented")
152-
}
153-
154150
func (a awsBucketClient) Delete() (bool, error) {
155151
s3Client, err := a.getS3Client()
156152
if err != nil {

0 commit comments

Comments
 (0)