github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controllerutil/util.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package controllerutil
    21  
    22  import (
    23  	"context"
    24  	"reflect"
    25  
    26  	corev1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/runtime"
    29  	"sigs.k8s.io/controller-runtime/pkg/client"
    30  	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
    31  
    32  	appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1"
    33  	"github.com/1aal/kubeblocks/pkg/constant"
    34  	viper "github.com/1aal/kubeblocks/pkg/viperx"
    35  )
    36  
    37  // GetUncachedObjects returns a list of K8s objects, for these object types,
    38  // and their list types, client.Reader will read directly from the API server instead
    39  // of the cache, which may not be up-to-date.
    40  // see sigs.k8s.io/controller-runtime/pkg/client/split.go to understand how client
    41  // works with this UncachedObjects filter.
    42  func GetUncachedObjects() []client.Object {
    43  	// client-side read cache reduces the number of requests processed in the API server,
    44  	// which is good for performance. However, it can sometimes lead to obscure issues,
    45  	// most notably lacking read-after-write consistency, i.e. reading a value immediately
    46  	// after updating it may miss to see the changes.
    47  	// while in most cases this problem can be mitigated by retrying later in an idempotent
    48  	// manner, there are some cases where it cannot, for example if a decision is to be made
    49  	// that has side-effect operations such as returning an error message to the user
    50  	// (in webhook) or deleting certain resources (in controllerutil.HandleCRDeletion).
    51  	// additionally, retry loops cause unnecessary delays when reconciliations are processed.
    52  	// for the sake of performance, now only the objects created by the end-user is listed here,
    53  	// to solve the two problems mentioned above.
    54  	// consider carefully before adding new objects to this list.
    55  	return []client.Object{
    56  		// avoid to cache potential large data objects
    57  		&corev1.ConfigMap{},
    58  		&corev1.Secret{},
    59  		&appsv1alpha1.Cluster{},
    60  		&appsv1alpha1.Configuration{},
    61  	}
    62  }
    63  
    64  // Event is wrapper for Recorder.Event, if Recorder is nil, then it's no-op.
    65  func (r *RequestCtx) Event(object runtime.Object, eventtype, reason, message string) {
    66  	if r == nil || r.Recorder == nil {
    67  		return
    68  	}
    69  	r.Recorder.Event(object, eventtype, reason, message)
    70  }
    71  
    72  // Eventf is wrapper for Recorder.Eventf, if Recorder is nil, then it's no-op.
    73  func (r *RequestCtx) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args ...interface{}) {
    74  	if r == nil || r.Recorder == nil {
    75  		return
    76  	}
    77  	r.Recorder.Eventf(object, eventtype, reason, messageFmt, args...)
    78  }
    79  
    80  // UpdateCtxValue updates Context value, returns parent Context.
    81  func (r *RequestCtx) UpdateCtxValue(key, val any) context.Context {
    82  	p := r.Ctx
    83  	r.Ctx = context.WithValue(r.Ctx, key, val)
    84  	return p
    85  }
    86  
    87  // WithValue returns a copy of parent in which the value associated with key is
    88  // val.
    89  func (r *RequestCtx) WithValue(key, val any) context.Context {
    90  	return context.WithValue(r.Ctx, key, val)
    91  }
    92  
    93  // IsRSMEnabled enables rsm by default.
    94  // respect the feature gate if set, keep the ability to disable it.
    95  func IsRSMEnabled() bool {
    96  	if viper.IsSet(constant.FeatureGateReplicatedStateMachine) {
    97  		return viper.GetBool(constant.FeatureGateReplicatedStateMachine)
    98  	}
    99  	return true
   100  }
   101  
   102  func IsNil(i interface{}) bool {
   103  	if i == nil {
   104  		return true
   105  	}
   106  	switch reflect.TypeOf(i).Kind() {
   107  	case reflect.Ptr, reflect.Map, reflect.Array, reflect.Chan, reflect.Slice:
   108  		return reflect.ValueOf(i).IsNil()
   109  	}
   110  	return false
   111  }
   112  
   113  var innerScheme, _ = appsv1alpha1.SchemeBuilder.Build()
   114  
   115  func SetOwnerReference(owner, object metav1.Object) error {
   116  	return controllerutil.SetOwnerReference(owner, object, innerScheme)
   117  }
   118  
   119  func SetControllerReference(owner, object metav1.Object) error {
   120  	return controllerutil.SetControllerReference(owner, object, innerScheme)
   121  }