Browse Source

Merge pull request #442 from ADustyOldMuffin/ibm-enable-retries

Enable Secret Store retries
paul-the-alien[bot] 4 years ago
parent
commit
f8cd59c764

+ 9 - 0
apis/externalsecrets/v1alpha1/secretstore_types.go

@@ -28,6 +28,10 @@ type SecretStoreSpec struct {
 
 	// Used to configure the provider. Only one provider may be set
 	Provider *SecretStoreProvider `json:"provider"`
+
+	// Used to configure http retries if failed
+	// +optional
+	RetrySettings *SecretStoreRetrySettings `json:"retrySettings,omitempty"`
 }
 
 // SecretStoreProvider contains the provider-specific configration.
@@ -75,6 +79,11 @@ type SecretStoreProvider struct {
 	Alibaba *AlibabaProvider `json:"alibaba,omitempty"`
 }
 
+type SecretStoreRetrySettings struct {
+	MaxRetries    *int32  `json:"maxRetries,omitempty"`
+	RetryInterval *string `json:"retryInterval,omitempty"`
+}
+
 type SecretStoreConditionType string
 
 const (

+ 30 - 0
apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go

@@ -931,6 +931,31 @@ func (in *SecretStoreRef) DeepCopy() *SecretStoreRef {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SecretStoreRetrySettings) DeepCopyInto(out *SecretStoreRetrySettings) {
+	*out = *in
+	if in.MaxRetries != nil {
+		in, out := &in.MaxRetries, &out.MaxRetries
+		*out = new(int32)
+		**out = **in
+	}
+	if in.RetryInterval != nil {
+		in, out := &in.RetryInterval, &out.RetryInterval
+		*out = new(string)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStoreRetrySettings.
+func (in *SecretStoreRetrySettings) DeepCopy() *SecretStoreRetrySettings {
+	if in == nil {
+		return nil
+	}
+	out := new(SecretStoreRetrySettings)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *SecretStoreSpec) DeepCopyInto(out *SecretStoreSpec) {
 	*out = *in
 	if in.Provider != nil {
@@ -938,6 +963,11 @@ func (in *SecretStoreSpec) DeepCopyInto(out *SecretStoreSpec) {
 		*out = new(SecretStoreProvider)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.RetrySettings != nil {
+		in, out := &in.RetrySettings, &out.RetrySettings
+		*out = new(SecretStoreRetrySettings)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStoreSpec.

+ 9 - 0
deploy/crds/external-secrets.io_clustersecretstores.yaml

@@ -925,6 +925,15 @@ spec:
                     - auth
                     type: object
                 type: object
+              retrySettings:
+                description: Used to configure http retries if failed
+                properties:
+                  maxRetries:
+                    format: int32
+                    type: integer
+                  retryInterval:
+                    type: string
+                type: object
             required:
             - provider
             type: object

+ 9 - 0
deploy/crds/external-secrets.io_secretstores.yaml

@@ -925,6 +925,15 @@ spec:
                     - auth
                     type: object
                 type: object
+              retrySettings:
+                description: Used to configure http retries if failed
+                properties:
+                  maxRetries:
+                    format: int32
+                    type: integer
+                  retryInterval:
+                    type: string
+                type: object
             required:
             - provider
             type: object

+ 8 - 0
docs/snippets/full-secret-store.yaml

@@ -11,6 +11,14 @@ spec:
   # Optional
   controller: dev
 
+  # You can specify retry settings for the http connection
+  # these fields allow you to set a maxRetries before failure, and
+  # an interval between the retries.
+  # Current supported providers: IBM
+  retrySettings:
+    maxRetries: 5
+    retryInterval: "10s"
+
   # provider field contains the configuration to access the provider
   # which contains the secret exactly one provider must be configured.
   provider:

+ 23 - 0
pkg/provider/ibm/provider.go

@@ -18,6 +18,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"strings"
+	"time"
 
 	"github.com/IBM/go-sdk-core/v5/core"
 	sm "github.com/IBM/secrets-manager-go-sdk/secretsmanagerv1"
@@ -334,6 +335,28 @@ func (ibm *providerIBM) NewClient(ctx context.Context, store esv1alpha1.GenericS
 		},
 	})
 
+	// Setup retry options, but only if present
+	if storeSpec.RetrySettings != nil {
+		var retryAmount int
+		var retryDuration time.Duration
+
+		if storeSpec.RetrySettings.MaxRetries != nil {
+			retryAmount = int(*storeSpec.RetrySettings.MaxRetries)
+		} else {
+			retryAmount = 3
+		}
+
+		if storeSpec.RetrySettings.RetryInterval != nil {
+			retryDuration, err = time.ParseDuration(*storeSpec.RetrySettings.RetryInterval)
+		} else {
+			retryDuration = 5 * time.Second
+		}
+
+		if err == nil {
+			secretsManager.Service.EnableRetries(retryAmount, retryDuration)
+		}
+	}
+
 	if err != nil {
 		return nil, fmt.Errorf(errIBMClient, err)
 	}

+ 52 - 0
pkg/provider/ibm/provider_test.go

@@ -22,9 +22,13 @@ import (
 
 	"github.com/IBM/go-sdk-core/v5/core"
 	sm "github.com/IBM/secrets-manager-go-sdk/secretsmanagerv1"
+	"github.com/crossplane/crossplane-runtime/pkg/test"
+	corev1 "k8s.io/api/core/v1"
 	utilpointer "k8s.io/utils/pointer"
+	kclient "sigs.k8s.io/controller-runtime/pkg/client"
 
 	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
 	fakesm "github.com/external-secrets/external-secrets/pkg/provider/ibm/fake"
 )
 
@@ -372,6 +376,54 @@ func TestGetSecretMap(t *testing.T) {
 	}
 }
 
+func TestValidRetryInput(t *testing.T) {
+	sm := providerIBM{}
+
+	invalid := "Invalid"
+	serviceURL := "http://fake-service-url.cool"
+
+	spec := &esv1alpha1.SecretStore{
+		Spec: esv1alpha1.SecretStoreSpec{
+			Provider: &esv1alpha1.SecretStoreProvider{
+				IBM: &esv1alpha1.IBMProvider{
+					Auth: esv1alpha1.IBMAuth{
+						SecretRef: esv1alpha1.IBMAuthSecretRef{
+							SecretAPIKey: v1.SecretKeySelector{
+								Name: "fake-secret",
+								Key:  "fake-key",
+							},
+						},
+					},
+					ServiceURL: &serviceURL,
+				},
+			},
+			RetrySettings: &esv1alpha1.SecretStoreRetrySettings{
+				RetryInterval: &invalid,
+			},
+		},
+	}
+
+	expected := fmt.Sprintf("cannot setup new ibm client: time: invalid duration %q", invalid)
+	ctx := context.TODO()
+	kube := &test.MockClient{
+		MockGet: test.NewMockGetFn(nil, func(obj kclient.Object) error {
+			if o, ok := obj.(*corev1.Secret); ok {
+				o.Data = map[string][]byte{
+					"fake-key": []byte("ImAFakeApiKey"),
+				}
+				return nil
+			}
+			return nil
+		}),
+	}
+
+	_, err := sm.NewClient(ctx, spec, kube, "default")
+
+	if !ErrorContains(err, expected) {
+		t.Errorf("CheckValidRetryInput unexpected error: %s, expected: '%s'", err.Error(), expected)
+	}
+}
+
 func ErrorContains(out error, want string) bool {
 	if out == nil {
 		return want == ""