Skip to content
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

[WIP] Fix Webhooks wrongly handling CRD conversion #73839

Closed
wants to merge 2 commits into from

Conversation

mbohlool
Copy link
Contributor

@mbohlool mbohlool commented Feb 8, 2019

APIServer uses a converter to convert the object to external version before sending it to the Mutating or Validation webhook. The converter was a static scheme converter that understands buildin types but not CRDs. This change uses the RequestScope object converter and creator instead which allows both standard types and CRDs to work properly.

fixes #73752

@parhamdoustdar @liggitt this is still work in progress. I need to find a way to add a test for this. I may not also catch all of the changes required for this. Just sending this early to see if you guys have any suggestion about the way I am fixing it.

@k8s-ci-robot
Copy link
Contributor

@mbohlool: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it.

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.

@k8s-ci-robot k8s-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. 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 Feb 8, 2019
@k8s-ci-robot
Copy link
Contributor

@mbohlool: PR needs rebase.

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.

@k8s-ci-robot k8s-ci-robot added needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. needs-priority Indicates a PR lacks a `priority/foo` label and requires one. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Feb 8, 2019
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: mbohlool
To fully approve this pull request, please assign additional approvers.
We suggest the following additional approver: deads2k

If they are not already assigned, you can assign the PR to them by writing /assign @deads2k in a comment when ready.

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added area/apiserver 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. and removed needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. labels Feb 8, 2019
@k8s-ci-robot
Copy link
Contributor

@mbohlool: The following tests failed, say /retest to rerun them all:

Test name Commit Details Rerun command
pull-kubernetes-bazel-test 4fef5ae link /test pull-kubernetes-bazel-test
pull-kubernetes-bazel-build 4fef5ae link /test pull-kubernetes-bazel-build
pull-kubernetes-e2e-gce 4fef5ae link /test pull-kubernetes-e2e-gce
pull-kubernetes-e2e-gce-device-plugin-gpu 4fef5ae link /test pull-kubernetes-e2e-gce-device-plugin-gpu
pull-kubernetes-node-e2e 4fef5ae link /test pull-kubernetes-node-e2e
pull-kubernetes-kubemark-e2e-gce-big 4fef5ae link /test pull-kubernetes-kubemark-e2e-gce-big
pull-kubernetes-typecheck 4fef5ae link /test pull-kubernetes-typecheck
pull-kubernetes-integration 4fef5ae link /test pull-kubernetes-integration
pull-kubernetes-e2e-gce-100-performance 4fef5ae link /test pull-kubernetes-e2e-gce-100-performance
pull-kubernetes-godeps 4fef5ae link /test pull-kubernetes-godeps
pull-kubernetes-verify 4fef5ae 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.

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.

@@ -69,7 +69,6 @@ func NewMutatingWebhook(configFile io.Reader) (*Plugin, error) {

// SetScheme sets a serializer(NegotiatedSerializer) which is derived from the scheme
func (a *Plugin) SetScheme(scheme *runtime.Scheme) {
a.Webhook.SetScheme(scheme)
if scheme != nil {
a.scheme = scheme
Copy link
Member

Choose a reason for hiding this comment

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

what do we use this scheme for now? I'd expect it to have similar issues wherever it was used

Copy link
Member

Choose a reason for hiding this comment

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

looks like we special-case unstructured in mutatingDispatcher#callAttrMutatingHook and avoid calling a.scheme.New... plumbing the request ObjectCreator there as well would likely be more correct

GetObjectConverter() runtime.ObjectConvertor

// TODO(mehdy): Doc
GetObjectCreator() runtime.ObjectCreater
Copy link
Member

@liggitt liggitt Feb 8, 2019

Choose a reason for hiding this comment

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

admission uses the defaulter as well:

this seems like it will converge to the set of runtime.Object* interfaces held by request scope over time

Copy link
Contributor Author

@mbohlool mbohlool Feb 11, 2019

Choose a reason for hiding this comment

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

I think a struct of all of these interfaces make more sense as we would need to pass a lot of parameters (and many nils in tests) if we don't do so. Something like a `type ObjectInterfaces struct {'. We can add interfaces to that as needed. Or we can just give access to the RequestScope here. I will read code to see which level of encapsulation make sense here. Recommendations are welcome :)

Copy link
Member

Choose a reason for hiding this comment

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

I think a struct of all of these interfaces make more sense as we would need to pass a lot of parameters (and many nils in tests) if we don't do so. Something like a `type ObjectInterfaces struct {'.

I agree gathering them makes sense.

What if we made the wrapper an interface:

type ObjectInterfaces interface {
	GetObjectCreater() runtime.ObjectCreater
	GetObjectTyper() runtime.ObjectTyper
	GetObjectDefaulter() runtime.ObjectDefaulter
	GetObjectConvertor() runtime.ObjectConvertor
}

which RequestScope could implement:

func (r *RequestScope) GetObjectCreater() runtime.ObjectCreater     { return r.Creater }
func (r *RequestScope) GetObjectTyper() runtime.ObjectTyper         { return r.Typer }
func (r *RequestScope) GetObjectDefaulter() runtime.ObjectDefaulter { return r.Defaulter }
func (r *RequestScope) GetObjectConvertor() runtime.ObjectConvertor { return r.Convertor }

and could be passed alongside attributes to admit/validate methods:

type MutationInterface interface {
	Interface

	// Admit makes an admission decision based on the request attributes
	Admit(a Attributes, i ObjectInterfaces) (err error)
}

// ValidationInterface is an abstract, pluggable interface for Admission Control decisions.
type ValidationInterface interface {
	Interface

	// Validate makes an admission decision based on the request attributes.  It is NOT allowed to mutate
	Validate(a Attributes, i ObjectInterfaces) (err error)
}

that keeps a clearer separation between the attributes being validated and the tools admission can make use of to do the validation

Copy link
Member

@liggitt liggitt Feb 14, 2019

Choose a reason for hiding this comment

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

I'm not thrilled about the signature changes, but I don't think we have any great options:

  • put new items into a separate parameter to Admit/Validate
    • pro: separates data and helpers
    • pro: keeps interface of admission.Attributes the same
    • con: changes interface of Admit/Validate (impacts admission plugin implementers)
  • put new items into admission.Attributes
    • pro: keeps Admit/Validate interfaces the same
    • con: mixes data being validated and helpers used to validate
    • con: changes interface of admission.Attributes (impacts admission plugin implementers)
  • let plugins implement an alternate interface (Admit2, AdmitWithHelpers, etc) for getting called with helpers
    • pro: no interface changes
    • con: wrapping/unioning/chaining/delegation layers make it likely the alternate method would get masked
  • let attributes implement an alternate interface interested admission plugins can attempt to cast it to to extract object helpers
    • pro: no interface changes
    • con: similar issues with attributes wrapping masking the second implemented interface
    • con: this is insane

if err != nil {
return nil, err
}
err = c.Scheme.Convert(obj, out, nil)
err = converter.Convert(obj, out, nil)
Copy link
Member

Choose a reason for hiding this comment

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

also a call here that needs to be switched to the request scope convertor:

// convert attr.VersionedObject to the internal version in the underlying admission.Attributes
if attr.VersionedObject != nil {
return a.plugin.scheme.Convert(attr.VersionedObject, attr.Attributes.GetObject(), nil)
}

@@ -69,7 +69,6 @@ func NewMutatingWebhook(configFile io.Reader) (*Plugin, error) {

// SetScheme sets a serializer(NegotiatedSerializer) which is derived from the scheme
func (a *Plugin) SetScheme(scheme *runtime.Scheme) {
a.Webhook.SetScheme(scheme)
if scheme != nil {
a.scheme = scheme
a.jsonSerializer = json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false)
Copy link
Member

@liggitt liggitt Feb 8, 2019

Choose a reason for hiding this comment

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

and I think we'd need a per-request serializer, which means we need the request-scoped ObjectTyper

@@ -20,12 +20,13 @@ import (
"testing"

"k8s.io/apiserver/pkg/admission"
webhooktesting "k8s.io/apiserver/pkg/admission/plugin/webhook/testing"
Copy link
Member

Choose a reason for hiding this comment

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

making all of these packages take a dependency on webhooktesting seems weird. most admission plugins don't use the Object{Typer,Converter,Defaulter,Creater} attributes... can we just set them to nil in all the test files for admission plugins that don't use them?

@liggitt liggitt added the priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. label Feb 14, 2019
@k8s-ci-robot k8s-ci-robot removed the needs-priority Indicates a PR lacks a `priority/foo` label and requires one. label Feb 14, 2019
@liggitt liggitt self-assigned this Feb 14, 2019
@mbohlool
Copy link
Contributor Author

closing in favor of #74154

@mbohlool mbohlool closed this Feb 16, 2019
@mbohlool mbohlool changed the title [WIP] Fix Webhooks wrongly handling CRD conversion Fix Webhooks wrongly handling CRD conversion Feb 21, 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 Feb 21, 2019
@mbohlool mbohlool changed the title Fix Webhooks wrongly handling CRD conversion [WIP] Fix Webhooks wrongly handling CRD conversion Feb 21, 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 Feb 21, 2019
@liggitt liggitt removed the sig/auth Categorizes an issue or PR as relevant to SIG Auth. label Feb 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/apiserver cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery.
Projects
None yet
3 participants