Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@

/_output
/openstack-tests
/bin
74 changes: 74 additions & 0 deletions test/extended/openstack/volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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)

Copy link
Copy Markdown

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.

o.Expect(err).Should(o.BeNil())

available, errs := constraint.Validate(latestVer)
o.Expect(len(errs)).Should(o.BeZero())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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) {
e2eskipper.Skipf("appendVolumeMetadata is only available on >= 5.1.0")
}

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]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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)
}
}
})
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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": "",
Expand Down