Browse Source

Refresh UBI digest and clean grpc lint

Signed-off-by: Moritz Johner <beller.moritz@googlemail.com>
Moritz Johner 2 months ago
parent
commit
f3196d835d

+ 1 - 1
Dockerfile.ubi

@@ -1,4 +1,4 @@
-FROM registry.access.redhat.com/ubi9/ubi@sha256:9e6e193bfc3596a84d2a32f42d6b1552398ec9735b9a4e893a0fc3c6fbccb381 AS minimal-ubi
+FROM registry.access.redhat.com/ubi9/ubi@sha256:039095faabf1edde946ff528b3b6906efa046ee129f3e33fd933280bb6936221 AS minimal-ubi
 
 # Add metadata
 LABEL maintainer="cncf-externalsecretsop-maintainers@lists.cncf.io" \

+ 3 - 3
providers/v2/common/grpc/client.go

@@ -32,7 +32,7 @@ import (
 )
 
 const (
-	// defaultTimeout is the default timeout for gRPC calls
+	// defaultTimeout is the default timeout for gRPC calls.
 	defaultTimeout = 30 * time.Second
 )
 
@@ -43,7 +43,7 @@ type grpcProviderClient struct {
 	log    logr.Logger
 }
 
-// Ensure grpcProviderClient implements Provider interface
+// Ensure grpcProviderClient implements the Provider interface.
 var _ v2.Provider = &grpcProviderClient{}
 
 // GetSecret retrieves a single secret from the provider via gRPC.
@@ -475,7 +475,7 @@ func (c *grpcProviderClient) Capabilities(ctx context.Context, providerRef *pb.P
 }
 
 // Close closes the gRPC connection.
-func (c *grpcProviderClient) Close(ctx context.Context) error {
+func (c *grpcProviderClient) Close(_ context.Context) error {
 	if c.conn != nil {
 		c.log.V(1).Info("closing gRPC connection",
 			"target", c.conn.Target(),

+ 23 - 20
providers/v2/common/grpc/client_test.go

@@ -31,7 +31,10 @@ import (
 	pb "github.com/external-secrets/external-secrets/proto/provider"
 )
 
-const bufSize = 1024 * 1024
+const (
+	bufSize             = 1024 * 1024
+	testSourceNamespace = "tenant-a"
+)
 
 type mockServer struct {
 	pb.UnimplementedSecretStoreProviderServer
@@ -164,7 +167,7 @@ func TestClientGetSecretSendsProviderReferenceAndNamespace(t *testing.T) {
 		MetadataPolicy:   esv1.ExternalSecretMetadataPolicyFetch,
 	}
 
-	value, err := client.GetSecret(context.Background(), ref, providerRef, "tenant-a")
+	value, err := client.GetSecret(context.Background(), ref, providerRef, testSourceNamespace)
 	if err != nil {
 		t.Fatalf("GetSecret failed: %v", err)
 	}
@@ -176,7 +179,7 @@ func TestClientGetSecretSendsProviderReferenceAndNamespace(t *testing.T) {
 		t.Fatal("expected get secret request to be recorded")
 	}
 	assertProviderRefEqual(t, mock.getSecretRequest.ProviderRef, providerRef)
-	if mock.getSecretRequest.SourceNamespace != "tenant-a" {
+	if mock.getSecretRequest.SourceNamespace != testSourceNamespace {
 		t.Fatalf("unexpected source namespace: %q", mock.getSecretRequest.SourceNamespace)
 	}
 	if mock.getSecretRequest.RemoteRef.Key != "test-key" || mock.getSecretRequest.RemoteRef.Version != "v1" || mock.getSecretRequest.RemoteRef.Property != "password" {
@@ -202,7 +205,7 @@ func TestClientGetSecretMapSendsProviderReferenceAndNamespace(t *testing.T) {
 	client := NewClientWithConn(conn)
 	providerRef := &pb.ProviderReference{Name: "provider", Namespace: "config-ns", StoreRefKind: esv1.ProviderKindStr}
 
-	value, err := client.GetSecretMap(context.Background(), esv1.ExternalSecretDataRemoteRef{Key: "test-key"}, providerRef, "tenant-a")
+	value, err := client.GetSecretMap(context.Background(), esv1.ExternalSecretDataRemoteRef{Key: "test-key"}, providerRef, testSourceNamespace)
 	if err != nil {
 		t.Fatalf("GetSecretMap failed: %v", err)
 	}
@@ -213,7 +216,7 @@ func TestClientGetSecretMapSendsProviderReferenceAndNamespace(t *testing.T) {
 	if mock.getSecretMapRequest == nil {
 		t.Fatal("expected get secret map request to be recorded")
 	}
-	if mock.getSecretMapRequest.SourceNamespace != "tenant-a" {
+	if mock.getSecretMapRequest.SourceNamespace != testSourceNamespace {
 		t.Fatalf("unexpected request: %#v", mock.getSecretMapRequest)
 	}
 	assertProviderRefEqual(t, mock.getSecretMapRequest.ProviderRef, providerRef)
@@ -232,7 +235,7 @@ func TestClientGetAllSecretsSendsFindCriteria(t *testing.T) {
 		Tags: map[string]string{"team": "a"},
 		Path: &path,
 		Name: &esv1.FindName{RegExp: "db-.*"},
-	}, providerRef, "tenant-a")
+	}, providerRef, testSourceNamespace)
 	if err != nil {
 		t.Fatalf("GetAllSecrets failed: %v", err)
 	}
@@ -243,7 +246,7 @@ func TestClientGetAllSecretsSendsFindCriteria(t *testing.T) {
 	if mock.getAllSecretsRequest == nil {
 		t.Fatal("expected get all secrets request to be recorded")
 	}
-	if mock.getAllSecretsRequest.SourceNamespace != "tenant-a" {
+	if mock.getAllSecretsRequest.SourceNamespace != testSourceNamespace {
 		t.Fatalf("unexpected request: %#v", mock.getAllSecretsRequest)
 	}
 	assertProviderRefEqual(t, mock.getAllSecretsRequest.ProviderRef, providerRef)
@@ -270,14 +273,14 @@ func TestClientPushDeleteExistsAndCapabilitiesSendProviderReferenceAndNamespace(
 		SecretKey: "token",
 		Property:  "property",
 		Metadata:  []byte(`{"mergePolicy":"replace"}`),
-	}, providerRef, "tenant-a")
+	}, providerRef, testSourceNamespace)
 	if err != nil {
 		t.Fatalf("PushSecret failed: %v", err)
 	}
 	if mock.pushSecretRequest == nil {
 		t.Fatal("expected push secret request to be recorded")
 	}
-	if mock.pushSecretRequest.SourceNamespace != "tenant-a" {
+	if mock.pushSecretRequest.SourceNamespace != testSourceNamespace {
 		t.Fatalf("unexpected push request: %#v", mock.pushSecretRequest)
 	}
 	assertProviderRefEqual(t, mock.pushSecretRequest.ProviderRef, providerRef)
@@ -288,11 +291,11 @@ func TestClientPushDeleteExistsAndCapabilitiesSendProviderReferenceAndNamespace(
 	err = client.DeleteSecret(context.Background(), &pb.PushSecretRemoteRef{
 		RemoteKey: "remote/path",
 		Property:  "property",
-	}, providerRef, "tenant-a")
+	}, providerRef, testSourceNamespace)
 	if err != nil {
 		t.Fatalf("DeleteSecret failed: %v", err)
 	}
-	if mock.deleteRequest == nil || mock.deleteRequest.SourceNamespace != "tenant-a" {
+	if mock.deleteRequest == nil || mock.deleteRequest.SourceNamespace != testSourceNamespace {
 		t.Fatalf("unexpected delete request: %#v", mock.deleteRequest)
 	}
 	assertProviderRefEqual(t, mock.deleteRequest.ProviderRef, providerRef)
@@ -300,26 +303,26 @@ func TestClientPushDeleteExistsAndCapabilitiesSendProviderReferenceAndNamespace(
 	exists, err := client.SecretExists(context.Background(), &pb.PushSecretRemoteRef{
 		RemoteKey: "remote/path",
 		Property:  "property",
-	}, providerRef, "tenant-a")
+	}, providerRef, testSourceNamespace)
 	if err != nil {
 		t.Fatalf("SecretExists failed: %v", err)
 	}
 	if !exists {
 		t.Fatal("expected exists to be true")
 	}
-	if mock.existsRequest == nil || mock.existsRequest.SourceNamespace != "tenant-a" {
+	if mock.existsRequest == nil || mock.existsRequest.SourceNamespace != testSourceNamespace {
 		t.Fatalf("unexpected exists request: %#v", mock.existsRequest)
 	}
 	assertProviderRefEqual(t, mock.existsRequest.ProviderRef, providerRef)
 
-	caps, err := client.Capabilities(context.Background(), providerRef, "tenant-a")
+	caps, err := client.Capabilities(context.Background(), providerRef, testSourceNamespace)
 	if err != nil {
 		t.Fatalf("Capabilities failed: %v", err)
 	}
 	if caps != pb.SecretStoreCapabilities_READ_WRITE {
 		t.Fatalf("expected READ_WRITE, got %v", caps)
 	}
-	if mock.capabilitiesRequest == nil || mock.capabilitiesRequest.SourceNamespace != "tenant-a" {
+	if mock.capabilitiesRequest == nil || mock.capabilitiesRequest.SourceNamespace != testSourceNamespace {
 		t.Fatalf("unexpected capabilities request: %#v", mock.capabilitiesRequest)
 	}
 	assertProviderRefEqual(t, mock.capabilitiesRequest.ProviderRef, providerRef)
@@ -347,7 +350,7 @@ func TestClientPushSecretSendsExpandedKubernetesSecretFields(t *testing.T) {
 		SecretKey: ".dockerconfigjson",
 		Property:  "property",
 		Metadata:  []byte(`{"mergePolicy":"replace"}`),
-	}, providerRef, "tenant-a")
+	}, providerRef, testSourceNamespace)
 	if err != nil {
 		t.Fatalf("PushSecret failed: %v", err)
 	}
@@ -358,7 +361,7 @@ func TestClientPushSecretSendsExpandedKubernetesSecretFields(t *testing.T) {
 		t.Errorf("expected request secret data %q, got %q", want, got)
 	}
 	assertProviderRefEqual(t, mock.pushSecretRequest.ProviderRef, providerRef)
-	if got, want := mock.pushSecretRequest.SourceNamespace, "tenant-a"; got != want {
+	if got, want := mock.pushSecretRequest.SourceNamespace, testSourceNamespace; got != want {
 		t.Errorf("expected source namespace %q, got %q", want, got)
 	}
 	if got, want := mock.pushSecretRequest.SecretType, string(corev1.SecretTypeDockerConfigJson); got != want {
@@ -384,14 +387,14 @@ func TestClientValidate(t *testing.T) {
 		client := NewClientWithConn(conn)
 		providerRef := &pb.ProviderReference{Name: "provider", Namespace: "config-ns", StoreRefKind: esv1.ProviderKindStr}
 
-		err := client.Validate(context.Background(), providerRef, "tenant-a")
+		err := client.Validate(context.Background(), providerRef, testSourceNamespace)
 		if err != nil {
 			t.Fatalf("Validate failed: %v", err)
 		}
 		if mock.validateRequest == nil {
 			t.Fatal("expected validate request to be recorded")
 		}
-		if mock.validateRequest.SourceNamespace != "tenant-a" {
+		if mock.validateRequest.SourceNamespace != testSourceNamespace {
 			t.Fatalf("unexpected validate request: %#v", mock.validateRequest)
 		}
 		assertProviderRefEqual(t, mock.validateRequest.ProviderRef, providerRef)
@@ -409,7 +412,7 @@ func TestClientValidate(t *testing.T) {
 
 		client := NewClientWithConn(conn)
 
-		err := client.Validate(context.Background(), &pb.ProviderReference{Name: "provider"}, "tenant-a")
+		err := client.Validate(context.Background(), &pb.ProviderReference{Name: "provider"}, testSourceNamespace)
 		if err == nil {
 			t.Fatal("Expected validation to fail, but it succeeded")
 		}

+ 18 - 0
providers/v2/common/grpc/doc.go

@@ -0,0 +1,18 @@
+/*
+Copyright © The ESO Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package grpc provides the v2 provider gRPC transport and client helpers.
+package grpc

+ 4 - 3
providers/v2/common/grpc/factory.go

@@ -47,14 +47,15 @@ func NewClientWithLogger(address string, tlsConfig *TLSConfig, log logr.Logger)
 		"address", address,
 		"tlsEnabled", tlsConfig != nil)
 
-	// Set up connection options
-	opts := []grpc.DialOption{
+	// Set up connection options.
+	opts := make([]grpc.DialOption, 0, 2)
+	opts = append(opts,
 		grpc.WithKeepaliveParams(keepalive.ClientParameters{
 			Time:                10 * time.Second, // Send keepalive pings every 10 seconds
 			Timeout:             5 * time.Second,  // Wait 5 seconds for ping ack
 			PermitWithoutStream: true,             // Allow pings when no streams are active
 		}),
-	}
+	)
 
 	log.V(1).Info("configured keepalive parameters",
 		"time", "10s",

+ 23 - 23
providers/v2/common/grpc/metrics.go

@@ -26,10 +26,10 @@ import (
 )
 
 var (
-	// gRPC latency buckets optimized for typical RPC call durations
+	// gRPC latency buckets optimized for typical RPC call durations.
 	grpcLatencyBuckets = []float64{0.01, 0.05, 0.1, 0.5, 1, 2, 5, 10, 30}
 
-	// Connection Pool Gauges
+	// Connection Pool gauges.
 	poolConnectionsActive = prometheus.NewGaugeVec(
 		prometheus.GaugeOpts{
 			Name: "grpc_pool_connections_active",
@@ -54,7 +54,7 @@ var (
 		[]string{"address", "tls_enabled"},
 	)
 
-	// Connection Pool Histograms
+	// Connection Pool histograms.
 	connectionAge = prometheus.NewHistogramVec(
 		prometheus.HistogramOpts{
 			Name:    "grpc_connection_age_seconds",
@@ -73,7 +73,7 @@ var (
 		[]string{"address", "tls_enabled"},
 	)
 
-	// Connection Pool Counters
+	// Connection Pool counters.
 	poolHits = prometheus.NewCounterVec(
 		prometheus.CounterOpts{
 			Name: "grpc_pool_hits_total",
@@ -106,7 +106,7 @@ var (
 		[]string{"address", "tls_enabled"},
 	)
 
-	// gRPC Client Metrics
+	// gRPC client metrics.
 	clientRequestDuration = prometheus.NewHistogramVec(
 		prometheus.HistogramOpts{
 			Name:    "grpc_client_request_duration_seconds",
@@ -133,7 +133,7 @@ var (
 	)
 )
 
-// Metrics interface for testability
+// PoolMetrics records connection-pool metrics.
 type PoolMetrics interface {
 	RecordHit(address string, tlsEnabled bool)
 	RecordMiss(address string, tlsEnabled bool)
@@ -144,35 +144,35 @@ type PoolMetrics interface {
 	RecordConnectionIdle(address string, tlsEnabled bool, idle time.Duration)
 }
 
-// ClientMetrics interface for testability
+// ClientMetrics records client request metrics.
 type ClientMetrics interface {
 	ObserveRequest(method, target string, err error, duration time.Duration)
 }
 
-// defaultPoolMetrics implements PoolMetrics using Prometheus
+// defaultPoolMetrics implements PoolMetrics using Prometheus.
 type defaultPoolMetrics struct{}
 
-// RecordHit records a connection pool cache hit
+// RecordHit records a connection pool cache hit.
 func (m *defaultPoolMetrics) RecordHit(address string, tlsEnabled bool) {
 	poolHits.WithLabelValues(address, strconv.FormatBool(tlsEnabled)).Inc()
 }
 
-// RecordMiss records a connection pool cache miss
+// RecordMiss records a connection pool cache miss.
 func (m *defaultPoolMetrics) RecordMiss(address string, tlsEnabled bool) {
 	poolMisses.WithLabelValues(address, strconv.FormatBool(tlsEnabled)).Inc()
 }
 
-// RecordEviction records a connection eviction with reason
+// RecordEviction records a connection eviction with reason.
 func (m *defaultPoolMetrics) RecordEviction(address string, tlsEnabled bool, reason string) {
 	poolEvictions.WithLabelValues(address, strconv.FormatBool(tlsEnabled), reason).Inc()
 }
 
-// RecordConnectionError records a failed connection attempt
+// RecordConnectionError records a failed connection attempt.
 func (m *defaultPoolMetrics) RecordConnectionError(address string, tlsEnabled bool) {
 	poolConnectionErrors.WithLabelValues(address, strconv.FormatBool(tlsEnabled)).Inc()
 }
 
-// UpdatePoolState updates the current pool state gauges
+// UpdatePoolState updates the current pool state gauges.
 func (m *defaultPoolMetrics) UpdatePoolState(address string, tlsEnabled bool, active, idle, total int) {
 	labels := prometheus.Labels{"address": address, "tls_enabled": strconv.FormatBool(tlsEnabled)}
 	poolConnectionsActive.With(labels).Set(float64(active))
@@ -180,20 +180,20 @@ func (m *defaultPoolMetrics) UpdatePoolState(address string, tlsEnabled bool, ac
 	poolConnectionsTotal.With(labels).Set(float64(total))
 }
 
-// RecordConnectionAge records the age of a connection
+// RecordConnectionAge records the age of a connection.
 func (m *defaultPoolMetrics) RecordConnectionAge(address string, tlsEnabled bool, age time.Duration) {
 	connectionAge.WithLabelValues(address, strconv.FormatBool(tlsEnabled)).Observe(age.Seconds())
 }
 
-// RecordConnectionIdle records the idle time of a connection
+// RecordConnectionIdle records the idle time of a connection.
 func (m *defaultPoolMetrics) RecordConnectionIdle(address string, tlsEnabled bool, idle time.Duration) {
 	connectionIdle.WithLabelValues(address, strconv.FormatBool(tlsEnabled)).Observe(idle.Seconds())
 }
 
-// defaultClientMetrics implements ClientMetrics using Prometheus
+// defaultClientMetrics implements ClientMetrics using Prometheus.
 type defaultClientMetrics struct{}
 
-// ObserveRequest records metrics for a client request
+// ObserveRequest records metrics for a client request.
 func (m *defaultClientMetrics) ObserveRequest(method, target string, err error, duration time.Duration) {
 	status := "success"
 	if err != nil {
@@ -206,7 +206,7 @@ func (m *defaultClientMetrics) ObserveRequest(method, target string, err error,
 	clientRequestsTotal.WithLabelValues(method, target, status).Inc()
 }
 
-// classifyError extracts error type for metrics
+// classifyError extracts error type for metrics.
 func classifyError(err error) string {
 	if err == nil {
 		return "none"
@@ -244,13 +244,13 @@ func findSubstring(s, substr string) bool {
 	return false
 }
 
-// Global instances
+// Global instances.
 var (
 	poolMetrics   PoolMetrics   = &defaultPoolMetrics{}
 	clientMetrics ClientMetrics = &defaultClientMetrics{}
 )
 
-// RegisterMetrics registers all gRPC metrics with Prometheus
+// RegisterMetrics registers all gRPC metrics with Prometheus.
 func RegisterMetrics(registry prometheus.Registerer) error {
 	collectors := []prometheus.Collector{
 		poolConnectionsActive,
@@ -269,7 +269,7 @@ func RegisterMetrics(registry prometheus.Registerer) error {
 
 	for _, collector := range collectors {
 		if err := registry.Register(collector); err != nil {
-			// Check if already registered
+			// Check if already registered.
 			var alreadyRegistered prometheus.AlreadyRegisteredError
 			if errors.As(err, &alreadyRegistered) {
 				continue
@@ -281,12 +281,12 @@ func RegisterMetrics(registry prometheus.Registerer) error {
 	return nil
 }
 
-// GetPoolMetrics returns the pool metrics instance (for testing)
+// GetPoolMetrics returns the pool metrics instance for testing.
 func GetPoolMetrics() PoolMetrics {
 	return poolMetrics
 }
 
-// GetClientMetrics returns the client metrics instance (for testing)
+// GetClientMetrics returns the client metrics instance for testing.
 func GetClientMetrics() ClientMetrics {
 	return clientMetrics
 }

+ 1 - 1
providers/v2/common/grpc/pool.go

@@ -95,7 +95,7 @@ func NewConnectionPool(cfg PoolConfig) *ConnectionPool {
 
 // Get retrieves or creates a connection to the specified provider address.
 // The caller must call Release() when done with the connection.
-func (p *ConnectionPool) Get(ctx context.Context, address string, tlsConfig *TLSConfig) (v2.Provider, error) {
+func (p *ConnectionPool) Get(_ context.Context, address string, tlsConfig *TLSConfig) (v2.Provider, error) {
 	p.mu.Lock()
 	defer p.mu.Unlock()
 

+ 2 - 2
providers/v2/common/grpc/resilient.go

@@ -84,7 +84,7 @@ func NewResilientClient(config ResilientClientConfig) (*ResilientClient, error)
 	}, nil
 }
 
-// Ensure ResilientClient implements Provider interface
+// Ensure ResilientClient implements the Provider interface.
 var _ v2.Provider = &ResilientClient{}
 
 // PushSecret writes a secret with retry logic and circuit breaking.
@@ -189,7 +189,7 @@ func (rc *ResilientClient) Capabilities(ctx context.Context, providerRef *pb.Pro
 }
 
 // Close closes the connection pool.
-func (rc *ResilientClient) Close(ctx context.Context) error {
+func (rc *ResilientClient) Close(_ context.Context) error {
 	return rc.pool.Close()
 }
 

+ 33 - 24
providers/v2/common/grpc/retry.go

@@ -18,10 +18,11 @@ package grpc
 
 import (
 	"context"
+	cryptorand "crypto/rand"
+	"encoding/binary"
 	"errors"
 	"fmt"
 	"math"
-	"math/rand"
 	"sync"
 	"time"
 
@@ -31,15 +32,15 @@ import (
 
 // RetryConfig configures retry behavior.
 type RetryConfig struct {
-	// MaxAttempts is the maximum number of retry attempts
+	// MaxAttempts is the maximum number of retry attempts.
 	MaxAttempts int
-	// InitialBackoff is the initial backoff duration
+	// InitialBackoff is the initial backoff duration.
 	InitialBackoff time.Duration
-	// MaxBackoff is the maximum backoff duration
+	// MaxBackoff is the maximum backoff duration.
 	MaxBackoff time.Duration
-	// BackoffMultiplier is the multiplier for exponential backoff
+	// BackoffMultiplier is the multiplier for exponential backoff.
 	BackoffMultiplier float64
-	// Jitter adds randomness to backoff to prevent thundering herd
+	// Jitter adds randomness to backoff to prevent thundering herd.
 	Jitter bool
 }
 
@@ -56,11 +57,11 @@ func DefaultRetryConfig() RetryConfig {
 
 // CircuitBreakerConfig configures circuit breaker behavior.
 type CircuitBreakerConfig struct {
-	// MaxFailures is the number of consecutive failures before opening
+	// MaxFailures is the number of consecutive failures before opening.
 	MaxFailures int
-	// Timeout is how long to wait in open state before trying again
+	// Timeout is how long to wait in open state before trying again.
 	Timeout time.Duration
-	// HalfOpenMaxRequests is max requests allowed in half-open state
+	// HalfOpenMaxRequests is max requests allowed in half-open state.
 	HalfOpenMaxRequests int
 }
 
@@ -77,11 +78,11 @@ func DefaultCircuitBreakerConfig() CircuitBreakerConfig {
 type CircuitState int
 
 const (
-	// StateClosed means the circuit is closed and requests flow normally
+	// StateClosed means the circuit is closed and requests flow normally.
 	StateClosed CircuitState = iota
-	// StateOpen means the circuit is open and requests fail fast
+	// StateOpen means the circuit is open and requests fail fast.
 	StateOpen
-	// StateHalfOpen means the circuit is testing if the service has recovered
+	// StateHalfOpen means the circuit is testing if the service has recovered.
 	StateHalfOpen
 )
 
@@ -104,16 +105,16 @@ func NewCircuitBreaker(config CircuitBreakerConfig) *CircuitBreaker {
 }
 
 // Call executes the given function with circuit breaker protection.
-func (cb *CircuitBreaker) Call(ctx context.Context, fn func() error) error {
-	// Check if we should allow the request
+func (cb *CircuitBreaker) Call(_ context.Context, fn func() error) error {
+	// Check if we should allow the request.
 	if err := cb.beforeRequest(); err != nil {
 		return err
 	}
 
-	// Execute the function
+	// Execute the function.
 	err := fn()
 
-	// Record the result
+	// Record the result.
 	cb.afterRequest(err)
 
 	return err
@@ -282,32 +283,40 @@ func isRetryable(err error) bool {
 		}
 	}
 
-	// For non-gRPC errors, retry network-related issues
-	// Context errors should not be retried
+	// For non-gRPC errors, retry network-related issues.
+	// Context errors should not be retried.
 	if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
 		return false
 	}
 
-	// Default: retry
+	// Default: retry.
 	return true
 }
 
 // calculateBackoff calculates the backoff duration for a given attempt.
 func calculateBackoff(attempt int, config RetryConfig) time.Duration {
-	// Exponential backoff: initialBackoff * (multiplier ^ attempt)
+	// Exponential backoff: initialBackoff * (multiplier ^ attempt).
 	backoff := float64(config.InitialBackoff) * math.Pow(config.BackoffMultiplier, float64(attempt))
 
-	// Apply max backoff
+	// Apply max backoff.
 	if backoff > float64(config.MaxBackoff) {
 		backoff = float64(config.MaxBackoff)
 	}
 
-	// Add jitter if enabled
+	// Add jitter if enabled.
 	if config.Jitter {
-		// Add random jitter between 0 and 25% of backoff
-		jitter := rand.Float64() * backoff * 0.25
+		// Add random jitter between 0 and 25% of backoff.
+		jitter := randomFloat64() * backoff * 0.25
 		backoff += jitter
 	}
 
 	return time.Duration(backoff)
 }
+
+func randomFloat64() float64 {
+	var buf [8]byte
+	if _, err := cryptorand.Read(buf[:]); err != nil {
+		return 0
+	}
+	return float64(binary.BigEndian.Uint64(buf[:])) / float64(^uint64(0))
+}

+ 3 - 2
providers/v2/common/grpc/retry_test.go

@@ -18,6 +18,7 @@ package grpc
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"testing"
 	"time"
@@ -41,7 +42,7 @@ func TestCircuitBreaker_States(t *testing.T) {
 	}
 
 	// Simulate 3 failures to open the circuit
-	for i := 0; i < 3; i++ {
+	for range 3 {
 		err := cb.Call(ctx, func() error {
 			return status.Error(codes.Unavailable, "service unavailable")
 		})
@@ -150,7 +151,7 @@ func TestRetry_ContextCancellation(t *testing.T) {
 		return status.Error(codes.Unavailable, "unavailable")
 	})
 
-	if err != context.Canceled {
+	if !errors.Is(err, context.Canceled) {
 		t.Errorf("expected context.Canceled, got: %v", err)
 	}
 }

+ 17 - 14
providers/v2/common/grpc/tls_test.go

@@ -17,6 +17,7 @@ limitations under the License.
 package grpc
 
 import (
+	"bytes"
 	"context"
 	"crypto/rand"
 	"crypto/rsa"
@@ -38,6 +39,8 @@ import (
 	fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
 )
 
+const testLoopbackAddress = "127.0.0.1"
+
 func TestNamespaceFromAddress(t *testing.T) {
 	testCases := []struct {
 		name     string
@@ -59,9 +62,9 @@ func TestNamespaceFromAddress(t *testing.T) {
 		},
 		{
 			name:     "non_service_address_uses_fallback",
-			address:  "127.0.0.1:9443",
-			fallback: "tenant-a",
-			expected: "tenant-a",
+			address:  testLoopbackAddress + ":9443",
+			fallback: testSourceNamespace,
+			expected: testSourceNamespace,
 		},
 	}
 
@@ -93,7 +96,7 @@ func TestResolveTLSSecretNamespace(t *testing.T) {
 		},
 		{
 			name:                 "auth_namespace_used_before_other_fallbacks",
-			address:              "127.0.0.1:9443",
+			address:              testLoopbackAddress + ":9443",
 			authNamespace:        "auth-ns",
 			resourceNamespace:    "resource-ns",
 			providerRefNamespace: "provider-ref-ns",
@@ -101,14 +104,14 @@ func TestResolveTLSSecretNamespace(t *testing.T) {
 		},
 		{
 			name:                 "resource_namespace_used_before_provider_ref_namespace",
-			address:              "127.0.0.1:9443",
+			address:              testLoopbackAddress + ":9443",
 			resourceNamespace:    "resource-ns",
 			providerRefNamespace: "provider-ref-ns",
 			expected:             "resource-ns",
 		},
 		{
 			name:                 "provider_ref_namespace_is_final_fallback",
-			address:              "127.0.0.1:9443",
+			address:              testLoopbackAddress + ":9443",
 			providerRefNamespace: "provider-ref-ns",
 			expected:             "provider-ref-ns",
 		},
@@ -125,7 +128,7 @@ func TestResolveTLSSecretNamespace(t *testing.T) {
 
 func TestLoadClientTLSConfig(t *testing.T) {
 	t.Run("success", func(t *testing.T) {
-		serverName := "127.0.0.1"
+		serverName := testLoopbackAddress
 		_, _, clientCertPEM, clientKeyPEM, caCertPEM := newTLSArtifactsForTest(t, serverName)
 		kubeClient := newTLSSecretClient(t, map[string][]byte{
 			"ca.crt":     caCertPEM,
@@ -133,12 +136,12 @@ func TestLoadClientTLSConfig(t *testing.T) {
 			"client.key": clientKeyPEM,
 		})
 
-		cfg, err := LoadClientTLSConfig(context.Background(), kubeClient, "127.0.0.1:9443", "tenant-a")
+		cfg, err := LoadClientTLSConfig(context.Background(), kubeClient, testLoopbackAddress+":9443", testSourceNamespace)
 		if err != nil {
 			t.Fatalf("LoadClientTLSConfig() error = %v", err)
 		}
 
-		if string(cfg.CACert) != string(caCertPEM) || string(cfg.ClientCert) != string(clientCertPEM) || string(cfg.ClientKey) != string(clientKeyPEM) {
+		if !bytes.Equal(cfg.CACert, caCertPEM) || !bytes.Equal(cfg.ClientCert, clientCertPEM) || !bytes.Equal(cfg.ClientKey, clientKeyPEM) {
 			t.Fatalf("unexpected tls config: %#v", cfg)
 		}
 		if cfg.ServerName != serverName {
@@ -154,7 +157,7 @@ func TestLoadClientTLSConfig(t *testing.T) {
 			WithScheme(scheme).
 			Build()
 
-		_, err := LoadClientTLSConfig(context.Background(), kubeClient, "127.0.0.1:9443", "tenant-a")
+		_, err := LoadClientTLSConfig(context.Background(), kubeClient, testLoopbackAddress+":9443", testSourceNamespace)
 		if err == nil || err.Error() == "" {
 			t.Fatalf("expected missing secret error, got %v", err)
 		}
@@ -165,7 +168,7 @@ func TestLoadClientTLSConfig(t *testing.T) {
 			"ca.crt": []byte("ca"),
 		})
 
-		_, err := LoadClientTLSConfig(context.Background(), kubeClient, "127.0.0.1:9443", "tenant-a")
+		_, err := LoadClientTLSConfig(context.Background(), kubeClient, testLoopbackAddress+":9443", testSourceNamespace)
 		if err == nil || err.Error() != "client.crt not found or empty in secret external-secrets-provider-tls" {
 			t.Fatalf("unexpected error: %v", err)
 		}
@@ -174,7 +177,7 @@ func TestLoadClientTLSConfig(t *testing.T) {
 
 func TestTLSConfigToGRPCTLSConfig(t *testing.T) {
 	t.Run("success", func(t *testing.T) {
-		serverName := "127.0.0.1"
+		serverName := testLoopbackAddress
 		_, _, clientCertPEM, clientKeyPEM, caCertPEM := newTLSArtifactsForTest(t, serverName)
 
 		cfg, err := (&TLSConfig{
@@ -213,7 +216,7 @@ func TestTLSConfigToGRPCTLSConfig(t *testing.T) {
 	})
 
 	t.Run("invalid_ca", func(t *testing.T) {
-		serverName := "127.0.0.1"
+		serverName := testLoopbackAddress
 		_, _, clientCertPEM, clientKeyPEM, _ := newTLSArtifactsForTest(t, serverName)
 
 		_, err := (&TLSConfig{
@@ -237,7 +240,7 @@ func newTLSSecretClient(t *testing.T, data map[string][]byte) ctrlclient.Client
 	return fakeclient.NewClientBuilder().
 		WithScheme(scheme).
 		WithObjects(&corev1.Secret{
-			ObjectMeta: metav1ForTLS("external-secrets-provider-tls", "tenant-a"),
+			ObjectMeta: metav1ForTLS("external-secrets-provider-tls", testSourceNamespace),
 			Data:       data,
 		}).
 		Build()