Skip to content

Commit

Permalink
Fix WithFieldValidation client
Browse files Browse the repository at this point in the history
Signed-off-by: Stefan Büringer [email protected]
  • Loading branch information
sbueringer committed Aug 8, 2024
1 parent e882354 commit 7dfd3bb
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 0 deletions.
127 changes: 127 additions & 0 deletions pkg/client/fieldvalidation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,80 @@ import (
"context"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/client/interceptor"
)

var _ = Describe("ClientWithFieldValidation", func() {
It("should return errors for invalid fields when using strict validation", func() {
cl, err := client.New(cfg, client.Options{})
Expect(err).NotTo(HaveOccurred())
Expect(cl).NotTo(BeNil())

wrappedClient := client.WithFieldValidation(cl, metav1.FieldValidationStrict)
ctx := context.Background()

baseNode := &unstructured.Unstructured{}
baseNode.SetGroupVersionKind(schema.GroupVersionKind{
Group: "",
Kind: "Node",
Version: "v1",
})
baseNode.SetName("client-with-field-validation-test-node")

validNode := baseNode.DeepCopy()
patch := client.MergeFrom(validNode.DeepCopy())

invalidNode := baseNode.DeepCopy()
Expect(unstructured.SetNestedField(invalidNode.Object, "value", "spec", "invalidField")).To(Succeed())

invalidStatusNode := baseNode.DeepCopy()
Expect(unstructured.SetNestedField(invalidStatusNode.Object, "value", "status", "invalidStatusField")).To(Succeed())

err = wrappedClient.Create(ctx, invalidNode)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("strict decoding error: unknown field \"spec.invalidField\""))

err = wrappedClient.Create(ctx, validNode)
Expect(err).ToNot(HaveOccurred())

err = wrappedClient.Update(ctx, invalidNode)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("strict decoding error: unknown field \"spec.invalidField\""))

err = wrappedClient.Patch(ctx, invalidNode, patch)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("strict decoding error: unknown field \"spec.invalidField\""))

// Status.Create is not supported on Nodes

err = wrappedClient.Status().Update(ctx, invalidStatusNode)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("strict decoding error: unknown field \"status.invalidStatusField\""))

err = wrappedClient.Status().Patch(ctx, invalidStatusNode, patch)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("strict decoding error: unknown field \"status.invalidStatusField\""))

// Status.Create is not supported on Nodes

err = wrappedClient.SubResource("status").Update(ctx, invalidStatusNode)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("strict decoding error: unknown field \"status.invalidStatusField\""))

err = wrappedClient.SubResource("status").Patch(ctx, invalidStatusNode, patch)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("strict decoding error: unknown field \"status.invalidStatusField\""))
})
})

func TestWithStrictFieldValidation(t *testing.T) {
calls := 0
fakeClient := testFieldValidationClient(t, metav1.FieldValidationStrict, func() { calls++ })
Expand Down Expand Up @@ -88,6 +155,16 @@ func testFieldValidationClient(t *testing.T, expectedFieldValidation string, cal
if got := out.FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}

if got := out.AsCreateOptions().FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}

co := &client.CreateOptions{}
out.ApplyToCreate(co)
if got := co.FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}
return nil
},
Update: func(ctx context.Context, c client.WithWatch, obj client.Object, opts ...client.UpdateOption) error {
Expand All @@ -99,6 +176,16 @@ func testFieldValidationClient(t *testing.T, expectedFieldValidation string, cal
if got := out.FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}

if got := out.AsUpdateOptions().FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}

co := &client.UpdateOptions{}
out.ApplyToUpdate(co)
if got := co.FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}
return nil
},
Patch: func(ctx context.Context, c client.WithWatch, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
Expand All @@ -110,6 +197,16 @@ func testFieldValidationClient(t *testing.T, expectedFieldValidation string, cal
if got := out.FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}

if got := out.AsPatchOptions().FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}

co := &client.PatchOptions{}
out.ApplyToPatch(co)
if got := co.FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}
return nil
},
SubResourceCreate: func(ctx context.Context, c client.Client, subResourceName string, obj client.Object, subResource client.Object, opts ...client.SubResourceCreateOption) error {
Expand All @@ -121,6 +218,16 @@ func testFieldValidationClient(t *testing.T, expectedFieldValidation string, cal
if got := out.FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}

if got := out.AsCreateOptions().FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}

co := &client.CreateOptions{}
out.ApplyToCreate(co)
if got := co.FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}
return nil
},
SubResourceUpdate: func(ctx context.Context, c client.Client, subResourceName string, obj client.Object, opts ...client.SubResourceUpdateOption) error {
Expand All @@ -132,6 +239,16 @@ func testFieldValidationClient(t *testing.T, expectedFieldValidation string, cal
if got := out.FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}

if got := out.AsUpdateOptions().FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}

co := &client.UpdateOptions{}
out.ApplyToUpdate(co)
if got := co.FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}
return nil
},
SubResourcePatch: func(ctx context.Context, c client.Client, subResourceName string, obj client.Object, patch client.Patch, opts ...client.SubResourcePatchOption) error {
Expand All @@ -143,6 +260,16 @@ func testFieldValidationClient(t *testing.T, expectedFieldValidation string, cal
if got := out.FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}

if got := out.AsPatchOptions().FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}

co := &client.PatchOptions{}
out.ApplyToPatch(co)
if got := co.FieldValidation; expectedFieldValidation != got {
t.Fatalf("wrong field validation: expected=%q; got=%q", expectedFieldValidation, got)
}
return nil
},
}).Build()
Expand Down
12 changes: 12 additions & 0 deletions pkg/client/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ func (o *CreateOptions) AsCreateOptions() *metav1.CreateOptions {

o.Raw.DryRun = o.DryRun
o.Raw.FieldManager = o.FieldManager
o.Raw.FieldValidation = o.FieldValidation
return o.Raw
}

Expand All @@ -274,6 +275,9 @@ func (o *CreateOptions) ApplyToCreate(co *CreateOptions) {
if o.FieldManager != "" {
co.FieldManager = o.FieldManager
}
if o.FieldValidation != "" {
co.FieldValidation = o.FieldValidation
}
if o.Raw != nil {
co.Raw = o.Raw
}
Expand Down Expand Up @@ -764,6 +768,7 @@ func (o *UpdateOptions) AsUpdateOptions() *metav1.UpdateOptions {

o.Raw.DryRun = o.DryRun
o.Raw.FieldManager = o.FieldManager
o.Raw.FieldValidation = o.FieldValidation
return o.Raw
}

Expand All @@ -786,6 +791,9 @@ func (o *UpdateOptions) ApplyToUpdate(uo *UpdateOptions) {
if o.FieldManager != "" {
uo.FieldManager = o.FieldManager
}
if o.FieldValidation != "" {
uo.FieldValidation = o.FieldValidation
}
if o.Raw != nil {
uo.Raw = o.Raw
}
Expand Down Expand Up @@ -858,6 +866,7 @@ func (o *PatchOptions) AsPatchOptions() *metav1.PatchOptions {
o.Raw.DryRun = o.DryRun
o.Raw.Force = o.Force
o.Raw.FieldManager = o.FieldManager
o.Raw.FieldValidation = o.FieldValidation
return o.Raw
}

Expand All @@ -874,6 +883,9 @@ func (o *PatchOptions) ApplyToPatch(po *PatchOptions) {
if o.FieldManager != "" {
po.FieldManager = o.FieldManager
}
if o.FieldValidation != "" {
po.FieldValidation = o.FieldValidation
}
if o.Raw != nil {
po.Raw = o.Raw
}
Expand Down

0 comments on commit 7dfd3bb

Please sign in to comment.