diff --git a/.gitignore b/.gitignore index f644d4da0..71a81635e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ /_output /openstack-tests +/bin diff --git a/test/extended/openstack/volumes.go b/test/extended/openstack/volumes.go index 01fd8383b..fd903d6ef 100644 --- a/test/extended/openstack/volumes.go +++ b/test/extended/openstack/volumes.go @@ -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()) + + 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] + 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) + } + } + }) }) }) diff --git a/test/extended/util/annotate/generated/zz_generated.annotations.go b/test/extended/util/annotate/generated/zz_generated.annotations.go index e271cee84..5c7145eab 100644 --- a/test/extended/util/annotate/generated/zz_generated.annotations.go +++ b/test/extended/util/annotate/generated/zz_generated.annotations.go @@ -49,6 +49,8 @@ var Annotations = map[string]string{ "[OTP][sig-installer][Suite:openshift/openstack] The OpenStack platform on volume creation should create a cinder volume when using cinder default storage class": "", + "[OTP][sig-installer][Suite:openshift/openstack] The OpenStack platform on volume creation should create a cinder volume with specified metadata when using cinder storage class with appendVolumeMetadata": "", + "[OTP][sig-installer][Suite:openshift/openstack] The OpenStack platform on volume creation should create a manila share when using manila storage class": "", "[OTP][sig-installer][Suite:openshift/openstack] The OpenStack platform on volume creation should follow PVC specs during resizing for prometheus": "",