From bcd6ded4c04daf002df8cded9905cb2ceaaab952 Mon Sep 17 00:00:00 2001 From: Markus Lehtonen Date: Tue, 18 Apr 2023 21:32:57 +0300 Subject: [PATCH 1/2] generate: update k8s code-generator to v0.27.1 Also, don't pre-install all k8s code-generator tools in the image. The generate-groups.sh of code-generator will do "go install" for the tools it needs which fails with permission denied error in some environments as it tries to overwrite the existing files owned by root. --- Dockerfile_generator | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile_generator b/Dockerfile_generator index 934f42f32..21a00b665 100644 --- a/Dockerfile_generator +++ b/Dockerfile_generator @@ -4,8 +4,8 @@ FROM ${BUILDER_IMAGE} as builder # Install tools RUN go install github.com/vektra/mockery/v2@v2.20.0 && \ go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.9.2 && \ - git clone https://github.com/kubernetes/code-generator -b v0.24.3 --depth 1 && \ - go install k8s.io/code-generator/cmd/...@v0.24.3 && \ + git clone https://github.com/kubernetes/code-generator -b v0.27.1 --depth 1 && \ + go install k8s.io/code-generator/cmd/go-to-protobuf/...@v0.27.1 && \ go install golang.org/x/tools/cmd/goimports@v0.1.1 && \ go install github.com/golang/protobuf/protoc-gen-go@v1.4.3 From ca7ed04a34fcbe55e74085bf78bbddf0a178b5f3 Mon Sep 17 00:00:00 2001 From: Markus Lehtonen Date: Tue, 18 Apr 2023 21:58:10 +0300 Subject: [PATCH 2/2] generate: update auto-generated code Re-run "make generate". --- .../clientset/versioned/clientset.go | 3 +- pkg/generated/clientset/versioned/doc.go | 20 ----- .../nfd/v1alpha1/fake/fake_nodefeature.go | 5 +- .../nfd/v1alpha1/fake/fake_nodefeaturerule.go | 5 +- .../informers/externalversions/factory.go | 79 ++++++++++++++++++- 5 files changed, 80 insertions(+), 32 deletions(-) delete mode 100644 pkg/generated/clientset/versioned/doc.go diff --git a/pkg/generated/clientset/versioned/clientset.go b/pkg/generated/clientset/versioned/clientset.go index b798df4e8..46e3dafe6 100644 --- a/pkg/generated/clientset/versioned/clientset.go +++ b/pkg/generated/clientset/versioned/clientset.go @@ -33,8 +33,7 @@ type Interface interface { NfdV1alpha1() nfdv1alpha1.NfdV1alpha1Interface } -// Clientset contains the clients for groups. Each group has exactly one -// version included in a Clientset. +// Clientset contains the clients for groups. type Clientset struct { *discovery.DiscoveryClient nfdV1alpha1 *nfdv1alpha1.NfdV1alpha1Client diff --git a/pkg/generated/clientset/versioned/doc.go b/pkg/generated/clientset/versioned/doc.go deleted file mode 100644 index d1411fc84..000000000 --- a/pkg/generated/clientset/versioned/doc.go +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2023 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by client-gen. DO NOT EDIT. - -// This package has the automatically generated clientset. -package versioned diff --git a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeature.go b/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeature.go index bac98b488..8a8c14629 100644 --- a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeature.go +++ b/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeature.go @@ -23,7 +23,6 @@ import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" - schema "k8s.io/apimachinery/pkg/runtime/schema" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" testing "k8s.io/client-go/testing" @@ -36,9 +35,9 @@ type FakeNodeFeatures struct { ns string } -var nodefeaturesResource = schema.GroupVersionResource{Group: "nfd.k8s-sigs.io", Version: "v1alpha1", Resource: "nodefeatures"} +var nodefeaturesResource = v1alpha1.SchemeGroupVersion.WithResource("nodefeatures") -var nodefeaturesKind = schema.GroupVersionKind{Group: "nfd.k8s-sigs.io", Version: "v1alpha1", Kind: "NodeFeature"} +var nodefeaturesKind = v1alpha1.SchemeGroupVersion.WithKind("NodeFeature") // Get takes name of the nodeFeature, and returns the corresponding nodeFeature object, and an error if there is any. func (c *FakeNodeFeatures) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeature, err error) { diff --git a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturerule.go b/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturerule.go index b5dce863e..cf0dcaa8c 100644 --- a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturerule.go +++ b/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeaturerule.go @@ -23,7 +23,6 @@ import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" - schema "k8s.io/apimachinery/pkg/runtime/schema" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" testing "k8s.io/client-go/testing" @@ -35,9 +34,9 @@ type FakeNodeFeatureRules struct { Fake *FakeNfdV1alpha1 } -var nodefeaturerulesResource = schema.GroupVersionResource{Group: "nfd.k8s-sigs.io", Version: "v1alpha1", Resource: "nodefeaturerules"} +var nodefeaturerulesResource = v1alpha1.SchemeGroupVersion.WithResource("nodefeaturerules") -var nodefeaturerulesKind = schema.GroupVersionKind{Group: "nfd.k8s-sigs.io", Version: "v1alpha1", Kind: "NodeFeatureRule"} +var nodefeaturerulesKind = v1alpha1.SchemeGroupVersion.WithKind("NodeFeatureRule") // Get takes name of the nodeFeatureRule, and returns the corresponding nodeFeatureRule object, and an error if there is any. func (c *FakeNodeFeatureRules) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeatureRule, err error) { diff --git a/pkg/generated/informers/externalversions/factory.go b/pkg/generated/informers/externalversions/factory.go index 01caa99ee..b04f7173f 100644 --- a/pkg/generated/informers/externalversions/factory.go +++ b/pkg/generated/informers/externalversions/factory.go @@ -47,6 +47,11 @@ type sharedInformerFactory struct { // startedInformers is used for tracking which informers have been started. // This allows Start() to be called multiple times safely. startedInformers map[reflect.Type]bool + // wg tracks how many goroutines were started. + wg sync.WaitGroup + // shuttingDown is true when Shutdown has been called. It may still be running + // because it needs to wait for goroutines. + shuttingDown bool } // WithCustomResyncConfig sets a custom resync period for the specified informer types. @@ -107,20 +112,39 @@ func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResy return factory } -// Start initializes all requested informers. func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { f.lock.Lock() defer f.lock.Unlock() + if f.shuttingDown { + return + } + for informerType, informer := range f.informers { if !f.startedInformers[informerType] { - go informer.Run(stopCh) + f.wg.Add(1) + // We need a new variable in each loop iteration, + // otherwise the goroutine would use the loop variable + // and that keeps changing. + informer := informer + go func() { + defer f.wg.Done() + informer.Run(stopCh) + }() f.startedInformers[informerType] = true } } } -// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) Shutdown() { + f.lock.Lock() + f.shuttingDown = true + f.lock.Unlock() + + // Will return immediately if there is nothing to wait for. + f.wg.Wait() +} + func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { informers := func() map[reflect.Type]cache.SharedIndexInformer { f.lock.Lock() @@ -167,11 +191,58 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal // SharedInformerFactory provides shared informers for resources in all known // API group versions. +// +// It is typically used like this: +// +// ctx, cancel := context.Background() +// defer cancel() +// factory := NewSharedInformerFactory(client, resyncPeriod) +// defer factory.WaitForStop() // Returns immediately if nothing was started. +// genericInformer := factory.ForResource(resource) +// typedInformer := factory.SomeAPIGroup().V1().SomeType() +// factory.Start(ctx.Done()) // Start processing these informers. +// synced := factory.WaitForCacheSync(ctx.Done()) +// for v, ok := range synced { +// if !ok { +// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) +// return +// } +// } +// +// // Creating informers can also be created after Start, but then +// // Start must be called again: +// anotherGenericInformer := factory.ForResource(resource) +// factory.Start(ctx.Done()) type SharedInformerFactory interface { internalinterfaces.SharedInformerFactory - ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // Start initializes all requested informers. They are handled in goroutines + // which run until the stop channel gets closed. + Start(stopCh <-chan struct{}) + + // Shutdown marks a factory as shutting down. At that point no new + // informers can be started anymore and Start will return without + // doing anything. + // + // In addition, Shutdown blocks until all goroutines have terminated. For that + // to happen, the close channel(s) that they were started with must be closed, + // either before Shutdown gets called or while it is waiting. + // + // Shutdown may be called multiple times, even concurrently. All such calls will + // block until all goroutines have terminated. + Shutdown() + + // WaitForCacheSync blocks until all started informers' caches were synced + // or the stop channel gets closed. WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + // ForResource gives generic access to a shared informer of the matching type. + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // InternalInformerFor returns the SharedIndexInformer for obj using an internal + // client. + InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer + Nfd() nfd.Interface }