Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 58 additions & 32 deletions internal/controller/kubevirt_dataupload_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1585,27 +1585,31 @@ func (r *KubeVirtDataUploadReconciler) buildDatamoverPodConfig(
}

return &DatamoverPodConfig{
Name: du.Name, // Used as a prefix for GenerateName
Namespace: vmRef.Namespace,
Image: image,
ImagePullPolicy: pullPolicy,
BSLProvider: cfg.Provider,
BSLBucket: cfg.Bucket,
BSLPrefix: cfg.Prefix,
BSLRegion: cfg.Region,
CredentialSecretName: cfg.CredentialName,
CredentialSecretKey: cfg.CredentialKey,
VMName: vmRef.Name,
VMNamespace: vmRef.Namespace,
CheckpointName: checkpointName,
BackupType: backupType,
VeleroBackupName: getVeleroBackupName(du),
DataUploadName: du.Name,
DataUploadUID: string(du.UID),
VMBName: vmb.Name,
VMBTName: vmbtName,
SourcePVCName: "", // overridden by handlePrepared with the rebound PVC name
Labels: make(map[string]string),
Name: du.Name, // Used as a prefix for GenerateName
Namespace: vmRef.Namespace,
Image: image,
ImagePullPolicy: pullPolicy,
BSLProvider: cfg.Provider,
BSLBucket: cfg.Bucket,
BSLPrefix: cfg.Prefix,
BSLRegion: cfg.Region,
BSLS3URL: cfg.S3URL,
BSLS3ForcePathStyle: strconv.FormatBool(cfg.S3ForcePathStyle),
BSLInsecureSkipTLSVerify: strconv.FormatBool(cfg.InsecureSkipTLSVerify),
BSLCACert: cfg.CACert,
CredentialSecretName: cfg.CredentialName,
CredentialSecretKey: cfg.CredentialKey,
VMName: vmRef.Name,
VMNamespace: vmRef.Namespace,
CheckpointName: checkpointName,
BackupType: backupType,
VeleroBackupName: getVeleroBackupName(du),
DataUploadName: du.Name,
DataUploadUID: string(du.UID),
VMBName: vmb.Name,
VMBTName: vmbtName,
SourcePVCName: "", // overridden by handlePrepared with the rebound PVC name
Labels: make(map[string]string),
}, nil
}

Expand Down Expand Up @@ -1647,6 +1651,12 @@ type bslConfig struct {
Region string
CredentialName string
CredentialKey string

// S3-compatible storage provider settings
S3URL string
S3ForcePathStyle bool
InsecureSkipTLSVerify bool
CACert string
}

// extractBSLConfig extracts and validates common BSL configuration fields.
Expand All @@ -1670,8 +1680,16 @@ func extractBSLConfig(bsl *velerov1.BackupStorageLocation) (*bslConfig, error) {
}

region := ""
s3URL := ""
s3ForcePathStyle := false
insecureSkipTLSVerify := false
caCert := ""
if bsl.Spec.Config != nil {
region = bsl.Spec.Config["region"]
s3URL = bsl.Spec.Config["s3Url"]
s3ForcePathStyle = strings.EqualFold(bsl.Spec.Config["s3ForcePathStyle"], "true")
insecureSkipTLSVerify = strings.EqualFold(bsl.Spec.Config["insecureSkipTLSVerify"], "true")
caCert = bsl.Spec.Config["caCert"]
}

credName := ""
Expand All @@ -1684,12 +1702,16 @@ func extractBSLConfig(bsl *velerov1.BackupStorageLocation) (*bslConfig, error) {
}

return &bslConfig{
Provider: bsl.Spec.Provider,
Bucket: bucket,
Prefix: prefix,
Region: region,
CredentialName: credName,
CredentialKey: credKey,
Provider: bsl.Spec.Provider,
Bucket: bucket,
Prefix: prefix,
Region: region,
CredentialName: credName,
CredentialKey: credKey,
S3URL: s3URL,
S3ForcePathStyle: s3ForcePathStyle,
InsecureSkipTLSVerify: insecureSkipTLSVerify,
CACert: caCert,
}, nil
}

Expand Down Expand Up @@ -1737,11 +1759,15 @@ func (r *KubeVirtDataUploadReconciler) initObjectStoreFromBSL(
}

store, err := factory(&uploader.UploaderConfig{
BSLProvider: cfg.Provider,
BSLBucket: cfg.Bucket,
BSLPrefix: cfg.Prefix,
BSLRegion: cfg.Region,
CredentialsData: credData,
BSLProvider: cfg.Provider,
BSLBucket: cfg.Bucket,
BSLPrefix: cfg.Prefix,
BSLRegion: cfg.Region,
BSLS3URL: cfg.S3URL,
BSLS3ForcePathStyle: cfg.S3ForcePathStyle,
BSLInsecureSkipTLSVerify: cfg.InsecureSkipTLSVerify,
BSLCACert: cfg.CACert,
CredentialsData: credData,
})
if err != nil {
return nil, nil, fmt.Errorf("failed to initialize object store: %w", err)
Expand Down
101 changes: 101 additions & 0 deletions internal/controller/kubevirt_dataupload_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4372,6 +4372,107 @@ func TestExtractBSLConfig(t *testing.T) {
}
},
},
{
name: "S3-compatible config keys are extracted",
bsl: &velerov1.BackupStorageLocation{
ObjectMeta: metav1.ObjectMeta{Name: "minio-bsl"},
Spec: velerov1.BackupStorageLocationSpec{
Provider: "aws",
StorageType: velerov1.StorageType{
ObjectStorage: &velerov1.ObjectStorageLocation{
Bucket: "my-bucket",
},
},
Config: map[string]string{
"region": "us-east-1",
"s3Url": "https://minio.example.com",
"s3ForcePathStyle": "true",
"insecureSkipTLSVerify": "true",
"caCert": "-----BEGIN CERTIFICATE-----\nMIIBxTCCAW...\n-----END CERTIFICATE-----",
},
Credential: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{Name: "creds"},
},
},
},
validate: func(t *testing.T, cfg *bslConfig) {
if cfg.S3URL != "https://minio.example.com" {
t.Errorf("S3URL = %q, want %q", cfg.S3URL, "https://minio.example.com")
}
if !cfg.S3ForcePathStyle {
t.Error("S3ForcePathStyle = false, want true")
}
if !cfg.InsecureSkipTLSVerify {
t.Error("InsecureSkipTLSVerify = false, want true")
}
if cfg.CACert != "-----BEGIN CERTIFICATE-----\nMIIBxTCCAW...\n-----END CERTIFICATE-----" {
t.Errorf("CACert = %q, want PEM content", cfg.CACert)
}
},
},
{
name: "S3-compatible booleans are case-insensitive",
bsl: &velerov1.BackupStorageLocation{
ObjectMeta: metav1.ObjectMeta{Name: "bsl"},
Spec: velerov1.BackupStorageLocationSpec{
Provider: "aws",
StorageType: velerov1.StorageType{
ObjectStorage: &velerov1.ObjectStorageLocation{
Bucket: "bucket",
},
},
Config: map[string]string{
"s3ForcePathStyle": "TRUE",
"insecureSkipTLSVerify": "True",
},
Credential: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{Name: "creds"},
},
},
},
validate: func(t *testing.T, cfg *bslConfig) {
if !cfg.S3ForcePathStyle {
t.Error("S3ForcePathStyle = false, want true (case-insensitive)")
}
if !cfg.InsecureSkipTLSVerify {
t.Error("InsecureSkipTLSVerify = false, want true (case-insensitive)")
}
},
},
{
name: "S3-compatible fields default when Config has no S3 keys",
bsl: &velerov1.BackupStorageLocation{
ObjectMeta: metav1.ObjectMeta{Name: "bsl"},
Spec: velerov1.BackupStorageLocationSpec{
Provider: "aws",
StorageType: velerov1.StorageType{
ObjectStorage: &velerov1.ObjectStorageLocation{
Bucket: "bucket",
},
},
Config: map[string]string{
"region": "us-east-1",
},
Credential: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{Name: "creds"},
},
},
},
validate: func(t *testing.T, cfg *bslConfig) {
if cfg.S3URL != "" {
t.Errorf("S3URL = %q, want empty", cfg.S3URL)
}
if cfg.S3ForcePathStyle {
t.Error("S3ForcePathStyle = true, want false")
}
if cfg.InsecureSkipTLSVerify {
t.Error("InsecureSkipTLSVerify = true, want false")
}
if cfg.CACert != "" {
t.Errorf("CACert = %q, want empty", cfg.CACert)
}
},
},
}

for _, tt := range tests {
Expand Down
10 changes: 10 additions & 0 deletions internal/controller/pod_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ type DatamoverPodConfig struct {
BSLPrefix string
BSLRegion string

// S3-compatible storage provider settings
BSLS3URL string
BSLS3ForcePathStyle string
BSLInsecureSkipTLSVerify string
BSLCACert string

// Credentials
CredentialSecretName string
CredentialSecretKey string
Expand Down Expand Up @@ -85,6 +91,10 @@ func buildDatamoverPod(config *DatamoverPodConfig) *corev1.Pod {
{Name: uploader.EnvBSLBucket, Value: config.BSLBucket},
{Name: uploader.EnvBSLPrefix, Value: config.BSLPrefix},
{Name: uploader.EnvBSLRegion, Value: config.BSLRegion},
{Name: uploader.EnvBSLS3URL, Value: config.BSLS3URL},
{Name: uploader.EnvBSLS3ForcePathStyle, Value: config.BSLS3ForcePathStyle},
{Name: uploader.EnvBSLInsecureSkipTLSVerify, Value: config.BSLInsecureSkipTLSVerify},
{Name: uploader.EnvBSLCACert, Value: config.BSLCACert},
{Name: uploader.EnvCredentialsFile, Value: uploader.DefaultCredentialsPath},
{Name: uploader.EnvVMName, Value: config.VMName},
{Name: uploader.EnvVMNamespace, Value: config.VMNamespace},
Expand Down
Loading
Loading