Update to Go 1.26.4, build runners and go.mod depedencies (#3108)

* update golang and dependencies
* fix incorrect log formatting
* clean mod chache and introduce GOARCH in Dockerfile (choose dynamically)
* remove GO111MODULE mentions
* bump github actions from v2 to v3
* bump docker runners to v7
* use extra event store for backwards compatibility with existing codebase
* updated generated opconfig api
This commit is contained in:
Felix Kunde
2026-06-23 13:35:53 +02:00
committed by GitHub
parent a664816c09
commit df3224730f
34 changed files with 1220 additions and 406 deletions
@@ -30,6 +30,7 @@ import (
fakeacidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake"
zalandov1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/zalando.org/v1"
fakezalandov1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/zalando.org/v1/fake"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/discovery"
@@ -41,10 +42,6 @@ import (
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
// without applying any field management, validations and/or defaults. It shouldn't be considered a replacement
// for a real clientset and is mostly useful in simple unit tests.
//
// DEPRECATED: NewClientset replaces this with support for field management, which significantly improves
// server side apply testing. NewClientset is only available when apply configurations are generated (e.g.
// via --with-applyconfig).
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
for _, obj := range objects {
@@ -57,9 +54,13 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset {
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
cs.AddReactor("*", "*", testing.ObjectReaction(o))
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
var opts metav1.ListOptions
if watchAction, ok := action.(testing.WatchActionImpl); ok {
opts = watchAction.ListOptions
}
gvr := action.GetResource()
ns := action.GetNamespace()
watch, err := o.Watch(gvr, ns)
watch, err := o.Watch(gvr, ns, opts)
if err != nil {
return false, nil, err
}
@@ -86,6 +87,17 @@ func (c *Clientset) Tracker() testing.ObjectTracker {
return c.tracker
}
// IsWatchListSemanticsUnSupported informs the reflector that this client
// doesn't support WatchList semantics.
//
// This is a synthetic method whose sole purpose is to satisfy the optional
// interface check performed by the reflector.
// Returning true signals that WatchList can NOT be used.
// No additional logic is implemented here.
func (c *Clientset) IsWatchListSemanticsUnSupported() bool {
return true
}
var (
_ clientset.Interface = &Clientset{}
_ testing.FakeClient = &Clientset{}
@@ -61,9 +61,7 @@ func (c *AcidV1Client) Postgresqls(namespace string) PostgresqlInterface {
// where httpClient was generated with rest.HTTPClientFor(c).
func NewForConfig(c *rest.Config) (*AcidV1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
setConfigDefaults(&config)
httpClient, err := rest.HTTPClientFor(&config)
if err != nil {
return nil, err
@@ -75,9 +73,7 @@ func NewForConfig(c *rest.Config) (*AcidV1Client, error) {
// Note the http client provided takes precedence over the configured transport values.
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*AcidV1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
setConfigDefaults(&config)
client, err := rest.RESTClientForConfigAndClient(&config, h)
if err != nil {
return nil, err
@@ -100,7 +96,7 @@ func New(c rest.Interface) *AcidV1Client {
return &AcidV1Client{c}
}
func setConfigDefaults(config *rest.Config) error {
func setConfigDefaults(config *rest.Config) {
gv := acidzalandov1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
@@ -109,8 +105,6 @@ func setConfigDefaults(config *rest.Config) error {
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
@@ -51,9 +51,7 @@ func (c *ZalandoV1Client) FabricEventStreams(namespace string) FabricEventStream
// where httpClient was generated with rest.HTTPClientFor(c).
func NewForConfig(c *rest.Config) (*ZalandoV1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
setConfigDefaults(&config)
httpClient, err := rest.HTTPClientFor(&config)
if err != nil {
return nil, err
@@ -65,9 +63,7 @@ func NewForConfig(c *rest.Config) (*ZalandoV1Client, error) {
// Note the http client provided takes precedence over the configured transport values.
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*ZalandoV1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
setConfigDefaults(&config)
client, err := rest.RESTClientForConfigAndClient(&config, h)
if err != nil {
return nil, err
@@ -90,7 +86,7 @@ func New(c rest.Interface) *ZalandoV1Client {
return &ZalandoV1Client{c}
}
func setConfigDefaults(config *rest.Config) error {
func setConfigDefaults(config *rest.Config) {
gv := zalandoorgv1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
@@ -99,8 +95,6 @@ func setConfigDefaults(config *rest.Config) error {
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
@@ -34,6 +34,7 @@ import (
acidzalandov1 "github.com/zalando/postgres-operator/pkg/generated/listers/acid.zalan.do/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
@@ -55,36 +56,61 @@ type operatorConfigurationInformer struct {
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewOperatorConfigurationInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredOperatorConfigurationInformer(client, namespace, resyncPeriod, indexers, nil)
return NewOperatorConfigurationInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers})
}
// NewFilteredOperatorConfigurationInformer constructs a new informer for OperatorConfiguration type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredOperatorConfigurationInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
return NewOperatorConfigurationInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions})
}
// NewOperatorConfigurationInformerWithOptions constructs a new informer for OperatorConfiguration type with additional options.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewOperatorConfigurationInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer {
gvr := schema.GroupVersionResource{Group: "acid.zalan.do", Version: "v1", Resource: "operatorconfigurations"}
identifier := options.InformerName.WithResource(gvr)
tweakListOptions := options.TweakListOptions
return cache.NewSharedIndexInformerWithOptions(
cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
tweakListOptions(&opts)
}
return client.AcidV1().OperatorConfigurations(namespace).List(context.TODO(), options)
return client.AcidV1().OperatorConfigurations(namespace).List(context.Background(), opts)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
tweakListOptions(&opts)
}
return client.AcidV1().OperatorConfigurations(namespace).Watch(context.TODO(), options)
return client.AcidV1().OperatorConfigurations(namespace).Watch(context.Background(), opts)
},
},
ListWithContextFunc: func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.AcidV1().OperatorConfigurations(namespace).List(ctx, opts)
},
WatchFuncWithContext: func(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.AcidV1().OperatorConfigurations(namespace).Watch(ctx, opts)
},
}, client),
&apisacidzalandov1.OperatorConfiguration{},
resyncPeriod,
indexers,
cache.SharedIndexInformerOptions{
ResyncPeriod: options.ResyncPeriod,
Indexers: options.Indexers,
Identifier: identifier,
},
)
}
func (f *operatorConfigurationInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredOperatorConfigurationInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
return NewOperatorConfigurationInformerWithOptions(client, f.namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions})
}
func (f *operatorConfigurationInformer) Informer() cache.SharedIndexInformer {
@@ -34,6 +34,7 @@ import (
acidzalandov1 "github.com/zalando/postgres-operator/pkg/generated/listers/acid.zalan.do/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
@@ -55,36 +56,61 @@ type postgresqlInformer struct {
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewPostgresqlInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredPostgresqlInformer(client, namespace, resyncPeriod, indexers, nil)
return NewPostgresqlInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers})
}
// NewFilteredPostgresqlInformer constructs a new informer for Postgresql type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredPostgresqlInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
return NewPostgresqlInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions})
}
// NewPostgresqlInformerWithOptions constructs a new informer for Postgresql type with additional options.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewPostgresqlInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer {
gvr := schema.GroupVersionResource{Group: "acid.zalan.do", Version: "v1", Resource: "postgresqls"}
identifier := options.InformerName.WithResource(gvr)
tweakListOptions := options.TweakListOptions
return cache.NewSharedIndexInformerWithOptions(
cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
tweakListOptions(&opts)
}
return client.AcidV1().Postgresqls(namespace).List(context.TODO(), options)
return client.AcidV1().Postgresqls(namespace).List(context.Background(), opts)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
tweakListOptions(&opts)
}
return client.AcidV1().Postgresqls(namespace).Watch(context.TODO(), options)
return client.AcidV1().Postgresqls(namespace).Watch(context.Background(), opts)
},
},
ListWithContextFunc: func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.AcidV1().Postgresqls(namespace).List(ctx, opts)
},
WatchFuncWithContext: func(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.AcidV1().Postgresqls(namespace).Watch(ctx, opts)
},
}, client),
&apisacidzalandov1.Postgresql{},
resyncPeriod,
indexers,
cache.SharedIndexInformerOptions{
ResyncPeriod: options.ResyncPeriod,
Indexers: options.Indexers,
Identifier: identifier,
},
)
}
func (f *postgresqlInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredPostgresqlInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
return NewPostgresqlInformerWithOptions(client, f.namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions})
}
func (f *postgresqlInformer) Informer() cache.SharedIndexInformer {
@@ -34,6 +34,7 @@ import (
acidzalandov1 "github.com/zalando/postgres-operator/pkg/generated/listers/acid.zalan.do/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
@@ -55,36 +56,61 @@ type postgresTeamInformer struct {
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewPostgresTeamInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredPostgresTeamInformer(client, namespace, resyncPeriod, indexers, nil)
return NewPostgresTeamInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers})
}
// NewFilteredPostgresTeamInformer constructs a new informer for PostgresTeam type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredPostgresTeamInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
return NewPostgresTeamInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions})
}
// NewPostgresTeamInformerWithOptions constructs a new informer for PostgresTeam type with additional options.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewPostgresTeamInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer {
gvr := schema.GroupVersionResource{Group: "acid.zalan.do", Version: "v1", Resource: "postgresteams"}
identifier := options.InformerName.WithResource(gvr)
tweakListOptions := options.TweakListOptions
return cache.NewSharedIndexInformerWithOptions(
cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
tweakListOptions(&opts)
}
return client.AcidV1().PostgresTeams(namespace).List(context.TODO(), options)
return client.AcidV1().PostgresTeams(namespace).List(context.Background(), opts)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
tweakListOptions(&opts)
}
return client.AcidV1().PostgresTeams(namespace).Watch(context.TODO(), options)
return client.AcidV1().PostgresTeams(namespace).Watch(context.Background(), opts)
},
},
ListWithContextFunc: func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.AcidV1().PostgresTeams(namespace).List(ctx, opts)
},
WatchFuncWithContext: func(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.AcidV1().PostgresTeams(namespace).Watch(ctx, opts)
},
}, client),
&apisacidzalandov1.PostgresTeam{},
resyncPeriod,
indexers,
cache.SharedIndexInformerOptions{
ResyncPeriod: options.ResyncPeriod,
Indexers: options.Indexers,
Identifier: identifier,
},
)
}
func (f *postgresTeamInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredPostgresTeamInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
return NewPostgresTeamInformerWithOptions(client, f.namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions})
}
func (f *postgresTeamInformer) Informer() cache.SharedIndexInformer {
@@ -25,6 +25,7 @@ SOFTWARE.
package externalversions
import (
context "context"
reflect "reflect"
sync "sync"
time "time"
@@ -36,6 +37,7 @@ import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
wait "k8s.io/apimachinery/pkg/util/wait"
cache "k8s.io/client-go/tools/cache"
)
@@ -50,6 +52,7 @@ type sharedInformerFactory struct {
defaultResync time.Duration
customResync map[reflect.Type]time.Duration
transform cache.TransformFunc
informerName *cache.InformerName
informers map[reflect.Type]cache.SharedIndexInformer
// startedInformers is used for tracking which informers have been started.
@@ -96,6 +99,21 @@ func WithTransform(transform cache.TransformFunc) SharedInformerOption {
}
}
// WithInformerName sets the InformerName for informer identity used in metrics.
// The InformerName must be created via cache.NewInformerName() at startup,
// which validates global uniqueness. Each informer type will register its
// GVR under this name.
func WithInformerName(informerName *cache.InformerName) SharedInformerOption {
return func(factory *sharedInformerFactory) *sharedInformerFactory {
factory.informerName = informerName
return factory
}
}
func (f *sharedInformerFactory) InformerName() *cache.InformerName {
return f.informerName
}
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
return NewSharedInformerFactoryWithOptions(client, defaultResync)
@@ -104,6 +122,7 @@ func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Dur
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
// Listers obtained via this SharedInformerFactory will be subject to the same filters
// as specified here.
//
// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
@@ -129,6 +148,10 @@ func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResy
}
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
f.StartWithContext(wait.ContextForChannel(stopCh))
}
func (f *sharedInformerFactory) StartWithContext(ctx context.Context) {
f.lock.Lock()
defer f.lock.Unlock()
@@ -138,15 +161,9 @@ func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
for informerType, informer := range f.informers {
if !f.startedInformers[informerType] {
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.wg.Go(func() {
informer.RunWithContext(ctx)
})
f.startedInformers[informerType] = true
}
}
@@ -159,9 +176,15 @@ func (f *sharedInformerFactory) Shutdown() {
// Will return immediately if there is nothing to wait for.
f.wg.Wait()
f.informerName.Release()
}
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
result := f.WaitForCacheSyncWithContext(wait.ContextForChannel(stopCh))
return result.Synced
}
func (f *sharedInformerFactory) WaitForCacheSyncWithContext(ctx context.Context) cache.SyncResult {
informers := func() map[reflect.Type]cache.SharedIndexInformer {
f.lock.Lock()
defer f.lock.Unlock()
@@ -175,10 +198,31 @@ func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[ref
return informers
}()
res := map[reflect.Type]bool{}
for informType, informer := range informers {
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
// Wait for informers to sync, without polling.
cacheSyncs := make([]cache.DoneChecker, 0, len(informers))
for _, informer := range informers {
cacheSyncs = append(cacheSyncs, informer.HasSyncedChecker())
}
cache.WaitFor(ctx, "" /* no logging */, cacheSyncs...)
res := cache.SyncResult{
Synced: make(map[reflect.Type]bool, len(informers)),
}
failed := false
for informType, informer := range informers {
hasSynced := informer.HasSynced()
if !hasSynced {
failed = true
}
res.Synced[informType] = hasSynced
}
if failed {
// context.Cause is more informative than ctx.Err().
// This must be non-nil, otherwise WaitFor wouldn't have stopped
// prematurely.
res.Err = context.Cause(ctx)
}
return res
}
@@ -200,7 +244,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal
}
informer = newFunc(f.client, resyncPeriod)
informer.SetTransform(f.transform)
if f.transform != nil {
informer.SetTransform(f.transform)
}
f.informers[informerType] = informer
return informer
@@ -211,33 +257,52 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal
//
// It is typically used like this:
//
// ctx, cancel := context.Background()
// ctx, cancel := context.WithCancel(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
// }
// handle, err := typeInformer.Informer().AddEventHandler(...)
// if err != nil {
// return fmt.Errorf("register event handler: %v", err)
// }
// defer typeInformer.Informer().RemoveEventHandler(handle) // Avoids leaking goroutines.
// factory.StartWithContext(ctx) // Start processing these informers.
// synced := factory.WaitForCacheSyncWithContext(ctx)
// if err := synced.AsError(); err != nil {
// return err
// }
// for v := range synced {
// // Only if desired log some information similar to this.
// fmt.Fprintf(os.Stdout, "cache synced: %s", v)
// }
//
// // Also make sure that all of the initial cache events have been delivered.
// if !WaitFor(ctx, "event handler sync", handle.HasSyncedChecker()) {
// // Must have failed because of context.
// return fmt.Errorf("sync event handler: %w", context.Cause(ctx))
// }
//
// // Creating informers can also be created after Start, but then
// // Start must be called again:
// anotherGenericInformer := factory.ForResource(resource)
// factory.Start(ctx.Done())
// factory.StartWithContext(ctx)
type SharedInformerFactory interface {
internalinterfaces.SharedInformerFactory
// Start initializes all requested informers. They are handled in goroutines
// which run until the stop channel gets closed.
// Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync.
//
// Contextual logging: StartWithContext should be used instead of Start in code which supports contextual logging.
Start(stopCh <-chan struct{})
// StartWithContext initializes all requested informers. They are handled in goroutines
// which run until the context gets canceled.
// Warning: StartWithContext does not block. When run in a go-routine, it will race with a later WaitForCacheSync.
StartWithContext(ctx context.Context)
// Shutdown marks a factory as shutting down. At that point no new
// informers can be started anymore and Start will return without
// doing anything.
@@ -252,8 +317,14 @@ type SharedInformerFactory interface {
// WaitForCacheSync blocks until all started informers' caches were synced
// or the stop channel gets closed.
//
// Contextual logging: WaitForCacheSync should be used instead of WaitForCacheSync in code which supports contextual logging. It also returns a more useful result.
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
// WaitForCacheSyncWithContext blocks until all started informers' caches were synced
// or the context gets canceled.
WaitForCacheSyncWithContext(ctx context.Context) cache.SyncResult
// ForResource gives generic access to a shared informer of the matching type.
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
@@ -40,7 +40,26 @@ type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexI
type SharedInformerFactory interface {
Start(stopCh <-chan struct{})
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
InformerName() *cache.InformerName
}
// TweakListOptionsFunc is a function that transforms a v1.ListOptions.
type TweakListOptionsFunc func(*v1.ListOptions)
// InformerOptions holds the options for creating an informer.
type InformerOptions struct {
// ResyncPeriod is the resync period for this informer.
// If not set, defaults to 0 (no resync).
ResyncPeriod time.Duration
// Indexers are the indexers for this informer.
Indexers cache.Indexers
// InformerName is used to uniquely identify this informer for metrics.
// If not set, metrics will not be published for this informer.
// Use cache.NewInformerName() to create an InformerName at startup.
InformerName *cache.InformerName
// TweakListOptions is an optional function to modify the list options.
TweakListOptions TweakListOptionsFunc
}
@@ -34,6 +34,7 @@ import (
zalandoorgv1 "github.com/zalando/postgres-operator/pkg/generated/listers/zalando.org/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
@@ -55,36 +56,61 @@ type fabricEventStreamInformer struct {
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFabricEventStreamInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredFabricEventStreamInformer(client, namespace, resyncPeriod, indexers, nil)
return NewFabricEventStreamInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers})
}
// NewFilteredFabricEventStreamInformer constructs a new informer for FabricEventStream type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredFabricEventStreamInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
return NewFabricEventStreamInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions})
}
// NewFabricEventStreamInformerWithOptions constructs a new informer for FabricEventStream type with additional options.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFabricEventStreamInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer {
gvr := schema.GroupVersionResource{Group: "zalando.org", Version: "v1", Resource: "fabriceventstreams"}
identifier := options.InformerName.WithResource(gvr)
tweakListOptions := options.TweakListOptions
return cache.NewSharedIndexInformerWithOptions(
cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
tweakListOptions(&opts)
}
return client.ZalandoV1().FabricEventStreams(namespace).List(context.TODO(), options)
return client.ZalandoV1().FabricEventStreams(namespace).List(context.Background(), opts)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
tweakListOptions(&opts)
}
return client.ZalandoV1().FabricEventStreams(namespace).Watch(context.TODO(), options)
return client.ZalandoV1().FabricEventStreams(namespace).Watch(context.Background(), opts)
},
},
ListWithContextFunc: func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.ZalandoV1().FabricEventStreams(namespace).List(ctx, opts)
},
WatchFuncWithContext: func(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.ZalandoV1().FabricEventStreams(namespace).Watch(ctx, opts)
},
}, client),
&apiszalandoorgv1.FabricEventStream{},
resyncPeriod,
indexers,
cache.SharedIndexInformerOptions{
ResyncPeriod: options.ResyncPeriod,
Indexers: options.Indexers,
Identifier: identifier,
},
)
}
func (f *fabricEventStreamInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredFabricEventStreamInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
return NewFabricEventStreamInformerWithOptions(client, f.namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions})
}
func (f *fabricEventStreamInformer) Informer() cache.SharedIndexInformer {