From 4c774a1070a0846af5f6638fefccc96bea2ec267 Mon Sep 17 00:00:00 2001 From: Benamar Mekhissi Date: Tue, 10 Sep 2024 09:52:47 -0400 Subject: [PATCH 1/3] Update Ramen to use latest CRD from external-snapshotter - Integrated the latest CRD from external-snapshotter. - Updated dependencies and relevant configuration files. - Changed VolumeSnapshotRefList in VolumeGroupSnapshotStatus to PVCVolumeSnapshotRefList, which allows to map a VolumeSnapshot to the application PVC. Signed-off-by: Benamar Mekhissi (cherry picked from commit 33c8a2a2211dc6ad0d605658e3627c29eb650012) --- cmd/main.go | 4 +- go.mod | 2 +- go.sum | 4 +- ...age.k8s.io_volumegroupsnapshotclasses.yaml | 3 +- ...t.storage.k8s.io_volumegroupsnapshots.yaml | 291 +++++++++--------- .../cephfscg/cephfscg_suite_test.go | 4 +- internal/controller/cephfscg/cghandler.go | 2 +- .../controller/cephfscg/cghandler_test.go | 4 +- .../replicationgroupdestination_test.go | 2 +- .../cephfscg/volumegroupsourcehandler.go | 99 ++---- .../cephfscg/volumegroupsourcehandler_test.go | 75 ++--- .../replicationgroupdestination_controller.go | 2 +- .../replicationgroupsource_controller.go | 2 +- internal/controller/suite_test.go | 4 +- internal/controller/util/cephfs_cg.go | 4 +- internal/controller/util/cephfs_cg_test.go | 4 +- internal/controller/util/misc.go | 22 +- internal/controller/util/pvcs_util.go | 12 + internal/controller/util/util_suite_test.go | 4 +- .../controller/volsync/volsync_suite_test.go | 2 +- internal/controller/volsync/vshandler.go | 2 +- internal/controller/volsync/vshandler_test.go | 2 +- internal/controller/vrg_volsync_test.go | 2 +- 23 files changed, 261 insertions(+), 291 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index b8c85fbc0..d804751e5 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -15,8 +15,8 @@ import ( volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" volrep "github.com/csi-addons/kubernetes-csi-addons/api/replication.storage/v1alpha1" - groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumegroupsnapshot/v1alpha1" - snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1" + snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" viewv1beta1 "github.com/stolostron/multicloud-operators-foundation/pkg/apis/view/v1beta1" plrv1 "github.com/stolostron/multicloud-operators-placementrule/pkg/apis/apps/v1" velero "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" diff --git a/go.mod b/go.mod index 486fc4895..533859bc0 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/csi-addons/kubernetes-csi-addons v0.8.1-0.20240822090723-89d4c5b45a32 github.com/go-logr/logr v1.4.2 github.com/google/uuid v1.6.0 - github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0 + github.com/kubernetes-csi/external-snapshotter/client/v8 v8.0.0 github.com/onsi/ginkgo/v2 v2.20.0 github.com/onsi/gomega v1.34.1 github.com/operator-framework/api v0.17.6 diff --git a/go.sum b/go.sum index 81868d081..91f30e863 100644 --- a/go.sum +++ b/go.sum @@ -196,8 +196,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kubernetes-csi/external-snapshotter/client/v6 v6.2.0 h1:cMM5AB37e9aRGjErygVT6EuBPB6s5a+l95OPERmSlVM= github.com/kubernetes-csi/external-snapshotter/client/v6 v6.2.0/go.mod h1:VQVLCPGDX5l6V5PezjlDXLa+SpCbWSVU7B16cFWVVeE= -github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0 h1:j3YK74myEQRxR/srciTpOrm221SAvz6J5OVWbyfeXFo= -github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0/go.mod h1:FlyYFe32mPxKEPaRXKNxfX576d1AoCzstYDoOOnyMA4= +github.com/kubernetes-csi/external-snapshotter/client/v8 v8.0.0 h1:mjQG0Vakr2h246kEDR85U8y8ZhPgT3bguTCajRa/jaw= +github.com/kubernetes-csi/external-snapshotter/client/v8 v8.0.0/go.mod h1:E3vdYxHj2C2q6qo8/Da4g7P+IcwqRZyy3gJBzYybV9Y= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= diff --git a/hack/test/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml b/hack/test/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml index f78126a55..a7d1b3de5 100644 --- a/hack/test/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml +++ b/hack/test/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml @@ -1,4 +1,3 @@ - --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -92,4 +91,4 @@ spec: type: object served: true storage: true - subresources: {} + subresources: {} \ No newline at end of file diff --git a/hack/test/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml b/hack/test/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml index d0d4d7907..8d7eaea61 100644 --- a/hack/test/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml +++ b/hack/test/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml @@ -3,9 +3,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/995" - controller-gen.kubebuilder.io/version: v0.12.0 - creationTimestamp: null + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1068" + controller-gen.kubebuilder.io/version: v0.15.0 name: volumegroupsnapshots.groupsnapshot.storage.k8s.io spec: group: groupsnapshot.storage.k8s.io @@ -47,215 +46,223 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: VolumeGroupSnapshot is a user's request for creating either a - point-in-time group snapshot or binding to a pre-existing group snapshot. + description: |- + VolumeGroupSnapshot is a user's request for creating either a point-in-time + group snapshot or binding to a pre-existing group snapshot. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: Spec defines the desired characteristics of a group snapshot - requested by a user. Required. + description: |- + Spec defines the desired characteristics of a group snapshot requested by a user. + Required. properties: source: - description: Source specifies where a group snapshot will be created - from. This field is immutable after creation. Required. + description: |- + Source specifies where a group snapshot will be created from. + This field is immutable after creation. + Required. properties: selector: - description: Selector is a label query over persistent volume - claims that are to be grouped together for snapshotting. This - labelSelector will be used to match the label added to a PVC. + description: |- + Selector is a label query over persistent volume claims that are to be + grouped together for snapshotting. + This labelSelector will be used to match the label added to a PVC. If the label is added or removed to a volume after a group snapshot is created, the existing group snapshots won't be modified. - Once a VolumeGroupSnapshotContent is created and the sidecar - starts to process it, the volume list will not change with retries. + Once a VolumeGroupSnapshotContent is created and the sidecar starts to process + it, the volume list will not change with retries. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that relates - the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, NotIn, - Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If - the operator is In or NotIn, the values array must - be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced - during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string - description: matchLabels is a map of {key,value} pairs. A - single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field is "key", - the operator is "In", and the values array contains only - "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic + x-kubernetes-validations: + - message: selector is immutable + rule: self == oldSelf volumeGroupSnapshotContentName: - description: VolumeGroupSnapshotContentName specifies the name - of a pre-existing VolumeGroupSnapshotContent object representing - an existing volume group snapshot. This field should be set - if the volume group snapshot already exists and only needs a - representation in Kubernetes. This field is immutable. + description: |- + VolumeGroupSnapshotContentName specifies the name of a pre-existing VolumeGroupSnapshotContent + object representing an existing volume group snapshot. + This field should be set if the volume group snapshot already exists and + only needs a representation in Kubernetes. + This field is immutable. type: string + x-kubernetes-validations: + - message: volumeGroupSnapshotContentName is immutable + rule: self == oldSelf type: object + x-kubernetes-validations: + - message: selector is required once set + rule: '!has(oldSelf.selector) || has(self.selector)' + - message: volumeGroupSnapshotContentName is required once set + rule: '!has(oldSelf.volumeGroupSnapshotContentName) || has(self.volumeGroupSnapshotContentName)' + - message: exactly one of selector and volumeGroupSnapshotContentName + must be set + rule: (has(self.selector) && !has(self.volumeGroupSnapshotContentName)) + || (!has(self.selector) && has(self.volumeGroupSnapshotContentName)) volumeGroupSnapshotClassName: - description: VolumeGroupSnapshotClassName is the name of the VolumeGroupSnapshotClass - requested by the VolumeGroupSnapshot. VolumeGroupSnapshotClassName - may be left nil to indicate that the default class will be used. + description: |- + VolumeGroupSnapshotClassName is the name of the VolumeGroupSnapshotClass + requested by the VolumeGroupSnapshot. + VolumeGroupSnapshotClassName may be left nil to indicate that the default + class will be used. Empty string is not allowed for this field. type: string + x-kubernetes-validations: + - message: volumeGroupSnapshotClassName must not be the empty string + when set + rule: size(self) > 0 required: - source type: object status: - description: Status represents the current information of a group snapshot. - Consumers must verify binding between VolumeGroupSnapshot and VolumeGroupSnapshotContent - objects is successful (by validating that both VolumeGroupSnapshot and - VolumeGroupSnapshotContent point to each other) before using this object. + description: |- + Status represents the current information of a group snapshot. + Consumers must verify binding between VolumeGroupSnapshot and + VolumeGroupSnapshotContent objects is successful (by validating that both + VolumeGroupSnapshot and VolumeGroupSnapshotContent point to each other) before + using this object. properties: boundVolumeGroupSnapshotContentName: - description: 'BoundVolumeGroupSnapshotContentName is the name of the - VolumeGroupSnapshotContent object to which this VolumeGroupSnapshot - object intends to bind to. If not specified, it indicates that the - VolumeGroupSnapshot object has not been successfully bound to a - VolumeGroupSnapshotContent object yet. NOTE: To avoid possible security - issues, consumers must verify binding between VolumeGroupSnapshot - and VolumeGroupSnapshotContent objects is successful (by validating - that both VolumeGroupSnapshot and VolumeGroupSnapshotContent point - at each other) before using this object.' + description: |- + BoundVolumeGroupSnapshotContentName is the name of the VolumeGroupSnapshotContent + object to which this VolumeGroupSnapshot object intends to bind to. + If not specified, it indicates that the VolumeGroupSnapshot object has not + been successfully bound to a VolumeGroupSnapshotContent object yet. + NOTE: To avoid possible security issues, consumers must verify binding between + VolumeGroupSnapshot and VolumeGroupSnapshotContent objects is successful + (by validating that both VolumeGroupSnapshot and VolumeGroupSnapshotContent + point at each other) before using this object. type: string creationTime: - description: CreationTime is the timestamp when the point-in-time - group snapshot is taken by the underlying storage system. If not - specified, it may indicate that the creation time of the group snapshot - is unknown. The format of this field is a Unix nanoseconds time - encoded as an int64. On Unix, the command date +%s%N returns the - current time in nanoseconds since 1970-01-01 00:00:00 UTC. + description: |- + CreationTime is the timestamp when the point-in-time group snapshot is taken + by the underlying storage system. + If not specified, it may indicate that the creation time of the group snapshot + is unknown. + The format of this field is a Unix nanoseconds time encoded as an int64. + On Unix, the command date +%s%N returns the current time in nanoseconds + since 1970-01-01 00:00:00 UTC. format: date-time type: string error: - description: Error is the last observed error during group snapshot - creation, if any. This field could be helpful to upper level controllers - (i.e., application controller) to decide whether they should continue - on waiting for the group snapshot to be created based on the type - of error reported. The snapshot controller will keep retrying when - an error occurs during the group snapshot creation. Upon success, - this error field will be cleared. + description: |- + Error is the last observed error during group snapshot creation, if any. + This field could be helpful to upper level controllers (i.e., application + controller) to decide whether they should continue on waiting for the group + snapshot to be created based on the type of error reported. + The snapshot controller will keep retrying when an error occurs during the + group snapshot creation. Upon success, this error field will be cleared. properties: message: - description: 'message is a string detailing the encountered error - during snapshot creation if specified. NOTE: message may be - logged, and it should not contain sensitive information.' + description: |- + message is a string detailing the encountered error during snapshot + creation if specified. + NOTE: message may be logged, and it should not contain sensitive + information. type: string time: description: time is the timestamp when the error was encountered. format: date-time type: string type: object - readyToUse: - description: ReadyToUse indicates if all the individual snapshots - in the group are ready to be used to restore a group of volumes. - ReadyToUse becomes true when ReadyToUse of all individual snapshots - become true. If not specified, it means the readiness of a group - snapshot is unknown. - type: boolean - volumeSnapshotRefList: - description: VolumeSnapshotRefList is the list of volume snapshot - references for this group snapshot. The maximum number of allowed - snapshots in the group is 100. + pvcVolumeSnapshotRefList: + description: |- + VolumeSnapshotRefList is the list of PVC and VolumeSnapshot pairs that + is part of this group snapshot. + The maximum number of allowed snapshots in the group is 100. items: - description: "ObjectReference contains enough information to let - you inspect or modify the referred object. --- New uses of this - type are discouraged because of difficulty describing its usage - when embedded in APIs. 1. Ignored fields. It includes many fields - which are not generally honored. For instance, ResourceVersion - and FieldPath are both very rarely valid in actual usage. 2. Invalid - usage help. It is impossible to add specific help for individual - usage. In most embedded usages, there are particular restrictions - like, \"must refer only to types A and B\" or \"UID not honored\" - or \"name must be restricted\". Those cannot be well described - when embedded. 3. Inconsistent validation. Because the usages - are different, the validation rules are different by usage, which - makes it hard for users to predict what will happen. 4. The fields - are both imprecise and overly precise. Kind is not a precise - mapping to a URL. This can produce ambiguity during interpretation - and require a REST mapping. In most cases, the dependency is - on the group,resource tuple and the version of the actual struct - is irrelevant. 5. We cannot easily change it. Because this type - is embedded in many locations, updates to this type will affect - numerous schemas. Don't make new APIs embed an underspecified - API type they do not control. \n Instead of using this type, create - a locally provided and used type that is well-focused on your - reference. For example, ServiceReferences for admission registration: - https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 - ." + description: PVCVolumeSnapshotPair defines a pair of a PVC reference + and a Volume Snapshot Reference properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: 'If referring to a piece of an object instead of - an entire object, this string should contain a valid JSON/Go - field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within - a pod, this would take on a value like: "spec.containers{name}" - (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" - (container with index 2 in this pod). This syntax is chosen - only to have some well-defined way of referencing a part of - an object. TODO: this design is not final and this field is - subject to change in the future.' - type: string - kind: - description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - namespace: - description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' - type: string - resourceVersion: - description: 'Specific resourceVersion to which this reference - is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' - type: string - uid: - description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' - type: string + persistentVolumeClaimRef: + description: PersistentVolumeClaimRef is a reference to the + PVC this pair is referring to + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid? + type: string + type: object + x-kubernetes-map-type: atomic + volumeSnapshotRef: + description: VolumeSnapshotRef is a reference to the VolumeSnapshot + this pair is referring to + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid? + type: string + type: object + x-kubernetes-map-type: atomic type: object - x-kubernetes-map-type: atomic type: array + readyToUse: + description: |- + ReadyToUse indicates if all the individual snapshots in the group are ready + to be used to restore a group of volumes. + ReadyToUse becomes true when ReadyToUse of all individual snapshots become true. + If not specified, it means the readiness of a group snapshot is unknown. + type: boolean type: object required: - spec diff --git a/internal/controller/cephfscg/cephfscg_suite_test.go b/internal/controller/cephfscg/cephfscg_suite_test.go index a11cb11da..ac01ece2e 100644 --- a/internal/controller/cephfscg/cephfscg_suite_test.go +++ b/internal/controller/cephfscg/cephfscg_suite_test.go @@ -9,8 +9,8 @@ import ( volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" "github.com/go-logr/logr" - groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumegroupsnapshot/v1alpha1" - snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1" + snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/format" diff --git a/internal/controller/cephfscg/cghandler.go b/internal/controller/cephfscg/cghandler.go index da8a72153..bf3ef0e94 100644 --- a/internal/controller/cephfscg/cghandler.go +++ b/internal/controller/cephfscg/cghandler.go @@ -6,7 +6,7 @@ import ( volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" "github.com/go-logr/logr" - snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" ramendrv1alpha1 "github.com/ramendr/ramen/api/v1alpha1" "github.com/ramendr/ramen/internal/controller/util" "github.com/ramendr/ramen/internal/controller/volsync" diff --git a/internal/controller/cephfscg/cghandler_test.go b/internal/controller/cephfscg/cghandler_test.go index e91a67691..cfa2228fb 100644 --- a/internal/controller/cephfscg/cghandler_test.go +++ b/internal/controller/cephfscg/cghandler_test.go @@ -4,8 +4,8 @@ import ( "context" volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" - groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumegroupsnapshot/v1alpha1" - vsv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1" + vsv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ramendrv1alpha1 "github.com/ramendr/ramen/api/v1alpha1" diff --git a/internal/controller/cephfscg/replicationgroupdestination_test.go b/internal/controller/cephfscg/replicationgroupdestination_test.go index 7a37882fe..8b8d67d93 100644 --- a/internal/controller/cephfscg/replicationgroupdestination_test.go +++ b/internal/controller/cephfscg/replicationgroupdestination_test.go @@ -6,7 +6,7 @@ import ( volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" "github.com/backube/volsync/controllers/statemachine" - snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" diff --git a/internal/controller/cephfscg/volumegroupsourcehandler.go b/internal/controller/cephfscg/volumegroupsourcehandler.go index 054379fee..a6d386148 100644 --- a/internal/controller/cephfscg/volumegroupsourcehandler.go +++ b/internal/controller/cephfscg/volumegroupsourcehandler.go @@ -7,8 +7,8 @@ import ( volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" "github.com/go-logr/logr" - vgsv1alphfa1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumegroupsnapshot/v1alpha1" - vsv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + vgsv1alphfa1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1" + vsv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" ramendrv1alpha1 "github.com/ramendr/ramen/api/v1alpha1" "github.com/ramendr/ramen/internal/controller/util" "github.com/ramendr/ramen/internal/controller/volsync" @@ -84,16 +84,18 @@ func NewVolumeGroupSourceHandler( ) VolumeGroupSourceHandler { vrgName := rgs.GetLabels()[volsync.VRGOwnerNameLabel] + vgsName := BuildVGSName(rgs.Name) + return &volumeGroupSourceHandler{ Client: client, - VolumeGroupSnapshotName: fmt.Sprintf(VolumeGroupSnapshotNameFormat, rgs.Name), + VolumeGroupSnapshotName: vgsName, VolumeGroupSnapshotNamespace: rgs.Namespace, VolumeGroupSnapshotClassName: rgs.Spec.VolumeGroupSnapshotClassName, VolumeGroupLabel: rgs.Spec.VolumeGroupSnapshotSource, VolsyncKeySecretName: volsync.GetVolSyncPSKSecretNameFromVRGName(vrgName), DefaultCephFSCSIDriverName: defaultCephFSCSIDriverName, Logger: logger.WithName("VolumeGroupSourceHandler"). - WithValues("VolumeGroupSnapshotName", fmt.Sprintf(VolumeGroupSnapshotNameFormat, rgs.Name)). + WithValues("VolumeGroupSnapshotName", vgsName). WithValues("VolumeGroupSnapshotNamespace", rgs.Namespace), } } @@ -166,20 +168,21 @@ func (h *volumeGroupSourceHandler) CleanVolumeGroupSnapshot( } if volumeGroupSnapshot.Status != nil { - for _, vsRef := range volumeGroupSnapshot.Status.VolumeSnapshotRefList { + for _, pvcVSRef := range volumeGroupSnapshot.Status.PVCVolumeSnapshotRefList { logger.Info("Get PVCName from volume snapshot", - "VolumeSnapshotName", vsRef.Name, "VolumeSnapshotNamespace", vsRef.Namespace) + "vsName", pvcVSRef.VolumeSnapshotRef.Name, "vsNamespace", volumeGroupSnapshot.Namespace) - pvc, err := GetPVCFromVolumeSnapshot(ctx, h.Client, vsRef.Name, vsRef.Namespace, volumeGroupSnapshot) + pvc, err := util.GetPVC(ctx, h.Client, + types.NamespacedName{Name: pvcVSRef.PersistentVolumeClaimRef.Name, Namespace: volumeGroupSnapshot.Namespace}) if err != nil { logger.Error(err, "Failed to get PVC name from volume snapshot", - "VolumeSnapshotName", vsRef.Name, "VolumeSnapshotNamespace", vsRef.Namespace) + "pvcName", pvcVSRef.PersistentVolumeClaimRef.Name, "vsNamespace", volumeGroupSnapshot.Namespace) return err } restoredPVCName := fmt.Sprintf(RestorePVCinCGNameFormat, pvc.Name) - restoredPVCNamespace := vsRef.Namespace + restoredPVCNamespace := pvc.Namespace logger.Info("Delete restored PVCs", "PVCName", restoredPVCName, "PVCNamespace", restoredPVCNamespace) @@ -229,28 +232,32 @@ func (h *volumeGroupSourceHandler) RestoreVolumesFromVolumeGroupSnapshot( restoredPVCs := []RestoredPVC{} - for _, vsRef := range volumeGroupSnapshot.Status.VolumeSnapshotRefList { + for _, pvcVSRef := range volumeGroupSnapshot.Status.PVCVolumeSnapshotRefList { logger.Info("Get PVCName from volume snapshot", - "VolumeSnapshotName", vsRef.Name, "VolumeSnapshotNamespace", vsRef.Namespace) + "PVCName", pvcVSRef.PersistentVolumeClaimRef.Name, "VolumeSnapshotName", pvcVSRef.VolumeSnapshotRef.Name) - pvc, err := GetPVCFromVolumeSnapshot(ctx, h.Client, vsRef.Name, vsRef.Namespace, volumeGroupSnapshot) + pvc, err := util.GetPVC(ctx, h.Client, + types.NamespacedName{Name: pvcVSRef.PersistentVolumeClaimRef.Name, Namespace: volumeGroupSnapshot.Namespace}) if err != nil { - return nil, fmt.Errorf("failed to get PVC name from volume snapshot %s: %w", vsRef.Namespace+"/"+vsRef.Name, err) + return nil, fmt.Errorf("failed to get PVC from VGS %s: %w", + volumeGroupSnapshot.Namespace+"/"+pvcVSRef.PersistentVolumeClaimRef.Name, err) } restoreStorageClass, err := GetRestoreStorageClass(ctx, h.Client, *pvc.Spec.StorageClassName, h.DefaultCephFSCSIDriverName) if err != nil { - return nil, fmt.Errorf("failed to get Restore Storage Class from PVC %s: %w", pvc.Name+"/"+vsRef.Namespace, err) + return nil, fmt.Errorf("failed to get Restore Storage Class from PVC %s: %w", pvc.Name+"/"+pvc.Namespace, err) } RestoredPVCNamespacedName := types.NamespacedName{ - Namespace: vsRef.Namespace, + Namespace: pvc.Namespace, Name: fmt.Sprintf(RestorePVCinCGNameFormat, pvc.Name), } if err := h.RestoreVolumesFromSnapshot( - ctx, vsRef, pvc, RestoredPVCNamespacedName, restoreStorageClass.GetName(), owner); err != nil { - return nil, fmt.Errorf("failed to restore volumes from snapshot %s: %w", vsRef.Name+"/"+vsRef.Namespace, err) + ctx, pvcVSRef.VolumeSnapshotRef.Name, pvc, RestoredPVCNamespacedName, + restoreStorageClass.GetName(), owner); err != nil { + return nil, fmt.Errorf("failed to restore volumes from snapshot %s: %w", + pvcVSRef.VolumeSnapshotRef.Name+"/"+pvc.Namespace, err) } logger.Info("Successfully restore volumes from snapshot", @@ -259,7 +266,7 @@ func (h *volumeGroupSourceHandler) RestoreVolumesFromVolumeGroupSnapshot( restoredPVCs = append(restoredPVCs, RestoredPVC{ SourcePVCName: pvc.Name, RestoredPVCName: RestoredPVCNamespacedName.Name, - VolumeSnapshotName: vsRef.Name, + VolumeSnapshotName: pvcVSRef.VolumeSnapshotRef.Name, }) } @@ -273,7 +280,7 @@ func (h *volumeGroupSourceHandler) RestoreVolumesFromVolumeGroupSnapshot( //nolint:funlen,gocognit,cyclop func (h *volumeGroupSourceHandler) RestoreVolumesFromSnapshot( ctx context.Context, - vsRef corev1.ObjectReference, + vsName string, pvc *corev1.PersistentVolumeClaim, restoredPVCNamespacedname types.NamespacedName, restoreStorageClassName string, @@ -285,13 +292,13 @@ func (h *volumeGroupSourceHandler) RestoreVolumesFromSnapshot( volumeSnapshot := &vsv1.VolumeSnapshot{} if err := h.Client.Get(ctx, - types.NamespacedName{Name: vsRef.Name, Namespace: vsRef.Namespace}, + types.NamespacedName{Name: vsName, Namespace: pvc.Namespace}, volumeSnapshot, ); err != nil { return fmt.Errorf("failed to get volume snapshot: %w", err) } - snapshotRef := corev1.TypedLocalObjectReference{Name: vsRef.Name, APIGroup: &SnapshotGroup, Kind: SnapshotGroupKind} + snapshotRef := corev1.TypedLocalObjectReference{Name: vsName, APIGroup: &SnapshotGroup, Kind: SnapshotGroupKind} restoredPVC := &corev1.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{ Name: restoredPVCNamespacedname.Name, @@ -502,56 +509,6 @@ var GetPVCFromVolumeSnapshot func( vsNamespace string, vgs *vgsv1alphfa1.VolumeGroupSnapshot, ) (*corev1.PersistentVolumeClaim, error) -func init() { - GetPVCFromVolumeSnapshot = FakeGetPVCFromVolumeSnapshot -} - -// TODO(wangyouhang): https://github.com/kubernetes-csi/external-snapshotter/issues/969 -// Fake func, need to be changed -func FakeGetPVCFromVolumeSnapshot( - ctx context.Context, k8sClient client.Client, vsName string, - vsNamespace string, vgs *vgsv1alphfa1.VolumeGroupSnapshot, -) (*corev1.PersistentVolumeClaim, error) { - if vgs.Status.BoundVolumeGroupSnapshotContentName == nil { - return nil, fmt.Errorf("BoundVolumeGroupSnapshotContentName is nil") - } - - // get vs index in vgs - var index int - - for i, VolumeSnapshotRef := range vgs.Status.VolumeSnapshotRefList { - if VolumeSnapshotRef.Name == vsName && VolumeSnapshotRef.Namespace == vsNamespace { - index = i - } - } - - // get storageHandle based on index - vgsc := &vgsv1alphfa1.VolumeGroupSnapshotContent{} - - err := k8sClient.Get(ctx, - types.NamespacedName{ - Name: *vgs.Status.BoundVolumeGroupSnapshotContentName, - Namespace: vgs.GetNamespace(), - }, - vgsc) - if err != nil { - return nil, err - } - - if len(vgs.Status.VolumeSnapshotRefList) != len(vgsc.Spec.Source.VolumeHandles) { - return nil, fmt.Errorf("len of vgs.Status.VolumeSnapshotRefList != len of vgsc.Spec.Source.VolumeHandles") - } - - storageHandle := vgsc.Spec.Source.VolumeHandles[index] - - pvc, err := GetPVCfromStorageHandle(ctx, k8sClient, storageHandle) - if err != nil { - return nil, fmt.Errorf("PVC is not found with storageHandle %s: %w", storageHandle, err) - } - - return pvc, nil -} - func GetPVCfromStorageHandle( ctx context.Context, k8sClient client.Client, diff --git a/internal/controller/cephfscg/volumegroupsourcehandler_test.go b/internal/controller/cephfscg/volumegroupsourcehandler_test.go index a3428688d..a3caefb7b 100644 --- a/internal/controller/cephfscg/volumegroupsourcehandler_test.go +++ b/internal/controller/cephfscg/volumegroupsourcehandler_test.go @@ -5,8 +5,8 @@ import ( "fmt" volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" - vgsv1alphfa1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumegroupsnapshot/v1alpha1" - snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + vgsv1alphfa1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1" + snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" @@ -25,6 +25,19 @@ import ( "github.com/ramendr/ramen/internal/controller/volsync" ) +var ( + vgsName = "vgs" + vgscName = "vgsc" + vsName = "vs" + anotherVSName = "another-vs" + vgsLabel = map[string]string{"test": "test"} + scName = "sc" + appPVCName = "apppvc" + anotherAppPVCName = "another-apppvc" + rsName = "rs" + manualString = "manual" +) + var _ = Describe("Volumegroupsourcehandler", func() { var volumeGroupSourceHandler cephfscg.VolumeGroupSourceHandler @@ -34,6 +47,9 @@ var _ = Describe("Volumegroupsourcehandler", func() { volumeGroupSourceHandler = cephfscg.NewVolumeGroupSourceHandler( k8sClient, rgs, internalController.DefaultCephFSCSIDriverName, testLogger, ) + + CreatePVC(appPVCName) + CreatePVC(anotherAppPVCName) }) Describe("CreateOrUpdateVolumeGroupSnapshot", func() { It("Should be successful", func() { @@ -69,11 +85,9 @@ var _ = Describe("Volumegroupsourcehandler", func() { }) Context("Restored PVC exist", func() { BeforeEach(func() { - EnableFakeGetPVCFromVolumeSnapshot() - err := volumeGroupSourceHandler.CreateOrUpdateVolumeGroupSnapshot(context.TODO(), rgs) Expect(err).To(BeNil()) - UpdateVGS(rgs, vsName) + UpdateVGS(rgs, vsName, appPVCName) CreateRestoredPVC(vsName) }) @@ -113,10 +127,9 @@ var _ = Describe("Volumegroupsourcehandler", func() { }) Context("VolumeGroupSnapshot is ready", func() { BeforeEach(func() { - EnableFakeGetPVCFromVolumeSnapshot() CreateStorageClass() - CreateVS(vsName + "0") - UpdateVGS(rgs, vsName+"0") + CreateVS(anotherVSName) + UpdateVGS(rgs, anotherVSName, anotherAppPVCName) }) It("Should be failed", func() { restoredPVCs, err := volumeGroupSourceHandler.RestoreVolumesFromVolumeGroupSnapshot(context.Background(), rgs) @@ -175,17 +188,6 @@ var _ = Describe("Volumegroupsourcehandler", func() { }) }) -var ( - vgsName = "vgs" - vgscName = "vgsc" - vsName = "vs" - vgsLabel = map[string]string{"test": "test"} - scName = "sc" - appPVCName = "apppvc" - rsName = "rs" - manualString = "manual" -) - func CreateRS(rsName string) { rs := &volsyncv1alpha1.ReplicationSource{ ObjectMeta: metav1.ObjectMeta{ @@ -244,32 +246,7 @@ func GenerateReplicationGroupSource( } } -func EnableFakeGetPVCFromVolumeSnapshot() { - cephfscg.GetPVCFromVolumeSnapshot = func( - ctx context.Context, k8sClient client.Client, vsName string, - vsNamespace string, vgs *vgsv1alphfa1.VolumeGroupSnapshot, - ) (*corev1.PersistentVolumeClaim, error) { - return &corev1.PersistentVolumeClaim{ - ObjectMeta: metav1.ObjectMeta{ - Name: vsName, - Namespace: vsNamespace, - }, - Spec: corev1.PersistentVolumeClaimSpec{ - StorageClassName: &scName, - Resources: corev1.VolumeResourceRequirements{ - Limits: map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceStorage: *resource.NewQuantity(1, resource.BinarySI), - }, - Requests: map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceStorage: *resource.NewQuantity(1, resource.BinarySI), - }, - }, - }, - }, nil - } -} - -func UpdateVGS(rgs *v1alpha1.ReplicationGroupSource, vsName string) { +func UpdateVGS(rgs *v1alpha1.ReplicationGroupSource, vsName, pvcName string) { retryErr := retry.RetryOnConflict(retry.DefaultBackoff, func() error { volumeGroupSnapshot := &vgsv1alphfa1.VolumeGroupSnapshot{} err := k8sClient.Get(context.TODO(), types.NamespacedName{ @@ -282,11 +259,9 @@ func UpdateVGS(rgs *v1alpha1.ReplicationGroupSource, vsName string) { ready := true volumeGroupSnapshot.Status = &vgsv1alphfa1.VolumeGroupSnapshotStatus{ ReadyToUse: &ready, - VolumeSnapshotRefList: []corev1.ObjectReference{{ - Name: vsName, - Namespace: "default", - Kind: "VolumeSnapshot", - APIVersion: "v1", + PVCVolumeSnapshotRefList: []vgsv1alphfa1.PVCVolumeSnapshotPair{{ + VolumeSnapshotRef: corev1.LocalObjectReference{Name: vsName}, + PersistentVolumeClaimRef: corev1.LocalObjectReference{Name: pvcName}, }}, } diff --git a/internal/controller/replicationgroupdestination_controller.go b/internal/controller/replicationgroupdestination_controller.go index cff0d5390..461ceabae 100644 --- a/internal/controller/replicationgroupdestination_controller.go +++ b/internal/controller/replicationgroupdestination_controller.go @@ -8,7 +8,7 @@ import ( volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" "github.com/backube/volsync/controllers/statemachine" - snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" ramendrv1alpha1 "github.com/ramendr/ramen/api/v1alpha1" "github.com/ramendr/ramen/internal/controller/cephfscg" "github.com/ramendr/ramen/internal/controller/util" diff --git a/internal/controller/replicationgroupsource_controller.go b/internal/controller/replicationgroupsource_controller.go index d92cc89fe..81e1abd54 100644 --- a/internal/controller/replicationgroupsource_controller.go +++ b/internal/controller/replicationgroupsource_controller.go @@ -7,7 +7,7 @@ import ( "context" "fmt" - vgsv1alphfa1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumegroupsnapshot/v1alpha1" + vgsv1alphfa1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1" corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/api/errors" diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go index cd91987c0..8b3527c9b 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -31,8 +31,8 @@ import ( volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" volrep "github.com/csi-addons/kubernetes-csi-addons/api/replication.storage/v1alpha1" - groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumegroupsnapshot/v1alpha1" - snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1" + snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" viewv1beta1 "github.com/stolostron/multicloud-operators-foundation/pkg/apis/view/v1beta1" plrv1 "github.com/stolostron/multicloud-operators-placementrule/pkg/apis/apps/v1" ocmclv1 "open-cluster-management.io/api/cluster/v1" diff --git a/internal/controller/util/cephfs_cg.go b/internal/controller/util/cephfs_cg.go index 2f7672631..2cceaced4 100644 --- a/internal/controller/util/cephfs_cg.go +++ b/internal/controller/util/cephfs_cg.go @@ -7,8 +7,8 @@ import ( volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" ramenutils "github.com/backube/volsync/controllers/utils" "github.com/go-logr/logr" - groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumegroupsnapshot/v1alpha1" - vsv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1" + vsv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" ramendrv1alpha1 "github.com/ramendr/ramen/api/v1alpha1" corev1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" diff --git a/internal/controller/util/cephfs_cg_test.go b/internal/controller/util/cephfs_cg_test.go index 5ee2635db..dd83e962c 100644 --- a/internal/controller/util/cephfs_cg_test.go +++ b/internal/controller/util/cephfs_cg_test.go @@ -5,8 +5,8 @@ import ( volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" ramenutils "github.com/backube/volsync/controllers/utils" - groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumegroupsnapshot/v1alpha1" - vsv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1" + vsv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/ramendr/ramen/api/v1alpha1" diff --git a/internal/controller/util/misc.go b/internal/controller/util/misc.go index cd152d502..8aca8315e 100644 --- a/internal/controller/util/misc.go +++ b/internal/controller/util/misc.go @@ -93,7 +93,7 @@ func AddLabel(obj client.Object, key, value string) bool { labels = map[string]string{} } - if _, ok := labels[key]; !ok { + if v, ok := labels[key]; !ok || v != value { labels[key] = value obj.SetLabels(labels) @@ -103,6 +103,26 @@ func AddLabel(obj client.Object, key, value string) bool { return !labelAdded } +func UpdateLabel(obj client.Object, key, newValue string) bool { + const labelUpdated = true + + labels := obj.GetLabels() + if labels == nil { + return !labelUpdated + } + + if currValue, ok := labels[key]; ok { + if currValue != newValue { + labels[key] = newValue + obj.SetLabels(labels) + + return labelUpdated + } + } + + return !labelUpdated +} + func HasLabel(obj client.Object, key string) bool { labels := obj.GetLabels() for k := range labels { diff --git a/internal/controller/util/pvcs_util.go b/internal/controller/util/pvcs_util.go index f4f513672..98ed4a1a6 100644 --- a/internal/controller/util/pvcs_util.go +++ b/internal/controller/util/pvcs_util.go @@ -230,6 +230,18 @@ func isPodReady(podConditions []corev1.PodCondition) bool { return false } +func GetPVC(ctx context.Context, k8sClient client.Client, pvcNamespacedName types.NamespacedName, +) (*corev1.PersistentVolumeClaim, error) { + pvc := &corev1.PersistentVolumeClaim{} + + err := k8sClient.Get(ctx, pvcNamespacedName, pvc) + if err != nil { + return nil, fmt.Errorf("%w", err) + } + + return pvc, nil +} + func DeletePVC(ctx context.Context, k8sClient client.Client, pvcName, namespace string, diff --git a/internal/controller/util/util_suite_test.go b/internal/controller/util/util_suite_test.go index 8d04be472..25bfa00db 100644 --- a/internal/controller/util/util_suite_test.go +++ b/internal/controller/util/util_suite_test.go @@ -12,8 +12,8 @@ import ( volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" "github.com/go-logr/logr" - groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumegroupsnapshot/v1alpha1" - snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + groupsnapv1alpha1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1" + snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/format" diff --git a/internal/controller/volsync/volsync_suite_test.go b/internal/controller/volsync/volsync_suite_test.go index 5f567aae4..cee30b858 100644 --- a/internal/controller/volsync/volsync_suite_test.go +++ b/internal/controller/volsync/volsync_suite_test.go @@ -13,7 +13,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" plrulev1 "github.com/stolostron/multicloud-operators-placementrule/pkg/apis/apps/v1" "go.uber.org/zap/zapcore" storagev1 "k8s.io/api/storage/v1" diff --git a/internal/controller/volsync/vshandler.go b/internal/controller/volsync/vshandler.go index a33cd7b1a..6457c9355 100644 --- a/internal/controller/volsync/vshandler.go +++ b/internal/controller/volsync/vshandler.go @@ -10,7 +10,7 @@ import ( "strings" "github.com/go-logr/logr" - snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" corev1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" diff --git a/internal/controller/volsync/vshandler_test.go b/internal/controller/volsync/vshandler_test.go index 9f9c00102..e9995845a 100644 --- a/internal/controller/volsync/vshandler_test.go +++ b/internal/controller/volsync/vshandler_test.go @@ -9,7 +9,7 @@ import ( "strings" "time" - snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" diff --git a/internal/controller/vrg_volsync_test.go b/internal/controller/vrg_volsync_test.go index ed24da430..783ad8a11 100644 --- a/internal/controller/vrg_volsync_test.go +++ b/internal/controller/vrg_volsync_test.go @@ -17,7 +17,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" - snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + snapv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" ramendrv1alpha1 "github.com/ramendr/ramen/api/v1alpha1" "github.com/ramendr/ramen/internal/controller/volsync" storagev1 "k8s.io/api/storage/v1" From b8d2c4eb7400111c6d731d7e950b926ac8a397e7 Mon Sep 17 00:00:00 2001 From: Benamar Mekhissi Date: Thu, 12 Sep 2024 06:57:31 -0400 Subject: [PATCH 2/3] Ensure VGS name contains at most 63 characters Signed-off-by: Benamar Mekhissi (cherry picked from commit 10e34bc9568709d315ecee6cddaf23a07c560709) --- internal/controller/cephfscg/cghandler.go | 4 ++-- internal/controller/cephfscg/volumegroupsourcehandler.go | 9 ++------- internal/controller/util/misc.go | 9 +++++++++ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/internal/controller/cephfscg/cghandler.go b/internal/controller/cephfscg/cghandler.go index bf3ef0e94..e778bd098 100644 --- a/internal/controller/cephfscg/cghandler.go +++ b/internal/controller/cephfscg/cghandler.go @@ -95,7 +95,7 @@ func (c *cgHandler) CreateOrUpdateReplicationGroupDestination( replicationGroupDestinationName, replicationGroupDestinationNamespace string, rdSpecsInGroup []ramendrv1alpha1.VolSyncReplicationDestinationSpec, ) (*ramendrv1alpha1.ReplicationGroupDestination, error) { - replicationGroupDestinationName += c.cgName + replicationGroupDestinationName = util.TrimToK8sResourceNameLength(replicationGroupDestinationName + c.cgName) log := c.logger.WithName("CreateOrUpdateReplicationGroupDestination"). WithValues("ReplicationGroupDestinationName", replicationGroupDestinationName, @@ -144,7 +144,7 @@ func (c *cgHandler) CreateOrUpdateReplicationGroupSource( replicationGroupSourceName, replicationGroupSourceNamespace string, runFinalSync bool, ) (*ramendrv1alpha1.ReplicationGroupSource, bool, error) { - replicationGroupSourceName += c.cgName + replicationGroupSourceName = util.TrimToK8sResourceNameLength(replicationGroupSourceName + c.cgName) log := c.logger.WithName("CreateOrUpdateReplicationGroupSource"). WithValues("ReplicationGroupSourceName", replicationGroupSourceName, diff --git a/internal/controller/cephfscg/volumegroupsourcehandler.go b/internal/controller/cephfscg/volumegroupsourcehandler.go index a6d386148..940b92e2c 100644 --- a/internal/controller/cephfscg/volumegroupsourcehandler.go +++ b/internal/controller/cephfscg/volumegroupsourcehandler.go @@ -84,7 +84,7 @@ func NewVolumeGroupSourceHandler( ) VolumeGroupSourceHandler { vrgName := rgs.GetLabels()[volsync.VRGOwnerNameLabel] - vgsName := BuildVGSName(rgs.Name) + vgsName := util.TrimToK8sResourceNameLength(fmt.Sprintf(VolumeGroupSnapshotNameFormat, rgs.Name)) return &volumeGroupSourceHandler{ Client: client, @@ -138,7 +138,7 @@ func (h *volumeGroupSourceHandler) CreateOrUpdateVolumeGroupSnapshot( return err } - logger.Info("VolumeGroupSnapshot successfully be created or updated", "operation", op) + logger.Info("VolumeGroupSnapshot successfully created or updated", "operation", op) return nil } @@ -504,11 +504,6 @@ func (h *volumeGroupSourceHandler) CheckReplicationSourceForRestoredPVCsComplete return true, nil } -var GetPVCFromVolumeSnapshot func( - ctx context.Context, k8sClient client.Client, vsName string, - vsNamespace string, vgs *vgsv1alphfa1.VolumeGroupSnapshot, -) (*corev1.PersistentVolumeClaim, error) - func GetPVCfromStorageHandle( ctx context.Context, k8sClient client.Client, diff --git a/internal/controller/util/misc.go b/internal/controller/util/misc.go index 8aca8315e..da2dab237 100644 --- a/internal/controller/util/misc.go +++ b/internal/controller/util/misc.go @@ -242,3 +242,12 @@ func IsCGEnabled(annotations map[string]string) bool { return annotations[IsCGEnabledAnnotation] == "true" } + +func TrimToK8sResourceNameLength(name string) string { + const maxLength = 63 + if len(name) > maxLength { + return name[:maxLength] + } + + return name +} From 714da8608f2e097b31febdfb19d022c7d6266923 Mon Sep 17 00:00:00 2001 From: Benamar Mekhissi Date: Thu, 12 Sep 2024 14:02:28 -0400 Subject: [PATCH 3/3] Ensure the Secondary VRG is updated when DRPC is updated This is mainly to ensure that the VRG on the primary and secondary are in sync in regards to labels and annotations Signed-off-by: Benamar Mekhissi (cherry picked from commit c24795046a19900ad34affb79480032bdb83cc6b) --- internal/controller/drplacementcontrolvolsync.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/controller/drplacementcontrolvolsync.go b/internal/controller/drplacementcontrolvolsync.go index 792fc8a1c..6e5b6624d 100644 --- a/internal/controller/drplacementcontrolvolsync.go +++ b/internal/controller/drplacementcontrolvolsync.go @@ -44,16 +44,16 @@ func (d *DRPCInstance) ensureVolSyncReplicationCommon(srcCluster string) error { // Make sure we have Source and Destination VRGs - Source should already have been created at this point d.setProgression(rmn.ProgressionEnsuringVolSyncSetup) + // Create or update the destination VRG + err := d.createVolSyncDestManifestWork(srcCluster) + if err != nil { + return err + } + vrgMWCount := d.mwu.GetVRGManifestWorkCount(rmnutil.DRPolicyClusterNames(d.drPolicy)) const maxNumberOfVRGs = 2 if len(d.vrgs) != maxNumberOfVRGs || vrgMWCount != maxNumberOfVRGs { - // Create the destination VRG - err := d.createVolSyncDestManifestWork(srcCluster) - if err != nil { - return err - } - return WaitForVolSyncManifestWorkCreation }