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

apiextensions: complete default-under-metadata validation and storage pruning #78829

Conversation

sttts
Copy link
Contributor

@sttts sttts commented Jun 9, 2019

Implement the validation part of kubernetes/enhancements#1166. Storage default pruning will be a follow-up. Both the validation and storage part is included.

Possible follow-ups (not in this PR):

  • make error paths in under-metadata default values absolute
Verify that CRD default values in OpenAPI specs are pruned, with the exceptions of values under `metadata`.

@k8s-ci-robot k8s-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. needs-priority Indicates a PR lacks a `priority/foo` label and requires one. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. and removed needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. labels Jun 9, 2019
@sttts sttts force-pushed the sttts-crd-embedded-resource-metadata-defaulting branch from 90b489c to 1e4f2f9 Compare June 10, 2019 09:32
@sttts sttts added this to the v1.16 milestone Jun 10, 2019
@sttts sttts force-pushed the sttts-crd-embedded-resource-metadata-defaulting branch from 1e4f2f9 to 67d25f5 Compare June 10, 2019 17:02
@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jun 10, 2019
@fedebongio
Copy link
Contributor

/assign @roycaihw
/cc @jennybuckley

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 30, 2019
@roycaihw
Copy link
Member

roycaihw commented Aug 7, 2019

/cc @liggitt

@sttts sttts force-pushed the sttts-crd-embedded-resource-metadata-defaulting branch from 67d25f5 to 4f8261b Compare August 17, 2019 13:10
@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. labels Aug 17, 2019
@sttts sttts changed the title WIP: apiextensions: complete default-under-metadata validation apiextensions: complete default-under-metadata validation Aug 17, 2019
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 17, 2019
@@ -80,7 +80,7 @@ func NewStructural(s *apiextensions.JSONSchemaProps) (*Structural, error) {
ss.Items = item
}

if len(s.Properties) > 0 {
if s.Properties != nil {
Copy link
Member

Choose a reason for hiding this comment

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

can you provide an empty, but defined properties field

you cannot if you use client-go to wire a CRD to a JSON or proto (the empty field gets omitted in both cases); you can if you write a JSON and send it to apiserver directly

nit: this relaxes validation slightly, the validation error message might be inaccurate now

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@liggitt are we fine with that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we could add a formal validation that properties for non-preserve-unknown-fields objects are never empty, making JSON and proto to behave the same.

Copy link
Member

Choose a reason for hiding this comment

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

@liggitt are we fine with that?

not as written.

we have to be really careful here... this could allow a user to submit the following data that would pass validation, then fail validation after round-tripping through etcd:

    openAPIV3Schema:
      type: object
      properties:
        template:
          type: object
          x-kubernetes-embedded-resource: true
          properties: {}

in 1.15, even if properties: {} was submitted to the apiserver (via a manual JSON request), the len(s.Properties) > 0 check here meant that the structural schema had a nil Properties field, and validation failed with ...properties: Required value: must not be empty if x-kubernetes-embedded-resource is true without x-kubernetes-preserve-unknown-fields error

with this PR, the CRD is allowed to be created, and updates fail with that message (since round-tripping through protobuf in etcd truncated the properties field to nil).

Copy link
Member

@liggitt liggitt Aug 23, 2019

Choose a reason for hiding this comment

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

we could add a formal validation that properties for non-preserve-unknown-fields objects are never empty, making JSON and proto to behave the same.

that seems best. we know no existing schemas or existing 1.15 API clients successfully specified empty properties to get around that nil check validation, because of the len() > 0 check here.

I would:

  • leave the len() > 0 check here (preserving the difference between nil and 0-length doesn't seem useful if we know we can't round-trip it in through etcd)
  • switch the if s.XEmbeddedResource && !s.XPreserveUnknownFields && s.Properties == nil { check to if s.XEmbeddedResource && !s.XPreserveUnknownFields && len(s.Properties) == 0 { to make the check match what we can round-trip

If someone really wants an embedded resource with no other properties without preserving unknown fields, they can explicitly define apiVersion / kind properties

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done ^^

Copy link
Contributor Author

Choose a reason for hiding this comment

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

including tests.


for _, tst := range tests {
t.Run(strings.Join(tst.path, "."), func(t *testing.T) {
obj, found, err := unstructured.NestedMap(foo.Object, tst.path...)
Copy link
Member

Choose a reason for hiding this comment

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

this tests that defaults of unknown fields didn't survive defaulting->serialization->etcd->decoding->pruning, but it's not clear that the pruning happened before data got persisted to etcd (which is what we really care about)

can we use the storage.NewEtcdObjectReader (from the conversion webhook tests) to pull data out of etcd for verification?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yep, I noticed that as well. Let me check about etcd object reader.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done. And verified that without the fixed default pruning algorithm it breaks 👍

if err != nil {
return false, fmt.Errorf("failed to prune default value: %v", err)
}
pruning.Prune(obj, p.rootSchema, true)
Copy link
Member

@liggitt liggitt Aug 23, 2019

Choose a reason for hiding this comment

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

just making sure I understand, this prunes both metadata and non-metadata fields? (though non-metadata defaults should be no-ops since we check there are no pruned fields in those at validation time?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no, it didn't. Fixed.

@liggitt
Copy link
Member

liggitt commented Aug 23, 2019

(also fix the golint verify errors :-/)

@sttts sttts force-pushed the sttts-crd-embedded-resource-metadata-defaulting branch from 5b49db8 to 1bfd7e9 Compare August 23, 2019 17:42
@liggitt
Copy link
Member

liggitt commented Aug 23, 2019

/approve

squash review commits, fixup lint, then lgtm

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 23, 2019
@sttts sttts force-pushed the sttts-crd-embedded-resource-metadata-defaulting branch from 1bfd7e9 to 55e2255 Compare August 23, 2019 20:07
@liggitt
Copy link
Member

liggitt commented Aug 23, 2019

/lgtm
/approve
/retest

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

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: liggitt, sttts

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:

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

@sttts sttts force-pushed the sttts-crd-embedded-resource-metadata-defaulting branch from 55e2255 to 4fd200c Compare August 23, 2019 20:21
@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 23, 2019
@liggitt
Copy link
Member

liggitt commented Aug 23, 2019

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 23, 2019
@sttts
Copy link
Contributor Author

sttts commented Aug 23, 2019

Again no bazel test logs.

/retest

@k8s-ci-robot k8s-ci-robot merged commit f9afe46 into kubernetes:master Aug 24, 2019
@roycaihw
Copy link
Member

/area custom-resources

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. area/custom-resources cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API lgtm "Looks good to me", indicates that a PR is ready to be merged. priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants