diff --git a/api/go.mod b/api/go.mod index e75c3fd8e..991e9da90 100644 --- a/api/go.mod +++ b/api/go.mod @@ -5,6 +5,7 @@ go 1.22.6 require ( k8s.io/api v0.29.0 k8s.io/apimachinery v0.29.0 + k8s.io/component-base v0.28.3 sigs.k8s.io/controller-runtime v0.16.3 ) @@ -19,7 +20,6 @@ require ( golang.org/x/text v0.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/component-base v0.28.3 // indirect k8s.io/klog/v2 v2.110.1 // indirect k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect 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 58eeb7c69..88bcae65c 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/csi-addons/kubernetes-csi-addons v0.9.1 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 d4f7a6b29..bb42267e2 100644 --- a/go.sum +++ b/go.sum @@ -200,8 +200,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..e778bd098 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" @@ -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/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..940b92e2c 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 := util.TrimToK8sResourceNameLength(fmt.Sprintf(VolumeGroupSnapshotNameFormat, 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), } } @@ -136,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 } @@ -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, @@ -497,61 +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 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/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 } 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 66ddc461b..a2e935ae7 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -32,8 +32,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..da2dab237 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 { @@ -222,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 +} 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" diff --git a/test/addons/volsync/test b/test/addons/volsync/test index d1f79b085..61c236b69 100755 --- a/test/addons/volsync/test +++ b/test/addons/volsync/test @@ -7,6 +7,8 @@ import json import os import sys +import yaml + import drenv from drenv import kubectl from drenv import subctl @@ -130,7 +132,7 @@ def run_replication(cluster): ) status = json.loads(out) print("Replication status:") - print(json.dumps(status, indent=2)) + print(yaml.dump(status)) def teardown(cluster1, cluster2): @@ -138,8 +140,13 @@ def teardown(cluster1, cluster2): Remove deployments from both clusters. This also deletes additonal resources created in the same namespace. """ - print("Cleaning up clusters") + print(f"Delete replication source in cluster '{cluster1}'") + kubectl.delete("--filename", "source/replication-src.yaml", context=cluster1) + + print(f"Unexporting volsync service in cluster '{cluster2}'") subctl.unexport("service", VOLSYNC_SERVICE, cluster2, namespace=NAMESPACE) + + print(f"Delete source in cluster '{cluster1}'") kubectl.delete( "--kustomize", "source", @@ -147,6 +154,8 @@ def teardown(cluster1, cluster2): "--wait=false", context=cluster1, ) + + print(f"Delete destination in cluster '{cluster2}'") kubectl.delete( "--kustomize", "destination", @@ -154,8 +163,12 @@ def teardown(cluster1, cluster2): "--wait=false", context=cluster2, ) - kubectl.delete("--kustomize", "source", "--ignore-not-found", context=cluster1) - kubectl.delete("--kustomize", "destination", "--ignore-not-found", context=cluster2) + + print(f"Waiting until namespace '{NAMESPACE}' is deleted in cluster '{cluster1}'") + kubectl.wait("ns", NAMESPACE, "--for=delete", "--timeout=120s", context=cluster1) + + print(f"Waiting until namespace '{NAMESPACE}' is deleted in cluster '{cluster2}'") + kubectl.wait("ns", NAMESPACE, "--for=delete", "--timeout=120s", context=cluster2) if len(sys.argv) != 3: diff --git a/test/envs/regional-dr.yaml b/test/envs/regional-dr.yaml index 89378e04d..a6f91e436 100644 --- a/test/envs/regional-dr.yaml +++ b/test/envs/regional-dr.yaml @@ -16,6 +16,10 @@ templates: - name: "dr-cluster" driver: "$vm" container_runtime: containerd + containerd: + plugins: + io.containerd.grpc.v1.cri: + device_ownership_from_security_context: true network: "$network" cpus: 4 memory: "6g"