@@ -28,10 +28,13 @@ import (
2828
2929 csipbv1 "github.com/container-storage-interface/spec/lib/go/csi"
3030 "github.com/onsi/ginkgo/v2"
31+ "github.com/onsi/gomega/gcustom"
32+ gomegatypes "github.com/onsi/gomega/types"
3133 "google.golang.org/grpc/codes"
3234 v1 "k8s.io/api/core/v1"
3335 storagev1 "k8s.io/api/storage/v1"
3436 apierrors "k8s.io/apimachinery/pkg/api/errors"
37+ "k8s.io/apimachinery/pkg/api/resource"
3538 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3639 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3740 "k8s.io/apimachinery/pkg/fields"
@@ -518,9 +521,46 @@ func (m *mockDriverSetup) createResourceQuota(ctx context.Context, quota *v1.Res
518521 quota , err = f .ClientSet .CoreV1 ().ResourceQuotas (f .Namespace .Name ).Create (ctx , quota , metav1.CreateOptions {})
519522 framework .ExpectNoError (err , "Failed to create resourceQuota" )
520523 m .quotas = append (m .quotas , quota )
524+ usedResources := v1.ResourceList {}
525+ usedResources [pvcSizeQuotaKey ] = resource .MustParse ("0" )
526+ usedResources [pvcCountQuotaKey ] = resource .MustParse ("0" )
527+ err = m .waitForResourceQuota (ctx , f .Namespace .Name , quota .Name , usedResources )
528+ framework .ExpectNoError (err , "Failed to wait for resourcequota creation" )
521529 return quota
522530}
523531
532+ func (m * mockDriverSetup ) waitForResourceQuota (ctx context.Context , ns , quotaName string , used v1.ResourceList ) error {
533+ var lastResourceQuota * v1.ResourceQuota
534+ f := m .f
535+ err := framework .Gomega ().Eventually (ctx , framework .GetObject (f .ClientSet .CoreV1 ().ResourceQuotas (ns ).Get , quotaName , metav1.GetOptions {})).Should (haveUsedResources (used , & lastResourceQuota ))
536+ if lastResourceQuota != nil && err == nil {
537+ framework .Logf ("Got expected ResourceQuota:\n %s" , format .Object (lastResourceQuota , 1 ))
538+ }
539+ return err
540+ }
541+
542+ func haveUsedResources (used v1.ResourceList , lastResourceQuota * * v1.ResourceQuota ) gomegatypes.GomegaMatcher {
543+ // The template emits the actual ResourceQuota object as YAML.
544+ // In particular the ManagedFields are interesting because both
545+ // kube-apiserver and kube-controller-manager set the status.
546+ return gcustom .MakeMatcher (func (resourceQuota * v1.ResourceQuota ) (bool , error ) {
547+ if lastResourceQuota != nil {
548+ * lastResourceQuota = resourceQuota
549+ }
550+ // used may not yet be calculated
551+ if resourceQuota .Status .Used == nil {
552+ return false , nil
553+ }
554+ // verify that the quota shows the expected used resource values
555+ for k , v := range used {
556+ if actualValue , found := resourceQuota .Status .Used [k ]; ! found || (actualValue .Cmp (v ) != 0 ) {
557+ return false , nil
558+ }
559+ }
560+ return true , nil
561+ }).WithTemplate ("Expected:\n {{.FormattedActual}}\n {{.To}} have the following .status.used entries:\n {{range $key, $value := .Data}} {{$key}}: \" {{$value.ToUnstructured}}\" \n {{end}}" ).WithTemplateData (used /* Formatting of the map is done inside the template. */ )
562+ }
563+
524564func waitForCSIDriver (cs clientset.Interface , driverName string ) error {
525565 timeout := 4 * time .Minute
526566
0 commit comments