mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-09 03:57:41 +00:00
Create e2e test for PV/PVC status endpoints
e2e test validates the following 6 endpoints - patchCoreV1PersistentVolumeStatus - readCoreV1PersistentVolumeStatus - replaceCoreV1PersistentVolumeStatus - patchCoreV1NamespacedPersistentVolumeClaimStatus - readCoreV1NamespacedPersistentVolumeClaimStatus - replaceCoreV1NamespacedPersistentVolumeClaimStatus
This commit is contained in:
parent
0241da314e
commit
00ae26cda8
@ -27,6 +27,8 @@ import (
|
|||||||
storagev1 "k8s.io/api/storage/v1"
|
storagev1 "k8s.io/api/storage/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
types "k8s.io/apimachinery/pkg/types"
|
types "k8s.io/apimachinery/pkg/types"
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
@ -43,6 +45,7 @@ import (
|
|||||||
|
|
||||||
"github.com/onsi/ginkgo/v2"
|
"github.com/onsi/ginkgo/v2"
|
||||||
"github.com/onsi/gomega"
|
"github.com/onsi/gomega"
|
||||||
|
"github.com/onsi/gomega/gstruct"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Validate PV/PVC, create and verify writer pod, delete the PVC, and validate the PV's
|
// Validate PV/PVC, create and verify writer pod, delete the PVC, and validate the PV's
|
||||||
@ -646,6 +649,122 @@ var _ = utils.SIGDescribe("PersistentVolumes", func() {
|
|||||||
}))
|
}))
|
||||||
framework.ExpectNoError(err, "Timeout while waiting to confirm PV %q deletion", retrievedPV.Name)
|
framework.ExpectNoError(err, "Timeout while waiting to confirm PV %q deletion", retrievedPV.Name)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should apply changes to a pv/pvc status", func(ctx context.Context) {
|
||||||
|
|
||||||
|
pvClient := c.CoreV1().PersistentVolumes()
|
||||||
|
pvcClient := c.CoreV1().PersistentVolumeClaims(ns)
|
||||||
|
|
||||||
|
ginkgo.By("Creating initial PV and PVC")
|
||||||
|
|
||||||
|
pvHostPathConfig := e2epv.PersistentVolumeConfig{
|
||||||
|
NamePrefix: ns + "-",
|
||||||
|
Labels: volLabel,
|
||||||
|
StorageClassName: ns,
|
||||||
|
PVSource: v1.PersistentVolumeSource{
|
||||||
|
CSI: &v1.CSIPersistentVolumeSource{
|
||||||
|
Driver: "e2e-driver-" + string(uuid.NewUUID()),
|
||||||
|
VolumeHandle: "e2e-status-conformance",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
numPVs, numPVCs := 1, 1
|
||||||
|
pvols, claims, err = e2epv.CreatePVsPVCs(ctx, numPVs, numPVCs, c, f.Timeouts, ns, pvHostPathConfig, pvcConfig)
|
||||||
|
framework.ExpectNoError(err, "Failed to create the requested storage resources")
|
||||||
|
|
||||||
|
ginkgo.By(fmt.Sprintf("Listing all PVs with the labelSelector: %q", volLabel.AsSelector().String()))
|
||||||
|
pvList, err := pvClient.List(ctx, metav1.ListOptions{LabelSelector: volLabel.AsSelector().String()})
|
||||||
|
framework.ExpectNoError(err, "Failed to list PVs with the labelSelector: %q", volLabel.AsSelector().String())
|
||||||
|
gomega.Expect(pvList.Items).To(gomega.HaveLen(1))
|
||||||
|
initialPV := pvList.Items[0]
|
||||||
|
|
||||||
|
ginkgo.By(fmt.Sprintf("Listing PVCs in namespace %q", ns))
|
||||||
|
pvcList, err := pvcClient.List(ctx, metav1.ListOptions{})
|
||||||
|
framework.ExpectNoError(err, "Failed to list PVCs with the labelSelector: %q", volLabel.AsSelector().String())
|
||||||
|
gomega.Expect(pvcList.Items).To(gomega.HaveLen(1))
|
||||||
|
initialPVC := pvcList.Items[0]
|
||||||
|
|
||||||
|
ginkgo.By(fmt.Sprintf("Reading %q Status", initialPVC.Name))
|
||||||
|
pvcResource := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}
|
||||||
|
pvcUnstructured, err := f.DynamicClient.Resource(pvcResource).Namespace(ns).Get(ctx, initialPVC.Name, metav1.GetOptions{}, "status")
|
||||||
|
framework.ExpectNoError(err, "Failed to fetch the status of PVC %s in namespace %s", initialPVC.Name, ns)
|
||||||
|
retrievedPVC := &v1.PersistentVolumeClaim{}
|
||||||
|
err = runtime.DefaultUnstructuredConverter.FromUnstructured(pvcUnstructured.UnstructuredContent(), &retrievedPVC)
|
||||||
|
framework.ExpectNoError(err, "Failed to retrieve %q status.", initialPV.Name)
|
||||||
|
gomega.Expect(string(retrievedPVC.Status.Phase)).To(gomega.Equal("Pending"), "Checking that the PVC status has been read")
|
||||||
|
|
||||||
|
ginkgo.By(fmt.Sprintf("Reading %q Status", initialPV.Name))
|
||||||
|
pvResource := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumes"}
|
||||||
|
pvUnstructured, err := f.DynamicClient.Resource(pvResource).Get(ctx, initialPV.Name, metav1.GetOptions{}, "status")
|
||||||
|
framework.ExpectNoError(err, "Failed to fetch the status of PV %s in namespace %s", initialPV.Name, ns)
|
||||||
|
retrievedPV := &v1.PersistentVolume{}
|
||||||
|
err = runtime.DefaultUnstructuredConverter.FromUnstructured(pvUnstructured.UnstructuredContent(), &retrievedPV)
|
||||||
|
framework.ExpectNoError(err, "Failed to retrieve %q status.", initialPV.Name)
|
||||||
|
gomega.Expect(string(retrievedPV.Status.Phase)).To(gomega.Or(gomega.Equal("Available"), gomega.Equal("Bound"), gomega.Equal("Pending")), "Checking that the PV status has been read")
|
||||||
|
|
||||||
|
ginkgo.By(fmt.Sprintf("Patching %q Status", initialPVC.Name))
|
||||||
|
payload := []byte(`{"status":{"conditions":[{"type":"StatusPatched","status":"True", "reason":"E2E patchedStatus", "message":"Set from e2e test"}]}}`)
|
||||||
|
|
||||||
|
patchedPVC, err := pvcClient.Patch(ctx, initialPVC.Name, types.MergePatchType, payload, metav1.PatchOptions{}, "status")
|
||||||
|
framework.ExpectNoError(err, "Failed to patch status.")
|
||||||
|
|
||||||
|
gomega.Expect(patchedPVC.Status.Conditions).To(gstruct.MatchElements(conditionType, gstruct.IgnoreExtras, gstruct.Elements{
|
||||||
|
"StatusPatched": gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{
|
||||||
|
"Message": gomega.ContainSubstring("Set from e2e test"),
|
||||||
|
"Reason": gomega.ContainSubstring("E2E patchedStatus"),
|
||||||
|
}),
|
||||||
|
}), "Checking that patched status has been applied")
|
||||||
|
|
||||||
|
ginkgo.By(fmt.Sprintf("Patching %q Status", retrievedPV.Name))
|
||||||
|
payload = []byte(`{"status":{"message": "StatusPatched", "reason": "E2E patchStatus"}}`)
|
||||||
|
|
||||||
|
patchedPV, err := pvClient.Patch(ctx, retrievedPV.Name, types.MergePatchType, payload, metav1.PatchOptions{}, "status")
|
||||||
|
framework.ExpectNoError(err, "Failed to patch %q status.", retrievedPV.Name)
|
||||||
|
gomega.Expect(patchedPV.Status.Reason).To(gomega.Equal("E2E patchStatus"), "Checking that patched status has been applied")
|
||||||
|
gomega.Expect(patchedPV.Status.Message).To(gomega.Equal("StatusPatched"), "Checking that patched status has been applied")
|
||||||
|
|
||||||
|
ginkgo.By(fmt.Sprintf("Updating %q Status", patchedPVC.Name))
|
||||||
|
var statusToUpdate, updatedPVC *v1.PersistentVolumeClaim
|
||||||
|
|
||||||
|
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||||
|
statusToUpdate, err = pvcClient.Get(ctx, patchedPVC.Name, metav1.GetOptions{})
|
||||||
|
framework.ExpectNoError(err, "Unable to retrieve pvc %s", patchedPVC.Name)
|
||||||
|
|
||||||
|
statusToUpdate.Status.Conditions = append(statusToUpdate.Status.Conditions, v1.PersistentVolumeClaimCondition{
|
||||||
|
Type: "StatusUpdated",
|
||||||
|
Status: "True",
|
||||||
|
Reason: "E2E updateStatus",
|
||||||
|
Message: "Set from e2e test",
|
||||||
|
})
|
||||||
|
|
||||||
|
updatedPVC, err = pvcClient.UpdateStatus(ctx, statusToUpdate, metav1.UpdateOptions{})
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
framework.ExpectNoError(err, "Failed to update status.")
|
||||||
|
gomega.Expect(updatedPVC.Status.Conditions).To(gstruct.MatchElements(conditionType, gstruct.IgnoreExtras, gstruct.Elements{
|
||||||
|
"StatusUpdated": gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{
|
||||||
|
"Message": gomega.ContainSubstring("Set from e2e test"),
|
||||||
|
"Reason": gomega.ContainSubstring("E2E updateStatus"),
|
||||||
|
}),
|
||||||
|
}), "Checking that updated status has been applied")
|
||||||
|
|
||||||
|
ginkgo.By(fmt.Sprintf("Updating %q Status", patchedPV.Name))
|
||||||
|
var pvToUpdate, updatedPV *v1.PersistentVolume
|
||||||
|
|
||||||
|
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||||
|
pvToUpdate, err = pvClient.Get(ctx, patchedPV.Name, metav1.GetOptions{})
|
||||||
|
framework.ExpectNoError(err, "Unable to retrieve pv %s", patchedPV.Name)
|
||||||
|
|
||||||
|
pvToUpdate.Status.Reason = "E2E updateStatus"
|
||||||
|
pvToUpdate.Status.Message = "StatusUpdated"
|
||||||
|
updatedPV, err = pvClient.UpdateStatus(ctx, pvToUpdate, metav1.UpdateOptions{})
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
framework.ExpectNoError(err, "Failed to update status.")
|
||||||
|
gomega.Expect(updatedPV.Status.Reason).To(gomega.Equal("E2E updateStatus"), "Checking that updated status has been applied")
|
||||||
|
gomega.Expect(updatedPV.Status.Message).To(gomega.Equal("StatusUpdated"), "Checking that updated status has been applied")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// testsuites/multivolume tests can now run with windows nodes
|
// testsuites/multivolume tests can now run with windows nodes
|
||||||
@ -804,3 +923,7 @@ func testPodSuccessOrFail(ctx context.Context, c clientset.Interface, t *framewo
|
|||||||
framework.Logf("Pod %v succeeded ", pod.Name)
|
framework.Logf("Pod %v succeeded ", pod.Name)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func conditionType(condition interface{}) string {
|
||||||
|
return string(condition.(v1.PersistentVolumeClaimCondition).Type)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user