Skip to content

Commit

Permalink
Fix custom defaulter from deleting unknown fields
Browse files Browse the repository at this point in the history
  • Loading branch information
alculquicondor authored and trasc committed Oct 14, 2024
1 parent 5af6ffa commit 13c4991
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
20 changes: 14 additions & 6 deletions pkg/webhook/admission/defaulter_custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,24 +71,32 @@ func (h *defaulterForType) Handle(ctx context.Context, req Request) Response {
ctx = NewContextWithRequest(ctx, req)

// Get the object in the request
obj := h.object.DeepCopyObject()
if err := h.decoder.Decode(req, obj); err != nil {
original := h.object.DeepCopyObject()
if err := h.decoder.Decode(req, original); err != nil {
return Errored(http.StatusBadRequest, err)
}

// Default the object
if err := h.defaulter.Default(ctx, obj); err != nil {
updated := original.DeepCopyObject()
if err := h.defaulter.Default(ctx, updated); err != nil {
var apiStatus apierrors.APIStatus
if errors.As(err, &apiStatus) {
return validationResponseFromStatus(false, apiStatus.Status())
}
return Denied(err.Error())
}

// Create the patch
marshalled, err := json.Marshal(obj)
// Create the patch.
// We need to decode and marshall the original because the type registered in the
// decoder might not match the latest version of the API.
// Creating a diff from the raw object might cause new fields to be dropped.
marshalledOriginal, err := json.Marshal(original)
if err != nil {
return Errored(http.StatusInternalServerError, err)
}
return PatchResponseFromRaw(req.Object.Raw, marshalled)
marshalledUpdated, err := json.Marshal(updated)
if err != nil {
return Errored(http.StatusInternalServerError, err)
}
return PatchResponseFromRaw(marshalledOriginal, marshalledUpdated)
}
22 changes: 22 additions & 0 deletions pkg/webhook/admission/defaulter_custom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"gomodules.xyz/jsonpatch/v2"

admissionv1 "k8s.io/api/admission/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand All @@ -28,6 +29,27 @@ import (

var _ = Describe("Defaulter Handler", func() {

It("should should not lose unknown fields", func() {
obj := &TestDefaulter{}
handler := WithCustomDefaulter(admissionScheme, obj, &TestCustomDefaulter{})

resp := handler.Handle(context.TODO(), Request{
AdmissionRequest: admissionv1.AdmissionRequest{
Operation: admissionv1.Create,
Object: runtime.RawExtension{
Raw: []byte(`{"newField":"foo"}`),
},
},
})
Expect(resp.Allowed).Should(BeTrue())
Expect(resp.Patches).To(Equal([]jsonpatch.JsonPatchOperation{{
Operation: "add",
Path: "/replica",
Value: 2.0,
}}))
Expect(resp.Result.Code).Should(Equal(int32(http.StatusOK)))
})

It("should return ok if received delete verb in defaulter handler", func() {
obj := &TestDefaulter{}
handler := WithCustomDefaulter(admissionScheme, obj, &TestCustomDefaulter{})
Expand Down

0 comments on commit 13c4991

Please sign in to comment.