Skip to content

Adding ObjectSelector to admission webhooks#78226

Closed
caesarxuchao wants to merge 8 commits intokubernetes:masterfrom
caesarxuchao:object-selector-admission-webhook
Closed

Adding ObjectSelector to admission webhooks#78226
caesarxuchao wants to merge 8 commits intokubernetes:masterfrom
caesarxuchao:object-selector-admission-webhook

Conversation

@caesarxuchao
Copy link
Copy Markdown
Contributor

@caesarxuchao caesarxuchao commented May 23, 2019

/assign
/sig api-machinery

Implementing KEP#objectSelector.

I only implemented it for the main resource. The behavior for subresources is undefined.

I added to the admission webhook integration test to make sure webhooks are called if labels matches the object selector. The test also makes sure in-flight label changes made by the mutation webhooks are not counted when compared to the object selector.

TODO:

  1. update the API doc to warn people that the objectSelector should only be used for opt-in webhooks.

I still need to do some code cleanup, so marked as WIP. cc @liggitt @jpbetz @roycaihw

Added object selector to admission webhook configurations.
The object selector applies to an object's labels. For CREATE and UPDATE, the object is the new object. For DELETE, it is existing object (passed as oldObject in the admissionRequest).
Admission behavior for subresources with non-empty object selector is undefined currently.
Use the object selector only if the webhook is opt-in, because end users may skip the admission webhook by setting the labels.

@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-priority Indicates a PR lacks a `priority/foo` label and requires one. labels May 23, 2019
@caesarxuchao caesarxuchao changed the title Adding ObjectSelector to admission webhooks [WIP] Adding ObjectSelector to admission webhooks May 23, 2019
@k8s-ci-robot k8s-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 23, 2019
@k8s-ci-robot k8s-ci-robot added area/apiserver area/test kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API sig/auth Categorizes an issue or PR as relevant to SIG Auth. sig/testing Categorizes an issue or PR as relevant to SIG Testing. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed needs-kind Indicates a PR lacks a `kind/foo` label and requires one. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels May 23, 2019
@caesarxuchao caesarxuchao force-pushed the object-selector-admission-webhook branch from 252773a to 13ef626 Compare May 23, 2019 22:14
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes to the patch handler are complicated. I need to extract the labels after the patch is applied to the existing object, but before the running the mutation webhooks (applyAdmission), and pass the labels to the validation webhooks (encapsuled in createValidation and updateValidation). I used the *ctx.LabelsHolder to pass the labels.

@caesarxuchao caesarxuchao force-pushed the object-selector-admission-webhook branch from 13ef626 to c2558a1 Compare May 23, 2019 23:44
@k8s-ci-robot k8s-ci-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels May 23, 2019
@caesarxuchao caesarxuchao force-pushed the object-selector-admission-webhook branch from 59426bd to 32297f4 Compare May 24, 2019 00:13
@caesarxuchao caesarxuchao changed the title [WIP] Adding ObjectSelector to admission webhooks Adding ObjectSelector to admission webhooks May 24, 2019
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 24, 2019
@caesarxuchao
Copy link
Copy Markdown
Contributor Author

/assign @jpbetz @liggitt
/unassign

I can still clean up the integration test more, but I want to get some early feedback. Thank you.

@k8s-ci-robot k8s-ci-robot assigned jpbetz and unassigned caesarxuchao May 24, 2019
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in what cases do we allow error?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extensions/v1beta1/deployments/rollback does not implement the Object interface. That seems to be the only exceptions.

I updated the update.go to return NewInternalError if meta.Accessor() fails.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks safe. Log an error if it ever does happen just so we're not entirely silent about the error?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the returning error behavior here different from other verbs?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems that the update doesn't tolerate modified object. I got the following flake locally:

--- FAIL: TestWebhookV1beta1/apiextensions.k8s.io.v1beta1.customresourcedefinitions/delete (0.35s)
            admission_test.go:608: Operation cannot be fulfilled on customresourcedefinitions.apiextensions.k8s.io "openshiftwebconsoleconfigs.webconsole.operator.openshift.io": the object has been modified; please apply your changes to the latest version and try again

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I'll update the code.

@caesarxuchao
Copy link
Copy Markdown
Contributor Author

I believe that the flake I encountered was due to the watch cache. The object in watch cache contains already removed labels, thus the request was dispatched to wrong webhooks.

Chao Xu added 6 commits May 24, 2019 16:37
It verifies that object selector is respected.
It verifies that labels added by the mutation webhooks are not affecting
object selector decision in the same round of admission.
if the obj does not implement the Object interface. The only exception
is the CREATE handler, as extension/v1beta1/deployments/rollback does
not implement the interface.
@caesarxuchao caesarxuchao force-pushed the object-selector-admission-webhook branch from 9cf4343 to 3264ace Compare May 25, 2019 00:04
@caesarxuchao
Copy link
Copy Markdown
Contributor Author

/retest

Integration test failure not related.

@k8s-ci-robot
Copy link
Copy Markdown
Contributor

k8s-ci-robot commented May 25, 2019

@caesarxuchao: The following test failed, say /retest to rerun them all:

Test name Commit Details Rerun command
pull-kubernetes-verify 3264ace link /test pull-kubernetes-verify

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

// object (passed as oldObject in the admissionRequest).
// Admission behavior for subresources with non-empty object selector
// is undefined currently.
// Use the object selector only if the webhook is opt-in, because end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to allowing users to opt-in to a webhook, labels also make it possible to ensure that all objects with a particular label have been admitted by the webhooks for that label.

type Matcher struct {
}

// MatchObjectSelector decideds whether the request matches the ObjectSelector
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/decideds/decides

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks safe. Log an error if it ever does happen just so we're not entirely silent about the error?

if !ok {
return nil, errors.NewInternalError(fmt.Errorf("expect labelsHolder set in context"))
}
labelsHolder.SetLabels(labels)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment here summarizing why/how labels are messaged via the context? Seems like we should comment about that somewhere..

// users may skip the admission webhook by setting the labels.
// Default to the empty LabelSelector, which matches everything.
// +optional
ObjectSelector *metav1.LabelSelector
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not ObjectLabelSelector ?

// UPDATE, the object is the new object. For DELETE, it is existing
// object (passed as oldObject in the admissionRequest).
// Admission behavior for subresources with non-empty object selector
// is undefined currently.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we define it?

dryRun: dryRun,
object: object,
oldObject: oldObject,
labels: labels,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need labels globally throughout the code base and not only in the webhooks. This looks wrong. Please move that logic into the webhook.

}

type mutateObjectUpdateFunc func(obj, old runtime.Object) error
type mutateObjectUpdateFunc func(ctx context.Context, obj, old runtime.Object) error
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this change?

@sttts
Copy link
Copy Markdown
Contributor

sttts commented May 27, 2019

I am not happy about the ripples of the change. I am against merging it in this way.

/hold

@k8s-ci-robot k8s-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label May 27, 2019
@sttts sttts self-assigned this May 27, 2019
@liggitt liggitt added this to the v1.15 milestone May 29, 2019
@caesarxuchao
Copy link
Copy Markdown
Contributor Author

caesarxuchao commented May 29, 2019

The requirement of extracting labels "at the admission time before running any plugins and will be used for all webhooks during the admission process" makes the implementation complicated. Especially for PATCH operations, I needed to extract the labels after the patch is applied, but before applying the mutation webhooks in this line, thus I used context to hold and pass the labels.

One alternative I had considered was letting the mutation webhook controller extract the labels. The drawbacks are:

  1. built-in admission plugins can change object labels (e.g., storage/pv/label/admission)
  2. it doesn't work for subresources. According to the KEP, sometimes we need to extract the labels from the parent object, which is not accessible by the mutation webhook controller.

@sttts

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 29, 2019
@k8s-ci-robot
Copy link
Copy Markdown
Contributor

@caesarxuchao: PR needs rebase.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@liggitt
Copy link
Copy Markdown
Member

liggitt commented May 29, 2019

Talked through the various issues with @sttts, @caesarxuchao, @jpbetz, and @roycaihw. most of the difficulties with this implementation came from the original behavior specified in the KEP, which in retrospect led to very counter-intuitive behavior from an end-user's perspective.

The updated behavior we landed on (which is much easier to explain and to implement... double win):

To determine whether the objectSelector matches given admission attributes:

  • An empty objectSelector always matches
  • A non-empty objectSelector is evaluated against both the oldObject and newObject that would be sent to the webhook, and is considered to match if either object matches the selector. A null object (for example, oldObject in the case of create, or newObject in the case of delete) or an object that cannot have labels (like a DeploymentRollback object) is not considered to match.

@sttts
Copy link
Copy Markdown
Contributor

sttts commented May 29, 2019

I very much prefer what @liggitt suggests in #78226 (comment). Feel free to unhold the PR with such an implementation.

@caesarxuchao
Copy link
Copy Markdown
Contributor Author

Superseded by #78505

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/admission-control area/apiserver area/test cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API needs-priority Indicates a PR lacks a `priority/foo` label and requires one. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. sig/auth Categorizes an issue or PR as relevant to SIG Auth. sig/testing Categorizes an issue or PR as relevant to SIG Testing. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants