Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass-through CA certificates to Velero #925

Merged
merged 1 commit into from Jun 15, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions api/v1alpha1/ramenconfig_types.go
Expand Up @@ -74,6 +74,9 @@ type S3StoreProfile struct {
S3SecretRef v1.SecretReference `json:"s3SecretRef"`
//+optional
VeleroNamespaceSecretKeyRef *v1.SecretKeySelector `json:"veleroNamespaceSecretKeyRef,omitempty"`
// A CA bundle to use when verifying TLS connections to the provider
//+optional
CACertificates []byte `json:"caCertificates,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions controllers/kubeobjects/requests.go
Expand Up @@ -104,6 +104,7 @@ type RequestsManager interface {
s3RegionName string,
s3KeyPrefix string,
secretKeyRef *corev1.SecretKeySelector,
caCertificates []byte,
sourceNamespaceName string,
objectsSpec Spec,
requestNamespaceName string,
Expand All @@ -118,6 +119,7 @@ type RequestsManager interface {
s3RegionName string,
s3KeyPrefix string,
secretKeyRef *corev1.SecretKeySelector,
caCertificates []byte,
sourceNamespaceName string,
targetNamespaceName string,
recoverSpec RecoverSpec,
Expand Down
14 changes: 14 additions & 0 deletions controllers/kubeobjects/velero/requests.go
Expand Up @@ -145,6 +145,7 @@ func (RequestsManager) RecoverRequestCreate(
s3RegionName string,
s3KeyPrefix string,
secretKeyRef *corev1.SecretKeySelector,
caCertificates []byte,
sourceNamespaceName string,
targetNamespaceName string,
recoverSpec kubeobjects.RecoverSpec,
Expand All @@ -160,6 +161,7 @@ func (RequestsManager) RecoverRequestCreate(
"s3 region", s3RegionName,
"s3 key prefix", s3KeyPrefix,
"secret key ref", secretKeyRef,
"CA certificates", caCertificates,
"source namespace", sourceNamespaceName,
"target namespace", targetNamespaceName,
"request namespace", requestNamespaceName,
Expand All @@ -177,6 +179,7 @@ func (RequestsManager) RecoverRequestCreate(
s3RegionName,
s3KeyPrefix,
secretKeyRef,
caCertificates,
sourceNamespaceName,
targetNamespaceName,
recoverSpec,
Expand All @@ -198,6 +201,7 @@ func backupDummyCreateAndRestore(
s3RegionName string,
s3KeyPrefix string,
secretKeyRef *corev1.SecretKeySelector,
caCertificates []byte,
sourceNamespaceName string,
targetNamespaceName string,
recoverSpec kubeobjects.RecoverSpec,
Expand All @@ -210,6 +214,7 @@ func backupDummyCreateAndRestore(
backupLocation, backup, err := backupCreate(
types.NamespacedName{Namespace: requestNamespaceName, Name: backupName},
w, reader, s3Url, s3BucketName, s3RegionName, s3KeyPrefix, secretKeyRef,
caCertificates,
backupSpecDummy(), sourceNamespaceName,
labels,
annotations,
Expand Down Expand Up @@ -338,6 +343,7 @@ func (RequestsManager) ProtectRequestCreate(
s3RegionName string,
s3KeyPrefix string,
secretKeyRef *corev1.SecretKeySelector,
caCertificates []byte,
sourceNamespaceName string,
objectsSpec kubeobjects.Spec,
requestNamespaceName string,
Expand All @@ -351,6 +357,7 @@ func (RequestsManager) ProtectRequestCreate(
"s3 region", s3RegionName,
"s3 key prefix", s3KeyPrefix,
"secret key ref", secretKeyRef,
"CA certificates", caCertificates,
"source namespace", sourceNamespaceName,
"request namespace", requestNamespaceName,
"capture name", captureName,
Expand All @@ -366,6 +373,7 @@ func (RequestsManager) ProtectRequestCreate(
s3RegionName,
s3KeyPrefix,
secretKeyRef,
caCertificates,
sourceNamespaceName,
objectsSpec,
requestNamespaceName,
Expand All @@ -385,6 +393,7 @@ func backupRealCreate(
s3RegionName string,
s3KeyPrefix string,
secretKeyRef *corev1.SecretKeySelector,
caCertificates []byte,
sourceNamespaceName string,
objectsSpec kubeobjects.Spec,
requestNamespaceName string,
Expand All @@ -395,6 +404,7 @@ func backupRealCreate(
backupLocation, backup, err := backupCreate(
types.NamespacedName{Namespace: requestNamespaceName, Name: captureName},
w, reader, s3Url, s3BucketName, s3RegionName, s3KeyPrefix, secretKeyRef,
caCertificates,
getBackupSpecFromObjectsSpec(objectsSpec),
sourceNamespaceName,
labels,
Expand Down Expand Up @@ -529,13 +539,15 @@ func backupCreate(
s3RegionName string,
s3KeyPrefix string,
secretKeyRef *corev1.SecretKeySelector,
caCertificates []byte,
backupSpec velero.BackupSpec,
sourceNamespaceName string,
labels map[string]string,
annotations map[string]string,
) (*velero.BackupStorageLocation, *velero.Backup, error) {
backupLocation := backupLocation(backupNamespacedName,
s3Url, s3BucketName, s3RegionName, s3KeyPrefix, secretKeyRef,
caCertificates,
labels,
)
if err := w.objectCreate(backupLocation); err != nil {
Expand Down Expand Up @@ -626,6 +638,7 @@ func restoreTypeMeta() metav1.TypeMeta { return veleroTypeMeta("Restore") }
func backupLocation(namespacedName types.NamespacedName,
s3Url, s3BucketName, s3RegionName, s3KeyPrefix string,
secretKeyRef *corev1.SecretKeySelector,
caCertificates []byte,
labels map[string]string,
) *velero.BackupStorageLocation {
return &velero.BackupStorageLocation{
Expand All @@ -641,6 +654,7 @@ func backupLocation(namespacedName types.NamespacedName,
ObjectStorage: &velero.ObjectStorageLocation{
Bucket: s3BucketName,
Prefix: s3KeyPrefix + path,
CACert: caCertificates,
},
},
Config: map[string]string{
Expand Down
13 changes: 2 additions & 11 deletions controllers/s3_store_accessors.go
Expand Up @@ -6,16 +6,11 @@ package controllers
import (
"github.com/go-logr/logr"
ramen "github.com/ramendr/ramen/api/v1alpha1"
corev1 "k8s.io/api/core/v1"
)

type s3StoreAccessor struct {
ObjectStorer
profileName string
url string
bucketName string
regionName string
veleroNamespaceSecretKeyRef *corev1.SecretKeySelector
ramen.S3StoreProfile
}

func s3StoreAccessorsGet(
Expand All @@ -41,11 +36,7 @@ func s3StoreAccessorsGet(

s3StoreAccessors = append(s3StoreAccessors, s3StoreAccessor{
objectStorer,
s3ProfileName,
s3StoreProfile.S3CompatibleEndpoint,
s3StoreProfile.S3Bucket,
s3StoreProfile.S3Region,
s3StoreProfile.VeleroNamespaceSecretKeyRef,
s3StoreProfile,
Comment on lines -44 to +39
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not obvious to me why this change is needed in this PR, but it's good refactoring. I believe the requests.go could use similar treatment so it's not required to pass in seven or so values for creating a backup/restore request, but that is optional and can/should be deferred.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more field that had to be duplicated was enough for me to fix it. The kubeobjects interface is intended to be a separate "library" and not have any dependencies on Ramen including its S3StoreProfile.

})
}

Expand Down
43 changes: 21 additions & 22 deletions controllers/vrg_kubeobjects.go
Expand Up @@ -205,7 +205,7 @@ func (v *VRGInstance) kubeObjectsCaptureDelete(
if err := s3StoreAccessor.ObjectStorer.DeleteObjects(pathName); err != nil {
v.log.Error(err, "Kube objects capture s3 objects delete error",
"number", captureNumber,
"profile", s3StoreAccessor.profileName,
"profile", s3StoreAccessor.S3ProfileName,
)
v.kubeObjectsCaptureFailed(err.Error())

Expand Down Expand Up @@ -242,12 +242,13 @@ func (v *VRGInstance) kubeObjectsCaptureStartOrResume(
log1 := log.WithValues("group", groupNumber, "name", captureGroup.Name)

for _, s3StoreAccessor := range s3StoreAccessors {
log2 := log.WithValues("profile", s3StoreAccessor.profileName)
log2 := log.WithValues("profile", s3StoreAccessor.S3ProfileName)
request, err := v.reconciler.kubeObjects.ProtectRequestCreate(
v.ctx, v.reconciler.Client, v.reconciler.APIReader, v.log,
s3StoreAccessor.url, s3StoreAccessor.bucketName, s3StoreAccessor.regionName,
pathName, s3StoreAccessor.veleroNamespaceSecretKeyRef, vrg.Namespace, captureGroup.Spec,
veleroNamespaceName, kubeObjectsCaptureName(namePrefix, captureGroup.Name, s3StoreAccessor.profileName),
s3StoreAccessor.S3CompatibleEndpoint, s3StoreAccessor.S3Bucket, s3StoreAccessor.S3Region,
pathName, s3StoreAccessor.VeleroNamespaceSecretKeyRef, s3StoreAccessor.CACertificates,
vrg.Namespace, captureGroup.Spec,
veleroNamespaceName, kubeObjectsCaptureName(namePrefix, captureGroup.Name, s3StoreAccessor.S3ProfileName),
labels, annotations)
requests[requestsProcessedCount] = request
requestsProcessedCount++
Expand Down Expand Up @@ -422,7 +423,7 @@ func (v *VRGInstance) getRecoverGroupsFromRecipe() []kubeobjects.RecoverSpec {
}

func (v *VRGInstance) kubeObjectsRecover(result *ctrl.Result,
s3ProfileName string, s3StoreProfile ramen.S3StoreProfile, objectStorer ObjectStorer,
s3StoreProfile ramen.S3StoreProfile, objectStorer ObjectStorer,
) error {
vrg := v.instance

Expand Down Expand Up @@ -454,11 +455,7 @@ func (v *VRGInstance) kubeObjectsRecover(result *ctrl.Result,
result,
s3StoreAccessor{
objectStorer,
s3ProfileName,
s3StoreProfile.S3CompatibleEndpoint,
s3StoreProfile.S3Bucket,
s3StoreProfile.S3Region,
s3StoreProfile.VeleroNamespaceSecretKeyRef,
s3StoreProfile,
},
sourceVrgNamespaceName,
sourceVrgName,
Expand Down Expand Up @@ -495,25 +492,27 @@ func (v *VRGInstance) createRecoverOrProtectRequest(
pathName, namePrefix := kubeObjectsCapturePathNameAndNamePrefix(vrg.Namespace, vrg.Name, backupSequenceNumber)
request, err = v.reconciler.kubeObjects.ProtectRequestCreate(
v.ctx, v.reconciler.Client, v.reconciler.APIReader, v.log,
s3StoreAccessor.url,
s3StoreAccessor.bucketName,
s3StoreAccessor.regionName,
s3StoreAccessor.S3CompatibleEndpoint,
s3StoreAccessor.S3Bucket,
s3StoreAccessor.S3Region,
pathName,
s3StoreAccessor.veleroNamespaceSecretKeyRef,
s3StoreAccessor.VeleroNamespaceSecretKeyRef,
s3StoreAccessor.CACertificates,
vrg.Namespace,
recoverGroup.Spec,
veleroNamespaceName, kubeObjectsCaptureName(namePrefix, backupName, s3StoreAccessor.profileName),
veleroNamespaceName, kubeObjectsCaptureName(namePrefix, backupName, s3StoreAccessor.S3ProfileName),
labels, annotations)
} else {
request, err = v.reconciler.kubeObjects.RecoverRequestCreate(
v.ctx, v.reconciler.Client, v.reconciler.APIReader, v.log,
s3StoreAccessor.url,
s3StoreAccessor.bucketName,
s3StoreAccessor.regionName,
s3StoreAccessor.S3CompatibleEndpoint,
s3StoreAccessor.S3Bucket,
s3StoreAccessor.S3Region,
capturePathName,
s3StoreAccessor.veleroNamespaceSecretKeyRef,
s3StoreAccessor.VeleroNamespaceSecretKeyRef,
s3StoreAccessor.CACertificates,
sourceVrgNamespaceName, vrg.Namespace, recoverGroup, veleroNamespaceName,
kubeObjectsCaptureName(captureNamePrefix, recoverGroup.BackupName, s3StoreAccessor.profileName),
kubeObjectsCaptureName(captureNamePrefix, recoverGroup.BackupName, s3StoreAccessor.S3ProfileName),
kubeObjectsRecoverName(recoverNamePrefix, groupNumber), labels, annotations)
}

Expand All @@ -531,7 +530,7 @@ func (v *VRGInstance) kubeObjectsRecoveryStartOrResume(
annotations := map[string]string{}
groups := v.getRecoverGroups()
requests := make([]kubeobjects.Request, len(groups)) // Request: interface for ProtectRequest, RecoverRequest
log := v.log.WithValues("number", capture.Number, "profile", s3StoreAccessor.profileName)
log := v.log.WithValues("number", capture.Number, "profile", s3StoreAccessor.S3ProfileName)

for groupNumber, recoverGroup := range groups {
log1 := log.WithValues("group", groupNumber, "name", recoverGroup.BackupName)
Expand Down
2 changes: 1 addition & 1 deletion controllers/vrg_volrep.go
Expand Up @@ -1777,7 +1777,7 @@ func (v *VRGInstance) restorePVsAndPVCsFromS3(result *ctrl.Result) error {

v.log.Info(fmt.Sprintf("Restored %d PVs and %d PVCs using profile %s", pvCount, pvcCount, s3ProfileName))

return v.kubeObjectsRecover(result, s3ProfileName, s3StoreProfile, objectStore)
return v.kubeObjectsRecover(result, s3StoreProfile, objectStore)
}

if NoS3 {
Expand Down
6 changes: 4 additions & 2 deletions controllers/vrg_vrgobject.go
Expand Up @@ -40,22 +40,24 @@ func (v *VRGInstance) vrgObjectProtect(result *ctrl.Result, s3StoreAccessors []s
}

for _, s3StoreAccessor := range s3StoreAccessors {
log1 := log.WithValues("profile", s3StoreAccessor.S3ProfileName)

if err := VrgObjectProtect(s3StoreAccessor.ObjectStorer, *vrg); err != nil {
util.ReportIfNotPresent(
eventReporter, vrg, corev1.EventTypeWarning, util.EventReasonVrgUploadFailed, err.Error(),
)

const message = "VRG Kube object protect error"

log.Error(err, message, "profile", s3StoreAccessor.profileName)
log1.Error(err, message)

v.vrgObjectProtected = newVRGClusterDataUnprotectedCondition(vrg.Generation, message)
result.Requeue = true

return
}

log.Info("VRG Kube object protected", "profile", s3StoreAccessor.profileName)
log1.Info("VRG Kube object protected")

vrgLastUploadTime[key] = metav1.Now()

Expand Down