-
Notifications
You must be signed in to change notification settings - Fork 39.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add namespace selector to admission webhook #54727
Add namespace selector to admission webhook #54727
Conversation
/retest |
31c2b58
to
fb1ea5a
Compare
fb1ea5a
to
b6d075f
Compare
// TestAdmit tests that GenericAdmissionWebhook#Admit works as expected | ||
func TestAdmit(t *testing.T) { | ||
scheme := runtime.NewScheme() | ||
v1alpha1.AddToScheme(scheme) | ||
api.AddToScheme(scheme) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that "api" was just an inappropriate alias.
de768ee
to
75730c5
Compare
if err != nil { | ||
return false, apierrors.NewInternalError(err) | ||
} | ||
namespace, err := a.namespaceLister.Get(namespaceName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Admittedly, the cache namespace can be stale. We tolerate the delay in other plugins like podtolerationrestriction, so I think it's ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
caesarxuchao 20 hours ago Member
Admittedly, the cache namespace can be stale. We tolerate the delay in other plugins like podtolerationrestriction, so I think it's ok.
Agree
@@ -165,6 +165,32 @@ type ExternalAdmissionHook struct { | |||
// allowed values are Ignore or Fail. Defaults to Ignore. | |||
// +optional | |||
FailurePolicy *FailurePolicyType | |||
|
|||
// Selects namespaces that are subjected to this webhook. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably reword this. It might be better to be slightly repetitive with the description so it is clear that it applies to both selectors. Something like "Selects whether to run the webhook on an object based on whether the namespace for that object is/is not labeled with the associated key and the values equals any of the provided values. To run the webhook on any object whose namespace was not associated with 'runlevel' of '0' or '1'; you would set the selector as follows."
"If instead you wanted to only run the the webhook on any objects whose namespace was associated with the 'environment' of 'prod' or 'staging'; you would set the selector as follows."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whether the namespace for that object is/is not labeled with the associated key and the values equals any of the provided values.
This is not accurate, because selector also supports operations like "if key exists/not exists".
I'll just say "whether the namespace for that object matches the selector".
Also, is it intentional to use the past tense?
Updated the comments in types.go, PTAL. Thank you.
// matching, so you can use this selector as a whitelist or a blacklist. | ||
// For example, to apply the webhook to all namespaces except for those have | ||
// labels with key "runlevel" and value equal to "0" or "1": | ||
// metav1.LabelSelctor{MatchExpressions: []LabelSelectorRequirement{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
metav1.LabelSelector
// }} | ||
// As another example, to only apply the webhook to the namespaces that have | ||
// labels with key "environment" and value equal to "prod" or "staging": | ||
// metav1.LabelSelctor{MatchExpressions: []LabelSelectorRequirement{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
metav1.LabelSelector
a.namespaceLister = namespaceInformer.Lister() | ||
a.SetReadyFunc(namespaceInformer.Informer().HasSynced) | ||
} | ||
|
||
// Validator holds Validate functions, which are responsible for validation of initialized shared resources | ||
// and should be implemented on admission plugins | ||
func (a *GenericAdmissionWebhook) Validate() error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add requirement for namespace lister.
// whether the namespace is exempted from the webhook. | ||
func (a *GenericAdmissionWebhook) exemptNamespace(h *v1alpha1.ExternalAdmissionHook, attr admission.Attributes) (bool, error) { | ||
namespaceName := attr.GetNamespace() | ||
if namespaceName == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
len(namespaceName) == 0
namespaceName := attr.GetNamespace() | ||
if namespaceName == "" { | ||
// if the request is root scoped, it is not exempted. | ||
return false, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a neat side-effect. A downed admission plugin could prevent the node that would run the admission webhook from running.
I don't think we need to resolve it for beta, but given the switch to a DNS name, perhaps admission plugins that can mess with nodes should be hosted in a way that allows off cluster access.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be solved with the run level concept, like by reserving some nodes for run level 0 items.
@@ -246,7 +259,42 @@ func (a *GenericAdmissionWebhook) Admit(attr admission.Attributes) error { | |||
return errs[0] | |||
} | |||
|
|||
// whether the namespace is exempted from the webhook. | |||
func (a *GenericAdmissionWebhook) exemptNamespace(h *v1alpha1.ExternalAdmissionHook, attr admission.Attributes) (bool, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this fail when it restricts namespaces and I'm trying to create a namespace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I updated the code to use the labels of the namespace object itself if the attr.Object
is a namespace.
if err != nil && !apierrors.IsNotFound(err) { | ||
return false, apierrors.NewInternalError(err) | ||
} | ||
if err != nil && apierrors.IsNotFound(err) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just need if apierrors.IsNotFound(err)
test/images/webhook/main.go
Outdated
@@ -115,12 +157,20 @@ func serve(w http.ResponseWriter, r *http.Request) { | |||
} | |||
} | |||
|
|||
func servePods(w http.ResponseWriter, r *http.Request) { | |||
serve(w, r, "pods") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe pass the function rather than a resource name. You would then get to lose the switch above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
7bcda79
to
1aad3a6
Compare
@cheftako comments addressed. PTAL. Thank you. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: caesarxuchao, cheftako, lavalamp No associated issue. Update pull-request body to add a reference to an issue, or get approval with The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
Applying the approval label based on #54727 (comment). |
1aad3a6
to
7ac8a38
Compare
7ac8a38
to
3e19bcd
Compare
Adding back the lgtm after rebase. |
business logic in webhook plugin and unit test add a e2e test for namespace selector
3e19bcd
to
2f83748
Compare
Rebased again. |
/retest |
/test all [submit-queue is verifying that this PR is safe to merge] |
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions here. |
Implementing the design.
cc @kubernetes/sig-api-machinery-api-reviews