Skip to content

apiextensions: add subresources for custom resources#55168

Merged
k8s-github-robot merged 3 commits intokubernetes:masterfrom
nikhita:customresources-subresources
Feb 22, 2018
Merged

apiextensions: add subresources for custom resources#55168
k8s-github-robot merged 3 commits intokubernetes:masterfrom
nikhita:customresources-subresources

Conversation

@nikhita
Copy link
Member

@nikhita nikhita commented Nov 6, 2017

Fixes #38113
Fixes #58778

Related:

Add types:

  • Add CustomResourceSubresources type to CRD.
  • Add feature gate for CustomResourceSubresources.
    • Update CRD strategy: if feature gate is disabled, this feature is dropped (i.e. set to nil).
  • Add validation for CustomResourceSubresources:
    • SpecReplicasPath should not be empty and should be a valid json path under .spec. If there is no value under the given path in the custom resource, the /scale subresource will return an error on GET.
    • StatusReplicasPath should not be empty and should be a valid json path under .status. If there is no value under the given path in the custom resource, the status replica value in the /scale subresource will default to 0.
    • If present, LabelSelectorPath is optional and should be a valid json path under .status. If there is no value under LabelSelectorPath in the custom resource, the status label selector value in the /scale subresource will default to the empty string.
    • If CustomResourceSubresources feature gate is enabled, only properties is allowed under the root schema for CRD validation.

Add status and scale subresources:

  • Use helper functions from apimachinery/pkg/apis/meta/v1/unstructured/helpers.go.
  • Introduce Registry interface for storage.
  • Update storage:
    • Introduce CustomResourceStorage which acts as storage for the custom resource and its status and scale subresources. Note: storage for status and scale is only enabled when the feature gate is enabled and the respective fields are enabled in the CRD.
    • Introduce StatusREST and its New(), Get() and Update() methods.
    • Introduce ScaleREST and its New(), Get() and Update() methods.
      • Get and Update use the json paths from the CRD and use it to return an autoscaling/v1.Scale object.
  • Update strategy:
    • In PrepareForCreate,
      • Clear .status.
      • Set .metadata.generation = 1
    • In PrepareForUpdate,
      • Do not update .status.
        • If both the old and new objects have .status and it is changed, set it back to its old value.
        • If the old object has a .status but the new object doesn't, set it to the old value.
        • If old object did not have a .status but the new object does, delete it.
      • Increment generation if spec changes i.e. in the following cases:
        • If both the old and new objects had .spec and it changed.
        • If the old object did not have .spec but the new object does.
        • If the old object had a .spec but the new object doesn't.
    • In Validate and ValidateUpdate,
      • ensure that values at specReplicasPath and statusReplicasPath are >=0 and < maxInt32.
      • make sure there are no errors in getting the value at all the paths.
    • Introduce statusStrategy with its methods.
      • In PrepareForUpdate:
        • Do not update .spec.
          • If both the old and new objects have .spec and it is changed, set it back to its old value.
          • If the old object has a .spec but the new object doesn't, set it to the old value.
          • If old object did not have a .spec but the new object does, delete it.
        • Do not update .metadata.
      • In ValidateStatusUpdate:
        • For CRD validation, validate only under .status.
        • Validate value at statusReplicasPath and labelSelectorPath as above.
  • Plug into the custom resource handler:
    • Store all three storage - customResource, status and scale in crdInfo.
    • Use the storage as per the subresource in the request.
    • Use the validator as per the subresource (for status, only use the schema for status, if present).
    • Serve the endpoint as per the subresource - see serveResource, serveStatus and serveScale.
  • Update discovery by adding the /status and /scale resources, if enabled.

Add tests:

  • Add unit tests in etcd_test.go.
  • Add integration tests.
    • In subresources_test.go, use the polymporphic scale client to get and update Scale.
    • Add a test to check everything works fine with yaml in yaml_test.go.

Release note:

`/status` and `/scale` subresources are added for custom resources.

@k8s-ci-robot k8s-ci-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. 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. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Nov 6, 2017
@nikhita
Copy link
Member Author

nikhita commented Nov 6, 2017

/assign @sttts @deads2k @enisoc

Copy link
Contributor

Choose a reason for hiding this comment

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

do we use typographical quotes?

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed.

Copy link
Contributor

Choose a reason for hiding this comment

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

not opt

Copy link
Member Author

Choose a reason for hiding this comment

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

This should be fixed when proto generation is fixed. Currently, update-generated-protobuf fails on CustomResourceSubResourceStatus

Copy link
Contributor

Choose a reason for hiding this comment

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

better: field.Invalid

Copy link
Contributor

Choose a reason for hiding this comment

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

also below

Copy link
Member 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

Choose a reason for hiding this comment

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

we have public unstructured helpers now. Would they work for you? apimachinery/pkg/apis/meta/v1/unstructured/helpers.go

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, they probably should. I'll try with them.

Copy link
Member 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

Choose a reason for hiding this comment

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

This makes every CR part of kubectl get all. Wondering, do we have a way to opt-in to that group in a CRD?

Copy link
Member Author

Choose a reason for hiding this comment

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

Wondering, do we have a way to opt-in to that group in a CRD?

Maybe another field in the CRD? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

err.Error()?

Copy link
Member 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

Choose a reason for hiding this comment

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

not capital Scale?

Copy link
Contributor

Choose a reason for hiding this comment

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

why a map?

Copy link
Contributor

Choose a reason for hiding this comment

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

would make all of the paths explicit here

Copy link
Member Author

Choose a reason for hiding this comment

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

To have something like this:

scaleJSONPath["specReplicasPath"] = crd.Spec.SubResources.Scale.SpecReplicasPath
scaleJSONPath["statusReplicasPath"] = crd.Spec.SubResources.Scale.StatusReplicasPath
scaleJSONPath["labelSelectorPath"] = crd.Spec.SubResources.Scale.LabelSelectorPath

Copy link
Member Author

@nikhita nikhita Nov 6, 2017

Choose a reason for hiding this comment

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

would make all of the paths explicit here

👍

Copy link
Contributor

Choose a reason for hiding this comment

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

3 string fields would do as well?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

isn't it mandatory?

Copy link
Contributor

Choose a reason for hiding this comment

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

These tests should go into the CRD validation.

Copy link
Contributor

Choose a reason for hiding this comment

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

also below

Copy link
Member Author

Choose a reason for hiding this comment

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

This validates the "custom resource". So I think it should not go in the CRD strategy and should instead remain the in the CR strategy.

@sttts WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

hmm, I think customResource["oneOf"] does not make sense here. We have to check that OneOf is not used in the root of the JSON schema in the CRD.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

:-(. It was fun while it lasted

@DirectXMan12
Copy link
Contributor

@kubernetes/sig-autoscaling-api-reviews

@k8s-ci-robot k8s-ci-robot added sig/autoscaling Categorizes an issue or PR as relevant to SIG Autoscaling. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API labels Nov 6, 2017
Copy link
Contributor

@DirectXMan12 DirectXMan12 left a comment

Choose a reason for hiding this comment

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

You're using the scheme used internally to the scale client as your internal version, which I'd say is not ok.

Other comments inline

Copy link
Contributor

Choose a reason for hiding this comment

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

why is StatusReplicas optional? If it defaults to something otherwise, you should probably write that here (same with the other optional fields)

Copy link
Contributor

Choose a reason for hiding this comment

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

If I remember right, the idea was that a scale subresource could exist without the scale being reflected in the status. So there is no defaulting of this field.

Copy link
Member Author

@nikhita nikhita Nov 9, 2017

Choose a reason for hiding this comment

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

Adding on to what @sttts said, the user cannot write to the /status .status of the scale object at all. It is completely read-only for the user. Only a controller has write access to the status fields. So we can leave it empty and not have it default to anything. This also matches our plan with CRDs.

Copy link
Contributor

Choose a reason for hiding this comment

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

This was intended to be purely internal to the scale client. The internal types aren't supposed to be used by other people.

Copy link
Contributor

Choose a reason for hiding this comment

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

Make them internal.

Copy link
Contributor

Choose a reason for hiding this comment

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

you mean change the name? Because they are marked as having the version be __internal.

Copy link
Contributor

Choose a reason for hiding this comment

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

We don't make any use of that, but Go 1.5+ has packages called internal which can only be imported if your package and the internal one shares a common root. Does not belong into this PR, but I really think we should move a lot of internal code into internal packages. These client schemes are candidates for that. So I agree, we probably should not use the scale scheme here in the registry.

Copy link
Member Author

Choose a reason for hiding this comment

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

Uses external type for autoscaling now. 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see what purpose this serves. This is never supposed to be used as an API server type.

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed.

@nikhita nikhita force-pushed the customresources-subresources branch from b716144 to b80000b Compare November 9, 2017 15:51
@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Nov 9, 2017
Copy link
Member Author

Choose a reason for hiding this comment

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

This needs fixing. Will do that.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops, done in 6f36088. Should be fine after a squash.

@k8s-github-robot k8s-github-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 11, 2017
@nikhita nikhita force-pushed the customresources-subresources branch from b80000b to 30fe1d1 Compare November 13, 2017 12:40
@k8s-github-robot k8s-github-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 13, 2017
@sttts
Copy link
Contributor

sttts commented Feb 21, 2018

/lgtm

1 similar comment
@sttts
Copy link
Contributor

sttts commented Feb 22, 2018

/lgtm

@anubhakushwaha
Copy link
Contributor

@nikhita @sttts Just a minor comment update required here I think in the comment it should be "3" instead of "5", let me know if I am wrong as it may lead to false test.

@sttts
Copy link
Contributor

sttts commented Feb 22, 2018

/lgtm

Copy link
Contributor

Choose a reason for hiding this comment

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

Per discussion in slack:

  1. This should be DefaultScaleGroupVersion, as it's not intended to prevent the server from serving additional versions. The version of polymorphic subresources is intended to be whatever the client of the subresource wants it to be. We haven't built this out because we don't have any multi-versioned subresources yet.
  2. The default is probably always going to be autoscaling/v1/scale.
  3. In the unlikely event we do change the default, we could always add this field at that time and backfill.

Therefore, let's remove this field, it's not necessary at the moment.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry to not have figured this out yesterday when I asked for changes!

@sttts
Copy link
Contributor

sttts commented Feb 22, 2018

/lgtm

@lavalamp
Copy link
Contributor

/approve

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: cblecker, deads2k, lavalamp, nikhita, sttts

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

The pull request process is described here

Details 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

@k8s-github-robot
Copy link

/test all [submit-queue is verifying that this PR is safe to merge]

@k8s-github-robot
Copy link

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions here.

@sttts
Copy link
Contributor

sttts commented Feb 22, 2018

🎉

@tamalsaha
Copy link
Member

Thanks @nikhita @sttts and everyone who helped to get this added!

@idvoretskyi
Copy link
Member

@nikhita @sttts can you please link this to an issue in https://github.com/kubernetes/features

@nikhita
Copy link
Member Author

nikhita commented Feb 23, 2018

@idvoretskyi It is a part of kubernetes/enhancements#95.

@sttts
Copy link
Contributor

sttts commented Apr 3, 2018

/lgtm
/approve

func (r *crdHandler) serveResource(w http.ResponseWriter, req *http.Request, requestInfo *apirequest.RequestInfo, crdInfo *crdInfo, terminating bool, supportedTypes []string) http.HandlerFunc {
requestScope := crdInfo.requestScope
storage := crdInfo.storage.CustomResource
minRequestTimeout := 1 * time.Minute
Copy link
Member

Choose a reason for hiding this comment

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

@nikhita do you know what's the point of setting a constant timeout here?

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. 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. sig/autoscaling Categorizes an issue or PR as relevant to SIG Autoscaling. 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.