sigs.k8s.io/controller-runtime@v0.18.2/example_test.go (about) 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 }