-
Notifications
You must be signed in to change notification settings - Fork 1.3k
🐛 fake client support scale subresource get/update for unstructured objects #3546
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
Changes from all commits
ee613fa
8d6841f
358acb9
e663f79
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,7 @@ import ( | |
| "k8s.io/apimachinery/pkg/runtime/schema" | ||
| "k8s.io/apimachinery/pkg/runtime/serializer" | ||
| "k8s.io/apimachinery/pkg/types" | ||
| "k8s.io/apimachinery/pkg/util/rand" | ||
| "k8s.io/apimachinery/pkg/util/sets" | ||
| "k8s.io/apimachinery/pkg/watch" | ||
| clientgoapplyconfigurations "k8s.io/client-go/applyconfigurations" | ||
|
|
@@ -54,6 +55,7 @@ import ( | |
|
|
||
| "sigs.k8s.io/controller-runtime/pkg/client" | ||
| "sigs.k8s.io/controller-runtime/pkg/client/interceptor" | ||
| "sigs.k8s.io/randfill" | ||
| ) | ||
|
|
||
| const ( | ||
|
|
@@ -2624,6 +2626,109 @@ var _ = Describe("Fake client", func() { | |
| Expect(cl.SubResource(subResourceScale).Get(ctx, obj, scale).Error()).To(Equal(expectedErr)) | ||
| Expect(cl.SubResource(subResourceScale).Update(ctx, obj, client.WithSubResourceBody(scale)).Error()).To(Equal(expectedErr)) | ||
| }) | ||
| It("supports scale subresources on unstructured objects with spec.replicas", func(ctx SpecContext) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we please add a test using https://github.com/kubernetes-sigs/randfill that asserts consistent behavior between the structured/unstructured representations by doing something like:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That makes a lot of sense. Before I proceed, would it be preferable to add this as a separate test or refactor the existing unstructured scale test to cover the structured/unstructured parity scenario? |
||
| obj := &unstructured.Unstructured{Object: map[string]any{ | ||
| "apiVersion": "apps/v1", | ||
| "kind": "Deployment", | ||
| "metadata": map[string]any{ | ||
| "name": "foo", | ||
| "namespace": "default", | ||
| }, | ||
| "spec": map[string]any{ | ||
| "replicas": int64(1), | ||
| }, | ||
| "status": map[string]any{ | ||
| "replicas": int64(1), | ||
| }, | ||
| }} | ||
| cl := NewClientBuilder().WithScheme(runtime.NewScheme()).WithObjects(obj).Build() | ||
|
|
||
| scale := &autoscalingv1.Scale{} | ||
| Expect(cl.SubResource(subResourceScale).Get(ctx, obj, scale)).To(Succeed()) | ||
| Expect(scale.Spec.Replicas).To(Equal(int32(1))) | ||
| Expect(scale.Status.Replicas).To(Equal(int32(1))) | ||
|
|
||
| scale.Spec.Replicas = 3 | ||
| Expect(cl.SubResource(subResourceScale).Update(ctx, obj, client.WithSubResourceBody(scale))).To(Succeed()) | ||
|
|
||
| updated := &unstructured.Unstructured{} | ||
| updated.SetAPIVersion("apps/v1") | ||
| updated.SetKind("Deployment") | ||
| updated.SetName("foo") | ||
| updated.SetNamespace("default") | ||
| Expect(cl.Get(ctx, client.ObjectKeyFromObject(updated), updated)).To(Succeed()) | ||
| replicas, found, err := unstructured.NestedInt64(updated.Object, "spec", "replicas") | ||
| Expect(err).NotTo(HaveOccurred()) | ||
| Expect(found).To(BeTrue()) | ||
| Expect(int32(replicas)).To(Equal(int32(3))) | ||
| }) | ||
|
|
||
| It("structured and unstructured scale subresources behave consistently", func(ctx SpecContext) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test looks good, but you need to run the fuzzing in a loop, a single iteration is not very likely to catch issues. Something simple like |
||
| seed := time.Now().UnixMicro() | ||
| GinkgoWriter.Printf("seed: %d\n", seed) | ||
| fuzzer := randfill.NewWithSeed(seed).Funcs( | ||
| func(d *appsv1.Deployment, c randfill.Continue) { | ||
| var replicas, statusReplicas int32 | ||
| c.Fill(&replicas) | ||
| c.Fill(&statusReplicas) | ||
| d.TypeMeta = metav1.TypeMeta{APIVersion: "apps/v1", Kind: "Deployment"} | ||
| d.ObjectMeta = metav1.ObjectMeta{Name: "scale-" + rand.String(8), Namespace: "default"} | ||
| d.Spec.Replicas = &replicas | ||
| d.Status.Replicas = statusReplicas | ||
| }, | ||
| func(scale *autoscalingv1.Scale, c randfill.Continue) { | ||
| c.Fill(&scale.Spec.Replicas) | ||
| }, | ||
| ) | ||
|
|
||
| for range 100 { | ||
| dep := &appsv1.Deployment{} | ||
| fuzzer.Fill(dep) | ||
|
|
||
| unstrMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(dep) | ||
| Expect(err).NotTo(HaveOccurred()) | ||
| unstr := &unstructured.Unstructured{Object: unstrMap} | ||
| unstr.SetAPIVersion("apps/v1") | ||
| unstr.SetKind("Deployment") | ||
|
|
||
| structuredCl := NewClientBuilder().WithObjects(dep.DeepCopy()).Build() | ||
| unstructuredCl := NewClientBuilder().WithScheme(runtime.NewScheme()).WithObjects(unstr.DeepCopy()).Build() | ||
|
|
||
| depKey := dep.DeepCopy() | ||
| unstrKey := &unstructured.Unstructured{} | ||
| unstrKey.SetAPIVersion("apps/v1") | ||
| unstrKey.SetKind("Deployment") | ||
| unstrKey.SetName(dep.Name) | ||
| unstrKey.SetNamespace(dep.Namespace) | ||
|
|
||
| scaleTyped, scaleUnstr := &autoscalingv1.Scale{}, &autoscalingv1.Scale{} | ||
| Expect(structuredCl.SubResource(subResourceScale).Get(ctx, depKey, scaleTyped)).To(Succeed()) | ||
| Expect(unstructuredCl.SubResource(subResourceScale).Get(ctx, unstrKey, scaleUnstr)).To(Succeed()) | ||
| Expect(scaleTyped.Spec.Replicas).To(Equal(scaleUnstr.Spec.Replicas)) | ||
| Expect(scaleTyped.Status.Replicas).To(Equal(scaleUnstr.Status.Replicas)) | ||
|
|
||
| updateScale := &autoscalingv1.Scale{} | ||
| fuzzer.Fill(updateScale) | ||
| Expect(structuredCl.SubResource(subResourceScale).Update(ctx, depKey, client.WithSubResourceBody(updateScale.DeepCopy()))).To(Succeed()) | ||
| Expect(unstructuredCl.SubResource(subResourceScale).Update(ctx, unstrKey, client.WithSubResourceBody(updateScale.DeepCopy()))).To(Succeed()) | ||
|
|
||
| Expect(structuredCl.Get(ctx, client.ObjectKeyFromObject(dep), depKey)).To(Succeed()) | ||
| Expect(depKey.Spec.Replicas).NotTo(BeNil()) | ||
| Expect(*depKey.Spec.Replicas).To(Equal(updateScale.Spec.Replicas)) | ||
|
|
||
| Expect(unstructuredCl.Get(ctx, client.ObjectKeyFromObject(dep), unstrKey)).To(Succeed()) | ||
| replicas, found, err := unstructured.NestedInt64(unstrKey.Object, "spec", "replicas") | ||
| Expect(err).NotTo(HaveOccurred()) | ||
| Expect(found).To(BeTrue()) | ||
| Expect(int32(replicas)).To(Equal(updateScale.Spec.Replicas)) | ||
|
|
||
| scaleTyped, scaleUnstr = &autoscalingv1.Scale{}, &autoscalingv1.Scale{} | ||
| Expect(structuredCl.SubResource(subResourceScale).Get(ctx, depKey, scaleTyped)).To(Succeed()) | ||
| Expect(unstructuredCl.SubResource(subResourceScale).Get(ctx, unstrKey, scaleUnstr)).To(Succeed()) | ||
| Expect(scaleTyped.Spec.Replicas).To(Equal(scaleUnstr.Spec.Replicas)) | ||
| Expect(scaleTyped.Spec.Replicas).To(Equal(updateScale.Spec.Replicas)) | ||
| } | ||
| }) | ||
|
|
||
| It("disallows scale subresources on non-existing objects", func(ctx SpecContext) { | ||
| obj := &appsv1.Deployment{ | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.