/
imagestreamtag_evaluator.go
135 lines (113 loc) · 4.08 KB
/
imagestreamtag_evaluator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package image
import (
"fmt"
"strings"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/admission"
kapi "k8s.io/kubernetes/pkg/api"
kerrors "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/resource"
kquota "k8s.io/kubernetes/pkg/quota"
"k8s.io/kubernetes/pkg/runtime"
osclient "github.com/openshift/origin/pkg/client"
imageapi "github.com/openshift/origin/pkg/image/api"
quotautil "github.com/openshift/origin/pkg/quota/util"
)
const imageStreamTagEvaluatorName = "Evaluator.ImageStreamTag"
// NewImageStreamTagEvaluator computes resource usage of ImageStreamsTags. Its sole purpose is to handle
// UPDATE admission operations on imageStreamTags resource.
func NewImageStreamTagEvaluator(osClient osclient.Interface) kquota.Evaluator {
computeResources := []kapi.ResourceName{
imageapi.ResourceImages,
}
matchesScopeFunc := func(kapi.ResourceQuotaScope, runtime.Object) bool { return true }
getFuncByNamespace := func(namespace, id string) (runtime.Object, error) {
nameParts := strings.SplitN(id, ":", 2)
if len(nameParts) != 2 {
return nil, fmt.Errorf("%q is an invalid id for an imagestreamtag. Must be in form <name>:<tag>.", id)
}
obj, err := osClient.ImageStreamTags(namespace).Get(nameParts[0], nameParts[1])
if err != nil {
if !kerrors.IsNotFound(err) {
return nil, err
}
obj = &imageapi.ImageStreamTag{
ObjectMeta: kapi.ObjectMeta{
Namespace: namespace,
Name: id,
},
}
}
return obj, nil
}
return quotautil.NewSharedContextEvaluator(
imageStreamTagEvaluatorName,
kapi.Kind("ImageStreamTag"),
map[admission.Operation][]kapi.ResourceName{admission.Update: computeResources},
computeResources,
matchesScopeFunc,
getFuncByNamespace,
nil,
imageStreamTagConstraintsFunc,
makeImageStreamTagUsageComputerFactory(osClient))
}
// imageStreamTagConstraintsFunc checks that given object is an image stream tag
func imageStreamTagConstraintsFunc(required []kapi.ResourceName, object runtime.Object) error {
if _, ok := object.(*imageapi.ImageStreamTag); !ok {
return fmt.Errorf("Unexpected input object %v", object)
}
return nil
}
// makeImageStreamTagUsageComputerFactory returns an object used during computation of image quota across all
// repositories in a namespace.
func makeImageStreamTagUsageComputerFactory(osClient osclient.Interface) quotautil.UsageComputerFactory {
return func() quotautil.UsageComputer {
return &imageStreamTagUsageComputer{
GenericImageStreamUsageComputer: *NewGenericImageStreamUsageComputer(osClient, false, true),
}
}
}
// imageStreamUsageComputer is a context object for use in SharedContextEvaluator.
type imageStreamTagUsageComputer struct {
GenericImageStreamUsageComputer
}
// Usage returns a usage for an image stream tag.
func (c *imageStreamTagUsageComputer) Usage(object runtime.Object) kapi.ResourceList {
ist, ok := object.(*imageapi.ImageStreamTag)
if !ok {
return kapi.ResourceList{}
}
res := map[kapi.ResourceName]resource.Quantity{
imageapi.ResourceImages: *resource.NewQuantity(0, resource.BinarySI),
}
if ist.Tag == nil {
glog.V(4).Infof("Nothing to tag to %s/%s", ist.Namespace, ist.Name)
return res
}
nameParts := strings.Split(ist.Name, ":")
if len(nameParts) != 2 {
glog.Errorf("failed to parse name of image stream tag %q", ist.Name)
return kapi.ResourceList{}
}
if ist.Tag.From == nil {
glog.V(2).Infof("from unspecified in tag reference of istag %s/%s, skipping", ist.Namespace, ist.Name)
return res
}
ref, err := c.getImageReferenceForObjectReference(ist.Namespace, ist.Tag.From)
if err != nil {
glog.Errorf("failed to get source docker image reference for istag %s/%s: %v", ist.Namespace, nameParts[0], err)
return res
}
img, err := c.getImage(ref.ID)
if err != nil {
glog.Errorf("failed to get an image %s: %v", ref.ID, err)
return res
}
_, imagesIncrement, err := c.GetProjectImagesUsageIncrement(ist.Namespace, nil, img)
if err != nil {
glog.Errorf("Failed to get namespace size increment of %q with an image %q: %v", ist.Namespace, img.Name, err)
return res
}
res[imageapi.ResourceImages] = *imagesIncrement
return res
}