Change:
[x] test approval issue : [x] test pr : [x] Flake [x] two weeks soak end date : 31 Oct 2023 [X] test promotion pr : [X] remove endpoint from According to following APIsnoop query, there are three PersistentVolume and three PersistentVolumeClaim endpoints that are untested. Using a number of existing e2e test practices a new has been created to provide future Conformance coverage for the 6 endpoints. The e2e logs for this test are listed below. This query shows the following PV and PVC endpoints are hit within a short period of running this e2e test. If a test with these calls gets merged, test coverage will go up by 6 points This test is also created with the goal of conformance promotion. /sig testing /sig architecture /area conformance
/triage accepted /cc
/reopen For tracking the rest of the steps to Promotion
Reopened this issue. <detailsIn response to : /reopen For tracking the rest of the steps to Promotion Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details

Discussion:
storagev1 "k8s.io/api/storage/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" <ins> "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" </ins> types "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/uuid"

"github.com/onsi/ginkgo/v2" "github.com/onsi/gomega" <ins> "github.com/onsi/gomega/gstruct" </ins> ) // Validate PV/PVC, create and verify writer pod, delete the PVC, and validate the PV's

})) framework.ExpectNoError(err, "Timeout while waiting to confirm PV %q deletion", retrievedPV.Name) }) <ins> 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") }) </ins> }) // testsuites/multivolume tests can now run with windows nodes

framework.Logf("Pod %v succeeded ", pod.Name) return nil } <ins> func conditionType(condition interface{}) string { return string(condition.(v1.PersistentVolumeClaimCondition).Type) } </ins>