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
61ba80cb
Commit
61ba80cb
authored
Aug 24, 2018
by
yue9944882
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
externalize limitrange
parent
444373b4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
99 additions
and
94 deletions
+99
-94
BUILD
plugin/pkg/admission/limitranger/BUILD
+11
-8
admission.go
plugin/pkg/admission/limitranger/admission.go
+56
-65
admission_test.go
plugin/pkg/admission/limitranger/admission_test.go
+28
-17
interfaces.go
plugin/pkg/admission/limitranger/interfaces.go
+4
-4
No files found.
plugin/pkg/admission/limitranger/BUILD
View file @
61ba80cb
...
...
@@ -15,10 +15,7 @@ go_library(
importpath = "k8s.io/kubernetes/plugin/pkg/admission/limitranger",
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
"//pkg/client/listers/core/internalversion:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta: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",
...
...
@@ -26,6 +23,10 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
"//vendor/github.com/hashicorp/golang-lru:go_default_library",
],
)
...
...
@@ -36,16 +37,18 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//pkg/apis/core/v1:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/equality: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:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/testing:go_default_library",
],
)
...
...
plugin/pkg/admission/limitranger/admission.go
View file @
61ba80cb
...
...
@@ -23,8 +23,9 @@ import (
"strings"
"time"
lru
"github.com/hashicorp/golang-lru"
"github.com/hashicorp/golang-lru"
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/resource"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
...
...
@@ -32,11 +33,11 @@ import (
"k8s.io/apimachinery/pkg/runtime"
utilerrors
"k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apiserver/pkg/admission"
genericadmissioninitailizer
"k8s.io/apiserver/pkg/admission/initializer"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
corev1listers
"k8s.io/client-go/listers/core/v1"
api
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
informers
"k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
corelisters
"k8s.io/kubernetes/pkg/client/listers/core/internalversion"
kubeapiserveradmission
"k8s.io/kubernetes/pkg/kubeapiserver/admission"
)
const
(
...
...
@@ -55,9 +56,9 @@ func Register(plugins *admission.Plugins) {
// LimitRanger enforces usage limits on a per resource basis in the namespace
type
LimitRanger
struct
{
*
admission
.
Handler
client
internalclientset
.
Interface
client
kubernetes
.
Interface
actions
LimitRangerActions
lister
corelisters
.
LimitRangeLister
lister
core
v1
listers
.
LimitRangeLister
// liveLookups holds the last few live lookups we've done to help ammortize cost on repeated lookup failures.
// This let's us handle the case of latent caches, by looking up actual results for a namespace on cache miss/no results.
...
...
@@ -68,19 +69,25 @@ type LimitRanger struct {
var
_
admission
.
MutationInterface
=
&
LimitRanger
{}
var
_
admission
.
ValidationInterface
=
&
LimitRanger
{}
var
_
kubeapiserveradmission
.
WantsInternalKubeInformerFactory
=
&
LimitRanger
{}
var
_
genericadmissioninitailizer
.
WantsExternalKubeInformerFactory
=
&
LimitRanger
{}
var
_
genericadmissioninitailizer
.
WantsExternalKubeClientSet
=
&
LimitRanger
{}
type
liveLookupEntry
struct
{
expiry
time
.
Time
items
[]
*
api
.
LimitRange
items
[]
*
corev1
.
LimitRange
}
func
(
l
*
LimitRanger
)
Set
In
ternalKubeInformerFactory
(
f
informers
.
SharedInformerFactory
)
{
limitRangeInformer
:=
f
.
Core
()
.
InternalVersion
()
.
LimitRanges
()
func
(
l
*
LimitRanger
)
Set
Ex
ternalKubeInformerFactory
(
f
informers
.
SharedInformerFactory
)
{
limitRangeInformer
:=
f
.
Core
()
.
V1
()
.
LimitRanges
()
l
.
SetReadyFunc
(
limitRangeInformer
.
Informer
()
.
HasSynced
)
l
.
lister
=
limitRangeInformer
.
Lister
()
}
func
(
a
*
LimitRanger
)
SetExternalKubeClientSet
(
client
kubernetes
.
Interface
)
{
a
.
client
=
client
}
func
(
l
*
LimitRanger
)
ValidateInitialization
()
error
{
if
l
.
lister
==
nil
{
return
fmt
.
Errorf
(
"missing limitRange lister"
)
...
...
@@ -101,20 +108,11 @@ func (l *LimitRanger) Validate(a admission.Attributes) (err error) {
return
l
.
runLimitFunc
(
a
,
l
.
actions
.
ValidateLimit
)
}
func
(
l
*
LimitRanger
)
runLimitFunc
(
a
admission
.
Attributes
,
limitFn
func
(
limitRange
*
api
.
LimitRange
,
kind
string
,
obj
runtime
.
Object
)
error
)
(
err
error
)
{
func
(
l
*
LimitRanger
)
runLimitFunc
(
a
admission
.
Attributes
,
limitFn
func
(
limitRange
*
corev1
.
LimitRange
,
kind
string
,
obj
runtime
.
Object
)
error
)
(
err
error
)
{
if
!
l
.
actions
.
SupportsAttributes
(
a
)
{
return
nil
}
obj
:=
a
.
GetObject
()
name
:=
"Unknown"
if
obj
!=
nil
{
name
,
_
=
meta
.
NewAccessor
()
.
Name
(
obj
)
if
len
(
name
)
==
0
{
name
,
_
=
meta
.
NewAccessor
()
.
GenerateName
(
obj
)
}
}
// ignore all objects marked for deletion
oldObj
:=
a
.
GetOldObject
()
if
oldObj
!=
nil
{
...
...
@@ -148,7 +146,7 @@ func (l *LimitRanger) runLimitFunc(a admission.Attributes, limitFn func(limitRan
return
nil
}
func
(
l
*
LimitRanger
)
GetLimitRanges
(
a
admission
.
Attributes
)
([]
*
api
.
LimitRange
,
error
)
{
func
(
l
*
LimitRanger
)
GetLimitRanges
(
a
admission
.
Attributes
)
([]
*
corev1
.
LimitRange
,
error
)
{
items
,
err
:=
l
.
lister
.
LimitRanges
(
a
.
GetNamespace
())
.
List
(
labels
.
Everything
())
if
err
!=
nil
{
return
nil
,
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"unable to %s %v at this time because there was an error enforcing limit ranges"
,
a
.
GetOperation
(),
a
.
GetResource
()))
...
...
@@ -163,7 +161,7 @@ func (l *LimitRanger) GetLimitRanges(a admission.Attributes) ([]*api.LimitRange,
// If there is already in-flight List() for a given namespace, we should wait until
// it is finished and cache is updated instead of doing the same, also to avoid
// throttling - see #22422 for details.
liveList
,
err
:=
l
.
client
.
Core
()
.
LimitRanges
(
a
.
GetNamespace
())
.
List
(
metav1
.
ListOptions
{})
liveList
,
err
:=
l
.
client
.
Core
V1
()
.
LimitRanges
(
a
.
GetNamespace
())
.
List
(
metav1
.
ListOptions
{})
if
err
!=
nil
{
return
nil
,
admission
.
NewForbidden
(
a
,
err
)
}
...
...
@@ -204,31 +202,24 @@ func NewLimitRanger(actions LimitRangerActions) (*LimitRanger, error) {
},
nil
}
var
_
=
kubeapiserveradmission
.
WantsInternalKubeInformerFactory
(
&
LimitRanger
{})
var
_
=
kubeapiserveradmission
.
WantsInternalKubeClientSet
(
&
LimitRanger
{})
func
(
a
*
LimitRanger
)
SetInternalKubeClientSet
(
client
internalclientset
.
Interface
)
{
a
.
client
=
client
}
// defaultContainerResourceRequirements returns the default requirements for a container
// the requirement.Limits are taken from the LimitRange defaults (if specified)
// the requirement.Requests are taken from the LimitRange default request (if specified)
func
defaultContainerResourceRequirements
(
limitRange
*
api
.
LimitRange
)
api
.
ResourceRequirements
{
func
defaultContainerResourceRequirements
(
limitRange
*
corev1
.
LimitRange
)
api
.
ResourceRequirements
{
requirements
:=
api
.
ResourceRequirements
{}
requirements
.
Requests
=
api
.
ResourceList
{}
requirements
.
Limits
=
api
.
ResourceList
{}
for
i
:=
range
limitRange
.
Spec
.
Limits
{
limit
:=
limitRange
.
Spec
.
Limits
[
i
]
if
limit
.
Type
==
api
.
LimitTypeContainer
{
if
limit
.
Type
==
corev1
.
LimitTypeContainer
{
for
k
,
v
:=
range
limit
.
DefaultRequest
{
value
:=
v
.
Copy
()
requirements
.
Requests
[
k
]
=
*
value
requirements
.
Requests
[
api
.
ResourceName
(
k
)
]
=
*
value
}
for
k
,
v
:=
range
limit
.
Default
{
value
:=
v
.
Copy
()
requirements
.
Limits
[
k
]
=
*
value
requirements
.
Limits
[
api
.
ResourceName
(
k
)
]
=
*
value
}
}
}
...
...
@@ -309,9 +300,9 @@ func requestLimitEnforcedValues(requestQuantity, limitQuantity, enforcedQuantity
}
// minConstraint enforces the min constraint over the specified resource
func
minConstraint
(
limitType
api
.
LimitType
,
resourceName
api
.
ResourceName
,
enforced
resource
.
Quantity
,
request
api
.
ResourceList
,
limit
api
.
ResourceList
)
error
{
req
,
reqExists
:=
request
[
resourceName
]
lim
,
limExists
:=
limit
[
resourceName
]
func
minConstraint
(
limitType
string
,
resourceName
string
,
enforced
resource
.
Quantity
,
request
api
.
ResourceList
,
limit
api
.
ResourceList
)
error
{
req
,
reqExists
:=
request
[
api
.
ResourceName
(
resourceName
)
]
lim
,
limExists
:=
limit
[
api
.
ResourceName
(
resourceName
)
]
observedReqValue
,
observedLimValue
,
enforcedValue
:=
requestLimitEnforcedValues
(
req
,
lim
,
enforced
)
if
!
reqExists
{
...
...
@@ -328,8 +319,8 @@ func minConstraint(limitType api.LimitType, resourceName api.ResourceName, enfor
// maxRequestConstraint enforces the max constraint over the specified resource
// use when specify LimitType resource doesn't recognize limit values
func
maxRequestConstraint
(
limitType
api
.
LimitType
,
resourceName
api
.
ResourceName
,
enforced
resource
.
Quantity
,
request
api
.
ResourceList
)
error
{
req
,
reqExists
:=
request
[
resourceName
]
func
maxRequestConstraint
(
limitType
string
,
resourceName
string
,
enforced
resource
.
Quantity
,
request
api
.
ResourceList
)
error
{
req
,
reqExists
:=
request
[
api
.
ResourceName
(
resourceName
)
]
observedReqValue
,
_
,
enforcedValue
:=
requestLimitEnforcedValues
(
req
,
resource
.
Quantity
{},
enforced
)
if
!
reqExists
{
...
...
@@ -342,9 +333,9 @@ func maxRequestConstraint(limitType api.LimitType, resourceName api.ResourceName
}
// maxConstraint enforces the max constraint over the specified resource
func
maxConstraint
(
limitType
api
.
LimitType
,
resourceName
api
.
ResourceName
,
enforced
resource
.
Quantity
,
request
api
.
ResourceList
,
limit
api
.
ResourceList
)
error
{
req
,
reqExists
:=
request
[
resourceName
]
lim
,
limExists
:=
limit
[
resourceName
]
func
maxConstraint
(
limitType
string
,
resourceName
string
,
enforced
resource
.
Quantity
,
request
api
.
ResourceList
,
limit
api
.
ResourceList
)
error
{
req
,
reqExists
:=
request
[
api
.
ResourceName
(
resourceName
)
]
lim
,
limExists
:=
limit
[
api
.
ResourceName
(
resourceName
)
]
observedReqValue
,
observedLimValue
,
enforcedValue
:=
requestLimitEnforcedValues
(
req
,
lim
,
enforced
)
if
!
limExists
{
...
...
@@ -360,9 +351,9 @@ func maxConstraint(limitType api.LimitType, resourceName api.ResourceName, enfor
}
// limitRequestRatioConstraint enforces the limit to request ratio over the specified resource
func
limitRequestRatioConstraint
(
limitType
api
.
LimitType
,
resourceName
api
.
ResourceName
,
enforced
resource
.
Quantity
,
request
api
.
ResourceList
,
limit
api
.
ResourceList
)
error
{
req
,
reqExists
:=
request
[
resourceName
]
lim
,
limExists
:=
limit
[
resourceName
]
func
limitRequestRatioConstraint
(
limitType
string
,
resourceName
string
,
enforced
resource
.
Quantity
,
request
api
.
ResourceList
,
limit
api
.
ResourceList
)
error
{
req
,
reqExists
:=
request
[
api
.
ResourceName
(
resourceName
)
]
lim
,
limExists
:=
limit
[
api
.
ResourceName
(
resourceName
)
]
observedReqValue
,
observedLimValue
,
_
:=
requestLimitEnforcedValues
(
req
,
lim
,
enforced
)
if
!
reqExists
||
(
observedReqValue
==
int64
(
0
))
{
...
...
@@ -435,7 +426,7 @@ var _ LimitRangerActions = &DefaultLimitRangerActions{}
// Limit enforces resource requirements of incoming resources against enumerated constraints
// on the LimitRange. It may modify the incoming object to apply default resource requirements
// if not specified, and enumerated on the LimitRange
func
(
d
*
DefaultLimitRangerActions
)
MutateLimit
(
limitRange
*
api
.
LimitRange
,
resourceName
string
,
obj
runtime
.
Object
)
error
{
func
(
d
*
DefaultLimitRangerActions
)
MutateLimit
(
limitRange
*
corev1
.
LimitRange
,
resourceName
string
,
obj
runtime
.
Object
)
error
{
switch
resourceName
{
case
"pods"
:
return
PodMutateLimitFunc
(
limitRange
,
obj
.
(
*
api
.
Pod
))
...
...
@@ -446,7 +437,7 @@ func (d *DefaultLimitRangerActions) MutateLimit(limitRange *api.LimitRange, reso
// Limit enforces resource requirements of incoming resources against enumerated constraints
// on the LimitRange. It may modify the incoming object to apply default resource requirements
// if not specified, and enumerated on the LimitRange
func
(
d
*
DefaultLimitRangerActions
)
ValidateLimit
(
limitRange
*
api
.
LimitRange
,
resourceName
string
,
obj
runtime
.
Object
)
error
{
func
(
d
*
DefaultLimitRangerActions
)
ValidateLimit
(
limitRange
*
corev1
.
LimitRange
,
resourceName
string
,
obj
runtime
.
Object
)
error
{
switch
resourceName
{
case
"pods"
:
return
PodValidateLimitFunc
(
limitRange
,
obj
.
(
*
api
.
Pod
))
...
...
@@ -467,7 +458,7 @@ func (d *DefaultLimitRangerActions) SupportsAttributes(a admission.Attributes) b
}
// SupportsLimit always returns true.
func
(
d
*
DefaultLimitRangerActions
)
SupportsLimit
(
limitRange
*
api
.
LimitRange
)
bool
{
func
(
d
*
DefaultLimitRangerActions
)
SupportsLimit
(
limitRange
*
corev1
.
LimitRange
)
bool
{
return
true
}
...
...
@@ -475,22 +466,22 @@ func (d *DefaultLimitRangerActions) SupportsLimit(limitRange *api.LimitRange) bo
// Users request storage via pvc.Spec.Resources.Requests. Min/Max is enforced by an admin with LimitRange.
// Claims will not be modified with default values because storage is a required part of pvc.Spec.
// All storage enforced values *only* apply to pvc.Spec.Resources.Requests.
func
PersistentVolumeClaimValidateLimitFunc
(
limitRange
*
api
.
LimitRange
,
pvc
*
api
.
PersistentVolumeClaim
)
error
{
func
PersistentVolumeClaimValidateLimitFunc
(
limitRange
*
corev1
.
LimitRange
,
pvc
*
api
.
PersistentVolumeClaim
)
error
{
var
errs
[]
error
for
i
:=
range
limitRange
.
Spec
.
Limits
{
limit
:=
limitRange
.
Spec
.
Limits
[
i
]
limitType
:=
limit
.
Type
if
limitType
==
api
.
LimitTypePersistentVolumeClaim
{
if
limitType
==
corev1
.
LimitTypePersistentVolumeClaim
{
for
k
,
v
:=
range
limit
.
Min
{
// normal usage of minConstraint. pvc.Spec.Resources.Limits is not recognized as user input
if
err
:=
minConstraint
(
limitType
,
k
,
v
,
pvc
.
Spec
.
Resources
.
Requests
,
api
.
ResourceList
{});
err
!=
nil
{
if
err
:=
minConstraint
(
string
(
limitType
),
string
(
k
)
,
v
,
pvc
.
Spec
.
Resources
.
Requests
,
api
.
ResourceList
{});
err
!=
nil
{
errs
=
append
(
errs
,
err
)
}
}
for
k
,
v
:=
range
limit
.
Max
{
// We want to enforce the max of the LimitRange against what
// the user requested.
if
err
:=
maxRequestConstraint
(
limitType
,
k
,
v
,
pvc
.
Spec
.
Resources
.
Requests
);
err
!=
nil
{
if
err
:=
maxRequestConstraint
(
string
(
limitType
),
string
(
k
)
,
v
,
pvc
.
Spec
.
Resources
.
Requests
);
err
!=
nil
{
errs
=
append
(
errs
,
err
)
}
}
...
...
@@ -502,7 +493,7 @@ func PersistentVolumeClaimValidateLimitFunc(limitRange *api.LimitRange, pvc *api
// PodMutateLimitFunc sets resource requirements enumerated by the pod against
// the specified LimitRange. The pod may be modified to apply default resource
// requirements if not specified, and enumerated on the LimitRange
func
PodMutateLimitFunc
(
limitRange
*
api
.
LimitRange
,
pod
*
api
.
Pod
)
error
{
func
PodMutateLimitFunc
(
limitRange
*
corev1
.
LimitRange
,
pod
*
api
.
Pod
)
error
{
defaultResources
:=
defaultContainerResourceRequirements
(
limitRange
)
mergePodResourceRequirements
(
pod
,
&
defaultResources
)
return
nil
...
...
@@ -510,28 +501,28 @@ func PodMutateLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {
// PodValidateLimitFunc enforces resource requirements enumerated by the pod against
// the specified LimitRange.
func
PodValidateLimitFunc
(
limitRange
*
api
.
LimitRange
,
pod
*
api
.
Pod
)
error
{
func
PodValidateLimitFunc
(
limitRange
*
corev1
.
LimitRange
,
pod
*
api
.
Pod
)
error
{
var
errs
[]
error
for
i
:=
range
limitRange
.
Spec
.
Limits
{
limit
:=
limitRange
.
Spec
.
Limits
[
i
]
limitType
:=
limit
.
Type
// enforce container limits
if
limitType
==
api
.
LimitTypeContainer
{
if
limitType
==
corev1
.
LimitTypeContainer
{
for
j
:=
range
pod
.
Spec
.
Containers
{
container
:=
&
pod
.
Spec
.
Containers
[
j
]
for
k
,
v
:=
range
limit
.
Min
{
if
err
:=
minConstraint
(
limitType
,
k
,
v
,
container
.
Resources
.
Requests
,
container
.
Resources
.
Limits
);
err
!=
nil
{
if
err
:=
minConstraint
(
string
(
limitType
),
string
(
k
)
,
v
,
container
.
Resources
.
Requests
,
container
.
Resources
.
Limits
);
err
!=
nil
{
errs
=
append
(
errs
,
err
)
}
}
for
k
,
v
:=
range
limit
.
Max
{
if
err
:=
maxConstraint
(
limitType
,
k
,
v
,
container
.
Resources
.
Requests
,
container
.
Resources
.
Limits
);
err
!=
nil
{
if
err
:=
maxConstraint
(
string
(
limitType
),
string
(
k
)
,
v
,
container
.
Resources
.
Requests
,
container
.
Resources
.
Limits
);
err
!=
nil
{
errs
=
append
(
errs
,
err
)
}
}
for
k
,
v
:=
range
limit
.
MaxLimitRequestRatio
{
if
err
:=
limitRequestRatioConstraint
(
limitType
,
k
,
v
,
container
.
Resources
.
Requests
,
container
.
Resources
.
Limits
);
err
!=
nil
{
if
err
:=
limitRequestRatioConstraint
(
string
(
limitType
),
string
(
k
)
,
v
,
container
.
Resources
.
Requests
,
container
.
Resources
.
Limits
);
err
!=
nil
{
errs
=
append
(
errs
,
err
)
}
}
...
...
@@ -539,17 +530,17 @@ func PodValidateLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {
for
j
:=
range
pod
.
Spec
.
InitContainers
{
container
:=
&
pod
.
Spec
.
InitContainers
[
j
]
for
k
,
v
:=
range
limit
.
Min
{
if
err
:=
minConstraint
(
limitType
,
k
,
v
,
container
.
Resources
.
Requests
,
container
.
Resources
.
Limits
);
err
!=
nil
{
if
err
:=
minConstraint
(
string
(
limitType
),
string
(
k
)
,
v
,
container
.
Resources
.
Requests
,
container
.
Resources
.
Limits
);
err
!=
nil
{
errs
=
append
(
errs
,
err
)
}
}
for
k
,
v
:=
range
limit
.
Max
{
if
err
:=
maxConstraint
(
limitType
,
k
,
v
,
container
.
Resources
.
Requests
,
container
.
Resources
.
Limits
);
err
!=
nil
{
if
err
:=
maxConstraint
(
string
(
limitType
),
string
(
k
)
,
v
,
container
.
Resources
.
Requests
,
container
.
Resources
.
Limits
);
err
!=
nil
{
errs
=
append
(
errs
,
err
)
}
}
for
k
,
v
:=
range
limit
.
MaxLimitRequestRatio
{
if
err
:=
limitRequestRatioConstraint
(
limitType
,
k
,
v
,
container
.
Resources
.
Requests
,
container
.
Resources
.
Limits
);
err
!=
nil
{
if
err
:=
limitRequestRatioConstraint
(
string
(
limitType
),
string
(
k
)
,
v
,
container
.
Resources
.
Requests
,
container
.
Resources
.
Limits
);
err
!=
nil
{
errs
=
append
(
errs
,
err
)
}
}
...
...
@@ -557,7 +548,7 @@ func PodValidateLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {
}
// enforce pod limits on init containers
if
limitType
==
api
.
LimitTypePod
{
if
limitType
==
corev1
.
LimitTypePod
{
containerRequests
,
containerLimits
:=
[]
api
.
ResourceList
{},
[]
api
.
ResourceList
{}
for
j
:=
range
pod
.
Spec
.
Containers
{
container
:=
&
pod
.
Spec
.
Containers
[
j
]
...
...
@@ -589,17 +580,17 @@ func PodValidateLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {
}
}
for
k
,
v
:=
range
limit
.
Min
{
if
err
:=
minConstraint
(
limitType
,
k
,
v
,
podRequests
,
podLimits
);
err
!=
nil
{
if
err
:=
minConstraint
(
string
(
limitType
),
string
(
k
)
,
v
,
podRequests
,
podLimits
);
err
!=
nil
{
errs
=
append
(
errs
,
err
)
}
}
for
k
,
v
:=
range
limit
.
Max
{
if
err
:=
maxConstraint
(
limitType
,
k
,
v
,
podRequests
,
podLimits
);
err
!=
nil
{
if
err
:=
maxConstraint
(
string
(
limitType
),
string
(
k
)
,
v
,
podRequests
,
podLimits
);
err
!=
nil
{
errs
=
append
(
errs
,
err
)
}
}
for
k
,
v
:=
range
limit
.
MaxLimitRequestRatio
{
if
err
:=
limitRequestRatioConstraint
(
limitType
,
k
,
v
,
podRequests
,
podLimits
);
err
!=
nil
{
if
err
:=
limitRequestRatioConstraint
(
string
(
limitType
),
string
(
k
)
,
v
,
podRequests
,
podLimits
);
err
!=
nil
{
errs
=
append
(
errs
,
err
)
}
}
...
...
plugin/pkg/admission/limitranger/admission_test.go
View file @
61ba80cb
...
...
@@ -22,18 +22,20 @@ import (
"testing"
"time"
corev1
"k8s.io/api/core/v1"
apiequality
"k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/resource"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/admission"
genericadmissioninitializer
"k8s.io/apiserver/pkg/admission/initializer"
"k8s.io/client-go/informers"
clientset
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
core
"k8s.io/client-go/testing"
api
"k8s.io/kubernetes/pkg/apis/core"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
informers
"k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
kubeadmission
"k8s.io/kubernetes/pkg/kubeapiserver/admission"
"k8s.io/kubernetes/pkg/apis/core/v1"
)
func
getComputeResourceList
(
cpu
,
memory
string
)
api
.
ResourceList
{
...
...
@@ -63,8 +65,8 @@ func getResourceRequirements(requests, limits api.ResourceList) api.ResourceRequ
}
// createLimitRange creates a limit range with the specified data
func
createLimitRange
(
limitType
api
.
LimitType
,
min
,
max
,
defaultLimit
,
defaultRequest
,
maxLimitRequestRatio
api
.
ResourceList
)
api
.
LimitRange
{
return
api
.
LimitRange
{
func
createLimitRange
(
limitType
api
.
LimitType
,
min
,
max
,
defaultLimit
,
defaultRequest
,
maxLimitRequestRatio
api
.
ResourceList
)
corev1
.
LimitRange
{
internalLimitRage
:=
api
.
LimitRange
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
"test"
,
...
...
@@ -82,10 +84,13 @@ func createLimitRange(limitType api.LimitType, min, max, defaultLimit, defaultRe
},
},
}
externalLimitRange
:=
corev1
.
LimitRange
{}
v1
.
Convert_core_LimitRange_To_v1_LimitRange
(
&
internalLimitRage
,
&
externalLimitRange
,
nil
)
return
externalLimitRange
}
func
validLimitRange
()
api
.
LimitRange
{
return
api
.
LimitRange
{
func
validLimitRange
()
corev1
.
LimitRange
{
internalLimitRange
:=
api
.
LimitRange
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
"test"
,
...
...
@@ -107,10 +112,13 @@ func validLimitRange() api.LimitRange {
},
},
}
externalLimitRange
:=
corev1
.
LimitRange
{}
v1
.
Convert_core_LimitRange_To_v1_LimitRange
(
&
internalLimitRange
,
&
externalLimitRange
,
nil
)
return
externalLimitRange
}
func
validLimitRangeNoDefaults
()
api
.
LimitRange
{
return
api
.
LimitRange
{
func
validLimitRangeNoDefaults
()
corev1
.
LimitRange
{
internalLimitRange
:=
api
.
LimitRange
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
"test"
,
...
...
@@ -130,6 +138,9 @@ func validLimitRangeNoDefaults() api.LimitRange {
},
},
}
externalLimitRange
:=
corev1
.
LimitRange
{}
v1
.
Convert_core_LimitRange_To_v1_LimitRange
(
&
internalLimitRange
,
&
externalLimitRange
,
nil
)
return
externalLimitRange
}
func
validPod
(
name
string
,
numContainers
int
,
resources
api
.
ResourceRequirements
)
api
.
Pod
{
...
...
@@ -255,7 +266,7 @@ func TestMergePodResourceRequirements(t *testing.T) {
func
TestPodLimitFunc
(
t
*
testing
.
T
)
{
type
testCase
struct
{
pod
api
.
Pod
limitRange
api
.
LimitRange
limitRange
corev1
.
LimitRange
}
successCases
:=
[]
testCase
{
...
...
@@ -686,7 +697,7 @@ func TestPodLimitFuncApplyDefault(t *testing.T) {
func
TestLimitRangerIgnoresSubresource
(
t
*
testing
.
T
)
{
limitRange
:=
validLimitRangeNoDefaults
()
mockClient
:=
newMockClientForTest
([]
api
.
LimitRange
{
limitRange
})
mockClient
:=
newMockClientForTest
([]
corev1
.
LimitRange
{
limitRange
})
handler
,
informerFactory
,
err
:=
newHandlerForTest
(
mockClient
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error initializing handler: %v"
,
err
)
...
...
@@ -712,7 +723,7 @@ func TestLimitRangerIgnoresSubresource(t *testing.T) {
func
TestLimitRangerAdmitPod
(
t
*
testing
.
T
)
{
limitRange
:=
validLimitRangeNoDefaults
()
mockClient
:=
newMockClientForTest
([]
api
.
LimitRange
{
limitRange
})
mockClient
:=
newMockClientForTest
([]
corev1
.
LimitRange
{
limitRange
})
handler
,
informerFactory
,
err
:=
newHandlerForTest
(
mockClient
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error initializing handler: %v"
,
err
)
...
...
@@ -745,10 +756,10 @@ func TestLimitRangerAdmitPod(t *testing.T) {
}
// newMockClientForTest creates a mock client that returns a client configured for the specified list of limit ranges
func
newMockClientForTest
(
limitRanges
[]
api
.
LimitRange
)
*
fake
.
Clientset
{
func
newMockClientForTest
(
limitRanges
[]
corev1
.
LimitRange
)
*
fake
.
Clientset
{
mockClient
:=
&
fake
.
Clientset
{}
mockClient
.
AddReactor
(
"list"
,
"limitranges"
,
func
(
action
core
.
Action
)
(
bool
,
runtime
.
Object
,
error
)
{
limitRangeList
:=
&
api
.
LimitRangeList
{
limitRangeList
:=
&
corev1
.
LimitRangeList
{
ListMeta
:
metav1
.
ListMeta
{
ResourceVersion
:
fmt
.
Sprintf
(
"%d"
,
len
(
limitRanges
)),
},
...
...
@@ -769,7 +780,7 @@ func newHandlerForTest(c clientset.Interface) (*LimitRanger, informers.SharedInf
if
err
!=
nil
{
return
nil
,
f
,
err
}
pluginInitializer
:=
kubeadmission
.
NewPluginInitializer
(
c
,
f
,
nil
,
nil
,
nil
)
pluginInitializer
:=
genericadmissioninitializer
.
New
(
c
,
f
,
nil
,
nil
)
pluginInitializer
.
Initialize
(
handler
)
err
=
admission
.
ValidateInitialization
(
handler
)
return
handler
,
f
,
err
...
...
@@ -788,7 +799,7 @@ func validPersistentVolumeClaim(name string, resources api.ResourceRequirements)
func
TestPersistentVolumeClaimLimitFunc
(
t
*
testing
.
T
)
{
type
testCase
struct
{
pvc
api
.
PersistentVolumeClaim
limitRange
api
.
LimitRange
limitRange
corev1
.
LimitRange
}
successCases
:=
[]
testCase
{
...
...
plugin/pkg/admission/limitranger/interfaces.go
View file @
61ba80cb
...
...
@@ -17,20 +17,20 @@ limitations under the License.
package
limitranger
import
(
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission"
api
"k8s.io/kubernetes/pkg/apis/core"
)
type
LimitRangerActions
interface
{
// MutateLimit is a pluggable function to set limits on the object.
MutateLimit
(
limitRange
*
api
.
LimitRange
,
kind
string
,
obj
runtime
.
Object
)
error
MutateLimit
(
limitRange
*
corev1
.
LimitRange
,
kind
string
,
obj
runtime
.
Object
)
error
// ValidateLimits is a pluggable function to enforce limits on the object.
ValidateLimit
(
limitRange
*
api
.
LimitRange
,
kind
string
,
obj
runtime
.
Object
)
error
ValidateLimit
(
limitRange
*
corev1
.
LimitRange
,
kind
string
,
obj
runtime
.
Object
)
error
// SupportsAttributes is a pluggable function to allow overridding what resources the limitranger
// supports.
SupportsAttributes
(
attr
admission
.
Attributes
)
bool
// SupportsLimit is a pluggable function to allow ignoring limits that should not be applied
// for any reason.
SupportsLimit
(
limitRange
*
api
.
LimitRange
)
bool
SupportsLimit
(
limitRange
*
corev1
.
LimitRange
)
bool
}
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