🐛 fake client support scale subresource get/update for unstructured objects - #3546
Conversation
|
Welcome @PullaguraSantosha! |
|
Hi @PullaguraSantosha. Thanks for your PR. I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with Regular contributors should join the org to skip this step. Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. DetailsInstructions 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-sigs/prow repository. |
1d056cc to
cfab02f
Compare
e3ce8de to
9b1a068
Compare
|
Hi @JoelSpeed @inteon — CLA and title are fixed and I updated the branch. Could a maintainer please approve the workflow so CI can run? If it looks ok, please review and add lgtm. Thanks! |
| func extractScale(obj client.Object) (*autoscalingv1.Scale, error) { | ||
| switch obj := obj.(type) { | ||
| case *unstructured.Unstructured: | ||
| replicas, found, err := unstructured.NestedInt64(obj.Object, "spec", "replicas") |
There was a problem hiding this comment.
I don't think this is necessarily correct, for crds its configurable where this is stored. If we do this, we should limit it to API types where we know the specReplicasPath and statusReplicasPath
There was a problem hiding this comment.
Good point — this change is intentionally limited to the conventional unstructured case where spec.replicas and status.replicas are used. I do not mean to claim generic CRD scale support for arbitrary custom specReplicasPath / statusReplicasPath values. If you’d like, I can narrow this further to only known API types or add a TODO noting that fully generic CRD scale support requires CRD metadata.
There was a problem hiding this comment.
this change is intentionally limited to the conventional unstructured case where spec.replicas and status.replicas are used
How, because it will error out otherwise? That seems more like an accident than deliberation. Please limit this to the same types where we also support this with the proper api types
There was a problem hiding this comment.
Updated fake client scale handling for unstructured objects so it only supports known built-in scale resource kinds:
- apps/v1 Deployment
- apps/v1 ReplicaSet
- apps/v1 StatefulSet
- v1 ReplicationController
Added regression coverage for apps/v1 Deployment and preserved the existing unimplemented scale subresource behavior for unsupported unstructured types.
|
/ok-to-test |
| switch obj := obj.(type) { | ||
| case *unstructured.Unstructured: | ||
| if !isUnstructuredScaleResource(obj) { | ||
| return nil, fmt.Errorf("unimplemented scale subresource for resource %T", obj) |
There was a problem hiding this comment.
| return nil, fmt.Errorf("unimplemented scale subresource for resource %T", obj) | |
| return nil, fmt.Errorf("scale subresource for resource %T is not implemented", obj) |
There was a problem hiding this comment.
This one does not seem to be addressed
| switch obj := obj.(type) { | ||
| case *unstructured.Unstructured: | ||
| if !isUnstructuredScaleResource(obj) { | ||
| return fmt.Errorf("unimplemented scale subresource for resource %T", obj) |
There was a problem hiding this comment.
| return fmt.Errorf("unimplemented scale subresource for resource %T", obj) | |
| return fmt.Errorf("scale subresource for resource %T is not implemented", obj) |
| } | ||
| }) | ||
|
|
||
| It("allows explicitly clearing managedFields on Update", func(ctx SpecContext) { |
There was a problem hiding this comment.
What does this have to do with the rest of the PR?
There was a problem hiding this comment.
Thanks for the review and suggestions, @sbueringer.
I updated the error text to: scale subresource for resource %T is not implemented and adjusted the test coverage to use apps/v1 Deployment to match the fake client's restricted unstructured support. I also reverted the unrelated test changes and force-pushed the cleaned commit. Please let me know if you'd prefer different wording or any additional changes.
97f87fe to
80a98e9
Compare
80a98e9 to
b2a90bc
Compare
| if !isUnstructuredScaleResource(obj) { | ||
| return nil, fmt.Errorf("scale subresource for resource %T is not implemented", obj) | ||
| } | ||
| replicas, found, err := unstructured.NestedInt64(obj.Object, "spec", "replicas") |
| return nil, err | ||
| } | ||
| if !found { | ||
| replicas = 0 |
There was a problem hiding this comment.
This gets defaulted to 1, not 0
| return nil, err | ||
| } | ||
| if !statusFound { | ||
| statusReplicas = replicas |
There was a problem hiding this comment.
I don't think this is correct, it should be 0 just like if the field was unset in the typed object
| default: | ||
| // TODO: CRDs https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#scale-subresource | ||
| return fmt.Errorf("unimplemented scale subresource for resource %T", obj) | ||
| return fmt.Errorf("scale subresource for resource %T is not implemented", obj) |
|
@Dasmat13 please refrain from copy pasting LLM output, we can do that ourselves. What you are doing is considered to be spam and you are risking getting banned from the Github org. |
|
Sorry about that my bad. I was experimenting with an AI assistant to draft reviews. |
| }) | ||
|
|
||
| It("structured and unstructured scale subresources behave consistently", func(ctx SpecContext) { | ||
| fuzzer := randfill.New().Funcs( |
There was a problem hiding this comment.
Lets make failures reproducible:
| fuzzer := randfill.New().Funcs( | |
| seed := time.Now().UnixMicro() | |
| GinkgoWriter.Printf("seed: %d", seed) | |
| fuzzer := randfill.NewWithSeed(seed).Funcs( |
| Expect(int32(replicas)).To(Equal(int32(3))) | ||
| }) | ||
|
|
||
| It("structured and unstructured scale subresources behave consistently", func(ctx SpecContext) { |
There was a problem hiding this comment.
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 for range 100 { existing test body } is fine
| sigs.k8s.io/yaml v1.6.0 | ||
| ) | ||
|
|
||
| require sigs.k8s.io/randfill v1.0.0 |
There was a problem hiding this comment.
Why not keep this in the existing block above this?
ab4f4f0 to
cf6880c
Compare
|
Hi @alvaroaleman — review comments are addressed and CI is green. Could you take another look when you have a chance? Thanks! |
|
@PullaguraSantosha Please rebase onto latest main, squash and get rid of the merge commit |
cf6880c to
ee613fa
Compare
| switch obj := obj.(type) { | ||
| case *unstructured.Unstructured: | ||
| if !isUnstructuredScaleResource(obj) { | ||
| return nil, fmt.Errorf("unimplemented scale subresource for resource %T", obj) |
There was a problem hiding this comment.
This one does not seem to be addressed
| switch obj := obj.(type) { | ||
| case *unstructured.Unstructured: | ||
| if !isUnstructuredScaleResource(obj) { | ||
| return fmt.Errorf("unimplemented scale subresource for resource %T", obj) |
|
Thx! /lgtm @alvaroaleman Do you want to take another look? |
|
LGTM label has been added. DetailsGit tree hash: 219adcef7ac6a7e8782294b9ab67e46f2d156bff |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: alvaroaleman, PullaguraSantosha The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
The fake client currently supports the
scalesubresource for several built-in workload types such asDeploymentandStatefulSet, but it does not provide equivalent behavior for unstructured objects.As a result, tests and controllers using the fake client cannot correctly exercise scale subresource operations on custom or unstructured resources that expose replica information via
spec.replicasandstatus.replicas.This change extends the fake client's scale subresource handling to support unstructured objects by reading and updating replica information from
spec.replicasandstatus.replicas, bringing its behavior closer to that of the Kubernetes API server.