From fe448f5661e658b934b10e0a5b3ed16077c9275a Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Fri, 8 May 2020 13:13:15 -0700 Subject: [PATCH 01/19] update 3rd party resource docs --- .../en/docs/kubebuilder/advanced-topics.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 01ef1de74e5..f9cec4f3e18 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -34,12 +34,12 @@ The operator's Manager supports the core Kubernetes resource types as found in t ```Go import ( - "github.com/example-inc/memcached-operator/pkg/apis" + cachev1alpha1 "github.com/example-inc/memcached-operator/api/v1alpha1 ... ) // Setup Scheme for all resources -if err := apis.AddToScheme(mgr.GetScheme()); err != nil { +if err := cachev1alpha1.AddToScheme(mgr.GetScheme()); err != nil { log.Error(err, "") os.Exit(1) } @@ -60,7 +60,7 @@ import ( routev1 "github.com/openshift/api/route/v1" ) -func main() { +func init() { ... // Adding the routev1 @@ -90,7 +90,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func main() { +func init() { ... log.Info("Registering Components.") @@ -115,13 +115,8 @@ func main() { ### Metrics -> **// TODO:** Update the [metrics doc](https://github.com/operator-framework/operator-sdk/blob/master/website/content/en/docs/golang/metrics/operator-sdk-monitoring.md) since it doesn't match the default scaffolded by kubebuilder anymore. - -To learn about how metrics work in the Operator SDK read the [metrics section][metrics_doc] of the user documentation. - -#### Default Metrics exported with 3rd party resource +To learn about how metrics work in the Operator SDK read the [metrics section][metrics_doc] of the Kubebuilder documentation. -> **// TODO:** Remove this section since we're no longer scaffolding main.go to use the SDK's `GenerateAndServeCRMetrics()` util in `pkg/kube-metrics`. ### Handle Cleanup on Deletion @@ -300,7 +295,7 @@ When the operator is not running in a cluster, the Manager will return an error [deployments_register]: https://github.com/kubernetes/api/blob/master/apps/v1/register.go#L41 [runtime_package]: https://godoc.org/k8s.io/apimachinery/pkg/runtime [scheme_builder]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/scheme#Builder -[metrics_doc]: /docs/golang/metrics/operator-sdk-monitoring/ +[metrics_doc]: https://book.kubebuilder.io/reference/metrics.html [lease_split_brain]: https://github.com/kubernetes/client-go/blob/30b06a83d67458700a5378239df6b96948cb9160/tools/leaderelection/leaderelection.go#L21-L24 [leader_for_life]: https://godoc.org/github.com/operator-framework/operator-sdk/pkg/leader [leader_with_lease]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/leaderelection From aff09d1167eb475bd5c589f9c56036fd69a28cca Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Fri, 8 May 2020 16:06:53 -0700 Subject: [PATCH 02/19] update init functions --- website/content/en/docs/kubebuilder/advanced-topics.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index f9cec4f3e18..02af4017182 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -67,7 +67,11 @@ func init() { if err := routev1.AddToScheme(mgr.GetScheme()); err != nil { log.Error(err, "") os.Exit(1) - } + } + + _ = clientgoscheme.AddToScheme(mgr.GetScheme()) + + _ = routev1.AddToScheme(mgr.GetScheme()) ... } From fe9714220e6f6daf62efd06353507890610b4d78 Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Mon, 11 May 2020 09:00:35 -0700 Subject: [PATCH 03/19] Update website/content/en/docs/kubebuilder/advanced-topics.md Co-authored-by: Camila Macedo --- website/content/en/docs/kubebuilder/advanced-topics.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 02af4017182..9ea5bfa49de 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -69,7 +69,7 @@ func init() { os.Exit(1) } - _ = clientgoscheme.AddToScheme(mgr.GetScheme()) + utilruntime.Must(clientgoscheme.AddToScheme(mgr.GetScheme())) _ = routev1.AddToScheme(mgr.GetScheme()) @@ -304,4 +304,4 @@ When the operator is not running in a cluster, the Manager will return an error [leader_for_life]: https://godoc.org/github.com/operator-framework/operator-sdk/pkg/leader [leader_with_lease]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/leaderelection [pod_eviction_timeout]: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/#options -[manager_options]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/manager#Options \ No newline at end of file +[manager_options]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/manager#Options From 3a4c9b2aeafb4b5194e843c6f7d85372d94ffdde Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Mon, 11 May 2020 09:00:42 -0700 Subject: [PATCH 04/19] Update website/content/en/docs/kubebuilder/advanced-topics.md Co-authored-by: Camila Macedo --- website/content/en/docs/kubebuilder/advanced-topics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 9ea5bfa49de..5d30ee2ffb1 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -71,7 +71,7 @@ func init() { utilruntime.Must(clientgoscheme.AddToScheme(mgr.GetScheme())) - _ = routev1.AddToScheme(mgr.GetScheme()) + utilruntime.Must(routev1.AddToScheme(mgr.GetScheme())) ... } From 220dd04b28ffbf5a36fa777599d3432e672f3f7c Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Mon, 11 May 2020 09:15:06 -0700 Subject: [PATCH 05/19] addressing nits --- website/content/en/docs/kubebuilder/advanced-topics.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 5d30ee2ffb1..12209dbdf0e 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -38,6 +38,8 @@ import ( ... ) +func init() { + // Setup Scheme for all resources if err := cachev1alpha1.AddToScheme(mgr.GetScheme()); err != nil { log.Error(err, "") @@ -64,14 +66,11 @@ func init() { ... // Adding the routev1 - if err := routev1.AddToScheme(mgr.GetScheme()); err != nil { - log.Error(err, "") - os.Exit(1) - } - + utilruntime.Must(clientgoscheme.AddToScheme(mgr.GetScheme())) utilruntime.Must(routev1.AddToScheme(mgr.GetScheme())) + // +kubebuilder:scaffold:scheme ... } From 2c1a297f1fd7559b39198a09bafcbd2ecd3df8f0 Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Mon, 11 May 2020 09:59:01 -0700 Subject: [PATCH 06/19] Update website/content/en/docs/kubebuilder/advanced-topics.md Co-authored-by: Eric Stroczynski --- website/content/en/docs/kubebuilder/advanced-topics.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 12209dbdf0e..9aea4755b63 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -41,7 +41,8 @@ import ( func init() { // Setup Scheme for all resources -if err := cachev1alpha1.AddToScheme(mgr.GetScheme()); err != nil { + utilruntime.Must(cachev1alpha1.AddToScheme(mgr.GetScheme())) + // +kubebuilder:scaffold:scheme log.Error(err, "") os.Exit(1) } From 0284e15b05bfcd2a01f5e632d5b97c1851acaaed Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Mon, 11 May 2020 11:51:19 -0700 Subject: [PATCH 07/19] remove err check --- website/content/en/docs/kubebuilder/advanced-topics.md | 1 - 1 file changed, 1 deletion(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 9aea4755b63..c6234fc66c3 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -43,7 +43,6 @@ func init() { // Setup Scheme for all resources utilruntime.Must(cachev1alpha1.AddToScheme(mgr.GetScheme())) // +kubebuilder:scaffold:scheme - log.Error(err, "") os.Exit(1) } ``` From 4f6516fc9215366d2f052efe07fdd57c0b4fd8d7 Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Tue, 12 May 2020 10:37:09 -0700 Subject: [PATCH 08/19] Update website/content/en/docs/kubebuilder/advanced-topics.md Co-authored-by: Eric Stroczynski --- website/content/en/docs/kubebuilder/advanced-topics.md | 1 - 1 file changed, 1 deletion(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index c6234fc66c3..a8c484b275b 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -43,7 +43,6 @@ func init() { // Setup Scheme for all resources utilruntime.Must(cachev1alpha1.AddToScheme(mgr.GetScheme())) // +kubebuilder:scaffold:scheme - os.Exit(1) } ``` From ac343c6eb045c7179be6f2a619f1ccd581da192e Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Tue, 12 May 2020 10:37:15 -0700 Subject: [PATCH 09/19] Update website/content/en/docs/kubebuilder/advanced-topics.md Co-authored-by: Eric Stroczynski --- website/content/en/docs/kubebuilder/advanced-topics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index a8c484b275b..9d0cd9aca35 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -40,7 +40,7 @@ import ( func init() { -// Setup Scheme for all resources + // Setup Scheme for all resources utilruntime.Must(cachev1alpha1.AddToScheme(mgr.GetScheme())) // +kubebuilder:scaffold:scheme } From 15a17683a96b304577002f8596d7a09204de112a Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Thu, 14 May 2020 13:28:33 -0700 Subject: [PATCH 10/19] remove todo, ref to main.go --- website/content/en/docs/kubebuilder/advanced-topics.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 9d0cd9aca35..064ac8e9359 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -28,7 +28,6 @@ Then, in your controller, you can use [`Conditions`][godoc-conditions] methods t ### Adding 3rd Party Resources To Your Operator -> **// TODO:** Update the `main.go` code in these sections to use the `init()` func to register the scheme instead of doing it in `main()`. The operator's Manager supports the core Kubernetes resource types as found in the client-go [scheme][scheme_package] package and will also register the schemes of all custom resource types defined in your project. @@ -50,8 +49,7 @@ To add a 3rd party resource to an operator, you must add it to the Manager's sch #### Register with the Manager's scheme -Call the `AddToScheme()` function for your 3rd party resource and pass it the Manager's scheme via `mgr.GetScheme()` -in `cmd/manager/main.go`. +Call the `AddToScheme()` function for your 3rd party resource and pass it the Manager's scheme via `mgr.GetScheme()`. Example: ```go From b150a8f345362462df2d4c1cca35e7a1c6f51ba6 Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Wed, 20 May 2020 08:15:06 -0700 Subject: [PATCH 11/19] update example reconcile function --- .../en/docs/kubebuilder/advanced-topics.md | 93 ++++++++++++------- 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 064ac8e9359..23e213287fb 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -138,61 +138,82 @@ import ( const memcachedFinalizer = "finalizer.cache.example.com" -func (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Result, error) { - reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name) - reqLogger.Info("Reconciling Memcached") +func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { + ctx := context.Background() + log := r.Log.WithValues("memcached", req.NamespacedName) // Fetch the Memcached instance memcached := &cachev1alpha1.Memcached{} - err := r.client.Get(context.TODO(), request.NamespacedName, memcached) + err := r.Get(ctx, req.NamespacedName, memcached) if err != nil { if errors.IsNotFound(err) { // Request object not found, could have been deleted after reconcile request. // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. // Return and don't requeue - reqLogger.Info("Memcached resource not found. Ignoring since object must be deleted.") - return reconcile.Result{}, nil + log.Info("Memcached resource not found. Ignoring since object must be deleted") + return ctrl.Result{}, nil } // Error reading the object - requeue the request. - reqLogger.Error(err, "Failed to get Memcached.") - return reconcile.Result{}, err + log.Error(err, "Failed to get Memcached") + return ctrl.Result{}, err } - ... - - // Check if the Memcached instance is marked to be deleted, which is - // indicated by the deletion timestamp being set. - isMemcachedMarkedToBeDeleted := memcached.GetDeletionTimestamp() != nil - if isMemcachedMarkedToBeDeleted { - if contains(memcached.GetFinalizers(), memcachedFinalizer) { - // Run finalization logic for memcachedFinalizer. If the - // finalization logic fails, don't remove the finalizer so - // that we can retry during the next reconciliation. - if err := r.finalizeMemcached(reqLogger, memcached); err != nil { - return reconcile.Result{}, err - } - - // Remove memcachedFinalizer. Once all finalizers have been - // removed, the object will be deleted. - controllerutil.RemoveFinalizer(memcached, memcachedFinalizer) - err := r.client.Update(context.TODO(), memcached) - if err != nil { - return reconcile.Result{}, err - } + // Check if the deployment already exists, if not create a new one + found := &appsv1.Deployment{} + err = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found) + if err != nil && errors.IsNotFound(err) { + // Define a new deployment + dep := r.deploymentForMemcached(memcached) + log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name) + err = r.Create(ctx, dep) + if err != nil { + log.Error(err, "Failed to create new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name) + return ctrl.Result{}, err } - return reconcile.Result{}, nil + // Deployment created successfully - return and requeue + return ctrl.Result{Requeue: true}, nil + } else if err != nil { + log.Error(err, "Failed to get Deployment") + return ctrl.Result{}, err } - // Add finalizer for this CR - if !contains(memcached.GetFinalizers(), memcachedFinalizer) { - if err := r.addFinalizer(reqLogger, memcached); err != nil { - return reconcile.Result{}, err + // Ensure the deployment size is the same as the spec + size := memcached.Spec.Size + if *found.Spec.Replicas != size { + found.Spec.Replicas = &size + err = r.Update(ctx, found) + if err != nil { + log.Error(err, "Failed to update Deployment", "Deployment.Namespace", found.Namespace, "Deployment.Name", found.Name) + return ctrl.Result{}, err } + // Spec updated - return and requeue + return ctrl.Result{Requeue: true}, nil } - ... + // Update the Memcached status with the pod names + // List the pods for this memcached's deployment + podList := &corev1.PodList{} + listOpts := []client.ListOption{ + client.InNamespace(memcached.Namespace), + client.MatchingLabels(labelsForMemcached(memcached.Name)), + } + if err = r.List(ctx, podList, listOpts...); err != nil { + log.Error(err, "Failed to list pods", "Memcached.Namespace", memcached.Namespace, "Memcached.Name", memcached.Name) + return ctrl.Result{}, err + } + podNames := getPodNames(podList.Items) + + // Update status.Nodes if needed + if !reflect.DeepEqual(podNames, memcached.Status.Nodes) { + memcached.Status.Nodes = podNames + err := r.Status().Update(ctx, memcached) + if err != nil { + log.Error(err, "Failed to update Memcached status") + return ctrl.Result{}, err + } + } - return reconcile.Result{}, nil + return ctrl.Result{}, nil } func (r *ReconcileMemcached) finalizeMemcached(reqLogger logr.Logger, m *cachev1alpha1.Memcached) error { From 2fbe547715a1220161af004829fb8b7242af75f9 Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Wed, 20 May 2020 08:17:28 -0700 Subject: [PATCH 12/19] remove todo --- website/content/en/docs/kubebuilder/advanced-topics.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 23e213287fb..7f6587e6ef0 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -120,8 +120,6 @@ To learn about how metrics work in the Operator SDK read the [metrics section][m ### Handle Cleanup on Deletion -> **// TODO:** Update finalizer reconcile code for kubebuilder's default reconciler imports and variable names - To implement complex deletion logic, you can add a finalizer to your Custom Resource. This will prevent your Custom Resource from being deleted until you remove the finalizer (ie, after your cleanup logic has successfully run). For more information, see the [official Kubernetes documentation on finalizers](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#finalizers). From 8faedb92751488d01715b6dd91c3ef33686a88b7 Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Wed, 20 May 2020 10:49:46 -0700 Subject: [PATCH 13/19] func sig and vars --- .../en/docs/kubebuilder/advanced-topics.md | 82 +++++++------------ 1 file changed, 31 insertions(+), 51 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 7f6587e6ef0..ebb3e051a24 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -138,7 +138,8 @@ const memcachedFinalizer = "finalizer.cache.example.com" func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { ctx := context.Background() - log := r.Log.WithValues("memcached", req.NamespacedName) + reqLogger := r.log.WithValues("memcached", req.NamespacedName) + reqLogger.Info("Reconciling Memcached") // Fetch the Memcached instance memcached := &cachev1alpha1.Memcached{} @@ -148,70 +149,49 @@ func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { // Request object not found, could have been deleted after reconcile request. // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. // Return and don't requeue - log.Info("Memcached resource not found. Ignoring since object must be deleted") + reqLogger.Info("Memcached resource not found. Ignoring since object must be deleted.") return ctrl.Result{}, nil } // Error reading the object - requeue the request. - log.Error(err, "Failed to get Memcached") + reqLogger.Error(err, "Failed to get Memcached.") return ctrl.Result{}, err } - // Check if the deployment already exists, if not create a new one - found := &appsv1.Deployment{} - err = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found) - if err != nil && errors.IsNotFound(err) { - // Define a new deployment - dep := r.deploymentForMemcached(memcached) - log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name) - err = r.Create(ctx, dep) - if err != nil { - log.Error(err, "Failed to create new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name) - return ctrl.Result{}, err + ... + + // Check if the Memcached instance is marked to be deleted, which is + // indicated by the deletion timestamp being set. + isMemcachedMarkedToBeDeleted := memcached.GetDeletionTimestamp() != nil + if isMemcachedMarkedToBeDeleted { + if contains(memcached.GetFinalizers(), memcachedFinalizer) { + // Run finalization logic for memcachedFinalizer. If the + // finalization logic fails, don't remove the finalizer so + // that we can retry during the next reconciliation. + if err := r.finalizeMemcached(reqLogger, memcached); err != nil { + return ctrl.Result{}, err + } + + // Remove memcachedFinalizer. Once all finalizers have been + // removed, the object will be deleted. + controllerutil.RemoveFinalizer(memcached, memcachedFinalizer) + err := r.Update(ctx, memcached) + if err != nil { + return ctrl.Result{}, err + } } - // Deployment created successfully - return and requeue - return ctrl.Result{Requeue: true}, nil - } else if err != nil { - log.Error(err, "Failed to get Deployment") - return ctrl.Result{}, err + return ctrl.Result{}, nil } - // Ensure the deployment size is the same as the spec - size := memcached.Spec.Size - if *found.Spec.Replicas != size { - found.Spec.Replicas = &size - err = r.Update(ctx, found) - if err != nil { - log.Error(err, "Failed to update Deployment", "Deployment.Namespace", found.Namespace, "Deployment.Name", found.Name) + // Add finalizer for this CR + if !contains(memcached.GetFinalizers(), memcachedFinalizer) { + if err := r.addFinalizer(reqLogger, memcached); err != nil { return ctrl.Result{}, err } - // Spec updated - return and requeue - return ctrl.Result{Requeue: true}, nil } - // Update the Memcached status with the pod names - // List the pods for this memcached's deployment - podList := &corev1.PodList{} - listOpts := []client.ListOption{ - client.InNamespace(memcached.Namespace), - client.MatchingLabels(labelsForMemcached(memcached.Name)), - } - if err = r.List(ctx, podList, listOpts...); err != nil { - log.Error(err, "Failed to list pods", "Memcached.Namespace", memcached.Namespace, "Memcached.Name", memcached.Name) - return ctrl.Result{}, err - } - podNames := getPodNames(podList.Items) - - // Update status.Nodes if needed - if !reflect.DeepEqual(podNames, memcached.Status.Nodes) { - memcached.Status.Nodes = podNames - err := r.Status().Update(ctx, memcached) - if err != nil { - log.Error(err, "Failed to update Memcached status") - return ctrl.Result{}, err - } - } + ... - return ctrl.Result{}, nil + return reconcile.Result{}, nil } func (r *ReconcileMemcached) finalizeMemcached(reqLogger logr.Logger, m *cachev1alpha1.Memcached) error { From e5542b96f3a6b702edf8991a12b2273cd923b901 Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Wed, 27 May 2020 08:09:29 -0700 Subject: [PATCH 14/19] fix tabs and filepath --- website/content/en/docs/kubebuilder/advanced-topics.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index ebb3e051a24..236b6c8db97 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -39,9 +39,9 @@ import ( func init() { - // Setup Scheme for all resources - utilruntime.Must(cachev1alpha1.AddToScheme(mgr.GetScheme())) - // +kubebuilder:scaffold:scheme + // Setup Scheme for all resources + utilruntime.Must(cachev1alpha1.AddToScheme(mgr.GetScheme())) + // +kubebuilder:scaffold:scheme } ``` @@ -49,8 +49,7 @@ To add a 3rd party resource to an operator, you must add it to the Manager's sch #### Register with the Manager's scheme -Call the `AddToScheme()` function for your 3rd party resource and pass it the Manager's scheme via `mgr.GetScheme()`. - +Call the `AddToScheme()` function for your 3rd party resource and pass it the Manager's scheme via `mgr.GetScheme()` in `main.go`. Example: ```go import ( From 7013dade5f8227e80aaa7a8b57c9c7817434ac6f Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Wed, 27 May 2020 08:10:42 -0700 Subject: [PATCH 15/19] fix recon to ctrl --- website/content/en/docs/kubebuilder/advanced-topics.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 236b6c8db97..5ef94095137 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -190,7 +190,7 @@ func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { ... - return reconcile.Result{}, nil + return ctrl.Result{}, nil } func (r *ReconcileMemcached) finalizeMemcached(reqLogger logr.Logger, m *cachev1alpha1.Memcached) error { @@ -227,8 +227,6 @@ func contains(list []string, s string) bool { ### Leader election -> **// TODO:** Update this section to remove `leader-for-life` option? Since it's no longer the default. - During the lifecycle of an operator it's possible that there may be more than 1 instance running at any given time e.g when rolling out an upgrade for the operator. In such a scenario it is necessary to avoid contention between multiple operator instances via leader election so that only one leader instance handles the reconciliation while the other instances are inactive but ready to take over when the leader steps down. From 54f5f94dc438c34f5c0b881ef4757d436124965f Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Wed, 27 May 2020 09:32:33 -0700 Subject: [PATCH 16/19] fix all tabs --- .../en/docs/kubebuilder/advanced-topics.md | 160 +++++++++--------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 5ef94095137..7c9303ad411 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -63,10 +63,10 @@ func init() { // Adding the routev1 - utilruntime.Must(clientgoscheme.AddToScheme(mgr.GetScheme())) + utilruntime.Must(clientgoscheme.AddToScheme(mgr.GetScheme())) - utilruntime.Must(routev1.AddToScheme(mgr.GetScheme())) - // +kubebuilder:scaffold:scheme + utilruntime.Must(routev1.AddToScheme(mgr.GetScheme())) + // +kubebuilder:scaffold:scheme ... } @@ -136,92 +136,92 @@ import ( const memcachedFinalizer = "finalizer.cache.example.com" func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { - ctx := context.Background() - reqLogger := r.log.WithValues("memcached", req.NamespacedName) - reqLogger.Info("Reconciling Memcached") - - // Fetch the Memcached instance - memcached := &cachev1alpha1.Memcached{} - err := r.Get(ctx, req.NamespacedName, memcached) - if err != nil { - if errors.IsNotFound(err) { - // Request object not found, could have been deleted after reconcile request. - // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. - // Return and don't requeue - reqLogger.Info("Memcached resource not found. Ignoring since object must be deleted.") - return ctrl.Result{}, nil - } - // Error reading the object - requeue the request. - reqLogger.Error(err, "Failed to get Memcached.") - return ctrl.Result{}, err - } - - ... - - // Check if the Memcached instance is marked to be deleted, which is - // indicated by the deletion timestamp being set. - isMemcachedMarkedToBeDeleted := memcached.GetDeletionTimestamp() != nil - if isMemcachedMarkedToBeDeleted { - if contains(memcached.GetFinalizers(), memcachedFinalizer) { - // Run finalization logic for memcachedFinalizer. If the - // finalization logic fails, don't remove the finalizer so - // that we can retry during the next reconciliation. - if err := r.finalizeMemcached(reqLogger, memcached); err != nil { - return ctrl.Result{}, err - } - - // Remove memcachedFinalizer. Once all finalizers have been - // removed, the object will be deleted. - controllerutil.RemoveFinalizer(memcached, memcachedFinalizer) - err := r.Update(ctx, memcached) - if err != nil { - return ctrl.Result{}, err - } - } - return ctrl.Result{}, nil - } - - // Add finalizer for this CR - if !contains(memcached.GetFinalizers(), memcachedFinalizer) { - if err := r.addFinalizer(reqLogger, memcached); err != nil { - return ctrl.Result{}, err - } - } - - ... - - return ctrl.Result{}, nil + ctx := context.Background() + reqLogger := r.log.WithValues("memcached", req.NamespacedName) + reqLogger.Info("Reconciling Memcached") + + // Fetch the Memcached instance + memcached := &cachev1alpha1.Memcached{} + err := r.Get(ctx, req.NamespacedName, memcached) + if err != nil { + if errors.IsNotFound(err) { + // Request object not found, could have been deleted after reconcile request. + // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. + // Return and don't requeue + reqLogger.Info("Memcached resource not found. Ignoring since object must be deleted.") + return ctrl.Result{}, nil + } + // Error reading the object - requeue the request. + reqLogger.Error(err, "Failed to get Memcached.") + return ctrl.Result{}, err + } + + ... + + // Check if the Memcached instance is marked to be deleted, which is + // indicated by the deletion timestamp being set. + isMemcachedMarkedToBeDeleted := memcached.GetDeletionTimestamp() != nil + if isMemcachedMarkedToBeDeleted { + if contains(memcached.GetFinalizers(), memcachedFinalizer) { + // Run finalization logic for memcachedFinalizer. If the + // finalization logic fails, don't remove the finalizer so + // that we can retry during the next reconciliation. + if err := r.finalizeMemcached(reqLogger, memcached); err != nil { + return ctrl.Result{}, err + } + + // Remove memcachedFinalizer. Once all finalizers have been + // removed, the object will be deleted. + controllerutil.RemoveFinalizer(memcached, memcachedFinalizer) + err := r.Update(ctx, memcached) + if err != nil { + return ctrl.Result{}, err + } + } + return ctrl.Result{}, nil + } + + // Add finalizer for this CR + if !contains(memcached.GetFinalizers(), memcachedFinalizer) { + if err := r.addFinalizer(reqLogger, memcached); err != nil { + return ctrl.Result{}, err + } + } + + ... + + return ctrl.Result{}, nil } func (r *ReconcileMemcached) finalizeMemcached(reqLogger logr.Logger, m *cachev1alpha1.Memcached) error { - // TODO(user): Add the cleanup steps that the operator - // needs to do before the CR can be deleted. Examples - // of finalizers include performing backups and deleting - // resources that are not owned by this CR, like a PVC. - reqLogger.Info("Successfully finalized memcached") - return nil + // TODO(user): Add the cleanup steps that the operator + // needs to do before the CR can be deleted. Examples + // of finalizers include performing backups and deleting + // resources that are not owned by this CR, like a PVC. + reqLogger.Info("Successfully finalized memcached") + return nil } func (r *ReconcileMemcached) addFinalizer(reqLogger logr.Logger, m *cachev1alpha1.Memcached) error { - reqLogger.Info("Adding Finalizer for the Memcached") - controllerutil.AddFinalizer(m, memcachedFinalizer) - - // Update CR - err := r.client.Update(context.TODO(), m) - if err != nil { - reqLogger.Error(err, "Failed to update Memcached with finalizer") - return err - } - return nil + reqLogger.Info("Adding Finalizer for the Memcached") + controllerutil.AddFinalizer(m, memcachedFinalizer) + + // Update CR + err := r.client.Update(context.TODO(), m) + if err != nil { + reqLogger.Error(err, "Failed to update Memcached with finalizer") + return err + } + return nil } func contains(list []string, s string) bool { - for _, v := range list { - if v == s { - return true - } - } - return false + for _, v := range list { + if v == s { + return true + } + } + return false } ``` From d9f7676260cede722a516238a2780d060ade450e Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Wed, 27 May 2020 09:43:02 -0700 Subject: [PATCH 17/19] align 4sp tabs --- .../en/docs/kubebuilder/advanced-topics.md | 75 +++++++++---------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index 7c9303ad411..b6ab8516bab 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -33,8 +33,8 @@ The operator's Manager supports the core Kubernetes resource types as found in t ```Go import ( - cachev1alpha1 "github.com/example-inc/memcached-operator/api/v1alpha1 - ... + cachev1alpha1 "github.com/example-inc/memcached-operator/api/v1alpha1 + ... ) func init() { @@ -53,22 +53,19 @@ Call the `AddToScheme()` function for your 3rd party resource and pass it the Ma Example: ```go import ( - .... - - routev1 "github.com/openshift/api/route/v1" + routev1 "github.com/openshift/api/route/v1" ) func init() { - ... - - // Adding the routev1 + ... + // Adding the routev1 utilruntime.Must(clientgoscheme.AddToScheme(mgr.GetScheme())) utilruntime.Must(routev1.AddToScheme(mgr.GetScheme())) // +kubebuilder:scaffold:scheme - ... + ... } ``` @@ -84,22 +81,22 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/scheme" ... - // DNSEndoints - externaldns "github.com/kubernetes-incubator/external-dns/endpoint" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + // DNSEndoints + externaldns "github.com/kubernetes-incubator/external-dns/endpoint" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func init() { ... - log.Info("Registering Components.") + log.Info("Registering Components.") - schemeBuilder := &scheme.Builder{GroupVersion: schema.GroupVersion{Group: "externaldns.k8s.io", Version: "v1alpha1"}} - schemeBuilder.Register(&externaldns.DNSEndpoint{}, &externaldns.DNSEndpointList{}) - if err := schemeBuilder.AddToScheme(mgr.GetScheme()); err != nil { - log.Error(err, "") - os.Exit(1) - } + schemeBuilder := &scheme.Builder{GroupVersion: schema.GroupVersion{Group: "externaldns.k8s.io", Version: "v1alpha1"}} + schemeBuilder.Register(&externaldns.DNSEndpoint{}, &externaldns.DNSEndpointList{}) + if err := schemeBuilder.AddToScheme(mgr.GetScheme()); err != nil { + log.Error(err, "") + os.Exit(1) + } ... } @@ -129,8 +126,8 @@ The following is a snippet from the controller file under `pkg/controller/memcac ```Go import ( - ... - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + ... + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) const memcachedFinalizer = "finalizer.cache.example.com" @@ -245,18 +242,18 @@ A call to `leader.Become()` will block the operator as it retries until it can b ```Go import ( - ... - "github.com/operator-framework/operator-sdk/pkg/leader" + ... + "github.com/operator-framework/operator-sdk/pkg/leader" ) func main() { - ... - err = leader.Become(context.TODO(), "memcached-operator-lock") - if err != nil { - log.Error(err, "Failed to retry for leader lock") - os.Exit(1) - } - ... + ... + err = leader.Become(context.TODO(), "memcached-operator-lock") + if err != nil { + log.Error(err, "Failed to retry for leader lock") + os.Exit(1) + } + ... } ``` If the operator is not running inside a cluster `leader.Become()` will simply return without error to skip the leader election since it can't detect the operator's namespace. @@ -267,19 +264,19 @@ The leader-with-lease approach can be enabled via the [Manager Options][manager_ ```Go import ( - ... - "sigs.k8s.io/controller-runtime/pkg/manager" + ... + "sigs.k8s.io/controller-runtime/pkg/manager" ) func main() { - ... - opts := manager.Options{ ... - LeaderElection: true, - LeaderElectionID: "memcached-operator-lock" - } - mgr, err := manager.New(cfg, opts) - ... + opts := manager.Options{ + ... + LeaderElection: true, + LeaderElectionID: "memcached-operator-lock" + } + mgr, err := manager.New(cfg, opts) + ... } ``` From 262e40d775f0caccfd4e5cc8405c8d54d414543d Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Wed, 27 May 2020 09:45:26 -0700 Subject: [PATCH 18/19] dots spacing --- website/content/en/docs/kubebuilder/advanced-topics.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index b6ab8516bab..f39fe78c20d 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -77,17 +77,17 @@ Example of registering `DNSEndpoints` 3rd party resource from `external-dns`: ```go import ( - ... + ... "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/scheme" - ... + ... // DNSEndoints externaldns "github.com/kubernetes-incubator/external-dns/endpoint" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func init() { - ... + ... log.Info("Registering Components.") @@ -98,7 +98,7 @@ func init() { os.Exit(1) } - ... + ... } ``` From e16b490b5b712e46b918f5492d111816825cca81 Mon Sep 17 00:00:00 2001 From: Ish Shah Date: Wed, 27 May 2020 10:26:43 -0700 Subject: [PATCH 19/19] final nits --- website/content/en/docs/kubebuilder/advanced-topics.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/content/en/docs/kubebuilder/advanced-topics.md b/website/content/en/docs/kubebuilder/advanced-topics.md index f39fe78c20d..9ea5147932b 100644 --- a/website/content/en/docs/kubebuilder/advanced-topics.md +++ b/website/content/en/docs/kubebuilder/advanced-topics.md @@ -190,7 +190,7 @@ func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { return ctrl.Result{}, nil } -func (r *ReconcileMemcached) finalizeMemcached(reqLogger logr.Logger, m *cachev1alpha1.Memcached) error { +func (r *MemcachedReconciler) finalizeMemcached(reqLogger logr.Logger, m *cachev1alpha1.Memcached) error { // TODO(user): Add the cleanup steps that the operator // needs to do before the CR can be deleted. Examples // of finalizers include performing backups and deleting @@ -199,12 +199,12 @@ func (r *ReconcileMemcached) finalizeMemcached(reqLogger logr.Logger, m *cachev1 return nil } -func (r *ReconcileMemcached) addFinalizer(reqLogger logr.Logger, m *cachev1alpha1.Memcached) error { +func (r *MemcachedReconciler) addFinalizer(reqLogger logr.Logger, m *cachev1alpha1.Memcached) error { reqLogger.Info("Adding Finalizer for the Memcached") controllerutil.AddFinalizer(m, memcachedFinalizer) // Update CR - err := r.client.Update(context.TODO(), m) + err := r.Update(context.TODO(), m) if err != nil { reqLogger.Error(err, "Failed to update Memcached with finalizer") return err