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

Add snapshot secret reference to group snapshot controller. #1034

Merged
merged 1 commit into from
Mar 25, 2024
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
27 changes: 20 additions & 7 deletions pkg/common-controller/groupsnapshot_controller_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ func (ctrl *csiSnapshotCommonController) createGroupSnapshotContent(groupSnapsho
TODO: Add PVC finalizer
*/

groupSnapshotClass, volumes, contentName, err := ctrl.getCreateGroupSnapshotInput(groupSnapshot)
groupSnapshotClass, volumes, contentName, snapshotterSecretRef, err := ctrl.getCreateGroupSnapshotInput(groupSnapshot)
if err != nil {
return nil, fmt.Errorf("failed to get input parameters to create group snapshot %s: %q", groupSnapshot.Name, err)
}
Expand Down Expand Up @@ -773,8 +773,15 @@ func (ctrl *csiSnapshotCommonController) createGroupSnapshotContent(groupSnapsho
}

/*
TODO: Add secret reference details
Add secret reference details
*/
if snapshotterSecretRef != nil {
klog.V(5).Infof("createGroupSnapshotContent: set annotation [%s] on volume group snapshot content [%s].", utils.AnnDeletionSecretRefName, groupSnapshotContent.Name)
metav1.SetMetaDataAnnotation(&groupSnapshotContent.ObjectMeta, utils.AnnDeletionSecretRefName, snapshotterSecretRef.Name)

klog.V(5).Infof("creategroupSnapshotContent: set annotation [%s] on volume group snapshot content [%s].", utils.AnnDeletionSecretRefNamespace, groupSnapshotContent.Name)
metav1.SetMetaDataAnnotation(&groupSnapshotContent.ObjectMeta, utils.AnnDeletionSecretRefNamespace, snapshotterSecretRef.Namespace)
}

var updateGroupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent
klog.V(5).Infof("volume group snapshot content %#v", groupSnapshotContent)
Expand Down Expand Up @@ -810,7 +817,7 @@ func (ctrl *csiSnapshotCommonController) createGroupSnapshotContent(groupSnapsho
return updateGroupSnapshotContent, nil
}

func (ctrl *csiSnapshotCommonController) getCreateGroupSnapshotInput(groupSnapshot *crdv1alpha1.VolumeGroupSnapshot) (*crdv1alpha1.VolumeGroupSnapshotClass, []*v1.PersistentVolume, string, error) {
func (ctrl *csiSnapshotCommonController) getCreateGroupSnapshotInput(groupSnapshot *crdv1alpha1.VolumeGroupSnapshot) (*crdv1alpha1.VolumeGroupSnapshotClass, []*v1.PersistentVolume, string, *v1.SecretReference, error) {
className := groupSnapshot.Spec.VolumeGroupSnapshotClassName
klog.V(5).Infof("getCreateGroupSnapshotInput [%s]", groupSnapshot.Name)
var groupSnapshotClass *crdv1alpha1.VolumeGroupSnapshotClass
Expand All @@ -819,23 +826,29 @@ func (ctrl *csiSnapshotCommonController) getCreateGroupSnapshotInput(groupSnapsh
groupSnapshotClass, err = ctrl.getGroupSnapshotClass(*className)
if err != nil {
klog.Errorf("getCreateGroupSnapshotInput failed to getClassFromVolumeGroupSnapshot %s", err)
return nil, nil, "", err
return nil, nil, "", nil, err
}
} else {
klog.Errorf("failed to getCreateGroupSnapshotInput %s without a group snapshot class", groupSnapshot.Name)
return nil, nil, "", fmt.Errorf("failed to take group snapshot %s without a group snapshot class", groupSnapshot.Name)
return nil, nil, "", nil, fmt.Errorf("failed to take group snapshot %s without a group snapshot class", groupSnapshot.Name)
}

volumes, err := ctrl.getVolumesFromVolumeGroupSnapshot(groupSnapshot)
if err != nil {
klog.Errorf("getCreateGroupSnapshotInput failed to get PersistentVolume objects [%s]: Error: [%#v]", groupSnapshot.Name, err)
return nil, nil, "", err
return nil, nil, "", nil, err
}

// Create VolumeGroupSnapshotContent name
contentName := utils.GetDynamicSnapshotContentNameForGroupSnapshot(groupSnapshot)

return groupSnapshotClass, volumes, contentName, nil
// Get the secret reference
snapshotterSecretRef, err := utils.GetGroupSnapshotSecretReference(utils.SnapshotterSecretParams, groupSnapshotClass.Parameters, contentName, groupSnapshot)
if err != nil {
return nil, nil, "", nil, err
}

return groupSnapshotClass, volumes, contentName, snapshotterSecretRef, nil
}

// syncGroupSnapshotContent deals with one key off the queue
Expand Down
51 changes: 48 additions & 3 deletions pkg/sidecar-controller/groupsnapshot_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,11 @@ func (ctrl *csiSnapshotSideCarController) createGroupSnapshotWrapper(groupSnapsh
creationTime = time.Now()
}

groupSnapshotSecret, err := utils.GetSecretReference(utils.GroupSnapshotterSecretParams, class.Parameters, groupSnapshotContent.GetObjectMeta().GetName(), nil)
if err != nil {
klog.Errorf("Failed to get secret reference for group snapshot content %s: %v", groupSnapshotContent.Name, err)
return groupSnapshotContent, fmt.Errorf("failed to get secret reference for group snapshot content %s: %v", groupSnapshotContent.Name, err)
}
// Create individual snapshots and snapshot contents
var snapshotContentNames []string
for _, snapshot := range snapshots {
Expand Down Expand Up @@ -452,6 +457,13 @@ func (ctrl *csiSnapshotSideCarController) createGroupSnapshotWrapper(groupSnapsh
},
}

if groupSnapshotSecret != nil {
klog.V(5).Infof("createGroupSnapshotContent: set annotation [%s] on volume snapshot content [%s].", utils.AnnDeletionSecretRefName, volumeSnapshotContent.Name)
metav1.SetMetaDataAnnotation(&volumeSnapshotContent.ObjectMeta, utils.AnnDeletionSecretRefName, groupSnapshotSecret.Name)

klog.V(5).Infof("createGroupSnapshotContent: set annotation [%s] on volume snapshot content [%s].", utils.AnnDeletionSecretRefNamespace, volumeSnapshotContent.Name)
metav1.SetMetaDataAnnotation(&volumeSnapshotContent.ObjectMeta, utils.AnnDeletionSecretRefNamespace, groupSnapshotSecret.Namespace)
}
label := make(map[string]string)
label["volumeGroupSnapshotName"] = groupSnapshotContent.Spec.VolumeGroupSnapshotRef.Name
volumeSnapshot := &crdv1.VolumeSnapshot{
Expand Down Expand Up @@ -498,7 +510,7 @@ func (ctrl *csiSnapshotSideCarController) createGroupSnapshotWrapper(groupSnapsh

func (ctrl *csiSnapshotSideCarController) getCSIGroupSnapshotInput(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) (*crdv1alpha1.VolumeGroupSnapshotClass, map[string]string, error) {
className := groupSnapshotContent.Spec.VolumeGroupSnapshotClassName
klog.V(5).Infof("getCSIGroupSnapshotInput for group snapshot content [%s]", groupSnapshotContent.Name)
klog.V(5).Infof("getCSIGroupSnapshotInput for group snapshot content %s", groupSnapshotContent.Name)
var class *crdv1alpha1.VolumeGroupSnapshotClass
var err error
if className != nil {
Expand All @@ -517,9 +529,13 @@ func (ctrl *csiSnapshotSideCarController) getCSIGroupSnapshotInput(groupSnapshot
klog.V(5).Infof("getCSISnapshotInput for groupSnapshotContent [%s]: no VolumeGroupSnapshotClassName provided for pre-provisioned group snapshot", groupSnapshotContent.Name)
}

// TODO: Resolve snapshotting secret credentials.
// Resolve snapshotting secret credentials.
snapshotterCredentials, err := ctrl.GetGroupCredentialsFromAnnotation(groupSnapshotContent)
if err != nil {
return nil, nil, err
}

return class, nil, nil
return class, snapshotterCredentials, nil
}

// getGroupSnapshotClass is a helper function to get group snapshot class from the class name.
Expand Down Expand Up @@ -826,3 +842,32 @@ func (ctrl *csiSnapshotSideCarController) checkandUpdateGroupSnapshotContentStat
}
return ctrl.createGroupSnapshotWrapper(groupSnapshotContent)
}

func (ctrl *csiSnapshotSideCarController) GetGroupCredentialsFromAnnotation(content *crdv1alpha1.VolumeGroupSnapshotContent) (map[string]string, error) {
var groupSnapshotterCredentials map[string]string
var err error

// Check if annotation exists
if metav1.HasAnnotation(content.ObjectMeta, utils.AnnDeletionSecretRefName) && metav1.HasAnnotation(content.ObjectMeta, utils.AnnDeletionSecretRefNamespace) {
annDeletionSecretName := content.Annotations[utils.AnnDeletionSecretRefName]
annDeletionSecretNamespace := content.Annotations[utils.AnnDeletionSecretRefNamespace]

groupSnapshotterSecretRef := &v1.SecretReference{}

if annDeletionSecretName == "" || annDeletionSecretNamespace == "" {
return nil, fmt.Errorf("cannot retrieve secrets for volume group snapshot content %#v, err: secret name or namespace not specified", content.Name)
}

groupSnapshotterSecretRef.Name = annDeletionSecretName
groupSnapshotterSecretRef.Namespace = annDeletionSecretNamespace

groupSnapshotterCredentials, err = utils.GetCredentials(ctrl.client, groupSnapshotterSecretRef)
if err != nil {
// Continue with deletion, as the secret may have already been deleted.
klog.Errorf("Failed to get credentials for snapshot %s: %s", content.Name, err.Error())
return nil, fmt.Errorf("cannot get credentials for snapshot content %#v", content.Name)
}
}

return groupSnapshotterCredentials, nil
}
64 changes: 64 additions & 0 deletions pkg/utils/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ const (
PrefixedSnapshotterSecretNameKey = csiParameterPrefix + "snapshotter-secret-name" // Prefixed name key for DeleteSnapshot secret
PrefixedSnapshotterSecretNamespaceKey = csiParameterPrefix + "snapshotter-secret-namespace" // Prefixed namespace key for DeleteSnapshot secret

PrefixedGroupSnapshotterSecretNameKey = csiParameterPrefix + "group-snapshotter-secret-name" // Prefixed name key for CreateGroupSnapshot secret
PrefixedGroupSnapshotterSecretNamespaceKey = csiParameterPrefix + "group-snapshotter-secret-namespace" // Prefixed namespace key for DeleteGroupSnapshot secret

PrefixedSnapshotterListSecretNameKey = csiParameterPrefix + "snapshotter-list-secret-name" // Prefixed name key for ListSnapshots secret
PrefixedSnapshotterListSecretNamespaceKey = csiParameterPrefix + "snapshotter-list-secret-namespace" // Prefixed namespace key for ListSnapshots secret

Expand Down Expand Up @@ -150,6 +153,12 @@ var SnapshotterSecretParams = secretParamsMap{
secretNamespaceKey: PrefixedSnapshotterSecretNamespaceKey,
}

var GroupSnapshotterSecretParams = secretParamsMap{
name: "GroupSnapshotter",
secretNameKey: PrefixedGroupSnapshotterSecretNameKey,
secretNamespaceKey: PrefixedGroupSnapshotterSecretNamespaceKey,
}

var SnapshotterListSecretParams = secretParamsMap{
name: "SnapshotterList",
secretNameKey: PrefixedSnapshotterListSecretNameKey,
Expand Down Expand Up @@ -376,6 +385,61 @@ func GetSecretReference(secretParams secretParamsMap, snapshotClassParams map[st
return ref, nil
}

// GetSecretReference for the group snapshot
func GetGroupSnapshotSecretReference(secretParams secretParamsMap, volumeGroupSnapshotClassParams map[string]string, groupSnapContentName string, volumeGroupSnapshot *crdv1alpha1.VolumeGroupSnapshot) (*v1.SecretReference, error) {
nameTemplate, namespaceTemplate, err := verifyAndGetSecretNameAndNamespaceTemplate(secretParams, volumeGroupSnapshotClassParams)
if err != nil {
return nil, fmt.Errorf("failed to get name and namespace template from params: %v", err)
}
if nameTemplate == "" && namespaceTemplate == "" {
return nil, nil
}

ref := &v1.SecretReference{}

// Secret namespace template can make use of the VolumeGroupSnapshotContent name, VolumeGroupSnapshot name or namespace.
// Note that neither of those things are under the control of the VolumeGroupSnapshot user.
namespaceParams := map[string]string{"volumegroupsnapshotcontent.name": groupSnapContentName}
// volume group snapshot may be nil when resolving create/delete volumegroupsnapshot secret names because the
// volume group snapshot may or may not exist at delete time
if volumeGroupSnapshot != nil {
namespaceParams["volumegroupsnapshot.namespace"] = volumeGroupSnapshot.Namespace
}

resolvedNamespace, err := resolveTemplate(namespaceTemplate, namespaceParams)
if err != nil {
return nil, fmt.Errorf("error resolving value %q: %v", namespaceTemplate, err)
}

if len(validation.IsDNS1123Label(resolvedNamespace)) > 0 {
if namespaceTemplate != resolvedNamespace {
return nil, fmt.Errorf("%q resolved to %q which is not a valid namespace name", namespaceTemplate, resolvedNamespace)
}
return nil, fmt.Errorf("%q is not a valid namespace name", namespaceTemplate)
}
ref.Namespace = resolvedNamespace

// Secret name template can make use of the VolumeGroupSnapshotContent name, VolumeGroupSnapshot name or namespace.
// Note that VolumeGroupSnapshot name and namespace are under the VolumeGroupSnapshot user's control.
nameParams := map[string]string{"volumegroupsnapshotcontent.name": groupSnapContentName}
if volumeGroupSnapshot != nil {
nameParams["volumegroupsnapshot.name"] = volumeGroupSnapshot.Name
nameParams["volumegroupsnapshot.namespace"] = volumeGroupSnapshot.Namespace
}
resolvedName, err := resolveTemplate(nameTemplate, nameParams)
if err != nil {
return nil, fmt.Errorf("error resolving value %q: %v", nameTemplate, err)
}
if len(validation.IsDNS1123Subdomain(resolvedName)) > 0 {
if nameTemplate != resolvedName {
return nil, fmt.Errorf("%q resolved to %q which is not a valid secret name", nameTemplate, resolvedName)
}
return nil, fmt.Errorf("%q is not a valid secret name", nameTemplate)
}
ref.Name = resolvedName
return ref, nil
}

// resolveTemplate resolves the template by checking if the value is missing for a key
func resolveTemplate(template string, params map[string]string) (string, error) {
missingParams := sets.NewString()
Expand Down