-
Notifications
You must be signed in to change notification settings - Fork 15
OSASINFRA-4468: add test for appendVolumeMetadata support in Cinder CSI #318
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,3 +13,4 @@ | |
|
|
||
| /_output | ||
| /openstack-tests | ||
| /bin | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,11 +2,13 @@ package openstack | |
|
|
||
| import ( | ||
| "context" | ||
| "encoding/json" | ||
| "fmt" | ||
| "strconv" | ||
| "strings" | ||
| "time" | ||
|
|
||
| "github.com/Masterminds/semver" | ||
| "github.com/gophercloud/gophercloud/v2" | ||
| "github.com/gophercloud/gophercloud/v2/openstack" | ||
| "github.com/gophercloud/gophercloud/v2/openstack/blockstorage/v3/volumes" | ||
|
|
@@ -18,6 +20,7 @@ import ( | |
| "github.com/stretchr/objx" | ||
| yaml "gopkg.in/yaml.v3" | ||
| v1 "k8s.io/api/core/v1" | ||
| storagev1 "k8s.io/api/storage/v1" | ||
| "k8s.io/apimachinery/pkg/api/errors" | ||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| "k8s.io/apimachinery/pkg/runtime/schema" | ||
|
|
@@ -320,6 +323,77 @@ var _ = g.Describe("[OTP][sig-installer][Suite:openshift/openstack] The OpenStac | |
| o.Expect(out).To(o.Equal(fileContent)) | ||
|
|
||
| }) | ||
|
|
||
| g.It("should create a cinder volume with specified metadata when using cinder storage class with appendVolumeMetadata", func(ctx g.SpecContext) { | ||
| constraint, err := semver.NewConstraint(">=5.1.0-0") | ||
| o.Expect(err).Should(o.BeNil()) | ||
|
|
||
| cv, err := oc.AdminConfigClient().ConfigV1().ClusterVersions().Get(ctx, "version", metav1.GetOptions{}) | ||
| o.Expect(err).Should(o.BeNil()) | ||
|
|
||
| o.Expect(len(cv.Status.History)).ShouldNot(o.BeZero()) | ||
|
|
||
| latestVer, err := semver.NewVersion(cv.Status.History[0].Version) | ||
| o.Expect(err).Should(o.BeNil()) | ||
|
|
||
| available, errs := constraint.Validate(latestVer) | ||
| o.Expect(len(errs)).Should(o.BeZero()) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This fails the test on older clusters instead of skipping it. Constraints.Validate (vendored Masterminds/semver) returns available=false AND a non-empty errs whenever the version does not satisfy >=5.1.0-0. So on exactly the clusters we intend to skip, this assertion fails before the Skipf on line 343 is ever reached — the skip branch is unreachable. Suggest gating on the boolean only and dropping the errs assertion: if !constraint.Check(latestVer) { errs is just the why-not detail, not an error condition to assert against. |
||
|
|
||
| if !available { | ||
| e2eskipper.Skipf("appendVolumeMetadata is only available on >= 5.1.0") | ||
| } | ||
|
|
||
| metadata := map[string]string{ | ||
| "environment": "production", | ||
| "team": "storage", | ||
| } | ||
|
|
||
| metadataStr, err := json.Marshal(metadata) | ||
| o.Expect(err).Should(o.BeNil()) | ||
|
|
||
| g.By("creating a storage class with appendVolumeMetadata specified") | ||
| sc := &storagev1.StorageClass{ | ||
| Provisioner: "cinder.csi.openstack.org", | ||
| Parameters: map[string]string{ | ||
| "appendVolumeMetadata": string(metadataStr), | ||
| }, | ||
| } | ||
| sc.GenerateName = "cinder-csi-metadata-" | ||
|
|
||
| sc, err = clientSet.StorageV1().StorageClasses().Create(ctx, sc, metav1.CreateOptions{}) | ||
| o.Expect(err).Should(o.BeNil()) | ||
|
|
||
| g.DeferCleanup(func(ctx g.SpecContext) { | ||
| o.Expect(clientSet.StorageV1().StorageClasses().Delete(ctx, sc.Name, metav1.DeleteOptions{})).Should(o.BeNil()) | ||
| }) | ||
|
|
||
| g.By("creating a persistent volume claim referencing the storage class") | ||
| ns := oc.Namespace() | ||
| pvc := CreatePVC(ctx, clientSet, "pvc-cinder-metadata", ns, sc.Name, "1Gi") | ||
| g.DeferCleanup(func(ctx g.SpecContext) { | ||
| o.Expect(clientSet.CoreV1().PersistentVolumeClaims(pvc.Namespace).Delete(ctx, pvc.Name, metav1.DeleteOptions{})).Should(o.BeNil()) | ||
| }) | ||
|
|
||
| pvcName, err := waitPvcVolume(ctx, clientSet, pvc.Name, ns) | ||
| o.Expect(err).Should(o.BeNil()) | ||
|
|
||
| g.By("fetching the volume created for the PVC") | ||
| vols, err := getVolumesFromName(ctx, volumeClient, pvcName) | ||
| o.Expect(err).Should(o.BeNil()) | ||
| o.Expect(len(vols)).Should(o.Equal(1)) | ||
|
|
||
| g.By("validating specified metadata exists in the provisioned volume") | ||
| volMetadata := vols[0].Metadata | ||
| e2e.Logf("volume metadata %q", volMetadata) | ||
| for k, v := range metadata { | ||
| v1, ok := volMetadata[k] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: v1 shadows the v1 "k8s.io/api/core/v1" import. It compiles fine since the package isn't referenced in this block, but renaming (e.g. got) reads more clearly. |
||
| if !ok { | ||
| e2e.Failf("metadata (%s:%s) not found on the volume", k, v) | ||
| } else if v1 != v { | ||
| e2e.Failf("metadata (%s:%s) expected but found (%s:%s)", k, v, k, v1) | ||
| } | ||
| } | ||
| }) | ||
| }) | ||
| }) | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
History[0] is the most recent entry but may be State: Partial during an in-progress upgrade, so this can read a version the cluster hasn't fully reached. Prefer cv.Status.Desired.Version (or the first History entry with State == Completed) for capability gating.