Skip to content

Commit 72ab36a

Browse files
author
Eric Stroczynski
authored
docs: update old links, FAQ, and Reconcile() code references (#4333)
1 parent f89a2c3 commit 72ab36a

File tree

6 files changed

+56
-63
lines changed

6 files changed

+56
-63
lines changed

website/content/en/docs/building-operators/golang/advanced-topics.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,7 @@ import (
142142
143143
const memcachedFinalizer = "finalizer.cache.example.com"
144144
145-
func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
146-
ctx := context.Background()
145+
func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
147146
reqLogger := r.log.WithValues("memcached", req.NamespacedName)
148147
reqLogger.Info("Reconciling Memcached")
149148

website/content/en/docs/building-operators/golang/migration.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ E.g `kubectl logs deployment.apps/memcached-operator-controller-manager -n memca
331331
[integration-doc]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/integrating-kubebuilder-and-osdk.md
332332
[quickstart]: /docs/building-operators/golang/quickstart/
333333
[metrics]: https://book.kubebuilder.io/reference/metrics.html?highlight=metr#metrics
334-
[memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/memcached-operator/controllers/memcached_controller.go
334+
[memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/v1.2.0/testdata/go/memcached-operator/controllers/memcached_controller.go
335335
[rbac_markers]: https://book.kubebuilder.io/reference/markers/rbac.html
336336
[kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy
337337
[markers]: https://book.kubebuilder.io/reference/markers.html?highlight=markers#marker-syntax
@@ -350,4 +350,4 @@ E.g `kubectl logs deployment.apps/memcached-operator-controller-manager -n memca
350350
[ctrl-options]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/manager#Options
351351
[envtest]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/envtest
352352
[gomega]: https://onsi.github.io/gomega/
353-
[multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html
353+
[multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html

website/content/en/docs/building-operators/golang/references/client.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Creating a new Client is not usually necessary nor advised, as the default Clien
8282

8383
### Reconcile and the Client API
8484

85-
A Reconciler implements the [`reconcile.Reconciler`][doc-reconcile-reconciler] interface, which exposes the Reconcile method. Reconcilers are added to a corresponding Controller for a Kind; Reconcile is called in response to cluster or external Events, with a `reconcile.Request` object argument, to read and write cluster state by the Controller, and returns a `reconcile.Result`. SDK Reconcilers have access to a Client in order to make Kubernetes API calls.
85+
A Reconciler implements the [`reconcile.Reconciler`][doc-reconcile-reconciler] interface, which exposes the Reconcile method. Reconcilers are added to a corresponding Controller for a Kind; Reconcile is called in response to cluster or external Events, with a `reconcile.Request` object argument, to read and write cluster state by the Controller, and returns a `ctrl.Result`. SDK Reconcilers have access to a Client in order to make Kubernetes API calls.
8686

8787
```Go
8888
// KindReconciler reconciles a Kind object
@@ -106,7 +106,7 @@ type KindReconciler struct {
106106
// The Controller will requeue the Request to be processed again if an error
107107
// is non-nil or Result.Requeue is true, otherwise upon completion it will
108108
// remove the work from the queue.
109-
func (r *KindReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error)
109+
func (r *KindReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error)
110110
```
111111

112112
Reconcile is where Controller business logic lives, i.e. where Client API calls are made via `KindReconciler.client`. A `client.Client` implementer performs the following operations:
@@ -128,7 +128,7 @@ import (
128128
ctrl "sigs.k8s.io/controller-runtime"
129129
)
130130

131-
func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) {
131+
func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) {
132132
...
133133

134134
app := &v1alpha1.App{}
@@ -160,7 +160,7 @@ import (
160160
ctrl "sigs.k8s.io/controller-runtime"
161161
)
162162

163-
func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) {
163+
func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) {
164164
...
165165

166166
// Return all pods in the request namespace with a label of `app=<name>`
@@ -202,7 +202,7 @@ import (
202202
ctrl "sigs.k8s.io/controller-runtime"
203203
)
204204

205-
func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) {
205+
func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) {
206206
...
207207

208208
app := &v1.Deployment{ // Any cluster object you want to create.
@@ -238,7 +238,7 @@ import (
238238
ctrl "sigs.k8s.io/controller-runtime"
239239
)
240240

241-
func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) {
241+
func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) {
242242
...
243243

244244
dep := &v1.Deployment{}
@@ -276,7 +276,7 @@ import (
276276
ctrl "sigs.k8s.io/controller-runtime"
277277
)
278278

279-
func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) {
279+
func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) {
280280
...
281281

282282
dep := &v1.Deployment{}
@@ -320,7 +320,7 @@ import (
320320
ctrl "sigs.k8s.io/controller-runtime"
321321
)
322322

323-
func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) {
323+
func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) {
324324
...
325325

326326
ctx := context.TODO()
@@ -365,7 +365,7 @@ import (
365365
ctrl "sigs.k8s.io/controller-runtime"
366366
)
367367

368-
func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) {
368+
func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) {
369369
...
370370

371371
pod := &v1.Pod{}
@@ -409,7 +409,7 @@ import (
409409
ctrl "sigs.k8s.io/controller-runtime"
410410
)
411411

412-
func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) {
412+
func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) {
413413
...
414414

415415
// Delete all pods in the request namespace with a label of `app=<name>`
@@ -457,7 +457,7 @@ type AppReconciler struct {
457457
Scheme *runtime.Scheme
458458
}
459459

460-
func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
460+
func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) {
461461

462462
// Fetch the App instance.
463463
app := &appv1alpha1.App{}

website/content/en/docs/building-operators/golang/references/logging.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,7 @@ type MemcachedReconciler struct {
202202
Scheme *runtime.Scheme
203203
}
204204

205-
func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
206-
ctx := context.Background()
205+
func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
207206
log := r.Log.WithValues("memcached", req.NamespacedName)
208207

209208
// Fetch the Memcached instance
@@ -260,7 +259,7 @@ If you do not want to use `logr` as your logging tool, you can remove `logr`-spe
260259
[repo_zapr]:https://godoc.org/github.com/go-logr/zapr
261260
[godoc_logr_logger]:https://godoc.org/github.com/go-logr/logr#Logger
262261
[site_struct_logging]:https://www.client9.com/structured-logging-in-golang/
263-
[code_memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/memcached-operator/controllers/memcached_controller.go
262+
[code_memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/v1.2.0/testdata/go/memcached-operator/controllers/memcached_controller.go
264263
[logfmt_repo]:https://github.com/jsternberg/zap-logfmt
265264
[controller_runtime_zap]:https://github.com/kubernetes-sigs/controller-runtime/tree/master/pkg/log/zap
266265
[logging_godocs]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/log/zap#Options.BindFlags

website/content/en/docs/building-operators/golang/tutorial.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ import (
225225
...
226226
)
227227

228-
func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
228+
func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
229229
// Lookup the Memcached instance for this reconcile request
230230
memcached := &cachev1alpha1.Memcached{}
231231
err := r.Get(ctx, req.NamespacedName, memcached)
@@ -267,7 +267,9 @@ The controller needs certain RBAC permissions to interact with the resources it
267267
// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
268268
// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;
269269

270-
func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
270+
func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
271+
...
272+
}
271273
```
272274

273275
The `ClusterRole` manifest at `config/rbac/role.yaml` is generated from the above markers via controller-gen with the following command:
@@ -493,7 +495,7 @@ Also see the [advanced topics][advanced_topics] doc for more use cases and under
493495
[markers]: https://book.kubebuilder.io/reference/markers.html
494496
[crd-markers]: https://book.kubebuilder.io/reference/markers/crd-validation.html
495497
[rbac-markers]: https://book.kubebuilder.io/reference/markers/rbac.html
496-
[memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/memcached-operator/controllers/memcached_controller.go
498+
[memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/v1.2.0/testdata/go/memcached-operator/controllers/memcached_controller.go
497499
[builder_godocs]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/builder#example-Builder
498500
[legacy_quickstart_doc]:https://v0-19-x.sdk.operatorframework.io/docs/golang/legacy/quickstart/
499501
[activate_modules]: https://github.com/golang/go/wiki/Modules#how-to-install-and-activate-module-support

website/content/en/docs/faqs/_index.md

Lines changed: 35 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -33,88 +33,81 @@ For more information on `kube-apiserver` request timeout options, see the [Kuber
3333

3434
Unfortunately, adding the entire dependency tree for all Ansible modules would be excessive. Fortunately, you can add it easily. Simply edit your build/Dockerfile. You'll want to change to root for the install command, just be sure to swap back using a series of commands like the following right after the `FROM` line.
3535

36-
```
36+
```docker
3737
USER 0
3838
RUN yum -y install my-dependency
3939
RUN pip3 install my-python-dependency
4040
USER 1001
4141
```
4242

43-
If you aren't sure what dependencies are required, start up a container using the image in the `FROM` line as root. That will look something like this.
44-
`docker run -u 0 -it --rm --entrypoint /bin/bash quay.io/operator-framework/ansible-operator:<sdk-tag-version>`
43+
If you aren't sure what dependencies are required, start up a container using the image in the `FROM` line as root. That will look something like this:
44+
```sh
45+
docker run -u 0 -it --rm --entrypoint /bin/bash quay.io/operator-framework/ansible-operator:<sdk-tag-version>
46+
```
4547

4648
## I keep seeing errors like "Failed to watch", how do I fix this?
4749

48-
If you run into the following error message, it means that your operator is unable to watch the resoruce:
50+
If you run into the following error message, it means that your operator is unable to watch the resource:
4951

5052
```
5153
E0320 15:42:17.676888 1 reflector.go:280] pkg/mod/k8s.io/[email protected]/tools/cache/reflector.go:96: Failed to watch *v1.ImageStreamTag: unknown (get imagestreamtags.image.openshift.io)
5254
{"level":"info","ts":1584718937.766342,"logger":"controller_memcached","msg":"ImageStreamTag resource not found.
5355
```
5456

55-
Using controller-runtime's split client means that read operations (gets and lists) are read from a cache, and write operations are written directly to the API server. To populate the cache for reads, controller-runtime initiates a `list` and then a `watch` even when your operator is only attempting to `get` a single resource. The above scenario occurs when the operator does not have an (RBAC)[rbac] permission to `watch` the resource. The solution is to grant permission in the `config/rbac/role.yaml` file.
57+
Using controller-runtime's split client means that read operations (gets and lists) are read from a cache, and write operations are written directly to the API server. To populate the cache for reads, controller-runtime initiates a `list` and then a `watch` even when your operator is only attempting to `get` a single resource. The above scenario occurs when the operator does not have an [RBAC][rbac] permission to `watch` the resource. The solution is to add an RBAC directive to generate a `config/rbac/role.yaml` with `watch` privileges:
5658

57-
In rare cases, it also could be that the particular resource does not implement the `watch` verb. In this case, it is necessary to use the [client.Reader][client.Reader] instead of the default split client. The manager's `GetAPIReader()` function can be used to get this reader.
58-
59-
**Example**
59+
```go
60+
// +kubebuilder:rbac:groups=some.group.com,resources=myresources,verbs=watch
61+
```
6062

61-
Here is an example that demonstrates how to use a `client.Reader` when a resource does not implement the `watch` verb:
63+
Alternatively, if the resource you're attempting to cannot be watched (like `v1.ImageStreamTag` above), you can specify that objects of this type should not be cached by adding the following to `main.go`:
6264

6365
```go
64-
6566
import (
6667
...
6768
imagev1 "github.com/openshift/api/image/v1"
6869
)
6970

70-
...
71-
72-
// newReconciler returns a new reconcile.Reconciler
73-
func newReconciler(mgr manager.Manager) reconcile.Reconciler {
74-
return &ReconcileMemcached{client: mgr.GetClient(), scheme: mgr.GetScheme(), APIReader: mgr.GetAPIReader() }
71+
var (
72+
scheme = runtime.NewScheme()
73+
)
7574

75+
func init() {
76+
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
77+
// Add imagev1's scheme.
78+
utilruntime.Must(imagev1.AddToScheme(scheme))
7679
}
7780

78-
...
79-
80-
// ReconcileMemcached reconciles a Memcached object
81-
type ReconcileMemcached struct {
82-
// TODO: Clarify the split client
83-
// This client, initialized using mgr.Client() above, is a split client
84-
// that reads objects from the cache and writes to the apiserver
85-
client client.Client
86-
scheme *runtime.Scheme
87-
APIReader client.Reader // the APIReader will not use the cache
81+
func main() {
82+
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
83+
Scheme: scheme,
84+
// Specify that ImageStreamTag's should not be cached.
85+
ClientBuilder: manager.NewClientBuilder().WithUncached(&imagev1.ImageStreamTag{}),
86+
})
8887
}
88+
```
8989

90-
...
91-
func (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Result, error) {
92-
93-
// Get the ImageStreamTag from OCP API which has not the WATCH verb.
94-
img := &imagev1.ImageStreamTag{}
95-
err = r.APIReader.Get(context.TODO(), types.NamespacedName{Name: fmt.Sprintf("%s:%s", "example-name", "example-tag"), img)
96-
if err != nil {
97-
if errors.IsNotFound(err) {
98-
reqLogger.Info("resource not found")
99-
} else {
100-
reqLogger.Error(err, "unexpected error")
101-
}
102-
}
90+
Then in your controller file, add an RBAC directive to generate a `config/rbac/role.yaml` with `get` privileges:
91+
92+
```go
93+
// +kubebuilder:rbac:groups=image.openshift.io,resources=imagestreamtags,verbs=get
10394
```
10495

96+
Now run `make manifests` to update your `role.yaml`.
97+
98+
10599
## I keep hitting errors like "is forbidden: cannot set blockOwnerDeletion if an ownerReference refers to a resource you can't set finalizers on:", how do I fix this?
106100

107101
If you are facing this issue, it means that the operator is missing the required RBAC permissions to update finalizers on the APIs it manages. This permission is necessary if the [OwnerReferencesPermissionEnforcement][owner-references-permission-enforcement] plugin is enabled in your cluster.
108102

109-
For Helm and Ansible operators, this permission is configured by default. However for Go operators, it may be necessary to add this permission yourself.
110-
111-
In Go operators, RBAC permissions are configured via [RBAC markers][rbac-markers], which are used to generate and update the manifest files present in `config/rbac/`. Add the following marker line on your controller's `Reconcile()` method:
103+
For Helm and Ansible operators, this permission is configured by default. However for Go operators, it may be necessary to add this permission yourself
104+
by adding an RBAC directive to generate a `config/rbac/role.yaml` with `update` privileges on your CR's finalizers:
112105

113106
```go
114107
// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update
115108
```
116109

117-
To update `config/rbac/role.yaml` after changing the markers, run `make manifests`.
110+
Now run `make manifests` to update your `role.yaml`.
118111

119112

120113
[kube-apiserver_options]: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/#options

0 commit comments

Comments
 (0)