diff --git a/Makefile b/Makefile index d2570ea..1e506b2 100644 --- a/Makefile +++ b/Makefile @@ -159,8 +159,8 @@ DEEPCOPY_GEN ?= $(LOCALBIN)/deepcopy-gen ## Tool Versions KUSTOMIZE_VERSION ?= v4.5.7 -CONTROLLER_TOOLS_VERSION ?= v0.11.1 -CLIENT_TOOLS_VERSION ?= v0.25.3 +CONTROLLER_TOOLS_VERSION ?= v0.12.0 +CLIENT_TOOLS_VERSION ?= v0.27.3 KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" .PHONY: kustomize diff --git a/generated/client/clientset/versioned/clientset.go b/generated/client/clientset/versioned/clientset.go index a0afd55..a671baa 100644 --- a/generated/client/clientset/versioned/clientset.go +++ b/generated/client/clientset/versioned/clientset.go @@ -32,8 +32,7 @@ type Interface interface { ObservabilityV1alpha1() observabilityv1alpha1.ObservabilityV1alpha1Interface } -// 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 observabilityV1alpha1 *observabilityv1alpha1.ObservabilityV1alpha1Client diff --git a/generated/client/clientset/versioned/doc.go b/generated/client/clientset/versioned/doc.go deleted file mode 100644 index b33fe18..0000000 --- a/generated/client/clientset/versioned/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2023. - -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/generated/client/clientset/versioned/typed/observability/v1alpha1/fake/fake_config.go b/generated/client/clientset/versioned/typed/observability/v1alpha1/fake/fake_config.go index 11bdc94..359a17a 100644 --- a/generated/client/clientset/versioned/typed/observability/v1alpha1/fake/fake_config.go +++ b/generated/client/clientset/versioned/typed/observability/v1alpha1/fake/fake_config.go @@ -23,7 +23,6 @@ import ( v1alpha1 "github.com/pluralsh/trace-shield-controller/api/observability/v1alpha1" 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" @@ -34,9 +33,9 @@ type FakeConfigs struct { Fake *FakeObservabilityV1alpha1 } -var configsResource = schema.GroupVersionResource{Group: "observability.traceshield.io", Version: "v1alpha1", Resource: "configs"} +var configsResource = v1alpha1.SchemeGroupVersion.WithResource("configs") -var configsKind = schema.GroupVersionKind{Group: "observability.traceshield.io", Version: "v1alpha1", Kind: "Config"} +var configsKind = v1alpha1.SchemeGroupVersion.WithKind("Config") // Get takes name of the config, and returns the corresponding config object, and an error if there is any. func (c *FakeConfigs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.Config, err error) { diff --git a/generated/client/clientset/versioned/typed/observability/v1alpha1/fake/fake_tenant.go b/generated/client/clientset/versioned/typed/observability/v1alpha1/fake/fake_tenant.go index 6de59d3..7d4cd21 100644 --- a/generated/client/clientset/versioned/typed/observability/v1alpha1/fake/fake_tenant.go +++ b/generated/client/clientset/versioned/typed/observability/v1alpha1/fake/fake_tenant.go @@ -23,7 +23,6 @@ import ( v1alpha1 "github.com/pluralsh/trace-shield-controller/api/observability/v1alpha1" 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" @@ -34,9 +33,9 @@ type FakeTenants struct { Fake *FakeObservabilityV1alpha1 } -var tenantsResource = schema.GroupVersionResource{Group: "observability.traceshield.io", Version: "v1alpha1", Resource: "tenants"} +var tenantsResource = v1alpha1.SchemeGroupVersion.WithResource("tenants") -var tenantsKind = schema.GroupVersionKind{Group: "observability.traceshield.io", Version: "v1alpha1", Kind: "Tenant"} +var tenantsKind = v1alpha1.SchemeGroupVersion.WithKind("Tenant") // Get takes name of the tenant, and returns the corresponding tenant object, and an error if there is any. func (c *FakeTenants) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.Tenant, err error) { diff --git a/generated/client/informers/externalversions/factory.go b/generated/client/informers/externalversions/factory.go index 12cf396..da851f3 100644 --- a/generated/client/informers/externalversions/factory.go +++ b/generated/client/informers/externalversions/factory.go @@ -46,6 +46,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. @@ -106,20 +111,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() @@ -166,11 +190,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 + Observability() observability.Interface }