✨ Add support for k8s:immutable#1354
✨ Add support for k8s:immutable#1354alvaroaleman wants to merge 1 commit intokubernetes-sigs:mainfrom
Conversation
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: alvaroaleman 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 |
|
/assign @JoelSpeed @lalitc375 |
|
@alvaroaleman: GitHub didn't allow me to assign the following users: lalitc375. Note that only kubernetes-sigs members with read permissions, repo collaborators and people who have commented on this issue/PR can be assigned. Additionally, issues/PRs can only have 10 assignees at the same time. DetailsIn response to this:
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-sigs/prow repository. |
e986453 to
c940070
Compare
pkg/crd/markers/validation.go
Outdated
| func (m Immutable) ApplyToSchema(schema *apiextensionsv1.JSONSchemaProps) error { | ||
| optionalOldSelf := true | ||
| schema.XValidations = append(schema.XValidations, apiextensionsv1.ValidationRule{ | ||
| Rule: "!oldSelf.hasValue() || self == oldSelf.value()", |
There was a problem hiding this comment.
Does this achieve the same thing if we use self == oldSelf and drop the OptionalOldSelf?
There was a problem hiding this comment.
Yeah, good catch, updated it to do that instead
| // Note that immutable fields that are nested below optional fields can still be | ||
| // updated by unsetting the optional parent field and re-setting it again. |
There was a problem hiding this comment.
Is there anything we can do to handle the "no clear" element of the KEP?
The usual pattern is to find the nearest required pattern and add a validation to check that if the oldSelf has the immutable field set, that it cannot be unset
There was a problem hiding this comment.
This is handled by the code in schema.go that adds a CEL rule to disallow unsetting once set
|
|
||
| // +k8s:immutable | ||
| // +optional | ||
| OptionalString *string `json:"optionalString,omitempty"` |
There was a problem hiding this comment.
Do we need to test a version of this where string isn't a pointer?
|
|
||
| // +k8s:immutable | ||
| // +optional | ||
| OptionalStruct *NestedStruct `json:"optionalStruct,omitempty"` |
There was a problem hiding this comment.
A version without a pointer, but with omitzero to test that combination?
There was a problem hiding this comment.
Sure but at that point we are mostly testing the go serialization?
There was a problem hiding this comment.
Are we actually using these structs in the tests? If not don't worry
I was just thinking we could example all of the combinations CRD authors might use
pkg/crd/testdata/immutable_test.go
Outdated
| Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(got), got)).To(Succeed()) | ||
|
|
||
| mutate(got) | ||
| Expect(k8sClient.Update(ctx, got)).NotTo(Succeed()) |
There was a problem hiding this comment.
Can we check the error contains the immutable substring to make sure this is doing what we think it is?
pkg/crd/testdata/immutable_test.go
Outdated
| clear(got) | ||
| Expect(k8sClient.Update(ctx, got)).NotTo(Succeed()) |
There was a problem hiding this comment.
I thought the doc said we weren't expecting clear to be rejected?
There was a problem hiding this comment.
The docs said we do expect clear to be rejected: https://github.com/kubernetes/enhancements/blob/c68dfb941894fc8859a951fe47a60b2161300b88/keps/sig-api-machinery/5073-declarative-validation-with-validation-gen/README.md#k8simmutable
Or what do you mean?
| // For optional immutable fields, add a parent-level validation rule to prevent | ||
| // clearing the field once set. The field-level rule prevents value changes, but | ||
| // when an optional field is removed, the field-level rule doesn't execute. |
There was a problem hiding this comment.
If this is an optional parent, nothing stops them from removing the optional parent, you need to find the nearest required parent and add it there
There was a problem hiding this comment.
No, the kep explicitly says that its valid to remove an optional parent and that that starts a new cycle: https://github.com/kubernetes/enhancements/blob/c68dfb941894fc8859a951fe47a60b2161300b88/keps/sig-api-machinery/5073-declarative-validation-with-validation-gen/README.md#L1143
There was a problem hiding this comment.
Fair, I had missed that part of the EP
There was a problem hiding this comment.
This surprised me initially as well which is why I left the comment on the marker. For the purpose of implementing the markers, I would just go by the assumption that the relevant discussions if that does or doesn't make sense were already had when the KEP was written/approved
|
/hold Since this has approve, lets avoid an accidental merge with a fly by lgtm |
c940070 to
dfeab69
Compare
This change adds support for `k8s:immutable` as described in the [KEP][0]. [0]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/5073-declarative-validation-with-validation-gen
dfeab69 to
5c0f006
Compare
|
/lgtm @alvaroaleman having re-read the EP, I think this is good to go Would be good if @lalitc375 could ack the behaviour as well, fields are immutable, and cannot be unset unless their parent is cleared |
|
LGTM label has been added. DetailsGit tree hash: 201dc2db4af33e575a36a9b13bbcaf83716bb63a |
I am out of office right now. @aaron-prindle Can you please take a look? |
This change adds support for
k8s:immutableas described in the KEP.It replaces #1216 and follows @jpbetz suggestion for the CEL expression. It also adds integration tests.
Closes #1216