Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
ec3b0886
Commit
ec3b0886
authored
Aug 27, 2018
by
yue9944882
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
directly switching quota pkg
parent
48dd084a
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
547 additions
and
552 deletions
+547
-552
BUILD
pkg/quota/BUILD
+1
-38
BUILD
pkg/quota/v1/BUILD
+53
-0
OWNERS
pkg/quota/v1/OWNERS
+0
-0
OWNERS
pkg/quota/v1/evaluator/OWNERS
+0
-0
BUILD
pkg/quota/v1/evaluator/core/BUILD
+8
-7
doc.go
pkg/quota/v1/evaluator/core/doc.go
+1
-1
persistent_volume_claims.go
pkg/quota/v1/evaluator/core/persistent_volume_claims.go
+39
-37
persistent_volume_claims_test.go
pkg/quota/v1/evaluator/core/persistent_volume_claims_test.go
+12
-11
pods.go
pkg/quota/v1/evaluator/core/pods.go
+92
-117
pods_test.go
pkg/quota/v1/evaluator/core/pods_test.go
+66
-65
registry.go
pkg/quota/v1/evaluator/core/registry.go
+8
-9
services.go
pkg/quota/v1/evaluator/core/services.go
+40
-40
services_test.go
pkg/quota/v1/evaluator/core/services_test.go
+39
-38
BUILD
pkg/quota/v1/generic/BUILD
+3
-3
OWNERS
pkg/quota/v1/generic/OWNERS
+0
-0
configuration.go
pkg/quota/v1/generic/configuration.go
+1
-1
evaluator.go
pkg/quota/v1/generic/evaluator.go
+28
-28
registry.go
pkg/quota/v1/generic/registry.go
+1
-1
BUILD
pkg/quota/v1/install/BUILD
+4
-4
OWNERS
pkg/quota/v1/install/OWNERS
+0
-0
registry.go
pkg/quota/v1/install/registry.go
+3
-3
interfaces.go
pkg/quota/v1/interfaces.go
+11
-11
resources.go
pkg/quota/v1/resources.go
+29
-30
resources_test.go
pkg/quota/v1/resources_test.go
+108
-108
No files found.
pkg/quota/BUILD
View file @
ec3b0886
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"interfaces.go",
"resources.go",
],
importpath = "k8s.io/kubernetes/pkg/quota",
deps = [
"//pkg/apis/core:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["resources_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
...
...
@@ -46,9 +11,7 @@ filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//pkg/quota/evaluator/core:all-srcs",
"//pkg/quota/generic:all-srcs",
"//pkg/quota/install:all-srcs",
"//pkg/quota/v1:all-srcs",
],
tags = ["automanaged"],
)
pkg/quota/v1/BUILD
0 → 100644
View file @
ec3b0886
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"interfaces.go",
"resources.go",
],
importpath = "k8s.io/kubernetes/pkg/quota/v1",
deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["resources_test.go"],
embed = [":go_default_library"],
deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//pkg/quota/v1/evaluator/core:all-srcs",
"//pkg/quota/v1/generic:all-srcs",
"//pkg/quota/v1/install:all-srcs",
],
tags = ["automanaged"],
)
pkg/quota/OWNERS
→
pkg/quota/
v1/
OWNERS
View file @
ec3b0886
File moved
pkg/quota/evaluator/OWNERS
→
pkg/quota/
v1/
evaluator/OWNERS
View file @
ec3b0886
File moved
pkg/quota/evaluator/core/BUILD
→
pkg/quota/
v1/
evaluator/core/BUILD
View file @
ec3b0886
...
...
@@ -15,16 +15,16 @@ go_library(
"registry.go",
"services.go",
],
importpath = "k8s.io/kubernetes/pkg/quota/evaluator/core",
importpath = "k8s.io/kubernetes/pkg/quota/
v1/
evaluator/core",
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/helper:go_default_library",
"//pkg/apis/core/helper/qos:go_default_library",
"//pkg/apis/core/v1:go_default_library",
"//pkg/apis/core/v1/helper:go_default_library",
"//pkg/apis/core/v1/helper/qos:go_default_library",
"//pkg/features:go_default_library",
"//pkg/kubeapiserver/admission/util:go_default_library",
"//pkg/quota:go_default_library",
"//pkg/quota/generic:go_default_library",
"//pkg/quota
/v1
:go_default_library",
"//pkg/quota/
v1/
generic:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
...
...
@@ -50,9 +50,10 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/quota:go_default_library",
"//pkg/quota/generic:go_default_library",
"//pkg/quota
/v1
:go_default_library",
"//pkg/quota/
v1/
generic:go_default_library",
"//pkg/util/node:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
...
...
pkg/quota/evaluator/core/doc.go
→
pkg/quota/
v1/
evaluator/core/doc.go
View file @
ec3b0886
...
...
@@ -15,4 +15,4 @@ limitations under the License.
*/
// core contains modules that interface with the core api group
package
core
// import "k8s.io/kubernetes/pkg/quota/evaluator/core"
package
core
// import "k8s.io/kubernetes/pkg/quota/
v1/
evaluator/core"
pkg/quota/evaluator/core/persistent_volume_claims.go
→
pkg/quota/
v1/
evaluator/core/persistent_volume_claims.go
View file @
ec3b0886
...
...
@@ -20,7 +20,7 @@ import (
"fmt"
"strings"
"k8s.io/api/core/v1"
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
...
...
@@ -30,22 +30,22 @@ import (
"k8s.io/apiserver/pkg/features"
utilfeature
"k8s.io/apiserver/pkg/util/feature"
api
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/core/helper"
k8s_api_v1
"k8s.io/kubernetes/pkg/apis/core/v1"
"k8s.io/kubernetes/pkg/apis/core/v1/helper"
k8sfeatures
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util"
"k8s.io/kubernetes/pkg/quota
"
"k8s.io/kubernetes/pkg/quota/generic"
quota
"k8s.io/kubernetes/pkg/quota/v1
"
"k8s.io/kubernetes/pkg/quota/
v1/
generic"
)
// the name used for object count quota
var
pvcObjectCountName
=
generic
.
ObjectCountQuotaResourceNameFor
(
v1
.
SchemeGroupVersion
.
WithResource
(
"persistentvolumeclaims"
)
.
GroupResource
())
var
pvcObjectCountName
=
generic
.
ObjectCountQuotaResourceNameFor
(
core
v1
.
SchemeGroupVersion
.
WithResource
(
"persistentvolumeclaims"
)
.
GroupResource
())
// pvcResources are the set of static resources managed by quota associated with pvcs.
// for each resource in this list, it may be refined dynamically based on storage class.
var
pvcResources
=
[]
api
.
ResourceName
{
api
.
ResourcePersistentVolumeClaims
,
api
.
ResourceRequestsStorage
,
var
pvcResources
=
[]
corev1
.
ResourceName
{
corev1
.
ResourcePersistentVolumeClaims
,
corev1
.
ResourceRequestsStorage
,
}
// storageClassSuffix is the suffix to the qualified portion of storage class resource name.
...
...
@@ -56,19 +56,21 @@ var pvcResources = []api.ResourceName{
// * bronze.storageclass.storage.k8s.io/requests.storage: 500Gi
const
storageClassSuffix
string
=
".storageclass.storage.k8s.io/"
/* TODO: prune?
// ResourceByStorageClass returns a quota resource name by storage class.
func
ResourceByStorageClass
(
storageClass
string
,
resourceName
api
.
ResourceName
)
api
.
ResourceName
{
return
api
.
ResourceName
(
string
(
storageClass
+
storageClassSuffix
+
string
(
resourceName
)))
func ResourceByStorageClass(storageClass string, resourceName
corev1.ResourceName) corev1
.ResourceName {
return
corev1
.ResourceName(string(storageClass + storageClassSuffix + string(resourceName)))
}
*/
// V1ResourceByStorageClass returns a quota resource name by storage class.
func
V1ResourceByStorageClass
(
storageClass
string
,
resourceName
v1
.
ResourceName
)
v1
.
ResourceName
{
return
v1
.
ResourceName
(
string
(
storageClass
+
storageClassSuffix
+
string
(
resourceName
)))
func
V1ResourceByStorageClass
(
storageClass
string
,
resourceName
corev1
.
ResourceName
)
core
v1
.
ResourceName
{
return
core
v1
.
ResourceName
(
string
(
storageClass
+
storageClassSuffix
+
string
(
resourceName
)))
}
// NewPersistentVolumeClaimEvaluator returns an evaluator that can evaluate persistent volume claims
func
NewPersistentVolumeClaimEvaluator
(
f
quota
.
ListerForResourceFunc
)
quota
.
Evaluator
{
listFuncByNamespace
:=
generic
.
ListResourceUsingListerFunc
(
f
,
v1
.
SchemeGroupVersion
.
WithResource
(
"persistentvolumeclaims"
))
listFuncByNamespace
:=
generic
.
ListResourceUsingListerFunc
(
f
,
core
v1
.
SchemeGroupVersion
.
WithResource
(
"persistentvolumeclaims"
))
pvcEvaluator
:=
&
pvcEvaluator
{
listFuncByNamespace
:
listFuncByNamespace
}
return
pvcEvaluator
}
...
...
@@ -80,14 +82,14 @@ type pvcEvaluator struct {
}
// Constraints verifies that all required resources are present on the item.
func
(
p
*
pvcEvaluator
)
Constraints
(
required
[]
api
.
ResourceName
,
item
runtime
.
Object
)
error
{
func
(
p
*
pvcEvaluator
)
Constraints
(
required
[]
corev1
.
ResourceName
,
item
runtime
.
Object
)
error
{
// no-op for persistent volume claims
return
nil
}
// GroupResource that this evaluator tracks
func
(
p
*
pvcEvaluator
)
GroupResource
()
schema
.
GroupResource
{
return
v1
.
SchemeGroupVersion
.
WithResource
(
"persistentvolumeclaims"
)
.
GroupResource
()
return
core
v1
.
SchemeGroupVersion
.
WithResource
(
"persistentvolumeclaims"
)
.
GroupResource
()
}
// Handles returns true if the evaluator should handle the specified operation.
...
...
@@ -119,27 +121,27 @@ func (p *pvcEvaluator) Handles(a admission.Attributes) bool {
}
// Matches returns true if the evaluator matches the specified quota with the provided input item
func
(
p
*
pvcEvaluator
)
Matches
(
resourceQuota
*
api
.
ResourceQuota
,
item
runtime
.
Object
)
(
bool
,
error
)
{
func
(
p
*
pvcEvaluator
)
Matches
(
resourceQuota
*
corev1
.
ResourceQuota
,
item
runtime
.
Object
)
(
bool
,
error
)
{
return
generic
.
Matches
(
resourceQuota
,
item
,
p
.
MatchingResources
,
generic
.
MatchesNoScopeFunc
)
}
// MatchingScopes takes the input specified list of scopes and input object. Returns the set of scopes resource matches.
func
(
p
*
pvcEvaluator
)
MatchingScopes
(
item
runtime
.
Object
,
scopes
[]
api
.
ScopedResourceSelectorRequirement
)
([]
api
.
ScopedResourceSelectorRequirement
,
error
)
{
return
[]
api
.
ScopedResourceSelectorRequirement
{},
nil
func
(
p
*
pvcEvaluator
)
MatchingScopes
(
item
runtime
.
Object
,
scopes
[]
corev1
.
ScopedResourceSelectorRequirement
)
([]
corev1
.
ScopedResourceSelectorRequirement
,
error
)
{
return
[]
corev1
.
ScopedResourceSelectorRequirement
{},
nil
}
// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes.
// It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope
func
(
p
*
pvcEvaluator
)
UncoveredQuotaScopes
(
limitedScopes
[]
api
.
ScopedResourceSelectorRequirement
,
matchedQuotaScopes
[]
api
.
ScopedResourceSelectorRequirement
)
([]
api
.
ScopedResourceSelectorRequirement
,
error
)
{
return
[]
api
.
ScopedResourceSelectorRequirement
{},
nil
func
(
p
*
pvcEvaluator
)
UncoveredQuotaScopes
(
limitedScopes
[]
corev1
.
ScopedResourceSelectorRequirement
,
matchedQuotaScopes
[]
corev1
.
ScopedResourceSelectorRequirement
)
([]
corev1
.
ScopedResourceSelectorRequirement
,
error
)
{
return
[]
corev1
.
ScopedResourceSelectorRequirement
{},
nil
}
// MatchingResources takes the input specified list of resources and returns the set of resources it matches.
func
(
p
*
pvcEvaluator
)
MatchingResources
(
items
[]
api
.
ResourceName
)
[]
api
.
ResourceName
{
result
:=
[]
api
.
ResourceName
{}
func
(
p
*
pvcEvaluator
)
MatchingResources
(
items
[]
corev1
.
ResourceName
)
[]
corev1
.
ResourceName
{
result
:=
[]
corev1
.
ResourceName
{}
for
_
,
item
:=
range
items
{
// match object count quota fields
if
quota
.
Contains
([]
api
.
ResourceName
{
pvcObjectCountName
},
item
)
{
if
quota
.
Contains
([]
corev1
.
ResourceName
{
pvcObjectCountName
},
item
)
{
result
=
append
(
result
,
item
)
continue
}
...
...
@@ -161,15 +163,15 @@ func (p *pvcEvaluator) MatchingResources(items []api.ResourceName) []api.Resourc
}
// Usage knows how to measure usage associated with item.
func
(
p
*
pvcEvaluator
)
Usage
(
item
runtime
.
Object
)
(
api
.
ResourceList
,
error
)
{
result
:=
api
.
ResourceList
{}
pvc
,
err
:=
to
In
ternalPersistentVolumeClaimOrError
(
item
)
func
(
p
*
pvcEvaluator
)
Usage
(
item
runtime
.
Object
)
(
corev1
.
ResourceList
,
error
)
{
result
:=
corev1
.
ResourceList
{}
pvc
,
err
:=
to
Ex
ternalPersistentVolumeClaimOrError
(
item
)
if
err
!=
nil
{
return
result
,
err
}
// charge for claim
result
[
api
.
ResourcePersistentVolumeClaims
]
=
*
(
resource
.
NewQuantity
(
1
,
resource
.
DecimalSI
))
result
[
corev1
.
ResourcePersistentVolumeClaims
]
=
*
(
resource
.
NewQuantity
(
1
,
resource
.
DecimalSI
))
result
[
pvcObjectCountName
]
=
*
(
resource
.
NewQuantity
(
1
,
resource
.
DecimalSI
))
if
utilfeature
.
DefaultFeatureGate
.
Enabled
(
features
.
Initializers
)
{
if
!
initialization
.
IsInitialized
(
pvc
.
Initializers
)
{
...
...
@@ -179,16 +181,16 @@ func (p *pvcEvaluator) Usage(item runtime.Object) (api.ResourceList, error) {
}
storageClassRef
:=
helper
.
GetPersistentVolumeClaimClass
(
pvc
)
if
len
(
storageClassRef
)
>
0
{
storageClassClaim
:=
api
.
ResourceName
(
storageClassRef
+
storageClassSuffix
+
string
(
api
.
ResourcePersistentVolumeClaims
))
storageClassClaim
:=
corev1
.
ResourceName
(
storageClassRef
+
storageClassSuffix
+
string
(
corev1
.
ResourcePersistentVolumeClaims
))
result
[
storageClassClaim
]
=
*
(
resource
.
NewQuantity
(
1
,
resource
.
DecimalSI
))
}
// charge for storage
if
request
,
found
:=
pvc
.
Spec
.
Resources
.
Requests
[
api
.
ResourceStorage
];
found
{
result
[
api
.
ResourceRequestsStorage
]
=
request
if
request
,
found
:=
pvc
.
Spec
.
Resources
.
Requests
[
corev1
.
ResourceStorage
];
found
{
result
[
corev1
.
ResourceRequestsStorage
]
=
request
// charge usage to the storage class (if present)
if
len
(
storageClassRef
)
>
0
{
storageClassStorage
:=
api
.
ResourceName
(
storageClassRef
+
storageClassSuffix
+
string
(
api
.
ResourceRequestsStorage
))
storageClassStorage
:=
corev1
.
ResourceName
(
storageClassRef
+
storageClassSuffix
+
string
(
corev1
.
ResourceRequestsStorage
))
result
[
storageClassStorage
]
=
request
}
}
...
...
@@ -203,15 +205,15 @@ func (p *pvcEvaluator) UsageStats(options quota.UsageStatsOptions) (quota.UsageS
// ensure we implement required interface
var
_
quota
.
Evaluator
=
&
pvcEvaluator
{}
func
to
InternalPersistentVolumeClaimOrError
(
obj
runtime
.
Object
)
(
*
api
.
PersistentVolumeClaim
,
error
)
{
pvc
:=
&
api
.
PersistentVolumeClaim
{}
func
to
ExternalPersistentVolumeClaimOrError
(
obj
runtime
.
Object
)
(
*
corev1
.
PersistentVolumeClaim
,
error
)
{
pvc
:=
&
corev1
.
PersistentVolumeClaim
{}
switch
t
:=
obj
.
(
type
)
{
case
*
v1
.
PersistentVolumeClaim
:
if
err
:=
k8s_api_v1
.
Convert_v1_PersistentVolumeClaim_To_core_PersistentVolumeClaim
(
t
,
pvc
,
nil
);
err
!=
nil
{
case
*
corev1
.
PersistentVolumeClaim
:
pvc
=
t
case
*
api
.
PersistentVolumeClaim
:
if
err
:=
k8s_api_v1
.
Convert_core_PersistentVolumeClaim_To_v1_PersistentVolumeClaim
(
t
,
pvc
,
nil
);
err
!=
nil
{
return
nil
,
err
}
case
*
api
.
PersistentVolumeClaim
:
pvc
=
t
default
:
return
nil
,
fmt
.
Errorf
(
"expect *api.PersistentVolumeClaim or *v1.PersistentVolumeClaim, got %v"
,
t
)
}
...
...
pkg/quota/evaluator/core/persistent_volume_claims_test.go
→
pkg/quota/
v1/
evaluator/core/persistent_volume_claims_test.go
View file @
ec3b0886
...
...
@@ -19,12 +19,13 @@ package core
import
(
"testing"
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
api
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/quota
"
"k8s.io/kubernetes/pkg/quota/generic"
quota
"k8s.io/kubernetes/pkg/quota/v1
"
"k8s.io/kubernetes/pkg/quota/
v1/
generic"
)
func
testVolumeClaim
(
name
string
,
namespace
string
,
spec
api
.
PersistentVolumeClaimSpec
)
*
api
.
PersistentVolumeClaim
{
...
...
@@ -79,23 +80,23 @@ func TestPersistentVolumeClaimEvaluatorUsage(t *testing.T) {
evaluator
:=
NewPersistentVolumeClaimEvaluator
(
nil
)
testCases
:=
map
[
string
]
struct
{
pvc
*
api
.
PersistentVolumeClaim
usage
api
.
ResourceList
usage
corev1
.
ResourceList
}{
"pvc-usage"
:
{
pvc
:
validClaim
,
usage
:
api
.
ResourceList
{
api
.
ResourceRequestsStorage
:
resource
.
MustParse
(
"10Gi"
),
api
.
ResourcePersistentVolumeClaims
:
resource
.
MustParse
(
"1"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceRequestsStorage
:
resource
.
MustParse
(
"10Gi"
),
corev1
.
ResourcePersistentVolumeClaims
:
resource
.
MustParse
(
"1"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"persistentvolumeclaims"
})
:
resource
.
MustParse
(
"1"
),
},
},
"pvc-usage-by-class"
:
{
pvc
:
validClaimByStorageClass
,
usage
:
api
.
ResourceList
{
api
.
ResourceRequestsStorage
:
resource
.
MustParse
(
"10Gi"
),
api
.
ResourcePersistentVolumeClaims
:
resource
.
MustParse
(
"1"
),
ResourceByStorageClass
(
classGold
,
api
.
ResourceRequestsStorage
)
:
resource
.
MustParse
(
"10Gi"
),
ResourceByStorageClass
(
classGold
,
api
.
ResourcePersistentVolumeClaims
)
:
resource
.
MustParse
(
"1"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceRequestsStorage
:
resource
.
MustParse
(
"10Gi"
),
corev1
.
ResourcePersistentVolumeClaims
:
resource
.
MustParse
(
"1"
),
V1ResourceByStorageClass
(
classGold
,
corev1
.
ResourceRequestsStorage
)
:
resource
.
MustParse
(
"10Gi"
),
V1ResourceByStorageClass
(
classGold
,
corev1
.
ResourcePersistentVolumeClaims
)
:
resource
.
MustParse
(
"1"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"persistentvolumeclaims"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
pkg/quota/evaluator/core/pods.go
→
pkg/quota/
v1/
evaluator/core/pods.go
View file @
ec3b0886
...
...
@@ -21,7 +21,7 @@ import (
"strings"
"time"
"k8s.io/api/core/v1"
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
...
...
@@ -32,57 +32,57 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/admission"
api
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/core/helper"
"k8s.io/kubernetes/pkg/apis/core/helper/qos"
k8s_api_v1
"k8s.io/kubernetes/pkg/apis/core/v1"
"k8s.io/kubernetes/pkg/apis/core/v1/helper"
"k8s.io/kubernetes/pkg/apis/core/v1/helper/qos"
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util"
"k8s.io/kubernetes/pkg/quota
"
"k8s.io/kubernetes/pkg/quota/generic"
quota
"k8s.io/kubernetes/pkg/quota/v1
"
"k8s.io/kubernetes/pkg/quota/
v1/
generic"
)
// the name used for object count quota
var
podObjectCountName
=
generic
.
ObjectCountQuotaResourceNameFor
(
v1
.
SchemeGroupVersion
.
WithResource
(
"pods"
)
.
GroupResource
())
var
podObjectCountName
=
generic
.
ObjectCountQuotaResourceNameFor
(
core
v1
.
SchemeGroupVersion
.
WithResource
(
"pods"
)
.
GroupResource
())
// podResources are the set of resources managed by quota associated with pods.
var
podResources
=
[]
api
.
ResourceName
{
var
podResources
=
[]
corev1
.
ResourceName
{
podObjectCountName
,
api
.
ResourceCPU
,
api
.
ResourceMemory
,
api
.
ResourceEphemeralStorage
,
api
.
ResourceRequestsCPU
,
api
.
ResourceRequestsMemory
,
api
.
ResourceRequestsEphemeralStorage
,
api
.
ResourceLimitsCPU
,
api
.
ResourceLimitsMemory
,
api
.
ResourceLimitsEphemeralStorage
,
api
.
ResourcePods
,
corev1
.
ResourceCPU
,
corev1
.
ResourceMemory
,
corev1
.
ResourceEphemeralStorage
,
corev1
.
ResourceRequestsCPU
,
corev1
.
ResourceRequestsMemory
,
corev1
.
ResourceRequestsEphemeralStorage
,
corev1
.
ResourceLimitsCPU
,
corev1
.
ResourceLimitsMemory
,
corev1
.
ResourceLimitsEphemeralStorage
,
corev1
.
ResourcePods
,
}
// podResourcePrefixes are the set of prefixes for resources (Hugepages, and other
// potential extended reources with specific prefix) managed by quota associated with pods.
var
podResourcePrefixes
=
[]
string
{
api
.
ResourceHugePagesPrefix
,
api
.
ResourceRequestsHugePagesPrefix
,
corev1
.
ResourceHugePagesPrefix
,
corev1
.
ResourceRequestsHugePagesPrefix
,
}
// requestedResourcePrefixes are the set of prefixes for resources
// that might be declared in pod's Resources.Requests/Limits
var
requestedResourcePrefixes
=
[]
string
{
api
.
ResourceHugePagesPrefix
,
corev1
.
ResourceHugePagesPrefix
,
}
// maskResourceWithPrefix mask resource with certain prefix
// e.g. hugepages-XXX -> requests.hugepages-XXX
func
maskResourceWithPrefix
(
resource
api
.
ResourceName
,
prefix
string
)
api
.
ResourceName
{
return
api
.
ResourceName
(
fmt
.
Sprintf
(
"%s%s"
,
prefix
,
string
(
resource
)))
func
maskResourceWithPrefix
(
resource
corev1
.
ResourceName
,
prefix
string
)
corev1
.
ResourceName
{
return
corev1
.
ResourceName
(
fmt
.
Sprintf
(
"%s%s"
,
prefix
,
string
(
resource
)))
}
// isExtendedResourceNameForQuota returns true if the extended resource name
// has the quota related resource prefix.
func
isExtendedResourceNameForQuota
(
name
api
.
ResourceName
)
bool
{
func
isExtendedResourceNameForQuota
(
name
corev1
.
ResourceName
)
bool
{
// As overcommit is not supported by extended resources for now,
// only quota objects in format of "requests.resourceName" is allowed.
return
!
helper
.
IsNativeResource
(
name
)
&&
strings
.
HasPrefix
(
string
(
name
),
api
.
DefaultResourceRequestsPrefix
)
return
!
helper
.
IsNativeResource
(
name
)
&&
strings
.
HasPrefix
(
string
(
name
),
corev1
.
DefaultResourceRequestsPrefix
)
}
// NOTE: it was a mistake, but if a quota tracks cpu or memory related resources,
...
...
@@ -90,17 +90,17 @@ func isExtendedResourceNameForQuota(name api.ResourceName) bool {
// this mistake for other future resources (gpus, ephemeral-storage,etc).
// do not add more resources to this list!
var
validationSet
=
sets
.
NewString
(
string
(
api
.
ResourceCPU
),
string
(
api
.
ResourceMemory
),
string
(
api
.
ResourceRequestsCPU
),
string
(
api
.
ResourceRequestsMemory
),
string
(
api
.
ResourceLimitsCPU
),
string
(
api
.
ResourceLimitsMemory
),
string
(
corev1
.
ResourceCPU
),
string
(
corev1
.
ResourceMemory
),
string
(
corev1
.
ResourceRequestsCPU
),
string
(
corev1
.
ResourceRequestsMemory
),
string
(
corev1
.
ResourceLimitsCPU
),
string
(
corev1
.
ResourceLimitsMemory
),
)
// NewPodEvaluator returns an evaluator that can evaluate pods
func
NewPodEvaluator
(
f
quota
.
ListerForResourceFunc
,
clock
clock
.
Clock
)
quota
.
Evaluator
{
listFuncByNamespace
:=
generic
.
ListResourceUsingListerFunc
(
f
,
v1
.
SchemeGroupVersion
.
WithResource
(
"pods"
))
listFuncByNamespace
:=
generic
.
ListResourceUsingListerFunc
(
f
,
core
v1
.
SchemeGroupVersion
.
WithResource
(
"pods"
))
podEvaluator
:=
&
podEvaluator
{
listFuncByNamespace
:
listFuncByNamespace
,
clock
:
clock
}
return
podEvaluator
}
...
...
@@ -115,10 +115,10 @@ type podEvaluator struct {
// Constraints verifies that all required resources are present on the pod
// In addition, it validates that the resources are valid (i.e. requests < limits)
func
(
p
*
podEvaluator
)
Constraints
(
required
[]
api
.
ResourceName
,
item
runtime
.
Object
)
error
{
pod
,
ok
:=
item
.
(
*
api
.
Pod
)
if
!
ok
{
return
fmt
.
Errorf
(
"unexpected input object %v"
,
item
)
func
(
p
*
podEvaluator
)
Constraints
(
required
[]
corev1
.
ResourceName
,
item
runtime
.
Object
)
error
{
pod
,
err
:=
toExternalPodOrError
(
item
)
if
err
!=
nil
{
return
err
}
// BACKWARD COMPATIBILITY REQUIREMENT: if we quota cpu or memory, then each container
...
...
@@ -141,7 +141,7 @@ func (p *podEvaluator) Constraints(required []api.ResourceName, item runtime.Obj
// GroupResource that this evaluator tracks
func
(
p
*
podEvaluator
)
GroupResource
()
schema
.
GroupResource
{
return
v1
.
SchemeGroupVersion
.
WithResource
(
"pods"
)
.
GroupResource
()
return
core
v1
.
SchemeGroupVersion
.
WithResource
(
"pods"
)
.
GroupResource
()
}
// Handles returns true if the evaluator should handle the specified attributes.
...
...
@@ -161,12 +161,12 @@ func (p *podEvaluator) Handles(a admission.Attributes) bool {
}
// Matches returns true if the evaluator matches the specified quota with the provided input item
func
(
p
*
podEvaluator
)
Matches
(
resourceQuota
*
api
.
ResourceQuota
,
item
runtime
.
Object
)
(
bool
,
error
)
{
func
(
p
*
podEvaluator
)
Matches
(
resourceQuota
*
corev1
.
ResourceQuota
,
item
runtime
.
Object
)
(
bool
,
error
)
{
return
generic
.
Matches
(
resourceQuota
,
item
,
p
.
MatchingResources
,
podMatchesScopeFunc
)
}
// MatchingResources takes the input specified list of resources and returns the set of resources it matches.
func
(
p
*
podEvaluator
)
MatchingResources
(
input
[]
api
.
ResourceName
)
[]
api
.
ResourceName
{
func
(
p
*
podEvaluator
)
MatchingResources
(
input
[]
corev1
.
ResourceName
)
[]
corev1
.
ResourceName
{
result
:=
quota
.
Intersection
(
input
,
podResources
)
for
_
,
resource
:=
range
input
{
// for resources with certain prefix, e.g. hugepages
...
...
@@ -183,12 +183,12 @@ func (p *podEvaluator) MatchingResources(input []api.ResourceName) []api.Resourc
}
// MatchingScopes takes the input specified list of scopes and pod object. Returns the set of scope selectors pod matches.
func
(
p
*
podEvaluator
)
MatchingScopes
(
item
runtime
.
Object
,
scopeSelectors
[]
api
.
ScopedResourceSelectorRequirement
)
([]
api
.
ScopedResourceSelectorRequirement
,
error
)
{
matchedScopes
:=
[]
api
.
ScopedResourceSelectorRequirement
{}
func
(
p
*
podEvaluator
)
MatchingScopes
(
item
runtime
.
Object
,
scopeSelectors
[]
corev1
.
ScopedResourceSelectorRequirement
)
([]
corev1
.
ScopedResourceSelectorRequirement
,
error
)
{
matchedScopes
:=
[]
corev1
.
ScopedResourceSelectorRequirement
{}
for
_
,
selector
:=
range
scopeSelectors
{
match
,
err
:=
podMatchesScopeFunc
(
selector
,
item
)
if
err
!=
nil
{
return
[]
api
.
ScopedResourceSelectorRequirement
{},
fmt
.
Errorf
(
"error on matching scope %v: %v"
,
selector
,
err
)
return
[]
corev1
.
ScopedResourceSelectorRequirement
{},
fmt
.
Errorf
(
"error on matching scope %v: %v"
,
selector
,
err
)
}
if
match
{
matchedScopes
=
append
(
matchedScopes
,
selector
)
...
...
@@ -199,8 +199,8 @@ func (p *podEvaluator) MatchingScopes(item runtime.Object, scopeSelectors []api.
// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes.
// It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope
func
(
p
*
podEvaluator
)
UncoveredQuotaScopes
(
limitedScopes
[]
api
.
ScopedResourceSelectorRequirement
,
matchedQuotaScopes
[]
api
.
ScopedResourceSelectorRequirement
)
([]
api
.
ScopedResourceSelectorRequirement
,
error
)
{
uncoveredScopes
:=
[]
api
.
ScopedResourceSelectorRequirement
{}
func
(
p
*
podEvaluator
)
UncoveredQuotaScopes
(
limitedScopes
[]
corev1
.
ScopedResourceSelectorRequirement
,
matchedQuotaScopes
[]
corev1
.
ScopedResourceSelectorRequirement
)
([]
corev1
.
ScopedResourceSelectorRequirement
,
error
)
{
uncoveredScopes
:=
[]
corev1
.
ScopedResourceSelectorRequirement
{}
for
_
,
selector
:=
range
limitedScopes
{
isCovered
:=
false
for
_
,
matchedScopeSelector
:=
range
matchedQuotaScopes
{
...
...
@@ -218,7 +218,7 @@ func (p *podEvaluator) UncoveredQuotaScopes(limitedScopes []api.ScopedResourceSe
}
// Usage knows how to measure usage associated with pods
func
(
p
*
podEvaluator
)
Usage
(
item
runtime
.
Object
)
(
api
.
ResourceList
,
error
)
{
func
(
p
*
podEvaluator
)
Usage
(
item
runtime
.
Object
)
(
corev1
.
ResourceList
,
error
)
{
// delegate to normal usage
return
PodUsageFunc
(
item
,
p
.
clock
)
}
...
...
@@ -233,7 +233,7 @@ var _ quota.Evaluator = &podEvaluator{}
// enforcePodContainerConstraints checks for required resources that are not set on this container and
// adds them to missingSet.
func
enforcePodContainerConstraints
(
container
*
api
.
Container
,
requiredSet
,
missingSet
sets
.
String
)
{
func
enforcePodContainerConstraints
(
container
*
corev1
.
Container
,
requiredSet
,
missingSet
sets
.
String
)
{
requests
:=
container
.
Resources
.
Requests
limits
:=
container
.
Resources
.
Limits
containerUsage
:=
podComputeUsageHelper
(
requests
,
limits
)
...
...
@@ -245,55 +245,55 @@ func enforcePodContainerConstraints(container *api.Container, requiredSet, missi
}
// podComputeUsageHelper can summarize the pod compute quota usage based on requests and limits
func
podComputeUsageHelper
(
requests
api
.
ResourceList
,
limits
api
.
ResourceList
)
api
.
ResourceList
{
result
:=
api
.
ResourceList
{}
result
[
api
.
ResourcePods
]
=
resource
.
MustParse
(
"1"
)
if
request
,
found
:=
requests
[
api
.
ResourceCPU
];
found
{
result
[
api
.
ResourceCPU
]
=
request
result
[
api
.
ResourceRequestsCPU
]
=
request
func
podComputeUsageHelper
(
requests
corev1
.
ResourceList
,
limits
corev1
.
ResourceList
)
corev1
.
ResourceList
{
result
:=
corev1
.
ResourceList
{}
result
[
corev1
.
ResourcePods
]
=
resource
.
MustParse
(
"1"
)
if
request
,
found
:=
requests
[
corev1
.
ResourceCPU
];
found
{
result
[
corev1
.
ResourceCPU
]
=
request
result
[
corev1
.
ResourceRequestsCPU
]
=
request
}
if
limit
,
found
:=
limits
[
api
.
ResourceCPU
];
found
{
result
[
api
.
ResourceLimitsCPU
]
=
limit
if
limit
,
found
:=
limits
[
corev1
.
ResourceCPU
];
found
{
result
[
corev1
.
ResourceLimitsCPU
]
=
limit
}
if
request
,
found
:=
requests
[
api
.
ResourceMemory
];
found
{
result
[
api
.
ResourceMemory
]
=
request
result
[
api
.
ResourceRequestsMemory
]
=
request
if
request
,
found
:=
requests
[
corev1
.
ResourceMemory
];
found
{
result
[
corev1
.
ResourceMemory
]
=
request
result
[
corev1
.
ResourceRequestsMemory
]
=
request
}
if
limit
,
found
:=
limits
[
api
.
ResourceMemory
];
found
{
result
[
api
.
ResourceLimitsMemory
]
=
limit
if
limit
,
found
:=
limits
[
corev1
.
ResourceMemory
];
found
{
result
[
corev1
.
ResourceLimitsMemory
]
=
limit
}
if
request
,
found
:=
requests
[
api
.
ResourceEphemeralStorage
];
found
{
result
[
api
.
ResourceEphemeralStorage
]
=
request
result
[
api
.
ResourceRequestsEphemeralStorage
]
=
request
if
request
,
found
:=
requests
[
corev1
.
ResourceEphemeralStorage
];
found
{
result
[
corev1
.
ResourceEphemeralStorage
]
=
request
result
[
corev1
.
ResourceRequestsEphemeralStorage
]
=
request
}
if
limit
,
found
:=
limits
[
api
.
ResourceEphemeralStorage
];
found
{
result
[
api
.
ResourceLimitsEphemeralStorage
]
=
limit
if
limit
,
found
:=
limits
[
corev1
.
ResourceEphemeralStorage
];
found
{
result
[
corev1
.
ResourceLimitsEphemeralStorage
]
=
limit
}
for
resource
,
request
:=
range
requests
{
// for resources with certain prefix, e.g. hugepages
if
quota
.
ContainsPrefix
(
requestedResourcePrefixes
,
resource
)
{
result
[
resource
]
=
request
result
[
maskResourceWithPrefix
(
resource
,
api
.
DefaultResourceRequestsPrefix
)]
=
request
result
[
maskResourceWithPrefix
(
resource
,
corev1
.
DefaultResourceRequestsPrefix
)]
=
request
}
// for extended resources
if
helper
.
IsExtendedResourceName
(
resource
)
{
// only quota objects in format of "requests.resourceName" is allowed for extended resource.
result
[
maskResourceWithPrefix
(
resource
,
api
.
DefaultResourceRequestsPrefix
)]
=
request
result
[
maskResourceWithPrefix
(
resource
,
corev1
.
DefaultResourceRequestsPrefix
)]
=
request
}
}
return
result
}
func
to
InternalPodOrError
(
obj
runtime
.
Object
)
(
*
api
.
Pod
,
error
)
{
pod
:=
&
api
.
Pod
{}
func
to
ExternalPodOrError
(
obj
runtime
.
Object
)
(
*
corev1
.
Pod
,
error
)
{
pod
:=
&
corev1
.
Pod
{}
switch
t
:=
obj
.
(
type
)
{
case
*
v1
.
Pod
:
if
err
:=
k8s_api_v1
.
Convert_v1_Pod_To_core_Pod
(
t
,
pod
,
nil
);
err
!=
nil
{
case
*
corev1
.
Pod
:
pod
=
t
case
*
api
.
Pod
:
if
err
:=
k8s_api_v1
.
Convert_core_Pod_To_v1_Pod
(
t
,
pod
,
nil
);
err
!=
nil
{
return
nil
,
err
}
case
*
api
.
Pod
:
pod
=
t
default
:
return
nil
,
fmt
.
Errorf
(
"expect *api.Pod or *v1.Pod, got %v"
,
t
)
}
...
...
@@ -301,21 +301,21 @@ func toInternalPodOrError(obj runtime.Object) (*api.Pod, error) {
}
// podMatchesScopeFunc is a function that knows how to evaluate if a pod matches a scope
func
podMatchesScopeFunc
(
selector
api
.
ScopedResourceSelectorRequirement
,
object
runtime
.
Object
)
(
bool
,
error
)
{
pod
,
err
:=
to
In
ternalPodOrError
(
object
)
func
podMatchesScopeFunc
(
selector
corev1
.
ScopedResourceSelectorRequirement
,
object
runtime
.
Object
)
(
bool
,
error
)
{
pod
,
err
:=
to
Ex
ternalPodOrError
(
object
)
if
err
!=
nil
{
return
false
,
err
}
switch
selector
.
ScopeName
{
case
api
.
ResourceQuotaScopeTerminating
:
case
corev1
.
ResourceQuotaScopeTerminating
:
return
isTerminating
(
pod
),
nil
case
api
.
ResourceQuotaScopeNotTerminating
:
case
corev1
.
ResourceQuotaScopeNotTerminating
:
return
!
isTerminating
(
pod
),
nil
case
api
.
ResourceQuotaScopeBestEffort
:
case
corev1
.
ResourceQuotaScopeBestEffort
:
return
isBestEffort
(
pod
),
nil
case
api
.
ResourceQuotaScopeNotBestEffort
:
case
corev1
.
ResourceQuotaScopeNotBestEffort
:
return
!
isBestEffort
(
pod
),
nil
case
api
.
ResourceQuotaScopePriorityClass
:
case
corev1
.
ResourceQuotaScopePriorityClass
:
return
podMatchesSelector
(
pod
,
selector
)
}
return
false
,
nil
...
...
@@ -325,28 +325,28 @@ func podMatchesScopeFunc(selector api.ScopedResourceSelectorRequirement, object
// A pod is charged for quota if the following are not true.
// - pod has a terminal phase (failed or succeeded)
// - pod has been marked for deletion and grace period has expired
func
PodUsageFunc
(
obj
runtime
.
Object
,
clock
clock
.
Clock
)
(
api
.
ResourceList
,
error
)
{
pod
,
err
:=
to
In
ternalPodOrError
(
obj
)
func
PodUsageFunc
(
obj
runtime
.
Object
,
clock
clock
.
Clock
)
(
corev1
.
ResourceList
,
error
)
{
pod
,
err
:=
to
Ex
ternalPodOrError
(
obj
)
if
err
!=
nil
{
return
api
.
ResourceList
{},
err
return
corev1
.
ResourceList
{},
err
}
// always quota the object count (even if the pod is end of life)
// object count quotas track all objects that are in storage.
// where "pods" tracks all pods that have not reached a terminal state,
// count/pods tracks all pods independent of state.
result
:=
api
.
ResourceList
{
result
:=
corev1
.
ResourceList
{
podObjectCountName
:
*
(
resource
.
NewQuantity
(
1
,
resource
.
DecimalSI
)),
}
// by convention, we do not quota compute resources that have reached end-of life
// note: the "pods" resource is considered a compute resource since it is tied to life-cycle.
if
!
QuotaPod
(
pod
,
clock
)
{
if
!
Quota
V1
Pod
(
pod
,
clock
)
{
return
result
,
nil
}
requests
:=
api
.
ResourceList
{}
limits
:=
api
.
ResourceList
{}
requests
:=
corev1
.
ResourceList
{}
limits
:=
corev1
.
ResourceList
{}
// TODO: ideally, we have pod level requests and limits in the future.
for
i
:=
range
pod
.
Spec
.
Containers
{
requests
=
quota
.
Add
(
requests
,
pod
.
Spec
.
Containers
[
i
]
.
Resources
.
Requests
)
...
...
@@ -364,25 +364,25 @@ func PodUsageFunc(obj runtime.Object, clock clock.Clock) (api.ResourceList, erro
return
result
,
nil
}
func
isBestEffort
(
pod
*
api
.
Pod
)
bool
{
return
qos
.
GetPodQOS
(
pod
)
==
api
.
PodQOSBestEffort
func
isBestEffort
(
pod
*
corev1
.
Pod
)
bool
{
return
qos
.
GetPodQOS
(
pod
)
==
corev1
.
PodQOSBestEffort
}
func
isTerminating
(
pod
*
api
.
Pod
)
bool
{
func
isTerminating
(
pod
*
corev1
.
Pod
)
bool
{
if
pod
.
Spec
.
ActiveDeadlineSeconds
!=
nil
&&
*
pod
.
Spec
.
ActiveDeadlineSeconds
>=
int64
(
0
)
{
return
true
}
return
false
}
func
podMatchesSelector
(
pod
*
api
.
Pod
,
selector
api
.
ScopedResourceSelectorRequirement
)
(
bool
,
error
)
{
func
podMatchesSelector
(
pod
*
corev1
.
Pod
,
selector
corev1
.
ScopedResourceSelectorRequirement
)
(
bool
,
error
)
{
labelSelector
,
err
:=
helper
.
ScopedResourceSelectorRequirementsAsSelector
(
selector
)
if
err
!=
nil
{
return
false
,
fmt
.
Errorf
(
"failed to parse and convert selector: %v"
,
err
)
}
var
m
map
[
string
]
string
if
len
(
pod
.
Spec
.
PriorityClassName
)
!=
0
{
m
=
map
[
string
]
string
{
string
(
api
.
ResourceQuotaScopePriorityClass
)
:
pod
.
Spec
.
PriorityClassName
}
m
=
map
[
string
]
string
{
string
(
corev1
.
ResourceQuotaScopePriorityClass
)
:
pod
.
Spec
.
PriorityClassName
}
}
if
labelSelector
.
Matches
(
labels
.
Set
(
m
))
{
return
true
,
nil
...
...
@@ -390,36 +390,11 @@ func podMatchesSelector(pod *api.Pod, selector api.ScopedResourceSelectorRequire
return
false
,
nil
}
// QuotaPod returns true if the pod is eligible to track against a quota
// A pod is eligible for quota, unless any of the following are true:
// - pod has a terminal phase (failed or succeeded)
// - pod has been marked for deletion and grace period has expired.
func
QuotaPod
(
pod
*
api
.
Pod
,
clock
clock
.
Clock
)
bool
{
// if pod is terminal, ignore it for quota
if
api
.
PodFailed
==
pod
.
Status
.
Phase
||
api
.
PodSucceeded
==
pod
.
Status
.
Phase
{
return
false
}
// deleted pods that should be gone should not be charged to user quota.
// this can happen if a node is lost, and the kubelet is never able to confirm deletion.
// even though the cluster may have drifting clocks, quota makes a reasonable effort
// to balance cluster needs against user needs. user's do not control clocks,
// but at worst a small drive in clocks will only slightly impact quota.
if
pod
.
DeletionTimestamp
!=
nil
&&
pod
.
DeletionGracePeriodSeconds
!=
nil
{
now
:=
clock
.
Now
()
deletionTime
:=
pod
.
DeletionTimestamp
.
Time
gracePeriod
:=
time
.
Duration
(
*
pod
.
DeletionGracePeriodSeconds
)
*
time
.
Second
if
now
.
After
(
deletionTime
.
Add
(
gracePeriod
))
{
return
false
}
}
return
true
}
// 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
,
clock
clock
.
Clock
)
bool
{
func
QuotaV1Pod
(
pod
*
core
v1
.
Pod
,
clock
clock
.
Clock
)
bool
{
// if pod is terminal, ignore it for quota
if
v1
.
PodFailed
==
pod
.
Status
.
Phase
||
v1
.
PodSucceeded
==
pod
.
Status
.
Phase
{
if
corev1
.
PodFailed
==
pod
.
Status
.
Phase
||
core
v1
.
PodSucceeded
==
pod
.
Status
.
Phase
{
return
false
}
// if pods are stuck terminating (for example, a node is lost), we do not want
...
...
pkg/quota/evaluator/core/pods_test.go
→
pkg/quota/
v1/
evaluator/core/pods_test.go
View file @
ec3b0886
...
...
@@ -20,20 +20,21 @@ import (
"testing"
"time"
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/clock"
api
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/quota
"
"k8s.io/kubernetes/pkg/quota/generic"
quota
"k8s.io/kubernetes/pkg/quota/v1
"
"k8s.io/kubernetes/pkg/quota/
v1/
generic"
"k8s.io/kubernetes/pkg/util/node"
)
func
TestPodConstraintsFunc
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
struct
{
pod
*
api
.
Pod
required
[]
api
.
ResourceName
required
[]
corev1
.
ResourceName
err
string
}{
"init container resource missing"
:
{
...
...
@@ -47,7 +48,7 @@ func TestPodConstraintsFunc(t *testing.T) {
}},
},
},
required
:
[]
api
.
ResourceName
{
api
.
ResourceMemory
},
required
:
[]
corev1
.
ResourceName
{
corev1
.
ResourceMemory
},
err
:
`must specify memory`
,
},
"container resource missing"
:
{
...
...
@@ -61,7 +62,7 @@ func TestPodConstraintsFunc(t *testing.T) {
}},
},
},
required
:
[]
api
.
ResourceName
{
api
.
ResourceMemory
},
required
:
[]
corev1
.
ResourceName
{
corev1
.
ResourceMemory
},
err
:
`must specify memory`
,
},
}
...
...
@@ -90,7 +91,7 @@ func TestPodEvaluatorUsage(t *testing.T) {
testCases
:=
map
[
string
]
struct
{
pod
*
api
.
Pod
usage
api
.
ResourceList
usage
corev1
.
ResourceList
}{
"init container CPU"
:
{
pod
:
&
api
.
Pod
{
...
...
@@ -103,11 +104,11 @@ func TestPodEvaluatorUsage(t *testing.T) {
}},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceRequestsCPU
:
resource
.
MustParse
(
"1m"
),
api
.
ResourceLimitsCPU
:
resource
.
MustParse
(
"2m"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
api
.
ResourceCPU
:
resource
.
MustParse
(
"1m"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceRequestsCPU
:
resource
.
MustParse
(
"1m"
),
corev1
.
ResourceLimitsCPU
:
resource
.
MustParse
(
"2m"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"1m"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -122,11 +123,11 @@ func TestPodEvaluatorUsage(t *testing.T) {
}},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceRequestsMemory
:
resource
.
MustParse
(
"1m"
),
api
.
ResourceLimitsMemory
:
resource
.
MustParse
(
"2m"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"1m"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceRequestsMemory
:
resource
.
MustParse
(
"1m"
),
corev1
.
ResourceLimitsMemory
:
resource
.
MustParse
(
"2m"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"1m"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -141,11 +142,11 @@ func TestPodEvaluatorUsage(t *testing.T) {
}},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceEphemeralStorage
:
resource
.
MustParse
(
"32Mi"
),
api
.
ResourceRequestsEphemeralStorage
:
resource
.
MustParse
(
"32Mi"
),
api
.
ResourceLimitsEphemeralStorage
:
resource
.
MustParse
(
"64Mi"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceEphemeralStorage
:
resource
.
MustParse
(
"32Mi"
),
corev1
.
ResourceRequestsEphemeralStorage
:
resource
.
MustParse
(
"32Mi"
),
corev1
.
ResourceLimitsEphemeralStorage
:
resource
.
MustParse
(
"64Mi"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -159,10 +160,10 @@ func TestPodEvaluatorUsage(t *testing.T) {
}},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceName
(
api
.
ResourceHugePagesPrefix
+
"2Mi"
)
:
resource
.
MustParse
(
"100Mi"
),
api
.
ResourceName
(
api
.
ResourceRequestsHugePagesPrefix
+
"2Mi"
)
:
resource
.
MustParse
(
"100Mi"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceName
(
corev1
.
ResourceHugePagesPrefix
+
"2Mi"
)
:
resource
.
MustParse
(
"100Mi"
),
corev1
.
ResourceName
(
corev1
.
ResourceRequestsHugePagesPrefix
+
"2Mi"
)
:
resource
.
MustParse
(
"100Mi"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -177,9 +178,9 @@ func TestPodEvaluatorUsage(t *testing.T) {
}},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceName
(
"requests.example.com/dongle"
)
:
resource
.
MustParse
(
"3"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceName
(
"requests.example.com/dongle"
)
:
resource
.
MustParse
(
"3"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -194,11 +195,11 @@ func TestPodEvaluatorUsage(t *testing.T) {
}},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceRequestsCPU
:
resource
.
MustParse
(
"1m"
),
api
.
ResourceLimitsCPU
:
resource
.
MustParse
(
"2m"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
api
.
ResourceCPU
:
resource
.
MustParse
(
"1m"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceRequestsCPU
:
resource
.
MustParse
(
"1m"
),
corev1
.
ResourceLimitsCPU
:
resource
.
MustParse
(
"2m"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"1m"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -213,11 +214,11 @@ func TestPodEvaluatorUsage(t *testing.T) {
}},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceRequestsMemory
:
resource
.
MustParse
(
"1m"
),
api
.
ResourceLimitsMemory
:
resource
.
MustParse
(
"2m"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"1m"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceRequestsMemory
:
resource
.
MustParse
(
"1m"
),
corev1
.
ResourceLimitsMemory
:
resource
.
MustParse
(
"2m"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"1m"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -232,11 +233,11 @@ func TestPodEvaluatorUsage(t *testing.T) {
}},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceEphemeralStorage
:
resource
.
MustParse
(
"32Mi"
),
api
.
ResourceRequestsEphemeralStorage
:
resource
.
MustParse
(
"32Mi"
),
api
.
ResourceLimitsEphemeralStorage
:
resource
.
MustParse
(
"64Mi"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceEphemeralStorage
:
resource
.
MustParse
(
"32Mi"
),
corev1
.
ResourceRequestsEphemeralStorage
:
resource
.
MustParse
(
"32Mi"
),
corev1
.
ResourceLimitsEphemeralStorage
:
resource
.
MustParse
(
"64Mi"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -250,10 +251,10 @@ func TestPodEvaluatorUsage(t *testing.T) {
}},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceName
(
api
.
ResourceHugePagesPrefix
+
"2Mi"
)
:
resource
.
MustParse
(
"100Mi"
),
api
.
ResourceName
(
api
.
ResourceRequestsHugePagesPrefix
+
"2Mi"
)
:
resource
.
MustParse
(
"100Mi"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceName
(
api
.
ResourceHugePagesPrefix
+
"2Mi"
)
:
resource
.
MustParse
(
"100Mi"
),
corev1
.
ResourceName
(
api
.
ResourceRequestsHugePagesPrefix
+
"2Mi"
)
:
resource
.
MustParse
(
"100Mi"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -268,9 +269,9 @@ func TestPodEvaluatorUsage(t *testing.T) {
}},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceName
(
"requests.example.com/dongle"
)
:
resource
.
MustParse
(
"3"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceName
(
"requests.example.com/dongle"
)
:
resource
.
MustParse
(
"3"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -339,15 +340,15 @@ func TestPodEvaluatorUsage(t *testing.T) {
},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceRequestsCPU
:
resource
.
MustParse
(
"4"
),
api
.
ResourceRequestsMemory
:
resource
.
MustParse
(
"100M"
),
api
.
ResourceLimitsCPU
:
resource
.
MustParse
(
"8"
),
api
.
ResourceLimitsMemory
:
resource
.
MustParse
(
"200M"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
api
.
ResourceCPU
:
resource
.
MustParse
(
"4"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"100M"
),
api
.
ResourceName
(
"requests.example.com/dongle"
)
:
resource
.
MustParse
(
"4"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceRequestsCPU
:
resource
.
MustParse
(
"4"
),
corev1
.
ResourceRequestsMemory
:
resource
.
MustParse
(
"100M"
),
corev1
.
ResourceLimitsCPU
:
resource
.
MustParse
(
"8"
),
corev1
.
ResourceLimitsMemory
:
resource
.
MustParse
(
"200M"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"4"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"100M"
),
corev1
.
ResourceName
(
"requests.example.com/dongle"
)
:
resource
.
MustParse
(
"4"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -378,7 +379,7 @@ func TestPodEvaluatorUsage(t *testing.T) {
},
},
},
usage
:
api
.
ResourceList
{
usage
:
corev1
.
ResourceList
{
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -406,11 +407,11 @@ func TestPodEvaluatorUsage(t *testing.T) {
},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceRequestsCPU
:
resource
.
MustParse
(
"1"
),
api
.
ResourceLimitsCPU
:
resource
.
MustParse
(
"2"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
api
.
ResourceCPU
:
resource
.
MustParse
(
"1"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceRequestsCPU
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceLimitsCPU
:
resource
.
MustParse
(
"2"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"1"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"pods"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
pkg/quota/evaluator/core/registry.go
→
pkg/quota/
v1/
evaluator/core/registry.go
View file @
ec3b0886
...
...
@@ -17,20 +17,19 @@ limitations under the License.
package
core
import
(
"k8s.io/api/core/v1"
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/clock"
api
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/quota"
"k8s.io/kubernetes/pkg/quota/generic"
quota
"k8s.io/kubernetes/pkg/quota/v1"
"k8s.io/kubernetes/pkg/quota/v1/generic"
)
// legacyObjectCountAliases are what we used to do simple object counting quota with mapped to alias
var
legacyObjectCountAliases
=
map
[
schema
.
GroupVersionResource
]
api
.
ResourceName
{
v1
.
SchemeGroupVersion
.
WithResource
(
"configmaps"
)
:
api
.
ResourceConfigMaps
,
v1
.
SchemeGroupVersion
.
WithResource
(
"resourcequotas"
)
:
api
.
ResourceQuotas
,
v1
.
SchemeGroupVersion
.
WithResource
(
"replicationcontrollers"
)
:
api
.
ResourceReplicationControllers
,
v1
.
SchemeGroupVersion
.
WithResource
(
"secrets"
)
:
api
.
ResourceSecrets
,
var
legacyObjectCountAliases
=
map
[
schema
.
GroupVersionResource
]
corev1
.
ResourceName
{
corev1
.
SchemeGroupVersion
.
WithResource
(
"configmaps"
)
:
corev1
.
ResourceConfigMaps
,
corev1
.
SchemeGroupVersion
.
WithResource
(
"resourcequotas"
)
:
corev1
.
ResourceQuotas
,
corev1
.
SchemeGroupVersion
.
WithResource
(
"replicationcontrollers"
)
:
corev1
.
ResourceReplicationControllers
,
corev1
.
SchemeGroupVersion
.
WithResource
(
"secrets"
)
:
corev1
.
ResourceSecrets
,
}
// NewEvaluators returns the list of static evaluators that manage more than counts
...
...
pkg/quota/evaluator/core/services.go
→
pkg/quota/
v1/
evaluator/core/services.go
View file @
ec3b0886
...
...
@@ -19,31 +19,31 @@ package core
import
(
"fmt"
"k8s.io/api/core/v1"
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission"
api
"k8s.io/kubernetes/pkg/apis/core"
k8s_api_v1
"k8s.io/kubernetes/pkg/apis/core/v1"
"k8s.io/kubernetes/pkg/quota"
"k8s.io/kubernetes/pkg/quota/generic"
"k8s.io/kubernetes/pkg/quota
/v1
"
"k8s.io/kubernetes/pkg/quota/
v1/
generic"
)
// the name used for object count quota
var
serviceObjectCountName
=
generic
.
ObjectCountQuotaResourceNameFor
(
v1
.
SchemeGroupVersion
.
WithResource
(
"services"
)
.
GroupResource
())
var
serviceObjectCountName
=
generic
.
ObjectCountQuotaResourceNameFor
(
core
v1
.
SchemeGroupVersion
.
WithResource
(
"services"
)
.
GroupResource
())
// serviceResources are the set of resources managed by quota associated with services.
var
serviceResources
=
[]
api
.
ResourceName
{
var
serviceResources
=
[]
corev1
.
ResourceName
{
serviceObjectCountName
,
api
.
ResourceServices
,
api
.
ResourceServicesNodePorts
,
api
.
ResourceServicesLoadBalancers
,
corev1
.
ResourceServices
,
corev1
.
ResourceServicesNodePorts
,
corev1
.
ResourceServicesLoadBalancers
,
}
// NewServiceEvaluator returns an evaluator that can evaluate services.
func
NewServiceEvaluator
(
f
quota
.
ListerForResourceFunc
)
quota
.
Evaluator
{
listFuncByNamespace
:=
generic
.
ListResourceUsingListerFunc
(
f
,
v1
.
SchemeGroupVersion
.
WithResource
(
"services"
))
listFuncByNamespace
:=
generic
.
ListResourceUsingListerFunc
(
f
,
core
v1
.
SchemeGroupVersion
.
WithResource
(
"services"
))
serviceEvaluator
:=
&
serviceEvaluator
{
listFuncByNamespace
:
listFuncByNamespace
}
return
serviceEvaluator
}
...
...
@@ -55,14 +55,14 @@ type serviceEvaluator struct {
}
// Constraints verifies that all required resources are present on the item
func
(
p
*
serviceEvaluator
)
Constraints
(
required
[]
api
.
ResourceName
,
item
runtime
.
Object
)
error
{
func
(
p
*
serviceEvaluator
)
Constraints
(
required
[]
corev1
.
ResourceName
,
item
runtime
.
Object
)
error
{
// this is a no-op for services
return
nil
}
// GroupResource that this evaluator tracks
func
(
p
*
serviceEvaluator
)
GroupResource
()
schema
.
GroupResource
{
return
v1
.
SchemeGroupVersion
.
WithResource
(
"services"
)
.
GroupResource
()
return
core
v1
.
SchemeGroupVersion
.
WithResource
(
"services"
)
.
GroupResource
()
}
// Handles returns true of the evaluator should handle the specified operation.
...
...
@@ -73,36 +73,36 @@ func (p *serviceEvaluator) Handles(a admission.Attributes) bool {
}
// Matches returns true if the evaluator matches the specified quota with the provided input item
func
(
p
*
serviceEvaluator
)
Matches
(
resourceQuota
*
api
.
ResourceQuota
,
item
runtime
.
Object
)
(
bool
,
error
)
{
func
(
p
*
serviceEvaluator
)
Matches
(
resourceQuota
*
corev1
.
ResourceQuota
,
item
runtime
.
Object
)
(
bool
,
error
)
{
return
generic
.
Matches
(
resourceQuota
,
item
,
p
.
MatchingResources
,
generic
.
MatchesNoScopeFunc
)
}
// MatchingResources takes the input specified list of resources and returns the set of resources it matches.
func
(
p
*
serviceEvaluator
)
MatchingResources
(
input
[]
api
.
ResourceName
)
[]
api
.
ResourceName
{
func
(
p
*
serviceEvaluator
)
MatchingResources
(
input
[]
corev1
.
ResourceName
)
[]
corev1
.
ResourceName
{
return
quota
.
Intersection
(
input
,
serviceResources
)
}
// MatchingScopes takes the input specified list of scopes and input object. Returns the set of scopes resource matches.
func
(
p
*
serviceEvaluator
)
MatchingScopes
(
item
runtime
.
Object
,
scopes
[]
api
.
ScopedResourceSelectorRequirement
)
([]
api
.
ScopedResourceSelectorRequirement
,
error
)
{
return
[]
api
.
ScopedResourceSelectorRequirement
{},
nil
func
(
p
*
serviceEvaluator
)
MatchingScopes
(
item
runtime
.
Object
,
scopes
[]
corev1
.
ScopedResourceSelectorRequirement
)
([]
corev1
.
ScopedResourceSelectorRequirement
,
error
)
{
return
[]
corev1
.
ScopedResourceSelectorRequirement
{},
nil
}
// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes.
// It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope
func
(
p
*
serviceEvaluator
)
UncoveredQuotaScopes
(
limitedScopes
[]
api
.
ScopedResourceSelectorRequirement
,
matchedQuotaScopes
[]
api
.
ScopedResourceSelectorRequirement
)
([]
api
.
ScopedResourceSelectorRequirement
,
error
)
{
return
[]
api
.
ScopedResourceSelectorRequirement
{},
nil
func
(
p
*
serviceEvaluator
)
UncoveredQuotaScopes
(
limitedScopes
[]
corev1
.
ScopedResourceSelectorRequirement
,
matchedQuotaScopes
[]
corev1
.
ScopedResourceSelectorRequirement
)
([]
corev1
.
ScopedResourceSelectorRequirement
,
error
)
{
return
[]
corev1
.
ScopedResourceSelectorRequirement
{},
nil
}
// convert the input object to an internal service object or error.
func
to
InternalServiceOrError
(
obj
runtime
.
Object
)
(
*
api
.
Service
,
error
)
{
svc
:=
&
api
.
Service
{}
func
to
ExternalServiceOrError
(
obj
runtime
.
Object
)
(
*
corev1
.
Service
,
error
)
{
svc
:=
&
corev1
.
Service
{}
switch
t
:=
obj
.
(
type
)
{
case
*
v1
.
Service
:
if
err
:=
k8s_api_v1
.
Convert_v1_Service_To_core_Service
(
t
,
svc
,
nil
);
err
!=
nil
{
case
*
corev1
.
Service
:
svc
=
t
case
*
api
.
Service
:
if
err
:=
k8s_api_v1
.
Convert_core_Service_To_v1_Service
(
t
,
svc
,
nil
);
err
!=
nil
{
return
nil
,
err
}
case
*
api
.
Service
:
svc
=
t
default
:
return
nil
,
fmt
.
Errorf
(
"expect *api.Service or *v1.Service, got %v"
,
t
)
}
...
...
@@ -110,28 +110,28 @@ func toInternalServiceOrError(obj runtime.Object) (*api.Service, error) {
}
// Usage knows how to measure usage associated with services
func
(
p
*
serviceEvaluator
)
Usage
(
item
runtime
.
Object
)
(
api
.
ResourceList
,
error
)
{
result
:=
api
.
ResourceList
{}
svc
,
err
:=
to
In
ternalServiceOrError
(
item
)
func
(
p
*
serviceEvaluator
)
Usage
(
item
runtime
.
Object
)
(
corev1
.
ResourceList
,
error
)
{
result
:=
corev1
.
ResourceList
{}
svc
,
err
:=
to
Ex
ternalServiceOrError
(
item
)
if
err
!=
nil
{
return
result
,
err
}
ports
:=
len
(
svc
.
Spec
.
Ports
)
// default service usage
result
[
serviceObjectCountName
]
=
*
(
resource
.
NewQuantity
(
1
,
resource
.
DecimalSI
))
result
[
api
.
ResourceServices
]
=
*
(
resource
.
NewQuantity
(
1
,
resource
.
DecimalSI
))
result
[
api
.
ResourceServicesLoadBalancers
]
=
resource
.
Quantity
{
Format
:
resource
.
DecimalSI
}
result
[
api
.
ResourceServicesNodePorts
]
=
resource
.
Quantity
{
Format
:
resource
.
DecimalSI
}
result
[
corev1
.
ResourceServices
]
=
*
(
resource
.
NewQuantity
(
1
,
resource
.
DecimalSI
))
result
[
corev1
.
ResourceServicesLoadBalancers
]
=
resource
.
Quantity
{
Format
:
resource
.
DecimalSI
}
result
[
corev1
.
ResourceServicesNodePorts
]
=
resource
.
Quantity
{
Format
:
resource
.
DecimalSI
}
switch
svc
.
Spec
.
Type
{
case
api
.
ServiceTypeNodePort
:
case
corev1
.
ServiceTypeNodePort
:
// node port services need to count node ports
value
:=
resource
.
NewQuantity
(
int64
(
ports
),
resource
.
DecimalSI
)
result
[
api
.
ResourceServicesNodePorts
]
=
*
value
case
api
.
ServiceTypeLoadBalancer
:
result
[
corev1
.
ResourceServicesNodePorts
]
=
*
value
case
corev1
.
ServiceTypeLoadBalancer
:
// load balancer services need to count node ports and load balancers
value
:=
resource
.
NewQuantity
(
int64
(
ports
),
resource
.
DecimalSI
)
result
[
api
.
ResourceServicesNodePorts
]
=
*
value
result
[
api
.
ResourceServicesLoadBalancers
]
=
*
(
resource
.
NewQuantity
(
1
,
resource
.
DecimalSI
))
result
[
corev1
.
ResourceServicesNodePorts
]
=
*
value
result
[
corev1
.
ResourceServicesLoadBalancers
]
=
*
(
resource
.
NewQuantity
(
1
,
resource
.
DecimalSI
))
}
return
result
,
nil
}
...
...
@@ -144,12 +144,12 @@ func (p *serviceEvaluator) UsageStats(options quota.UsageStatsOptions) (quota.Us
var
_
quota
.
Evaluator
=
&
serviceEvaluator
{}
//GetQuotaServiceType returns ServiceType if the service type is eligible to track against a quota, nor return ""
func
GetQuotaServiceType
(
service
*
v1
.
Service
)
v1
.
ServiceType
{
func
GetQuotaServiceType
(
service
*
corev1
.
Service
)
core
v1
.
ServiceType
{
switch
service
.
Spec
.
Type
{
case
v1
.
ServiceTypeNodePort
:
return
v1
.
ServiceTypeNodePort
case
v1
.
ServiceTypeLoadBalancer
:
return
v1
.
ServiceTypeLoadBalancer
case
core
v1
.
ServiceTypeNodePort
:
return
core
v1
.
ServiceTypeNodePort
case
core
v1
.
ServiceTypeLoadBalancer
:
return
core
v1
.
ServiceTypeLoadBalancer
}
return
v1
.
ServiceType
(
""
)
return
core
v1
.
ServiceType
(
""
)
}
pkg/quota/evaluator/core/services_test.go
→
pkg/quota/
v1/
evaluator/core/services_test.go
View file @
ec3b0886
...
...
@@ -19,28 +19,29 @@ package core
import
(
"testing"
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime/schema"
api
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/quota
"
"k8s.io/kubernetes/pkg/quota/generic"
quota
"k8s.io/kubernetes/pkg/quota/v1
"
"k8s.io/kubernetes/pkg/quota/
v1/
generic"
)
func
TestServiceEvaluatorMatchesResources
(
t
*
testing
.
T
)
{
evaluator
:=
NewServiceEvaluator
(
nil
)
// we give a lot of resources
input
:=
[]
api
.
ResourceName
{
api
.
ResourceConfigMaps
,
api
.
ResourceCPU
,
api
.
ResourceServices
,
api
.
ResourceServicesNodePorts
,
api
.
ResourceServicesLoadBalancers
,
input
:=
[]
corev1
.
ResourceName
{
corev1
.
ResourceConfigMaps
,
corev1
.
ResourceCPU
,
corev1
.
ResourceServices
,
corev1
.
ResourceServicesNodePorts
,
corev1
.
ResourceServicesLoadBalancers
,
}
// but we only match these...
expected
:=
quota
.
ToSet
([]
api
.
ResourceName
{
api
.
ResourceServices
,
api
.
ResourceServicesNodePorts
,
api
.
ResourceServicesLoadBalancers
,
expected
:=
quota
.
ToSet
([]
corev1
.
ResourceName
{
corev1
.
ResourceServices
,
corev1
.
ResourceServicesNodePorts
,
corev1
.
ResourceServicesLoadBalancers
,
})
actual
:=
quota
.
ToSet
(
evaluator
.
MatchingResources
(
input
))
if
!
expected
.
Equal
(
actual
)
{
...
...
@@ -52,7 +53,7 @@ func TestServiceEvaluatorUsage(t *testing.T) {
evaluator
:=
NewServiceEvaluator
(
nil
)
testCases
:=
map
[
string
]
struct
{
service
*
api
.
Service
usage
api
.
ResourceList
usage
corev1
.
ResourceList
}{
"loadbalancer"
:
{
service
:
&
api
.
Service
{
...
...
@@ -60,10 +61,10 @@ func TestServiceEvaluatorUsage(t *testing.T) {
Type
:
api
.
ServiceTypeLoadBalancer
,
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceServicesNodePorts
:
resource
.
MustParse
(
"0"
),
api
.
ResourceServicesLoadBalancers
:
resource
.
MustParse
(
"1"
),
api
.
ResourceServices
:
resource
.
MustParse
(
"1"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceServicesNodePorts
:
resource
.
MustParse
(
"0"
),
corev1
.
ResourceServicesLoadBalancers
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceServices
:
resource
.
MustParse
(
"1"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"services"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -78,10 +79,10 @@ func TestServiceEvaluatorUsage(t *testing.T) {
},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceServicesNodePorts
:
resource
.
MustParse
(
"1"
),
api
.
ResourceServicesLoadBalancers
:
resource
.
MustParse
(
"1"
),
api
.
ResourceServices
:
resource
.
MustParse
(
"1"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceServicesNodePorts
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceServicesLoadBalancers
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceServices
:
resource
.
MustParse
(
"1"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"services"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -91,10 +92,10 @@ func TestServiceEvaluatorUsage(t *testing.T) {
Type
:
api
.
ServiceTypeClusterIP
,
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceServices
:
resource
.
MustParse
(
"1"
),
api
.
ResourceServicesNodePorts
:
resource
.
MustParse
(
"0"
),
api
.
ResourceServicesLoadBalancers
:
resource
.
MustParse
(
"0"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceServices
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceServicesNodePorts
:
resource
.
MustParse
(
"0"
),
corev1
.
ResourceServicesLoadBalancers
:
resource
.
MustParse
(
"0"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"services"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -109,10 +110,10 @@ func TestServiceEvaluatorUsage(t *testing.T) {
},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceServices
:
resource
.
MustParse
(
"1"
),
api
.
ResourceServicesNodePorts
:
resource
.
MustParse
(
"1"
),
api
.
ResourceServicesLoadBalancers
:
resource
.
MustParse
(
"0"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceServices
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceServicesNodePorts
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceServicesLoadBalancers
:
resource
.
MustParse
(
"0"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"services"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -130,10 +131,10 @@ func TestServiceEvaluatorUsage(t *testing.T) {
},
},
},
usage
:
api
.
ResourceList
{
api
.
ResourceServices
:
resource
.
MustParse
(
"1"
),
api
.
ResourceServicesNodePorts
:
resource
.
MustParse
(
"2"
),
api
.
ResourceServicesLoadBalancers
:
resource
.
MustParse
(
"0"
),
usage
:
corev1
.
ResourceList
{
corev1
.
ResourceServices
:
resource
.
MustParse
(
"1"
),
corev1
.
ResourceServicesNodePorts
:
resource
.
MustParse
(
"2"
),
corev1
.
ResourceServicesLoadBalancers
:
resource
.
MustParse
(
"0"
),
generic
.
ObjectCountQuotaResourceNameFor
(
schema
.
GroupResource
{
Resource
:
"services"
})
:
resource
.
MustParse
(
"1"
),
},
},
...
...
@@ -152,7 +153,7 @@ func TestServiceEvaluatorUsage(t *testing.T) {
func
TestServiceConstraintsFunc
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
struct
{
service
*
api
.
Service
required
[]
api
.
ResourceName
required
[]
corev1
.
ResourceName
err
string
}{
"loadbalancer"
:
{
...
...
@@ -161,7 +162,7 @@ func TestServiceConstraintsFunc(t *testing.T) {
Type
:
api
.
ServiceTypeLoadBalancer
,
},
},
required
:
[]
api
.
ResourceName
{
api
.
ResourceServicesLoadBalancers
},
required
:
[]
corev1
.
ResourceName
{
corev1
.
ResourceServicesLoadBalancers
},
},
"clusterip"
:
{
service
:
&
api
.
Service
{
...
...
@@ -169,7 +170,7 @@ func TestServiceConstraintsFunc(t *testing.T) {
Type
:
api
.
ServiceTypeClusterIP
,
},
},
required
:
[]
api
.
ResourceName
{
api
.
ResourceServicesLoadBalancers
,
api
.
ResourceServices
},
required
:
[]
corev1
.
ResourceName
{
corev1
.
ResourceServicesLoadBalancers
,
corev1
.
ResourceServices
},
},
"nodeports"
:
{
service
:
&
api
.
Service
{
...
...
@@ -182,7 +183,7 @@ func TestServiceConstraintsFunc(t *testing.T) {
},
},
},
required
:
[]
api
.
ResourceName
{
api
.
ResourceServicesNodePorts
},
required
:
[]
corev1
.
ResourceName
{
corev1
.
ResourceServicesNodePorts
},
},
"multi-nodeports"
:
{
service
:
&
api
.
Service
{
...
...
@@ -198,7 +199,7 @@ func TestServiceConstraintsFunc(t *testing.T) {
},
},
},
required
:
[]
api
.
ResourceName
{
api
.
ResourceServicesNodePorts
},
required
:
[]
corev1
.
ResourceName
{
corev1
.
ResourceServicesNodePorts
},
},
}
...
...
pkg/quota/generic/BUILD
→
pkg/quota/
v1/
generic/BUILD
View file @
ec3b0886
...
...
@@ -12,10 +12,10 @@ go_library(
"evaluator.go",
"registry.go",
],
importpath = "k8s.io/kubernetes/pkg/quota/generic",
importpath = "k8s.io/kubernetes/pkg/quota/
v1/
generic",
deps = [
"//pkg/
apis/core
:go_default_library",
"//
pkg/quota
:go_default_library",
"//pkg/
quota/v1
:go_default_library",
"//
staging/src/k8s.io/api/core/v1
:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
...
...
pkg/quota/generic/OWNERS
→
pkg/quota/
v1/
generic/OWNERS
View file @
ec3b0886
File moved
pkg/quota/generic/configuration.go
→
pkg/quota/
v1/
generic/configuration.go
View file @
ec3b0886
...
...
@@ -18,7 +18,7 @@ package generic
import
(
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/quota
"
quota
"k8s.io/kubernetes/pkg/quota/v1
"
)
// implements a basic configuration
...
...
pkg/quota/generic/evaluator.go
→
pkg/quota/
v1/
generic/evaluator.go
View file @
ec3b0886
...
...
@@ -19,6 +19,7 @@ package generic
import
(
"fmt"
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
...
...
@@ -26,8 +27,7 @@ import (
"k8s.io/apiserver/pkg/admission"
"k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
api
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/quota"
quota
"k8s.io/kubernetes/pkg/quota/v1"
)
// InformerForResourceFunc knows how to provision an informer
...
...
@@ -56,33 +56,33 @@ func ListResourceUsingListerFunc(l quota.ListerForResourceFunc, resource schema.
}
// ObjectCountQuotaResourceNameFor returns the object count quota name for specified groupResource
func
ObjectCountQuotaResourceNameFor
(
groupResource
schema
.
GroupResource
)
api
.
ResourceName
{
func
ObjectCountQuotaResourceNameFor
(
groupResource
schema
.
GroupResource
)
corev1
.
ResourceName
{
if
len
(
groupResource
.
Group
)
==
0
{
return
api
.
ResourceName
(
"count/"
+
groupResource
.
Resource
)
return
corev1
.
ResourceName
(
"count/"
+
groupResource
.
Resource
)
}
return
api
.
ResourceName
(
"count/"
+
groupResource
.
Resource
+
"."
+
groupResource
.
Group
)
return
corev1
.
ResourceName
(
"count/"
+
groupResource
.
Resource
+
"."
+
groupResource
.
Group
)
}
// ListFuncByNamespace knows how to list resources in a namespace
type
ListFuncByNamespace
func
(
namespace
string
)
([]
runtime
.
Object
,
error
)
// MatchesScopeFunc knows how to evaluate if an object matches a scope
type
MatchesScopeFunc
func
(
scope
api
.
ScopedResourceSelectorRequirement
,
object
runtime
.
Object
)
(
bool
,
error
)
type
MatchesScopeFunc
func
(
scope
corev1
.
ScopedResourceSelectorRequirement
,
object
runtime
.
Object
)
(
bool
,
error
)
// UsageFunc knows how to measure usage associated with an object
type
UsageFunc
func
(
object
runtime
.
Object
)
(
api
.
ResourceList
,
error
)
type
UsageFunc
func
(
object
runtime
.
Object
)
(
corev1
.
ResourceList
,
error
)
// MatchingResourceNamesFunc is a function that returns the list of resources matched
type
MatchingResourceNamesFunc
func
(
input
[]
api
.
ResourceName
)
[]
api
.
ResourceName
type
MatchingResourceNamesFunc
func
(
input
[]
corev1
.
ResourceName
)
[]
corev1
.
ResourceName
// MatchesNoScopeFunc returns false on all match checks
func
MatchesNoScopeFunc
(
scope
api
.
ScopedResourceSelectorRequirement
,
object
runtime
.
Object
)
(
bool
,
error
)
{
func
MatchesNoScopeFunc
(
scope
corev1
.
ScopedResourceSelectorRequirement
,
object
runtime
.
Object
)
(
bool
,
error
)
{
return
false
,
nil
}
// Matches returns true if the quota matches the specified item.
func
Matches
(
resourceQuota
*
api
.
ResourceQuota
,
item
runtime
.
Object
,
resourceQuota
*
corev1
.
ResourceQuota
,
item
runtime
.
Object
,
matchFunc
MatchingResourceNamesFunc
,
scopeFunc
MatchesScopeFunc
)
(
bool
,
error
)
{
if
resourceQuota
==
nil
{
return
false
,
fmt
.
Errorf
(
"expected non-nil quota"
)
...
...
@@ -101,12 +101,12 @@ func Matches(
return
matchResource
&&
matchScope
,
nil
}
func
getScopeSelectorsFromQuota
(
quota
*
api
.
ResourceQuota
)
[]
api
.
ScopedResourceSelectorRequirement
{
selectors
:=
[]
api
.
ScopedResourceSelectorRequirement
{}
func
getScopeSelectorsFromQuota
(
quota
*
corev1
.
ResourceQuota
)
[]
corev1
.
ScopedResourceSelectorRequirement
{
selectors
:=
[]
corev1
.
ScopedResourceSelectorRequirement
{}
for
_
,
scope
:=
range
quota
.
Spec
.
Scopes
{
selectors
=
append
(
selectors
,
api
.
ScopedResourceSelectorRequirement
{
selectors
=
append
(
selectors
,
corev1
.
ScopedResourceSelectorRequirement
{
ScopeName
:
scope
,
Operator
:
api
.
ScopeSelectorOpExists
})
Operator
:
corev1
.
ScopeSelectorOpExists
})
}
if
quota
.
Spec
.
ScopeSelector
!=
nil
{
for
_
,
scopeSelector
:=
range
quota
.
Spec
.
ScopeSelector
.
MatchExpressions
{
...
...
@@ -122,7 +122,7 @@ func CalculateUsageStats(options quota.UsageStatsOptions,
scopeFunc
MatchesScopeFunc
,
usageFunc
UsageFunc
)
(
quota
.
UsageStats
,
error
)
{
// default each tracked resource to zero
result
:=
quota
.
UsageStats
{
Used
:
api
.
ResourceList
{}}
result
:=
quota
.
UsageStats
{
Used
:
corev1
.
ResourceList
{}}
for
_
,
resourceName
:=
range
options
.
Resources
{
result
.
Used
[
resourceName
]
=
resource
.
Quantity
{
Format
:
resource
.
DecimalSI
}
}
...
...
@@ -134,7 +134,7 @@ func CalculateUsageStats(options quota.UsageStatsOptions,
// need to verify that the item matches the set of scopes
matchesScopes
:=
true
for
_
,
scope
:=
range
options
.
Scopes
{
innerMatch
,
err
:=
scopeFunc
(
api
.
ScopedResourceSelectorRequirement
{
ScopeName
:
scope
},
item
)
innerMatch
,
err
:=
scopeFunc
(
corev1
.
ScopedResourceSelectorRequirement
{
ScopeName
:
scope
},
item
)
if
err
!=
nil
{
return
result
,
nil
}
...
...
@@ -174,11 +174,11 @@ type objectCountEvaluator struct {
// TODO move to dynamic client in future
listFuncByNamespace
ListFuncByNamespace
// Names associated with this resource in the quota for generic counting.
resourceNames
[]
api
.
ResourceName
resourceNames
[]
corev1
.
ResourceName
}
// Constraints returns an error if the configured resource name is not in the required set.
func
(
o
*
objectCountEvaluator
)
Constraints
(
required
[]
api
.
ResourceName
,
item
runtime
.
Object
)
error
{
func
(
o
*
objectCountEvaluator
)
Constraints
(
required
[]
corev1
.
ResourceName
,
item
runtime
.
Object
)
error
{
// no-op for object counting
return
nil
}
...
...
@@ -190,30 +190,30 @@ func (o *objectCountEvaluator) Handles(a admission.Attributes) bool {
}
// Matches returns true if the evaluator matches the specified quota with the provided input item
func
(
o
*
objectCountEvaluator
)
Matches
(
resourceQuota
*
api
.
ResourceQuota
,
item
runtime
.
Object
)
(
bool
,
error
)
{
func
(
o
*
objectCountEvaluator
)
Matches
(
resourceQuota
*
corev1
.
ResourceQuota
,
item
runtime
.
Object
)
(
bool
,
error
)
{
return
Matches
(
resourceQuota
,
item
,
o
.
MatchingResources
,
MatchesNoScopeFunc
)
}
// MatchingResources takes the input specified list of resources and returns the set of resources it matches.
func
(
o
*
objectCountEvaluator
)
MatchingResources
(
input
[]
api
.
ResourceName
)
[]
api
.
ResourceName
{
func
(
o
*
objectCountEvaluator
)
MatchingResources
(
input
[]
corev1
.
ResourceName
)
[]
corev1
.
ResourceName
{
return
quota
.
Intersection
(
input
,
o
.
resourceNames
)
}
// MatchingScopes takes the input specified list of scopes and input object. Returns the set of scopes resource matches.
func
(
o
*
objectCountEvaluator
)
MatchingScopes
(
item
runtime
.
Object
,
scopes
[]
api
.
ScopedResourceSelectorRequirement
)
([]
api
.
ScopedResourceSelectorRequirement
,
error
)
{
return
[]
api
.
ScopedResourceSelectorRequirement
{},
nil
func
(
o
*
objectCountEvaluator
)
MatchingScopes
(
item
runtime
.
Object
,
scopes
[]
corev1
.
ScopedResourceSelectorRequirement
)
([]
corev1
.
ScopedResourceSelectorRequirement
,
error
)
{
return
[]
corev1
.
ScopedResourceSelectorRequirement
{},
nil
}
// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes.
// It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope
func
(
o
*
objectCountEvaluator
)
UncoveredQuotaScopes
(
limitedScopes
[]
api
.
ScopedResourceSelectorRequirement
,
matchedQuotaScopes
[]
api
.
ScopedResourceSelectorRequirement
)
([]
api
.
ScopedResourceSelectorRequirement
,
error
)
{
return
[]
api
.
ScopedResourceSelectorRequirement
{},
nil
func
(
o
*
objectCountEvaluator
)
UncoveredQuotaScopes
(
limitedScopes
[]
corev1
.
ScopedResourceSelectorRequirement
,
matchedQuotaScopes
[]
corev1
.
ScopedResourceSelectorRequirement
)
([]
corev1
.
ScopedResourceSelectorRequirement
,
error
)
{
return
[]
corev1
.
ScopedResourceSelectorRequirement
{},
nil
}
// Usage returns the resource usage for the specified object
func
(
o
*
objectCountEvaluator
)
Usage
(
object
runtime
.
Object
)
(
api
.
ResourceList
,
error
)
{
func
(
o
*
objectCountEvaluator
)
Usage
(
object
runtime
.
Object
)
(
corev1
.
ResourceList
,
error
)
{
quantity
:=
resource
.
NewQuantity
(
1
,
resource
.
DecimalSI
)
resourceList
:=
api
.
ResourceList
{}
resourceList
:=
corev1
.
ResourceList
{}
for
_
,
resourceName
:=
range
o
.
resourceNames
{
resourceList
[
resourceName
]
=
*
quantity
}
...
...
@@ -239,9 +239,9 @@ var _ quota.Evaluator = &objectCountEvaluator{}
// backward compatibility, alias should not be used.
func
NewObjectCountEvaluator
(
groupResource
schema
.
GroupResource
,
listFuncByNamespace
ListFuncByNamespace
,
alias
api
.
ResourceName
)
quota
.
Evaluator
{
alias
corev1
.
ResourceName
)
quota
.
Evaluator
{
resourceNames
:=
[]
api
.
ResourceName
{
ObjectCountQuotaResourceNameFor
(
groupResource
)}
resourceNames
:=
[]
corev1
.
ResourceName
{
ObjectCountQuotaResourceNameFor
(
groupResource
)}
if
len
(
alias
)
>
0
{
resourceNames
=
append
(
resourceNames
,
alias
)
}
...
...
pkg/quota/generic/registry.go
→
pkg/quota/
v1/
generic/registry.go
View file @
ec3b0886
...
...
@@ -20,7 +20,7 @@ import (
"sync"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/quota
"
quota
"k8s.io/kubernetes/pkg/quota/v1
"
)
// implements a basic registry
...
...
pkg/quota/install/BUILD
→
pkg/quota/
v1/
install/BUILD
View file @
ec3b0886
...
...
@@ -8,11 +8,11 @@ load(
go_library(
name = "go_default_library",
srcs = ["registry.go"],
importpath = "k8s.io/kubernetes/pkg/quota/install",
importpath = "k8s.io/kubernetes/pkg/quota/
v1/
install",
deps = [
"//pkg/quota:go_default_library",
"//pkg/quota/evaluator/core:go_default_library",
"//pkg/quota/generic:go_default_library",
"//pkg/quota
/v1
:go_default_library",
"//pkg/quota/
v1/
evaluator/core:go_default_library",
"//pkg/quota/
v1/
generic:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
...
...
pkg/quota/install/OWNERS
→
pkg/quota/
v1/
install/OWNERS
View file @
ec3b0886
File moved
pkg/quota/install/registry.go
→
pkg/quota/
v1/
install/registry.go
View file @
ec3b0886
...
...
@@ -18,9 +18,9 @@ package install
import
(
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/quota
"
"k8s.io/kubernetes/pkg/quota
/evaluator/core"
"k8s.io/kubernetes/pkg/quota
/generic"
quota
"k8s.io/kubernetes/pkg/quota/v1
"
core
"k8s.io/kubernetes/pkg/quota/v1
/evaluator/core"
generic
"k8s.io/kubernetes/pkg/quota/v1
/generic"
)
// NewQuotaConfigurationForAdmission returns a quota configuration for admission control.
...
...
pkg/quota/interfaces.go
→
pkg/quota/
v1/
interfaces.go
View file @
ec3b0886
...
...
@@ -17,11 +17,11 @@ limitations under the License.
package
quota
import
(
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission"
"k8s.io/client-go/tools/cache"
api
"k8s.io/kubernetes/pkg/apis/core"
)
// UsageStatsOptions is an options structs that describes how stats should be calculated
...
...
@@ -29,37 +29,37 @@ type UsageStatsOptions struct {
// Namespace where stats should be calculate
Namespace
string
// Scopes that must match counted objects
Scopes
[]
api
.
ResourceQuotaScope
Scopes
[]
corev1
.
ResourceQuotaScope
// Resources are the set of resources to include in the measurement
Resources
[]
api
.
ResourceName
ScopeSelector
*
api
.
ScopeSelector
Resources
[]
corev1
.
ResourceName
ScopeSelector
*
corev1
.
ScopeSelector
}
// UsageStats is result of measuring observed resource use in the system
type
UsageStats
struct
{
// Used maps resource to quantity used
Used
api
.
ResourceList
Used
corev1
.
ResourceList
}
// Evaluator knows how to evaluate quota usage for a particular group resource
type
Evaluator
interface
{
// Constraints ensures that each required resource is present on item
Constraints
(
required
[]
api
.
ResourceName
,
item
runtime
.
Object
)
error
Constraints
(
required
[]
corev1
.
ResourceName
,
item
runtime
.
Object
)
error
// GroupResource returns the groupResource that this object knows how to evaluate
GroupResource
()
schema
.
GroupResource
// Handles determines if quota could be impacted by the specified attribute.
// If true, admission control must perform quota processing for the operation, otherwise it is safe to ignore quota.
Handles
(
operation
admission
.
Attributes
)
bool
// Matches returns true if the specified quota matches the input item
Matches
(
resourceQuota
*
api
.
ResourceQuota
,
item
runtime
.
Object
)
(
bool
,
error
)
Matches
(
resourceQuota
*
corev1
.
ResourceQuota
,
item
runtime
.
Object
)
(
bool
,
error
)
// MatchingScopes takes the input specified list of scopes and input object and returns the set of scopes that matches input object.
MatchingScopes
(
item
runtime
.
Object
,
scopes
[]
api
.
ScopedResourceSelectorRequirement
)
([]
api
.
ScopedResourceSelectorRequirement
,
error
)
MatchingScopes
(
item
runtime
.
Object
,
scopes
[]
corev1
.
ScopedResourceSelectorRequirement
)
([]
corev1
.
ScopedResourceSelectorRequirement
,
error
)
// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes. It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope
UncoveredQuotaScopes
(
limitedScopes
[]
api
.
ScopedResourceSelectorRequirement
,
matchedQuotaScopes
[]
api
.
ScopedResourceSelectorRequirement
)
([]
api
.
ScopedResourceSelectorRequirement
,
error
)
UncoveredQuotaScopes
(
limitedScopes
[]
corev1
.
ScopedResourceSelectorRequirement
,
matchedQuotaScopes
[]
corev1
.
ScopedResourceSelectorRequirement
)
([]
corev1
.
ScopedResourceSelectorRequirement
,
error
)
// MatchingResources takes the input specified list of resources and returns the set of resources evaluator matches.
MatchingResources
(
input
[]
api
.
ResourceName
)
[]
api
.
ResourceName
MatchingResources
(
input
[]
corev1
.
ResourceName
)
[]
corev1
.
ResourceName
// Usage returns the resource usage for the specified object
Usage
(
item
runtime
.
Object
)
(
api
.
ResourceList
,
error
)
Usage
(
item
runtime
.
Object
)
(
corev1
.
ResourceList
,
error
)
// UsageStats calculates latest observed usage stats for all objects
UsageStats
(
options
UsageStatsOptions
)
(
UsageStats
,
error
)
}
...
...
pkg/quota/resources.go
→
pkg/quota/
v1/
resources.go
View file @
ec3b0886
...
...
@@ -19,14 +19,13 @@ package quota
import
(
"strings"
"k8s.io/api/core/v1"
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/sets"
api
"k8s.io/kubernetes/pkg/apis/core"
)
// Equals returns true if the two lists are equivalent
func
Equals
(
a
api
.
ResourceList
,
b
api
.
ResourceList
)
bool
{
func
Equals
(
a
corev1
.
ResourceList
,
b
corev1
.
ResourceList
)
bool
{
if
len
(
a
)
!=
len
(
b
)
{
return
false
}
...
...
@@ -45,7 +44,7 @@ func Equals(a api.ResourceList, b api.ResourceList) bool {
}
// V1Equals returns true if the two lists are equivalent
func
V1Equals
(
a
v1
.
ResourceList
,
b
v1
.
ResourceList
)
bool
{
func
V1Equals
(
a
corev1
.
ResourceList
,
b
core
v1
.
ResourceList
)
bool
{
if
len
(
a
)
!=
len
(
b
)
{
return
false
}
...
...
@@ -65,9 +64,9 @@ func V1Equals(a v1.ResourceList, b v1.ResourceList) bool {
// LessThanOrEqual returns true if a < b for each key in 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
corev1
.
ResourceList
,
b
corev1
.
ResourceList
)
(
bool
,
[]
corev1
.
ResourceName
)
{
result
:=
true
resourceNames
:=
[]
api
.
ResourceName
{}
resourceNames
:=
[]
corev1
.
ResourceName
{}
for
key
,
value
:=
range
b
{
if
other
,
found
:=
a
[
key
];
found
{
if
other
.
Cmp
(
value
)
>
0
{
...
...
@@ -80,8 +79,8 @@ func LessThanOrEqual(a api.ResourceList, b api.ResourceList) (bool, []api.Resour
}
// Max returns the result of Max(a, b) for each named resource
func
Max
(
a
api
.
ResourceList
,
b
api
.
ResourceList
)
api
.
ResourceList
{
result
:=
api
.
ResourceList
{}
func
Max
(
a
corev1
.
ResourceList
,
b
corev1
.
ResourceList
)
corev1
.
ResourceList
{
result
:=
corev1
.
ResourceList
{}
for
key
,
value
:=
range
a
{
if
other
,
found
:=
b
[
key
];
found
{
if
value
.
Cmp
(
other
)
<=
0
{
...
...
@@ -100,8 +99,8 @@ func Max(a api.ResourceList, b api.ResourceList) api.ResourceList {
}
// Add returns the result of a + b for each named resource
func
Add
(
a
api
.
ResourceList
,
b
api
.
ResourceList
)
api
.
ResourceList
{
result
:=
api
.
ResourceList
{}
func
Add
(
a
corev1
.
ResourceList
,
b
corev1
.
ResourceList
)
corev1
.
ResourceList
{
result
:=
corev1
.
ResourceList
{}
for
key
,
value
:=
range
a
{
quantity
:=
*
value
.
Copy
()
if
other
,
found
:=
b
[
key
];
found
{
...
...
@@ -120,10 +119,10 @@ func Add(a api.ResourceList, b api.ResourceList) api.ResourceList {
// SubtractWithNonNegativeResult - subtracts and returns result of a - b but
// makes sure we don't return negative values to prevent negative resource usage.
func
SubtractWithNonNegativeResult
(
a
api
.
ResourceList
,
b
api
.
ResourceList
)
api
.
ResourceList
{
func
SubtractWithNonNegativeResult
(
a
corev1
.
ResourceList
,
b
corev1
.
ResourceList
)
corev1
.
ResourceList
{
zero
:=
resource
.
MustParse
(
"0"
)
result
:=
api
.
ResourceList
{}
result
:=
corev1
.
ResourceList
{}
for
key
,
value
:=
range
a
{
quantity
:=
*
value
.
Copy
()
if
other
,
found
:=
b
[
key
];
found
{
...
...
@@ -145,8 +144,8 @@ func SubtractWithNonNegativeResult(a api.ResourceList, b api.ResourceList) api.R
}
// Subtract returns the result of a - b for each named resource
func
Subtract
(
a
api
.
ResourceList
,
b
api
.
ResourceList
)
api
.
ResourceList
{
result
:=
api
.
ResourceList
{}
func
Subtract
(
a
corev1
.
ResourceList
,
b
corev1
.
ResourceList
)
corev1
.
ResourceList
{
result
:=
corev1
.
ResourceList
{}
for
key
,
value
:=
range
a
{
quantity
:=
*
value
.
Copy
()
if
other
,
found
:=
b
[
key
];
found
{
...
...
@@ -165,9 +164,9 @@ func Subtract(a api.ResourceList, b api.ResourceList) api.ResourceList {
}
// Mask returns a new resource list that only has the values with the specified names
func
Mask
(
resources
api
.
ResourceList
,
names
[]
api
.
ResourceName
)
api
.
ResourceList
{
func
Mask
(
resources
corev1
.
ResourceList
,
names
[]
corev1
.
ResourceName
)
corev1
.
ResourceList
{
nameSet
:=
ToSet
(
names
)
result
:=
api
.
ResourceList
{}
result
:=
corev1
.
ResourceList
{}
for
key
,
value
:=
range
resources
{
if
nameSet
.
Has
(
string
(
key
))
{
result
[
key
]
=
*
value
.
Copy
()
...
...
@@ -177,8 +176,8 @@ func Mask(resources api.ResourceList, names []api.ResourceName) api.ResourceList
}
// ResourceNames returns a list of all resource names in the ResourceList
func
ResourceNames
(
resources
api
.
ResourceList
)
[]
api
.
ResourceName
{
result
:=
[]
api
.
ResourceName
{}
func
ResourceNames
(
resources
corev1
.
ResourceList
)
[]
corev1
.
ResourceName
{
result
:=
[]
corev1
.
ResourceName
{}
for
resourceName
:=
range
resources
{
result
=
append
(
result
,
resourceName
)
}
...
...
@@ -186,12 +185,12 @@ func ResourceNames(resources api.ResourceList) []api.ResourceName {
}
// Contains returns true if the specified item is in the list of items
func
Contains
(
items
[]
api
.
ResourceName
,
item
api
.
ResourceName
)
bool
{
func
Contains
(
items
[]
corev1
.
ResourceName
,
item
corev1
.
ResourceName
)
bool
{
return
ToSet
(
items
)
.
Has
(
string
(
item
))
}
// ContainsPrefix returns true if the specified item has a prefix that contained in given prefix Set
func
ContainsPrefix
(
prefixSet
[]
string
,
item
api
.
ResourceName
)
bool
{
func
ContainsPrefix
(
prefixSet
[]
string
,
item
corev1
.
ResourceName
)
bool
{
for
_
,
prefix
:=
range
prefixSet
{
if
strings
.
HasPrefix
(
string
(
item
),
prefix
)
{
return
true
...
...
@@ -201,19 +200,19 @@ func ContainsPrefix(prefixSet []string, item api.ResourceName) bool {
}
// Intersection returns the intersection of both list of resources
func
Intersection
(
a
[]
api
.
ResourceName
,
b
[]
api
.
ResourceName
)
[]
api
.
ResourceName
{
func
Intersection
(
a
[]
corev1
.
ResourceName
,
b
[]
corev1
.
ResourceName
)
[]
corev1
.
ResourceName
{
setA
:=
ToSet
(
a
)
setB
:=
ToSet
(
b
)
setC
:=
setA
.
Intersection
(
setB
)
result
:=
[]
api
.
ResourceName
{}
result
:=
[]
corev1
.
ResourceName
{}
for
_
,
resourceName
:=
range
setC
.
List
()
{
result
=
append
(
result
,
api
.
ResourceName
(
resourceName
))
result
=
append
(
result
,
corev1
.
ResourceName
(
resourceName
))
}
return
result
}
// IsZero returns true if each key maps to the quantity value 0
func
IsZero
(
a
api
.
ResourceList
)
bool
{
func
IsZero
(
a
corev1
.
ResourceList
)
bool
{
zero
:=
resource
.
MustParse
(
"0"
)
for
_
,
v
:=
range
a
{
if
v
.
Cmp
(
zero
)
!=
0
{
...
...
@@ -224,8 +223,8 @@ func IsZero(a api.ResourceList) bool {
}
// IsNegative returns the set of resource names that have a negative value.
func
IsNegative
(
a
api
.
ResourceList
)
[]
api
.
ResourceName
{
results
:=
[]
api
.
ResourceName
{}
func
IsNegative
(
a
corev1
.
ResourceList
)
[]
corev1
.
ResourceName
{
results
:=
[]
corev1
.
ResourceName
{}
zero
:=
resource
.
MustParse
(
"0"
)
for
k
,
v
:=
range
a
{
if
v
.
Cmp
(
zero
)
<
0
{
...
...
@@ -236,7 +235,7 @@ func IsNegative(a api.ResourceList) []api.ResourceName {
}
// ToSet takes a list of resource names and converts to a string set
func
ToSet
(
resourceNames
[]
api
.
ResourceName
)
sets
.
String
{
func
ToSet
(
resourceNames
[]
corev1
.
ResourceName
)
sets
.
String
{
result
:=
sets
.
NewString
()
for
_
,
resourceName
:=
range
resourceNames
{
result
.
Insert
(
string
(
resourceName
))
...
...
@@ -245,12 +244,12 @@ func ToSet(resourceNames []api.ResourceName) sets.String {
}
// CalculateUsage calculates and returns the requested ResourceList usage
func
CalculateUsage
(
namespaceName
string
,
scopes
[]
api
.
ResourceQuotaScope
,
hardLimits
api
.
ResourceList
,
registry
Registry
,
scopeSelector
*
api
.
ScopeSelector
)
(
api
.
ResourceList
,
error
)
{
func
CalculateUsage
(
namespaceName
string
,
scopes
[]
corev1
.
ResourceQuotaScope
,
hardLimits
corev1
.
ResourceList
,
registry
Registry
,
scopeSelector
*
corev1
.
ScopeSelector
)
(
corev1
.
ResourceList
,
error
)
{
// 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
:=
ResourceNames
(
hardLimits
)
potentialResources
:=
[]
api
.
ResourceName
{}
potentialResources
:=
[]
corev1
.
ResourceName
{}
evaluators
:=
registry
.
List
()
for
_
,
evaluator
:=
range
evaluators
{
potentialResources
=
append
(
potentialResources
,
evaluator
.
MatchingResources
(
hardResources
)
...
)
...
...
@@ -259,7 +258,7 @@ func CalculateUsage(namespaceName string, scopes []api.ResourceQuotaScope, hardL
matchedResources
:=
Intersection
(
hardResources
,
potentialResources
)
// sum the observed usage from each evaluator
newUsage
:=
api
.
ResourceList
{}
newUsage
:=
corev1
.
ResourceList
{}
for
_
,
evaluator
:=
range
evaluators
{
// only trigger the evaluator if it matches a resource in the quota, otherwise, skip calculating anything
intersection
:=
evaluator
.
MatchingResources
(
matchedResources
)
...
...
pkg/quota/resources_test.go
→
pkg/quota/
v1/
resources_test.go
View file @
ec3b0886
...
...
@@ -19,52 +19,52 @@ package quota
import
(
"testing"
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
api
"k8s.io/kubernetes/pkg/apis/core"
)
func
TestEquals
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
struct
{
a
api
.
ResourceList
b
api
.
ResourceList
a
corev1
.
ResourceList
b
corev1
.
ResourceList
expected
bool
}{
"isEqual"
:
{
a
:
api
.
ResourceList
{},
b
:
api
.
ResourceList
{},
a
:
corev1
.
ResourceList
{},
b
:
corev1
.
ResourceList
{},
expected
:
true
,
},
"isEqualWithKeys"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
},
b
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
b
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
},
expected
:
true
,
},
"isNotEqualSameKeys"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"200m"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"200m"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
},
b
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
b
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
},
expected
:
false
,
},
"isNotEqualDiffKeys"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
},
b
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
api
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
b
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
corev1
.
ResourcePods
:
resource
.
MustParse
(
"1"
),
},
expected
:
false
,
},
...
...
@@ -78,34 +78,34 @@ func TestEquals(t *testing.T) {
func
TestMax
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
struct
{
a
api
.
ResourceList
b
api
.
ResourceList
expected
api
.
ResourceList
a
corev1
.
ResourceList
b
corev1
.
ResourceList
expected
corev1
.
ResourceList
}{
"noKeys"
:
{
a
:
api
.
ResourceList
{},
b
:
api
.
ResourceList
{},
expected
:
api
.
ResourceList
{},
a
:
corev1
.
ResourceList
{},
b
:
corev1
.
ResourceList
{},
expected
:
corev1
.
ResourceList
{},
},
"toEmpty"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
b
:
api
.
ResourceList
{},
expected
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
b
:
corev1
.
ResourceList
{},
expected
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
},
"matching"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
b
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"150m"
)},
expected
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"150m"
)},
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
b
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"150m"
)},
expected
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"150m"
)},
},
"matching(reverse)"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"150m"
)},
b
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
expected
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"150m"
)},
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"150m"
)},
b
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
expected
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"150m"
)},
},
"matching-equal"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
b
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
expected
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
b
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
expected
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
},
}
for
testName
,
testCase
:=
range
testCases
{
...
...
@@ -118,24 +118,24 @@ func TestMax(t *testing.T) {
func
TestAdd
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
struct
{
a
api
.
ResourceList
b
api
.
ResourceList
expected
api
.
ResourceList
a
corev1
.
ResourceList
b
corev1
.
ResourceList
expected
corev1
.
ResourceList
}{
"noKeys"
:
{
a
:
api
.
ResourceList
{},
b
:
api
.
ResourceList
{},
expected
:
api
.
ResourceList
{},
a
:
corev1
.
ResourceList
{},
b
:
corev1
.
ResourceList
{},
expected
:
corev1
.
ResourceList
{},
},
"toEmpty"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
b
:
api
.
ResourceList
{},
expected
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
b
:
corev1
.
ResourceList
{},
expected
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
},
"matching"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
b
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
expected
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"200m"
)},
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
b
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
expected
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"200m"
)},
},
}
for
testName
,
testCase
:=
range
testCases
{
...
...
@@ -148,29 +148,29 @@ func TestAdd(t *testing.T) {
func
TestSubtract
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
struct
{
a
api
.
ResourceList
b
api
.
ResourceList
expected
api
.
ResourceList
a
corev1
.
ResourceList
b
corev1
.
ResourceList
expected
corev1
.
ResourceList
}{
"noKeys"
:
{
a
:
api
.
ResourceList
{},
b
:
api
.
ResourceList
{},
expected
:
api
.
ResourceList
{},
a
:
corev1
.
ResourceList
{},
b
:
corev1
.
ResourceList
{},
expected
:
corev1
.
ResourceList
{},
},
"value-empty"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
b
:
api
.
ResourceList
{},
expected
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
b
:
corev1
.
ResourceList
{},
expected
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
},
"empty-value"
:
{
a
:
api
.
ResourceList
{},
b
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
expected
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"-100m"
)},
a
:
corev1
.
ResourceList
{},
b
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
expected
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"-100m"
)},
},
"value-value"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"200m"
)},
b
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
expected
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"200m"
)},
b
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
expected
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
)},
},
}
for
testName
,
testCase
:=
range
testCases
{
...
...
@@ -183,19 +183,19 @@ func TestSubtract(t *testing.T) {
func
TestResourceNames
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
struct
{
a
api
.
ResourceList
expected
[]
api
.
ResourceName
a
corev1
.
ResourceList
expected
[]
corev1
.
ResourceName
}{
"empty"
:
{
a
:
api
.
ResourceList
{},
expected
:
[]
api
.
ResourceName
{},
a
:
corev1
.
ResourceList
{},
expected
:
[]
corev1
.
ResourceName
{},
},
"values"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"100m"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
},
expected
:
[]
api
.
ResourceName
{
api
.
ResourceMemory
,
api
.
ResourceCPU
},
expected
:
[]
corev1
.
ResourceName
{
corev1
.
ResourceMemory
,
corev1
.
ResourceCPU
},
},
}
for
testName
,
testCase
:=
range
testCases
{
...
...
@@ -209,18 +209,18 @@ func TestResourceNames(t *testing.T) {
func
TestContains
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
struct
{
a
[]
api
.
ResourceName
b
api
.
ResourceName
a
[]
corev1
.
ResourceName
b
corev1
.
ResourceName
expected
bool
}{
"does-not-contain"
:
{
a
:
[]
api
.
ResourceName
{
api
.
ResourceMemory
},
b
:
api
.
ResourceCPU
,
a
:
[]
corev1
.
ResourceName
{
corev1
.
ResourceMemory
},
b
:
corev1
.
ResourceCPU
,
expected
:
false
,
},
"does-contain"
:
{
a
:
[]
api
.
ResourceName
{
api
.
ResourceMemory
,
api
.
ResourceCPU
},
b
:
api
.
ResourceCPU
,
a
:
[]
corev1
.
ResourceName
{
corev1
.
ResourceMemory
,
corev1
.
ResourceCPU
},
b
:
corev1
.
ResourceCPU
,
expected
:
true
,
},
}
...
...
@@ -234,17 +234,17 @@ func TestContains(t *testing.T) {
func
TestContainsPrefix
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
struct
{
a
[]
string
b
api
.
ResourceName
b
corev1
.
ResourceName
expected
bool
}{
"does-not-contain"
:
{
a
:
[]
string
{
api
.
ResourceHugePagesPrefix
},
b
:
api
.
ResourceCPU
,
a
:
[]
string
{
corev1
.
ResourceHugePagesPrefix
},
b
:
corev1
.
ResourceCPU
,
expected
:
false
,
},
"does-contain"
:
{
a
:
[]
string
{
api
.
ResourceHugePagesPrefix
},
b
:
api
.
ResourceName
(
api
.
ResourceHugePagesPrefix
+
"2Mi"
),
a
:
[]
string
{
corev1
.
ResourceHugePagesPrefix
},
b
:
corev1
.
ResourceName
(
corev1
.
ResourceHugePagesPrefix
+
"2Mi"
),
expected
:
true
,
},
}
...
...
@@ -257,24 +257,24 @@ func TestContainsPrefix(t *testing.T) {
func
TestIsZero
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
struct
{
a
api
.
ResourceList
a
corev1
.
ResourceList
expected
bool
}{
"empty"
:
{
a
:
api
.
ResourceList
{},
a
:
corev1
.
ResourceList
{},
expected
:
true
,
},
"zero"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"0"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"0"
),
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"0"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"0"
),
},
expected
:
true
,
},
"non-zero"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"200m"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"200m"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"1Gi"
),
},
expected
:
false
,
},
...
...
@@ -288,26 +288,26 @@ func TestIsZero(t *testing.T) {
func
TestIsNegative
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
struct
{
a
api
.
ResourceList
expected
[]
api
.
ResourceName
a
corev1
.
ResourceList
expected
[]
corev1
.
ResourceName
}{
"empty"
:
{
a
:
api
.
ResourceList
{},
expected
:
[]
api
.
ResourceName
{},
a
:
corev1
.
ResourceList
{},
expected
:
[]
corev1
.
ResourceName
{},
},
"some-negative"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"-10"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"0"
),
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"-10"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"0"
),
},
expected
:
[]
api
.
ResourceName
{
api
.
ResourceCPU
},
expected
:
[]
corev1
.
ResourceName
{
corev1
.
ResourceCPU
},
},
"all-negative"
:
{
a
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"-200m"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"-1Gi"
),
a
:
corev1
.
ResourceList
{
corev1
.
ResourceCPU
:
resource
.
MustParse
(
"-200m"
),
corev1
.
ResourceMemory
:
resource
.
MustParse
(
"-1Gi"
),
},
expected
:
[]
api
.
ResourceName
{
api
.
ResourceCPU
,
api
.
ResourceMemory
},
expected
:
[]
corev1
.
ResourceName
{
corev1
.
ResourceCPU
,
corev1
.
ResourceMemory
},
},
}
for
testName
,
testCase
:=
range
testCases
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment