Skip to content

ROSAENG-60112 | test: add unit tests for pkg/aws#3274

Draft
olucasfreitas wants to merge 2 commits into
openshift:masterfrom
olucasfreitas:ROSAENG-60112-1A
Draft

ROSAENG-60112 | test: add unit tests for pkg/aws#3274
olucasfreitas wants to merge 2 commits into
openshift:masterfrom
olucasfreitas:ROSAENG-60112-1A

Conversation

@olucasfreitas

@olucasfreitas olucasfreitas commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Description

Add meaningful unit tests for previously untested files and functions in pkg/aws/. This is Phase 1A of the coverage improvement initiative targeting 90% meaningful test coverage across the ROSA CLI.

New and expanded test files (8 files, ~185 test cases, 2,645 lines):

File Specs Coverage Target
idps_test.go 11 OIDC provider Create/Has/Delete -- tags, NoSuchEntity, URL mismatch
quota_test.go 7 GetServiceQuota lookup, GetIAMServiceQuota via mock
policy_document_test.go 30 Parse/interpolate/principals/actions/GenerateRolePolicyDoc
helpers_additional_test.go ~63 ARNValidator, SecretManagerArnValidator, GetPathFromARN, GetResourceId*, SetSubnetOption, HasDuplicates, TrimRoleSuffix, ARNPathValidator, UserNoProxyValidator, name builders, isSTS, resolveSTSRole
cloudformation_test.go 22 CheckStackReady, GetCFStack, DeleteCFStack, UpdateStack no-op, buildInput
sts_test.go 25 ValidateRoleARNAccountID, HasPermissionsBoundary, SortRolesByLinkedRole, DeleteUserRole, DeleteOCMRole
client_additional_test.go 14 CheckRoleExists, GetRoleByARN, GetRoleByName, SecretsManager CRUD
policies_additional_test.go 14 hasCompatibleMajorMinorVersionTags (semver upgrade logic), IsPolicyCompatible

What's NOT included (intentionally):

  • permissions.go (ValidateSCP) -- deep dependencies on SimulatePrincipalPolicy paginator; better covered by integration/E2E tests
  • ValidateQuota / ListServiceQuotas -- use internal paginators that can't be cleanly mocked; the pure GetServiceQuota function is tested
  • CreateS3Bucket / DeleteS3Bucket -- require 5+ chained S3 mock expectations; meaningful testing requires integration approach
  • Coverage-for-coverage-sake tests -- all tests validate real expected behavior

Summary:

  • Before: 121 specs in pkg/aws
  • After: 309 specs (188 new), all passing
  • No existing tests modified or weakened

Validation

  • go test ./pkg/aws/... -- 309/309 specs pass
  • go vet ./pkg/aws/... -- clean
  • make pre-push-checks -- all 5 checks pass (format, build, lint, coverage, tests)
  • No existing tests were modified or weakened

Links

Summary by CodeRabbit

  • Tests
    • Expanded test coverage for AWS service integrations, including IAM roles, secrets management, CloudFormation stacks, OIDC providers, and policy handling.

Add meaningful unit tests for previously untested files in pkg/aws:

- idps_test.go: OIDC provider Create/Has/Delete operations
- quota_test.go: service quota lookup and IAM quota retrieval
- policy_document_test.go: policy parsing, interpolation, principals, actions
- helpers_additional_test.go: ARN validation, path extraction, subnet display
- cloudformation_test.go: stack lifecycle, ready check, update no-op
- sts_test.go: account ID validation, permissions boundary, role sorting

Total: 6 new files, ~120 test cases, all passing.
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 18, 2026
@openshift-ci

openshift-ci Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Seven new Ginkgo/Gomega test files are added to pkg/aws, covering the following areas: ARN validators and helper/naming utilities (helpers_additional_test.go); policy document construction, interpolation, and generation (policy_document_test.go); IAM role and Secrets Manager client methods (client_additional_test.go); OIDC provider management (idps_test.go); policy version compatibility logic (policies_additional_test.go); STS role validation and IAM role deletion flows (sts_test.go); and CloudFormation stack operations plus service quota retrieval (cloudformation_test.go, quota_test.go). All tests use gomock-backed AWS API mocks; no production code is modified.

🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Test Structure And Quality ⚠️ Warning Review comment flagged missing nil-Principal test for GetAWSPrincipals—implementation dereferences p.Principal without checking if nil, which would panic. This critical edge case test was not added... Add test case: "It(\"returns empty when Principal is nil\"...)" to GetAWSPrincipals tests; also add meaningful failure messages to Expect assertions lacking them across policy_document_test.go and helpers_additional_test.go per check req...
✅ Passed checks (14 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely identifies the main change: adding unit tests for pkg/aws, with the associated Jira ticket (ROSAENG-60112) following the required commit format.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed All test titles in the 8 new test files use static, descriptive string literals with no dynamic values (no UUIDs, timestamps, pod/namespace names, IPs, or fmt.Sprintf calls) embedded in test names.
Microshift Test Compatibility ✅ Passed All new test files are unit tests in pkg/aws/ using gomock to mock AWS APIs. They do not interact with Kubernetes clusters, use OpenShift-specific APIs, or make any cluster assumptions. The MicroSh...
Single Node Openshift (Sno) Test Compatibility ✅ Passed These are unit tests for AWS client library code (pkg/aws/), not e2e tests. They mock AWS services via gomock and don't interact with cluster topology. SNO compatibility check applies only to e2e t...
Topology-Aware Scheduling Compatibility ✅ Passed This PR adds only Go unit tests for pkg/aws/ business logic. No deployment manifests, operator code, or Kubernetes scheduling constraints are present. The check is not applicable to pure test files.
Ote Binary Stdout Contract ✅ Passed All 8 new test files use safe Ginkgo v2 patterns (var _ = Describe); no process-level code, logging, or stdout writes detected; aws_suite_test.go has only TestAws() and RunSpecs() calls.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed These are local unit tests of AWS SDK client wrappers using gomock with no network operations, IPv4-only assumptions, or external connectivity requirements. IPv4 addresses (10.0.0.1, etc.) are test...
No-Weak-Crypto ✅ Passed No weak cryptography usage detected. All 8 test files (2,645 lines) contain only test code using AWS SDK and standard testing frameworks without MD5, SHA1, DES, RC4, 3DES, Blowfish, ECB, custom cry...
Container-Privileges ✅ Passed PR contains only Go test files in pkg/aws/; no container/K8s manifests with privileged configurations present.
No-Sensitive-Data-In-Logs ✅ Passed Test files contain no logging statements that expose passwords, tokens, API keys, PII, or credentials. Mentions of "secret" are limited to test data, mock ARNs, and Gomega assertions.
Description check ✅ Passed The pull request description provides comprehensive context including PR summary, detailed objectives, test coverage metrics, validation steps, and Jira link.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci

openshift-ci Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: olucasfreitas

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@olucasfreitas olucasfreitas changed the title ROSAENG-60112 | test: add unit tests for pkg/aws (Phase 1A) ROSAENG-60112 | test: add unit tests for pkg/aws Jun 18, 2026
@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 18, 2026
@olucasfreitas

Copy link
Copy Markdown
Contributor Author

/ok-to-test

@openshift-ci openshift-ci Bot added the ok-to-test Indicates a non-member PR verified by an org member that is safe to test. label Jun 18, 2026
@olucasfreitas

Copy link
Copy Markdown
Contributor Author

/test all

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

Add tests for previously uncovered high-priority functions:

- client_additional_test.go: CheckRoleExists, GetRoleByARN, GetRoleByName,
  CreateSecretInSecretsManager, DeleteSecretInSecretsManager
- policies_additional_test.go: hasCompatibleMajorMinorVersionTags (semver
  upgrade logic), IsPolicyCompatible (version tag checking)
- sts_test.go: DeleteUserRole, DeleteOCMRole with full mock chains
  including detach/delete policy flows and DeleteConflictException handling
- helpers_additional_test.go: ARNPathValidator, UserNoProxyValidator,
  UserNoProxyDuplicateValidator, GetOCMRoleName, GetUserRoleName,
  GetOperatorPolicyName, GetPolicyArn, GetOperatorPolicyARN,
  IsStandardNamedAccountRole, isSTS, resolveSTSRole

Total: 309 specs (up from 121 baseline), all passing.
@olucasfreitas

Copy link
Copy Markdown
Contributor Author

/test all

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
pkg/aws/client_additional_test.go (1)

202-205: ⚡ Quick win

Strengthen Secrets Manager input assertions to avoid false positives.

These expectations currently accept any request payload, so regressions in secret target/name/value can still pass. Assert key input fields in the mock callbacks.

Suggested tightening
- mockSecretsManagerAPI.EXPECT().CreateSecret(gomock.Any(), gomock.Any()).Return(
-   &secretsmanager.CreateSecretOutput{
-     ARN: awsSdk.String(secretARN),
-   }, nil)
+ mockSecretsManagerAPI.EXPECT().CreateSecret(gomock.Any(), gomock.Any()).
+   DoAndReturn(func(_ interface{}, input *secretsmanager.CreateSecretInput, _ ...interface{}) (*secretsmanager.CreateSecretOutput, error) {
+     Expect(awsSdk.ToString(input.Name)).To(Equal(secretName))
+     Expect(awsSdk.ToString(input.SecretString)).To(Equal(secretValue))
+     return &secretsmanager.CreateSecretOutput{
+       ARN: awsSdk.String(secretARN),
+     }, nil
+   })

- mockSecretsManagerAPI.EXPECT().DescribeSecret(gomock.Any(), gomock.Any()).Return(
-   &secretsmanager.DescribeSecretOutput{}, nil)
- mockSecretsManagerAPI.EXPECT().DeleteSecret(gomock.Any(), gomock.Any()).Return(
-   &secretsmanager.DeleteSecretOutput{}, nil)
+ mockSecretsManagerAPI.EXPECT().DescribeSecret(gomock.Any(), gomock.Any()).
+   DoAndReturn(func(_ interface{}, input *secretsmanager.DescribeSecretInput, _ ...interface{}) (*secretsmanager.DescribeSecretOutput, error) {
+     Expect(awsSdk.ToString(input.SecretId)).To(Equal(secretARN))
+     return &secretsmanager.DescribeSecretOutput{}, nil
+   })
+ mockSecretsManagerAPI.EXPECT().DeleteSecret(gomock.Any(), gomock.Any()).
+   DoAndReturn(func(_ interface{}, input *secretsmanager.DeleteSecretInput, _ ...interface{}) (*secretsmanager.DeleteSecretOutput, error) {
+     Expect(awsSdk.ToString(input.SecretId)).To(Equal(secretARN))
+     return &secretsmanager.DeleteSecretOutput{}, nil
+   })

As per coding guidelines, **/*_test.go: “Flag weak tests that only restate implementation or changes that weaken existing assertions.”

Also applies to: 230-233

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/aws/client_additional_test.go` around lines 202 - 205, The mock
expectation for mockSecretsManagerAPI.EXPECT().CreateSecret currently uses
gomock.Any() to match the input parameter, which means any request payload is
accepted and regressions in secret target/name/value can pass undetected.
Replace the gomock.Any() matcher for the input parameter in the CreateSecret
expectation with specific matchers (such as gomock.Eq() or a custom matcher)
that assert the key input fields like the secret name and value being passed to
the API call. This will ensure the test catches actual regressions if these
critical parameters are not set correctly. Apply the same strengthening to the
other CreateSecret expectation mentioned in the comment.

Source: Coding guidelines

pkg/aws/sts_test.go (1)

300-301: ⚡ Quick win

Assert role/policy identifiers in detach/delete expectations.

Using gomock.Any() + call counts here allows wrong policy ARN/role wiring to pass. Use explicit DetachRolePolicyInput / DeletePolicyInput expectations per policy.

Suggested tightening
- mockIamAPI.EXPECT().DetachRolePolicy(gomock.Any(), gomock.Any()).Return(&iam.DetachRolePolicyOutput{}, nil).Times(2)
+ mockIamAPI.EXPECT().DetachRolePolicy(gomock.Any(), &iam.DetachRolePolicyInput{
+   RoleName:  awsSdk.String("test-role"),
+   PolicyArn: awsSdk.String("arn:aws:iam::123:policy/Policy1"),
+ }).Return(&iam.DetachRolePolicyOutput{}, nil)
+ mockIamAPI.EXPECT().DetachRolePolicy(gomock.Any(), &iam.DetachRolePolicyInput{
+   RoleName:  awsSdk.String("test-role"),
+   PolicyArn: awsSdk.String("arn:aws:iam::123:policy/Policy2"),
+ }).Return(&iam.DetachRolePolicyOutput{}, nil)

- mockIamAPI.EXPECT().DetachRolePolicy(gomock.Any(), gomock.Any()).Return(&iam.DetachRolePolicyOutput{}, nil)
- mockIamAPI.EXPECT().DeletePolicy(gomock.Any(), gomock.Any()).Return(&iam.DeletePolicyOutput{}, nil)
+ mockIamAPI.EXPECT().DetachRolePolicy(gomock.Any(), &iam.DetachRolePolicyInput{
+   RoleName:  awsSdk.String("ocm-role"),
+   PolicyArn: awsSdk.String("arn:aws:iam::123:policy/TestPolicy"),
+ }).Return(&iam.DetachRolePolicyOutput{}, nil)
+ mockIamAPI.EXPECT().DeletePolicy(gomock.Any(), &iam.DeletePolicyInput{
+   PolicyArn: awsSdk.String("arn:aws:iam::123:policy/TestPolicy"),
+ }).Return(&iam.DeletePolicyOutput{}, nil)

As per coding guidelines, **/*_test.go: “Flag weak tests that only restate implementation or changes that weaken existing assertions.”

Also applies to: 391-392

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/aws/sts_test.go` around lines 300 - 301, The mock expectations for
DetachRolePolicy and DeletePolicy use gomock.Any() for input parameters combined
with Times(2) call counts, which weakens the test by allowing incorrect policy
ARNs or role names to pass without detection. Replace the gomock.Any()
placeholders with explicit DetachRolePolicyInput and DeletePolicyInput
expectations that specify the exact policy ARN and role identifier values that
should be used, ensuring the test validates the correct wiring of roles and
policies rather than just counting calls.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/aws/policy_document_test.go`:
- Around line 67-109: The GetAWSPrincipals test suite does not cover the edge
case where the PolicyStatement has a nil Principal field. Add a new test case
within the Describe("GetAWSPrincipals") block that creates a PolicyStatement
with Principal explicitly set to nil and verifies that GetAWSPrincipals()
handles this gracefully by returning an empty slice, ensuring the implementation
does not panic when dereferencing a nil Principal.

---

Nitpick comments:
In `@pkg/aws/client_additional_test.go`:
- Around line 202-205: The mock expectation for
mockSecretsManagerAPI.EXPECT().CreateSecret currently uses gomock.Any() to match
the input parameter, which means any request payload is accepted and regressions
in secret target/name/value can pass undetected. Replace the gomock.Any()
matcher for the input parameter in the CreateSecret expectation with specific
matchers (such as gomock.Eq() or a custom matcher) that assert the key input
fields like the secret name and value being passed to the API call. This will
ensure the test catches actual regressions if these critical parameters are not
set correctly. Apply the same strengthening to the other CreateSecret
expectation mentioned in the comment.

In `@pkg/aws/sts_test.go`:
- Around line 300-301: The mock expectations for DetachRolePolicy and
DeletePolicy use gomock.Any() for input parameters combined with Times(2) call
counts, which weakens the test by allowing incorrect policy ARNs or role names
to pass without detection. Replace the gomock.Any() placeholders with explicit
DetachRolePolicyInput and DeletePolicyInput expectations that specify the exact
policy ARN and role identifier values that should be used, ensuring the test
validates the correct wiring of roles and policies rather than just counting
calls.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: f3221126-1f62-42d2-86ca-6c7786a4b68a

📥 Commits

Reviewing files that changed from the base of the PR and between da4975e and 91aa4ac.

📒 Files selected for processing (8)
  • pkg/aws/client_additional_test.go
  • pkg/aws/cloudformation_test.go
  • pkg/aws/helpers_additional_test.go
  • pkg/aws/idps_test.go
  • pkg/aws/policies_additional_test.go
  • pkg/aws/policy_document_test.go
  • pkg/aws/quota_test.go
  • pkg/aws/sts_test.go

Comment on lines +67 to +109
Describe("GetAWSPrincipals", func() {
It("returns a single principal when AWS is a string", func() {
stmt := PolicyStatement{
Principal: &PolicyStatementPrincipal{
AWS: "arn:aws:iam::123456:root",
},
}
Expect(stmt.GetAWSPrincipals()).To(Equal([]string{"arn:aws:iam::123456:root"}))
})

It("returns all principals when AWS is a slice", func() {
stmt := PolicyStatement{
Principal: &PolicyStatementPrincipal{
AWS: []interface{}{"arn:aws:iam::111:root", "arn:aws:iam::222:root"},
},
}
Expect(stmt.GetAWSPrincipals()).To(ConsistOf(
"arn:aws:iam::111:root",
"arn:aws:iam::222:root",
))
})

It("returns an empty slice when AWS is nil", func() {
stmt := PolicyStatement{
Principal: &PolicyStatementPrincipal{AWS: nil},
}
Expect(stmt.GetAWSPrincipals()).To(BeEmpty())
})

It("handles a single-element slice from unmarshalled JSON", func() {
raw := `{"Principal":{"AWS":["arn:aws:iam::999:role/foo"]}}`
var stmt PolicyStatement
Expect(json.Unmarshal([]byte(raw), &stmt)).To(Succeed())
Expect(stmt.GetAWSPrincipals()).To(Equal([]string{"arn:aws:iam::999:role/foo"}))
})

It("handles a string from unmarshalled JSON", func() {
raw := `{"Principal":{"AWS":"arn:aws:iam::888:role/bar"}}`
var stmt PolicyStatement
Expect(json.Unmarshal([]byte(raw), &stmt)).To(Succeed())
Expect(stmt.GetAWSPrincipals()).To(Equal([]string{"arn:aws:iam::888:role/bar"}))
})
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a nil-Principal test for GetAWSPrincipals.

This suite never exercises PolicyStatement{Principal: nil}. In pkg/aws/policy_document.go, GetAWSPrincipals dereferences p.Principal directly, so this edge case can panic untested.

✅ Suggested test addition
 Describe("GetAWSPrincipals", func() {
+	It("returns an empty slice when Principal is nil", func() {
+		stmt := PolicyStatement{}
+		Expect(stmt.GetAWSPrincipals()).To(BeEmpty())
+	})
+
 	It("returns a single principal when AWS is a string", func() {
 		stmt := PolicyStatement{
 			Principal: &PolicyStatementPrincipal{

As per coding guidelines, “tests should prove correctness and be kept accurate to real failure/edge cases.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/aws/policy_document_test.go` around lines 67 - 109, The GetAWSPrincipals
test suite does not cover the edge case where the PolicyStatement has a nil
Principal field. Add a new test case within the Describe("GetAWSPrincipals")
block that creates a PolicyStatement with Principal explicitly set to nil and
verifies that GetAWSPrincipals() handles this gracefully by returning an empty
slice, ensuring the implementation does not panic when dereferencing a nil
Principal.

Source: Coding guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. ok-to-test Indicates a non-member PR verified by an org member that is safe to test.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant