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

client-gen: independent scheme for clientsets #41486

Merged
merged 4 commits into from
Feb 23, 2017

Conversation

sttts
Copy link
Contributor

@sttts sttts commented Feb 15, 2017

This PR adds a clientset internal scheme instead of using pkg/api.Scheme. The clientset API stays the same.

In detail:

  • introduce a scheme for each clientset, i.e. do not use pkg/api.Scheme+Registry+Codec+ParameterCodecs.

    This makes it easier to compose client-go's clientset (which is rewritten in staging/copy.sh and therefore hardcoded to use k8s.io/client-go/pkg/api.Scheme+Registry+Codecs+ParameterCodecs) with third-party clientsets (kube-aggregator, openshift, federation) which are not rewritten using copy.sh as all of them are self-contained and therefore relocatable.

    This fixes https://github.com/kubernetes/kubernetes/pull/41403/files#diff-76edfb07dee54ff7ddeda25c33c10d29R81 and prepares client-gen for use in OpenShift.

  • register types into the clientset scheme via AddToScheme for versioned clientsets. This decouples the client-go clients from announce+registration (internal clients continue using announce+registry and apigroup installers).

    This reduces complexity for client-go, possibly remove the necessity for the announce+register machinery for many use-cases, maybe even to delete it mid-term.

  • port federation and testgroup install/install.go to announced.GroupMetaFactory in order to have a proper Install.Install(...) func for registration.

With the first change it's easy to add the types of one clientset to the scheme of the other using the clientset/scheme.AddToScheme method. This allows to use cross-clientset runtime.RawExtensions:

import (
     "k8s.io/client-go/kubernetes"
     clientsetscheme "k8s.io/client-go/kuberentes/scheme"
     aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
)

kclientset, _ := kubernetes.NewForConfig(c)
aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)

Kubernetes types with a RawExtension can en/decode aggregator types after this.

TODO:

  • fix fake clientsets
  • get the *Options types registered correctly for core, compare DO-NOT-MERGE commit.
  • get prefered version right in internal client. Do we need all versions registered in the internal client to support negotiation?
  • run staging/copy.sh and run tests: TEST: update client-go with clientset specific scheme #41744
  • [ ] fixup usage through-out the code-base
  • Follow-up: move import_known_versions.go files somewhere such that import of the api.Scheme package automatically installs the apigroups. It looks like we depended on the import fo the clientset for this purpose.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Feb 15, 2017
@k8s-github-robot k8s-github-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. release-note-label-needed labels Feb 15, 2017
@k8s-reviewable
Copy link

This change is Reviewable

configShallowCopy.ParameterCodec = parameterCodec
}
if configShallowCopy.NegotiatedSerializer == nil {
configShallowCopy.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: codecs}
Copy link
Contributor

Choose a reason for hiding this comment

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

I've missed where codecs is coming from.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

register.go in the same package.


var groupFactoryRegistry = make(announced.APIGroupFactoryRegistry)
var registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS"))
var scheme = runtime.NewScheme()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@deads2k your comment from irc was that runtime.RawExtension needs all types that should be embedded. E.g. in the PodTemplate case this is the pod.

We could make scheme public of course, or add some way to compose apigroups and clients explicitly.

Copy link
Contributor

Choose a reason for hiding this comment

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

It needs to be public or openshift will break downstream.

"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/client-go/pkg/apis/batch/install"
Copy link
Contributor

Choose a reason for hiding this comment

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

your plan is to generate this and import and install all the ones we need?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Exactly.

Copy link
Contributor Author

@sttts sttts Feb 16, 2017

Choose a reason for hiding this comment

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

With a bit more thought we should be able to handle the clientsets as a big module and combine them easily. Something around these lines:

kubeclientset.AddToScheme(originclientset.Scheme)

Copy link
Contributor

Choose a reason for hiding this comment

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

With a bit more thought we should be able to handle the clientsets as a big module and combine them easily. Something around these lines:

I agree, but I don't know know if we get there in 1.6. Think you can tie off generators for a separate scheme in 1.6?

@k8s-github-robot k8s-github-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Feb 16, 2017
@sttts sttts changed the title [PoC] client-go: independent scheme for clientset [WIP] client-go: independent scheme for clientset Feb 16, 2017
@@ -60,9 +60,9 @@ func (g *genClientset) Imports(c *generator.Context) (imports []string) {
for _, group := range g.groups {
for _, version := range group.Versions {
typedClientPath := filepath.Join(g.typedClientPath, group.Group.NonEmpty(), version.NonEmpty())
imports = append(imports, strings.ToLower(fmt.Sprintf("%s%s \"%s\"", version.NonEmpty(), group.Group.NonEmpty(), typedClientPath)))
imports = append(imports, strings.ToLower(fmt.Sprintf("%s%s \"%s\"", group.Group.NonEmpty(), version.NonEmpty(), typedClientPath)))
Copy link
Contributor

Choose a reason for hiding this comment

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

wow, really? This is how its being done in client-go? I was reasonably sure you could use it from the universe and it would just end up imported.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not clean for sure. Maybe somebody didn't like the autogenerated aliases.

@@ -102,6 +112,17 @@ func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Wr
return sw.Error()
}

var globalsTemplate = `
var Scheme = $.runtimeNewScheme|raw$()
var codecs = $.serializerNewCodecFactory|raw$(scheme)
Copy link
Contributor

Choose a reason for hiding this comment

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

Capital Scheme?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fake clientsets have some issues left.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do this tomorrow.

@@ -195,26 +191,20 @@ func (c *$.GroupVersion$Client) RESTClient() $.RESTClientInterface|raw$ {

var newClientForRESTClientTemplate = `
// New creates a new $.GroupVersion$Client for the given RESTClient.
func New(c $.RESTClientInterface|raw$) *$.GroupVersion$Client {
return &$.GroupVersion$Client{c}
func New(c $.RESTClientInterface|raw$, parameterCodec $.runtimeParameterCodec|raw$) *$.GroupVersion$Client {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is going to be a very unpopular change. You should be able to keep the old API with a generated and working default param codec (which we'll use 99% of the time) and if you must, a separate method that can take it as a parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme)

func init() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This matches my expectations.

@@ -63,26 +63,22 @@ func NewForConfigOrDie(c *rest.Config) *AutoscalingV1Client {

// New creates a new AutoscalingV1Client for the given RESTClient.
func New(c rest.Interface) *AutoscalingV1Client {
return &AutoscalingV1Client{c}
return &AutoscalingV1Client{c, scheme.ParameterCodec}
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good.

gv, err := schema.ParseGroupVersion("autoscaling/v1")
if err != nil {
return err
gv := schema.GroupVersion{Group: "autoscaling", Version: "v1"}
Copy link
Contributor

Choose a reason for hiding this comment

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

much nicer.

// if autoscaling/v1 is not enabled, return an error
if !api.Registry.IsEnabledVersion(gv) {
return fmt.Errorf("autoscaling/v1 is not enabled")
if config.ParameterCodec == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be correct enough to auto-assign the generated one? If this doesn't cause many problems, I don't really object, but I also don't expect many people to mess with it.

return err
gv := schema.GroupVersion{Group: "autoscaling", Version: "v1"}
if config.NegotiatedSerializer == nil {
return fmt.Errorf("expected non-nil NegotiatedSerializer for %v client", gv)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why don't we choose our generated one by default?

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 we had the circular dependency which is gone now. Fixing.

@deads2k
Copy link
Contributor

deads2k commented Feb 16, 2017

Some comments on defaulting, but I like the output a lot better.

@sttts sttts changed the title [WIP] client-go: independent scheme for clientset client-go: independent scheme for clientset Feb 17, 2017
@deads2k
Copy link
Contributor

deads2k commented Feb 17, 2017

lgtm. Looks like you have a few rough edges to work out.

@sttts sttts added release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed release-note-label-needed labels Feb 17, 2017
@sttts sttts added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Feb 17, 2017
@sttts sttts added approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm "Looks good to me", indicates that a PR is ready to be merged. labels Feb 22, 2017
@k8s-github-robot k8s-github-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 22, 2017
@deads2k
Copy link
Contributor

deads2k commented Feb 22, 2017

@k8s-bot unit test this: issue #41885

@sttts
Copy link
Contributor Author

sttts commented Feb 22, 2017

@k8s-bot gce etcd3 e2e test this issue #41889

@sttts
Copy link
Contributor Author

sttts commented Feb 22, 2017

@k8s-bot gci gce e2e test this #41889

@sttts sttts added approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm "Looks good to me", indicates that a PR is ready to be merged. and removed approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm "Looks good to me", indicates that a PR is ready to be merged. labels Feb 22, 2017
@deads2k
Copy link
Contributor

deads2k commented Feb 22, 2017

@sttts check the staging godeps on this.

@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

The following people have approved this PR: smarterclayton, sttts

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-github-robot k8s-github-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Feb 22, 2017
@sttts sttts added approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm "Looks good to me", indicates that a PR is ready to be merged. and removed approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Feb 22, 2017
@k8s-github-robot k8s-github-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Feb 22, 2017
@k8s-ci-robot
Copy link
Contributor

k8s-ci-robot commented Feb 22, 2017

@sttts: The following test(s) failed:

Test name Commit Details Rerun command
Jenkins CRI GCE Node e2e c421b89 link @k8s-bot cri node e2e test this

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

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/test-infra repository. I understand the commands that are listed here.

@deads2k
Copy link
Contributor

deads2k commented Feb 22, 2017

@k8s-bot verify test this

@deads2k
Copy link
Contributor

deads2k commented Feb 22, 2017

@k8s-bot gce etcd3 e2e test this

@sttts
Copy link
Contributor Author

sttts commented Feb 22, 2017

@k8s-bot verify test this

@k8s-github-robot
Copy link

Automatic merge from submit-queue (batch tested with PRs 41146, 41486, 41482, 41538, 41784)

@k8s-github-robot k8s-github-robot merged commit e49f44d into kubernetes:master Feb 23, 2017
@sttts sttts deleted the sttts-clientset-scheme branch February 23, 2017 05:41
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. release-note-none Denotes a PR that doesn't merit a release note. 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

7 participants