Skip to content
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

Allow marker comments to extend validations for subschemas #469

Merged
merged 3 commits into from
May 21, 2024

Conversation

alexzielenski
Copy link
Contributor

@alexzielenski alexzielenski commented Apr 12, 2024

This extends current marker syntax to support extending the subschemas of a struct inside items, properties, or additionalProperties. This is useful in cases like declarative validation for native types where we have many shared types whose validations change at point-of-use, so it does not make sense to annotate the type. And using an alias is too disruptive.

Example:

package foo

// +k8s:openapi-gen=true
// +k8s:validation:properties:field:maxLength=10
// +k8s:validation:properties:aliasMap:additionalProperties:pattern>^foo$
type Blah struct {
	// +k8s:validation:items:cel[0]:rule="self.length() % 2 == 0"
        // +k8s:validation:items:cel[0]:message="length must be even"
	Field MyAlias `json:"field"`

	// +k8s:validation:additionalProperties:maxLength=10
	AliasMap MyAliasMap `json:"aliasMap"`
}
		
type MyAliasMap map[string]MyAlias
type MyAlias []string

In the above example we can override subschemas at multiple different levels, with type checking supported.

This yields schema:

type: object
allOf:
    properties:
        field: 
            items: {maxLength: 10}
        aliasMap: {pattern: ^foo$}
properties:
    field:
        type: array
        items:
            type: string
        allOf:
            items:
                x-kubernetes-validations:
                - rule: self.length() % 2 == 0
                  message: length must be even
    aliasMap:
        additionalProperties: {type: string}
        allOf:
            additionalProperties:
                maxLength: 10

The value validations are placed in an allOf inside the object they were attached to and override subproperties. New structure is not allowed to be placed in these tags, only validations. We validate that any named properties are also in the structure of the Go type.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Apr 12, 2024
@k8s-ci-robot k8s-ci-robot added approved Indicates a PR has been approved by an approver from all required OWNERS files. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Apr 12, 2024
@alexzielenski alexzielenski force-pushed the nested-markers branch 4 times, most recently from bf5bc2e to 626a771 Compare April 12, 2024 19:41
@alexzielenski
Copy link
Contributor Author

/cc @Jefftree @jpbetz

Copy link
Member

@Jefftree Jefftree left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like there are quite a few implicit changes here, would you be able to separate them out into another PR/commit to explain the relevance? The changes move the codebase in a good direction but I'm a bit confused about the interdependency between them and the PR description goal.

OTOH

  • a set of fields being transformed into ptrs
  • deterministic output
  • validations such as minItems/etc should only be attached corresponding types

pkg/generators/markers.go Outdated Show resolved Hide resolved
Copy link
Contributor

@jpbetz jpbetz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. A few very minor comments.

pkg/generators/markers.go Outdated Show resolved Hide resolved
test/integration/pkg/generated/openapi_generated.go Outdated Show resolved Hide resolved
@alexzielenski alexzielenski force-pushed the nested-markers branch 2 times, most recently from 4160662 to db03e74 Compare April 16, 2024 22:50
@alexzielenski
Copy link
Contributor Author

I feel like there are quite a few implicit changes here, would you be able to separate them out into another PR/commit to explain the relevance? The changes move the codebase in a good direction but I'm a bit confused about the interdependency between them and the PR description goal.

OTOH

  • a set of fields being transformed into ptrs
  • deterministic output
  • validations such as minItems/etc should only be attached corresponding types

I split the deterministic output change into a separate commit (no test changes, since theres only 1 possible element so it is more of a future-proofing change)

I also removed the MinProperties/MaxProperties behavior change, so diff is much smaller.

ready for another pass

pattern := ""
if c.Pattern != nil {
pattern = *c.Pattern
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: What's the purpose of changing this set of fields to pointers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It allows us to disambiguate empty from unset. It doesnt affect anything right now but I thought that while I was copying the fields over it'd be better to have this ability.

@alexzielenski
Copy link
Contributor Author

/hold

@jpbetz While trying to use this I've ran into the problem that CEL expressions inside allOf are not validated, since it is not part of the "structural" portion of the schema. Is this something that will ever change in the future? I'm also curious why this is the case, since CEL expressions are definitely value validations and don't impact schema structure unlike other X-extensions

@k8s-ci-robot k8s-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Apr 17, 2024
@alexzielenski alexzielenski force-pushed the nested-markers branch 2 times, most recently from ef73428 to b7afea5 Compare April 29, 2024 21:19
@alexzielenski
Copy link
Contributor Author

alexzielenski commented May 7, 2024

Ive tested this extensively as part of kubernetes/kubernetes#123163

To use CEL within these still requires kubernetes/kubernetes#124381 but I think this is ready to merge

/cc @jpbetz
/remove-hold

@k8s-ci-robot k8s-ci-robot requested a review from jpbetz May 7, 2024 01:30
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label May 7, 2024
@Jefftree
Copy link
Member

lgtm from me, I'll leave lgtm with @jpbetz if he wants another pass

Comment on lines 2361 to 2364
// +k8s:validation:maxProperties=10
// +k8s:validation:minProperties=1
// +k8s:validation:exclusiveMinimum
// +k8s:validation:exclusiveMaximum
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if this is obvious, but why are we removing these tags from this test input?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this PR enforcement of invalid marker tags on structs was skipped:

https://github.com/kubernetes/kube-openapi/pull/469/files/8d2dde0ae8c4bdb1b57dfa5c0a417383dc2dc0d9#diff-72f8260914152fe9557b05d756ec94854184645e991ff755855628428d6d7a18L177-R295

So tags like exclusiveMinimum and exclusiveMaximum now throw errors for structs. minProperties and maxProperties are allowed on structs, so their removal was likely overzealous. I'll add it back

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added back

@jpbetz
Copy link
Contributor

jpbetz commented May 21, 2024

One question about the removed test cases then this looks ready to merge.

…er comments

adds powerful feature to marker comments to be able to add validations attributed to subschemas. Does not support removing validations from subschemas
@jpbetz
Copy link
Contributor

jpbetz commented May 21, 2024

/approve
/lgtm
Leaning on @Jefftree's review here, but it all looked reasonable to me.

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 21, 2024
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: alexzielenski, jpbetz

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:
  • OWNERS [alexzielenski,jpbetz]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot merged commit 835d969 into kubernetes:master May 21, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants