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

✨ crd conversion webhook implementation #351

Merged

Conversation

droot
Copy link
Contributor

@droot droot commented Mar 6, 2019

This PR implements CRD Conversion Webhook handler.

The design has been documented here.

Note:
Need to add more tests. I am in process of converting the design doc in markdown format (doc link shared above)

@droot droot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Mar 6, 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 Mar 6, 2019
@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 6, 2019
@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Mar 6, 2019
@droot droot removed approved Indicates a PR has been approved by an approver from all required OWNERS files. 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. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Mar 6, 2019
@droot droot requested a review from mengqiy March 6, 2019 17:58
@k8s-ci-robot k8s-ci-robot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Mar 6, 2019
@droot
Copy link
Contributor Author

droot commented Mar 7, 2019

/cc @shawn-hurley @JoelSpeed

@k8s-ci-robot
Copy link
Contributor

@droot: GitHub didn't allow me to request PR reviews from the following users: shawn-hurley, JoelSpeed.

Note that only kubernetes-sigs members and repo collaborators can review this PR, and authors cannot review their own PRs.

In response to this:

/cc @shawn-hurley @JoelSpeed

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.

Copy link
Contributor

@JoelSpeed JoelSpeed left a comment

Choose a reason for hiding this comment

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

I've taken a read over the design and over the implementation and left a few comments

I'm so glad you've started work on this @droot as I need to bump a kubebuilder API version soon and need this 😅 Let me know if there's any way I can help with this

}
}

// neigher src nor dst are Hub, means both of them are spoke, so lets get the hub
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo here

Suggested change
// neigher src nor dst are Hub, means both of them are spoke, so lets get the hub
// neither src nor dst are Hub, means both of them are spoke, so lets get the hub

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

if err != nil {
return err
}
// shall we get Hub for dst type as well and ensure hubs are same ?
Copy link
Contributor

Choose a reason for hiding this comment

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

Commented on the design doc but I think this is probably work doing, the current result, if I've read this properly, is that err = dst.(conversion.Convertible).ConvertFrom(hub) will result in an error later down (approx failed to convert from hub version: unsupported type) which may not be immediately obvious as to what the problem is, WDYT?

Might be worth making this a TODO?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a check at the beginning of the function to ensure both src and dst belong to same API group to ensure src/dst have same hub type.

// v2.ExternalJob is the storage version so mark this as Hub
// Storage version doesn't need to implement any conversion methods because
// default conversionHandler implements conversion logic for storage version.
// Adding comment annotation here to mark it as storage version
Copy link
Contributor

Choose a reason for hiding this comment

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

Annotation not set yet?


// since v1.ExternalJob is a spoke, it needs to be convertable.
// It needs to implement convert to/from storage version
// TODO(droot): evaluate advantages of taking `conversion.Hub` as input to
Copy link
Contributor

Choose a reason for hiding this comment

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

My 2 cents on this is that the current design has two ways to indicate that a type is the storage version, the annotation and this conversion.Hub, I would imagine it would be very easy to forget to do one. Is there a good way to remove one of the two?

I had kinda expected ConvertTo and ConvertFrom to take a runtime.Object initially but I concluded that it's probably a disadvantage as you lose some compile time checks theoretically

Copy link
Contributor Author

@droot droot Mar 13, 2019

Choose a reason for hiding this comment

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

Is there a good way to remove one of the two?

Annotations (we have started calling them markers now because annotation/tags are so overloaded in k8s world :)) is primarily needed for controller-gen to generate the manifests for conversion webhook. Only way to remove them would be to make controller-gen parse these types and examine if they implement these methods (which can be done, but is a bit stretch looking at current state of the code in controller-gen). Till then, this is the only option.

I had kinda expected ConvertTo and ConvertFrom to take a runtime.Object initially but I concluded that it's probably a disadvantage as you lose some compile time checks theoretically

Agreed. using Hub has type-safety as well readability from an end-user's perspective. So will took out that TODO.

@shawn-hurley
Copy link

@droot did I miss how someone could move to a new hub version? It was not immediately clear to me how this would work.

I think the overall simplification of the concept is really nice! I need to read through the code still but the design doc is really good!

Sent with GitHawk

@DirectXMan12
Copy link
Contributor

@shawn-hurley I've never seen something that wasn't a little bit painful, but the process here would basically be:

  1. Mark the new type as hub with the interface
  2. Unmark the old type
  3. Migrate your ConvertTo and ConvertFrom methods to the new hub
  4. Add new conversions for your old hub

While this is a bit of a pain, it's not more painful (in my experience) that the k/k method, which, from my experience with HPA v2, looks a lot like:

  1. Update the internal version to have a convenient representation for supporting the new external version
  2. Generate the new generated conversions
  3. Realize that the internal version looks a lot like the new external version, so now you need to rewrite your existing conversions to work with the new internal version
  4. Write conversions for the old external version that used to look a lot like the internal version
  5. (bonus round) realize that the new internal version needs to be slightly different from the external version for some reason (maybe it makes round-tripping a lot easier), so now you have to write conversions for your new external version too.

Now, that's not a high bar, but I also don't see a good way to make things better without supporting arbitrary conversion graphs and gradually growing a strange web of conversions.

pkg/conversion/conversion.go Show resolved Hide resolved
@@ -0,0 +1,249 @@
/*
Copyright 2018 The Kubernetes Authors.
Copy link
Contributor

Choose a reason for hiding this comment

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

It isn't 2018 :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed :)

@droot droot force-pushed the feature/crd-conversion-webhook branch from a095ab3 to c56ac5b Compare March 13, 2019 19:58
@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Mar 13, 2019
@droot
Copy link
Contributor Author

droot commented Mar 13, 2019

@JoelSpeed

I'm so glad you've started work on this @droot as I need to bump a kubebuilder API version soon and need this 😅 Let me know if there's any way I can help with this

Awesome. Thanks for reviewing the PR. Usability feedback will be super important and I am glad that you will be using it your project, so keep us posted from end-user's perspective. Have addressed the comments and added a few more tests.

@droot
Copy link
Contributor Author

droot commented Mar 13, 2019

@shawn-hurley

@droot did I miss how someone could move to a new hub version? It was not immediately clear to me how this would work.

Pretty much along the lines as @DirectXMan12 described above. I will add those to the design doc.

@droot droot force-pushed the feature/crd-conversion-webhook branch 2 times, most recently from 9c4ac2f to c5be062 Compare March 13, 2019 20:52
var hub conversion.Hub
var isHub, hubFoundAlready bool
for _, gvk := range gvks {
o, _ := wh.scheme.New(gvk)
Copy link
Member

Choose a reason for hiding this comment

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

The error should be checked here. If the gvk is not registered in the scheme, scheme.New will return an error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good pt. Added catch.

}

// Decode decodes the inlined object.
func (d *Decoder) Decode(content []byte) (runtime.Object, *schema.GroupVersionKind, error) {
Copy link
Member

Choose a reason for hiding this comment

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

I feel we can move the decoder in admission pkg to a shared the place and reuse it potentially.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a TODO for now. I am sure conversion pkg will evolve as it goes to Beta and we can reevaluate it at that point.

Copy link
Contributor

Choose a reason for hiding this comment

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

not convinced we need this at all (see above comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, @DirectXMan12 is right. We don't need the decoder for conversionRequest now, we only need for processing the objects embedded in the the request.

func errored(err error) *apix.ConversionResponse {
return &apix.ConversionResponse{
Result: metav1.Status{
Code: http.StatusOK,
Copy link
Member

Choose a reason for hiding this comment

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

It seems to be wrong here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, tool it out.

return
}

// TODO(droot): may be move the conversion logic to a separate module to
Copy link
Member

Choose a reason for hiding this comment

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

IMO it's a good idea and align with what admission package. It may look like

func (wh *Webhook) ServeConvert(req ConversionRequest, resp ConversionResponse) {
  // Do something
}

func (wh *Webhook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  // Decoding http request to get ConversionRequest

  // Do conversion
  wh.ServeConvert(convReq, convResp)

  // Write the conversion response to http.ResponseWriter
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I want to keep this as TODO for now and revisit later. The good thing it can be done as internal refactoring later.

@droot droot force-pushed the feature/crd-conversion-webhook branch from c5be062 to 90b9818 Compare March 25, 2019 19:18
Copy link
Contributor Author

@droot droot left a comment

Choose a reason for hiding this comment

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

Thanks for the review @mengqiy. Addressed some comments. PTAL.

return
}

// TODO(droot): may be move the conversion logic to a separate module to
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I want to keep this as TODO for now and revisit later. The good thing it can be done as internal refactoring later.

var hub conversion.Hub
var isHub, hubFoundAlready bool
for _, gvk := range gvks {
o, _ := wh.scheme.New(gvk)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good pt. Added catch.

}

// Decode decodes the inlined object.
func (d *Decoder) Decode(content []byte) (runtime.Object, *schema.GroupVersionKind, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a TODO for now. I am sure conversion pkg will evolve as it goes to Beta and we can reevaluate it at that point.

func errored(err error) *apix.ConversionResponse {
return &apix.ConversionResponse{
Result: metav1.Status{
Code: http.StatusOK,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, tool it out.

@droot
Copy link
Contributor Author

droot commented Mar 25, 2019

/cc @mbohlool

@k8s-ci-robot
Copy link
Contributor

@droot: GitHub didn't allow me to request PR reviews from the following users: mbohlool.

Note that only kubernetes-sigs members and repo collaborators can review this PR, and authors cannot review their own PRs.

In response to this:

/cc @mbohlool

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.

@droot droot force-pushed the feature/crd-conversion-webhook branch 2 times, most recently from 785e79e to 3b9e1e1 Compare March 25, 2019 19:45
@droot droot changed the title WIP ✨ crd conversion webhook implementation ✨ crd conversion webhook implementation Mar 25, 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 Mar 25, 2019
@droot
Copy link
Contributor Author

droot commented Mar 25, 2019

@mbohlool @mengqiy @JoelSpeed This is good to go from my perspective. I think this is a good starting point to get feedback for the CRD conversion feature.

Copy link
Member

@mengqiy mengqiy left a comment

Choose a reason for hiding this comment

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

Code LGTM. I'm OK having some TODOs and revisit them later.

"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/conversion"

"encoding/json"
Copy link
Member

Choose a reason for hiding this comment

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

nit: please group the imports.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


func TestConversionWebhook(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecsWithDefaultAndCustomReporters(t, "application Suite", []Reporter{envtest.NewlineReporter{}})
Copy link
Member

Choose a reason for hiding this comment

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

application Suite

maybe conversion suite?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


It("should convert objects successfully", func() {

v1Obj := &jobsv1.ExternalJob{
Copy link
Member

Choose a reason for hiding this comment

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

v1Obj is used in all test cases and is static. It can extract out of It and put it in BeforeEach or others.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I know it looks more verbose in current form, but it makes the test more readable from perspective of input and output and expectations.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd just move it to outside, or at least make a helper -- it'll make it way easier to refactor later.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Made a helper for this one because recently added objects using one of the core resource (Deployment).

Copy link

@shawn-hurley shawn-hurley left a comment

Choose a reason for hiding this comment

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

Wonder if it would make sense to add tests testing the src and dest are not convertible or if src is the hub and if dest is the hub and make sure each happy path is covered?

@droot droot force-pushed the feature/crd-conversion-webhook branch from 3b9e1e1 to d88c13b Compare March 28, 2019 18:54
@droot
Copy link
Contributor Author

droot commented Mar 28, 2019

Wonder if it would make sense to add tests testing the src and dest are not convertible or if src is the hub and if dest is the hub and make sure each happy path is covered?

I just added a test to cover the case where hub is not defined. One test which is missing now is (spoke-to-spoke conversion), I will have to define a two API group under testData to do that.

limitations under the License.
*/

package conversion
Copy link
Contributor

Choose a reason for hiding this comment

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

Godocs on the package

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

ConvertFrom(src Hub) error
}

// Hub defines capability to indicate whether a versioned type is a Hub or not.
Copy link
Contributor

Choose a reason for hiding this comment

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

This sentence is a bit awkward in its construction -- I'd go with Hub marks that a given type is the hub type for conversion. This means that all conversions will first convert to the hub type, then convert from the hub type to the destination type. All types besides the hub type should implement Convertible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the suggestion, that reads much better.

limitations under the License.
*/

package conversion
Copy link
Contributor

Choose a reason for hiding this comment

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

godocs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

)

var (
log = logf.Log.WithName("conversion_webhook")
Copy link
Contributor

Choose a reason for hiding this comment

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

hyphens instead of underscores, generally

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

return err
}

// inject the decoder here too, just in case the order of calling this is not
Copy link
Contributor

Choose a reason for hiding this comment

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

??

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not needed, so took it out.


convReview := doRequest(convReq)

Expect(convReview.Response.ConvertedObjects).Should(HaveLen(1))
Copy link
Contributor

Choose a reason for hiding this comment

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

Expect().To (more idiomatic)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, reads better. Done

}

convReview := doRequest(convReq)
Expect(convReview.Response.Result.Message).Should(
Copy link
Contributor

Choose a reason for hiding this comment

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

blech. I hate directly checking error message strings. Can't we just check codes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Need to explore a bit more, but in general I agree checking error messages is bad.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I explored bit more about using codes here, couldn't find an easy way to do it at this level which is conversionRequest/Response level. At this level, we can only indicate status and failure message (which contains the reason for failure). I removed reason string checking here because that makes the tests brittle.

}

// Decode decodes the inlined object.
func (d *Decoder) Decode(content []byte) (runtime.Object, *schema.GroupVersionKind, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

not convinced we need this at all (see above comment)

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func errored(err error) *apix.ConversionResponse {
Copy link
Contributor

Choose a reason for hiding this comment

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

just move this into the other file where it's used, probably

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, killed the file.

@@ -0,0 +1,25 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

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

move this under example/ (or just use example/), just to be certain we don't cause import issues

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Copy link
Contributor Author

@droot droot left a comment

Choose a reason for hiding this comment

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

Thanks for the review @DirectXMan12 . Addressed the comments. PTAL.
I have addressed the comments in a separate commit for making it easier to review. I am putting it on hold so that I can squash the commits before the merge.

ConvertFrom(src Hub) error
}

// Hub defines capability to indicate whether a versioned type is a Hub or not.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the suggestion, that reads much better.

)

var (
log = logf.Log.WithName("conversion_webhook")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

return err
}

// inject the decoder here too, just in case the order of calling this is not
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not needed, so took it out.

convertReview := &apix.ConversionReview{}
// TODO(droot): figure out if we want to split decoder for conversion
// request from the objects contained in the request
err = wh.decoder.DecodeInto(body, convertReview)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, you are right. Thanks for pointing out, this has simplified the code even further.

srcGVK := src.GetObjectKind().GroupVersionKind()
dstGVK := dst.GetObjectKind().GroupVersionKind()

if srcGVK.GroupKind().String() != dstGVK.GroupKind().String() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, you are right :)

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func errored(err error) *apix.ConversionResponse {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, killed the file.

@@ -0,0 +1,25 @@
/*
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

limitations under the License.
*/

package conversion
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

limitations under the License.
*/

package conversion
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

}

convReview := doRequest(convReq)
Expect(convReview.Response.Result.Message).Should(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Need to explore a bit more, but in general I agree checking error messages is bad.

@droot droot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Apr 1, 2019
@droot droot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Apr 22, 2019
@droot droot force-pushed the feature/crd-conversion-webhook branch from 4cac767 to 7cf7a99 Compare April 23, 2019 18:08
Copy link
Contributor Author

@droot droot left a comment

Choose a reason for hiding this comment

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

@DirectXMan12 I think this is good to go. PTAL a look.

}

convReview := doRequest(convReq)
Expect(convReview.Response.Result.Message).Should(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I explored bit more about using codes here, couldn't find an easy way to do it at this level which is conversionRequest/Response level. At this level, we can only indicate status and failure message (which contains the reason for failure). I removed reason string checking here because that makes the tests brittle.

Copy link
Contributor

@DirectXMan12 DirectXMan12 left a comment

Choose a reason for hiding this comment

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

/lgtm
/approve

just tackle the nits in a follow-up -- they're not functionally blocking


// allocateDstObject returns an instance for a given GVK.
func (wh *Webhook) allocateDstObject(apiVersion, kind string) (runtime.Object, error) {
gvk := schema.FromAPIVersionAndKind(apiVersion, kind)
Copy link
Contributor

Choose a reason for hiding this comment

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

could put this in a sync.Once, or something. We can tackle in a follow-up

}

scheme = kscheme.Scheme
Expect(jobsapis.AddToScheme(scheme)).Should(Succeed())
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Expect().To

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 8, 2019
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: DirectXMan12, droot

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 merged commit faa41bc into kubernetes-sigs:master May 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. 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.

None yet

7 participants