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
bf6155b0
Commit
bf6155b0
authored
Aug 09, 2017
by
Chao Xu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
make admission plugins handle mutating spec of uninitialized pods
parent
e86f43bc
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
298 additions
and
6 deletions
+298
-6
BUILD
pkg/kubeapiserver/admission/BUILD
+1
-0
BUILD
pkg/kubeapiserver/admission/util/BUILD
+31
-0
initializer.go
pkg/kubeapiserver/admission/util/initializer.go
+56
-0
BUILD
plugin/pkg/admission/podnodeselector/BUILD
+1
-0
admission.go
plugin/pkg/admission/podnodeselector/admission.go
+12
-2
admission_test.go
plugin/pkg/admission/podnodeselector/admission_test.go
+51
-1
BUILD
plugin/pkg/admission/podtolerationrestriction/BUILD
+1
-0
admission.go
plugin/pkg/admission/podtolerationrestriction/admission.go
+6
-1
admission_test.go
.../pkg/admission/podtolerationrestriction/admission_test.go
+66
-0
BUILD
plugin/pkg/admission/serviceaccount/BUILD
+1
-0
admission.go
plugin/pkg/admission/serviceaccount/admission.go
+11
-1
admission_test.go
plugin/pkg/admission/serviceaccount/admission_test.go
+61
-1
No files found.
pkg/kubeapiserver/admission/BUILD
View file @
bf6155b0
...
@@ -42,6 +42,7 @@ filegroup(
...
@@ -42,6 +42,7 @@ filegroup(
srcs = [
srcs = [
":package-srcs",
":package-srcs",
"//pkg/kubeapiserver/admission/configuration:all-srcs",
"//pkg/kubeapiserver/admission/configuration:all-srcs",
"//pkg/kubeapiserver/admission/util:all-srcs",
],
],
tags = ["automanaged"],
tags = ["automanaged"],
)
)
pkg/kubeapiserver/admission/util/BUILD
0 → 100644
View file @
bf6155b0
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["initializer.go"],
tags = ["automanaged"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
pkg/kubeapiserver/admission/util/initializer.go
0 → 100644
View file @
bf6155b0
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
util
import
(
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apiserver/pkg/admission"
)
// IsUpdatingInitializedObject returns if the operation is trying to update an
// already initialized object.
func
IsUpdatingInitializedObject
(
a
admission
.
Attributes
)
(
bool
,
error
)
{
if
a
.
GetOperation
()
!=
admission
.
Update
{
return
false
,
nil
}
oldObj
:=
a
.
GetOldObject
()
accessor
,
err
:=
meta
.
Accessor
(
oldObj
)
if
err
!=
nil
{
return
false
,
err
}
if
accessor
.
GetInitializers
()
==
nil
{
return
true
,
nil
}
return
false
,
nil
}
// IsUpdatingUninitializedObject returns if the operation is trying to update an
// object that is not initialized yet.
func
IsUpdatingUninitializedObject
(
a
admission
.
Attributes
)
(
bool
,
error
)
{
if
a
.
GetOperation
()
!=
admission
.
Update
{
return
false
,
nil
}
oldObj
:=
a
.
GetOldObject
()
accessor
,
err
:=
meta
.
Accessor
(
oldObj
)
if
err
!=
nil
{
return
false
,
err
}
if
accessor
.
GetInitializers
()
==
nil
{
return
false
,
nil
}
return
true
,
nil
}
plugin/pkg/admission/podnodeselector/BUILD
View file @
bf6155b0
...
@@ -15,6 +15,7 @@ go_library(
...
@@ -15,6 +15,7 @@ go_library(
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
"//pkg/client/listers/core/internalversion:go_default_library",
"//pkg/client/listers/core/internalversion:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//pkg/kubeapiserver/admission/util:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
...
...
plugin/pkg/admission/podnodeselector/admission.go
View file @
bf6155b0
...
@@ -33,6 +33,7 @@ import (
...
@@ -33,6 +33,7 @@ import (
informers
"k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
informers
"k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
corelisters
"k8s.io/kubernetes/pkg/client/listers/core/internalversion"
corelisters
"k8s.io/kubernetes/pkg/client/listers/core/internalversion"
kubeapiserveradmission
"k8s.io/kubernetes/pkg/kubeapiserver/admission"
kubeapiserveradmission
"k8s.io/kubernetes/pkg/kubeapiserver/admission"
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util"
)
)
// The annotation key scheduler.alpha.kubernetes.io/node-selector is for assigning
// The annotation key scheduler.alpha.kubernetes.io/node-selector is for assigning
...
@@ -112,11 +113,20 @@ func (p *podNodeSelector) Admit(a admission.Attributes) error {
...
@@ -112,11 +113,20 @@ func (p *podNodeSelector) Admit(a admission.Attributes) error {
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"not yet ready to handle request"
))
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"not yet ready to handle request"
))
}
}
updateInitialized
,
err
:=
util
.
IsUpdatingInitializedObject
(
a
)
if
err
!=
nil
{
return
err
}
if
updateInitialized
{
// node selector of an initialized pod is immutable
return
nil
}
name
:=
pod
.
Name
name
:=
pod
.
Name
nsName
:=
a
.
GetNamespace
()
nsName
:=
a
.
GetNamespace
()
var
namespace
*
api
.
Namespace
var
namespace
*
api
.
Namespace
namespace
,
err
:
=
p
.
namespaceLister
.
Get
(
nsName
)
namespace
,
err
=
p
.
namespaceLister
.
Get
(
nsName
)
if
errors
.
IsNotFound
(
err
)
{
if
errors
.
IsNotFound
(
err
)
{
namespace
,
err
=
p
.
defaultGetNamespace
(
nsName
)
namespace
,
err
=
p
.
defaultGetNamespace
(
nsName
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -158,7 +168,7 @@ func (p *podNodeSelector) Admit(a admission.Attributes) error {
...
@@ -158,7 +168,7 @@ func (p *podNodeSelector) Admit(a admission.Attributes) error {
func
NewPodNodeSelector
(
clusterNodeSelectors
map
[
string
]
string
)
*
podNodeSelector
{
func
NewPodNodeSelector
(
clusterNodeSelectors
map
[
string
]
string
)
*
podNodeSelector
{
return
&
podNodeSelector
{
return
&
podNodeSelector
{
Handler
:
admission
.
NewHandler
(
admission
.
Create
),
Handler
:
admission
.
NewHandler
(
admission
.
Create
,
admission
.
Update
),
clusterNodeSelectors
:
clusterNodeSelectors
,
clusterNodeSelectors
:
clusterNodeSelectors
,
}
}
}
}
...
...
plugin/pkg/admission/podnodeselector/admission_test.go
View file @
bf6155b0
...
@@ -52,6 +52,12 @@ func TestPodAdmission(t *testing.T) {
...
@@ -52,6 +52,12 @@ func TestPodAdmission(t *testing.T) {
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"testPod"
,
Namespace
:
"testNamespace"
},
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"testPod"
,
Namespace
:
"testNamespace"
},
}
}
oldPod
:=
*
pod
oldPod
.
Initializers
=
&
metav1
.
Initializers
{
Pending
:
[]
metav1
.
Initializer
{{
Name
:
"init"
}}}
oldPod
.
Spec
.
NodeSelector
=
map
[
string
]
string
{
"old"
:
"true"
,
}
tests
:=
[]
struct
{
tests
:=
[]
struct
{
defaultNodeSelector
string
defaultNodeSelector
string
namespaceNodeSelector
string
namespaceNodeSelector
string
...
@@ -166,7 +172,17 @@ func TestPodAdmission(t *testing.T) {
...
@@ -166,7 +172,17 @@ func TestPodAdmission(t *testing.T) {
}
else
if
!
test
.
admit
&&
err
==
nil
{
}
else
if
!
test
.
admit
&&
err
==
nil
{
t
.
Errorf
(
"Test: %s, expected an error"
,
test
.
testName
)
t
.
Errorf
(
"Test: %s, expected an error"
,
test
.
testName
)
}
}
if
test
.
admit
&&
!
labels
.
Equals
(
test
.
mergedNodeSelector
,
labels
.
Set
(
pod
.
Spec
.
NodeSelector
))
{
t
.
Errorf
(
"Test: %s, expected: %s but got: %s"
,
test
.
testName
,
test
.
mergedNodeSelector
,
pod
.
Spec
.
NodeSelector
)
}
// handles update of uninitialized pod like it's newly created.
err
=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
pod
,
&
oldPod
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"testNamespace"
,
namespace
.
ObjectMeta
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Update
,
nil
))
if
test
.
admit
&&
err
!=
nil
{
t
.
Errorf
(
"Test: %s, expected no error but got: %s"
,
test
.
testName
,
err
)
}
else
if
!
test
.
admit
&&
err
==
nil
{
t
.
Errorf
(
"Test: %s, expected an error"
,
test
.
testName
)
}
if
test
.
admit
&&
!
labels
.
Equals
(
test
.
mergedNodeSelector
,
labels
.
Set
(
pod
.
Spec
.
NodeSelector
))
{
if
test
.
admit
&&
!
labels
.
Equals
(
test
.
mergedNodeSelector
,
labels
.
Set
(
pod
.
Spec
.
NodeSelector
))
{
t
.
Errorf
(
"Test: %s, expected: %s but got: %s"
,
test
.
testName
,
test
.
mergedNodeSelector
,
pod
.
Spec
.
NodeSelector
)
t
.
Errorf
(
"Test: %s, expected: %s but got: %s"
,
test
.
testName
,
test
.
mergedNodeSelector
,
pod
.
Spec
.
NodeSelector
)
}
}
...
@@ -176,7 +192,7 @@ func TestPodAdmission(t *testing.T) {
...
@@ -176,7 +192,7 @@ func TestPodAdmission(t *testing.T) {
func
TestHandles
(
t
*
testing
.
T
)
{
func
TestHandles
(
t
*
testing
.
T
)
{
for
op
,
shouldHandle
:=
range
map
[
admission
.
Operation
]
bool
{
for
op
,
shouldHandle
:=
range
map
[
admission
.
Operation
]
bool
{
admission
.
Create
:
true
,
admission
.
Create
:
true
,
admission
.
Update
:
fals
e
,
admission
.
Update
:
tru
e
,
admission
.
Connect
:
false
,
admission
.
Connect
:
false
,
admission
.
Delete
:
false
,
admission
.
Delete
:
false
,
}
{
}
{
...
@@ -187,6 +203,40 @@ func TestHandles(t *testing.T) {
...
@@ -187,6 +203,40 @@ func TestHandles(t *testing.T) {
}
}
}
}
func
TestIgnoreUpdatingInitializedPod
(
t
*
testing
.
T
)
{
mockClient
:=
&
fake
.
Clientset
{}
handler
,
informerFactory
,
err
:=
newHandlerForTest
(
mockClient
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error initializing handler: %v"
,
err
)
}
handler
.
SetReadyFunc
(
func
()
bool
{
return
true
})
podNodeSelector
:=
map
[
string
]
string
{
"infra"
:
"false"
}
pod
:=
&
api
.
Pod
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"testPod"
,
Namespace
:
"testNamespace"
},
Spec
:
api
.
PodSpec
{
NodeSelector
:
podNodeSelector
},
}
// this conflicts with podNodeSelector
namespaceNodeSelector
:=
"infra=true"
namespace
:=
&
api
.
Namespace
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"testNamespace"
,
Namespace
:
""
,
Annotations
:
map
[
string
]
string
{
"scheduler.alpha.kubernetes.io/node-selector"
:
namespaceNodeSelector
},
},
}
err
=
informerFactory
.
Core
()
.
InternalVersion
()
.
Namespaces
()
.
Informer
()
.
GetStore
()
.
Update
(
namespace
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// if the update of initialized pod is not ignored, an error will be returned because the pod's nodeSelector conflicts with namespace's nodeSelector.
err
=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
pod
,
pod
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"testNamespace"
,
namespace
.
ObjectMeta
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Update
,
nil
))
if
err
!=
nil
{
t
.
Errorf
(
"expected no error, got: %v"
,
err
)
}
}
// newHandlerForTest returns the admission controller configured for testing.
// newHandlerForTest returns the admission controller configured for testing.
func
newHandlerForTest
(
c
clientset
.
Interface
)
(
*
podNodeSelector
,
informers
.
SharedInformerFactory
,
error
)
{
func
newHandlerForTest
(
c
clientset
.
Interface
)
(
*
podNodeSelector
,
informers
.
SharedInformerFactory
,
error
)
{
f
:=
informers
.
NewSharedInformerFactory
(
c
,
5
*
time
.
Minute
)
f
:=
informers
.
NewSharedInformerFactory
(
c
,
5
*
time
.
Minute
)
...
...
plugin/pkg/admission/podtolerationrestriction/BUILD
View file @
bf6155b0
...
@@ -40,6 +40,7 @@ go_library(
...
@@ -40,6 +40,7 @@ go_library(
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
"//pkg/client/listers/core/internalversion:go_default_library",
"//pkg/client/listers/core/internalversion:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//pkg/kubeapiserver/admission/util:go_default_library",
"//pkg/util/tolerations:go_default_library",
"//pkg/util/tolerations:go_default_library",
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library",
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library",
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install:go_default_library",
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install:go_default_library",
...
...
plugin/pkg/admission/podtolerationrestriction/admission.go
View file @
bf6155b0
...
@@ -34,6 +34,7 @@ import (
...
@@ -34,6 +34,7 @@ import (
informers
"k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
informers
"k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
corelisters
"k8s.io/kubernetes/pkg/client/listers/core/internalversion"
corelisters
"k8s.io/kubernetes/pkg/client/listers/core/internalversion"
kubeapiserveradmission
"k8s.io/kubernetes/pkg/kubeapiserver/admission"
kubeapiserveradmission
"k8s.io/kubernetes/pkg/kubeapiserver/admission"
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util"
"k8s.io/kubernetes/pkg/util/tolerations"
"k8s.io/kubernetes/pkg/util/tolerations"
pluginapi
"k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
pluginapi
"k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
...
@@ -112,7 +113,11 @@ func (p *podTolerationsPlugin) Admit(a admission.Attributes) error {
...
@@ -112,7 +113,11 @@ func (p *podTolerationsPlugin) Admit(a admission.Attributes) error {
}
}
var
finalTolerations
[]
api
.
Toleration
var
finalTolerations
[]
api
.
Toleration
if
a
.
GetOperation
()
==
admission
.
Create
{
updateUninitialized
,
err
:=
util
.
IsUpdatingUninitializedObject
(
a
)
if
err
!=
nil
{
return
err
}
if
a
.
GetOperation
()
==
admission
.
Create
||
updateUninitialized
{
ts
,
err
:=
p
.
getNamespaceDefaultTolerations
(
namespace
)
ts
,
err
:=
p
.
getNamespaceDefaultTolerations
(
namespace
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
...
plugin/pkg/admission/podtolerationrestriction/admission_test.go
View file @
bf6155b0
...
@@ -233,6 +233,11 @@ func TestPodAdmission(t *testing.T) {
...
@@ -233,6 +233,11 @@ func TestPodAdmission(t *testing.T) {
pod
:=
test
.
pod
pod
:=
test
.
pod
pod
.
Spec
.
Tolerations
=
test
.
podTolerations
pod
.
Spec
.
Tolerations
=
test
.
podTolerations
// copy the original pod for tests of uninitialized pod updates.
oldPod
:=
*
pod
oldPod
.
Initializers
=
&
metav1
.
Initializers
{
Pending
:
[]
metav1
.
Initializer
{{
Name
:
"init"
}}}
oldPod
.
Spec
.
Tolerations
=
[]
api
.
Toleration
{{
Key
:
"testKey"
,
Operator
:
"Equal"
,
Value
:
"testValue1"
,
Effect
:
"NoSchedule"
,
TolerationSeconds
:
nil
}}
err
:=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"testNamespace"
,
namespace
.
ObjectMeta
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
))
err
:=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"testNamespace"
,
namespace
.
ObjectMeta
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
))
if
test
.
admit
&&
err
!=
nil
{
if
test
.
admit
&&
err
!=
nil
{
t
.
Errorf
(
"Test: %s, expected no error but got: %s"
,
test
.
testName
,
err
)
t
.
Errorf
(
"Test: %s, expected no error but got: %s"
,
test
.
testName
,
err
)
...
@@ -244,6 +249,19 @@ func TestPodAdmission(t *testing.T) {
...
@@ -244,6 +249,19 @@ func TestPodAdmission(t *testing.T) {
if
test
.
admit
&&
!
tolerations
.
EqualTolerations
(
updatedPodTolerations
,
test
.
mergedTolerations
)
{
if
test
.
admit
&&
!
tolerations
.
EqualTolerations
(
updatedPodTolerations
,
test
.
mergedTolerations
)
{
t
.
Errorf
(
"Test: %s, expected: %#v but got: %#v"
,
test
.
testName
,
test
.
mergedTolerations
,
updatedPodTolerations
)
t
.
Errorf
(
"Test: %s, expected: %#v but got: %#v"
,
test
.
testName
,
test
.
mergedTolerations
,
updatedPodTolerations
)
}
}
// handles update of uninitialized pod like it's newly created.
err
=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
pod
,
&
oldPod
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"testNamespace"
,
namespace
.
ObjectMeta
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Update
,
nil
))
if
test
.
admit
&&
err
!=
nil
{
t
.
Errorf
(
"Test: %s, expected no error but got: %s"
,
test
.
testName
,
err
)
}
else
if
!
test
.
admit
&&
err
==
nil
{
t
.
Errorf
(
"Test: %s, expected an error"
,
test
.
testName
)
}
updatedPodTolerations
=
pod
.
Spec
.
Tolerations
if
test
.
admit
&&
!
tolerations
.
EqualTolerations
(
updatedPodTolerations
,
test
.
mergedTolerations
)
{
t
.
Errorf
(
"Test: %s, expected: %#v but got: %#v"
,
test
.
testName
,
test
.
mergedTolerations
,
updatedPodTolerations
)
}
}
}
}
}
...
@@ -267,6 +285,54 @@ func TestHandles(t *testing.T) {
...
@@ -267,6 +285,54 @@ func TestHandles(t *testing.T) {
}
}
}
}
func
TestIgnoreUpdatingInitializedPod
(
t
*
testing
.
T
)
{
mockClient
:=
&
fake
.
Clientset
{}
handler
,
informerFactory
,
err
:=
newHandlerForTest
(
mockClient
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error initializing handler: %v"
,
err
)
}
handler
.
SetReadyFunc
(
func
()
bool
{
return
true
})
pod
:=
&
api
.
Pod
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"testPod"
,
Namespace
:
"testNamespace"
},
Spec
:
api
.
PodSpec
{},
}
podToleration
:=
api
.
Toleration
{
Key
:
"testKey"
,
Operator
:
"Equal"
,
Value
:
"testValue1"
,
Effect
:
"NoSchedule"
,
TolerationSeconds
:
nil
,
}
pod
.
Spec
.
Tolerations
=
[]
api
.
Toleration
{
podToleration
}
// this conflicts with pod's Tolerations
namespaceToleration
:=
podToleration
namespaceToleration
.
Value
=
"testValue2"
namespaceTolerations
:=
[]
api
.
Toleration
{
namespaceToleration
}
tolerationsStr
,
err
:=
json
.
Marshal
(
namespaceTolerations
)
if
err
!=
nil
{
t
.
Errorf
(
"error in marshalling namespace tolerations %v"
,
namespaceTolerations
)
}
namespace
:=
&
api
.
Namespace
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"testNamespace"
,
Namespace
:
""
,
},
}
namespace
.
Annotations
=
map
[
string
]
string
{
NSDefaultTolerations
:
string
(
tolerationsStr
)}
err
=
informerFactory
.
Core
()
.
InternalVersion
()
.
Namespaces
()
.
Informer
()
.
GetStore
()
.
Update
(
namespace
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// if the update of initialized pod is not ignored, an error will be returned because the pod's Tolerations conflicts with namespace's Tolerations.
err
=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
pod
,
pod
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"testNamespace"
,
pod
.
ObjectMeta
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Update
,
nil
))
if
err
!=
nil
{
t
.
Errorf
(
"expected no error, got: %v"
,
err
)
}
}
// newHandlerForTest returns the admission controller configured for testing.
// newHandlerForTest returns the admission controller configured for testing.
func
newHandlerForTest
(
c
clientset
.
Interface
)
(
*
podTolerationsPlugin
,
informers
.
SharedInformerFactory
,
error
)
{
func
newHandlerForTest
(
c
clientset
.
Interface
)
(
*
podTolerationsPlugin
,
informers
.
SharedInformerFactory
,
error
)
{
f
:=
informers
.
NewSharedInformerFactory
(
c
,
5
*
time
.
Minute
)
f
:=
informers
.
NewSharedInformerFactory
(
c
,
5
*
time
.
Minute
)
...
...
plugin/pkg/admission/serviceaccount/BUILD
View file @
bf6155b0
...
@@ -19,6 +19,7 @@ go_library(
...
@@ -19,6 +19,7 @@ go_library(
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
"//pkg/client/listers/core/internalversion:go_default_library",
"//pkg/client/listers/core/internalversion:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//pkg/kubeapiserver/admission/util:go_default_library",
"//pkg/serviceaccount:go_default_library",
"//pkg/serviceaccount:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
...
...
plugin/pkg/admission/serviceaccount/admission.go
View file @
bf6155b0
...
@@ -36,6 +36,7 @@ import (
...
@@ -36,6 +36,7 @@ import (
informers
"k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
informers
"k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
corelisters
"k8s.io/kubernetes/pkg/client/listers/core/internalversion"
corelisters
"k8s.io/kubernetes/pkg/client/listers/core/internalversion"
kubeapiserveradmission
"k8s.io/kubernetes/pkg/kubeapiserver/admission"
kubeapiserveradmission
"k8s.io/kubernetes/pkg/kubeapiserver/admission"
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util"
"k8s.io/kubernetes/pkg/serviceaccount"
"k8s.io/kubernetes/pkg/serviceaccount"
)
)
...
@@ -90,7 +91,7 @@ var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&serviceAccount{
...
@@ -90,7 +91,7 @@ var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&serviceAccount{
// 5. If MountServiceAccountToken is true, it adds a VolumeMount with the pod's ServiceAccount's api token secret to containers
// 5. If MountServiceAccountToken is true, it adds a VolumeMount with the pod's ServiceAccount's api token secret to containers
func
NewServiceAccount
()
*
serviceAccount
{
func
NewServiceAccount
()
*
serviceAccount
{
return
&
serviceAccount
{
return
&
serviceAccount
{
Handler
:
admission
.
NewHandler
(
admission
.
Create
),
Handler
:
admission
.
NewHandler
(
admission
.
Create
,
admission
.
Update
),
// TODO: enable this once we've swept secret usage to account for adding secret references to service accounts
// TODO: enable this once we've swept secret usage to account for adding secret references to service accounts
LimitSecretReferences
:
false
,
LimitSecretReferences
:
false
,
// Auto mount service account API token secrets
// Auto mount service account API token secrets
...
@@ -143,6 +144,15 @@ func (s *serviceAccount) Admit(a admission.Attributes) (err error) {
...
@@ -143,6 +144,15 @@ func (s *serviceAccount) Admit(a admission.Attributes) (err error) {
return
nil
return
nil
}
}
updateInitialized
,
err
:=
util
.
IsUpdatingInitializedObject
(
a
)
if
err
!=
nil
{
return
err
}
if
updateInitialized
{
// related pod spec fields are immutable after the pod is initialized
return
nil
}
// Don't modify the spec of mirror pods.
// Don't modify the spec of mirror pods.
// That makes the kubelet very angry and confused, and it immediately deletes the pod (because the spec doesn't match)
// That makes the kubelet very angry and confused, and it immediately deletes the pod (because the spec doesn't match)
// That said, don't allow mirror pods to reference ServiceAccounts or SecretVolumeSources either
// That said, don't allow mirror pods to reference ServiceAccounts or SecretVolumeSources either
...
...
plugin/pkg/admission/serviceaccount/admission_test.go
View file @
bf6155b0
...
@@ -36,7 +36,7 @@ import (
...
@@ -36,7 +36,7 @@ import (
func
TestIgnoresNonCreate
(
t
*
testing
.
T
)
{
func
TestIgnoresNonCreate
(
t
*
testing
.
T
)
{
pod
:=
&
api
.
Pod
{}
pod
:=
&
api
.
Pod
{}
for
_
,
op
:=
range
[]
admission
.
Operation
{
admission
.
Update
,
admission
.
Delete
,
admission
.
Connect
}
{
for
_
,
op
:=
range
[]
admission
.
Operation
{
admission
.
Delete
,
admission
.
Connect
}
{
attrs
:=
admission
.
NewAttributesRecord
(
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"myns"
,
"myname"
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
op
,
nil
)
attrs
:=
admission
.
NewAttributesRecord
(
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"myns"
,
"myname"
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
op
,
nil
)
handler
:=
admission
.
NewChainHandler
(
NewServiceAccount
())
handler
:=
admission
.
NewChainHandler
(
NewServiceAccount
())
err
:=
handler
.
Admit
(
attrs
)
err
:=
handler
.
Admit
(
attrs
)
...
@@ -46,6 +46,17 @@ func TestIgnoresNonCreate(t *testing.T) {
...
@@ -46,6 +46,17 @@ func TestIgnoresNonCreate(t *testing.T) {
}
}
}
}
func
TestIgnoresUpdateOfInitializedPod
(
t
*
testing
.
T
)
{
pod
:=
&
api
.
Pod
{}
oldPod
:=
&
api
.
Pod
{}
attrs
:=
admission
.
NewAttributesRecord
(
pod
,
oldPod
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"myns"
,
"myname"
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Update
,
nil
)
handler
:=
admission
.
NewChainHandler
(
NewServiceAccount
())
err
:=
handler
.
Admit
(
attrs
)
if
err
!=
nil
{
t
.
Errorf
(
"Expected update of initialized pod allowed, got err: %v"
,
err
)
}
}
func
TestIgnoresNonPodResource
(
t
*
testing
.
T
)
{
func
TestIgnoresNonPodResource
(
t
*
testing
.
T
)
{
pod
:=
&
api
.
Pod
{}
pod
:=
&
api
.
Pod
{}
attrs
:=
admission
.
NewAttributesRecord
(
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"myns"
,
"myname"
,
api
.
Resource
(
"CustomResource"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
)
attrs
:=
admission
.
NewAttributesRecord
(
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"myns"
,
"myname"
,
api
.
Resource
(
"CustomResource"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
)
...
@@ -309,6 +320,55 @@ func TestAutomountsAPIToken(t *testing.T) {
...
@@ -309,6 +320,55 @@ func TestAutomountsAPIToken(t *testing.T) {
t
.
Fatalf
(
"Expected
\n\t
%#v
\n
got
\n\t
%#v"
,
expectedVolumeMount
,
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
[
0
])
t
.
Fatalf
(
"Expected
\n\t
%#v
\n
got
\n\t
%#v"
,
expectedVolumeMount
,
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
[
0
])
}
}
// Test ServiceAccount admission plugin applies the same changes if the
// operation is an update to an uninitialized pod.
oldPod
:=
&
api
.
Pod
{
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{
// the volumeMount in the oldPod shouldn't affect the result.
VolumeMounts
:
[]
api
.
VolumeMount
{
{
Name
:
"wrong-"
+
tokenName
,
ReadOnly
:
true
,
MountPath
:
DefaultAPITokenMountPath
,
},
},
},
},
},
}
// oldPod is not intialized.
oldPod
.
Initializers
=
&
metav1
.
Initializers
{
Pending
:
[]
metav1
.
Initializer
{{
Name
:
"init"
}}}
pod
=
&
api
.
Pod
{
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{},
},
},
}
attrs
=
admission
.
NewAttributesRecord
(
pod
,
oldPod
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
ns
,
"myname"
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Update
,
nil
)
err
=
admit
.
Admit
(
attrs
)
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
if
pod
.
Spec
.
ServiceAccountName
!=
DefaultServiceAccountName
{
t
.
Errorf
(
"Expected service account %s assigned, got %s"
,
DefaultServiceAccountName
,
pod
.
Spec
.
ServiceAccountName
)
}
if
len
(
pod
.
Spec
.
Volumes
)
!=
1
{
t
.
Fatalf
(
"Expected 1 volume, got %d"
,
len
(
pod
.
Spec
.
Volumes
))
}
if
!
reflect
.
DeepEqual
(
expectedVolume
,
pod
.
Spec
.
Volumes
[
0
])
{
t
.
Fatalf
(
"Expected
\n\t
%#v
\n
got
\n\t
%#v"
,
expectedVolume
,
pod
.
Spec
.
Volumes
[
0
])
}
if
len
(
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
)
!=
1
{
t
.
Fatalf
(
"Expected 1 volume mount, got %d"
,
len
(
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
))
}
if
!
reflect
.
DeepEqual
(
expectedVolumeMount
,
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
[
0
])
{
t
.
Fatalf
(
"Expected
\n\t
%#v
\n
got
\n\t
%#v"
,
expectedVolumeMount
,
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
[
0
])
}
// testing InitContainers
pod
=
&
api
.
Pod
{
pod
=
&
api
.
Pod
{
Spec
:
api
.
PodSpec
{
Spec
:
api
.
PodSpec
{
InitContainers
:
[]
api
.
Container
{
InitContainers
:
[]
api
.
Container
{
...
...
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