-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Increase or Decrease polling rate for instance in a final state ready or failed. #53
Changes from all commits
e726462
38b75be
219b6ad
23e8a73
8ab268f
78f81d9
d438d26
31dacc6
0c00cb9
ecc8e90
ad3d74c
188d5c2
5ca01c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and cf-service-operator contributors | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/* | ||
Package controllers contains the implementation of various helper functions used by the reconciler. | ||
*/ | ||
|
||
package controllers | ||
|
||
import ( | ||
"strconv" | ||
"time" | ||
|
||
"github.com/go-logr/logr" | ||
cfv1alpha1 "github.com/sap/cf-service-operator/api/v1alpha1" | ||
ctrl "sigs.k8s.io/controller-runtime" | ||
) | ||
|
||
// setMaxRetries sets the maximum number of retries for a service instance based on the value provided in the annotations | ||
// or uses the default value if the annotation is not set or is invalid. | ||
// TODO: Make it Generic so applies to Space and ServiceBinding. | ||
// TODO: Add a test for this function. | ||
func setMaxRetries(serviceInstance *cfv1alpha1.ServiceInstance, log logr.Logger) { | ||
// Default to an infinite number of retries | ||
serviceInstance.Status.MaxRetries = serviceInstanceDefaultMaxRetries | ||
|
||
// Use max retries from annotation | ||
maxRetriesStr, found := serviceInstance.GetAnnotations()[cfv1alpha1.AnnotationMaxRetries] | ||
if found { | ||
maxRetries, err := strconv.Atoi(maxRetriesStr) | ||
if err != nil { | ||
log.V(1).Info("Invalid max retries annotation value, using default", "AnnotationMaxRetries", maxRetriesStr) | ||
} else { | ||
serviceInstance.Status.MaxRetries = maxRetries | ||
} | ||
} | ||
} | ||
|
||
// getReconcileTimeout reads the reconcile timeout from the annotation on the service instance | ||
// or - if the annotation is not set - uses the default value serviceInstanceDefaultRequeueTimeout | ||
// or else returns the reconcile timeout as a time duration | ||
// TODO: Make it Generic so applies to Space and ServiceBinding. | ||
// TODO: Add a test for this function. | ||
func getReconcileTimeout(serviceInstance *cfv1alpha1.ServiceInstance) time.Duration { | ||
// Use reconcile timeout from annotation, use default if annotation is missing or not parsable | ||
reconcileTimeoutStr, ok := serviceInstance.GetAnnotations()[cfv1alpha1.AnnotationReconcileTimeout] | ||
if !ok { | ||
return serviceInstanceDefaultReconcileInterval | ||
} | ||
reconcileTimeout, err := time.ParseDuration(reconcileTimeoutStr) | ||
if err != nil { | ||
return serviceInstanceDefaultReconcileInterval | ||
} | ||
return reconcileTimeout | ||
} | ||
|
||
// getPollingInterval retrieves the polling interval from the annotaion on the service instance | ||
// or - in case the annotation is not set or invalid - returns either the defaultDurationStr or an empty ctrl.Result{}. | ||
// Otherwise, it returns a ctrl.Result with the RequeueAfter field set in the annotation. | ||
func getPollingInterval(annotations map[string]string, defaultDurationStr, annotationName string) ctrl.Result { | ||
pollingIntervalStr, ok := annotations[annotationName] | ||
if ok { | ||
pollingInterval, err := time.ParseDuration(pollingIntervalStr) | ||
if err == nil { | ||
return ctrl.Result{RequeueAfter: pollingInterval} | ||
} | ||
} | ||
|
||
// If the polling interval is not set, return the default duration | ||
defaultDuration, err := time.ParseDuration(defaultDurationStr) | ||
if err != nil { | ||
// If the default duration is not parsable, return an empty result | ||
return ctrl.Result{} | ||
} | ||
|
||
return ctrl.Result{RequeueAfter: defaultDuration} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* | ||
SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and cf-service-operator contributors | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package controllers | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
cfv1alpha1 "github.com/sap/cf-service-operator/api/v1alpha1" | ||
ctrl "sigs.k8s.io/controller-runtime" | ||
) | ||
|
||
func TestReconcilerHelpers(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
// RunSpecs(t, "Reconciler Helpers Suite") | ||
} | ||
|
||
var _ = Describe("Create a instance with the polling interval annotation | GetPollingInterval", func() { | ||
|
||
It("It should return a RequeueAfter of 10 Seconds time duration", func() { | ||
serviceInstance := &cfv1alpha1.ServiceInstance{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Annotations: map[string]string{ | ||
cfv1alpha1.AnnotationPollingIntervalReady: "10s", | ||
}, | ||
}, | ||
} | ||
|
||
result := getPollingInterval(serviceInstance.GetAnnotations(), "100m", cfv1alpha1.AnnotationPollingIntervalReady) | ||
Expect(result.RequeueAfter).To(Equal(10 * time.Second)) | ||
}) | ||
|
||
It("It should return a RequeueAfter of 2 Minutes time duration", func() { | ||
serviceInstance := &cfv1alpha1.ServiceInstance{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Annotations: map[string]string{ | ||
cfv1alpha1.AnnotationPollingIntervalFail: "2m", | ||
}, | ||
}, | ||
} | ||
|
||
result := getPollingInterval(serviceInstance.GetAnnotations(), "100m", cfv1alpha1.AnnotationPollingIntervalFail) | ||
Expect(result.RequeueAfter).To(Equal(2 * time.Minute)) | ||
}) | ||
}) | ||
|
||
var _ = Describe("Create a ServiceBinding without the polling interval annotation | GetPollingInterval", func() { | ||
It("Should return a ctrl.Result with RequeueAfter of default duration", func() { | ||
defaultDurationStr := "100m" | ||
|
||
serviceInstance := &cfv1alpha1.ServiceBinding{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Annotations: map[string]string{}, | ||
}, | ||
} | ||
|
||
result := getPollingInterval(serviceInstance.GetAnnotations(), defaultDurationStr, cfv1alpha1.AnnotationPollingIntervalReady) | ||
Expect(result).To(Equal(ctrl.Result{RequeueAfter: 100 * time.Minute})) | ||
}) | ||
}) | ||
|
||
var _ = Describe("Create a Space instance with an invalid polling interval annotation | GetPollingInterval", func() { | ||
It("Should return a ctrl.Result with RequeueAfter of default duration", func() { | ||
defaultDurationStr := "10h" | ||
|
||
serviceInstance := &cfv1alpha1.Space{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Annotations: map[string]string{ | ||
cfv1alpha1.AnnotationPollingIntervalReady: "invalid", | ||
}, | ||
}, | ||
} | ||
|
||
result := getPollingInterval(serviceInstance.GetAnnotations(), defaultDurationStr, cfv1alpha1.AnnotationPollingIntervalReady) | ||
Expect(result).To(Equal(ctrl.Result{RequeueAfter: 10 * time.Hour})) | ||
}) | ||
}) | ||
|
||
var _ = Describe("Create a Space instance without annotations and empty defaul time duration| GetPollingInterval", func() { | ||
It("Should return an empty ctrl.Result", func() { | ||
defaultDurationStr := "" | ||
|
||
space := &cfv1alpha1.Space{ | ||
ObjectMeta: metav1.ObjectMeta{}, | ||
} | ||
|
||
result := getPollingInterval(space.GetAnnotations(), defaultDurationStr, cfv1alpha1.AnnotationPollingIntervalReady) | ||
Expect(result).To(Equal(ctrl.Result{})) | ||
}) | ||
}) |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe mentioning the default values/behavior is helpful. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I made some changes to the document. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
--- | ||
title: "Annotations" | ||
linkTitle: "Annotations" | ||
weight: 20 | ||
type: "docs" | ||
description: > | ||
How to control and optimize the CF Service Operator behavior via annotations. | ||
--- | ||
|
||
## Annotation Polling Interval Ready | ||
|
||
The AnnotationPollingIntervalReady annotation is used to specify the duration of the requeue after interval at which the operator polls the status of a Custom Resource after final state ready. It is possible to apply this annotations to Space, ServiceInstance and ServiceBiding CRs. | ||
|
||
By using this annotation, the code allows for flexible configuration of the polling interval, making it easier to adjust the readiness checking frequency based on specific requirements or conditions. | ||
|
||
The value of the annotation is a string representing a duration, such as "100m" or "5h". | ||
|
||
Usage: | ||
|
||
```yaml | ||
apiVersion: cf.cs.sap.com/v1alpha1 | ||
kind: ServiceInstance | ||
metadata: | ||
annotations: | ||
service-operator.cf.cs.sap.com/polling-interval-ready: "3h" | ||
``` | ||
|
||
In the example above the custom resource will be reconcile every three hours after reaching the state Ready. | ||
|
||
**Default Requeue After Interval** | ||
|
||
If the annotation AnnotationPollingIntervalReady is not set, the interval duration will be set to 10 minutes by default. | ||
|
||
### Annotation Polling Interval Fail | ||
|
||
The AnnotationPollingIntervalFail annotation is used to specify the duration of the requeue interval at which the operator polls the status of a Custom Resource after the final states Creation Failed and Deletion Failed. Currently it is possible to apply this annotations to ServiceInstance custom resource only. | ||
RalfHammer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
By using this annotation, the code allows for flexible configuration of the polling interval, making it easier to adjust the re-queue frequency after the failure based on specific requirements or conditions. | ||
|
||
The value of the annotation is a string representing a duration, such as "20s" or "10m". | ||
|
||
Usage: | ||
|
||
```yaml | ||
apiVersion: cf.cs.sap.com/v1alpha1 | ||
kind: ServiceInstance | ||
metadata: | ||
annotations: | ||
service-operator.cf.cs.sap.com/polling-interval-fail: "5m" | ||
``` | ||
|
||
In the example above the custom resource will be reconcile every five minutes after reaching the final state Failed. | ||
|
||
**Default Requeue After Interval** | ||
|
||
If the annotation AnnotationPollingIntervalFail is not set, there won't be an immediate requeue. This means the resource will not be re-reconciled right away. The operator will consider the custom resource to be in a stable state, at least for now. | ||
|
||
That means there is no default time duration for it, and it will return an empty result, ctrl.Result{}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to activate this test?