// WaitForResourceQuotaSync watches given resource quota until its usage is updated to desired level or a // timeout occurs. If successful, used quota values will be returned for expected resources. Otherwise an // ErrWaitTimeout will be returned. If expectedIsUpperLimit is true, given expected usage must compare greater // or equal to quota's usage, which is useful for expected usage increment. Otherwise expected usage must // compare lower or equal to quota's usage, which is useful for expected usage decrement. func WaitForResourceQuotaSync( client kcoreclient.ResourceQuotaInterface, name string, expectedUsage kapi.ResourceList, expectedIsUpperLimit bool, timeout time.Duration, ) (kapi.ResourceList, error) { startTime := time.Now() endTime := startTime.Add(timeout) expectedResourceNames := quota.ResourceNames(expectedUsage) list, err := client.List(kapi.ListOptions{FieldSelector: fields.Set{"metadata.name": name}.AsSelector()}) if err != nil { return nil, err } for i := range list.Items { used := quota.Mask(list.Items[i].Status.Used, expectedResourceNames) if isUsageSynced(used, expectedUsage, expectedIsUpperLimit) { return used, nil } } rv := list.ResourceVersion w, err := client.Watch(kapi.ListOptions{FieldSelector: fields.Set{"metadata.name": name}.AsSelector(), ResourceVersion: rv}) if err != nil { return nil, err } defer w.Stop() for time.Now().Before(endTime) { select { case val, ok := <-w.ResultChan(): if !ok { // reget and re-watch continue } if rq, ok := val.Object.(*kapi.ResourceQuota); ok { used := quota.Mask(rq.Status.Used, expectedResourceNames) if isUsageSynced(used, expectedUsage, expectedIsUpperLimit) { return used, nil } } case <-time.After(endTime.Sub(time.Now())): return nil, wait.ErrWaitTimeout } } return nil, wait.ErrWaitTimeout }
// bumpQuota modifies hard spec of quota object with the given value. It returns modified hard spec. func bumpQuota(t *testing.T, rqs kcoreclient.ResourceQuotaInterface, quotaName string, resourceName kapi.ResourceName, value int64) kapi.ResourceList { t.Logf("bump the quota %s to %s=%d", quotaName, resourceName, value) rq, err := rqs.Get(quotaName) if err != nil { t.Fatal(err) } rq.Spec.Hard[resourceName] = *resource.NewQuantity(value, resource.DecimalSI) _, err = rqs.Update(rq) if err != nil { t.Fatal(err) } err = testutil.WaitForResourceQuotaLimitSync( rqs, quotaName, rq.Spec.Hard, time.Second*10) if err != nil { t.Fatal(err) } return rq.Spec.Hard }
// createResourceQuota creates a resource quota with given hard limits in a current namespace and waits until // a first usage refresh func createResourceQuota(t *testing.T, rqClient kcoreclient.ResourceQuotaInterface, quotaName string, hard kapi.ResourceList) *kapi.ResourceQuota { rq := &kapi.ResourceQuota{ ObjectMeta: kapi.ObjectMeta{ Name: quotaName, }, Spec: kapi.ResourceQuotaSpec{ Hard: hard, }, } t.Logf("creating resource quota %q with a limit %v", quotaName, hard) rq, err := rqClient.Create(rq) if err != nil { t.Fatal(err) } err = testutil.WaitForResourceQuotaLimitSync(rqClient, quotaName, hard, time.Second*30) if err != nil { t.Fatal(err) } return rq }