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
5029bb56
Commit
5029bb56
authored
Jan 09, 2018
by
Chao Xu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Let mutating webhook defaults the object after applying the patch sent back by the webhook
parent
009701f1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
120 additions
and
5 deletions
+120
-5
admission.go
...server/pkg/admission/plugin/webhook/mutating/admission.go
+6
-2
webhook.go
test/e2e/apimachinery/webhook.go
+78
-0
Makefile
test/images/webhook/Makefile
+2
-2
main.go
test/images/webhook/main.go
+33
-0
manifest.go
test/utils/image/manifest.go
+1
-1
No files found.
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/admission.go
View file @
5029bb56
...
...
@@ -112,6 +112,7 @@ type MutatingWebhook struct {
namespaceMatcher
namespace
.
Matcher
clientManager
config
.
ClientManager
convertor
versioned
.
Convertor
defaulter
runtime
.
ObjectDefaulter
jsonSerializer
runtime
.
Serializer
}
...
...
@@ -137,6 +138,7 @@ func (a *MutatingWebhook) SetScheme(scheme *runtime.Scheme) {
Serializer
:
serializer
.
NewCodecFactory
(
scheme
)
.
LegacyCodec
(
admissionv1beta1
.
SchemeGroupVersion
),
}))
a
.
convertor
.
Scheme
=
scheme
a
.
defaulter
=
scheme
a
.
jsonSerializer
=
json
.
NewSerializer
(
json
.
DefaultMetaFactory
,
scheme
,
scheme
,
false
)
}
}
...
...
@@ -171,6 +173,9 @@ func (a *MutatingWebhook) ValidateInitialization() error {
if
err
:=
a
.
convertor
.
Validate
();
err
!=
nil
{
return
fmt
.
Errorf
(
"MutatingWebhook.convertor is not properly setup: %v"
,
err
)
}
if
a
.
defaulter
==
nil
{
return
fmt
.
Errorf
(
"MutatingWebhook.defaulter is not properly setup: %v"
)
}
go
a
.
hookSource
.
Run
(
wait
.
NeverStop
)
return
nil
}
...
...
@@ -312,10 +317,9 @@ func (a *MutatingWebhook) callAttrMutatingHook(ctx context.Context, h *v1beta1.W
if
err
!=
nil
{
return
apierrors
.
NewInternalError
(
err
)
}
// TODO: if we have multiple mutating webhooks, we can remember the json
// instead of encoding and decoding for each one.
if
_
,
_
,
err
:=
a
.
jsonSerializer
.
Decode
(
patchedJS
,
nil
,
attr
.
Object
);
err
!=
nil
{
return
apierrors
.
NewInternalError
(
err
)
}
a
.
defaulter
.
Default
(
attr
.
Object
)
return
nil
}
test/e2e/apimachinery/webhook.go
View file @
5029bb56
...
...
@@ -133,6 +133,12 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
testMutatingConfigMapWebhook
(
f
)
})
It
(
"Should mutate pod and apply defaults after mutation"
,
func
()
{
registerMutatingWebhookForPod
(
f
,
context
)
defer
client
.
AdmissionregistrationV1beta1
()
.
MutatingWebhookConfigurations
()
.
Delete
(
mutatingWebhookConfigName
,
nil
)
testMutatingPodWebhook
(
f
)
})
It
(
"Should mutate crd"
,
func
()
{
crdCleanup
,
dynamicClient
:=
createCRD
(
f
)
defer
crdCleanup
()
...
...
@@ -423,6 +429,7 @@ func registerMutatingWebhookForConfigMap(f *framework.Framework, context *certCo
// The webhook configuration is honored in 1s.
time
.
Sleep
(
10
*
time
.
Second
)
}
func
testMutatingConfigMapWebhook
(
f
*
framework
.
Framework
)
{
By
(
"create a configmap that should be updated by the webhook"
)
client
:=
f
.
ClientSet
...
...
@@ -439,6 +446,77 @@ func testMutatingConfigMapWebhook(f *framework.Framework) {
}
}
func
registerMutatingWebhookForPod
(
f
*
framework
.
Framework
,
context
*
certContext
)
{
client
:=
f
.
ClientSet
By
(
"Registering the mutating pod webhook via the AdmissionRegistration API"
)
namespace
:=
f
.
Namespace
.
Name
_
,
err
:=
client
.
AdmissionregistrationV1beta1
()
.
MutatingWebhookConfigurations
()
.
Create
(
&
v1beta1
.
MutatingWebhookConfiguration
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
mutatingWebhookConfigName
,
},
Webhooks
:
[]
v1beta1
.
Webhook
{
{
Name
:
"adding-init-container.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Operations
:
[]
v1beta1
.
OperationType
{
v1beta1
.
Create
},
Rule
:
v1beta1
.
Rule
{
APIGroups
:
[]
string
{
""
},
APIVersions
:
[]
string
{
"v1"
},
Resources
:
[]
string
{
"pods"
},
},
}},
ClientConfig
:
v1beta1
.
WebhookClientConfig
{
Service
:
&
v1beta1
.
ServiceReference
{
Namespace
:
namespace
,
Name
:
serviceName
,
Path
:
strPtr
(
"/mutating-pods"
),
},
CABundle
:
context
.
signingCert
,
},
},
},
})
framework
.
ExpectNoError
(
err
,
"registering mutating webhook config %s with namespace %s"
,
mutatingWebhookConfigName
,
namespace
)
// The webhook configuration is honored in 1s.
time
.
Sleep
(
10
*
time
.
Second
)
}
func
testMutatingPodWebhook
(
f
*
framework
.
Framework
)
{
By
(
"create a pod that should be updated by the webhook"
)
client
:=
f
.
ClientSet
configMap
:=
toBeMutatedPod
(
f
)
mutatedPod
,
err
:=
client
.
CoreV1
()
.
Pods
(
f
.
Namespace
.
Name
)
.
Create
(
configMap
)
Expect
(
err
)
.
To
(
BeNil
())
if
len
(
mutatedPod
.
Spec
.
InitContainers
)
!=
1
{
framework
.
Failf
(
"expect pod to have 1 init container, got %#v"
,
mutatedPod
.
Spec
.
InitContainers
)
}
if
got
,
expected
:=
mutatedPod
.
Spec
.
InitContainers
[
0
]
.
Name
,
"webhook-added-init-container"
;
got
!=
expected
{
framework
.
Failf
(
"expect the init container name to be %q, got %q"
,
expected
,
got
)
}
if
got
,
expected
:=
mutatedPod
.
Spec
.
InitContainers
[
0
]
.
TerminationMessagePolicy
,
v1
.
TerminationMessageReadFile
;
got
!=
expected
{
framework
.
Failf
(
"expect the init terminationMessagePolicy to be default to %q, got %q"
,
expected
,
got
)
}
}
func
toBeMutatedPod
(
f
*
framework
.
Framework
)
*
v1
.
Pod
{
return
&
v1
.
Pod
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"webhook-to-be-mutated"
,
},
Spec
:
v1
.
PodSpec
{
Containers
:
[]
v1
.
Container
{
{
Name
:
"example"
,
Image
:
framework
.
GetPauseImageName
(
f
.
ClientSet
),
},
},
},
}
}
func
testWebhook
(
f
*
framework
.
Framework
)
{
By
(
"create a pod that should be denied by the webhook"
)
client
:=
f
.
ClientSet
...
...
test/images/webhook/Makefile
View file @
5029bb56
...
...
@@ -14,7 +14,7 @@
build
:
CGO_ENABLED
=
0
GOOS
=
linux go build
-a
-installsuffix
cgo
-o
webhook .
docker build
--no-cache
-t
gcr.io/kubernetes-e2e-test-images/k8s-sample-admission-webhook-amd64:1.
8v7
.
docker build
--no-cache
-t
gcr.io/kubernetes-e2e-test-images/k8s-sample-admission-webhook-amd64:1.
9v1
.
rm
-rf
webhook
push
:
gcloud docker
--
push gcr.io/kubernetes-e2e-test-images/k8s-sample-admission-webhook-amd64:1.
8v7
gcloud docker
--
push gcr.io/kubernetes-e2e-test-images/k8s-sample-admission-webhook-amd64:1.
9v1
test/images/webhook/main.go
View file @
5029bb56
...
...
@@ -40,6 +40,9 @@ const (
patch2
string
=
`[
{ "op": "add", "path": "/data/mutation-stage-2", "value": "yes" }
]`
addInitContainerPatch
string
=
`[
{"op":"add","path":"/spec/initContainers","value":[{"image":"webhook-added-image","name":"webhook-added-init-container","resources":{}}]}
]`
)
// Config contains the server (the webhook) cert and key.
...
...
@@ -108,6 +111,31 @@ func admitPods(ar v1beta1.AdmissionReview) *v1beta1.AdmissionResponse {
return
&
reviewResponse
}
func
mutatePods
(
ar
v1beta1
.
AdmissionReview
)
*
v1beta1
.
AdmissionResponse
{
glog
.
V
(
2
)
.
Info
(
"mutating pods"
)
podResource
:=
metav1
.
GroupVersionResource
{
Group
:
""
,
Version
:
"v1"
,
Resource
:
"pods"
}
if
ar
.
Request
.
Resource
!=
podResource
{
glog
.
Errorf
(
"expect resource to be %s"
,
podResource
)
return
nil
}
raw
:=
ar
.
Request
.
Object
.
Raw
pod
:=
corev1
.
Pod
{}
deserializer
:=
codecs
.
UniversalDeserializer
()
if
_
,
_
,
err
:=
deserializer
.
Decode
(
raw
,
nil
,
&
pod
);
err
!=
nil
{
glog
.
Error
(
err
)
return
toAdmissionResponse
(
err
)
}
reviewResponse
:=
v1beta1
.
AdmissionResponse
{}
reviewResponse
.
Allowed
=
true
if
pod
.
Name
==
"webhook-to-be-mutated"
{
reviewResponse
.
Patch
=
[]
byte
(
addInitContainerPatch
)
pt
:=
v1beta1
.
PatchTypeJSONPatch
reviewResponse
.
PatchType
=
&
pt
}
return
&
reviewResponse
}
// deny configmaps with specific key-value pair.
func
admitConfigMaps
(
ar
v1beta1
.
AdmissionReview
)
*
v1beta1
.
AdmissionResponse
{
glog
.
V
(
2
)
.
Info
(
"admitting configmaps"
)
...
...
@@ -271,6 +299,10 @@ func servePods(w http.ResponseWriter, r *http.Request) {
serve
(
w
,
r
,
admitPods
)
}
func
serveMutatePods
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
serve
(
w
,
r
,
mutatePods
)
}
func
serveConfigmaps
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
serve
(
w
,
r
,
admitConfigMaps
)
}
...
...
@@ -293,6 +325,7 @@ func main() {
flag
.
Parse
()
http
.
HandleFunc
(
"/pods"
,
servePods
)
http
.
HandleFunc
(
"/mutating-pods"
,
serveMutatePods
)
http
.
HandleFunc
(
"/configmaps"
,
serveConfigmaps
)
http
.
HandleFunc
(
"/mutating-configmaps"
,
serveMutateConfigmaps
)
http
.
HandleFunc
(
"/crd"
,
serveCRD
)
...
...
test/utils/image/manifest.go
View file @
5029bb56
...
...
@@ -48,7 +48,7 @@ func (i *ImageConfig) SetVersion(version string) {
}
var
(
AdmissionWebhook
=
ImageConfig
{
e2eRegistry
,
"k8s-sample-admission-webhook"
,
"1.
8v7
"
,
true
}
AdmissionWebhook
=
ImageConfig
{
e2eRegistry
,
"k8s-sample-admission-webhook"
,
"1.
9v1
"
,
true
}
APIServer
=
ImageConfig
{
e2eRegistry
,
"k8s-aggregator-sample-apiserver"
,
"1.7v2"
,
true
}
AppArmorLoader
=
ImageConfig
{
gcRegistry
,
"apparmor-loader"
,
"0.1"
,
false
}
BusyBox
=
ImageConfig
{
gcRegistry
,
"busybox"
,
"1.24"
,
false
}
...
...
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