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
55ecc454
Commit
55ecc454
authored
May 29, 2019
by
Joe Betz
Committed by
Chao Xu
May 30, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
split admissionregistration.v1beta1/Webhook into MutatingWebhook and ValidatingWebhook
parent
9356561c
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
696 additions
and
168 deletions
+696
-168
.golint_failures
hack/.golint_failures
+1
-0
fuzzer.go
pkg/apis/admissionregistration/fuzzer/fuzzer.go
+15
-1
types.go
pkg/apis/admissionregistration/types.go
+114
-4
defaults.go
pkg/apis/admissionregistration/v1beta1/defaults.go
+29
-1
validation.go
pkg/apis/admissionregistration/validation/validation.go
+62
-7
validation_test.go
pkg/apis/admissionregistration/validation/validation_test.go
+0
-0
types.go
...ing/src/k8s.io/api/admissionregistration/v1beta1/types.go
+122
-4
BUILD
staging/src/k8s.io/apiserver/pkg/admission/BUILD
+1
-12
BUILD
...ng/src/k8s.io/apiserver/pkg/admission/configuration/BUILD
+1
-0
mutating_webhook_manager.go
...r/pkg/admission/configuration/mutating_webhook_manager.go
+10
-7
mutating_webhook_manager_test.go
.../admission/configuration/mutating_webhook_manager_test.go
+10
-3
validating_webhook_manager.go
...pkg/admission/configuration/validating_webhook_manager.go
+10
-9
validating_webhook_manager_test.go
...dmission/configuration/validating_webhook_manager_test.go
+10
-3
BUILD
...g/src/k8s.io/apiserver/pkg/admission/plugin/webhook/BUILD
+41
-0
accessors.go
...8s.io/apiserver/pkg/admission/plugin/webhook/accessors.go
+139
-0
BUILD
...s.io/apiserver/pkg/admission/plugin/webhook/generic/BUILD
+2
-0
interfaces.go
...server/pkg/admission/plugin/webhook/generic/interfaces.go
+3
-4
webhook.go
...apiserver/pkg/admission/plugin/webhook/generic/webhook.go
+14
-13
webhook_test.go
...rver/pkg/admission/plugin/webhook/generic/webhook_test.go
+16
-15
dispatcher.go
...erver/pkg/admission/plugin/webhook/mutating/dispatcher.go
+19
-16
plugin_test.go
...rver/pkg/admission/plugin/webhook/mutating/plugin_test.go
+3
-3
BUILD
...io/apiserver/pkg/admission/plugin/webhook/namespace/BUILD
+2
-1
matcher.go
...iserver/pkg/admission/plugin/webhook/namespace/matcher.go
+3
-3
matcher_test.go
...er/pkg/admission/plugin/webhook/namespace/matcher_test.go
+3
-2
testcase.go
...piserver/pkg/admission/plugin/webhook/testing/testcase.go
+0
-0
BUILD
.../k8s.io/apiserver/pkg/admission/plugin/webhook/util/BUILD
+1
-1
client_config.go
...server/pkg/admission/plugin/webhook/util/client_config.go
+20
-19
dispatcher.go
...ver/pkg/admission/plugin/webhook/validating/dispatcher.go
+19
-18
plugin_test.go
...er/pkg/admission/plugin/webhook/validating/plugin_test.go
+2
-2
webhook.go
test/e2e/apimachinery/webhook.go
+15
-15
admission_test.go
.../integration/apiserver/admissionwebhook/admission_test.go
+5
-2
broken_webhook_test.go
...gration/apiserver/admissionwebhook/broken_webhook_test.go
+1
-1
webhook_test.go
test/integration/examples/webhook_test.go
+2
-2
modules.txt
vendor/modules.txt
+1
-0
No files found.
hack/.golint_failures
View file @
55ecc454
...
@@ -423,6 +423,7 @@ staging/src/k8s.io/apimachinery/pkg/watch
...
@@ -423,6 +423,7 @@ staging/src/k8s.io/apimachinery/pkg/watch
staging/src/k8s.io/apiserver/pkg/admission
staging/src/k8s.io/apiserver/pkg/admission
staging/src/k8s.io/apiserver/pkg/admission/configuration
staging/src/k8s.io/apiserver/pkg/admission/configuration
staging/src/k8s.io/apiserver/pkg/admission/initializer
staging/src/k8s.io/apiserver/pkg/admission/initializer
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts
...
...
pkg/apis/admissionregistration/fuzzer/fuzzer.go
View file @
55ecc454
...
@@ -33,7 +33,21 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
...
@@ -33,7 +33,21 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
obj
.
Scope
=
&
s
obj
.
Scope
=
&
s
}
}
},
},
func
(
obj
*
admissionregistration
.
Webhook
,
c
fuzz
.
Continue
)
{
func
(
obj
*
admissionregistration
.
ValidatingWebhook
,
c
fuzz
.
Continue
)
{
c
.
FuzzNoCustom
(
obj
)
// fuzz self without calling this function again
p
:=
admissionregistration
.
FailurePolicyType
(
"Fail"
)
obj
.
FailurePolicy
=
&
p
m
:=
admissionregistration
.
MatchPolicyType
(
"Exact"
)
obj
.
MatchPolicy
=
&
m
s
:=
admissionregistration
.
SideEffectClassUnknown
obj
.
SideEffects
=
&
s
if
obj
.
TimeoutSeconds
==
nil
{
i
:=
int32
(
30
)
obj
.
TimeoutSeconds
=
&
i
}
obj
.
AdmissionReviewVersions
=
[]
string
{
"v1beta1"
}
},
func
(
obj
*
admissionregistration
.
MutatingWebhook
,
c
fuzz
.
Continue
)
{
c
.
FuzzNoCustom
(
obj
)
// fuzz self without calling this function again
c
.
FuzzNoCustom
(
obj
)
// fuzz self without calling this function again
p
:=
admissionregistration
.
FailurePolicyType
(
"Fail"
)
p
:=
admissionregistration
.
FailurePolicyType
(
"Fail"
)
obj
.
FailurePolicy
=
&
p
obj
.
FailurePolicy
=
&
p
...
...
pkg/apis/admissionregistration/types.go
View file @
55ecc454
...
@@ -123,7 +123,7 @@ type ValidatingWebhookConfiguration struct {
...
@@ -123,7 +123,7 @@ type ValidatingWebhookConfiguration struct {
metav1
.
ObjectMeta
metav1
.
ObjectMeta
// Webhooks is a list of webhooks and the affected resources and operations.
// Webhooks is a list of webhooks and the affected resources and operations.
// +optional
// +optional
Webhooks
[]
Webhook
Webhooks
[]
Validating
Webhook
}
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
...
@@ -149,7 +149,7 @@ type MutatingWebhookConfiguration struct {
...
@@ -149,7 +149,7 @@ type MutatingWebhookConfiguration struct {
metav1
.
ObjectMeta
metav1
.
ObjectMeta
// Webhooks is a list of webhooks and the affected resources and operations.
// Webhooks is a list of webhooks and the affected resources and operations.
// +optional
// +optional
Webhooks
[]
Webhook
Webhooks
[]
Mutating
Webhook
}
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
...
@@ -165,8 +165,118 @@ type MutatingWebhookConfigurationList struct {
...
@@ -165,8 +165,118 @@ type MutatingWebhookConfigurationList struct {
Items
[]
MutatingWebhookConfiguration
Items
[]
MutatingWebhookConfiguration
}
}
// Webhook describes an admission webhook and the resources and operations it applies to.
// ValidatingWebhook describes an admission webhook and the resources and operations it applies to.
type
Webhook
struct
{
type
ValidatingWebhook
struct
{
// The name of the admission webhook.
// Name should be fully qualified, e.g., imagepolicy.kubernetes.io, where
// "imagepolicy" is the name of the webhook, and kubernetes.io is the name
// of the organization.
// Required.
Name
string
// ClientConfig defines how to communicate with the hook.
// Required
ClientConfig
WebhookClientConfig
// Rules describes what operations on what resources/subresources the webhook cares about.
// The webhook cares about an operation if it matches _any_ Rule.
Rules
[]
RuleWithOperations
// FailurePolicy defines how unrecognized errors from the admission endpoint are handled -
// allowed values are Ignore or Fail. Defaults to Ignore.
// +optional
FailurePolicy
*
FailurePolicyType
// matchPolicy defines how the "rules" list is used to match incoming requests.
// Allowed values are "Exact" or "Equivalent".
//
// - Exact: match a request only if it exactly matches a specified rule.
// For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1,
// but "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`,
// a request to apps/v1beta1 or extensions/v1beta1 would not be sent to the webhook.
//
// - Equivalent: match a request if modifies a resource listed in rules, even via another API group or version.
// For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1,
// and "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`,
// a request to apps/v1beta1 or extensions/v1beta1 would be converted to apps/v1 and sent to the webhook.
//
// +optional
MatchPolicy
*
MatchPolicyType
// NamespaceSelector decides whether to run the webhook on an object based
// on whether the namespace for that object matches the selector. If the
// object itself is a namespace, the matching is performed on
// object.metadata.labels. If the object is another cluster scoped resource,
// it never skips the webhook.
//
// For example, to run the webhook on any objects whose namespace is not
// associated with "runlevel" of "0" or "1"; you will set the selector as
// follows:
// "namespaceSelector": {
// "matchExpressions": [
// {
// "key": "runlevel",
// "operator": "NotIn",
// "values": [
// "0",
// "1"
// ]
// }
// ]
// }
//
// If instead you want to only run the webhook on any objects whose
// namespace is associated with the "environment" of "prod" or "staging";
// you will set the selector as follows:
// "namespaceSelector": {
// "matchExpressions": [
// {
// "key": "environment",
// "operator": "In",
// "values": [
// "prod",
// "staging"
// ]
// }
// ]
// }
//
// See
// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
// for more examples of label selectors.
//
// Default to the empty LabelSelector, which matches everything.
// +optional
NamespaceSelector
*
metav1
.
LabelSelector
// SideEffects states whether this webhookk has side effects.
// Acceptable values are: Unknown, None, Some, NoneOnDryRun
// Webhooks with side effects MUST implement a reconciliation system, since a request may be
// rejected by a future step in the admission change and the side effects therefore need to be undone.
// Requests with the dryRun attribute will be auto-rejected if they match a webhook with
// sideEffects == Unknown or Some. Defaults to Unknown.
// +optional
SideEffects
*
SideEffectClass
// TimeoutSeconds specifies the timeout for this webhook. After the timeout passes,
// the webhook call will be ignored or the API call will fail based on the
// failure policy.
// The timeout value must be between 1 and 30 seconds.
// +optional
TimeoutSeconds
*
int32
// AdmissionReviewVersions is an ordered list of preferred `AdmissionReview`
// versions the Webhook expects. API server will try to use first version in
// the list which it supports. If none of the versions specified in this list
// supported by API server, validation will fail for this object.
// If the webhook configuration has already been persisted with a version apiserver
// does not understand, calls to the webhook will fail and be subject to the failure policy.
// +optional
AdmissionReviewVersions
[]
string
}
// MutatingWebhook describes an admission webhook and the resources and operations it applies to.
type
MutatingWebhook
struct
{
// The name of the admission webhook.
// The name of the admission webhook.
// Name should be fully qualified, e.g., imagepolicy.kubernetes.io, where
// Name should be fully qualified, e.g., imagepolicy.kubernetes.io, where
// "imagepolicy" is the name of the webhook, and kubernetes.io is the name
// "imagepolicy" is the name of the webhook, and kubernetes.io is the name
...
...
pkg/apis/admissionregistration/v1beta1/defaults.go
View file @
55ecc454
...
@@ -27,7 +27,35 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error {
...
@@ -27,7 +27,35 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error {
return
RegisterDefaults
(
scheme
)
return
RegisterDefaults
(
scheme
)
}
}
func
SetDefaults_Webhook
(
obj
*
admissionregistrationv1beta1
.
Webhook
)
{
func
SetDefaults_ValidatingWebhook
(
obj
*
admissionregistrationv1beta1
.
ValidatingWebhook
)
{
if
obj
.
FailurePolicy
==
nil
{
policy
:=
admissionregistrationv1beta1
.
Ignore
obj
.
FailurePolicy
=
&
policy
}
if
obj
.
MatchPolicy
==
nil
{
policy
:=
admissionregistrationv1beta1
.
Exact
obj
.
MatchPolicy
=
&
policy
}
if
obj
.
NamespaceSelector
==
nil
{
selector
:=
metav1
.
LabelSelector
{}
obj
.
NamespaceSelector
=
&
selector
}
if
obj
.
SideEffects
==
nil
{
// TODO: revisit/remove this default and possibly make the field required when promoting to v1
unknown
:=
admissionregistrationv1beta1
.
SideEffectClassUnknown
obj
.
SideEffects
=
&
unknown
}
if
obj
.
TimeoutSeconds
==
nil
{
obj
.
TimeoutSeconds
=
new
(
int32
)
*
obj
.
TimeoutSeconds
=
30
}
if
len
(
obj
.
AdmissionReviewVersions
)
==
0
{
obj
.
AdmissionReviewVersions
=
[]
string
{
admissionregistrationv1beta1
.
SchemeGroupVersion
.
Version
}
}
}
func
SetDefaults_MutatingWebhook
(
obj
*
admissionregistrationv1beta1
.
MutatingWebhook
)
{
if
obj
.
FailurePolicy
==
nil
{
if
obj
.
FailurePolicy
==
nil
{
policy
:=
admissionregistrationv1beta1
.
Ignore
policy
:=
admissionregistrationv1beta1
.
Ignore
obj
.
FailurePolicy
=
&
policy
obj
.
FailurePolicy
=
&
policy
...
...
pkg/apis/admissionregistration/validation/validation.go
View file @
55ecc454
...
@@ -201,7 +201,7 @@ func ValidateValidatingWebhookConfiguration(e *admissionregistration.ValidatingW
...
@@ -201,7 +201,7 @@ func ValidateValidatingWebhookConfiguration(e *admissionregistration.ValidatingW
func
validateValidatingWebhookConfiguration
(
e
*
admissionregistration
.
ValidatingWebhookConfiguration
,
requireRecognizedVersion
bool
)
field
.
ErrorList
{
func
validateValidatingWebhookConfiguration
(
e
*
admissionregistration
.
ValidatingWebhookConfiguration
,
requireRecognizedVersion
bool
)
field
.
ErrorList
{
allErrors
:=
genericvalidation
.
ValidateObjectMeta
(
&
e
.
ObjectMeta
,
false
,
genericvalidation
.
NameIsDNSSubdomain
,
field
.
NewPath
(
"metadata"
))
allErrors
:=
genericvalidation
.
ValidateObjectMeta
(
&
e
.
ObjectMeta
,
false
,
genericvalidation
.
NameIsDNSSubdomain
,
field
.
NewPath
(
"metadata"
))
for
i
,
hook
:=
range
e
.
Webhooks
{
for
i
,
hook
:=
range
e
.
Webhooks
{
allErrors
=
append
(
allErrors
,
validateWebhook
(
&
hook
,
field
.
NewPath
(
"webhooks"
)
.
Index
(
i
))
...
)
allErrors
=
append
(
allErrors
,
validate
Validating
Webhook
(
&
hook
,
field
.
NewPath
(
"webhooks"
)
.
Index
(
i
))
...
)
allErrors
=
append
(
allErrors
,
validateAdmissionReviewVersions
(
hook
.
AdmissionReviewVersions
,
requireRecognizedVersion
,
field
.
NewPath
(
"webhooks"
)
.
Index
(
i
)
.
Child
(
"admissionReviewVersions"
))
...
)
allErrors
=
append
(
allErrors
,
validateAdmissionReviewVersions
(
hook
.
AdmissionReviewVersions
,
requireRecognizedVersion
,
field
.
NewPath
(
"webhooks"
)
.
Index
(
i
)
.
Child
(
"admissionReviewVersions"
))
...
)
}
}
return
allErrors
return
allErrors
...
@@ -214,13 +214,50 @@ func ValidateMutatingWebhookConfiguration(e *admissionregistration.MutatingWebho
...
@@ -214,13 +214,50 @@ func ValidateMutatingWebhookConfiguration(e *admissionregistration.MutatingWebho
func
validateMutatingWebhookConfiguration
(
e
*
admissionregistration
.
MutatingWebhookConfiguration
,
requireRecognizedVersion
bool
)
field
.
ErrorList
{
func
validateMutatingWebhookConfiguration
(
e
*
admissionregistration
.
MutatingWebhookConfiguration
,
requireRecognizedVersion
bool
)
field
.
ErrorList
{
allErrors
:=
genericvalidation
.
ValidateObjectMeta
(
&
e
.
ObjectMeta
,
false
,
genericvalidation
.
NameIsDNSSubdomain
,
field
.
NewPath
(
"metadata"
))
allErrors
:=
genericvalidation
.
ValidateObjectMeta
(
&
e
.
ObjectMeta
,
false
,
genericvalidation
.
NameIsDNSSubdomain
,
field
.
NewPath
(
"metadata"
))
for
i
,
hook
:=
range
e
.
Webhooks
{
for
i
,
hook
:=
range
e
.
Webhooks
{
allErrors
=
append
(
allErrors
,
validateWebhook
(
&
hook
,
field
.
NewPath
(
"webhooks"
)
.
Index
(
i
))
...
)
allErrors
=
append
(
allErrors
,
validate
Mutating
Webhook
(
&
hook
,
field
.
NewPath
(
"webhooks"
)
.
Index
(
i
))
...
)
allErrors
=
append
(
allErrors
,
validateAdmissionReviewVersions
(
hook
.
AdmissionReviewVersions
,
requireRecognizedVersion
,
field
.
NewPath
(
"webhooks"
)
.
Index
(
i
)
.
Child
(
"admissionReviewVersions"
))
...
)
allErrors
=
append
(
allErrors
,
validateAdmissionReviewVersions
(
hook
.
AdmissionReviewVersions
,
requireRecognizedVersion
,
field
.
NewPath
(
"webhooks"
)
.
Index
(
i
)
.
Child
(
"admissionReviewVersions"
))
...
)
}
}
return
allErrors
return
allErrors
}
}
func
validateWebhook
(
hook
*
admissionregistration
.
Webhook
,
fldPath
*
field
.
Path
)
field
.
ErrorList
{
func
validateValidatingWebhook
(
hook
*
admissionregistration
.
ValidatingWebhook
,
fldPath
*
field
.
Path
)
field
.
ErrorList
{
var
allErrors
field
.
ErrorList
// hook.Name must be fully qualified
allErrors
=
append
(
allErrors
,
utilvalidation
.
IsFullyQualifiedName
(
fldPath
.
Child
(
"name"
),
hook
.
Name
)
...
)
for
i
,
rule
:=
range
hook
.
Rules
{
allErrors
=
append
(
allErrors
,
validateRuleWithOperations
(
&
rule
,
fldPath
.
Child
(
"rules"
)
.
Index
(
i
))
...
)
}
if
hook
.
FailurePolicy
!=
nil
&&
!
supportedFailurePolicies
.
Has
(
string
(
*
hook
.
FailurePolicy
))
{
allErrors
=
append
(
allErrors
,
field
.
NotSupported
(
fldPath
.
Child
(
"failurePolicy"
),
*
hook
.
FailurePolicy
,
supportedFailurePolicies
.
List
()))
}
if
hook
.
MatchPolicy
!=
nil
&&
!
supportedMatchPolicies
.
Has
(
string
(
*
hook
.
MatchPolicy
))
{
allErrors
=
append
(
allErrors
,
field
.
NotSupported
(
fldPath
.
Child
(
"matchPolicy"
),
*
hook
.
MatchPolicy
,
supportedMatchPolicies
.
List
()))
}
if
hook
.
SideEffects
!=
nil
&&
!
supportedSideEffectClasses
.
Has
(
string
(
*
hook
.
SideEffects
))
{
allErrors
=
append
(
allErrors
,
field
.
NotSupported
(
fldPath
.
Child
(
"sideEffects"
),
*
hook
.
SideEffects
,
supportedSideEffectClasses
.
List
()))
}
if
hook
.
TimeoutSeconds
!=
nil
&&
(
*
hook
.
TimeoutSeconds
>
30
||
*
hook
.
TimeoutSeconds
<
1
)
{
allErrors
=
append
(
allErrors
,
field
.
Invalid
(
fldPath
.
Child
(
"timeoutSeconds"
),
*
hook
.
TimeoutSeconds
,
"the timeout value must be between 1 and 30 seconds"
))
}
if
hook
.
NamespaceSelector
!=
nil
{
allErrors
=
append
(
allErrors
,
metav1validation
.
ValidateLabelSelector
(
hook
.
NamespaceSelector
,
fldPath
.
Child
(
"namespaceSelector"
))
...
)
}
cc
:=
hook
.
ClientConfig
switch
{
case
(
cc
.
URL
==
nil
)
==
(
cc
.
Service
==
nil
)
:
allErrors
=
append
(
allErrors
,
field
.
Required
(
fldPath
.
Child
(
"clientConfig"
),
"exactly one of url or service is required"
))
case
cc
.
URL
!=
nil
:
allErrors
=
append
(
allErrors
,
webhook
.
ValidateWebhookURL
(
fldPath
.
Child
(
"clientConfig"
)
.
Child
(
"url"
),
*
cc
.
URL
,
true
)
...
)
case
cc
.
Service
!=
nil
:
allErrors
=
append
(
allErrors
,
webhook
.
ValidateWebhookService
(
fldPath
.
Child
(
"clientConfig"
)
.
Child
(
"service"
),
cc
.
Service
.
Name
,
cc
.
Service
.
Namespace
,
cc
.
Service
.
Path
,
cc
.
Service
.
Port
)
...
)
}
return
allErrors
}
func
validateMutatingWebhook
(
hook
*
admissionregistration
.
MutatingWebhook
,
fldPath
*
field
.
Path
)
field
.
ErrorList
{
var
allErrors
field
.
ErrorList
var
allErrors
field
.
ErrorList
// hook.Name must be fully qualified
// hook.Name must be fully qualified
allErrors
=
append
(
allErrors
,
utilvalidation
.
IsFullyQualifiedName
(
fldPath
.
Child
(
"name"
),
hook
.
Name
)
...
)
allErrors
=
append
(
allErrors
,
utilvalidation
.
IsFullyQualifiedName
(
fldPath
.
Child
(
"name"
),
hook
.
Name
)
...
)
...
@@ -309,9 +346,27 @@ func validateRuleWithOperations(ruleWithOperations *admissionregistration.RuleWi
...
@@ -309,9 +346,27 @@ func validateRuleWithOperations(ruleWithOperations *admissionregistration.RuleWi
return
allErrors
return
allErrors
}
}
// hasAcceptedAdmissionReviewVersions returns true if all webhooks have at least one
// mutatingHasAcceptedAdmissionReviewVersions returns true if all webhooks have at least one
// admission review version this apiserver accepts.
func
mutatingHasAcceptedAdmissionReviewVersions
(
webhooks
[]
admissionregistration
.
MutatingWebhook
)
bool
{
for
_
,
hook
:=
range
webhooks
{
hasRecognizedVersion
:=
false
for
_
,
version
:=
range
hook
.
AdmissionReviewVersions
{
if
isAcceptedAdmissionReviewVersion
(
version
)
{
hasRecognizedVersion
=
true
break
}
}
if
!
hasRecognizedVersion
&&
len
(
hook
.
AdmissionReviewVersions
)
>
0
{
return
false
}
}
return
true
}
// validatingHasAcceptedAdmissionReviewVersions returns true if all webhooks have at least one
// admission review version this apiserver accepts.
// admission review version this apiserver accepts.
func
hasAcceptedAdmissionReviewVersions
(
webhooks
[]
admissionregistration
.
Webhook
)
bool
{
func
validatingHasAcceptedAdmissionReviewVersions
(
webhooks
[]
admissionregistration
.
Validating
Webhook
)
bool
{
for
_
,
hook
:=
range
webhooks
{
for
_
,
hook
:=
range
webhooks
{
hasRecognizedVersion
:=
false
hasRecognizedVersion
:=
false
for
_
,
version
:=
range
hook
.
AdmissionReviewVersions
{
for
_
,
version
:=
range
hook
.
AdmissionReviewVersions
{
...
@@ -328,9 +383,9 @@ func hasAcceptedAdmissionReviewVersions(webhooks []admissionregistration.Webhook
...
@@ -328,9 +383,9 @@ func hasAcceptedAdmissionReviewVersions(webhooks []admissionregistration.Webhook
}
}
func
ValidateValidatingWebhookConfigurationUpdate
(
newC
,
oldC
*
admissionregistration
.
ValidatingWebhookConfiguration
)
field
.
ErrorList
{
func
ValidateValidatingWebhookConfigurationUpdate
(
newC
,
oldC
*
admissionregistration
.
ValidatingWebhookConfiguration
)
field
.
ErrorList
{
return
validateValidatingWebhookConfiguration
(
newC
,
h
asAcceptedAdmissionReviewVersions
(
oldC
.
Webhooks
))
return
validateValidatingWebhookConfiguration
(
newC
,
validatingH
asAcceptedAdmissionReviewVersions
(
oldC
.
Webhooks
))
}
}
func
ValidateMutatingWebhookConfigurationUpdate
(
newC
,
oldC
*
admissionregistration
.
MutatingWebhookConfiguration
)
field
.
ErrorList
{
func
ValidateMutatingWebhookConfigurationUpdate
(
newC
,
oldC
*
admissionregistration
.
MutatingWebhookConfiguration
)
field
.
ErrorList
{
return
validateMutatingWebhookConfiguration
(
newC
,
h
asAcceptedAdmissionReviewVersions
(
oldC
.
Webhooks
))
return
validateMutatingWebhookConfiguration
(
newC
,
mutatingH
asAcceptedAdmissionReviewVersions
(
oldC
.
Webhooks
))
}
}
pkg/apis/admissionregistration/validation/validation_test.go
View file @
55ecc454
This diff is collapsed.
Click to expand it.
staging/src/k8s.io/api/admissionregistration/v1beta1/types.go
View file @
55ecc454
...
@@ -124,7 +124,7 @@ type ValidatingWebhookConfiguration struct {
...
@@ -124,7 +124,7 @@ type ValidatingWebhookConfiguration struct {
// +optional
// +optional
// +patchMergeKey=name
// +patchMergeKey=name
// +patchStrategy=merge
// +patchStrategy=merge
Webhooks
[]
Webhook
`json:"webhooks,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,2,rep,name=Webhooks"`
Webhooks
[]
Validating
Webhook
`json:"webhooks,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,2,rep,name=Webhooks"`
}
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
...
@@ -154,7 +154,7 @@ type MutatingWebhookConfiguration struct {
...
@@ -154,7 +154,7 @@ type MutatingWebhookConfiguration struct {
// +optional
// +optional
// +patchMergeKey=name
// +patchMergeKey=name
// +patchStrategy=merge
// +patchStrategy=merge
Webhooks
[]
Webhook
`json:"webhooks,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,2,rep,name=Webhooks"`
Webhooks
[]
Mutating
Webhook
`json:"webhooks,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,2,rep,name=Webhooks"`
}
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
...
@@ -170,8 +170,126 @@ type MutatingWebhookConfigurationList struct {
...
@@ -170,8 +170,126 @@ type MutatingWebhookConfigurationList struct {
Items
[]
MutatingWebhookConfiguration
`json:"items" protobuf:"bytes,2,rep,name=items"`
Items
[]
MutatingWebhookConfiguration
`json:"items" protobuf:"bytes,2,rep,name=items"`
}
}
// Webhook describes an admission webhook and the resources and operations it applies to.
// ValidatingWebhook describes an admission webhook and the resources and operations it applies to.
type
Webhook
struct
{
type
ValidatingWebhook
struct
{
// The name of the admission webhook.
// Name should be fully qualified, e.g., imagepolicy.kubernetes.io, where
// "imagepolicy" is the name of the webhook, and kubernetes.io is the name
// of the organization.
// Required.
Name
string
`json:"name" protobuf:"bytes,1,opt,name=name"`
// ClientConfig defines how to communicate with the hook.
// Required
ClientConfig
WebhookClientConfig
`json:"clientConfig" protobuf:"bytes,2,opt,name=clientConfig"`
// Rules describes what operations on what resources/subresources the webhook cares about.
// The webhook cares about an operation if it matches _any_ Rule.
// However, in order to prevent ValidatingAdmissionWebhooks and MutatingAdmissionWebhooks
// from putting the cluster in a state which cannot be recovered from without completely
// disabling the plugin, ValidatingAdmissionWebhooks and MutatingAdmissionWebhooks are never called
// on admission requests for ValidatingWebhookConfiguration and MutatingWebhookConfiguration objects.
Rules
[]
RuleWithOperations
`json:"rules,omitempty" protobuf:"bytes,3,rep,name=rules"`
// FailurePolicy defines how unrecognized errors from the admission endpoint are handled -
// allowed values are Ignore or Fail. Defaults to Ignore.
// +optional
FailurePolicy
*
FailurePolicyType
`json:"failurePolicy,omitempty" protobuf:"bytes,4,opt,name=failurePolicy,casttype=FailurePolicyType"`
// matchPolicy defines how the "rules" list is used to match incoming requests.
// Allowed values are "Exact" or "Equivalent".
//
// - Exact: match a request only if it exactly matches a specified rule.
// For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1,
// but "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`,
// a request to apps/v1beta1 or extensions/v1beta1 would not be sent to the webhook.
//
// - Equivalent: match a request if modifies a resource listed in rules, even via another API group or version.
// For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1,
// and "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`,
// a request to apps/v1beta1 or extensions/v1beta1 would be converted to apps/v1 and sent to the webhook.
//
// Defaults to "Exact"
// +optional
MatchPolicy
*
MatchPolicyType
`json:"matchPolicy,omitempty" protobuf:"bytes,9,opt,name=matchPolicy,casttype=MatchPolicyType"`
// NamespaceSelector decides whether to run the webhook on an object based
// on whether the namespace for that object matches the selector. If the
// object itself is a namespace, the matching is performed on
// object.metadata.labels. If the object is another cluster scoped resource,
// it never skips the webhook.
//
// For example, to run the webhook on any objects whose namespace is not
// associated with "runlevel" of "0" or "1"; you will set the selector as
// follows:
// "namespaceSelector": {
// "matchExpressions": [
// {
// "key": "runlevel",
// "operator": "NotIn",
// "values": [
// "0",
// "1"
// ]
// }
// ]
// }
//
// If instead you want to only run the webhook on any objects whose
// namespace is associated with the "environment" of "prod" or "staging";
// you will set the selector as follows:
// "namespaceSelector": {
// "matchExpressions": [
// {
// "key": "environment",
// "operator": "In",
// "values": [
// "prod",
// "staging"
// ]
// }
// ]
// }
//
// See
// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
// for more examples of label selectors.
//
// Default to the empty LabelSelector, which matches everything.
// +optional
NamespaceSelector
*
metav1
.
LabelSelector
`json:"namespaceSelector,omitempty" protobuf:"bytes,5,opt,name=namespaceSelector"`
// SideEffects states whether this webhookk has side effects.
// Acceptable values are: Unknown, None, Some, NoneOnDryRun
// Webhooks with side effects MUST implement a reconciliation system, since a request may be
// rejected by a future step in the admission change and the side effects therefore need to be undone.
// Requests with the dryRun attribute will be auto-rejected if they match a webhook with
// sideEffects == Unknown or Some. Defaults to Unknown.
// +optional
SideEffects
*
SideEffectClass
`json:"sideEffects,omitempty" protobuf:"bytes,6,opt,name=sideEffects,casttype=SideEffectClass"`
// TimeoutSeconds specifies the timeout for this webhook. After the timeout passes,
// the webhook call will be ignored or the API call will fail based on the
// failure policy.
// The timeout value must be between 1 and 30 seconds.
// Default to 30 seconds.
// +optional
TimeoutSeconds
*
int32
`json:"timeoutSeconds,omitempty" protobuf:"varint,7,opt,name=timeoutSeconds"`
// AdmissionReviewVersions is an ordered list of preferred `AdmissionReview`
// versions the Webhook expects. API server will try to use first version in
// the list which it supports. If none of the versions specified in this list
// supported by API server, validation will fail for this object.
// If a persisted webhook configuration specifies allowed versions and does not
// include any versions known to the API Server, calls to the webhook will fail
// and be subject to the failure policy.
// Default to `['v1beta1']`.
// +optional
AdmissionReviewVersions
[]
string
`json:"admissionReviewVersions,omitempty" protobuf:"bytes,8,rep,name=admissionReviewVersions"`
}
// MutatingWebhook describes an admission webhook and the resources and operations it applies to.
type
MutatingWebhook
struct
{
// The name of the admission webhook.
// The name of the admission webhook.
// Name should be fully qualified, e.g., imagepolicy.kubernetes.io, where
// Name should be fully qualified, e.g., imagepolicy.kubernetes.io, where
// "imagepolicy" is the name of the webhook, and kubernetes.io is the name
// "imagepolicy" is the name of the webhook, and kubernetes.io is the name
...
...
staging/src/k8s.io/apiserver/pkg/admission/BUILD
View file @
55ecc454
...
@@ -80,18 +80,7 @@ filegroup(
...
@@ -80,18 +80,7 @@ filegroup(
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/metrics:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/metrics:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/errors:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/initializer:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/util:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/testing:all-srcs",
],
],
tags = ["automanaged"],
tags = ["automanaged"],
...
...
staging/src/k8s.io/apiserver/pkg/admission/configuration/BUILD
View file @
55ecc454
...
@@ -39,6 +39,7 @@ go_library(
...
@@ -39,6 +39,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1:go_default_library",
"//staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1:go_default_library",
...
...
staging/src/k8s.io/apiserver/pkg/admission/configuration/mutating_webhook_manager.go
View file @
55ecc454
...
@@ -24,6 +24,7 @@ import (
...
@@ -24,6 +24,7 @@ import (
"k8s.io/api/admissionregistration/v1beta1"
"k8s.io/api/admissionregistration/v1beta1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/labels"
utilruntime
"k8s.io/apimachinery/pkg/util/runtime"
utilruntime
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/admission/plugin/webhook"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/client-go/informers"
"k8s.io/client-go/informers"
admissionregistrationlisters
"k8s.io/client-go/listers/admissionregistration/v1beta1"
admissionregistrationlisters
"k8s.io/client-go/listers/admissionregistration/v1beta1"
...
@@ -48,7 +49,7 @@ func NewMutatingWebhookConfigurationManager(f informers.SharedInformerFactory) g
...
@@ -48,7 +49,7 @@ func NewMutatingWebhookConfigurationManager(f informers.SharedInformerFactory) g
}
}
// Start with an empty list
// Start with an empty list
manager
.
configuration
.
Store
(
&
v1beta1
.
MutatingWebhookConfiguration
{})
manager
.
configuration
.
Store
(
[]
webhook
.
WebhookAccessor
{})
// On any change, rebuild the config
// On any change, rebuild the config
informer
.
Informer
()
.
AddEventHandler
(
cache
.
ResourceEventHandlerFuncs
{
informer
.
Informer
()
.
AddEventHandler
(
cache
.
ResourceEventHandlerFuncs
{
...
@@ -61,8 +62,8 @@ func NewMutatingWebhookConfigurationManager(f informers.SharedInformerFactory) g
...
@@ -61,8 +62,8 @@ func NewMutatingWebhookConfigurationManager(f informers.SharedInformerFactory) g
}
}
// Webhooks returns the merged MutatingWebhookConfiguration.
// Webhooks returns the merged MutatingWebhookConfiguration.
func
(
m
*
mutatingWebhookConfigurationManager
)
Webhooks
()
[]
v1beta1
.
Webhook
{
func
(
m
*
mutatingWebhookConfigurationManager
)
Webhooks
()
[]
webhook
.
WebhookAccessor
{
return
m
.
configuration
.
Load
()
.
(
*
v1beta1
.
MutatingWebhookConfiguration
)
.
Webhooks
return
m
.
configuration
.
Load
()
.
(
[]
webhook
.
WebhookAccessor
)
}
}
func
(
m
*
mutatingWebhookConfigurationManager
)
HasSynced
()
bool
{
func
(
m
*
mutatingWebhookConfigurationManager
)
HasSynced
()
bool
{
...
@@ -78,16 +79,18 @@ func (m *mutatingWebhookConfigurationManager) updateConfiguration() {
...
@@ -78,16 +79,18 @@ func (m *mutatingWebhookConfigurationManager) updateConfiguration() {
m
.
configuration
.
Store
(
mergeMutatingWebhookConfigurations
(
configurations
))
m
.
configuration
.
Store
(
mergeMutatingWebhookConfigurations
(
configurations
))
}
}
func
mergeMutatingWebhookConfigurations
(
configurations
[]
*
v1beta1
.
MutatingWebhookConfiguration
)
*
v1beta1
.
MutatingWebhookConfiguration
{
func
mergeMutatingWebhookConfigurations
(
configurations
[]
*
v1beta1
.
MutatingWebhookConfiguration
)
[]
webhook
.
WebhookAccessor
{
var
ret
v1beta1
.
MutatingWebhookConfiguration
// The internal order of webhooks for each configuration is provided by the user
// The internal order of webhooks for each configuration is provided by the user
// but configurations themselves can be in any order. As we are going to run these
// but configurations themselves can be in any order. As we are going to run these
// webhooks in serial, they are sorted here to have a deterministic order.
// webhooks in serial, they are sorted here to have a deterministic order.
sort
.
SliceStable
(
configurations
,
MutatingWebhookConfigurationSorter
(
configurations
)
.
ByName
)
sort
.
SliceStable
(
configurations
,
MutatingWebhookConfigurationSorter
(
configurations
)
.
ByName
)
accessors
:=
[]
webhook
.
WebhookAccessor
{}
for
_
,
c
:=
range
configurations
{
for
_
,
c
:=
range
configurations
{
ret
.
Webhooks
=
append
(
ret
.
Webhooks
,
c
.
Webhooks
...
)
for
i
:=
range
c
.
Webhooks
{
accessors
=
append
(
accessors
,
webhook
.
NewMutatingWebhookAccessor
(
&
c
.
Webhooks
[
i
]))
}
}
}
return
&
ret
return
accessors
}
}
type
MutatingWebhookConfigurationSorter
[]
*
v1beta1
.
MutatingWebhookConfiguration
type
MutatingWebhookConfigurationSorter
[]
*
v1beta1
.
MutatingWebhookConfiguration
...
...
staging/src/k8s.io/apiserver/pkg/admission/configuration/mutating_webhook_manager_test.go
View file @
55ecc454
...
@@ -45,7 +45,7 @@ func TestGetMutatingWebhookConfig(t *testing.T) {
...
@@ -45,7 +45,7 @@ func TestGetMutatingWebhookConfig(t *testing.T) {
webhookConfiguration
:=
&
v1beta1
.
MutatingWebhookConfiguration
{
webhookConfiguration
:=
&
v1beta1
.
MutatingWebhookConfiguration
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"webhook1"
},
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"webhook1"
},
Webhooks
:
[]
v1beta1
.
Webhook
{{
Name
:
"webhook1.1"
}},
Webhooks
:
[]
v1beta1
.
Mutating
Webhook
{{
Name
:
"webhook1.1"
}},
}
}
mutatingInformer
:=
informerFactory
.
Admissionregistration
()
.
V1beta1
()
.
MutatingWebhookConfigurations
()
mutatingInformer
:=
informerFactory
.
Admissionregistration
()
.
V1beta1
()
.
MutatingWebhookConfigurations
()
...
@@ -57,7 +57,14 @@ func TestGetMutatingWebhookConfig(t *testing.T) {
...
@@ -57,7 +57,14 @@ func TestGetMutatingWebhookConfig(t *testing.T) {
if
len
(
configurations
)
==
0
{
if
len
(
configurations
)
==
0
{
t
.
Errorf
(
"expected non empty webhooks"
)
t
.
Errorf
(
"expected non empty webhooks"
)
}
}
if
!
reflect
.
DeepEqual
(
configurations
,
webhookConfiguration
.
Webhooks
)
{
for
i
:=
range
configurations
{
t
.
Errorf
(
"Expected
\n
%#v
\n
got
\n
%#v"
,
webhookConfiguration
.
Webhooks
,
configurations
)
h
,
ok
:=
configurations
[
i
]
.
GetMutatingWebhook
()
if
!
ok
{
t
.
Errorf
(
"Expected mutating webhook"
)
continue
}
if
!
reflect
.
DeepEqual
(
h
,
&
webhookConfiguration
.
Webhooks
[
i
])
{
t
.
Errorf
(
"Expected
\n
%#v
\n
got
\n
%#v"
,
&
webhookConfiguration
.
Webhooks
[
i
],
h
)
}
}
}
}
}
staging/src/k8s.io/apiserver/pkg/admission/configuration/validating_webhook_manager.go
View file @
55ecc454
...
@@ -24,6 +24,7 @@ import (
...
@@ -24,6 +24,7 @@ import (
"k8s.io/api/admissionregistration/v1beta1"
"k8s.io/api/admissionregistration/v1beta1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/labels"
utilruntime
"k8s.io/apimachinery/pkg/util/runtime"
utilruntime
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/admission/plugin/webhook"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/client-go/informers"
"k8s.io/client-go/informers"
admissionregistrationlisters
"k8s.io/client-go/listers/admissionregistration/v1beta1"
admissionregistrationlisters
"k8s.io/client-go/listers/admissionregistration/v1beta1"
...
@@ -48,7 +49,7 @@ func NewValidatingWebhookConfigurationManager(f informers.SharedInformerFactory)
...
@@ -48,7 +49,7 @@ func NewValidatingWebhookConfigurationManager(f informers.SharedInformerFactory)
}
}
// Start with an empty list
// Start with an empty list
manager
.
configuration
.
Store
(
&
v1beta1
.
ValidatingWebhookConfiguration
{})
manager
.
configuration
.
Store
(
[]
webhook
.
WebhookAccessor
{})
// On any change, rebuild the config
// On any change, rebuild the config
informer
.
Informer
()
.
AddEventHandler
(
cache
.
ResourceEventHandlerFuncs
{
informer
.
Informer
()
.
AddEventHandler
(
cache
.
ResourceEventHandlerFuncs
{
...
@@ -61,8 +62,8 @@ func NewValidatingWebhookConfigurationManager(f informers.SharedInformerFactory)
...
@@ -61,8 +62,8 @@ func NewValidatingWebhookConfigurationManager(f informers.SharedInformerFactory)
}
}
// Webhooks returns the merged ValidatingWebhookConfiguration.
// Webhooks returns the merged ValidatingWebhookConfiguration.
func
(
v
*
validatingWebhookConfigurationManager
)
Webhooks
()
[]
v1beta1
.
Webhook
{
func
(
v
*
validatingWebhookConfigurationManager
)
Webhooks
()
[]
webhook
.
WebhookAccessor
{
return
v
.
configuration
.
Load
()
.
(
*
v1beta1
.
ValidatingWebhookConfiguration
)
.
Webhooks
return
v
.
configuration
.
Load
()
.
(
[]
webhook
.
WebhookAccessor
)
}
}
// HasSynced returns true if the shared informers have synced.
// HasSynced returns true if the shared informers have synced.
...
@@ -79,15 +80,15 @@ func (v *validatingWebhookConfigurationManager) updateConfiguration() {
...
@@ -79,15 +80,15 @@ func (v *validatingWebhookConfigurationManager) updateConfiguration() {
v
.
configuration
.
Store
(
mergeValidatingWebhookConfigurations
(
configurations
))
v
.
configuration
.
Store
(
mergeValidatingWebhookConfigurations
(
configurations
))
}
}
func
mergeValidatingWebhookConfigurations
(
func
mergeValidatingWebhookConfigurations
(
configurations
[]
*
v1beta1
.
ValidatingWebhookConfiguration
)
[]
webhook
.
WebhookAccessor
{
configurations
[]
*
v1beta1
.
ValidatingWebhookConfiguration
,
)
*
v1beta1
.
ValidatingWebhookConfiguration
{
sort
.
SliceStable
(
configurations
,
ValidatingWebhookConfigurationSorter
(
configurations
)
.
ByName
)
sort
.
SliceStable
(
configurations
,
ValidatingWebhookConfigurationSorter
(
configurations
)
.
ByName
)
var
ret
v1beta1
.
ValidatingWebhookConfiguration
accessors
:=
[]
webhook
.
WebhookAccessor
{}
for
_
,
c
:=
range
configurations
{
for
_
,
c
:=
range
configurations
{
ret
.
Webhooks
=
append
(
ret
.
Webhooks
,
c
.
Webhooks
...
)
for
i
:=
range
c
.
Webhooks
{
accessors
=
append
(
accessors
,
webhook
.
NewValidatingWebhookAccessor
(
&
c
.
Webhooks
[
i
]))
}
}
}
return
&
ret
return
accessors
}
}
type
ValidatingWebhookConfigurationSorter
[]
*
v1beta1
.
ValidatingWebhookConfiguration
type
ValidatingWebhookConfigurationSorter
[]
*
v1beta1
.
ValidatingWebhookConfiguration
...
...
staging/src/k8s.io/apiserver/pkg/admission/configuration/validating_webhook_manager_test.go
View file @
55ecc454
...
@@ -46,7 +46,7 @@ func TestGetValidatingWebhookConfig(t *testing.T) {
...
@@ -46,7 +46,7 @@ func TestGetValidatingWebhookConfig(t *testing.T) {
webhookConfiguration
:=
&
v1beta1
.
ValidatingWebhookConfiguration
{
webhookConfiguration
:=
&
v1beta1
.
ValidatingWebhookConfiguration
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"webhook1"
},
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"webhook1"
},
Webhooks
:
[]
v1beta1
.
Webhook
{{
Name
:
"webhook1.1"
}},
Webhooks
:
[]
v1beta1
.
Validating
Webhook
{{
Name
:
"webhook1.1"
}},
}
}
validatingInformer
:=
informerFactory
.
Admissionregistration
()
.
V1beta1
()
.
ValidatingWebhookConfigurations
()
validatingInformer
:=
informerFactory
.
Admissionregistration
()
.
V1beta1
()
.
ValidatingWebhookConfigurations
()
...
@@ -59,7 +59,14 @@ func TestGetValidatingWebhookConfig(t *testing.T) {
...
@@ -59,7 +59,14 @@ func TestGetValidatingWebhookConfig(t *testing.T) {
if
len
(
configurations
)
==
0
{
if
len
(
configurations
)
==
0
{
t
.
Errorf
(
"expected non empty webhooks"
)
t
.
Errorf
(
"expected non empty webhooks"
)
}
}
if
!
reflect
.
DeepEqual
(
configurations
,
webhookConfiguration
.
Webhooks
)
{
for
i
:=
range
configurations
{
t
.
Errorf
(
"Expected
\n
%#v
\n
got
\n
%#v"
,
webhookConfiguration
.
Webhooks
,
configurations
)
h
,
ok
:=
configurations
[
i
]
.
GetValidatingWebhook
()
if
!
ok
{
t
.
Errorf
(
"Expected validating webhook"
)
continue
}
if
!
reflect
.
DeepEqual
(
h
,
&
webhookConfiguration
.
Webhooks
[
i
])
{
t
.
Errorf
(
"Expected
\n
%#v
\n
got
\n
%#v"
,
&
webhookConfiguration
.
Webhooks
[
i
],
h
)
}
}
}
}
}
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/BUILD
0 → 100644
View file @
55ecc454
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["accessors.go"],
importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook",
importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/api/admissionregistration/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/errors:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/initializer:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/util:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/accessors.go
0 → 100644
View file @
55ecc454
/*
Copyright 2019 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
webhook
import
(
"k8s.io/api/admissionregistration/v1beta1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
)
// WebhookAccessor provides a common interface to both mutating and validating webhook types.
type
WebhookAccessor
interface
{
// GetName gets the webhook Name field.
GetName
()
string
// GetClientConfig gets the webhook ClientConfig field.
GetClientConfig
()
v1beta1
.
WebhookClientConfig
// GetRules gets the webhook Rules field.
GetRules
()
[]
v1beta1
.
RuleWithOperations
// GetFailurePolicy gets the webhook FailurePolicy field.
GetFailurePolicy
()
*
v1beta1
.
FailurePolicyType
// GetMatchPolicy gets the webhook MatchPolicy field.
GetMatchPolicy
()
*
v1beta1
.
MatchPolicyType
// GetNamespaceSelector gets the webhook NamespaceSelector field.
GetNamespaceSelector
()
*
metav1
.
LabelSelector
// GetSideEffects gets the webhook SideEffects field.
GetSideEffects
()
*
v1beta1
.
SideEffectClass
// GetTimeoutSeconds gets the webhook TimeoutSeconds field.
GetTimeoutSeconds
()
*
int32
// GetAdmissionReviewVersions gets the webhook AdmissionReviewVersions field.
GetAdmissionReviewVersions
()
[]
string
// GetMutatingWebhook if the accessor contains a MutatingWebhook, returns it and true, else returns false.
GetMutatingWebhook
()
(
*
v1beta1
.
MutatingWebhook
,
bool
)
// GetValidatingWebhook if the accessor contains a ValidatingWebhook, returns it and true, else returns false.
GetValidatingWebhook
()
(
*
v1beta1
.
ValidatingWebhook
,
bool
)
}
// NewMutatingWebhookAccessor creates an accessor for a MutatingWebhook.
func
NewMutatingWebhookAccessor
(
h
*
v1beta1
.
MutatingWebhook
)
WebhookAccessor
{
return
mutatingWebhookAccessor
{
h
}
}
type
mutatingWebhookAccessor
struct
{
*
v1beta1
.
MutatingWebhook
}
func
(
m
mutatingWebhookAccessor
)
GetName
()
string
{
return
m
.
Name
}
func
(
m
mutatingWebhookAccessor
)
GetClientConfig
()
v1beta1
.
WebhookClientConfig
{
return
m
.
ClientConfig
}
func
(
m
mutatingWebhookAccessor
)
GetRules
()
[]
v1beta1
.
RuleWithOperations
{
return
m
.
Rules
}
func
(
m
mutatingWebhookAccessor
)
GetFailurePolicy
()
*
v1beta1
.
FailurePolicyType
{
return
m
.
FailurePolicy
}
func
(
m
mutatingWebhookAccessor
)
GetMatchPolicy
()
*
v1beta1
.
MatchPolicyType
{
return
m
.
MatchPolicy
}
func
(
m
mutatingWebhookAccessor
)
GetNamespaceSelector
()
*
metav1
.
LabelSelector
{
return
m
.
NamespaceSelector
}
func
(
m
mutatingWebhookAccessor
)
GetSideEffects
()
*
v1beta1
.
SideEffectClass
{
return
m
.
SideEffects
}
func
(
m
mutatingWebhookAccessor
)
GetTimeoutSeconds
()
*
int32
{
return
m
.
TimeoutSeconds
}
func
(
m
mutatingWebhookAccessor
)
GetAdmissionReviewVersions
()
[]
string
{
return
m
.
AdmissionReviewVersions
}
func
(
m
mutatingWebhookAccessor
)
GetMutatingWebhook
()
(
*
v1beta1
.
MutatingWebhook
,
bool
)
{
return
m
.
MutatingWebhook
,
true
}
func
(
m
mutatingWebhookAccessor
)
GetValidatingWebhook
()
(
*
v1beta1
.
ValidatingWebhook
,
bool
)
{
return
nil
,
false
}
// NewValidatingWebhookAccessor creates an accessor for a ValidatingWebhook.
func
NewValidatingWebhookAccessor
(
h
*
v1beta1
.
ValidatingWebhook
)
WebhookAccessor
{
return
validatingWebhookAccessor
{
h
}
}
type
validatingWebhookAccessor
struct
{
*
v1beta1
.
ValidatingWebhook
}
func
(
v
validatingWebhookAccessor
)
GetName
()
string
{
return
v
.
Name
}
func
(
v
validatingWebhookAccessor
)
GetClientConfig
()
v1beta1
.
WebhookClientConfig
{
return
v
.
ClientConfig
}
func
(
v
validatingWebhookAccessor
)
GetRules
()
[]
v1beta1
.
RuleWithOperations
{
return
v
.
Rules
}
func
(
v
validatingWebhookAccessor
)
GetFailurePolicy
()
*
v1beta1
.
FailurePolicyType
{
return
v
.
FailurePolicy
}
func
(
v
validatingWebhookAccessor
)
GetMatchPolicy
()
*
v1beta1
.
MatchPolicyType
{
return
v
.
MatchPolicy
}
func
(
v
validatingWebhookAccessor
)
GetNamespaceSelector
()
*
metav1
.
LabelSelector
{
return
v
.
NamespaceSelector
}
func
(
v
validatingWebhookAccessor
)
GetSideEffects
()
*
v1beta1
.
SideEffectClass
{
return
v
.
SideEffects
}
func
(
v
validatingWebhookAccessor
)
GetTimeoutSeconds
()
*
int32
{
return
v
.
TimeoutSeconds
}
func
(
v
validatingWebhookAccessor
)
GetAdmissionReviewVersions
()
[]
string
{
return
v
.
AdmissionReviewVersions
}
func
(
v
validatingWebhookAccessor
)
GetMutatingWebhook
()
(
*
v1beta1
.
MutatingWebhook
,
bool
)
{
return
nil
,
false
}
func
(
v
validatingWebhookAccessor
)
GetValidatingWebhook
()
(
*
v1beta1
.
ValidatingWebhook
,
bool
)
{
return
v
.
ValidatingWebhook
,
true
}
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/BUILD
View file @
55ecc454
...
@@ -18,6 +18,7 @@ go_library(
...
@@ -18,6 +18,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission: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/apiserver/pkg/admission/initializer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules:go_default_library",
...
@@ -56,6 +57,7 @@ go_test(
...
@@ -56,6 +57,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/apis/example:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/apis/example:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/apis/example/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/apis/example/v1:go_default_library",
...
...
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/interfaces.go
View file @
55ecc454
...
@@ -19,15 +19,15 @@ package generic
...
@@ -19,15 +19,15 @@ package generic
import
(
import
(
"context"
"context"
"k8s.io/api/admissionregistration/v1beta1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/webhook"
)
)
// Source can list dynamic webhook plugins.
// Source can list dynamic webhook plugins.
type
Source
interface
{
type
Source
interface
{
Webhooks
()
[]
v1beta1
.
Webhook
Webhooks
()
[]
webhook
.
WebhookAccessor
HasSynced
()
bool
HasSynced
()
bool
}
}
...
@@ -51,8 +51,7 @@ type VersionedAttributes struct {
...
@@ -51,8 +51,7 @@ type VersionedAttributes struct {
// WebhookInvocation describes how to call a webhook, including the resource and subresource the webhook registered for,
// WebhookInvocation describes how to call a webhook, including the resource and subresource the webhook registered for,
// and the kind that should be sent to the webhook.
// and the kind that should be sent to the webhook.
type
WebhookInvocation
struct
{
type
WebhookInvocation
struct
{
Webhook
*
v1beta1
.
Webhook
Webhook
webhook
.
WebhookAccessor
Resource
schema
.
GroupVersionResource
Resource
schema
.
GroupVersionResource
Subresource
string
Subresource
string
Kind
schema
.
GroupVersionKind
Kind
schema
.
GroupVersionKind
...
...
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/webhook.go
View file @
55ecc454
...
@@ -27,10 +27,11 @@ import (
...
@@ -27,10 +27,11 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission"
genericadmissioninit
"k8s.io/apiserver/pkg/admission/initializer"
genericadmissioninit
"k8s.io/apiserver/pkg/admission/initializer"
"k8s.io/apiserver/pkg/admission/plugin/webhook"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config"
"k8s.io/apiserver/pkg/admission/plugin/webhook/namespace"
"k8s.io/apiserver/pkg/admission/plugin/webhook/namespace"
"k8s.io/apiserver/pkg/admission/plugin/webhook/rules"
"k8s.io/apiserver/pkg/admission/plugin/webhook/rules"
"k8s.io/apiserver/pkg/util/webhook"
webhookutil
"k8s.io/apiserver/pkg/util/webhook"
"k8s.io/client-go/informers"
"k8s.io/client-go/informers"
clientset
"k8s.io/client-go/kubernetes"
clientset
"k8s.io/client-go/kubernetes"
)
)
...
@@ -42,7 +43,7 @@ type Webhook struct {
...
@@ -42,7 +43,7 @@ type Webhook struct {
sourceFactory
sourceFactory
sourceFactory
sourceFactory
hookSource
Source
hookSource
Source
clientManager
*
webhook
.
ClientManager
clientManager
*
webhook
util
.
ClientManager
namespaceMatcher
*
namespace
.
Matcher
namespaceMatcher
*
namespace
.
Matcher
dispatcher
Dispatcher
dispatcher
Dispatcher
}
}
...
@@ -53,7 +54,7 @@ var (
...
@@ -53,7 +54,7 @@ var (
)
)
type
sourceFactory
func
(
f
informers
.
SharedInformerFactory
)
Source
type
sourceFactory
func
(
f
informers
.
SharedInformerFactory
)
Source
type
dispatcherFactory
func
(
cm
*
webhook
.
ClientManager
)
Dispatcher
type
dispatcherFactory
func
(
cm
*
webhook
util
.
ClientManager
)
Dispatcher
// NewWebhook creates a new generic admission webhook.
// NewWebhook creates a new generic admission webhook.
func
NewWebhook
(
handler
*
admission
.
Handler
,
configFile
io
.
Reader
,
sourceFactory
sourceFactory
,
dispatcherFactory
dispatcherFactory
)
(
*
Webhook
,
error
)
{
func
NewWebhook
(
handler
*
admission
.
Handler
,
configFile
io
.
Reader
,
sourceFactory
sourceFactory
,
dispatcherFactory
dispatcherFactory
)
(
*
Webhook
,
error
)
{
...
@@ -62,17 +63,17 @@ func NewWebhook(handler *admission.Handler, configFile io.Reader, sourceFactory
...
@@ -62,17 +63,17 @@ func NewWebhook(handler *admission.Handler, configFile io.Reader, sourceFactory
return
nil
,
err
return
nil
,
err
}
}
cm
,
err
:=
webhook
.
NewClientManager
(
admissionv1beta1
.
SchemeGroupVersion
,
admissionv1beta1
.
AddToScheme
)
cm
,
err
:=
webhook
util
.
NewClientManager
(
admissionv1beta1
.
SchemeGroupVersion
,
admissionv1beta1
.
AddToScheme
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
authInfoResolver
,
err
:=
webhook
.
NewDefaultAuthenticationInfoResolver
(
kubeconfigFile
)
authInfoResolver
,
err
:=
webhook
util
.
NewDefaultAuthenticationInfoResolver
(
kubeconfigFile
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
// Set defaults which may be overridden later.
// Set defaults which may be overridden later.
cm
.
SetAuthenticationInfoResolver
(
authInfoResolver
)
cm
.
SetAuthenticationInfoResolver
(
authInfoResolver
)
cm
.
SetServiceResolver
(
webhook
.
NewDefaultServiceResolver
())
cm
.
SetServiceResolver
(
webhook
util
.
NewDefaultServiceResolver
())
return
&
Webhook
{
return
&
Webhook
{
Handler
:
handler
,
Handler
:
handler
,
...
@@ -86,13 +87,13 @@ func NewWebhook(handler *admission.Handler, configFile io.Reader, sourceFactory
...
@@ -86,13 +87,13 @@ func NewWebhook(handler *admission.Handler, configFile io.Reader, sourceFactory
// SetAuthenticationInfoResolverWrapper sets the
// SetAuthenticationInfoResolverWrapper sets the
// AuthenticationInfoResolverWrapper.
// AuthenticationInfoResolverWrapper.
// TODO find a better way wire this, but keep this pull small for now.
// TODO find a better way wire this, but keep this pull small for now.
func
(
a
*
Webhook
)
SetAuthenticationInfoResolverWrapper
(
wrapper
webhook
.
AuthenticationInfoResolverWrapper
)
{
func
(
a
*
Webhook
)
SetAuthenticationInfoResolverWrapper
(
wrapper
webhook
util
.
AuthenticationInfoResolverWrapper
)
{
a
.
clientManager
.
SetAuthenticationInfoResolverWrapper
(
wrapper
)
a
.
clientManager
.
SetAuthenticationInfoResolverWrapper
(
wrapper
)
}
}
// SetServiceResolver sets a service resolver for the webhook admission plugin.
// SetServiceResolver sets a service resolver for the webhook admission plugin.
// Passing a nil resolver does not have an effect, instead a default one will be used.
// Passing a nil resolver does not have an effect, instead a default one will be used.
func
(
a
*
Webhook
)
SetServiceResolver
(
sr
webhook
.
ServiceResolver
)
{
func
(
a
*
Webhook
)
SetServiceResolver
(
sr
webhook
util
.
ServiceResolver
)
{
a
.
clientManager
.
SetServiceResolver
(
sr
)
a
.
clientManager
.
SetServiceResolver
(
sr
)
}
}
...
@@ -128,10 +129,10 @@ func (a *Webhook) ValidateInitialization() error {
...
@@ -128,10 +129,10 @@ func (a *Webhook) ValidateInitialization() error {
// shouldCallHook returns invocation details if the webhook should be called, nil if the webhook should not be called,
// shouldCallHook returns invocation details if the webhook should be called, nil if the webhook should not be called,
// or an error if an error was encountered during evaluation.
// or an error if an error was encountered during evaluation.
func
(
a
*
Webhook
)
shouldCallHook
(
h
*
v1beta1
.
Webhook
,
attr
admission
.
Attributes
,
o
admission
.
ObjectInterfaces
)
(
*
WebhookInvocation
,
*
apierrors
.
StatusError
)
{
func
(
a
*
Webhook
)
shouldCallHook
(
h
webhook
.
WebhookAccessor
,
attr
admission
.
Attributes
,
o
admission
.
ObjectInterfaces
)
(
*
WebhookInvocation
,
*
apierrors
.
StatusError
)
{
var
err
*
apierrors
.
StatusError
var
err
*
apierrors
.
StatusError
var
invocation
*
WebhookInvocation
var
invocation
*
WebhookInvocation
for
_
,
r
:=
range
h
.
Rules
{
for
_
,
r
:=
range
h
.
GetRules
()
{
m
:=
rules
.
Matcher
{
Rule
:
r
,
Attr
:
attr
}
m
:=
rules
.
Matcher
{
Rule
:
r
,
Attr
:
attr
}
if
m
.
Matches
()
{
if
m
.
Matches
()
{
invocation
=
&
WebhookInvocation
{
invocation
=
&
WebhookInvocation
{
...
@@ -143,12 +144,12 @@ func (a *Webhook) shouldCallHook(h *v1beta1.Webhook, attr admission.Attributes,
...
@@ -143,12 +144,12 @@ func (a *Webhook) shouldCallHook(h *v1beta1.Webhook, attr admission.Attributes,
break
break
}
}
}
}
if
invocation
==
nil
&&
h
.
MatchPolicy
!=
nil
&&
*
h
.
MatchPolicy
==
v1beta1
.
Equivalent
{
if
invocation
==
nil
&&
h
.
GetMatchPolicy
()
!=
nil
&&
*
h
.
GetMatchPolicy
()
==
v1beta1
.
Equivalent
{
attrWithOverride
:=
&
attrWithResourceOverride
{
Attributes
:
attr
}
attrWithOverride
:=
&
attrWithResourceOverride
{
Attributes
:
attr
}
equivalents
:=
o
.
GetEquivalentResourceMapper
()
.
EquivalentResourcesFor
(
attr
.
GetResource
(),
attr
.
GetSubresource
())
equivalents
:=
o
.
GetEquivalentResourceMapper
()
.
EquivalentResourcesFor
(
attr
.
GetResource
(),
attr
.
GetSubresource
())
// honor earlier rules first
// honor earlier rules first
OuterLoop
:
OuterLoop
:
for
_
,
r
:=
range
h
.
Rules
{
for
_
,
r
:=
range
h
.
GetRules
()
{
// see if the rule matches any of the equivalent resources
// see if the rule matches any of the equivalent resources
for
_
,
equivalent
:=
range
equivalents
{
for
_
,
equivalent
:=
range
equivalents
{
if
equivalent
==
attr
.
GetResource
()
{
if
equivalent
==
attr
.
GetResource
()
{
...
@@ -207,7 +208,7 @@ func (a *Webhook) Dispatch(attr admission.Attributes, o admission.ObjectInterfac
...
@@ -207,7 +208,7 @@ func (a *Webhook) Dispatch(attr admission.Attributes, o admission.ObjectInterfac
var
relevantHooks
[]
*
WebhookInvocation
var
relevantHooks
[]
*
WebhookInvocation
for
i
:=
range
hooks
{
for
i
:=
range
hooks
{
invocation
,
err
:=
a
.
shouldCallHook
(
&
hooks
[
i
],
attr
,
o
)
invocation
,
err
:=
a
.
shouldCallHook
(
hooks
[
i
],
attr
,
o
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
...
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/webhook_test.go
View file @
55ecc454
...
@@ -25,6 +25,7 @@ import (
...
@@ -25,6 +25,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/webhook"
"k8s.io/apiserver/pkg/admission/plugin/webhook/namespace"
"k8s.io/apiserver/pkg/admission/plugin/webhook/namespace"
)
)
...
@@ -61,7 +62,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -61,7 +62,7 @@ func TestShouldCallHook(t *testing.T) {
testcases
:=
[]
struct
{
testcases
:=
[]
struct
{
name
string
name
string
webhook
*
v1beta1
.
Webhook
webhook
*
v1beta1
.
Validating
Webhook
attrs
admission
.
Attributes
attrs
admission
.
Attributes
expectCall
bool
expectCall
bool
...
@@ -72,13 +73,13 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -72,13 +73,13 @@ func TestShouldCallHook(t *testing.T) {
}{
}{
{
{
name
:
"no rules (just write)"
,
name
:
"no rules (just write)"
,
webhook
:
&
v1beta1
.
Webhook
{
Rules
:
[]
v1beta1
.
RuleWithOperations
{}},
webhook
:
&
v1beta1
.
Validating
Webhook
{
Rules
:
[]
v1beta1
.
RuleWithOperations
{}},
attrs
:
admission
.
NewAttributesRecord
(
nil
,
nil
,
schema
.
GroupVersionKind
{
"apps"
,
"v1"
,
"Deployment"
},
"ns"
,
"name"
,
schema
.
GroupVersionResource
{
"apps"
,
"v1"
,
"deployments"
},
""
,
admission
.
Create
,
&
metav1
.
CreateOptions
{},
false
,
nil
),
attrs
:
admission
.
NewAttributesRecord
(
nil
,
nil
,
schema
.
GroupVersionKind
{
"apps"
,
"v1"
,
"Deployment"
},
"ns"
,
"name"
,
schema
.
GroupVersionResource
{
"apps"
,
"v1"
,
"deployments"
},
""
,
admission
.
Create
,
&
metav1
.
CreateOptions
{},
false
,
nil
),
expectCall
:
false
,
expectCall
:
false
,
},
},
{
{
name
:
"invalid kind lookup"
,
name
:
"invalid kind lookup"
,
webhook
:
&
v1beta1
.
Webhook
{
webhook
:
&
v1beta1
.
Validating
Webhook
{
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
MatchPolicy
:
&
equivalentMatch
,
MatchPolicy
:
&
equivalentMatch
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -91,7 +92,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -91,7 +92,7 @@ func TestShouldCallHook(t *testing.T) {
},
},
{
{
name
:
"wildcard rule, match as requested"
,
name
:
"wildcard rule, match as requested"
,
webhook
:
&
v1beta1
.
Webhook
{
webhook
:
&
v1beta1
.
Validating
Webhook
{
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Operations
:
[]
v1beta1
.
OperationType
{
"*"
},
Operations
:
[]
v1beta1
.
OperationType
{
"*"
},
...
@@ -105,7 +106,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -105,7 +106,7 @@ func TestShouldCallHook(t *testing.T) {
},
},
{
{
name
:
"specific rules, prefer exact match"
,
name
:
"specific rules, prefer exact match"
,
webhook
:
&
v1beta1
.
Webhook
{
webhook
:
&
v1beta1
.
Validating
Webhook
{
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Operations
:
[]
v1beta1
.
OperationType
{
"*"
},
Operations
:
[]
v1beta1
.
OperationType
{
"*"
},
...
@@ -125,7 +126,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -125,7 +126,7 @@ func TestShouldCallHook(t *testing.T) {
},
},
{
{
name
:
"specific rules, match miss"
,
name
:
"specific rules, match miss"
,
webhook
:
&
v1beta1
.
Webhook
{
webhook
:
&
v1beta1
.
Validating
Webhook
{
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Operations
:
[]
v1beta1
.
OperationType
{
"*"
},
Operations
:
[]
v1beta1
.
OperationType
{
"*"
},
...
@@ -139,7 +140,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -139,7 +140,7 @@ func TestShouldCallHook(t *testing.T) {
},
},
{
{
name
:
"specific rules, exact match miss"
,
name
:
"specific rules, exact match miss"
,
webhook
:
&
v1beta1
.
Webhook
{
webhook
:
&
v1beta1
.
Validating
Webhook
{
MatchPolicy
:
&
exactMatch
,
MatchPolicy
:
&
exactMatch
,
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -154,7 +155,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -154,7 +155,7 @@ func TestShouldCallHook(t *testing.T) {
},
},
{
{
name
:
"specific rules, equivalent match, prefer extensions"
,
name
:
"specific rules, equivalent match, prefer extensions"
,
webhook
:
&
v1beta1
.
Webhook
{
webhook
:
&
v1beta1
.
Validating
Webhook
{
MatchPolicy
:
&
equivalentMatch
,
MatchPolicy
:
&
equivalentMatch
,
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -172,7 +173,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -172,7 +173,7 @@ func TestShouldCallHook(t *testing.T) {
},
},
{
{
name
:
"specific rules, equivalent match, prefer apps"
,
name
:
"specific rules, equivalent match, prefer apps"
,
webhook
:
&
v1beta1
.
Webhook
{
webhook
:
&
v1beta1
.
Validating
Webhook
{
MatchPolicy
:
&
equivalentMatch
,
MatchPolicy
:
&
equivalentMatch
,
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -191,7 +192,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -191,7 +192,7 @@ func TestShouldCallHook(t *testing.T) {
{
{
name
:
"specific rules, subresource prefer exact match"
,
name
:
"specific rules, subresource prefer exact match"
,
webhook
:
&
v1beta1
.
Webhook
{
webhook
:
&
v1beta1
.
Validating
Webhook
{
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Operations
:
[]
v1beta1
.
OperationType
{
"*"
},
Operations
:
[]
v1beta1
.
OperationType
{
"*"
},
...
@@ -211,7 +212,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -211,7 +212,7 @@ func TestShouldCallHook(t *testing.T) {
},
},
{
{
name
:
"specific rules, subresource match miss"
,
name
:
"specific rules, subresource match miss"
,
webhook
:
&
v1beta1
.
Webhook
{
webhook
:
&
v1beta1
.
Validating
Webhook
{
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Operations
:
[]
v1beta1
.
OperationType
{
"*"
},
Operations
:
[]
v1beta1
.
OperationType
{
"*"
},
...
@@ -225,7 +226,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -225,7 +226,7 @@ func TestShouldCallHook(t *testing.T) {
},
},
{
{
name
:
"specific rules, subresource exact match miss"
,
name
:
"specific rules, subresource exact match miss"
,
webhook
:
&
v1beta1
.
Webhook
{
webhook
:
&
v1beta1
.
Validating
Webhook
{
MatchPolicy
:
&
exactMatch
,
MatchPolicy
:
&
exactMatch
,
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -240,7 +241,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -240,7 +241,7 @@ func TestShouldCallHook(t *testing.T) {
},
},
{
{
name
:
"specific rules, subresource equivalent match, prefer extensions"
,
name
:
"specific rules, subresource equivalent match, prefer extensions"
,
webhook
:
&
v1beta1
.
Webhook
{
webhook
:
&
v1beta1
.
Validating
Webhook
{
MatchPolicy
:
&
equivalentMatch
,
MatchPolicy
:
&
equivalentMatch
,
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -258,7 +259,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -258,7 +259,7 @@ func TestShouldCallHook(t *testing.T) {
},
},
{
{
name
:
"specific rules, subresource equivalent match, prefer apps"
,
name
:
"specific rules, subresource equivalent match, prefer apps"
,
webhook
:
&
v1beta1
.
Webhook
{
webhook
:
&
v1beta1
.
Validating
Webhook
{
MatchPolicy
:
&
equivalentMatch
,
MatchPolicy
:
&
equivalentMatch
,
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -278,7 +279,7 @@ func TestShouldCallHook(t *testing.T) {
...
@@ -278,7 +279,7 @@ func TestShouldCallHook(t *testing.T) {
for
_
,
testcase
:=
range
testcases
{
for
_
,
testcase
:=
range
testcases
{
t
.
Run
(
testcase
.
name
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
testcase
.
name
,
func
(
t
*
testing
.
T
)
{
invocation
,
err
:=
a
.
shouldCallHook
(
testcase
.
webhook
,
testcase
.
attrs
,
interfaces
)
invocation
,
err
:=
a
.
shouldCallHook
(
webhook
.
NewValidatingWebhookAccessor
(
testcase
.
webhook
)
,
testcase
.
attrs
,
interfaces
)
if
err
!=
nil
{
if
err
!=
nil
{
if
len
(
testcase
.
expectErr
)
==
0
{
if
len
(
testcase
.
expectErr
)
==
0
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
...
...
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go
View file @
55ecc454
...
@@ -39,16 +39,16 @@ import (
...
@@ -39,16 +39,16 @@ import (
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/apiserver/pkg/admission/plugin/webhook/request"
"k8s.io/apiserver/pkg/admission/plugin/webhook/request"
"k8s.io/apiserver/pkg/admission/plugin/webhook/util"
"k8s.io/apiserver/pkg/admission/plugin/webhook/util"
"k8s.io/apiserver/pkg/util/webhook"
webhookutil
"k8s.io/apiserver/pkg/util/webhook"
)
)
type
mutatingDispatcher
struct
{
type
mutatingDispatcher
struct
{
cm
*
webhook
.
ClientManager
cm
*
webhook
util
.
ClientManager
plugin
*
Plugin
plugin
*
Plugin
}
}
func
newMutatingDispatcher
(
p
*
Plugin
)
func
(
cm
*
webhook
.
ClientManager
)
generic
.
Dispatcher
{
func
newMutatingDispatcher
(
p
*
Plugin
)
func
(
cm
*
webhook
util
.
ClientManager
)
generic
.
Dispatcher
{
return
func
(
cm
*
webhook
.
ClientManager
)
generic
.
Dispatcher
{
return
func
(
cm
*
webhook
util
.
ClientManager
)
generic
.
Dispatcher
{
return
&
mutatingDispatcher
{
cm
,
p
}
return
&
mutatingDispatcher
{
cm
,
p
}
}
}
}
}
...
@@ -58,7 +58,10 @@ var _ generic.Dispatcher = &mutatingDispatcher{}
...
@@ -58,7 +58,10 @@ var _ generic.Dispatcher = &mutatingDispatcher{}
func
(
a
*
mutatingDispatcher
)
Dispatch
(
ctx
context
.
Context
,
attr
admission
.
Attributes
,
o
admission
.
ObjectInterfaces
,
relevantHooks
[]
*
generic
.
WebhookInvocation
)
error
{
func
(
a
*
mutatingDispatcher
)
Dispatch
(
ctx
context
.
Context
,
attr
admission
.
Attributes
,
o
admission
.
ObjectInterfaces
,
relevantHooks
[]
*
generic
.
WebhookInvocation
)
error
{
var
versionedAttr
*
generic
.
VersionedAttributes
var
versionedAttr
*
generic
.
VersionedAttributes
for
_
,
invocation
:=
range
relevantHooks
{
for
_
,
invocation
:=
range
relevantHooks
{
hook
:=
invocation
.
Webhook
hook
,
ok
:=
invocation
.
Webhook
.
GetMutatingWebhook
()
if
!
ok
{
return
fmt
.
Errorf
(
"mutating webhook dispatch requires v1beta1.MutatingWebhook, but got %T"
,
hook
)
}
if
versionedAttr
==
nil
{
if
versionedAttr
==
nil
{
// First webhook, create versioned attributes
// First webhook, create versioned attributes
var
err
error
var
err
error
...
@@ -73,14 +76,14 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr admission.Attrib
...
@@ -73,14 +76,14 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr admission.Attrib
}
}
t
:=
time
.
Now
()
t
:=
time
.
Now
()
err
:=
a
.
callAttrMutatingHook
(
ctx
,
invocation
,
versionedAttr
,
o
)
err
:=
a
.
callAttrMutatingHook
(
ctx
,
hook
,
invocation
,
versionedAttr
,
o
)
admissionmetrics
.
Metrics
.
ObserveWebhook
(
time
.
Since
(
t
),
err
!=
nil
,
versionedAttr
.
Attributes
,
"admit"
,
hook
.
Name
)
admissionmetrics
.
Metrics
.
ObserveWebhook
(
time
.
Since
(
t
),
err
!=
nil
,
versionedAttr
.
Attributes
,
"admit"
,
hook
.
Name
)
if
err
==
nil
{
if
err
==
nil
{
continue
continue
}
}
ignoreClientCallFailures
:=
hook
.
FailurePolicy
!=
nil
&&
*
hook
.
FailurePolicy
==
v1beta1
.
Ignore
ignoreClientCallFailures
:=
hook
.
FailurePolicy
!=
nil
&&
*
hook
.
FailurePolicy
==
v1beta1
.
Ignore
if
callErr
,
ok
:=
err
.
(
*
webhook
.
ErrCallingWebhook
);
ok
{
if
callErr
,
ok
:=
err
.
(
*
webhook
util
.
ErrCallingWebhook
);
ok
{
if
ignoreClientCallFailures
{
if
ignoreClientCallFailures
{
klog
.
Warningf
(
"Failed calling webhook, failing open %v: %v"
,
hook
.
Name
,
callErr
)
klog
.
Warningf
(
"Failed calling webhook, failing open %v: %v"
,
hook
.
Name
,
callErr
)
utilruntime
.
HandleError
(
callErr
)
utilruntime
.
HandleError
(
callErr
)
...
@@ -100,11 +103,11 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr admission.Attrib
...
@@ -100,11 +103,11 @@ func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr admission.Attrib
}
}
// note that callAttrMutatingHook updates attr
// note that callAttrMutatingHook updates attr
func
(
a
*
mutatingDispatcher
)
callAttrMutatingHook
(
ctx
context
.
Context
,
invocation
*
generic
.
WebhookInvocation
,
attr
*
generic
.
VersionedAttributes
,
o
admission
.
ObjectInterfaces
)
error
{
h
:=
invocation
.
Webhook
func
(
a
*
mutatingDispatcher
)
callAttrMutatingHook
(
ctx
context
.
Context
,
h
*
v1beta1
.
MutatingWebhook
,
invocation
*
generic
.
WebhookInvocation
,
attr
*
generic
.
VersionedAttributes
,
o
admission
.
ObjectInterfaces
)
error
{
if
attr
.
Attributes
.
IsDryRun
()
{
if
attr
.
Attributes
.
IsDryRun
()
{
if
h
.
SideEffects
==
nil
{
if
h
.
SideEffects
==
nil
{
return
&
webhook
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
fmt
.
Errorf
(
"Webhook SideEffects is nil"
)}
return
&
webhook
util
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
fmt
.
Errorf
(
"Webhook SideEffects is nil"
)}
}
}
if
!
(
*
h
.
SideEffects
==
v1beta1
.
SideEffectClassNone
||
*
h
.
SideEffects
==
v1beta1
.
SideEffectClassNoneOnDryRun
)
{
if
!
(
*
h
.
SideEffects
==
v1beta1
.
SideEffectClassNone
||
*
h
.
SideEffects
==
v1beta1
.
SideEffectClassNoneOnDryRun
)
{
return
webhookerrors
.
NewDryRunUnsupportedErr
(
h
.
Name
)
return
webhookerrors
.
NewDryRunUnsupportedErr
(
h
.
Name
)
...
@@ -113,15 +116,15 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, invocatio
...
@@ -113,15 +116,15 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, invocatio
// Currently dispatcher only supports `v1beta1` AdmissionReview
// Currently dispatcher only supports `v1beta1` AdmissionReview
// TODO: Make the dispatcher capable of sending multiple AdmissionReview versions
// TODO: Make the dispatcher capable of sending multiple AdmissionReview versions
if
!
util
.
HasAdmissionReviewVersion
(
v1beta1
.
SchemeGroupVersion
.
Version
,
h
)
{
if
!
util
.
HasAdmissionReviewVersion
(
v1beta1
.
SchemeGroupVersion
.
Version
,
invocation
.
Webhook
)
{
return
&
webhook
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
fmt
.
Errorf
(
"webhook does not accept v1beta1 AdmissionReview"
)}
return
&
webhook
util
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
fmt
.
Errorf
(
"webhook does not accept v1beta1 AdmissionReview"
)}
}
}
// Make the webhook request
// Make the webhook request
request
:=
request
.
CreateAdmissionReview
(
attr
,
invocation
)
request
:=
request
.
CreateAdmissionReview
(
attr
,
invocation
)
client
,
err
:=
a
.
cm
.
HookClient
(
util
.
HookClientConfigForWebhook
(
h
))
client
,
err
:=
a
.
cm
.
HookClient
(
util
.
HookClientConfigForWebhook
(
invocation
.
Webhook
))
if
err
!=
nil
{
if
err
!=
nil
{
return
&
webhook
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
err
}
return
&
webhook
util
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
err
}
}
}
response
:=
&
admissionv1beta1
.
AdmissionReview
{}
response
:=
&
admissionv1beta1
.
AdmissionReview
{}
r
:=
client
.
Post
()
.
Context
(
ctx
)
.
Body
(
&
request
)
r
:=
client
.
Post
()
.
Context
(
ctx
)
.
Body
(
&
request
)
...
@@ -129,11 +132,11 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, invocatio
...
@@ -129,11 +132,11 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, invocatio
r
=
r
.
Timeout
(
time
.
Duration
(
*
h
.
TimeoutSeconds
)
*
time
.
Second
)
r
=
r
.
Timeout
(
time
.
Duration
(
*
h
.
TimeoutSeconds
)
*
time
.
Second
)
}
}
if
err
:=
r
.
Do
()
.
Into
(
response
);
err
!=
nil
{
if
err
:=
r
.
Do
()
.
Into
(
response
);
err
!=
nil
{
return
&
webhook
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
err
}
return
&
webhook
util
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
err
}
}
}
if
response
.
Response
==
nil
{
if
response
.
Response
==
nil
{
return
&
webhook
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
fmt
.
Errorf
(
"Webhook response was absent"
)}
return
&
webhook
util
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
fmt
.
Errorf
(
"Webhook response was absent"
)}
}
}
for
k
,
v
:=
range
response
.
Response
.
AuditAnnotations
{
for
k
,
v
:=
range
response
.
Response
.
AuditAnnotations
{
...
...
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin_test.go
View file @
55ecc454
...
@@ -46,7 +46,7 @@ func TestAdmit(t *testing.T) {
...
@@ -46,7 +46,7 @@ func TestAdmit(t *testing.T) {
defer
close
(
stopCh
)
defer
close
(
stopCh
)
testCases
:=
append
(
webhooktesting
.
NewMutatingTestCases
(
serverURL
),
testCases
:=
append
(
webhooktesting
.
NewMutatingTestCases
(
serverURL
),
webhooktesting
.
NewNonMutatingTestCases
(
serverURL
)
...
)
webhooktesting
.
ConvertToMutatingTestCases
(
webhooktesting
.
NewNonMutatingTestCases
(
serverURL
)
)
...
)
for
_
,
tt
:=
range
testCases
{
for
_
,
tt
:=
range
testCases
{
wh
,
err
:=
NewMutatingWebhook
(
nil
)
wh
,
err
:=
NewMutatingWebhook
(
nil
)
...
@@ -56,7 +56,7 @@ func TestAdmit(t *testing.T) {
...
@@ -56,7 +56,7 @@ func TestAdmit(t *testing.T) {
}
}
ns
:=
"webhook-test"
ns
:=
"webhook-test"
client
,
informer
:=
webhooktesting
.
NewFake
DataSource
(
ns
,
tt
.
Webhooks
,
true
,
stopCh
)
client
,
informer
:=
webhooktesting
.
NewFake
MutatingDataSource
(
ns
,
tt
.
Webhooks
,
stopCh
)
wh
.
SetAuthenticationInfoResolverWrapper
(
webhooktesting
.
Wrapper
(
webhooktesting
.
NewAuthenticationInfoResolver
(
new
(
int32
))))
wh
.
SetAuthenticationInfoResolverWrapper
(
webhooktesting
.
Wrapper
(
webhooktesting
.
NewAuthenticationInfoResolver
(
new
(
int32
))))
wh
.
SetServiceResolver
(
webhooktesting
.
NewServiceResolver
(
*
serverURL
))
wh
.
SetServiceResolver
(
webhooktesting
.
NewServiceResolver
(
*
serverURL
))
...
@@ -136,7 +136,7 @@ func TestAdmitCachedClient(t *testing.T) {
...
@@ -136,7 +136,7 @@ func TestAdmitCachedClient(t *testing.T) {
for
_
,
tt
:=
range
webhooktesting
.
NewCachedClientTestcases
(
serverURL
)
{
for
_
,
tt
:=
range
webhooktesting
.
NewCachedClientTestcases
(
serverURL
)
{
ns
:=
"webhook-test"
ns
:=
"webhook-test"
client
,
informer
:=
webhooktesting
.
NewFake
DataSource
(
ns
,
tt
.
Webhooks
,
true
,
stopCh
)
client
,
informer
:=
webhooktesting
.
NewFake
MutatingDataSource
(
ns
,
webhooktesting
.
ConvertToMutatingWebhooks
(
tt
.
Webhooks
)
,
stopCh
)
// override the webhook source. The client cache will stay the same.
// override the webhook source. The client cache will stay the same.
cacheMisses
:=
new
(
int32
)
cacheMisses
:=
new
(
int32
)
...
...
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace/BUILD
View file @
55ecc454
...
@@ -10,13 +10,13 @@ go_library(
...
@@ -10,13 +10,13 @@ go_library(
importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/namespace",
importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/namespace",
visibility = ["//visibility:public"],
visibility = ["//visibility:public"],
deps = [
deps = [
"//staging/src/k8s.io/api/admissionregistration/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/errors: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:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes: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",
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
],
],
...
@@ -34,6 +34,7 @@ go_test(
...
@@ -34,6 +34,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook:go_default_library",
],
],
)
)
...
...
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace/matcher.go
View file @
55ecc454
...
@@ -19,13 +19,13 @@ package namespace
...
@@ -19,13 +19,13 @@ package namespace
import
(
import
(
"fmt"
"fmt"
"k8s.io/api/admissionregistration/v1beta1"
apierrors
"k8s.io/apimachinery/pkg/api/errors"
apierrors
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/meta"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/labels"
utilerrors
"k8s.io/apimachinery/pkg/util/errors"
utilerrors
"k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/webhook"
clientset
"k8s.io/client-go/kubernetes"
clientset
"k8s.io/client-go/kubernetes"
corelisters
"k8s.io/client-go/listers/core/v1"
corelisters
"k8s.io/client-go/listers/core/v1"
)
)
...
@@ -86,7 +86,7 @@ func (m *Matcher) GetNamespaceLabels(attr admission.Attributes) (map[string]stri
...
@@ -86,7 +86,7 @@ func (m *Matcher) GetNamespaceLabels(attr admission.Attributes) (map[string]stri
// MatchNamespaceSelector decideds whether the request matches the
// MatchNamespaceSelector decideds whether the request matches the
// namespaceSelctor of the webhook. Only when they match, the webhook is called.
// namespaceSelctor of the webhook. Only when they match, the webhook is called.
func
(
m
*
Matcher
)
MatchNamespaceSelector
(
h
*
v1beta1
.
Webhook
,
attr
admission
.
Attributes
)
(
bool
,
*
apierrors
.
StatusError
)
{
func
(
m
*
Matcher
)
MatchNamespaceSelector
(
h
webhook
.
WebhookAccessor
,
attr
admission
.
Attributes
)
(
bool
,
*
apierrors
.
StatusError
)
{
namespaceName
:=
attr
.
GetNamespace
()
namespaceName
:=
attr
.
GetNamespace
()
if
len
(
namespaceName
)
==
0
&&
attr
.
GetResource
()
.
Resource
!=
"namespaces"
{
if
len
(
namespaceName
)
==
0
&&
attr
.
GetResource
()
.
Resource
!=
"namespaces"
{
// If the request is about a cluster scoped resource, and it is not a
// If the request is about a cluster scoped resource, and it is not a
...
@@ -96,7 +96,7 @@ func (m *Matcher) MatchNamespaceSelector(h *v1beta1.Webhook, attr admission.Attr
...
@@ -96,7 +96,7 @@ func (m *Matcher) MatchNamespaceSelector(h *v1beta1.Webhook, attr admission.Attr
return
true
,
nil
return
true
,
nil
}
}
// TODO: adding an LRU cache to cache the translation
// TODO: adding an LRU cache to cache the translation
selector
,
err
:=
metav1
.
LabelSelectorAsSelector
(
h
.
NamespaceSelector
)
selector
,
err
:=
metav1
.
LabelSelectorAsSelector
(
h
.
GetNamespaceSelector
()
)
if
err
!=
nil
{
if
err
!=
nil
{
return
false
,
apierrors
.
NewInternalError
(
err
)
return
false
,
apierrors
.
NewInternalError
(
err
)
}
}
...
...
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace/matcher_test.go
View file @
55ecc454
...
@@ -27,6 +27,7 @@ import (
...
@@ -27,6 +27,7 @@ import (
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/webhook"
)
)
type
fakeNamespaceLister
struct
{
type
fakeNamespaceLister
struct
{
...
@@ -114,12 +115,12 @@ func TestGetNamespaceLabels(t *testing.T) {
...
@@ -114,12 +115,12 @@ func TestGetNamespaceLabels(t *testing.T) {
}
}
func
TestNotExemptClusterScopedResource
(
t
*
testing
.
T
)
{
func
TestNotExemptClusterScopedResource
(
t
*
testing
.
T
)
{
hook
:=
&
registrationv1beta1
.
Webhook
{
hook
:=
&
registrationv1beta1
.
Validating
Webhook
{
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
NamespaceSelector
:
&
metav1
.
LabelSelector
{},
}
}
attr
:=
admission
.
NewAttributesRecord
(
nil
,
nil
,
schema
.
GroupVersionKind
{},
""
,
"mock-name"
,
schema
.
GroupVersionResource
{
Version
:
"v1"
,
Resource
:
"nodes"
},
""
,
admission
.
Create
,
&
metav1
.
CreateOptions
{},
false
,
nil
)
attr
:=
admission
.
NewAttributesRecord
(
nil
,
nil
,
schema
.
GroupVersionKind
{},
""
,
"mock-name"
,
schema
.
GroupVersionResource
{
Version
:
"v1"
,
Resource
:
"nodes"
},
""
,
admission
.
Create
,
&
metav1
.
CreateOptions
{},
false
,
nil
)
matcher
:=
Matcher
{}
matcher
:=
Matcher
{}
matches
,
err
:=
matcher
.
MatchNamespaceSelector
(
hook
,
attr
)
matches
,
err
:=
matcher
.
MatchNamespaceSelector
(
webhook
.
NewValidatingWebhookAccessor
(
hook
)
,
attr
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
...
...
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/testcase.go
View file @
55ecc454
This diff is collapsed.
Click to expand it.
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/util/BUILD
View file @
55ecc454
...
@@ -7,7 +7,7 @@ go_library(
...
@@ -7,7 +7,7 @@ go_library(
importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/util",
importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/util",
visibility = ["//visibility:public"],
visibility = ["//visibility:public"],
deps = [
deps = [
"//staging/src/k8s.io/api
/admissionregistration/v1beta1
:go_default_library",
"//staging/src/k8s.io/api
server/pkg/admission/plugin/webhook
:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library",
],
],
)
)
...
...
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/util/client_config.go
View file @
55ecc454
...
@@ -17,38 +17,39 @@ limitations under the License.
...
@@ -17,38 +17,39 @@ limitations under the License.
package
util
package
util
import
(
import
(
"k8s.io/api
/admissionregistration/v1beta1
"
"k8s.io/api
server/pkg/admission/plugin/webhook
"
"k8s.io/apiserver/pkg/util/webhook"
webhookutil
"k8s.io/apiserver/pkg/util/webhook"
)
)
// HookClientConfigForWebhook construct a webhook.ClientConfig using a v1beta1.Webhook API object.
// HookClientConfigForWebhook construct a webhookutil.ClientConfig using a WebhookAccessor to access
// webhook.ClientConfig is used to create a HookClient and the purpose of the config struct is to
// v1beta1.MutatingWebhook and v1beta1.ValidatingWebhook API objects. webhookutil.ClientConfig is used
// share that with other packages that need to create a HookClient.
// to create a HookClient and the purpose of the config struct is to share that with other packages
func
HookClientConfigForWebhook
(
w
*
v1beta1
.
Webhook
)
webhook
.
ClientConfig
{
// that need to create a HookClient.
ret
:=
webhook
.
ClientConfig
{
Name
:
w
.
Name
,
CABundle
:
w
.
ClientConfig
.
CABundle
}
func
HookClientConfigForWebhook
(
w
webhook
.
WebhookAccessor
)
webhookutil
.
ClientConfig
{
if
w
.
ClientConfig
.
URL
!=
nil
{
ret
:=
webhookutil
.
ClientConfig
{
Name
:
w
.
GetName
(),
CABundle
:
w
.
GetClientConfig
()
.
CABundle
}
ret
.
URL
=
*
w
.
ClientConfig
.
URL
if
w
.
GetClientConfig
()
.
URL
!=
nil
{
ret
.
URL
=
*
w
.
GetClientConfig
()
.
URL
}
}
if
w
.
ClientConfig
.
Service
!=
nil
{
if
w
.
GetClientConfig
()
.
Service
!=
nil
{
ret
.
Service
=
&
webhook
.
ClientConfigService
{
ret
.
Service
=
&
webhook
util
.
ClientConfigService
{
Name
:
w
.
ClientConfig
.
Service
.
Name
,
Name
:
w
.
GetClientConfig
()
.
Service
.
Name
,
Namespace
:
w
.
ClientConfig
.
Service
.
Namespace
,
Namespace
:
w
.
GetClientConfig
()
.
Service
.
Namespace
,
}
}
if
w
.
ClientConfig
.
Service
.
Port
!=
nil
{
if
w
.
GetClientConfig
()
.
Service
.
Port
!=
nil
{
ret
.
Service
.
Port
=
*
w
.
ClientConfig
.
Service
.
Port
ret
.
Service
.
Port
=
*
w
.
GetClientConfig
()
.
Service
.
Port
}
else
{
}
else
{
ret
.
Service
.
Port
=
443
ret
.
Service
.
Port
=
443
}
}
if
w
.
ClientConfig
.
Service
.
Path
!=
nil
{
if
w
.
GetClientConfig
()
.
Service
.
Path
!=
nil
{
ret
.
Service
.
Path
=
*
w
.
ClientConfig
.
Service
.
Path
ret
.
Service
.
Path
=
*
w
.
GetClientConfig
()
.
Service
.
Path
}
}
}
}
return
ret
return
ret
}
}
// HasAdmissionReviewVersion check whether a version is accepted by a given webhook.
// HasAdmissionReviewVersion check whether a version is accepted by a given webhook.
func
HasAdmissionReviewVersion
(
a
string
,
w
*
v1beta1
.
Webhook
)
bool
{
func
HasAdmissionReviewVersion
(
a
string
,
w
webhook
.
WebhookAccessor
)
bool
{
for
_
,
b
:=
range
w
.
AdmissionReviewVersions
{
for
_
,
b
:=
range
w
.
GetAdmissionReviewVersions
()
{
if
b
==
a
{
if
b
==
a
{
return
true
return
true
}
}
...
...
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/dispatcher.go
View file @
55ecc454
...
@@ -22,8 +22,6 @@ import (
...
@@ -22,8 +22,6 @@ import (
"sync"
"sync"
"time"
"time"
"k8s.io/klog"
admissionv1beta1
"k8s.io/api/admission/v1beta1"
admissionv1beta1
"k8s.io/api/admission/v1beta1"
"k8s.io/api/admissionregistration/v1beta1"
"k8s.io/api/admissionregistration/v1beta1"
apierrors
"k8s.io/apimachinery/pkg/api/errors"
apierrors
"k8s.io/apimachinery/pkg/api/errors"
...
@@ -35,14 +33,15 @@ import (
...
@@ -35,14 +33,15 @@ import (
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/apiserver/pkg/admission/plugin/webhook/request"
"k8s.io/apiserver/pkg/admission/plugin/webhook/request"
"k8s.io/apiserver/pkg/admission/plugin/webhook/util"
"k8s.io/apiserver/pkg/admission/plugin/webhook/util"
"k8s.io/apiserver/pkg/util/webhook"
webhookutil
"k8s.io/apiserver/pkg/util/webhook"
"k8s.io/klog"
)
)
type
validatingDispatcher
struct
{
type
validatingDispatcher
struct
{
cm
*
webhook
.
ClientManager
cm
*
webhook
util
.
ClientManager
}
}
func
newValidatingDispatcher
(
cm
*
webhook
.
ClientManager
)
generic
.
Dispatcher
{
func
newValidatingDispatcher
(
cm
*
webhook
util
.
ClientManager
)
generic
.
Dispatcher
{
return
&
validatingDispatcher
{
cm
}
return
&
validatingDispatcher
{
cm
}
}
}
...
@@ -69,18 +68,21 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attr
...
@@ -69,18 +68,21 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attr
for
i
:=
range
relevantHooks
{
for
i
:=
range
relevantHooks
{
go
func
(
invocation
*
generic
.
WebhookInvocation
)
{
go
func
(
invocation
*
generic
.
WebhookInvocation
)
{
defer
wg
.
Done
()
defer
wg
.
Done
()
hook
:=
invocation
.
Webhook
hook
,
ok
:=
invocation
.
Webhook
.
GetValidatingWebhook
()
if
!
ok
{
utilruntime
.
HandleError
(
fmt
.
Errorf
(
"validating webhook dispatch requires v1beta1.ValidatingWebhook, but got %T"
,
hook
))
return
}
versionedAttr
:=
versionedAttrs
[
invocation
.
Kind
]
versionedAttr
:=
versionedAttrs
[
invocation
.
Kind
]
t
:=
time
.
Now
()
t
:=
time
.
Now
()
err
:=
d
.
callHook
(
ctx
,
invocation
,
versionedAttr
)
err
:=
d
.
callHook
(
ctx
,
hook
,
invocation
,
versionedAttr
)
admissionmetrics
.
Metrics
.
ObserveWebhook
(
time
.
Since
(
t
),
err
!=
nil
,
versionedAttr
.
Attributes
,
"validating"
,
hook
.
Name
)
admissionmetrics
.
Metrics
.
ObserveWebhook
(
time
.
Since
(
t
),
err
!=
nil
,
versionedAttr
.
Attributes
,
"validating"
,
hook
.
Name
)
if
err
==
nil
{
if
err
==
nil
{
return
return
}
}
ignoreClientCallFailures
:=
hook
.
FailurePolicy
!=
nil
&&
*
hook
.
FailurePolicy
==
v1beta1
.
Ignore
ignoreClientCallFailures
:=
hook
.
FailurePolicy
!=
nil
&&
*
hook
.
FailurePolicy
==
v1beta1
.
Ignore
if
callErr
,
ok
:=
err
.
(
*
webhook
.
ErrCallingWebhook
);
ok
{
if
callErr
,
ok
:=
err
.
(
*
webhook
util
.
ErrCallingWebhook
);
ok
{
if
ignoreClientCallFailures
{
if
ignoreClientCallFailures
{
klog
.
Warningf
(
"Failed calling webhook, failing open %v: %v"
,
hook
.
Name
,
callErr
)
klog
.
Warningf
(
"Failed calling webhook, failing open %v: %v"
,
hook
.
Name
,
callErr
)
utilruntime
.
HandleError
(
callErr
)
utilruntime
.
HandleError
(
callErr
)
...
@@ -115,11 +117,10 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attr
...
@@ -115,11 +117,10 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr admission.Attr
return
errs
[
0
]
return
errs
[
0
]
}
}
func
(
d
*
validatingDispatcher
)
callHook
(
ctx
context
.
Context
,
invocation
*
generic
.
WebhookInvocation
,
attr
*
generic
.
VersionedAttributes
)
error
{
func
(
d
*
validatingDispatcher
)
callHook
(
ctx
context
.
Context
,
h
*
v1beta1
.
ValidatingWebhook
,
invocation
*
generic
.
WebhookInvocation
,
attr
*
generic
.
VersionedAttributes
)
error
{
h
:=
invocation
.
Webhook
if
attr
.
Attributes
.
IsDryRun
()
{
if
attr
.
Attributes
.
IsDryRun
()
{
if
h
.
SideEffects
==
nil
{
if
h
.
SideEffects
==
nil
{
return
&
webhook
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
fmt
.
Errorf
(
"Webhook SideEffects is nil"
)}
return
&
webhook
util
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
fmt
.
Errorf
(
"Webhook SideEffects is nil"
)}
}
}
if
!
(
*
h
.
SideEffects
==
v1beta1
.
SideEffectClassNone
||
*
h
.
SideEffects
==
v1beta1
.
SideEffectClassNoneOnDryRun
)
{
if
!
(
*
h
.
SideEffects
==
v1beta1
.
SideEffectClassNone
||
*
h
.
SideEffects
==
v1beta1
.
SideEffectClassNoneOnDryRun
)
{
return
webhookerrors
.
NewDryRunUnsupportedErr
(
h
.
Name
)
return
webhookerrors
.
NewDryRunUnsupportedErr
(
h
.
Name
)
...
@@ -128,15 +129,15 @@ func (d *validatingDispatcher) callHook(ctx context.Context, invocation *generic
...
@@ -128,15 +129,15 @@ func (d *validatingDispatcher) callHook(ctx context.Context, invocation *generic
// Currently dispatcher only supports `v1beta1` AdmissionReview
// Currently dispatcher only supports `v1beta1` AdmissionReview
// TODO: Make the dispatcher capable of sending multiple AdmissionReview versions
// TODO: Make the dispatcher capable of sending multiple AdmissionReview versions
if
!
util
.
HasAdmissionReviewVersion
(
v1beta1
.
SchemeGroupVersion
.
Version
,
h
)
{
if
!
util
.
HasAdmissionReviewVersion
(
v1beta1
.
SchemeGroupVersion
.
Version
,
invocation
.
Webhook
)
{
return
&
webhook
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
fmt
.
Errorf
(
"webhook does not accept v1beta1 AdmissionReviewRequest"
)}
return
&
webhook
util
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
fmt
.
Errorf
(
"webhook does not accept v1beta1 AdmissionReviewRequest"
)}
}
}
// Make the webhook request
// Make the webhook request
request
:=
request
.
CreateAdmissionReview
(
attr
,
invocation
)
request
:=
request
.
CreateAdmissionReview
(
attr
,
invocation
)
client
,
err
:=
d
.
cm
.
HookClient
(
util
.
HookClientConfigForWebhook
(
h
))
client
,
err
:=
d
.
cm
.
HookClient
(
util
.
HookClientConfigForWebhook
(
invocation
.
Webhook
))
if
err
!=
nil
{
if
err
!=
nil
{
return
&
webhook
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
err
}
return
&
webhook
util
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
err
}
}
}
response
:=
&
admissionv1beta1
.
AdmissionReview
{}
response
:=
&
admissionv1beta1
.
AdmissionReview
{}
r
:=
client
.
Post
()
.
Context
(
ctx
)
.
Body
(
&
request
)
r
:=
client
.
Post
()
.
Context
(
ctx
)
.
Body
(
&
request
)
...
@@ -144,11 +145,11 @@ func (d *validatingDispatcher) callHook(ctx context.Context, invocation *generic
...
@@ -144,11 +145,11 @@ func (d *validatingDispatcher) callHook(ctx context.Context, invocation *generic
r
=
r
.
Timeout
(
time
.
Duration
(
*
h
.
TimeoutSeconds
)
*
time
.
Second
)
r
=
r
.
Timeout
(
time
.
Duration
(
*
h
.
TimeoutSeconds
)
*
time
.
Second
)
}
}
if
err
:=
r
.
Do
()
.
Into
(
response
);
err
!=
nil
{
if
err
:=
r
.
Do
()
.
Into
(
response
);
err
!=
nil
{
return
&
webhook
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
err
}
return
&
webhook
util
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
err
}
}
}
if
response
.
Response
==
nil
{
if
response
.
Response
==
nil
{
return
&
webhook
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
fmt
.
Errorf
(
"Webhook response was absent"
)}
return
&
webhook
util
.
ErrCallingWebhook
{
WebhookName
:
h
.
Name
,
Reason
:
fmt
.
Errorf
(
"Webhook response was absent"
)}
}
}
for
k
,
v
:=
range
response
.
Response
.
AuditAnnotations
{
for
k
,
v
:=
range
response
.
Response
.
AuditAnnotations
{
key
:=
h
.
Name
+
"/"
+
k
key
:=
h
.
Name
+
"/"
+
k
...
...
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin_test.go
View file @
55ecc454
...
@@ -51,7 +51,7 @@ func TestValidate(t *testing.T) {
...
@@ -51,7 +51,7 @@ func TestValidate(t *testing.T) {
}
}
ns
:=
"webhook-test"
ns
:=
"webhook-test"
client
,
informer
:=
webhooktesting
.
NewFake
DataSource
(
ns
,
tt
.
Webhooks
,
false
,
stopCh
)
client
,
informer
:=
webhooktesting
.
NewFake
ValidatingDataSource
(
ns
,
tt
.
Webhooks
,
stopCh
)
wh
.
SetAuthenticationInfoResolverWrapper
(
webhooktesting
.
Wrapper
(
webhooktesting
.
NewAuthenticationInfoResolver
(
new
(
int32
))))
wh
.
SetAuthenticationInfoResolverWrapper
(
webhooktesting
.
Wrapper
(
webhooktesting
.
NewAuthenticationInfoResolver
(
new
(
int32
))))
wh
.
SetServiceResolver
(
webhooktesting
.
NewServiceResolver
(
*
serverURL
))
wh
.
SetServiceResolver
(
webhooktesting
.
NewServiceResolver
(
*
serverURL
))
...
@@ -116,7 +116,7 @@ func TestValidateCachedClient(t *testing.T) {
...
@@ -116,7 +116,7 @@ func TestValidateCachedClient(t *testing.T) {
for
_
,
tt
:=
range
webhooktesting
.
NewCachedClientTestcases
(
serverURL
)
{
for
_
,
tt
:=
range
webhooktesting
.
NewCachedClientTestcases
(
serverURL
)
{
ns
:=
"webhook-test"
ns
:=
"webhook-test"
client
,
informer
:=
webhooktesting
.
NewFake
DataSource
(
ns
,
tt
.
Webhooks
,
false
,
stopCh
)
client
,
informer
:=
webhooktesting
.
NewFake
ValidatingDataSource
(
ns
,
tt
.
Webhooks
,
stopCh
)
// override the webhook source. The client cache will stay the same.
// override the webhook source. The client cache will stay the same.
cacheMisses
:=
new
(
int32
)
cacheMisses
:=
new
(
int32
)
...
...
test/e2e/apimachinery/webhook.go
View file @
55ecc454
...
@@ -436,7 +436,7 @@ func registerWebhook(f *framework.Framework, context *certContext) func() {
...
@@ -436,7 +436,7 @@ func registerWebhook(f *framework.Framework, context *certContext) func() {
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
configName
,
Name
:
configName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Validating
Webhook
{
{
{
Name
:
"deny-unwanted-pod-container-name-and-label.k8s.io"
,
Name
:
"deny-unwanted-pod-container-name-and-label.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -517,7 +517,7 @@ func registerWebhookForAttachingPod(f *framework.Framework, context *certContext
...
@@ -517,7 +517,7 @@ func registerWebhookForAttachingPod(f *framework.Framework, context *certContext
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
configName
,
Name
:
configName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Validating
Webhook
{
{
{
Name
:
"deny-attaching-pod.k8s.io"
,
Name
:
"deny-attaching-pod.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -561,7 +561,7 @@ func registerMutatingWebhookForConfigMap(f *framework.Framework, context *certCo
...
@@ -561,7 +561,7 @@ func registerMutatingWebhookForConfigMap(f *framework.Framework, context *certCo
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
configName
,
Name
:
configName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Mutating
Webhook
{
{
{
Name
:
"adding-configmap-data-stage-1.k8s.io"
,
Name
:
"adding-configmap-data-stage-1.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -638,7 +638,7 @@ func registerMutatingWebhookForPod(f *framework.Framework, context *certContext)
...
@@ -638,7 +638,7 @@ func registerMutatingWebhookForPod(f *framework.Framework, context *certContext)
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
configName
,
Name
:
configName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Mutating
Webhook
{
{
{
Name
:
"adding-init-container.k8s.io"
,
Name
:
"adding-init-container.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -841,8 +841,8 @@ func testAttachingPodWebhook(f *framework.Framework) {
...
@@ -841,8 +841,8 @@ func testAttachingPodWebhook(f *framework.Framework) {
// failingWebhook returns a webhook with rule of create configmaps,
// failingWebhook returns a webhook with rule of create configmaps,
// but with an invalid client config so that server cannot communicate with it
// but with an invalid client config so that server cannot communicate with it
func
failingWebhook
(
namespace
,
name
string
)
v1beta1
.
Webhook
{
func
failingWebhook
(
namespace
,
name
string
)
v1beta1
.
Validating
Webhook
{
return
v1beta1
.
Webhook
{
return
v1beta1
.
Validating
Webhook
{
Name
:
name
,
Name
:
name
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Operations
:
[]
v1beta1
.
OperationType
{
v1beta1
.
Create
},
Operations
:
[]
v1beta1
.
OperationType
{
v1beta1
.
Create
},
...
@@ -889,7 +889,7 @@ func registerFailClosedWebhook(f *framework.Framework, context *certContext) fun
...
@@ -889,7 +889,7 @@ func registerFailClosedWebhook(f *framework.Framework, context *certContext) fun
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
configName
,
Name
:
configName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Validating
Webhook
{
// Server cannot talk to this webhook, so it always fails.
// Server cannot talk to this webhook, so it always fails.
// Because this webhook is configured fail-closed, request should be rejected after the call fails.
// Because this webhook is configured fail-closed, request should be rejected after the call fails.
hook
,
hook
,
...
@@ -945,7 +945,7 @@ func registerValidatingWebhookForWebhookConfigurations(f *framework.Framework, c
...
@@ -945,7 +945,7 @@ func registerValidatingWebhookForWebhookConfigurations(f *framework.Framework, c
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
configName
,
Name
:
configName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Validating
Webhook
{
{
{
Name
:
"deny-webhook-configuration-deletions.k8s.io"
,
Name
:
"deny-webhook-configuration-deletions.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -998,7 +998,7 @@ func registerMutatingWebhookForWebhookConfigurations(f *framework.Framework, con
...
@@ -998,7 +998,7 @@ func registerMutatingWebhookForWebhookConfigurations(f *framework.Framework, con
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
configName
,
Name
:
configName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Mutating
Webhook
{
{
{
Name
:
"add-label-to-webhook-configurations.k8s.io"
,
Name
:
"add-label-to-webhook-configurations.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -1050,7 +1050,7 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) {
...
@@ -1050,7 +1050,7 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) {
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
dummyValidatingWebhookConfigName
,
Name
:
dummyValidatingWebhookConfigName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Validating
Webhook
{
{
{
Name
:
"dummy-validating-webhook.k8s.io"
,
Name
:
"dummy-validating-webhook.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -1098,7 +1098,7 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) {
...
@@ -1098,7 +1098,7 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) {
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
dummyMutatingWebhookConfigName
,
Name
:
dummyMutatingWebhookConfigName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Mutating
Webhook
{
{
{
Name
:
"dummy-mutating-webhook.k8s.io"
,
Name
:
"dummy-mutating-webhook.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -1306,7 +1306,7 @@ func registerWebhookForCustomResource(f *framework.Framework, context *certConte
...
@@ -1306,7 +1306,7 @@ func registerWebhookForCustomResource(f *framework.Framework, context *certConte
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
configName
,
Name
:
configName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Validating
Webhook
{
{
{
Name
:
"deny-unwanted-custom-resource-data.k8s.io"
,
Name
:
"deny-unwanted-custom-resource-data.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -1348,7 +1348,7 @@ func registerMutatingWebhookForCustomResource(f *framework.Framework, context *c
...
@@ -1348,7 +1348,7 @@ func registerMutatingWebhookForCustomResource(f *framework.Framework, context *c
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
configName
,
Name
:
configName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Mutating
Webhook
{
{
{
Name
:
"mutate-custom-resource-data-stage-1.k8s.io"
,
Name
:
"mutate-custom-resource-data-stage-1.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -1543,7 +1543,7 @@ func registerValidatingWebhookForCRD(f *framework.Framework, context *certContex
...
@@ -1543,7 +1543,7 @@ func registerValidatingWebhookForCRD(f *framework.Framework, context *certContex
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
configName
,
Name
:
configName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Validating
Webhook
{
{
{
Name
:
"deny-crd-with-unwanted-label.k8s.io"
,
Name
:
"deny-crd-with-unwanted-label.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
@@ -1649,7 +1649,7 @@ func registerSlowWebhook(f *framework.Framework, context *certContext, policy *v
...
@@ -1649,7 +1649,7 @@ func registerSlowWebhook(f *framework.Framework, context *certContext, policy *v
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
configName
,
Name
:
configName
,
},
},
Webhooks
:
[]
v1beta1
.
Webhook
{
Webhooks
:
[]
v1beta1
.
Validating
Webhook
{
{
{
Name
:
"allow-configmap-with-delay-webhook.k8s.io"
,
Name
:
"allow-configmap-with-delay-webhook.k8s.io"
,
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
Rules
:
[]
v1beta1
.
RuleWithOperations
{{
...
...
test/integration/apiserver/admissionwebhook/admission_test.go
View file @
55ecc454
...
@@ -283,6 +283,9 @@ func (h *holder) record(phase string, converted bool, request *v1beta1.Admission
...
@@ -283,6 +283,9 @@ func (h *holder) record(phase string, converted bool, request *v1beta1.Admission
return
return
}
}
if
debug
{
h
.
t
.
Logf
(
"recording: %#v = %s %#v %v"
,
webhookOptions
{
phase
:
phase
,
converted
:
converted
},
request
.
Operation
,
request
.
Resource
,
request
.
SubResource
)
}
h
.
recorded
[
webhookOptions
{
phase
:
phase
,
converted
:
converted
}]
=
request
h
.
recorded
[
webhookOptions
{
phase
:
phase
,
converted
:
converted
}]
=
request
}
}
...
@@ -1287,7 +1290,7 @@ func createV1beta1ValidationWebhook(client clientset.Interface, endpoint, conver
...
@@ -1287,7 +1290,7 @@ func createV1beta1ValidationWebhook(client clientset.Interface, endpoint, conver
// Attaching Admission webhook to API server
// Attaching Admission webhook to API server
_
,
err
:=
client
.
AdmissionregistrationV1beta1
()
.
ValidatingWebhookConfigurations
()
.
Create
(
&
admissionv1beta1
.
ValidatingWebhookConfiguration
{
_
,
err
:=
client
.
AdmissionregistrationV1beta1
()
.
ValidatingWebhookConfigurations
()
.
Create
(
&
admissionv1beta1
.
ValidatingWebhookConfiguration
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"admission.integration.test"
},
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"admission.integration.test"
},
Webhooks
:
[]
admissionv1beta1
.
Webhook
{
Webhooks
:
[]
admissionv1beta1
.
Validating
Webhook
{
{
{
Name
:
"admission.integration.test"
,
Name
:
"admission.integration.test"
,
ClientConfig
:
admissionv1beta1
.
WebhookClientConfig
{
ClientConfig
:
admissionv1beta1
.
WebhookClientConfig
{
...
@@ -1323,7 +1326,7 @@ func createV1beta1MutationWebhook(client clientset.Interface, endpoint, converte
...
@@ -1323,7 +1326,7 @@ func createV1beta1MutationWebhook(client clientset.Interface, endpoint, converte
// Attaching Mutation webhook to API server
// Attaching Mutation webhook to API server
_
,
err
:=
client
.
AdmissionregistrationV1beta1
()
.
MutatingWebhookConfigurations
()
.
Create
(
&
admissionv1beta1
.
MutatingWebhookConfiguration
{
_
,
err
:=
client
.
AdmissionregistrationV1beta1
()
.
MutatingWebhookConfigurations
()
.
Create
(
&
admissionv1beta1
.
MutatingWebhookConfiguration
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"mutation.integration.test"
},
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"mutation.integration.test"
},
Webhooks
:
[]
admissionv1beta1
.
Webhook
{
Webhooks
:
[]
admissionv1beta1
.
Mutating
Webhook
{
{
{
Name
:
"mutation.integration.test"
,
Name
:
"mutation.integration.test"
,
ClientConfig
:
admissionv1beta1
.
WebhookClientConfig
{
ClientConfig
:
admissionv1beta1
.
WebhookClientConfig
{
...
...
test/integration/apiserver/admissionwebhook/broken_webhook_test.go
View file @
55ecc454
...
@@ -155,7 +155,7 @@ func brokenWebhookConfig(name string) *admissionregistrationv1beta1.ValidatingWe
...
@@ -155,7 +155,7 @@ func brokenWebhookConfig(name string) *admissionregistrationv1beta1.ValidatingWe
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
name
,
Name
:
name
,
},
},
Webhooks
:
[]
admissionregistrationv1beta1
.
Webhook
{
Webhooks
:
[]
admissionregistrationv1beta1
.
Validating
Webhook
{
{
{
Name
:
"broken-webhook.k8s.io"
,
Name
:
"broken-webhook.k8s.io"
,
Rules
:
[]
admissionregistrationv1beta1
.
RuleWithOperations
{{
Rules
:
[]
admissionregistrationv1beta1
.
RuleWithOperations
{{
...
...
test/integration/examples/webhook_test.go
View file @
55ecc454
...
@@ -22,7 +22,7 @@ import (
...
@@ -22,7 +22,7 @@ import (
"time"
"time"
admissionv1beta1
"k8s.io/api/admissionregistration/v1beta1"
admissionv1beta1
"k8s.io/api/admissionregistration/v1beta1"
"k8s.io/api/core/v1"
v1
"k8s.io/api/core/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/util/wait"
auditinternal
"k8s.io/apiserver/pkg/apis/audit"
auditinternal
"k8s.io/apiserver/pkg/apis/audit"
...
@@ -65,7 +65,7 @@ func TestWebhookLoopback(t *testing.T) {
...
@@ -65,7 +65,7 @@ func TestWebhookLoopback(t *testing.T) {
fail
:=
admissionv1beta1
.
Fail
fail
:=
admissionv1beta1
.
Fail
_
,
err
:=
client
.
AdmissionregistrationV1beta1
()
.
MutatingWebhookConfigurations
()
.
Create
(
&
admissionv1beta1
.
MutatingWebhookConfiguration
{
_
,
err
:=
client
.
AdmissionregistrationV1beta1
()
.
MutatingWebhookConfigurations
()
.
Create
(
&
admissionv1beta1
.
MutatingWebhookConfiguration
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"webhooktest.example.com"
},
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"webhooktest.example.com"
},
Webhooks
:
[]
admissionv1beta1
.
Webhook
{{
Webhooks
:
[]
admissionv1beta1
.
Mutating
Webhook
{{
Name
:
"webhooktest.example.com"
,
Name
:
"webhooktest.example.com"
,
ClientConfig
:
admissionv1beta1
.
WebhookClientConfig
{
ClientConfig
:
admissionv1beta1
.
WebhookClientConfig
{
Service
:
&
admissionv1beta1
.
ServiceReference
{
Namespace
:
"default"
,
Name
:
"kubernetes"
,
Path
:
&
webhookPath
},
Service
:
&
admissionv1beta1
.
ServiceReference
{
Namespace
:
"default"
,
Name
:
"kubernetes"
,
Path
:
&
webhookPath
},
...
...
vendor/modules.txt
View file @
55ecc454
...
@@ -1184,6 +1184,7 @@ k8s.io/apiserver/pkg/admission/configuration
...
@@ -1184,6 +1184,7 @@ k8s.io/apiserver/pkg/admission/configuration
k8s.io/apiserver/pkg/admission/initializer
k8s.io/apiserver/pkg/admission/initializer
k8s.io/apiserver/pkg/admission/metrics
k8s.io/apiserver/pkg/admission/metrics
k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle
k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle
k8s.io/apiserver/pkg/admission/plugin/webhook
k8s.io/apiserver/pkg/admission/plugin/webhook/config
k8s.io/apiserver/pkg/admission/plugin/webhook/config
k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission
k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission
k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1
k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1
...
...
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