Skip to content

Commit c3a6a36

Browse files
Merge pull request #2155 from jsafrane/4.18-add-groupsnapshot
OCPBUGS-45214: Add groupsnapshot tests
2 parents 0d5e184 + 613b73f commit c3a6a36

11 files changed

+115
-134
lines changed

openshift-hack/e2e/annotate/generated/zz_generated.annotations.go

+19-19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

openshift-hack/e2e/annotate/rules.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ var (
2626
`\[Feature:RelaxedDNSSearchValidation\]`,
2727
`\[Feature:PodLogsQuerySplitStreams\]`,
2828
`\[Feature:PodLifecycleSleepActionAllowZero\]`,
29+
`\[Feature:volumegroupsnapshot\]`, // disabled Beta
30+
2931
},
3032
// tests for features that are not implemented in openshift
3133
"[Disabled:Unimplemented]": {
@@ -169,10 +171,6 @@ var (
169171
// https://issues.redhat.com/browse/OCPBUGS-17194
170172
`\[sig-node\] ImageCredentialProvider \[Feature:KubeletCredentialProviders\] should be able to create pod with image credentials fetched from external credential provider`,
171173

172-
// https://issues.redhat.com/browse/OCPBUGS-45214
173-
// Even though this feature is not GA in k/k, it will be GA in OCP 4.19, so we should fix it and unskip this test
174-
`\[Feature:volumegroupsnapshot\]`,
175-
176174
// https://issues.redhat.com/browse/OCPBUGS-45273
177175
`\[sig-network\] Services should implement NodePort and HealthCheckNodePort correctly when ExternalTrafficPolicy changes`,
178176

test/e2e/storage/framework/volume_group_snapshot_resource.go

+19-12
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
"fmt"
2222

2323
"github.com/onsi/ginkgo/v2"
24-
24+
"github.com/onsi/gomega"
2525
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2626
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2727
"k8s.io/kubernetes/test/e2e/framework"
@@ -56,15 +56,15 @@ type VolumeGroupSnapshotResource struct {
5656
Config *PerTestConfig
5757
Pattern TestPattern
5858

59-
Vgs *unstructured.Unstructured
60-
Vgscontent *unstructured.Unstructured
61-
Vgsclass *unstructured.Unstructured
59+
VGS *unstructured.Unstructured
60+
VGSContent *unstructured.Unstructured
61+
VGSClass *unstructured.Unstructured
6262
}
6363

6464
// CreateVolumeGroupSnapshot creates a VolumeGroupSnapshotClass with given SnapshotDeletionPolicy and a VolumeGroupSnapshot
6565
// from the VolumeGroupSnapshotClass using a dynamic client.
6666
// Returns the unstructured VolumeGroupSnapshotClass and VolumeGroupSnapshot objects.
67-
func CreateVolumeGroupSnapshot(ctx context.Context, sDriver VoulmeGroupSnapshottableTestDriver, config *PerTestConfig, pattern TestPattern, groupName string, pvcNamespace string, timeouts *framework.TimeoutContext, parameters map[string]string) (*unstructured.Unstructured, *unstructured.Unstructured) {
67+
func CreateVolumeGroupSnapshot(ctx context.Context, sDriver VoulmeGroupSnapshottableTestDriver, config *PerTestConfig, pattern TestPattern, groupName string, pvcNamespace string, timeouts *framework.TimeoutContext, parameters map[string]string) (*unstructured.Unstructured, *unstructured.Unstructured, *unstructured.Unstructured) {
6868
defer ginkgo.GinkgoRecover()
6969
var err error
7070
if pattern.SnapshotType != VolumeGroupSnapshot {
@@ -99,28 +99,35 @@ func CreateVolumeGroupSnapshot(ctx context.Context, sDriver VoulmeGroupSnapshott
9999
ginkgo.By("Getting group snapshot and content")
100100
volumeGroupSnapshot, err = dc.Resource(utils.VolumeGroupSnapshotGVR).Namespace(volumeGroupSnapshot.GetNamespace()).Get(ctx, volumeGroupSnapshot.GetName(), metav1.GetOptions{})
101101
framework.ExpectNoError(err, "Failed to get volume group snapshot after creation")
102-
103-
return gsclass, volumeGroupSnapshot
102+
status := volumeGroupSnapshot.Object["status"]
103+
err = framework.Gomega().Expect(status).NotTo(gomega.BeNil())
104+
framework.ExpectNoError(err, "Failed to get status of volume group snapshot")
105+
vgscName := status.(map[string]interface{})["boundVolumeGroupSnapshotContentName"].(string)
106+
err = framework.Gomega().Expect(vgscName).NotTo(gomega.BeNil())
107+
framework.ExpectNoError(err, "Failed to get content name of volume group snapshot")
108+
vgsc, err := dc.Resource(utils.VolumeGroupSnapshotContentGVR).Get(ctx, vgscName, metav1.GetOptions{})
109+
framework.ExpectNoError(err, "failed to get content of group snapshot")
110+
return gsclass, volumeGroupSnapshot, vgsc
104111
}
105112

106113
// CleanupResource deletes the VolumeGroupSnapshotClass and VolumeGroupSnapshot objects using a dynamic client.
107114
func (r *VolumeGroupSnapshotResource) CleanupResource(ctx context.Context, timeouts *framework.TimeoutContext) error {
108115
defer ginkgo.GinkgoRecover()
109116
dc := r.Config.Framework.DynamicClient
110-
err := dc.Resource(utils.VolumeGroupSnapshotClassGVR).Delete(ctx, r.Vgsclass.GetName(), metav1.DeleteOptions{})
117+
err := dc.Resource(utils.VolumeGroupSnapshotClassGVR).Delete(ctx, r.VGSClass.GetName(), metav1.DeleteOptions{})
111118
framework.ExpectNoError(err, "Failed to delete volume group snapshot class")
112119
return nil
113120
}
114121

115122
// CreateVolumeGroupSnapshotResource creates a VolumeGroupSnapshotResource object with the given parameters.
116123
func CreateVolumeGroupSnapshotResource(ctx context.Context, sDriver VoulmeGroupSnapshottableTestDriver, config *PerTestConfig, pattern TestPattern, pvcName string, pvcNamespace string, timeouts *framework.TimeoutContext, parameters map[string]string) *VolumeGroupSnapshotResource {
117-
vgsclass, snapshot := CreateVolumeGroupSnapshot(ctx, sDriver, config, pattern, pvcName, pvcNamespace, timeouts, parameters)
124+
vgsClass, snapshot, vgsc := CreateVolumeGroupSnapshot(ctx, sDriver, config, pattern, pvcName, pvcNamespace, timeouts, parameters)
118125
vgs := &VolumeGroupSnapshotResource{
119126
Config: config,
120127
Pattern: pattern,
121-
Vgs: snapshot,
122-
Vgsclass: vgsclass,
123-
Vgscontent: nil,
128+
VGS: snapshot,
129+
VGSClass: vgsClass,
130+
VGSContent: vgsc,
124131
}
125132
return vgs
126133
}

test/e2e/storage/testsuites/volume_group_snapshottable.go

+23-8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ package testsuites
1818

1919
import (
2020
"context"
21+
"crypto/sha256"
22+
"fmt"
2123

2224
"github.com/onsi/ginkgo/v2"
2325
"github.com/onsi/gomega"
@@ -176,18 +178,30 @@ func (s *VolumeGroupSnapshottableTestSuite) DefineTests(driver storageframework.
176178
snapshot := storageframework.CreateVolumeGroupSnapshotResource(ctx, snapshottableDriver, groupTest.config, pattern, labelValue, groupTest.volumeGroup[0][0].Pvc.GetNamespace(), f.Timeouts, map[string]string{"deletionPolicy": pattern.SnapshotDeletionPolicy.String()})
177179
groupTest.snapshots = append(groupTest.snapshots, snapshot)
178180
ginkgo.By("verifying the snapshots in the group are ready to use")
179-
status := snapshot.Vgs.Object["status"]
181+
status := snapshot.VGS.Object["status"]
180182
err := framework.Gomega().Expect(status).NotTo(gomega.BeNil())
181183
framework.ExpectNoError(err, "failed to get status of group snapshot")
182-
volumes := status.(map[string]interface{})["pvcVolumeSnapshotRefList"]
183-
err = framework.Gomega().Expect(volumes).NotTo(gomega.BeNil())
184+
185+
volumeListMap := snapshot.VGSContent.Object["status"].(map[string]interface{})
186+
err = framework.Gomega().Expect(volumeListMap).NotTo(gomega.BeNil())
187+
framework.ExpectNoError(err, "failed to get volume snapshot list")
188+
volumeSnapshotHandlePairList := volumeListMap["volumeSnapshotHandlePairList"].([]interface{})
189+
err = framework.Gomega().Expect(volumeSnapshotHandlePairList).NotTo(gomega.BeNil())
184190
framework.ExpectNoError(err, "failed to get volume snapshot list")
185-
volumeList := volumes.([]interface{})
186-
err = framework.Gomega().Expect(len(volumeList)).To(gomega.Equal(groupTest.numVolumes))
191+
err = framework.Gomega().Expect(len(volumeSnapshotHandlePairList)).To(gomega.Equal(groupTest.numVolumes))
187192
framework.ExpectNoError(err, "failed to get volume snapshot list")
188193
claimSize := groupTest.volumeGroup[0][0].Pvc.Spec.Resources.Requests.Storage().String()
189-
for _, volume := range volumeList {
194+
for _, volume := range volumeSnapshotHandlePairList {
190195
// Create a PVC from the snapshot
196+
volumeHandle := volume.(map[string]interface{})["volumeHandle"].(string)
197+
err = framework.Gomega().Expect(volumeHandle).NotTo(gomega.BeNil())
198+
framework.ExpectNoError(err, "failed to get volume handle from volume")
199+
uid := snapshot.VGSContent.Object["metadata"].(map[string]interface{})["uid"].(string)
200+
err = framework.Gomega().Expect(uid).NotTo(gomega.BeNil())
201+
framework.ExpectNoError(err, "failed to get uuid from content")
202+
volumeSnapshotName := fmt.Sprintf("snapshot-%x", sha256.Sum256([]byte(
203+
uid+volumeHandle)))
204+
191205
pvc := e2epv.MakePersistentVolumeClaim(e2epv.PersistentVolumeClaimConfig{
192206
StorageClassName: &groupTest.volumeGroup[0][0].Sc.Name,
193207
ClaimSize: claimSize,
@@ -198,7 +212,7 @@ func (s *VolumeGroupSnapshottableTestSuite) DefineTests(driver storageframework.
198212
pvc.Spec.DataSource = &v1.TypedLocalObjectReference{
199213
APIGroup: &group,
200214
Kind: "VolumeSnapshot",
201-
Name: volume.(map[string]interface{})["volumeSnapshotRef"].(map[string]interface{})["name"].(string),
215+
Name: volumeSnapshotName,
202216
}
203217

204218
volSrc := v1.VolumeSource{
@@ -208,8 +222,9 @@ func (s *VolumeGroupSnapshottableTestSuite) DefineTests(driver storageframework.
208222
},
209223
},
210224
}
211-
pvc, err := cs.CoreV1().PersistentVolumeClaims(f.Namespace.Name).Create(ctx, pvc, metav1.CreateOptions{})
225+
pvc, err = cs.CoreV1().PersistentVolumeClaims(f.Namespace.Name).Create(ctx, pvc, metav1.CreateOptions{})
212226
framework.ExpectNoError(err, "failed to create PVC from snapshot")
227+
213228
pod := StartInPodWithVolumeSource(ctx, cs, volSrc, pvc.Namespace, "snapshot-pod", "sleep 300", groupTest.config.ClientNodeSelection)
214229
ginkgo.DeferCleanup(e2epod.DeletePodWithWait, cs, pod)
215230
framework.ExpectNoError(e2epod.WaitTimeoutForPodRunningInNamespace(ctx, cs, pod.Name, pod.Namespace, f.Timeouts.PodStartSlow), "Pod did not start in expected time")

test/e2e/storage/utils/volume_group_snapshot.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,16 @@ const (
3333
// VolumeGroupSnapshot is the group snapshot api
3434
VolumeGroupSnapshotAPIGroup = "groupsnapshot.storage.k8s.io"
3535
// VolumeGroupSnapshotAPIVersion is the group snapshot api version
36-
VolumeGroupSnapshotAPIVersion = "groupsnapshot.storage.k8s.io/v1alpha1"
36+
VolumeGroupSnapshotAPIVersion = "groupsnapshot.storage.k8s.io/v1beta1"
3737
)
3838

3939
var (
4040

4141
// VolumeGroupSnapshotGVR is GroupVersionResource for volumegroupsnapshots
42-
VolumeGroupSnapshotGVR = schema.GroupVersionResource{Group: VolumeGroupSnapshotAPIGroup, Version: "v1alpha1", Resource: "volumegroupsnapshots"}
42+
VolumeGroupSnapshotGVR = schema.GroupVersionResource{Group: VolumeGroupSnapshotAPIGroup, Version: "v1beta1", Resource: "volumegroupsnapshots"}
4343
// VolumeGroupSnapshotClassGVR is GroupVersionResource for volumegroupsnapshotsclasses
44-
VolumeGroupSnapshotClassGVR = schema.GroupVersionResource{Group: VolumeGroupSnapshotAPIGroup, Version: "v1alpha1", Resource: "volumegroupsnapshotclasses"}
44+
VolumeGroupSnapshotClassGVR = schema.GroupVersionResource{Group: VolumeGroupSnapshotAPIGroup, Version: "v1beta1", Resource: "volumegroupsnapshotclasses"}
45+
VolumeGroupSnapshotContentGVR = schema.GroupVersionResource{Group: VolumeGroupSnapshotAPIGroup, Version: "v1beta1", Resource: "volumegroupsnapshotcontents"}
4546
)
4647

4748
// WaitForVolumeGroupSnapshotReady waits for a VolumeGroupSnapshot to be ready to use or until timeout occurs, whichever comes first.

test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/814"
6+
api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1150"
77
controller-gen.kubebuilder.io/version: v0.15.0
88
name: volumegroupsnapshotclasses.groupsnapshot.storage.k8s.io
99
spec:
@@ -31,7 +31,7 @@ spec:
3131
- jsonPath: .metadata.creationTimestamp
3232
name: Age
3333
type: date
34-
name: v1alpha1
34+
name: v1beta1
3535
schema:
3636
openAPIV3Schema:
3737
description: |-

test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshotcontents.yaml

+31-42
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1068"
6+
api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1150"
77
controller-gen.kubebuilder.io/version: v0.15.0
88
name: volumegroupsnapshotcontents.groupsnapshot.storage.k8s.io
99
spec:
@@ -53,7 +53,7 @@ spec:
5353
- jsonPath: .metadata.creationTimestamp
5454
name: Age
5555
type: date
56-
name: v1alpha1
56+
name: v1beta1
5757
schema:
5858
openAPIV3Schema:
5959
description: |-
@@ -237,8 +237,6 @@ spec:
237237
- message: both volumeGroupSnapshotRef.name and volumeGroupSnapshotRef.namespace
238238
must be set
239239
rule: has(self.name) && has(self.__namespace__)
240-
- message: volumeGroupSnapshotRef is immutable
241-
rule: self == oldSelf
242240
required:
243241
- deletionPolicy
244242
- driver
@@ -257,8 +255,9 @@ spec:
257255
The format of this field is a Unix nanoseconds time encoded as an int64.
258256
On Unix, the command date +%s%N returns the current time in nanoseconds
259257
since 1970-01-01 00:00:00 UTC.
260-
format: int64
261-
type: integer
258+
This field is the source for the CreationTime field in VolumeGroupSnapshotStatus
259+
format: date-time
260+
type: string
262261
error:
263262
description: |-
264263
Error is the last observed error during group snapshot creation, if any.
@@ -276,42 +275,6 @@ spec:
276275
format: date-time
277276
type: string
278277
type: object
279-
pvVolumeSnapshotContentList:
280-
description: |-
281-
PVVolumeSnapshotContentList is the list of pairs of PV and
282-
VolumeSnapshotContent for this group snapshot
283-
The maximum number of allowed snapshots in the group is 100.
284-
items:
285-
description: |-
286-
PVVolumeSnapshotContentPair represent a pair of PV names and
287-
VolumeSnapshotContent names
288-
properties:
289-
persistentVolumeRef:
290-
description: PersistentVolumeRef is a reference to the persistent
291-
volume resource
292-
properties:
293-
name:
294-
description: |-
295-
Name of the referent.
296-
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
297-
TODO: Add other useful fields. apiVersion, kind, uid?
298-
type: string
299-
type: object
300-
x-kubernetes-map-type: atomic
301-
volumeSnapshotContentRef:
302-
description: VolumeSnapshotContentRef is a reference to the
303-
volume snapshot content resource
304-
properties:
305-
name:
306-
description: |-
307-
Name of the referent.
308-
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
309-
TODO: Add other useful fields. apiVersion, kind, uid?
310-
type: string
311-
type: object
312-
x-kubernetes-map-type: atomic
313-
type: object
314-
type: array
315278
readyToUse:
316279
description: |-
317280
ReadyToUse indicates if all the individual snapshots in the group are ready to be
@@ -325,6 +288,32 @@ spec:
325288
If a storage system does not provide such an id, the
326289
CSI driver can choose to return the VolumeGroupSnapshot name.
327290
type: string
291+
volumeSnapshotHandlePairList:
292+
description: |-
293+
VolumeSnapshotHandlePairList is a list of CSI "volume_id" and "snapshot_id"
294+
pair returned by the CSI driver to identify snapshots and their source volumes
295+
on the storage system.
296+
items:
297+
description: VolumeSnapshotHandlePair defines a pair of a source
298+
volume handle and a snapshot handle
299+
properties:
300+
snapshotHandle:
301+
description: |-
302+
SnapshotHandle is a unique id returned by the CSI driver to identify a volume
303+
snapshot on the storage system
304+
Required.
305+
type: string
306+
volumeHandle:
307+
description: |-
308+
VolumeHandle is a unique id returned by the CSI driver to identify a volume
309+
on the storage system
310+
Required.
311+
type: string
312+
required:
313+
- snapshotHandle
314+
- volumeHandle
315+
type: object
316+
type: array
328317
type: object
329318
required:
330319
- spec

test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml

+3-37
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1068"
6+
api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1150"
77
controller-gen.kubebuilder.io/version: v0.15.0
88
name: volumegroupsnapshots.groupsnapshot.storage.k8s.io
99
spec:
@@ -43,7 +43,7 @@ spec:
4343
- jsonPath: .metadata.creationTimestamp
4444
name: Age
4545
type: date
46-
name: v1alpha1
46+
name: v1beta1
4747
schema:
4848
openAPIV3Schema:
4949
description: |-
@@ -198,6 +198,7 @@ spec:
198198
The format of this field is a Unix nanoseconds time encoded as an int64.
199199
On Unix, the command date +%s%N returns the current time in nanoseconds
200200
since 1970-01-01 00:00:00 UTC.
201+
This field is updated based on the CreationTime field in VolumeGroupSnapshotContentStatus
201202
format: date-time
202203
type: string
203204
error:
@@ -221,41 +222,6 @@ spec:
221222
format: date-time
222223
type: string
223224
type: object
224-
pvcVolumeSnapshotRefList:
225-
description: |-
226-
VolumeSnapshotRefList is the list of PVC and VolumeSnapshot pairs that
227-
is part of this group snapshot.
228-
The maximum number of allowed snapshots in the group is 100.
229-
items:
230-
description: PVCVolumeSnapshotPair defines a pair of a PVC reference
231-
and a Volume Snapshot Reference
232-
properties:
233-
persistentVolumeClaimRef:
234-
description: PersistentVolumeClaimRef is a reference to the
235-
PVC this pair is referring to
236-
properties:
237-
name:
238-
description: |-
239-
Name of the referent.
240-
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
241-
TODO: Add other useful fields. apiVersion, kind, uid?
242-
type: string
243-
type: object
244-
x-kubernetes-map-type: atomic
245-
volumeSnapshotRef:
246-
description: VolumeSnapshotRef is a reference to the VolumeSnapshot
247-
this pair is referring to
248-
properties:
249-
name:
250-
description: |-
251-
Name of the referent.
252-
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
253-
TODO: Add other useful fields. apiVersion, kind, uid?
254-
type: string
255-
type: object
256-
x-kubernetes-map-type: atomic
257-
type: object
258-
type: array
259225
readyToUse:
260226
description: |-
261227
ReadyToUse indicates if all the individual snapshots in the group are ready

0 commit comments

Comments
 (0)