Skip to content

Commit e787eaa

Browse files
authored
📖 Add more examples in documentation (#2498)
* Add more examples in documentation * update examples after review
1 parent bb09db8 commit e787eaa

File tree

4 files changed

+120
-8
lines changed

4 files changed

+120
-8
lines changed

example_test.go

+97-2
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,21 @@ package controllerruntime_test
1818

1919
import (
2020
"context"
21+
"encoding/json"
2122
"fmt"
2223
"os"
2324
"time"
2425

2526
appsv1 "k8s.io/api/apps/v1"
2627
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+
2732
ctrl "sigs.k8s.io/controller-runtime"
2833
"sigs.k8s.io/controller-runtime/pkg/client"
34+
"sigs.k8s.io/controller-runtime/pkg/handler"
35+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
2936

3037
// since we invoke tests with -ginkgo.junit-report we need to import ginkgo.
3138
_ "github.com/onsi/ginkgo/v2"
@@ -38,7 +45,7 @@ import (
3845
//
3946
// * Start the application.
4047
func Example() {
41-
var log = ctrl.Log.WithName("builder-examples")
48+
log := ctrl.Log.WithName("builder-examples")
4249

4350
manager, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{})
4451
if err != nil {
@@ -62,6 +69,94 @@ func Example() {
6269
}
6370
}
6471

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+
65160
// This example creates a simple application Controller that is configured for ReplicaSets and Pods.
66161
// This application controller will be running leader election with the provided configuration in the manager options.
67162
// If leader election configuration is not provided, controller runs leader election with default values.
@@ -75,7 +170,7 @@ func Example() {
75170
//
76171
// * Start the application.
77172
func Example_updateLeaderElectionDurations() {
78-
var log = ctrl.Log.WithName("builder-examples")
173+
log := ctrl.Log.WithName("builder-examples")
79174
leaseDuration := 100 * time.Second
80175
renewDeadline := 80 * time.Second
81176
retryPeriod := 20 * time.Second

pkg/builder/example_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import (
3838
func ExampleBuilder_metadata_only() {
3939
logf.SetLogger(zap.New())
4040

41-
var log = logf.Log.WithName("builder-examples")
41+
log := logf.Log.WithName("builder-examples")
4242

4343
mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{})
4444
if err != nil {
@@ -95,7 +95,7 @@ func ExampleBuilder_metadata_only() {
9595
func ExampleBuilder() {
9696
logf.SetLogger(zap.New())
9797

98-
var log = logf.Log.WithName("builder-examples")
98+
log := logf.Log.WithName("builder-examples")
9999

100100
mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{})
101101
if err != nil {

pkg/client/example_test.go

+17-2
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@ import (
2525
corev1 "k8s.io/api/core/v1"
2626
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2727
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
28+
"k8s.io/apimachinery/pkg/runtime"
2829
"k8s.io/apimachinery/pkg/runtime/schema"
2930
"k8s.io/apimachinery/pkg/types"
31+
corev1ac "k8s.io/client-go/applyconfigurations/core/v1"
3032

3133
"sigs.k8s.io/controller-runtime/pkg/client"
3234
"sigs.k8s.io/controller-runtime/pkg/client/config"
35+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3336
)
3437

3538
var (
@@ -159,7 +162,7 @@ func ExampleClient_update() {
159162
Namespace: "namespace",
160163
Name: "name",
161164
}, pod)
162-
pod.SetFinalizers(append(pod.GetFinalizers(), "new-finalizer"))
165+
controllerutil.AddFinalizer(pod, "new-finalizer")
163166
_ = c.Update(context.Background(), pod)
164167

165168
// Using a unstructured object.
@@ -173,7 +176,7 @@ func ExampleClient_update() {
173176
Namespace: "namespace",
174177
Name: "name",
175178
}, u)
176-
u.SetFinalizers(append(u.GetFinalizers(), "new-finalizer"))
179+
controllerutil.AddFinalizer(u, "new-finalizer")
177180
_ = c.Update(context.Background(), u)
178181
}
179182

@@ -188,6 +191,18 @@ func ExampleClient_patch() {
188191
}, client.RawPatch(types.StrategicMergePatchType, patch))
189192
}
190193

194+
// This example shows how to use the client with unstructured objects to create/patch objects using Server Side Apply,
195+
// "k8s.io/apimachinery/pkg/runtime".DefaultUnstructuredConverter.ToUnstructured is used to convert an object into map[string]any representation,
196+
// which is then set as an "Object" field in *unstructured.Unstructured struct, which implements client.Object.
197+
func ExampleClient_apply() {
198+
// Using a typed object.
199+
configMap := corev1ac.ConfigMap("name", "namespace").WithData(map[string]string{"key": "value"})
200+
// c is a created client.
201+
u := &unstructured.Unstructured{}
202+
u.Object, _ = runtime.DefaultUnstructuredConverter.ToUnstructured(configMap)
203+
_ = c.Patch(context.Background(), u, client.Apply, client.ForceOwnership, client.FieldOwner("field-owner"))
204+
}
205+
191206
// This example shows how to use the client with typed and unstructured objects to patch objects' status.
192207
func ExampleClient_patchStatus() {
193208
u := &unstructured.Unstructured{}

pkg/handler/example_test.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ import (
3232
"sigs.k8s.io/controller-runtime/pkg/source"
3333
)
3434

35-
var mgr manager.Manager
36-
var c controller.Controller
35+
var (
36+
mgr manager.Manager
37+
c controller.Controller
38+
)
3739

3840
// This example watches Pods and enqueues Requests with the Name and Namespace of the Pod from
3941
// the Event (i.e. change caused by a Create, Update, Delete).

0 commit comments

Comments
 (0)