本文整理汇总了Golang中k8s/io/kubernetes/pkg/quota.Mask函数的典型用法代码示例。如果您正苦于以下问题:Golang Mask函数的具体用法?Golang Mask怎么用?Golang Mask使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了Mask函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: syncResourceQuota
// syncResourceQuota runs a complete sync of resource quota status across all known kinds
func (rq *ResourceQuotaController) syncResourceQuota(v1ResourceQuota v1.ResourceQuota) (err error) {
// quota is dirty if any part of spec hard limits differs from the status hard limits
dirty := !api.Semantic.DeepEqual(v1ResourceQuota.Spec.Hard, v1ResourceQuota.Status.Hard)
resourceQuota := api.ResourceQuota{}
if err := v1.Convert_v1_ResourceQuota_To_api_ResourceQuota(&v1ResourceQuota, &resourceQuota, nil); err != nil {
return err
}
// dirty tracks if the usage status differs from the previous sync,
// if so, we send a new usage with latest status
// if this is our first sync, it will be dirty by default, since we need track usage
dirty = dirty || (resourceQuota.Status.Hard == nil || resourceQuota.Status.Used == nil)
used := api.ResourceList{}
if resourceQuota.Status.Used != nil {
used = quota.Add(api.ResourceList{}, resourceQuota.Status.Used)
}
hardLimits := quota.Add(api.ResourceList{}, resourceQuota.Spec.Hard)
newUsage, err := quota.CalculateUsage(resourceQuota.Namespace, resourceQuota.Spec.Scopes, hardLimits, rq.registry)
if err != nil {
return err
}
for key, value := range newUsage {
used[key] = value
}
// ensure set of used values match those that have hard constraints
hardResources := quota.ResourceNames(hardLimits)
used = quota.Mask(used, hardResources)
// Create a usage object that is based on the quota resource version that will handle updates
// by default, we preserve the past usage observation, and set hard to the current spec
usage := api.ResourceQuota{
ObjectMeta: metav1.ObjectMeta{
Name: resourceQuota.Name,
Namespace: resourceQuota.Namespace,
ResourceVersion: resourceQuota.ResourceVersion,
Labels: resourceQuota.Labels,
Annotations: resourceQuota.Annotations},
Status: api.ResourceQuotaStatus{
Hard: hardLimits,
Used: used,
},
}
dirty = dirty || !quota.Equals(usage.Status.Used, resourceQuota.Status.Used)
// there was a change observed by this controller that requires we update quota
if dirty {
v1Usage := &v1.ResourceQuota{}
if err := v1.Convert_api_ResourceQuota_To_v1_ResourceQuota(&usage, v1Usage, nil); err != nil {
return err
}
_, err = rq.kubeClient.Core().ResourceQuotas(usage.Namespace).UpdateStatus(v1Usage)
return err
}
return nil
}
示例2: isLimitSynced
func isLimitSynced(received, expected kapi.ResourceList) bool {
resourceNames := quota.ResourceNames(expected)
masked := quota.Mask(received, resourceNames)
if len(masked) != len(expected) {
return false
}
if le, _ := quota.LessThanOrEqual(masked, expected); !le {
return false
}
if le, _ := quota.LessThanOrEqual(expected, masked); !le {
return false
}
return true
}
示例3: admitBlobWrite
// admitBlobWrite checks whether the blob does not exceed image quota, if set. Returns
// ErrAccessDenied error if the quota is exceeded.
func admitBlobWrite(ctx context.Context, repo *repository) error {
rqs, err := repo.quotaClient.ResourceQuotas(repo.namespace).List(kapi.ListOptions{})
if err != nil {
if kerrors.IsForbidden(err) {
context.GetLogger(ctx).Warnf("Cannot list resourcequotas because of outdated cluster roles: %v", err)
return nil
}
context.GetLogger(ctx).Errorf("Failed to list resourcequotas: %v", err)
return err
}
usage := kapi.ResourceList{
// we are about to tag a single image to an image stream
imageapi.ResourceImages: *resource.NewQuantity(1, resource.DecimalSI),
}
resources := quota.ResourceNames(usage)
for _, rq := range rqs.Items {
newUsage := quota.Add(usage, rq.Status.Used)
newUsage = quota.Mask(newUsage, resources)
requested := quota.Mask(rq.Spec.Hard, resources)
allowed, exceeded := quota.LessThanOrEqual(newUsage, requested)
if !allowed {
details := make([]string, len(exceeded))
by := quota.Subtract(newUsage, requested)
for i, r := range exceeded {
details[i] = fmt.Sprintf("%s limited to %s by %s", r, requested[r], by[r])
}
context.GetLogger(ctx).Error("Refusing to write blob exceeding quota: " + strings.Join(details, ", "))
return distribution.ErrAccessDenied
}
}
return nil
}
示例4: TestImageStreamAdmissionEvaluatorUsage
//.........这里部分代码省略.........
expectedImages: 0,
},
} {
var newIS, oldIS *imageapi.ImageStream
if tc.oldStatus != nil || tc.oldSpec != nil {
oldIS = &imageapi.ImageStream{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "is",
},
}
if tc.oldSpec != nil {
oldIS.Spec = *tc.oldSpec
}
if tc.oldStatus != nil {
oldIS.Status = *tc.oldStatus
}
}
if tc.newStatus != nil || tc.newSpec != nil {
newIS = &imageapi.ImageStream{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "is",
},
}
if tc.newSpec != nil {
newIS.Spec = *tc.newSpec
}
if tc.newStatus != nil {
newIS.Status = *tc.newStatus
}
}
commonIS := imageapi.ImageStream{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "common",
},
Status: imageapi.ImageStreamStatus{
Tags: map[string]imageapi.TagEventList{
"misc": {
Items: []imageapi.TagEvent{
{
DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/[email protected]%s", miscImageDigest),
Image: miscImageDigest,
},
},
},
},
},
}
iss := []imageapi.ImageStream{commonIS}
if oldIS != nil {
iss = append(iss, *oldIS)
}
fakeClient := &testclient.Fake{}
fakeClient.AddReactor("get", "imagestreams", getFakeImageStreamGetHandler(t, iss...))
fakeClient.AddReactor("list", "imagestreams", getFakeImageStreamListHandler(t, iss...))
fakeClient.AddReactor("get", "images", getFakeImageGetHandler(t, "test"))
evaluator := NewImageStreamAdmissionEvaluator(fakeClient)
usage := evaluator.Usage(newIS)
if len(usage) != len(expectedResources) {
t.Errorf("[%s]: got unexpected number of computed resources: %d != %d", tc.name, len(usage), len(expectedResources))
}
expectedUsage := kapi.ResourceList{
imageapi.ResourceImages: *resource.NewQuantity(tc.expectedImages, resource.DecimalSI),
}
masked := kquota.Mask(usage, expectedResources)
if len(masked) != len(expectedUsage) {
for k := range usage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: got unexpected resource %q from Usage() method", tc.name, k)
}
}
for k := range expectedUsage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: expected resource %q not computed", tc.name, k)
}
}
}
for rname, expectedValue := range expectedUsage {
if v, exists := masked[rname]; exists {
if v.Cmp(expectedValue) != 0 {
t.Errorf("[%s]: got unexpected usage for %q: %s != %s", tc.name, rname, v.String(), expectedValue.String())
}
}
}
}
}
示例5: TestImageStreamEvaluatorUsageStats
//.........这里部分代码省略.........
"test",
1,
},
{
"same image in two different image streams",
[]imageapi.ImageStream{
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "is1",
},
Status: imageapi.ImageStreamStatus{
Tags: map[string]imageapi.TagEventList{
"latest": {
Items: []imageapi.TagEvent{
{
DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/[email protected]%s", childImageWith2LayersDigest),
Image: childImageWith2LayersDigest,
},
},
},
},
},
},
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "is2",
},
Status: imageapi.ImageStreamStatus{
Tags: map[string]imageapi.TagEventList{
"latest": {
Items: []imageapi.TagEvent{
{
DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/[email protected]%s", miscImageDigest),
Image: miscImageDigest,
},
},
},
"foo": {
Items: []imageapi.TagEvent{
{
DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/[email protected]%s", childImageWith2LayersDigest),
Image: childImageWith2LayersDigest,
},
},
},
},
},
},
},
"test",
2,
},
} {
fakeClient := &testclient.Fake{}
fakeClient.AddReactor("list", "imagestreams", getFakeImageStreamListHandler(t, tc.iss...))
fakeClient.AddReactor("get", "imagestreamimages", getFakeImageStreamImageGetHandler(t, tc.iss...))
evaluator := NewImageStreamEvaluator(fakeClient)
stats, err := evaluator.UsageStats(kquota.UsageStatsOptions{Namespace: tc.namespace})
if err != nil {
t.Errorf("[%s]: could not get usage stats for namespace %q: %v", tc.name, tc.namespace, err)
continue
}
if len(stats.Used) != len(expectedResources) {
t.Errorf("[%s]: got unexpected number of computed resources: %d != %d", tc.name, len(stats.Used), len(expectedResources))
}
masked := kquota.Mask(stats.Used, expectedResources)
expectedUsage := kapi.ResourceList{
imageapi.ResourceImages: *resource.NewQuantity(tc.expectedImages, resource.DecimalSI),
}
if len(masked) != len(expectedResources) {
for k := range stats.Used {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: got unexpected resource %q from Usage() method", tc.name, k)
}
}
for _, k := range expectedResources {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: expected resource %q not computed", tc.name, k)
}
}
}
for rname, expectedValue := range expectedUsage {
if v, exists := masked[rname]; exists {
if v.Cmp(expectedValue) != 0 {
t.Errorf("[%s]: got unexpected usage for %q: %s != %s", tc.name, rname, v.String(), expectedValue.String())
}
}
}
}
}
示例6: TestImageStreamImportEvaluatorUsage
//.........这里部分代码省略.........
Namespace: "test",
Name: "spec",
},
},
},
isiSpec: imageapi.ImageStreamImportSpec{
Import: true,
Repository: &imageapi.RepositoryImportSpec{
From: kapi.ObjectReference{
Kind: "DockerImage",
Name: "docker.io/library/fedora",
},
},
},
expectedISCount: 1,
},
{
name: "import images",
isiSpec: imageapi.ImageStreamImportSpec{
Import: true,
Images: []imageapi.ImageImportSpec{
{
From: kapi.ObjectReference{
Kind: "DockerImage",
Name: "docker.io/library/fedora:f23",
},
},
},
},
expectedISCount: 1,
},
{
name: "import image and repository",
isiSpec: imageapi.ImageStreamImportSpec{
Import: true,
Images: []imageapi.ImageImportSpec{
{
From: kapi.ObjectReference{
Kind: "DockerImage",
Name: "docker.io/centos:latest",
},
},
},
Repository: &imageapi.RepositoryImportSpec{
From: kapi.ObjectReference{
Kind: "DockerImage",
Name: "docker.io/library/fedora",
},
},
},
expectedISCount: 1,
},
} {
fakeClient := &testclient.Fake{}
fakeClient.AddReactor("get", "imagestreams", imagetest.GetFakeImageStreamGetHandler(t, tc.iss...))
evaluator := NewImageStreamImportEvaluator(fakeClient)
isi := &imageapi.ImageStreamImport{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "is",
},
Spec: tc.isiSpec,
}
usage := evaluator.Usage(isi)
expectedUsage := imagetest.ExpectedResourceListFor(tc.expectedISCount)
expectedResources := kquota.ResourceNames(expectedUsage)
if len(usage) != len(expectedResources) {
t.Errorf("[%s]: got unexpected number of computed resources: %d != %d", tc.name, len(usage), len(expectedResources))
}
masked := kquota.Mask(usage, expectedResources)
if len(masked) != len(expectedUsage) {
for k := range usage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: got unexpected resource %q from Usage() method", tc.name, k)
}
}
for k := range expectedUsage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: expected resource %q not computed", tc.name, k)
}
}
}
for rname, expectedValue := range expectedUsage {
if v, exists := masked[rname]; exists {
if v.Cmp(expectedValue) != 0 {
t.Errorf("[%s]: got unexpected usage for %q: %s != %s", tc.name, rname, v.String(), expectedValue.String())
}
}
}
}
}
示例7: Admit
//.........这里部分代码省略.........
// on updates, we need to subtract the previous measured usage
// if usage shows no change, just return since it has no impact on quota
deltaUsage := evaluator.Usage(inputObject)
if admission.Update == op {
prevItem, err := evaluator.Get(namespace, name)
if err != nil {
return admission.NewForbidden(a, fmt.Errorf("Unable to get previous: %v", err))
}
prevUsage := evaluator.Usage(prevItem)
deltaUsage = quota.Subtract(deltaUsage, prevUsage)
}
if quota.IsZero(deltaUsage) {
return nil
}
// TODO: Move to a bucketing work queue
// If we guaranteed that we processed the request in order it was received to server, we would reduce quota conflicts.
// Until we have the bucketing work queue, we jitter requests and retry on conflict.
numRetries := 10
interval := time.Duration(rand.Int63n(90)+int64(10)) * time.Millisecond
// seed the retry loop with the initial set of quotas to process (should reduce each iteration)
resourceQuotasToProcess := resourceQuotas
for retry := 1; retry <= numRetries; retry++ {
// the list of quotas we will try again if there is a version conflict
tryAgain := []*api.ResourceQuota{}
// check that we pass all remaining quotas so we do not prematurely charge
// for each quota, mask the usage to the set of resources tracked by the quota
// if request + used > hard, return an error describing the failure
updatedUsage := map[string]api.ResourceList{}
for _, resourceQuota := range resourceQuotasToProcess {
hardResources := quota.ResourceNames(resourceQuota.Status.Hard)
requestedUsage := quota.Mask(deltaUsage, hardResources)
newUsage := quota.Add(resourceQuota.Status.Used, requestedUsage)
if allowed, exceeded := quota.LessThanOrEqual(newUsage, resourceQuota.Status.Hard); !allowed {
failedRequestedUsage := quota.Mask(requestedUsage, exceeded)
failedUsed := quota.Mask(resourceQuota.Status.Used, exceeded)
failedHard := quota.Mask(resourceQuota.Status.Hard, exceeded)
return admission.NewForbidden(a,
fmt.Errorf("Exceeded quota: %s, requested: %s, used: %s, limited: %s",
resourceQuota.Name,
prettyPrint(failedRequestedUsage),
prettyPrint(failedUsed),
prettyPrint(failedHard)))
}
updatedUsage[resourceQuota.Name] = newUsage
}
// update the status for each quota with its new usage
// if we get a conflict, get updated quota, and enqueue
for i, resourceQuota := range resourceQuotasToProcess {
newUsage := updatedUsage[resourceQuota.Name]
quotaToUpdate := &api.ResourceQuota{
ObjectMeta: api.ObjectMeta{
Name: resourceQuota.Name,
Namespace: resourceQuota.Namespace,
ResourceVersion: resourceQuota.ResourceVersion,
},
Status: api.ResourceQuotaStatus{
Hard: quota.Add(api.ResourceList{}, resourceQuota.Status.Hard),
Used: newUsage,
},
}
_, err = q.client.Core().ResourceQuotas(quotaToUpdate.Namespace).UpdateStatus(quotaToUpdate)
if err != nil {
示例8: TestImageStreamEvaluatorUsageStats
func TestImageStreamEvaluatorUsageStats(t *testing.T) {
for _, tc := range []struct {
name string
iss []imageapi.ImageStream
namespace string
expectedISCount int64
}{
{
name: "no image stream",
iss: []imageapi.ImageStream{},
namespace: "test",
expectedISCount: 0,
},
{
name: "one image stream",
iss: []imageapi.ImageStream{
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "onetag",
},
},
},
namespace: "test",
expectedISCount: 1,
},
{
name: "two image streams",
iss: []imageapi.ImageStream{
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "is1",
},
},
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "is2",
},
},
},
namespace: "test",
expectedISCount: 2,
},
{
name: "two image streams in different namespaces",
iss: []imageapi.ImageStream{
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "is1",
},
},
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "other",
Name: "is2",
},
},
},
namespace: "test",
expectedISCount: 1,
},
} {
fakeClient := &testclient.Fake{}
fakeClient.AddReactor("list", "imagestreams", imagetest.GetFakeImageStreamListHandler(t, tc.iss...))
evaluator := NewImageStreamEvaluator(fakeClient)
stats, err := evaluator.UsageStats(kquota.UsageStatsOptions{Namespace: tc.namespace})
if err != nil {
t.Errorf("[%s]: could not get usage stats for namespace %q: %v", tc.name, tc.namespace, err)
continue
}
expectedUsage := imagetest.ExpectedResourceListFor(tc.expectedISCount)
expectedResources := kquota.ResourceNames(expectedUsage)
if len(stats.Used) != len(expectedResources) {
t.Errorf("[%s]: got unexpected number of computed resources: %d != %d", tc.name, len(stats.Used), len(expectedResources))
}
masked := kquota.Mask(stats.Used, expectedResources)
if len(masked) != len(expectedResources) {
for k := range stats.Used {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: got unexpected resource %q from Usage() method", tc.name, k)
}
}
for _, k := range expectedResources {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: expected resource %q not computed", tc.name, k)
}
}
}
//.........这里部分代码省略.........
示例9: TestImageStreamEvaluatorUsage
func TestImageStreamEvaluatorUsage(t *testing.T) {
for _, tc := range []struct {
name string
iss []imageapi.ImageStream
expectedISCount int64
}{
{
name: "new image stream",
expectedISCount: 1,
},
{
name: "image stream already exists",
iss: []imageapi.ImageStream{
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "is",
},
},
},
expectedISCount: 1,
},
{
name: "new image stream in non-empty project",
iss: []imageapi.ImageStream{
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "existing",
},
},
},
expectedISCount: 1,
},
} {
newIS := &imageapi.ImageStream{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "is",
},
}
fakeClient := &testclient.Fake{}
fakeClient.AddReactor("get", "imagestreams", imagetest.GetFakeImageStreamGetHandler(t, tc.iss...))
evaluator := NewImageStreamEvaluator(fakeClient)
usage := evaluator.Usage(newIS)
expectedUsage := imagetest.ExpectedResourceListFor(tc.expectedISCount)
expectedResources := kquota.ResourceNames(expectedUsage)
if len(usage) != len(expectedResources) {
t.Errorf("[%s]: got unexpected number of computed resources: %d != %d", tc.name, len(usage), len(expectedResources))
}
masked := kquota.Mask(usage, expectedResources)
if len(masked) != len(expectedUsage) {
for k := range usage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: got unexpected resource %q from Usage() method", tc.name, k)
}
}
for k := range expectedUsage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: expected resource %q not computed", tc.name, k)
}
}
}
for rname, expectedValue := range expectedUsage {
if v, exists := masked[rname]; exists {
if v.Cmp(expectedValue) != 0 {
t.Errorf("[%s]: got unexpected usage for %q: %s != %s", tc.name, rname, v.String(), expectedValue.String())
}
}
}
}
}
示例10: TestImageStreamTagEvaluatorUsage
//.........这里部分代码省略.........
Tag: &imageapi.TagReference{
Name: "latest",
From: &kapi.ObjectReference{
Kind: "ImageStreamImage",
Namespace: "shared",
Name: "[email protected]" + baseImageWith1LayerDigest,
},
},
},
expectedImages: 0,
},
{
name: "tag an image already present using image stream tag",
iss: []imageapi.ImageStream{
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "destis",
},
Status: imageapi.ImageStreamStatus{
Tags: map[string]imageapi.TagEventList{
"latest": {
Items: []imageapi.TagEvent{
{
DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/[email protected]%s", baseImageWith1LayerDigest),
Image: baseImageWith1LayerDigest,
},
{
DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/[email protected]%s", miscImageDigest),
Image: miscImageDigest,
},
},
},
},
},
},
},
ist: imageapi.ImageStreamTag{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "another:latest",
},
Tag: &imageapi.TagReference{
Name: "latest",
// shared is has name of baseImageWith1Layer at the first place in event list
From: &kapi.ObjectReference{
Kind: "ImageStreamTag",
Namespace: "shared",
Name: "is:latest",
},
},
},
expectedImages: 0,
},
} {
fakeClient := &testclient.Fake{}
fakeClient.AddReactor("get", "images", getFakeImageGetHandler(t, "ns"))
fakeClient.AddReactor("get", "imagestreams", getFakeImageStreamGetHandler(t, tc.iss...))
fakeClient.AddReactor("list", "imagestreams", getFakeImageStreamListHandler(t, tc.iss...))
fakeClient.AddReactor("get", "imagestreamimages", getFakeImageStreamImageGetHandler(t, tc.iss...))
evaluator := NewImageStreamTagEvaluator(fakeClient)
usage := evaluator.Usage(&tc.ist)
expectedUsage := kapi.ResourceList{
imageapi.ResourceImages: *resource.NewQuantity(tc.expectedImages, resource.DecimalSI),
}
if len(usage) != len(expectedUsage) {
t.Errorf("[%s]: got unexpected number of computed resources: %d != %d", tc.name, len(usage), len(expectedResources))
}
masked := kquota.Mask(usage, expectedResources)
if len(masked) != len(expectedUsage) {
for k := range usage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: got unexpected resource %q from Usage() method", tc.name, k)
}
}
for k := range expectedUsage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: expected resource %q not computed", tc.name, k)
}
}
}
for rname, expectedValue := range expectedUsage {
if v, exists := masked[rname]; exists {
if v.Cmp(expectedValue) != 0 {
t.Errorf("[%s]: got unexpected usage for %q: %s != %s", tc.name, rname, v.String(), expectedValue.String())
}
}
}
}
}
示例11: TestImageStreamTagEvaluatorUsage
//.........这里部分代码省略.........
"latest": {
Items: []imageapi.TagEvent{
{
DockerImageReference: imagetest.MakeDockerImageReference("test", "havingtag", imagetest.BaseImageWith1LayerDigest),
Image: imagetest.BaseImageWith1LayerDigest,
},
},
},
},
},
},
},
ist: imageapi.ImageStreamTag{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "havingtag:latest",
},
Tag: &imageapi.TagReference{
Name: "latest",
From: &kapi.ObjectReference{
Kind: "ImageStreamImage",
Namespace: "shared",
Name: "[email protected]" + imagetest.ChildImageWith2LayersDigest,
},
},
},
expectedISCount: 0,
},
{
name: "add a new tag with 2 image streams",
iss: []imageapi.ImageStream{
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "is",
},
},
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "other",
Name: "is2",
},
},
},
ist: imageapi.ImageStreamTag{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "destis:latest",
},
Tag: &imageapi.TagReference{
Name: "latest",
From: &kapi.ObjectReference{
Kind: "ImageStreamTag",
Namespace: "other",
Name: "is2:latest",
},
},
},
expectedISCount: 1,
},
} {
fakeClient := &testclient.Fake{}
fakeClient.AddReactor("get", "imagestreams", imagetest.GetFakeImageStreamGetHandler(t, tc.iss...))
evaluator := NewImageStreamTagEvaluator(fakeClient, fakeClient)
usage := evaluator.Usage(&tc.ist)
expectedUsage := imagetest.ExpectedResourceListFor(tc.expectedISCount)
expectedResources := kquota.ResourceNames(expectedUsage)
if len(usage) != len(expectedUsage) {
t.Errorf("[%s]: got unexpected number of computed resources: %d != %d", tc.name, len(usage), len(expectedResources))
}
masked := kquota.Mask(usage, expectedResources)
if len(masked) != len(expectedUsage) {
for k := range usage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: got unexpected resource %q from Usage() method", tc.name, k)
}
}
for k := range expectedUsage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: expected resource %q not computed", tc.name, k)
}
}
}
for rname, expectedValue := range expectedUsage {
if v, exists := masked[rname]; exists {
if v.Cmp(expectedValue) != 0 {
t.Errorf("[%s]: got unexpected usage for %q: %s != %s", tc.name, rname, v.String(), expectedValue.String())
}
}
}
}
}
示例12: syncResourceQuota
// syncResourceQuota runs a complete sync of resource quota status across all known kinds
func (rq *ResourceQuotaController) syncResourceQuota(resourceQuota api.ResourceQuota) (err error) {
// quota is dirty if any part of spec hard limits differs from the status hard limits
dirty := !api.Semantic.DeepEqual(resourceQuota.Spec.Hard, resourceQuota.Status.Hard)
// dirty tracks if the usage status differs from the previous sync,
// if so, we send a new usage with latest status
// if this is our first sync, it will be dirty by default, since we need track usage
dirty = dirty || (resourceQuota.Status.Hard == nil || resourceQuota.Status.Used == nil)
// Create a usage object that is based on the quota resource version that will handle updates
// by default, we preserve the past usage observation, and set hard to the current spec
previousUsed := api.ResourceList{}
if resourceQuota.Status.Used != nil {
previousUsed = quota.Add(api.ResourceList{}, resourceQuota.Status.Used)
}
usage := api.ResourceQuota{
ObjectMeta: api.ObjectMeta{
Name: resourceQuota.Name,
Namespace: resourceQuota.Namespace,
ResourceVersion: resourceQuota.ResourceVersion,
Labels: resourceQuota.Labels,
Annotations: resourceQuota.Annotations},
Status: api.ResourceQuotaStatus{
Hard: quota.Add(api.ResourceList{}, resourceQuota.Spec.Hard),
Used: previousUsed,
},
}
// find the intersection between the hard resources on the quota
// and the resources this controller can track to know what we can
// look to measure updated usage stats for
hardResources := quota.ResourceNames(usage.Status.Hard)
potentialResources := []api.ResourceName{}
evaluators := rq.registry.Evaluators()
for _, evaluator := range evaluators {
potentialResources = append(potentialResources, evaluator.MatchesResources()...)
}
matchedResources := quota.Intersection(hardResources, potentialResources)
// sum the observed usage from each evaluator
newUsage := api.ResourceList{}
usageStatsOptions := quota.UsageStatsOptions{Namespace: resourceQuota.Namespace, Scopes: resourceQuota.Spec.Scopes}
for _, evaluator := range evaluators {
stats, err := evaluator.UsageStats(usageStatsOptions)
if err != nil {
return err
}
newUsage = quota.Add(newUsage, stats.Used)
}
// mask the observed usage to only the set of resources tracked by this quota
// merge our observed usage with the quota usage status
// if the new usage is different than the last usage, we will need to do an update
newUsage = quota.Mask(newUsage, matchedResources)
for key, value := range newUsage {
usage.Status.Used[key] = value
}
dirty = dirty || !quota.Equals(usage.Status.Used, resourceQuota.Status.Used)
// there was a change observed by this controller that requires we update quota
if dirty {
_, err = rq.kubeClient.Core().ResourceQuotas(usage.Namespace).UpdateStatus(&usage)
return err
}
return nil
}
示例13: TestImageStreamEvaluatorUsage
//.........这里部分代码省略.........
Tags: map[string]imageapi.TagEventList{
"foo": {
Items: []imageapi.TagEvent{
{
DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/[email protected]%s", baseImageWith2LayersDigest),
Image: baseImageWith2LayersDigest,
},
},
},
"bar": {
Items: []imageapi.TagEvent{
{
DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/[email protected]%s", childImageWith3LayersDigest),
Image: childImageWith3LayersDigest,
},
},
},
},
},
},
2,
},
{
"image stream with the same image under different tag",
imageapi.ImageStream{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "noshared",
},
Status: imageapi.ImageStreamStatus{
Tags: map[string]imageapi.TagEventList{
"latest": {
Items: []imageapi.TagEvent{
{
DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/[email protected]%s", childImageWith2LayersDigest),
Image: childImageWith2LayersDigest,
},
},
},
"foo": {
Items: []imageapi.TagEvent{
{
DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/[email protected]%s", childImageWith2LayersDigest),
Image: childImageWith2LayersDigest,
},
},
},
},
},
},
1,
},
} {
fakeClient := &testclient.Fake{}
fakeClient.AddReactor("get", "imagestreams", getFakeImageStreamGetHandler(t, tc.is))
fakeClient.AddReactor("get", "imagestreamimages", getFakeImageStreamImageGetHandler(t, tc.is))
evaluator := NewImageStreamEvaluator(fakeClient)
is, err := evaluator.Get(tc.is.Namespace, tc.is.Name)
if err != nil {
t.Errorf("[%s]: could not get image stream %q: %v", tc.name, tc.is.Name, err)
continue
}
usage := evaluator.Usage(is)
if len(usage) != len(expectedResources) {
t.Errorf("[%s]: got unexpected number of computed resources: %d != %d", tc.name, len(usage), len(expectedResources))
}
masked := kquota.Mask(usage, expectedResources)
expectedUsage := kapi.ResourceList{
imageapi.ResourceImages: *resource.NewQuantity(tc.expectedImages, resource.DecimalSI),
}
if len(masked) != len(expectedResources) {
for k := range usage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: got unexpected resource %q from Usage() method", tc.name, k)
}
}
for _, k := range expectedResources {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: expected resource %q not computed", tc.name, k)
}
}
}
for rname, expectedValue := range expectedUsage {
if v, exists := masked[rname]; exists {
if v.Cmp(expectedValue) != 0 {
t.Errorf("[%s]: got unexpected usage for %q: %s != %s", tc.name, rname, v.String(), expectedValue.String())
}
}
}
}
}
示例14: checkRequest
// checkRequest verifies that the request does not exceed any quota constraint. it returns back a copy of quotas not yet persisted
// that capture what the usage would be if the request succeeded. It return an error if the is insufficient quota to satisfy the request
func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.Attributes) ([]api.ResourceQuota, error) {
namespace := a.GetNamespace()
evaluators := e.registry.Evaluators()
evaluator, found := evaluators[a.GetKind().GroupKind()]
if !found {
return quotas, nil
}
op := a.GetOperation()
operationResources := evaluator.OperationResources(op)
if len(operationResources) == 0 {
return quotas, nil
}
// find the set of quotas that are pertinent to this request
// reject if we match the quota, but usage is not calculated yet
// reject if the input object does not satisfy quota constraints
// if there are no pertinent quotas, we can just return
inputObject := a.GetObject()
interestingQuotaIndexes := []int{}
for i := range quotas {
resourceQuota := quotas[i]
match := evaluator.Matches(&resourceQuota, inputObject)
if !match {
continue
}
hardResources := quota.ResourceNames(resourceQuota.Status.Hard)
evaluatorResources := evaluator.MatchesResources()
requiredResources := quota.Intersection(hardResources, evaluatorResources)
err := evaluator.Constraints(requiredResources, inputObject)
if err != nil {
return nil, admission.NewForbidden(a, fmt.Errorf("Failed quota: %s: %v", resourceQuota.Name, err))
}
if !hasUsageStats(&resourceQuota) {
return nil, admission.NewForbidden(a, fmt.Errorf("Status unknown for quota: %s", resourceQuota.Name))
}
interestingQuotaIndexes = append(interestingQuotaIndexes, i)
}
if len(interestingQuotaIndexes) == 0 {
return quotas, nil
}
// Usage of some resources cannot be counted in isolation. For example when
// the resource represents a number of unique references to external
// resource. In such a case an evaluator needs to process other objects in
// the same namespace which needs to be known.
if accessor, err := meta.Accessor(inputObject); namespace != "" && err == nil {
if accessor.GetNamespace() == "" {
accessor.SetNamespace(namespace)
}
}
// there is at least one quota that definitely matches our object
// as a result, we need to measure the usage of this object for quota
// on updates, we need to subtract the previous measured usage
// if usage shows no change, just return since it has no impact on quota
deltaUsage := evaluator.Usage(inputObject)
if admission.Update == op {
prevItem := a.GetOldObject()
if prevItem == nil {
return nil, admission.NewForbidden(a, fmt.Errorf("Unable to get previous usage since prior version of object was not found"))
}
// if we can definitively determine that this is not a case of "create on update",
// then charge based on the delta. Otherwise, bill the maximum
metadata, err := meta.Accessor(prevItem)
if err == nil && len(metadata.GetResourceVersion()) > 0 {
prevUsage := evaluator.Usage(prevItem)
deltaUsage = quota.Subtract(deltaUsage, prevUsage)
}
}
if quota.IsZero(deltaUsage) {
return quotas, nil
}
for _, index := range interestingQuotaIndexes {
resourceQuota := quotas[index]
hardResources := quota.ResourceNames(resourceQuota.Status.Hard)
requestedUsage := quota.Mask(deltaUsage, hardResources)
newUsage := quota.Add(resourceQuota.Status.Used, requestedUsage)
maskedNewUsage := quota.Mask(newUsage, quota.ResourceNames(requestedUsage))
if allowed, exceeded := quota.LessThanOrEqual(maskedNewUsage, resourceQuota.Status.Hard); !allowed {
failedRequestedUsage := quota.Mask(requestedUsage, exceeded)
failedUsed := quota.Mask(resourceQuota.Status.Used, exceeded)
failedHard := quota.Mask(resourceQuota.Status.Hard, exceeded)
return nil, admission.NewForbidden(a,
fmt.Errorf("Exceeded quota: %s, requested: %s, used: %s, limited: %s",
resourceQuota.Name,
prettyPrint(failedRequestedUsage),
prettyPrint(failedUsed),
prettyPrint(failedHard)))
}
// update to the new usage number
//.........这里部分代码省略.........
示例15: TestImageStreamMappingEvaluatorUsage
//.........这里部分代码省略.........
},
},
},
},
},
},
imageName: childImageWith3LayersDigest,
imageManifest: childImageWith3Layers,
imageAnnotations: map[string]string{imageapi.ManagedByOpenShiftAnnotation: "true"},
destISNamespace: "test",
destISName: "destis",
expectedImages: 1,
},
{
name: "add a new tag to a new image stream with image present in the other",
iss: []imageapi.ImageStream{
{
ObjectMeta: kapi.ObjectMeta{
Namespace: "test",
Name: "other",
},
Status: imageapi.ImageStreamStatus{
Tags: map[string]imageapi.TagEventList{
"latest": {
Items: []imageapi.TagEvent{
{
DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/[email protected]%s", baseImageWith2LayersDigest),
Image: baseImageWith2LayersDigest,
},
},
},
},
},
},
},
imageName: baseImageWith2LayersDigest,
imageManifest: baseImageWith2Layers,
imageAnnotations: map[string]string{imageapi.ManagedByOpenShiftAnnotation: "true"},
destISNamespace: "test",
destISName: "destis",
expectedImages: 0,
},
} {
fakeClient := &testclient.Fake{}
fakeClient.AddReactor("list", "imagestreams", getFakeImageStreamListHandler(t, tc.iss...))
fakeClient.AddReactor("get", "imagestreamimages", getFakeImageStreamImageGetHandler(t, tc.iss...))
evaluator := NewImageStreamMappingEvaluator(fakeClient)
ism := &imageapi.ImageStreamMapping{
ObjectMeta: kapi.ObjectMeta{
Namespace: tc.destISNamespace,
Name: tc.destISName,
},
Image: imageapi.Image{
ObjectMeta: kapi.ObjectMeta{
Name: tc.imageName,
Annotations: tc.imageAnnotations,
},
DockerImageReference: fmt.Sprintf("registry.example.org/%s/%[email protected]%s", tc.destISNamespace, tc.destISName, tc.imageName),
DockerImageManifest: tc.imageManifest,
},
}
usage := evaluator.Usage(ism)
if len(usage) != len(expectedResources) {
t.Errorf("[%s]: got unexpected number of computed resources: %d != %d", tc.name, len(usage), len(expectedResources))
}
masked := kquota.Mask(usage, expectedResources)
expectedUsage := kapi.ResourceList{
imageapi.ResourceImages: *resource.NewQuantity(tc.expectedImages, resource.DecimalSI),
}
if len(masked) != len(expectedUsage) {
for k := range usage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: got unexpected resource %q from Usage() method", tc.name, k)
}
}
for k := range expectedUsage {
if _, exists := masked[k]; !exists {
t.Errorf("[%s]: expected resource %q not computed", tc.name, k)
}
}
}
for rname, expectedValue := range expectedUsage {
if v, exists := masked[rname]; exists {
if v.Cmp(expectedValue) != 0 {
t.Errorf("[%s]: got unexpected usage for %q: %s != %s", tc.name, rname, v.String(), expectedValue.String())
}
}
}
}
}