Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
424 changes: 422 additions & 2 deletions test/e2e/e2e_test.go

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions test/e2e/testdata/aws_external_secret_binary.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
labels:
app.kubernetes.io/name: aws-external-secret-binary
app.kubernetes.io/managed-by: external-secrets-operator-e2e
name: aws-external-secret-binary
namespace: external-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: ${SECRETSTORE_NAME}
kind: ${SECRETSTORE_KIND}
target:
name: aws-secret-binary
creationPolicy: Owner
data:
- secretKey: binary_data
remoteRef:
key: "${AWS_SECRET_KEY_NAME}"
property: binary_data
19 changes: 19 additions & 0 deletions test/e2e/testdata/aws_external_secret_datafrom.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
labels:
app.kubernetes.io/name: aws-external-secret-datafrom
app.kubernetes.io/managed-by: external-secrets-operator-e2e
name: aws-external-secret-datafrom
namespace: external-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: ${SECRETSTORE_NAME}
kind: ${SECRETSTORE_KIND}
target:
name: aws-secret-datafrom
creationPolicy: Owner
dataFrom:
- extract:
key: "${AWS_SECRET_KEY_NAME}"
21 changes: 21 additions & 0 deletions test/e2e/testdata/aws_external_secret_jsonpath.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
labels:
app.kubernetes.io/name: aws-external-secret-jsonpath
app.kubernetes.io/managed-by: external-secrets-operator-e2e
name: aws-external-secret-jsonpath
namespace: external-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: ${SECRETSTORE_NAME}
kind: ${SECRETSTORE_KIND}
target:
name: aws-secret-jsonpath
creationPolicy: Owner
data:
- secretKey: nested_value
remoteRef:
key: "${AWS_SECRET_KEY_NAME}"
property: db.credentials.password
29 changes: 29 additions & 0 deletions test/e2e/testdata/aws_external_secret_multi_key.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
labels:
app.kubernetes.io/name: aws-external-secret-multi-key
app.kubernetes.io/managed-by: external-secrets-operator-e2e
name: aws-external-secret-multi-key
namespace: external-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: ${SECRETSTORE_NAME}
kind: ${SECRETSTORE_KIND}
target:
name: aws-secret-multi-key
creationPolicy: Owner
data:
- secretKey: key1
remoteRef:
key: "${AWS_SECRET_KEY_NAME}"
property: key1
- secretKey: key2
remoteRef:
key: "${AWS_SECRET_KEY_NAME}"
property: key2
- secretKey: key3
remoteRef:
key: "${AWS_SECRET_KEY_NAME}"
property: key3
21 changes: 21 additions & 0 deletions test/e2e/testdata/aws_external_secret_refresh.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
labels:
app.kubernetes.io/name: aws-external-secret-refresh
app.kubernetes.io/managed-by: external-secrets-operator-e2e
name: aws-external-secret-refresh
namespace: external-secrets
spec:
refreshInterval: 30s
secretStoreRef:
name: ${SECRETSTORE_NAME}
kind: ${SECRETSTORE_KIND}
target:
name: aws-secret-refresh
creationPolicy: Owner
data:
- secretKey: refresh_value
remoteRef:
key: "${AWS_SECRET_KEY_NAME}"
property: value
32 changes: 32 additions & 0 deletions test/e2e/testdata/aws_external_secret_template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
labels:
app.kubernetes.io/name: aws-external-secret-template
app.kubernetes.io/managed-by: external-secrets-operator-e2e
name: aws-external-secret-template
namespace: external-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: ${SECRETSTORE_NAME}
kind: ${SECRETSTORE_KIND}
target:
name: aws-secret-template
creationPolicy: Owner
template:
type: Opaque
data:
config.yaml: |
database:
username: {{ .username }}
password: {{ .password }}
data:
- secretKey: username
remoteRef:
key: "${AWS_SECRET_KEY_NAME}"
property: username
- secretKey: password
remoteRef:
key: "${AWS_SECRET_KEY_NAME}"
property: password
23 changes: 23 additions & 0 deletions test/e2e/testdata/aws_invalid_secret_store.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
labels:
app.kubernetes.io/name: aws-invalid-secret-store
app.kubernetes.io/managed-by: external-secrets-operator-e2e
name: ${SECRETSTORE_NAME}
namespace: external-secrets
spec:
provider:
aws:
service: SecretsManager
region: ap-south-1
auth:
secretRef:
accessKeyIDSecretRef:
name: ${INVALID_CREDS_SECRET_NAME}
key: aws_access_key_id
namespace: external-secrets
secretAccessKeySecretRef:
name: ${INVALID_CREDS_SECRET_NAME}
key: aws_secret_access_key
namespace: external-secrets
13 changes: 13 additions & 0 deletions test/e2e/testdata/aws_k8s_secret_multi_key.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Secret
metadata:
labels:
app.kubernetes.io/name: aws-k8s-secret-multi-key
app.kubernetes.io/managed-by: external-secrets-operator-e2e
name: aws-k8s-secret-multi-key
namespace: external-secrets
data:
key1: ${KEY1_VALUE}
key2: ${KEY2_VALUE}
key3: ${KEY3_VALUE}
type: Opaque
2 changes: 1 addition & 1 deletion test/e2e/testdata/aws_secret_store.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
provider:
aws:
service: SecretsManager
region: ap-south-1
region: ${AWS_REGION}
auth:
secretRef:
accessKeyIDSecretRef:
Expand Down
20 changes: 20 additions & 0 deletions test/e2e/testdata/aws_secret_store_namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
labels:
app.kubernetes.io/name: aws-secret-store-namespace
app.kubernetes.io/managed-by: external-secrets-operator-e2e
name: ${SECRETSTORE_NAME}
spec:
provider:
aws:
service: SecretsManager
region: ${AWS_REGION}
auth:
secretRef:
accessKeyIDSecretRef:
name: "${SECRETNAME}"
key: aws_access_key_id
secretAccessKeySecretRef:
name: "${SECRETNAME}"
key: aws_secret_access_key
20 changes: 20 additions & 0 deletions test/e2e/testdata/aws_ssm_external_secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
labels:
app.kubernetes.io/name: aws-ssm-external-secret
app.kubernetes.io/managed-by: external-secrets-operator-e2e
name: aws-ssm-external-secret
namespace: external-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: ${CLUSTERSECRETSTORE_NAME}
kind: ClusterSecretStore
target:
name: aws-ssm-secret
creationPolicy: Owner
data:
- secretKey: parameter_value
remoteRef:
key: "${AWS_PARAMETER_NAME}"
22 changes: 22 additions & 0 deletions test/e2e/testdata/aws_ssm_secret_store.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
labels:
app.kubernetes.io/name: aws-ssm-secret-store
app.kubernetes.io/managed-by: external-secrets-operator-e2e
name: ${CLUSTERSECRETSTORE_NAME}
spec:
provider:
aws:
service: ParameterStore
region: ${AWS_REGION}
auth:
secretRef:
accessKeyIDSecretRef:
name: aws-creds
key: aws_access_key_id
namespace: kube-system
secretAccessKeySecretRef:
name: aws-creds
key: aws_secret_access_key
namespace: kube-system
58 changes: 57 additions & 1 deletion test/utils/conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,62 @@ func fetchAWSCreds(ctx context.Context, k8sClient *kubernetes.Clientset) (string
return id, key, nil
}

func CreateAWSSecret(ctx context.Context, k8sClient *kubernetes.Clientset, secretName, secretValue, region string) error {
id, key, err := fetchAWSCreds(ctx, k8sClient)
if err != nil {
return err
}

sess, err := session.NewSession(&aws.Config{
Credentials: awscred.NewCredentials(&awscred.StaticProvider{Value: awscred.Value{
AccessKeyID: id,
SecretAccessKey: key,
}}),
Region: aws.String(region),
})
if err != nil {
return fmt.Errorf("failed to create AWS session: %w", err)
}

svc := secretsmanager.New(sess)
_, err = svc.CreateSecret(&secretsmanager.CreateSecretInput{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_, err = svc.CreateSecret(&secretsmanager.CreateSecretInput{
_, err = svc.CreateSecretWithContext(ctx, &secretsmanager.CreateSecretInput{

Name: aws.String(secretName),
SecretString: aws.String(secretValue),
})
if err != nil {
return fmt.Errorf("failed to create AWS secret: %w", err)
}
return nil
}

func UpdateAWSSecret(ctx context.Context, k8sClient *kubernetes.Clientset, secretName, secretValue, region string) error {
id, key, err := fetchAWSCreds(ctx, k8sClient)
if err != nil {
return err
}

sess, err := session.NewSession(&aws.Config{
Credentials: awscred.NewCredentials(&awscred.StaticProvider{Value: awscred.Value{
AccessKeyID: id,
SecretAccessKey: key,
}}),
Region: aws.String(region),
})
if err != nil {
return fmt.Errorf("failed to create AWS session: %w", err)
}

svc := secretsmanager.New(sess)
_, err = svc.UpdateSecret(&secretsmanager.UpdateSecretInput{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_, err = svc.UpdateSecret(&secretsmanager.UpdateSecretInput{
_, err = svc.UpdateSecretWithContext(ctx, &secretsmanager.UpdateSecretInput{

SecretId: aws.String(secretName),
SecretString: aws.String(secretValue),
})
if err != nil {
return fmt.Errorf("failed to update AWS secret: %w", err)
}
return nil
}
Comment on lines +149 to +203
Copy link

@coderabbitai coderabbitai bot Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -path "*/test/utils/conditions.go" -type f

Repository: openshift/external-secrets-operator

Length of output: 105


🏁 Script executed:

# If file exists, check its contents around lines 149-203
if [ -f "test/utils/conditions.go" ]; then
  wc -l test/utils/conditions.go
  echo "---"
  sed -n '140,210p' test/utils/conditions.go
fi

Repository: openshift/external-secrets-operator

Length of output: 2146


🌐 Web query:

AWS SDK Go secretsmanager CreateSecretWithContext UpdateSecretWithContext methods

💡 Result:

In AWS SDK for Go v1 (github.com/aws/aws-sdk-go/service/secretsmanager), the WithContext variants are the same API calls as CreateSecret / UpdateSecret, but let you pass a non-nil context for cancellation/timeouts plus optional request options:

  • func (c *SecretsManager) CreateSecretWithContext(ctx aws.Context, input *CreateSecretInput, opts ...request.Option) (*CreateSecretOutput, error) (docs.aws.amazon.com)
  • func (c *SecretsManager) UpdateSecretWithContext(ctx aws.Context, input *UpdateSecretInput, opts ...request.Option) (*UpdateSecretOutput, error) (docs.aws.amazon.com)

Example (v1):

sess := session.Must(session.NewSession())
sm := secretsmanager.New(sess)

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

_, err := sm.CreateSecretWithContext(ctx, &secretsmanager.CreateSecretInput{
    Name:         aws.String("my-secret"),
    SecretString: aws.String(`{"user":"u","pass":"p"}`),
})

_, err = sm.UpdateSecretWithContext(ctx, &secretsmanager.UpdateSecretInput{
    SecretId:     aws.String("my-secret"),
    SecretString: aws.String(`{"user":"u","pass":"p2"}`),
})

In AWS SDK for Go v2 (github.com/aws/aws-sdk-go-v2/service/secretsmanager), the context is already part of the standard method signature (no WithContext suffix):

  • func (c *Client) CreateSecret(ctx context.Context, params *CreateSecretInput, optFns ...func(*Options)) (*CreateSecretOutput, error) (pkg.go.dev)
  • func (c *Client) UpdateSecret(ctx context.Context, params *UpdateSecretInput, optFns ...func(*Options)) (*UpdateSecretOutput, error) (pkg.go.dev)

Citations:


Use context-aware AWS SDK calls to avoid hanging tests.

ctx is accepted by both CreateAWSSecret and UpdateAWSSecret but ignored in the AWS SDK calls. This prevents test timeouts and cancellations from propagating, risking hung tests on network stalls. Use the WithContext variants to respect the provided context.

🛠️ Suggested changes
-	_, err = svc.CreateSecret(&secretsmanager.CreateSecretInput{
+	_, err = svc.CreateSecretWithContext(ctx, &secretsmanager.CreateSecretInput{
 		Name:         aws.String(secretName),
 		SecretString: aws.String(secretValue),
 	})
-	_, err = svc.UpdateSecret(&secretsmanager.UpdateSecretInput{
+	_, err = svc.UpdateSecretWithContext(ctx, &secretsmanager.UpdateSecretInput{
 		SecretId:     aws.String(secretName),
 		SecretString: aws.String(secretValue),
 	})
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func CreateAWSSecret(ctx context.Context, k8sClient *kubernetes.Clientset, secretName, secretValue, region string) error {
id, key, err := fetchAWSCreds(ctx, k8sClient)
if err != nil {
return err
}
sess, err := session.NewSession(&aws.Config{
Credentials: awscred.NewCredentials(&awscred.StaticProvider{Value: awscred.Value{
AccessKeyID: id,
SecretAccessKey: key,
}}),
Region: aws.String(region),
})
if err != nil {
return fmt.Errorf("failed to create AWS session: %w", err)
}
svc := secretsmanager.New(sess)
_, err = svc.CreateSecret(&secretsmanager.CreateSecretInput{
Name: aws.String(secretName),
SecretString: aws.String(secretValue),
})
if err != nil {
return fmt.Errorf("failed to create AWS secret: %w", err)
}
return nil
}
func UpdateAWSSecret(ctx context.Context, k8sClient *kubernetes.Clientset, secretName, secretValue, region string) error {
id, key, err := fetchAWSCreds(ctx, k8sClient)
if err != nil {
return err
}
sess, err := session.NewSession(&aws.Config{
Credentials: awscred.NewCredentials(&awscred.StaticProvider{Value: awscred.Value{
AccessKeyID: id,
SecretAccessKey: key,
}}),
Region: aws.String(region),
})
if err != nil {
return fmt.Errorf("failed to create AWS session: %w", err)
}
svc := secretsmanager.New(sess)
_, err = svc.UpdateSecret(&secretsmanager.UpdateSecretInput{
SecretId: aws.String(secretName),
SecretString: aws.String(secretValue),
})
if err != nil {
return fmt.Errorf("failed to update AWS secret: %w", err)
}
return nil
}
func CreateAWSSecret(ctx context.Context, k8sClient *kubernetes.Clientset, secretName, secretValue, region string) error {
id, key, err := fetchAWSCreds(ctx, k8sClient)
if err != nil {
return err
}
sess, err := session.NewSession(&aws.Config{
Credentials: awscred.NewCredentials(&awscred.StaticProvider{Value: awscred.Value{
AccessKeyID: id,
SecretAccessKey: key,
}}),
Region: aws.String(region),
})
if err != nil {
return fmt.Errorf("failed to create AWS session: %w", err)
}
svc := secretsmanager.New(sess)
_, err = svc.CreateSecretWithContext(ctx, &secretsmanager.CreateSecretInput{
Name: aws.String(secretName),
SecretString: aws.String(secretValue),
})
if err != nil {
return fmt.Errorf("failed to create AWS secret: %w", err)
}
return nil
}
func UpdateAWSSecret(ctx context.Context, k8sClient *kubernetes.Clientset, secretName, secretValue, region string) error {
id, key, err := fetchAWSCreds(ctx, k8sClient)
if err != nil {
return err
}
sess, err := session.NewSession(&aws.Config{
Credentials: awscred.NewCredentials(&awscred.StaticProvider{Value: awscred.Value{
AccessKeyID: id,
SecretAccessKey: key,
}}),
Region: aws.String(region),
})
if err != nil {
return fmt.Errorf("failed to create AWS session: %w", err)
}
svc := secretsmanager.New(sess)
_, err = svc.UpdateSecretWithContext(ctx, &secretsmanager.UpdateSecretInput{
SecretId: aws.String(secretName),
SecretString: aws.String(secretValue),
})
if err != nil {
return fmt.Errorf("failed to update AWS secret: %w", err)
}
return nil
}
🤖 Prompt for AI Agents
In `@test/utils/conditions.go` around lines 149 - 203, Both CreateAWSSecret and
UpdateAWSSecret accept a ctx but call the blocking SDK methods; update each to
use the context-aware variants by replacing svc.CreateSecret(...) with
svc.CreateSecretWithContext(ctx, ...) in CreateAWSSecret and
svc.UpdateSecret(...) with svc.UpdateSecretWithContext(ctx, ...) in
UpdateAWSSecret so cancellations/timeouts propagate; keep the same
inputs/outputs and error wrapping around the calls.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


func DeleteAWSSecret(ctx context.Context, k8sClient *kubernetes.Clientset, secretName, region string) error {
id, key, err := fetchAWSCreds(ctx, k8sClient)
if err != nil {
Expand Down Expand Up @@ -201,4 +257,4 @@ func ReplacePatternInAsset(replacePatternString ...string) AssetFunc {
replacedFileContent := replacer.Replace(string(fileContent))
return []byte(replacedFileContent), nil
}
}
}