TRICKY: dependencies: pkg/quota

This commit is contained in:
Chao Xu
2016-11-18 13:23:02 -08:00
parent 98a82de6d1
commit f8b36bdd40
17 changed files with 142 additions and 76 deletions

View File

@@ -30,11 +30,11 @@ go_library(
"//pkg/api/resource:go_default_library", "//pkg/api/resource:go_default_library",
"//pkg/api/unversioned:go_default_library", "//pkg/api/unversioned:go_default_library",
"//pkg/api/validation:go_default_library", "//pkg/api/validation:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/release_1_5:go_default_library",
"//pkg/controller/informers:go_default_library", "//pkg/controller/informers:go_default_library",
"//pkg/kubelet/qos:go_default_library", "//pkg/kubelet/qos:go_default_library",
"//pkg/quota:go_default_library", "//pkg/quotainternal:go_default_library",
"//pkg/quota/generic:go_default_library", "//pkg/quotainternal/generic:go_default_library",
"//pkg/runtime:go_default_library", "//pkg/runtime:go_default_library",
"//pkg/util/sets:go_default_library", "//pkg/util/sets:go_default_library",
"//pkg/util/validation/field:go_default_library", "//pkg/util/validation/field:go_default_library",
@@ -54,7 +54,7 @@ go_test(
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/resource:go_default_library", "//pkg/api/resource:go_default_library",
"//pkg/api/unversioned:go_default_library", "//pkg/api/unversioned:go_default_library",
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library", "//pkg/client/clientset_generated/release_1_5/fake:go_default_library",
"//pkg/quota:go_default_library", "//pkg/quotainternal:go_default_library",
], ],
) )

View File

@@ -19,7 +19,8 @@ package core
import ( import (
"k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/api/v1"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
"k8s.io/kubernetes/pkg/quota/generic" "k8s.io/kubernetes/pkg/quota/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
@@ -38,7 +39,7 @@ func NewConfigMapEvaluator(kubeClient clientset.Interface) quota.Evaluator {
MatchesScopeFunc: generic.MatchesNoScopeFunc, MatchesScopeFunc: generic.MatchesNoScopeFunc,
ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceConfigMaps), ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceConfigMaps),
UsageFunc: generic.ObjectCountUsageFunc(api.ResourceConfigMaps), UsageFunc: generic.ObjectCountUsageFunc(api.ResourceConfigMaps),
ListFuncByNamespace: func(namespace string, options api.ListOptions) ([]runtime.Object, error) { ListFuncByNamespace: func(namespace string, options v1.ListOptions) ([]runtime.Object, error) {
itemList, err := kubeClient.Core().ConfigMaps(namespace).List(options) itemList, err := kubeClient.Core().ConfigMaps(namespace).List(options)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -24,7 +24,8 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/api/v1"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/controller/informers" "k8s.io/kubernetes/pkg/controller/informers"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
"k8s.io/kubernetes/pkg/quota/generic" "k8s.io/kubernetes/pkg/quota/generic"
@@ -37,7 +38,7 @@ func listPersistentVolumeClaimsByNamespaceFuncUsingClient(kubeClient clientset.I
// TODO: ideally, we could pass dynamic client pool down into this code, and have one way of doing this. // TODO: ideally, we could pass dynamic client pool down into this code, and have one way of doing this.
// unfortunately, dynamic client works with Unstructured objects, and when we calculate Usage, we require // unfortunately, dynamic client works with Unstructured objects, and when we calculate Usage, we require
// structured objects. // structured objects.
return func(namespace string, options api.ListOptions) ([]runtime.Object, error) { return func(namespace string, options v1.ListOptions) ([]runtime.Object, error) {
itemList, err := kubeClient.Core().PersistentVolumeClaims(namespace).List(options) itemList, err := kubeClient.Core().PersistentVolumeClaims(namespace).List(options)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -75,13 +76,21 @@ func NewPersistentVolumeClaimEvaluator(kubeClient clientset.Interface, f informe
// PersistentVolumeClaimUsageFunc knows how to measure usage associated with persistent volume claims // PersistentVolumeClaimUsageFunc knows how to measure usage associated with persistent volume claims
func PersistentVolumeClaimUsageFunc(object runtime.Object) api.ResourceList { func PersistentVolumeClaimUsageFunc(object runtime.Object) api.ResourceList {
pvc, ok := object.(*api.PersistentVolumeClaim)
if !ok {
return api.ResourceList{}
}
result := api.ResourceList{} result := api.ResourceList{}
var found bool
var request resource.Quantity
switch t := object.(type) {
case *v1.PersistentVolumeClaim:
request, found = t.Spec.Resources.Requests[v1.ResourceStorage]
case *api.PersistentVolumeClaim:
request, found = t.Spec.Resources.Requests[api.ResourceStorage]
default:
panic(fmt.Sprintf("expect *api.PersistenVolumeClaim or *v1.PersistentVolumeClaim, got %v", t))
}
result[api.ResourcePersistentVolumeClaims] = resource.MustParse("1") result[api.ResourcePersistentVolumeClaims] = resource.MustParse("1")
if request, found := pvc.Spec.Resources.Requests[api.ResourceStorage]; found { if found {
result[api.ResourceRequestsStorage] = request result[api.ResourceRequestsStorage] = request
} }
return result return result

View File

@@ -22,7 +22,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/fake"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
) )

View File

@@ -24,8 +24,9 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/api/validation"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/controller/informers" "k8s.io/kubernetes/pkg/controller/informers"
"k8s.io/kubernetes/pkg/kubelet/qos" "k8s.io/kubernetes/pkg/kubelet/qos"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
@@ -40,7 +41,7 @@ func listPodsByNamespaceFuncUsingClient(kubeClient clientset.Interface) generic.
// TODO: ideally, we could pass dynamic client pool down into this code, and have one way of doing this. // TODO: ideally, we could pass dynamic client pool down into this code, and have one way of doing this.
// unfortunately, dynamic client works with Unstructured objects, and when we calculate Usage, we require // unfortunately, dynamic client works with Unstructured objects, and when we calculate Usage, we require
// structured objects. // structured objects.
return func(namespace string, options api.ListOptions) ([]runtime.Object, error) { return func(namespace string, options v1.ListOptions) ([]runtime.Object, error) {
itemList, err := kubeClient.Core().Pods(namespace).List(options) itemList, err := kubeClient.Core().Pods(namespace).List(options)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -163,23 +164,32 @@ func podUsageHelper(requests api.ResourceList, limits api.ResourceList) api.Reso
return result return result
} }
// PodUsageFunc knows how to measure usage associated with pods func toInternalPodOrDie(obj runtime.Object) *api.Pod {
func PodUsageFunc(object runtime.Object) api.ResourceList { pod := &api.Pod{}
pod, ok := object.(*api.Pod) switch t := obj.(type) {
if !ok { case *v1.Pod:
return api.ResourceList{} if err := v1.Convert_v1_Pod_To_api_Pod(t, pod, nil); err != nil {
panic(err)
}
case *api.Pod:
pod = t
default:
panic(fmt.Sprintf("expect *api.Pod or *v1.Pod, got %v", t))
} }
return pod
}
// PodUsageFunc knows how to measure usage associated with pods
func PodUsageFunc(obj runtime.Object) api.ResourceList {
pod := toInternalPodOrDie(obj)
// by convention, we do not quota pods that have reached an end-of-life state // by convention, we do not quota pods that have reached an end-of-life state
if !QuotaPod(pod) { if !QuotaPod(pod) {
return api.ResourceList{} return api.ResourceList{}
} }
// TODO: fix this when we have pod level cgroups
// when we have pod level cgroups, we can just read pod level requests/limits
requests := api.ResourceList{} requests := api.ResourceList{}
limits := api.ResourceList{} limits := api.ResourceList{}
// TODO: fix this when we have pod level cgroups
// when we have pod level cgroups, we can just read pod level requests/limits
for i := range pod.Spec.Containers { for i := range pod.Spec.Containers {
requests = quota.Add(requests, pod.Spec.Containers[i].Resources.Requests) requests = quota.Add(requests, pod.Spec.Containers[i].Resources.Requests)
limits = quota.Add(limits, pod.Spec.Containers[i].Resources.Limits) limits = quota.Add(limits, pod.Spec.Containers[i].Resources.Limits)
@@ -197,10 +207,7 @@ func PodUsageFunc(object runtime.Object) api.ResourceList {
// PodMatchesScopeFunc is a function that knows how to evaluate if a pod matches a scope // PodMatchesScopeFunc is a function that knows how to evaluate if a pod matches a scope
func PodMatchesScopeFunc(scope api.ResourceQuotaScope, object runtime.Object) bool { func PodMatchesScopeFunc(scope api.ResourceQuotaScope, object runtime.Object) bool {
pod, ok := object.(*api.Pod) pod := toInternalPodOrDie(object)
if !ok {
return false
}
switch scope { switch scope {
case api.ResourceQuotaScopeTerminating: case api.ResourceQuotaScopeTerminating:
return isTerminating(pod) return isTerminating(pod)
@@ -215,7 +222,7 @@ func PodMatchesScopeFunc(scope api.ResourceQuotaScope, object runtime.Object) bo
} }
func isBestEffort(pod *api.Pod) bool { func isBestEffort(pod *api.Pod) bool {
return qos.GetPodQOS(pod) == qos.BestEffort return qos.InternalGetPodQOS(pod) == qos.BestEffort
} }
func isTerminating(pod *api.Pod) bool { func isTerminating(pod *api.Pod) bool {
@@ -228,7 +235,11 @@ func isTerminating(pod *api.Pod) bool {
// QuotaPod returns true if the pod is eligible to track against a quota // QuotaPod returns true if the pod is eligible to track against a quota
// if it's not in a terminal state according to its phase. // if it's not in a terminal state according to its phase.
func QuotaPod(pod *api.Pod) bool { func QuotaPod(pod *api.Pod) bool {
// see GetPhase in kubelet.go for details on how it covers all restart policy conditions
// https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/kubelet.go#L3001
return !(api.PodFailed == pod.Status.Phase || api.PodSucceeded == pod.Status.Phase) return !(api.PodFailed == pod.Status.Phase || api.PodSucceeded == pod.Status.Phase)
} }
// QuotaV1Pod returns true if the pod is eligible to track against a quota
// if it's not in a terminal state according to its phase.
func QuotaV1Pod(pod *v1.Pod) bool {
return !(v1.PodFailed == pod.Status.Phase || v1.PodSucceeded == pod.Status.Phase)
}

View File

@@ -21,7 +21,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/fake"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
) )

View File

@@ -18,7 +18,7 @@ package core
import ( import (
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/controller/informers" "k8s.io/kubernetes/pkg/controller/informers"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
"k8s.io/kubernetes/pkg/quota/generic" "k8s.io/kubernetes/pkg/quota/generic"

View File

@@ -19,7 +19,8 @@ package core
import ( import (
"k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/api/v1"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
"k8s.io/kubernetes/pkg/quota/generic" "k8s.io/kubernetes/pkg/quota/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
@@ -38,7 +39,7 @@ func NewReplicationControllerEvaluator(kubeClient clientset.Interface) quota.Eva
MatchesScopeFunc: generic.MatchesNoScopeFunc, MatchesScopeFunc: generic.MatchesNoScopeFunc,
ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceReplicationControllers), ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceReplicationControllers),
UsageFunc: generic.ObjectCountUsageFunc(api.ResourceReplicationControllers), UsageFunc: generic.ObjectCountUsageFunc(api.ResourceReplicationControllers),
ListFuncByNamespace: func(namespace string, options api.ListOptions) ([]runtime.Object, error) { ListFuncByNamespace: func(namespace string, options v1.ListOptions) ([]runtime.Object, error) {
itemList, err := kubeClient.Core().ReplicationControllers(namespace).List(options) itemList, err := kubeClient.Core().ReplicationControllers(namespace).List(options)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -19,7 +19,8 @@ package core
import ( import (
"k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/api/v1"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
"k8s.io/kubernetes/pkg/quota/generic" "k8s.io/kubernetes/pkg/quota/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
@@ -38,7 +39,7 @@ func NewResourceQuotaEvaluator(kubeClient clientset.Interface) quota.Evaluator {
MatchesScopeFunc: generic.MatchesNoScopeFunc, MatchesScopeFunc: generic.MatchesNoScopeFunc,
ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceQuotas), ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceQuotas),
UsageFunc: generic.ObjectCountUsageFunc(api.ResourceQuotas), UsageFunc: generic.ObjectCountUsageFunc(api.ResourceQuotas),
ListFuncByNamespace: func(namespace string, options api.ListOptions) ([]runtime.Object, error) { ListFuncByNamespace: func(namespace string, options v1.ListOptions) ([]runtime.Object, error) {
itemList, err := kubeClient.Core().ResourceQuotas(namespace).List(options) itemList, err := kubeClient.Core().ResourceQuotas(namespace).List(options)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -19,7 +19,8 @@ package core
import ( import (
"k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/api/v1"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
"k8s.io/kubernetes/pkg/quota/generic" "k8s.io/kubernetes/pkg/quota/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
@@ -38,7 +39,7 @@ func NewSecretEvaluator(kubeClient clientset.Interface) quota.Evaluator {
MatchesScopeFunc: generic.MatchesNoScopeFunc, MatchesScopeFunc: generic.MatchesNoScopeFunc,
ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceSecrets), ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceSecrets),
UsageFunc: generic.ObjectCountUsageFunc(api.ResourceSecrets), UsageFunc: generic.ObjectCountUsageFunc(api.ResourceSecrets),
ListFuncByNamespace: func(namespace string, options api.ListOptions) ([]runtime.Object, error) { ListFuncByNamespace: func(namespace string, options v1.ListOptions) ([]runtime.Object, error) {
itemList, err := kubeClient.Core().Secrets(namespace).List(options) itemList, err := kubeClient.Core().Secrets(namespace).List(options)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -23,7 +23,8 @@ import (
"k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/api/v1"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
"k8s.io/kubernetes/pkg/quota/generic" "k8s.io/kubernetes/pkg/quota/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
@@ -48,7 +49,7 @@ func NewServiceEvaluator(kubeClient clientset.Interface) quota.Evaluator {
MatchesScopeFunc: generic.MatchesNoScopeFunc, MatchesScopeFunc: generic.MatchesNoScopeFunc,
ConstraintsFunc: ServiceConstraintsFunc, ConstraintsFunc: ServiceConstraintsFunc,
UsageFunc: ServiceUsageFunc, UsageFunc: ServiceUsageFunc,
ListFuncByNamespace: func(namespace string, options api.ListOptions) ([]runtime.Object, error) { ListFuncByNamespace: func(namespace string, options v1.ListOptions) ([]runtime.Object, error) {
itemList, err := kubeClient.Core().Services(namespace).List(options) itemList, err := kubeClient.Core().Services(namespace).List(options)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -65,42 +66,54 @@ func NewServiceEvaluator(kubeClient clientset.Interface) quota.Evaluator {
// ServiceUsageFunc knows how to measure usage associated with services // ServiceUsageFunc knows how to measure usage associated with services
func ServiceUsageFunc(object runtime.Object) api.ResourceList { func ServiceUsageFunc(object runtime.Object) api.ResourceList {
result := api.ResourceList{} result := api.ResourceList{}
if service, ok := object.(*api.Service); ok { var serviceType api.ServiceType
// default service usage var ports int
result[api.ResourceServices] = resource.MustParse("1")
result[api.ResourceServicesLoadBalancers] = resource.MustParse("0") switch t := object.(type) {
result[api.ResourceServicesNodePorts] = resource.MustParse("0") case *v1.Service:
switch service.Spec.Type { serviceType = api.ServiceType(t.Spec.Type)
case api.ServiceTypeNodePort: ports = len(t.Spec.Ports)
// node port services need to count node ports case *api.Service:
value := resource.NewQuantity(int64(len(service.Spec.Ports)), resource.DecimalSI) serviceType = t.Spec.Type
result[api.ResourceServicesNodePorts] = *value ports = len(t.Spec.Ports)
case api.ServiceTypeLoadBalancer: default:
// load balancer services need to count load balancers panic(fmt.Sprintf("expect *api.Service or *v1.Service, got %v", t))
result[api.ResourceServicesLoadBalancers] = resource.MustParse("1") }
}
// default service usage
result[api.ResourceServices] = resource.MustParse("1")
result[api.ResourceServicesLoadBalancers] = resource.MustParse("0")
result[api.ResourceServicesNodePorts] = resource.MustParse("0")
switch serviceType {
case api.ServiceTypeNodePort:
// node port services need to count node ports
value := resource.NewQuantity(int64(ports), resource.DecimalSI)
result[api.ResourceServicesNodePorts] = *value
case api.ServiceTypeLoadBalancer:
// load balancer services need to count load balancers
result[api.ResourceServicesLoadBalancers] = resource.MustParse("1")
} }
return result return result
} }
// QuotaServiceType returns true if the service type is eligible to track against a quota // QuotaServiceType returns true if the service type is eligible to track against a quota
func QuotaServiceType(service *api.Service) bool { func QuotaServiceType(service *v1.Service) bool {
switch service.Spec.Type { switch service.Spec.Type {
case api.ServiceTypeNodePort, api.ServiceTypeLoadBalancer: case v1.ServiceTypeNodePort, v1.ServiceTypeLoadBalancer:
return true return true
} }
return false return false
} }
//GetQuotaServiceType returns ServiceType if the service type is eligible to track against a quota, nor return "" //GetQuotaServiceType returns ServiceType if the service type is eligible to track against a quota, nor return ""
func GetQuotaServiceType(service *api.Service) api.ServiceType { func GetQuotaServiceType(service *v1.Service) v1.ServiceType {
switch service.Spec.Type { switch service.Spec.Type {
case api.ServiceTypeNodePort: case v1.ServiceTypeNodePort:
return api.ServiceTypeNodePort return v1.ServiceTypeNodePort
case api.ServiceTypeLoadBalancer: case v1.ServiceTypeLoadBalancer:
return api.ServiceTypeLoadBalancer return v1.ServiceTypeLoadBalancer
} }
return api.ServiceType("") return v1.ServiceType("")
} }
// ServiceConstraintsFunc verifies that all required resources are captured in service usage. // ServiceConstraintsFunc verifies that all required resources are captured in service usage.

View File

@@ -21,7 +21,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/fake"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
) )

View File

@@ -24,7 +24,7 @@ go_library(
"//pkg/api/unversioned:go_default_library", "//pkg/api/unversioned:go_default_library",
"//pkg/controller/informers:go_default_library", "//pkg/controller/informers:go_default_library",
"//pkg/labels:go_default_library", "//pkg/labels:go_default_library",
"//pkg/quota:go_default_library", "//pkg/quotainternal:go_default_library",
"//pkg/runtime:go_default_library", "//pkg/runtime:go_default_library",
], ],
) )

View File

@@ -23,6 +23,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/controller/informers" "k8s.io/kubernetes/pkg/controller/informers"
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
@@ -31,12 +32,16 @@ import (
// ListResourceUsingInformerFunc returns a listing function based on the shared informer factory for the specified resource. // ListResourceUsingInformerFunc returns a listing function based on the shared informer factory for the specified resource.
func ListResourceUsingInformerFunc(f informers.SharedInformerFactory, groupResource unversioned.GroupResource) ListFuncByNamespace { func ListResourceUsingInformerFunc(f informers.SharedInformerFactory, groupResource unversioned.GroupResource) ListFuncByNamespace {
return func(namespace string, options api.ListOptions) ([]runtime.Object, error) { return func(namespace string, options v1.ListOptions) ([]runtime.Object, error) {
labelSelector, err := labels.Parse(options.LabelSelector)
if err != nil {
return nil, err
}
informer, err := f.ForResource(groupResource) informer, err := f.ForResource(groupResource)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return informer.Lister().ByNamespace(namespace).List(options.LabelSelector) return informer.Lister().ByNamespace(namespace).List(labelSelector)
} }
} }
@@ -47,7 +52,7 @@ type ConstraintsFunc func(required []api.ResourceName, item runtime.Object) erro
type GetFuncByNamespace func(namespace, name string) (runtime.Object, error) type GetFuncByNamespace func(namespace, name string) (runtime.Object, error)
// ListFuncByNamespace knows how to list resources in a namespace // ListFuncByNamespace knows how to list resources in a namespace
type ListFuncByNamespace func(namespace string, options api.ListOptions) ([]runtime.Object, error) type ListFuncByNamespace func(namespace string, options v1.ListOptions) ([]runtime.Object, error)
// MatchesScopeFunc knows how to evaluate if an object matches a scope // MatchesScopeFunc knows how to evaluate if an object matches a scope
type MatchesScopeFunc func(scope api.ResourceQuotaScope, object runtime.Object) bool type MatchesScopeFunc func(scope api.ResourceQuotaScope, object runtime.Object) bool
@@ -183,8 +188,8 @@ func (g *GenericEvaluator) UsageStats(options quota.UsageStatsOptions) (quota.Us
for _, resourceName := range g.MatchedResourceNames { for _, resourceName := range g.MatchedResourceNames {
result.Used[resourceName] = resource.MustParse("0") result.Used[resourceName] = resource.MustParse("0")
} }
items, err := g.ListFuncByNamespace(options.Namespace, api.ListOptions{ items, err := g.ListFuncByNamespace(options.Namespace, v1.ListOptions{
LabelSelector: labels.Everything(), LabelSelector: labels.Everything().String(),
}) })
if err != nil { if err != nil {
return result, fmt.Errorf("%s: Failed to list %v: %v", g.Name, g.GroupKind(), err) return result, fmt.Errorf("%s: Failed to list %v: %v", g.Name, g.GroupKind(), err)

View File

@@ -15,9 +15,9 @@ go_library(
srcs = ["registry.go"], srcs = ["registry.go"],
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/release_1_5:go_default_library",
"//pkg/controller/informers:go_default_library", "//pkg/controller/informers:go_default_library",
"//pkg/quota:go_default_library", "//pkg/quotainternal:go_default_library",
"//pkg/quota/evaluator/core:go_default_library", "//pkg/quotainternal/evaluator/core:go_default_library",
], ],
) )

View File

@@ -17,7 +17,7 @@ limitations under the License.
package install package install
import ( import (
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/controller/informers" "k8s.io/kubernetes/pkg/controller/informers"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
"k8s.io/kubernetes/pkg/quota/evaluator/core" "k8s.io/kubernetes/pkg/quota/evaluator/core"

View File

@@ -19,6 +19,7 @@ package quota
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
) )
@@ -45,6 +46,29 @@ func Equals(a api.ResourceList, b api.ResourceList) bool {
return true return true
} }
// V1Equals returns true if the two lists are equivalent
func V1Equals(a v1.ResourceList, b v1.ResourceList) bool {
for key, value1 := range a {
value2, found := b[key]
if !found {
return false
}
if value1.Cmp(value2) != 0 {
return false
}
}
for key, value1 := range b {
value2, found := a[key]
if !found {
return false
}
if value1.Cmp(value2) != 0 {
return false
}
}
return true
}
// LessThanOrEqual returns true if a < b for each key in b // LessThanOrEqual returns true if a < b for each key in b
// If false, it returns the keys in a that exceeded b // If false, it returns the keys in a that exceeded b
func LessThanOrEqual(a api.ResourceList, b api.ResourceList) (bool, []api.ResourceName) { func LessThanOrEqual(a api.ResourceList, b api.ResourceList) (bool, []api.ResourceName) {