1
0
Fork 0
mirror of https://github.com/prometheus-operator/prometheus-operator.git synced 2025-04-16 09:16:38 +00:00
prometheus-operator/pkg/informers/informers.go
jaehanbyun d57143311b fix: Correct typo in comment
Replace ocured with occurred in the comment of the Get function.

Signed-off-by: jaehanbyun <awbrg789@naver.com>
2025-03-08 19:59:31 +09:00

219 lines
7.1 KiB
Go

// Copyright 2020 The prometheus-operator 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.
package informers
import (
"fmt"
"sort"
apierrors "k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/tools/cache"
"github.com/prometheus-operator/prometheus-operator/pkg/listwatch"
)
// InformLister is the interface that both exposes a shared index informer
// and a generic lister.
// Usually generated clients declare this interface as "GenericInformer".
type InformLister interface {
Informer() cache.SharedIndexInformer
Lister() cache.GenericLister
}
// FactoriesForNamespaces is a way to combine several shared informers into a single struct with unified listing power.
type FactoriesForNamespaces interface {
ForResource(namespace string, resource schema.GroupVersionResource) (InformLister, error)
Namespaces() sets.Set[string]
}
// ForResource contains a slice of InformLister for a concrete resource type,
// one per namespace.
type ForResource struct {
informers []InformLister
}
// NewInformersForResource returns a composite informer exposing the most basic set of operations
// needed from informers and listers. It does not implement a formal interface,
// but exposes a minimal set of methods from underlying slice of cache.SharedIndexInformers and cache.GenericListers.
//
// It takes a namespace aware informer factory, wrapped in a FactoriesForNamespaces interface
// that is able to instantiate an informer for a given namespace.
func NewInformersForResource(ifs FactoriesForNamespaces, resource schema.GroupVersionResource) (*ForResource, error) {
return NewInformersForResourceWithTransform(ifs, resource, nil)
}
func NewInformersForResourceWithTransform(ifs FactoriesForNamespaces, resource schema.GroupVersionResource, handler cache.TransformFunc) (*ForResource, error) {
namespaces := ifs.Namespaces().UnsortedList()
sort.Strings(namespaces)
informers := make([]InformLister, 0, len(namespaces))
for _, ns := range namespaces {
informer, err := ifs.ForResource(ns, resource)
if err != nil {
return nil, fmt.Errorf("error getting informer in namespace %q for resource %v: %w", ns, resource, err)
}
if handler != nil {
if err := informer.Informer().SetTransform(handler); err != nil {
return nil, fmt.Errorf("error setting transform in namespace %q for resource %v: %w", ns, resource, err)
}
}
informers = append(informers, informer)
}
return &ForResource{
informers: informers,
}, nil
}
// PartialObjectMetadataStrip removes the following fields from PartialObjectMetadata objects:
// * Annotations
// * Labels
// * ManagedFields
// * Finalizers
// * OwnerReferences.
//
// If the passed object isn't of type *v1.PartialObjectMetadata, it is returned unmodified.
//
// It matches the cache.TransformFunc type and can be used by informers
// watching PartialObjectMetadata objects to reduce memory consumption.
// See https://pkg.go.dev/k8s.io/client-go@v0.29.1/tools/cache#TransformFunc for details.
func PartialObjectMetadataStrip(obj interface{}) (interface{}, error) {
partialMeta, ok := obj.(*v1.PartialObjectMetadata)
if !ok {
// Don't do anything if the cast isn't successful.
// The object might be of type "cache.DeletedFinalStateUnknown".
return obj, nil
}
partialMeta.Annotations = nil
partialMeta.Labels = nil
partialMeta.ManagedFields = nil
partialMeta.Finalizers = nil
partialMeta.OwnerReferences = nil
return partialMeta, nil
}
// Start starts all underlying informers, passing the given stop channel to each of them.
func (w *ForResource) Start(stopCh <-chan struct{}) {
for _, i := range w.informers {
go i.Informer().Run(stopCh)
}
}
// GetInformers returns all wrapped informers.
func (w *ForResource) GetInformers() []InformLister {
return w.informers
}
// AddEventHandler registers the given handler to all wrapped informers.
func (w *ForResource) AddEventHandler(handler cache.ResourceEventHandler) {
for _, i := range w.informers {
_, _ = i.Informer().AddEventHandler(handler)
}
}
// HasSynced returns true if all underlying informers have synced, else false.
func (w *ForResource) HasSynced() bool {
for _, i := range w.informers {
if !i.Informer().HasSynced() {
return false
}
}
return true
}
// ListAll invokes the ListAll method for all wrapped informers passing the
// same selector and appendFn.
func (w *ForResource) ListAll(selector labels.Selector, appendFn cache.AppendFunc) error {
for _, inf := range w.informers {
err := cache.ListAll(inf.Informer().GetIndexer(), selector, appendFn)
if err != nil {
return err
}
}
return nil
}
// ListAllByNamespace invokes all wrapped informers passing the same appendFn.
// While wrapped informers are usually namespace aware, it is still important to iterate over all of them
// as some informers might wrap k8s.io/apimachinery/pkg/apis/meta/v1.NamespaceAll.
func (w *ForResource) ListAllByNamespace(namespace string, selector labels.Selector, appendFn cache.AppendFunc) error {
for _, inf := range w.informers {
err := cache.ListAllByNamespace(inf.Informer().GetIndexer(), namespace, selector, appendFn)
if err != nil {
return err
}
}
return nil
}
// Get invokes all wrapped informers and returns the first found runtime object.
// It returns the first occurred error.
func (w *ForResource) Get(name string) (runtime.Object, error) {
var err error
for _, inf := range w.informers {
var ret runtime.Object
ret, err = inf.Lister().Get(name)
if apierrors.IsNotFound(err) {
continue
}
if err != nil {
return nil, err
}
return ret, nil
}
return nil, err
}
// newInformerOptions returns a list option tweak function and a list of namespaces
// based on the given allowed and denied namespaces.
//
// If allowedNamespaces contains one only entry equal to k8s.io/apimachinery/pkg/apis/meta/v1.NamespaceAll
// then it returns it and a tweak function filtering denied namespaces using a field selector.
//
// Else, denied namespaces are ignored and just the set of allowed namespaces is returned.
func newInformerOptions(allowedNamespaces, deniedNamespaces map[string]struct{}, tweaks func(*v1.ListOptions)) (func(*v1.ListOptions), []string) {
if tweaks == nil {
tweaks = func(*v1.ListOptions) {} // nop
}
var namespaces []string
if listwatch.IsAllNamespaces(allowedNamespaces) {
return func(options *v1.ListOptions) {
tweaks(options)
listwatch.DenyTweak(options, "metadata.namespace", deniedNamespaces)
}, []string{v1.NamespaceAll}
}
for ns := range allowedNamespaces {
namespaces = append(namespaces, ns)
}
return tweaks, namespaces
}