Skip to content

Commit d3d7887

Browse files
authored
[SAPBTPCFS-7876] Optimize handling of non-transient errors (#394)
1 parent d938af4 commit d3d7887

20 files changed

+98
-373
lines changed

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,9 @@ lint-deps:
108108

109109
helm-charts:
110110
kustomize build config/default > ./sapbtp-operator-charts/templates/crd.yml
111+
112+
precommit: goimports lint ## Run this before commiting
113+
114+
goimports:
115+
go install golang.org/x/tools/cmd/goimports@latest
116+
goimports -l -w .

api/common/common.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,14 @@ import (
1111
type ControllerName string
1212

1313
const (
14-
ServiceInstanceController ControllerName = "ServiceInstance"
15-
ServiceBindingController ControllerName = "ServiceBinding"
16-
FinalizerName string = "services.cloud.sap.com/sap-btp-finalizer"
17-
StaleBindingIDLabel string = "services.cloud.sap.com/stale"
18-
StaleBindingRotationOfLabel string = "services.cloud.sap.com/rotationOf"
19-
ForceRotateAnnotation string = "services.cloud.sap.com/forceRotate"
20-
PreventDeletion string = "services.cloud.sap.com/preventDeletion"
21-
UseInstanceMetadataNameInSecret string = "services.cloud.sap.com/useInstanceMetadataName"
22-
IgnoreNonTransientErrorAnnotation string = "services.cloud.sap.com/ignoreNonTransientError"
23-
IgnoreNonTransientErrorTimestampAnnotation string = "services.cloud.sap.com/ignoreNonTransientErrorTimestamp"
14+
ServiceInstanceController ControllerName = "ServiceInstance"
15+
ServiceBindingController ControllerName = "ServiceBinding"
16+
FinalizerName string = "services.cloud.sap.com/sap-btp-finalizer"
17+
StaleBindingIDLabel string = "services.cloud.sap.com/stale"
18+
StaleBindingRotationOfLabel string = "services.cloud.sap.com/rotationOf"
19+
ForceRotateAnnotation string = "services.cloud.sap.com/forceRotate"
20+
PreventDeletion string = "services.cloud.sap.com/preventDeletion"
21+
UseInstanceMetadataNameInSecret string = "services.cloud.sap.com/useInstanceMetadataName"
2422
)
2523

2624
type HTTPStatusCodeError struct {

api/v1/servicebinding_types_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ var _ = Describe("Service Binding Type Test", func() {
100100

101101
It("should update annotation", func() {
102102
annotation := map[string]string{
103-
common.IgnoreNonTransientErrorAnnotation: "true",
103+
"key": "true",
104104
}
105105
binding.SetAnnotations(annotation)
106106
Expect(binding.GetAnnotations()).To(Equal(annotation))

api/v1/servicebinding_validating_webhook.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ var _ webhook.Validator = &ServiceBinding{}
5050
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
5151
func (sb *ServiceBinding) ValidateCreate() (admission.Warnings, error) {
5252
servicebindinglog.Info("validate create", "name", sb.Name)
53-
if err := sb.validateAnnotations(); err != nil {
54-
return nil, err
55-
}
5653
if sb.Spec.CredRotationPolicy != nil {
5754
if err := sb.validateCredRotatingConfig(); err != nil {
5855
return nil, err
@@ -64,9 +61,6 @@ func (sb *ServiceBinding) ValidateCreate() (admission.Warnings, error) {
6461
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
6562
func (sb *ServiceBinding) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
6663
servicebindinglog.Info("validate update", "name", sb.Name)
67-
if err := sb.validateAnnotations(); err != nil {
68-
return nil, err
69-
}
7064
if sb.Spec.CredRotationPolicy != nil {
7165
if err := sb.validateCredRotatingConfig(); err != nil {
7266
return nil, err
@@ -131,12 +125,3 @@ func (sb *ServiceBinding) validateCredRotatingConfig() error {
131125

132126
return nil
133127
}
134-
135-
func (sb *ServiceBinding) validateAnnotations() error {
136-
if sb.Annotations != nil {
137-
if _, ok := sb.Annotations[common.IgnoreNonTransientErrorAnnotation]; ok {
138-
return fmt.Errorf(AnnotationNotSupportedError, common.IgnoreNonTransientErrorAnnotation)
139-
}
140-
}
141-
return nil
142-
}

api/v1/servicebinding_validating_webhook_test.go

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package v1
22

33
import (
4-
"fmt"
54
"github.com/SAP/sap-btp-service-operator/api/common"
65
. "github.com/onsi/ginkgo"
76
. "github.com/onsi/gomega"
@@ -20,15 +19,6 @@ var _ = Describe("Service Binding Webhook Test", func() {
2019
_, err := binding.ValidateCreate()
2120
Expect(err).ToNot(HaveOccurred())
2221
})
23-
It("should failed", func() {
24-
binding.Annotations = map[string]string{
25-
common.IgnoreNonTransientErrorAnnotation: "false",
26-
}
27-
_, err := binding.ValidateCreate()
28-
Expect(err).To(HaveOccurred())
29-
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(AnnotationNotSupportedError, common.IgnoreNonTransientErrorAnnotation)))
30-
31-
})
3222
})
3323

3424
Context("Validate update of spec before binding is created (failure recovery)", func() {
@@ -119,18 +109,6 @@ var _ = Describe("Service Binding Webhook Test", func() {
119109
Expect(err).ToNot(HaveOccurred())
120110
})
121111
})
122-
When("Annotation changed", func() {
123-
It("should fail", func() {
124-
newBinding.Annotations = map[string]string{
125-
common.IgnoreNonTransientErrorAnnotation: "false",
126-
}
127-
_, err := newBinding.ValidateUpdate(binding)
128-
Expect(err).To(HaveOccurred())
129-
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(AnnotationNotSupportedError, common.IgnoreNonTransientErrorAnnotation)))
130-
131-
})
132-
})
133-
134112
})
135113

136114
Context("Validate update of spec after binding is created", func() {

api/v1/serviceinstance_types_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ var _ = Describe("Service Instance Type Test", func() {
124124

125125
It("should update annotation", func() {
126126
annotation := map[string]string{
127-
common.IgnoreNonTransientErrorAnnotation: "true",
127+
"key": "true",
128128
}
129129
instance.SetAnnotations(annotation)
130130
Expect(instance.GetAnnotations()).To(Equal(annotation))

api/v1/serviceinstance_validating_webhook.go

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package v1
1919
import (
2020
"fmt"
2121
"strings"
22-
"time"
2322

2423
"github.com/SAP/sap-btp-service-operator/api/common"
2524

@@ -30,11 +29,6 @@ import (
3029
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
3130
)
3231

33-
const (
34-
annotationInFutureError = "Annotation %s cannot be a date in the future."
35-
annotationNotValidTimestampError = "Annotation %s is not a valid timestamp"
36-
)
37-
3832
func (si *ServiceInstance) SetupWebhookWithManager(mgr ctrl.Manager) error {
3933
return ctrl.NewWebhookManagedBy(mgr).
4034
For(si).
@@ -49,7 +43,7 @@ var _ webhook.Validator = &ServiceInstance{}
4943
var serviceinstancelog = logf.Log.WithName("serviceinstance-resource")
5044

5145
func (si *ServiceInstance) ValidateCreate() (warnings admission.Warnings, err error) {
52-
return nil, si.validateNonTransientTimestampAnnotation()
46+
return nil, nil
5347
}
5448

5549
func (si *ServiceInstance) ValidateUpdate(old runtime.Object) (warnings admission.Warnings, err error) {
@@ -59,7 +53,7 @@ func (si *ServiceInstance) ValidateUpdate(old runtime.Object) (warnings admissio
5953
if oldInstance.Spec.BTPAccessCredentialsSecret != si.Spec.BTPAccessCredentialsSecret {
6054
return nil, fmt.Errorf("changing the btpAccessCredentialsSecret for an existing instance is not allowed")
6155
}
62-
return nil, si.validateNonTransientTimestampAnnotation()
56+
return nil, nil
6357
}
6458

6559
func (si *ServiceInstance) ValidateDelete() (warnings admission.Warnings, err error) {
@@ -72,20 +66,3 @@ func (si *ServiceInstance) ValidateDelete() (warnings admission.Warnings, err er
7266
}
7367
return nil, nil
7468
}
75-
76-
func (si *ServiceInstance) validateNonTransientTimestampAnnotation() error {
77-
if len(si.Annotations) > 0 && len(si.Annotations[common.IgnoreNonTransientErrorAnnotation]) > 0 {
78-
serviceinstancelog.Info(fmt.Sprintf("%s annotation exist, validating %s annotation", common.IgnoreNonTransientErrorAnnotation, common.IgnoreNonTransientErrorTimestampAnnotation))
79-
annotationTime, err := time.Parse(time.RFC3339, si.Annotations[common.IgnoreNonTransientErrorTimestampAnnotation])
80-
if err != nil {
81-
serviceinstancelog.Error(err, fmt.Sprintf("failed to parse %s", common.IgnoreNonTransientErrorTimestampAnnotation))
82-
return fmt.Errorf(annotationNotValidTimestampError, common.IgnoreNonTransientErrorTimestampAnnotation)
83-
}
84-
85-
if time.Since(annotationTime) < 0 {
86-
return fmt.Errorf(annotationInFutureError, common.IgnoreNonTransientErrorTimestampAnnotation)
87-
}
88-
}
89-
90-
return nil
91-
}
Lines changed: 0 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package v1
22

33
import (
4-
"fmt"
54
"github.com/SAP/sap-btp-service-operator/api/common"
65
. "github.com/onsi/ginkgo"
76
. "github.com/onsi/gomega"
8-
"time"
97
)
108

119
var _ = Describe("Service Instance Webhook Test", func() {
@@ -26,27 +24,6 @@ var _ = Describe("Service Instance Webhook Test", func() {
2624
Expect(err.Error()).To(ContainSubstring("changing the btpAccessCredentialsSecret for an existing instance is not allowed"))
2725
})
2826
})
29-
When("service instance IgnoreNonTransientErrorTimestampAnnotation annotation is not set with not a date", func() {
30-
It("should return error from webhook", func() {
31-
instance.Annotations = map[string]string{
32-
common.IgnoreNonTransientErrorAnnotation: "true",
33-
common.IgnoreNonTransientErrorTimestampAnnotation: "true",
34-
}
35-
_, err := instance.ValidateUpdate(instance)
36-
Expect(err).To(HaveOccurred())
37-
38-
})
39-
})
40-
When("service instance IgnoreNonTransientErrorTimestampAnnotation annotation is not set with future date", func() {
41-
It("should return error from webhook", func() {
42-
instance.Annotations = map[string]string{
43-
common.IgnoreNonTransientErrorAnnotation: "true",
44-
common.IgnoreNonTransientErrorTimestampAnnotation: time.Now().Add(48 * time.Hour).Format(time.RFC3339),
45-
}
46-
_, err := instance.ValidateUpdate(instance)
47-
Expect(err).To(HaveOccurred())
48-
})
49-
})
5027
})
5128

5229
Context("Validate Delete", func() {
@@ -76,94 +53,5 @@ var _ = Describe("Service Instance Webhook Test", func() {
7653
Expect(err).ToNot(HaveOccurred())
7754
})
7855
})
79-
Context("Validate Create", func() {
80-
When("service instance IgnoreNonTransientErrorTimestampAnnotation annotation is not set with not a date", func() {
81-
It("should not return error from webhook", func() {
82-
instance.Annotations = map[string]string{
83-
common.IgnoreNonTransientErrorAnnotation: "true",
84-
common.IgnoreNonTransientErrorTimestampAnnotation: "true",
85-
}
86-
_, err := instance.ValidateCreate()
87-
Expect(err).To(HaveOccurred())
88-
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(annotationNotValidTimestampError, common.IgnoreNonTransientErrorTimestampAnnotation)))
89-
90-
})
91-
})
92-
When("service instance IgnoreNonTransientErrorTimestampAnnotation annotation is not set with future date", func() {
93-
It("should not return error from webhook", func() {
94-
instance.Annotations = map[string]string{
95-
common.IgnoreNonTransientErrorAnnotation: "true",
96-
common.IgnoreNonTransientErrorTimestampAnnotation: time.Now().Add(48 * time.Hour).Format(time.RFC3339),
97-
}
98-
_, err := instance.ValidateCreate()
99-
Expect(err).To(HaveOccurred())
100-
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(annotationInFutureError, common.IgnoreNonTransientErrorTimestampAnnotation)))
101-
102-
})
103-
})
104-
})
105-
})
106-
107-
Context("validateNonTransientTimestampAnnotation", func() {
108-
It("fails when not a valid date", func() {
109-
annotation := map[string]string{
110-
common.IgnoreNonTransientErrorAnnotation: "true",
111-
common.IgnoreNonTransientErrorTimestampAnnotation: "true",
112-
}
113-
instance.SetAnnotations(annotation)
114-
err := instance.validateNonTransientTimestampAnnotation()
115-
Expect(err).To(HaveOccurred())
116-
Expect(err.Error()).To(ContainSubstring("is not a valid timestamp"))
117-
})
118-
119-
It("fails when a future date", func() {
120-
annotation := map[string]string{
121-
common.IgnoreNonTransientErrorAnnotation: "true",
122-
common.IgnoreNonTransientErrorTimestampAnnotation: time.Now().Add(48 * time.Hour).Format(time.RFC3339),
123-
}
124-
instance.SetAnnotations(annotation)
125-
err := instance.validateNonTransientTimestampAnnotation()
126-
Expect(err).To(HaveOccurred())
127-
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(annotationInFutureError, common.IgnoreNonTransientErrorTimestampAnnotation)))
128-
})
129-
130-
It("succeeds when timestamp is valid and in the past", func() {
131-
annotation := map[string]string{
132-
common.IgnoreNonTransientErrorAnnotation: "true",
133-
common.IgnoreNonTransientErrorTimestampAnnotation: time.Now().Format(time.RFC3339),
134-
}
135-
instance.SetAnnotations(annotation)
136-
err := instance.validateNonTransientTimestampAnnotation()
137-
Expect(err).NotTo(HaveOccurred())
138-
})
139-
//
140-
//It("validate annotation exist and valid", func() {
141-
// annotation := map[string]string{
142-
// api.IgnoreNonTransientErrorAnnotation: "true",
143-
// api.IgnoreNonTransientErrorTimestampAnnotation: time.Now().Format(time.RFC3339),
144-
// }
145-
// instance.SetAnnotations(annotation)
146-
// exist := utils.IsIgnoreNonTransientAnnotationExistAndValid(serviceinstancelog, instance, time.Hour)
147-
// Expect(exist).To(BeTrue())
148-
//})
149-
//
150-
//It("validate timeout for Ignore Non Transient Error Annotation", func() {
151-
// annotation := map[string]string{
152-
// api.IgnoreNonTransientErrorAnnotation: "true",
153-
// api.IgnoreNonTransientErrorTimestampAnnotation: time.Now().Truncate(48 * time.Hour).Format(time.RFC3339),
154-
// }
155-
// instance.SetAnnotations(annotation)
156-
// exist := utils.IsIgnoreNonTransientAnnotationExistAndValid(serviceinstancelog, instance, time.Hour)
157-
// Expect(exist).To(BeFalse())
158-
//})
159-
//
160-
//It("validate annotation not exist", func() {
161-
// annotation := map[string]string{
162-
// api.IgnoreNonTransientErrorTimestampAnnotation: time.Now().Format(time.RFC3339),
163-
// }
164-
// instance.SetAnnotations(annotation)
165-
// exist := utils.IsIgnoreNonTransientAnnotationExistAndValid(serviceinstancelog, instance, time.Hour)
166-
// Expect(exist).To(BeFalse())
167-
//})
16856
})
16957
})

api/v1/webhooks/serviceinstance_mutating_webhook.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ import (
66
"fmt"
77
"net/http"
88
"reflect"
9-
"time"
10-
11-
"github.com/SAP/sap-btp-service-operator/api/common"
129

1310
v1admission "k8s.io/api/admission/v1"
1411
v1 "k8s.io/api/authentication/v1"
@@ -42,14 +39,6 @@ func (s *ServiceInstanceDefaulter) Handle(_ context.Context, req admission.Reque
4239
return admission.Errored(http.StatusInternalServerError, err)
4340
}
4441

45-
if len(instance.Annotations) > 0 && len(instance.Annotations[common.IgnoreNonTransientErrorAnnotation]) > 0 {
46-
if _, exist := instance.Annotations[common.IgnoreNonTransientErrorTimestampAnnotation]; !exist {
47-
annotationValue := time.Now().Format(time.RFC3339)
48-
instancelog.Info(fmt.Sprintf("%s annotation exists, adding %s annotation with value %s", common.IgnoreNonTransientErrorAnnotation, common.IgnoreNonTransientErrorTimestampAnnotation, annotationValue))
49-
instance.Annotations[common.IgnoreNonTransientErrorTimestampAnnotation] = annotationValue
50-
}
51-
}
52-
5342
marshaledInstance, err := json.Marshal(instance)
5443
if err != nil {
5544
return admission.Errored(http.StatusInternalServerError, err)

api/v1alpha1/serviceinstance_types_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ var _ = Describe("Service Instance Type Test", func() {
125125

126126
It("should update annotation", func() {
127127
annotation := map[string]string{
128-
common.IgnoreNonTransientErrorAnnotation: "true",
128+
"key": "true",
129129
}
130130
instance.SetAnnotations(annotation)
131131
Expect(instance.GetAnnotations()).To(Equal(annotation))

0 commit comments

Comments
 (0)