...

Source file src/sigs.k8s.io/controller-runtime/example_test.go

Documentation: sigs.k8s.io/controller-runtime

     1  /*
     2  Copyright 2018 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package controllerruntime_test
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"os"
    24  	"time"
    25  
    26  	appsv1 "k8s.io/api/apps/v1"
    27  	corev1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/runtime"
    30  	"k8s.io/apimachinery/pkg/types"
    31  
    32  	ctrl "sigs.k8s.io/controller-runtime"
    33  	"sigs.k8s.io/controller-runtime/pkg/client"
    34  	"sigs.k8s.io/controller-runtime/pkg/handler"
    35  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    36  
    37  	// since we invoke tests with -ginkgo.junit-report we need to import ginkgo.
    38  	_ "github.com/onsi/ginkgo/v2"
    39  )
    40  
    41  // This example creates a simple application Controller that is configured for ReplicaSets and Pods.
    42  //
    43  // * Create a new application for ReplicaSets that manages Pods owned by the ReplicaSet and calls into
    44  // ReplicaSetReconciler.
    45  //
    46  // * Start the application.
    47  func Example() {
    48  	log := ctrl.Log.WithName("builder-examples")
    49  
    50  	manager, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{})
    51  	if err != nil {
    52  		log.Error(err, "could not create manager")
    53  		os.Exit(1)
    54  	}
    55  
    56  	err = ctrl.
    57  		NewControllerManagedBy(manager). // Create the Controller
    58  		For(&appsv1.ReplicaSet{}).       // ReplicaSet is the Application API
    59  		Owns(&corev1.Pod{}).             // ReplicaSet owns Pods created by it
    60  		Complete(&ReplicaSetReconciler{Client: manager.GetClient()})
    61  	if err != nil {
    62  		log.Error(err, "could not create controller")
    63  		os.Exit(1)
    64  	}
    65  
    66  	if err := manager.Start(ctrl.SetupSignalHandler()); err != nil {
    67  		log.Error(err, "could not start manager")
    68  		os.Exit(1)
    69  	}
    70  }
    71  
    72  type ExampleCRDWithConfigMapRef struct {
    73  	metav1.TypeMeta   `json:",inline"`
    74  	metav1.ObjectMeta `json:"metadata,omitempty"`
    75  	ConfigMapRef      corev1.LocalObjectReference `json:"configMapRef"`
    76  }
    77  
    78  func deepCopyObject(arg any) runtime.Object {
    79  	// DO NOT use this code in production code, this is only for presentation purposes.
    80  	// in real code you should generate DeepCopy methods by using controller-gen CLI tool.
    81  	argBytes, err := json.Marshal(arg)
    82  	if err != nil {
    83  		panic(err)
    84  	}
    85  	out := &ExampleCRDWithConfigMapRefList{}
    86  	if err := json.Unmarshal(argBytes, out); err != nil {
    87  		panic(err)
    88  	}
    89  	return out
    90  }
    91  
    92  // DeepCopyObject implements client.Object.
    93  func (in *ExampleCRDWithConfigMapRef) DeepCopyObject() runtime.Object {
    94  	return deepCopyObject(in)
    95  }
    96  
    97  type ExampleCRDWithConfigMapRefList struct {
    98  	metav1.TypeMeta `json:",inline"`
    99  	metav1.ListMeta `json:"metadata,omitempty"`
   100  	Items           []ExampleCRDWithConfigMapRef `json:"items"`
   101  }
   102  
   103  // DeepCopyObject implements client.ObjectList.
   104  func (in *ExampleCRDWithConfigMapRefList) DeepCopyObject() runtime.Object {
   105  	return deepCopyObject(in)
   106  }
   107  
   108  // This example creates a simple application Controller that is configured for ExampleCRDWithConfigMapRef CRD.
   109  // Any change in the configMap referenced in this Custom Resource will cause the re-reconcile of the parent ExampleCRDWithConfigMapRef
   110  // due to the implementation of the .Watches method of "sigs.k8s.io/controller-runtime/pkg/builder".Builder.
   111  func Example_customHandler() {
   112  	log := ctrl.Log.WithName("builder-examples")
   113  
   114  	manager, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{})
   115  	if err != nil {
   116  		log.Error(err, "could not create manager")
   117  		os.Exit(1)
   118  	}
   119  
   120  	err = ctrl.
   121  		NewControllerManagedBy(manager).
   122  		For(&ExampleCRDWithConfigMapRef{}).
   123  		Watches(&corev1.ConfigMap{}, handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, cm client.Object) []ctrl.Request {
   124  			// map a change from referenced configMap to ExampleCRDWithConfigMapRef, which causes its re-reconcile
   125  			crList := &ExampleCRDWithConfigMapRefList{}
   126  			if err := manager.GetClient().List(ctx, crList); err != nil {
   127  				manager.GetLogger().Error(err, "while listing ExampleCRDWithConfigMapRefs")
   128  				return nil
   129  			}
   130  
   131  			reqs := make([]ctrl.Request, 0, len(crList.Items))
   132  			for _, item := range crList.Items {
   133  				if item.ConfigMapRef.Name == cm.GetName() {
   134  					reqs = append(reqs, ctrl.Request{
   135  						NamespacedName: types.NamespacedName{
   136  							Namespace: item.GetNamespace(),
   137  							Name:      item.GetName(),
   138  						},
   139  					})
   140  				}
   141  			}
   142  
   143  			return reqs
   144  		})).
   145  		Complete(reconcile.Func(func(ctx context.Context, r reconcile.Request) (reconcile.Result, error) {
   146  			// Your business logic to implement the API by creating, updating, deleting objects goes here.
   147  			return reconcile.Result{}, nil
   148  		}))
   149  	if err != nil {
   150  		log.Error(err, "could not create controller")
   151  		os.Exit(1)
   152  	}
   153  
   154  	if err := manager.Start(ctrl.SetupSignalHandler()); err != nil {
   155  		log.Error(err, "could not start manager")
   156  		os.Exit(1)
   157  	}
   158  }
   159  
   160  // This example creates a simple application Controller that is configured for ReplicaSets and Pods.
   161  // This application controller will be running leader election with the provided configuration in the manager options.
   162  // If leader election configuration is not provided, controller runs leader election with default values.
   163  // Default values taken from: https://github.com/kubernetes/component-base/blob/master/config/v1alpha1/defaults.go
   164  // * defaultLeaseDuration = 15 * time.Second
   165  // * defaultRenewDeadline = 10 * time.Second
   166  // * defaultRetryPeriod   = 2 * time.Second
   167  //
   168  // * Create a new application for ReplicaSets that manages Pods owned by the ReplicaSet and calls into
   169  // ReplicaSetReconciler.
   170  //
   171  // * Start the application.
   172  func Example_updateLeaderElectionDurations() {
   173  	log := ctrl.Log.WithName("builder-examples")
   174  	leaseDuration := 100 * time.Second
   175  	renewDeadline := 80 * time.Second
   176  	retryPeriod := 20 * time.Second
   177  	manager, err := ctrl.NewManager(
   178  		ctrl.GetConfigOrDie(),
   179  		ctrl.Options{
   180  			LeaseDuration: &leaseDuration,
   181  			RenewDeadline: &renewDeadline,
   182  			RetryPeriod:   &retryPeriod,
   183  		})
   184  	if err != nil {
   185  		log.Error(err, "could not create manager")
   186  		os.Exit(1)
   187  	}
   188  
   189  	err = ctrl.
   190  		NewControllerManagedBy(manager). // Create the Controller
   191  		For(&appsv1.ReplicaSet{}).       // ReplicaSet is the Application API
   192  		Owns(&corev1.Pod{}).             // ReplicaSet owns Pods created by it
   193  		Complete(&ReplicaSetReconciler{Client: manager.GetClient()})
   194  	if err != nil {
   195  		log.Error(err, "could not create controller")
   196  		os.Exit(1)
   197  	}
   198  
   199  	if err := manager.Start(ctrl.SetupSignalHandler()); err != nil {
   200  		log.Error(err, "could not start manager")
   201  		os.Exit(1)
   202  	}
   203  }
   204  
   205  // ReplicaSetReconciler is a simple Controller example implementation.
   206  type ReplicaSetReconciler struct {
   207  	client.Client
   208  }
   209  
   210  // Implement the business logic:
   211  // This function will be called when there is a change to a ReplicaSet or a Pod with an OwnerReference
   212  // to a ReplicaSet.
   213  //
   214  // * Read the ReplicaSet
   215  // * Read the Pods
   216  // * Set a Label on the ReplicaSet with the Pod count.
   217  func (a *ReplicaSetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
   218  	// Read the ReplicaSet
   219  	rs := &appsv1.ReplicaSet{}
   220  	err := a.Get(ctx, req.NamespacedName, rs)
   221  	if err != nil {
   222  		return ctrl.Result{}, err
   223  	}
   224  
   225  	// List the Pods matching the PodTemplate Labels
   226  	pods := &corev1.PodList{}
   227  	err = a.List(ctx, pods, client.InNamespace(req.Namespace), client.MatchingLabels(rs.Spec.Template.Labels))
   228  	if err != nil {
   229  		return ctrl.Result{}, err
   230  	}
   231  
   232  	// Update the ReplicaSet
   233  	rs.Labels["pod-count"] = fmt.Sprintf("%v", len(pods.Items))
   234  	err = a.Update(ctx, rs)
   235  	if err != nil {
   236  		return ctrl.Result{}, err
   237  	}
   238  
   239  	return ctrl.Result{}, nil
   240  }
   241  

View as plain text