Skip to content

Conversation

@osterman
Copy link
Member

@osterman osterman commented Dec 5, 2025

what

  • Implement four new AWS YAML functions: !aws.account_id, !aws.caller_identity_arn, !aws.caller_identity_user_id, and !aws.region
  • These functions retrieve AWS identity and configuration information using the STS GetCallerIdentity API
  • Provide seamless integration with Atmos authentication contexts for SSO and multi-account scenarios
  • Share a unified in-memory caching mechanism to minimize API calls during CLI invocation

why

  • Equivalent to Terragrunt's get_aws_account_id(), get_aws_caller_identity_arn(), get_aws_caller_identity_user_id(), and similar functions
  • Commonly needed for dynamic resource naming, cross-account access control, and audit logging
  • Integrates cleanly with existing Atmos YAML function architecture and authentication infrastructure
  • Reduces boilerplate by eliminating need for separate !exec calls to AWS CLI
  • Type-safe and predictable compared to template-based approaches

references

Summary by CodeRabbit

  • New Features

    • Added four AWS YAML functions for stack manifests to surface AWS account, caller ARN, caller user ID, and region; results are cached per CLI invocation to reduce API calls.
  • Documentation

    • Added detailed docs and examples for each AWS YAML function and a blog post describing use cases and integration.
  • Tests

    • Added extensive tests covering function behavior, caching, error handling, and integration scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

@osterman osterman requested a review from a team as a code owner December 5, 2025 16:38
@github-actions github-actions bot added the size/xl Extra large size PR label Dec 5, 2025
@mergify
Copy link

mergify bot commented Dec 5, 2025

Warning

This PR exceeds the recommended limit of 1,000 lines.

Large PRs are difficult to review and may be rejected due to their size.

Please verify that this PR does not address multiple issues.
Consider refactoring it into smaller, more focused PRs to facilitate a smoother review process.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 5, 2025

📝 Walkthrough

Walkthrough

Adds four AWS YAML functions, STS caller-identity utilities, an injectable AWSGetter with per-auth-context caching, a new sentinel error, tests, docs/blog pages, and a linter exclusion for the aws_utils directory.

Changes

Cohort / File(s) Summary
Build & Lint
\.golangci\.yml
Added a depguard exclusion so internal/aws_utils is exempt from provider-agnostic import restrictions.
Errors
errors/errors.go
Added exported sentinel error ErrAwsGetCallerIdentity = errors.New("failed to get AWS caller identity").
AWS Utilities
internal/aws_utils/...
internal/aws_utils/aws_utils.go
Added AWSCallerIdentityResult type and GetAWSCallerIdentity(ctx, region, roleArn, assumeRoleDuration, authContext) which loads AWS config (wrapping inner errors with %w) and calls STS GetCallerIdentity, returning structured result.
AWS Getter & Cache
internal/exec/aws_getter.go
New AWSCallerIdentity type and AWSGetter interface; production defaultAWSGetter; global injectable getter via SetAWSGetter; RWMutex-protected per-auth-context in-memory caching with double-checked locking; ClearAWSIdentityCache; logging and perf traces.
YAML Processors
internal/exec/yaml_func_aws.go
New processTagAwsValue helper and four concrete processors for !aws.account_id, !aws.caller_identity_arn, !aws.caller_identity_user_id, and !aws.region that resolve identity via the cached getter and extract fields; includes perf/logging and error handling.
YAML Simple Tag Routing
internal/exec/yaml_func_utils.go
Extended processSimpleTags to dispatch the four new AWS YAML function constants (each guarded by skip checks).
YAML Constants & Utils
pkg/utils/yaml_utils.go
Added exported constants AtmosYamlFuncAwsAccountID, AtmosYamlFuncAwsCallerIdentityArn, AtmosYamlFuncAwsCallerIdentityUserID, AtmosYamlFuncAwsRegion; appended them to AtmosYamlTags and added map keys for O(1) lookup.
Tests
internal/exec/yaml_func_aws_test.go, pkg/utils/yaml_utils_test.go
Added comprehensive tests: mock/counting AWSGetter, caching semantics (hits/misses, error caching), cache-key tests, interface/default getter checks, error wrapping verification, tag map tests, and tests covering auth-context behavior and SetAWSGetter.
Docs & Blog
website/docs/functions/yaml/*.mdx, website/blog/2025-12-05-aws-yaml-functions.mdx
Added docs for each AWS YAML function, updated YAML functions index, and added a blog post describing the functions, behavior, caching, examples, and Atmos Auth integration.

Sequence Diagram

sequenceDiagram
    actor User
    participant YAML as "YAML Processor"
    participant Cache as "Identity Cache"
    participant Getter as "AWS Getter"
    participant Utils as "internal/aws_utils"
    participant STS as "AWS STS"

    User->>YAML: Evaluate "!aws.*" tag
    YAML->>Cache: lookup(authContext)
    alt cache hit
        Cache-->>YAML: cached identity
    else cache miss
        Cache->>Getter: GetCallerIdentity(ctx, atmosConfig, authContext)
        Getter->>Utils: GetAWSCallerIdentity(ctx, region, roleArn, ...)
        Utils->>Utils: LoadAWSConfigWithAuth(...) (wrap errors with %w)
        Utils->>STS: STS GetCallerIdentity
        STS-->>Utils: caller identity
        Utils-->>Getter: AWSCallerIdentityResult
        Getter-->>Cache: store(identity or error)
        Cache-->>YAML: identity (or propagate error)
    end
    YAML->>YAML: extract field (account_id / arn / user_id / region)
    YAML-->>User: return resolved value or error
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas to focus on:
    • RWMutex double-checked locking and cache key correctness (possible data races).
    • Error wrapping/provenance across LoadAWSConfigWithAuth → GetAWSCallerIdentity → sentinel error.
    • Global state injection via SetAWSGetter and restore semantics used by tests.

Possibly related PRs

Suggested reviewers

  • aknysh
  • mcalhoun

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: implementing four new AWS YAML functions (!aws.account_id, !aws.caller_identity_arn, !aws.caller_identity_user_id, !aws.region) for retrieving AWS identity and region information.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch osterman/aws-yaml-funcs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions
Copy link

github-actions bot commented Dec 5, 2025

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

@osterman osterman force-pushed the osterman/aws-yaml-funcs branch from ca45d16 to a7f353d Compare December 5, 2025 18:15
@codecov
Copy link

codecov bot commented Dec 5, 2025

Codecov Report

❌ Patch coverage is 63.56589% with 47 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.68%. Comparing base (61ac5a5) to head (c9bfe8a).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
internal/exec/aws_getter.go 61.11% 20 Missing and 1 partial ⚠️
internal/aws_utils/aws_utils.go 5.26% 18 Missing ⚠️
internal/exec/yaml_func_aws.go 83.33% 6 Missing and 2 partials ⚠️

❌ Your patch check has failed because the patch coverage (63.56%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1843      +/-   ##
==========================================
+ Coverage   72.57%   72.68%   +0.11%     
==========================================
  Files         521      527       +6     
  Lines       49522    50477     +955     
==========================================
+ Hits        35939    36689     +750     
- Misses      10844    11008     +164     
- Partials     2739     2780      +41     
Flag Coverage Δ
unittests 72.68% <63.56%> (+0.11%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
errors/errors.go 100.00% <ø> (ø)
internal/exec/yaml_func_utils.go 95.23% <100.00%> (+0.50%) ⬆️
pkg/utils/yaml_utils.go 81.10% <ø> (ø)
internal/exec/yaml_func_aws.go 83.33% <83.33%> (ø)
internal/aws_utils/aws_utils.go 54.38% <5.26%> (-25.11%) ⬇️
internal/exec/aws_getter.go 61.11% <61.11%> (ø)

... and 31 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
pkg/utils/yaml_utils_test.go (1)

755-779: AWS YAML tags correctly wired into AtmosYamlTagsMap tests.

Adding the four AtmosYamlFuncAws* entries to expectedTags keeps the map–slice consistency check up to date for the new functions. If you want a bit more coverage, you could also add these tags to the table in TestAtmosYamlTagsMap_O1Lookup so the O(1) lookup test explicitly exercises them too.

internal/exec/yaml_func_utils.go (1)

157-169: Consider treating misused AWS tags as errors instead of leaving them unprocessed.

Right now the AWS branches gate on exact equality:

if input == u.AtmosYamlFuncAwsAccountID && !skipFunc(skip, u.AtmosYamlFuncAwsAccountID) {
    return processTagAwsAccountID(...)
}

so something like !aws.account_id foo will fall through and be returned as a raw string. Given processTagAwsValue already validates input != expectedTag and returns ErrYamlFuncInvalidArguments, you could instead route on matchesPrefix (or similar) to surface a clear error when callers accidentally supply arguments to these no-arg functions.

That would make the AWS tags behave more like the other YAML functions in terms of misuse reporting, without changing the happy path.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ed4c02b and a7f353d.

📒 Files selected for processing (14)
  • .golangci.yml (1 hunks)
  • errors/errors.go (1 hunks)
  • internal/aws_utils/aws_utils.go (2 hunks)
  • internal/exec/aws_getter.go (1 hunks)
  • internal/exec/yaml_func_aws.go (1 hunks)
  • internal/exec/yaml_func_aws_test.go (1 hunks)
  • internal/exec/yaml_func_utils.go (1 hunks)
  • pkg/utils/yaml_utils.go (2 hunks)
  • pkg/utils/yaml_utils_test.go (1 hunks)
  • website/docs/functions/yaml/aws.account-id.mdx (1 hunks)
  • website/docs/functions/yaml/aws.caller-identity-arn.mdx (1 hunks)
  • website/docs/functions/yaml/aws.caller-identity-user-id.mdx (1 hunks)
  • website/docs/functions/yaml/aws.region.mdx (1 hunks)
  • website/docs/functions/yaml/index.mdx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.go: Use functional options pattern to avoid functions with many parameters. Define Option functions that modify a Config struct and pass variadic options to New functions.
Use context.Context for cancellation signals, deadlines/timeouts, and request-scoped values (trace IDs). Context should be first parameter in functions that accept it. DO NOT use context for configuration, dependencies, or avoiding proper function parameters.
All comments must end with periods. This is enforced by the godot linter.
NEVER delete existing comments without a very strong reason. Preserve helpful comments, update them to match code changes, refactor for clarity, and add context when modifying code. Only remove factually incorrect, duplicated, or outdated comments.
Organize imports in three groups separated by blank lines (Go stdlib, 3rd-party excluding cloudposse/atmos, Atmos packages), sorted alphabetically. Maintain aliases: cfg, log, u, errUtils.
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig parameter.
All errors MUST be wrapped using static errors defined in errors/errors.go. Use errors.Join for combining multiple errors, fmt.Errorf with %w for adding string context, error builder for complex errors, and errors.Is() for error checking. NEVER use dynamic errors directly.
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation. Never create manual mocks.
Use viper.BindEnv with ATMOS_ prefix for environment variables.
Use colors from pkg/ui/theme/colors.go for theme consistency.
Ensure Linux/macOS/Windows compatibility. Use SDKs over binaries. Use filepath.Join(), not hardcoded path separators.
Small focused files (<600 lines). One cmd/impl per file. Co-locate tests. Never use //revive:disable:file-length-limit.

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider us...

Files:

  • errors/errors.go
  • internal/aws_utils/aws_utils.go
  • pkg/utils/yaml_utils.go
  • internal/exec/yaml_func_utils.go
  • internal/exec/yaml_func_aws.go
  • pkg/utils/yaml_utils_test.go
  • internal/exec/aws_getter.go
  • internal/exec/yaml_func_aws_test.go
.golangci.yml

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Configure golangci-lint in .golangci.yml with specific linters enabled: gofmt, goimports, govet, staticcheck, errcheck, ineffassign, misspell, unused, revive, gocritic

Files:

  • .golangci.yml
website/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

website/**: Update website documentation in the website/ directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in the website/ directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases

Files:

  • website/docs/functions/yaml/aws.caller-identity-arn.mdx
  • website/docs/functions/yaml/aws.account-id.mdx
  • website/docs/functions/yaml/aws.caller-identity-user-id.mdx
  • website/docs/functions/yaml/aws.region.mdx
  • website/docs/functions/yaml/index.mdx
**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

**/*_test.go: Prefer unit tests with mocks over integration tests. Use interfaces + dependency injection for testability. Generate mocks with go.uber.org/mock/mockgen. Use table-driven tests for comprehensive coverage. Target >80% code coverage.
Test behavior, not implementation. Never test stub functions. Avoid tautological tests. Make code testable with DI to avoid os.Exit and external systems. Use assert.ErrorIs(err, ErrSentinel) for stdlib/our errors.

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Files:

  • pkg/utils/yaml_utils_test.go
  • internal/exec/yaml_func_aws_test.go
🧠 Learnings (36)
📓 Common learnings
Learnt from: mcalhoun
Repo: cloudposse/atmos PR: 963
File: website/docs/core-concepts/projects/configuration/stores.mdx:286-286
Timestamp: 2025-04-25T20:54:19.701Z
Learning: For the AWS SSM Parameter Store implementation in Atmos, support for `read_role_arn` and `write_role_arn` options is essential to enable cross-account access, allowing users to run operations like `terraform plan` in multiple accounts while accessing values across keystores. Azure Key Vault would need similar capabilities for cross-tenant/subscription authentication.
📚 Learning: 2025-06-23T02:14:30.937Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1327
File: cmd/terraform.go:111-117
Timestamp: 2025-06-23T02:14:30.937Z
Learning: In cmd/terraform.go, flags for the DescribeAffected function are added dynamically at runtime when info.Affected is true. This is intentional to avoid exposing internal flags like "file", "format", "verbose", "include-spacelift-admin-stacks", "include-settings", and "upload" in the terraform command interface, while still providing them for the shared DescribeAffected function used by both `atmos describe affected` and `atmos terraform apply --affected`.

Applied to files:

  • errors/errors.go
  • pkg/utils/yaml_utils.go
  • internal/exec/yaml_func_utils.go
📚 Learning: 2025-09-25T01:02:48.697Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/manager.go:304-312
Timestamp: 2025-09-25T01:02:48.697Z
Learning: The auth manager in pkg/auth/manager.go should remain cloud-agnostic and not contain AWS-specific logic or references to specific cloud providers. Keep the manager generic and extensible.

Applied to files:

  • .golangci.yml
  • internal/exec/aws_getter.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*.go : All code must pass golangci-lint checks

Applied to files:

  • .golangci.yml
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Organize imports in three groups separated by blank lines (Go stdlib, 3rd-party excluding cloudposse/atmos, Atmos packages), sorted alphabetically. Maintain aliases: cfg, log, u, errUtils.

Applied to files:

  • .golangci.yml
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to {go.mod,go.sum} : Manage dependencies with Go modules and keep dependencies up to date while minimizing external dependencies

Applied to files:

  • .golangci.yml
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.

Applied to files:

  • .golangci.yml
📚 Learning: 2024-12-03T04:01:16.446Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:0-0
Timestamp: 2024-12-03T04:01:16.446Z
Learning: In the `terraform.output.mdx` documentation file (`website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx`), the cache invalidation and cache scope behavior for the `!terraform.output` function are already described.

Applied to files:

  • website/docs/functions/yaml/aws.caller-identity-arn.mdx
  • website/docs/functions/yaml/aws.account-id.mdx
  • website/docs/functions/yaml/aws.caller-identity-user-id.mdx
  • website/docs/functions/yaml/aws.region.mdx
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).

Applied to files:

  • website/docs/functions/yaml/aws.account-id.mdx
  • website/docs/functions/yaml/aws.region.mdx
  • pkg/utils/yaml_utils.go
  • website/docs/functions/yaml/index.mdx
📚 Learning: 2024-12-01T00:33:20.298Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.

Applied to files:

  • website/docs/functions/yaml/aws.region.mdx
  • pkg/utils/yaml_utils.go
  • website/docs/functions/yaml/index.mdx
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • pkg/utils/yaml_utils.go
  • internal/exec/yaml_func_utils.go
  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-09-30T19:03:50.738Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 1560
File: pkg/utils/string_utils.go:43-64
Timestamp: 2025-09-30T19:03:50.738Z
Learning: In the Atmos codebase, YAML tags like !terraform.output rely on positional arguments, so the SplitStringByDelimiter function in pkg/utils/string_utils.go must preserve empty strings (even after trimming quotes) to maintain the correct number of positional arguments. Filtering out empty values after trimming would collapse the array and break these function calls.

Applied to files:

  • pkg/utils/yaml_utils.go
  • internal/exec/yaml_func_utils.go
  • internal/exec/yaml_func_aws.go
  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig parameter.

Applied to files:

  • pkg/utils/yaml_utils.go
  • internal/exec/yaml_func_utils.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.

Applied to files:

  • pkg/utils/yaml_utils.go
  • internal/exec/yaml_func_utils.go
📚 Learning: 2024-11-25T17:17:15.703Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 797
File: pkg/list/atmos.yaml:213-214
Timestamp: 2024-11-25T17:17:15.703Z
Learning: The file `pkg/list/atmos.yaml` is primarily intended for testing purposes.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2024-10-20T13:12:46.499Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 736
File: pkg/config/const.go:6-6
Timestamp: 2024-10-20T13:12:46.499Z
Learning: In `cmd/cmd_utils.go`, it's acceptable to have hardcoded references to `atmos.yaml` in logs, and it's not necessary to update them to use the `CliConfigFileName` constant.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-09-05T14:57:37.360Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 1448
File: cmd/ansible.go:26-28
Timestamp: 2025-09-05T14:57:37.360Z
Learning: The Atmos codebase uses a consistent pattern for commands that delegate to external tools: `PersistentFlags().Bool("", false, doubleDashHint)` where doubleDashHint provides help text about using double dashes to separate Atmos options from native command arguments. This pattern is used across terraform, packer, helmfile, atlantis, aws, and ansible commands.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2024-12-17T07:08:41.288Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 863
File: internal/exec/yaml_func_terraform_output.go:34-38
Timestamp: 2024-12-17T07:08:41.288Z
Learning: In the `processTagTerraformOutput` function within `internal/exec/yaml_func_terraform_output.go`, parameters are separated by spaces and do not contain spaces. Therefore, using `strings.Fields()` for parsing is acceptable, and there's no need to handle parameters with spaces.

Applied to files:

  • pkg/utils/yaml_utils.go
  • internal/exec/yaml_func_utils.go
  • internal/exec/yaml_func_aws.go
  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables → Viper unmarshals into atmosConfig.Settings via mapstructure → business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to internal/exec/template_funcs.go : New configs support Go templating with FuncMap() from internal/exec/template_funcs.go. Implement template functions in internal/exec/template_funcs.go, register them, add tests, and update documentation.

Applied to files:

  • internal/exec/yaml_func_utils.go
  • internal/exec/yaml_func_aws.go
  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-04-11T22:06:46.999Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1147
File: internal/exec/validate_schema.go:42-57
Timestamp: 2025-04-11T22:06:46.999Z
Learning: The "ExecuteAtmosValidateSchemaCmd" function in internal/exec/validate_schema.go has been reviewed and confirmed to have acceptable cognitive complexity despite static analysis warnings. The function uses a clean structure with only three if statements for error handling and delegates complex operations to helper methods.

Applied to files:

  • internal/exec/yaml_func_utils.go
📚 Learning: 2024-11-30T22:07:08.610Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: internal/exec/yaml_func_terraform_output.go:35-40
Timestamp: 2024-11-30T22:07:08.610Z
Learning: In the Go function `processTagTerraformOutput` in `internal/exec/yaml_func_terraform_output.go`, parameters cannot contain spaces. The code splits the input by spaces, and if the parameters contain spaces, `len(parts) != 3` will fail and show an error to the user.

Applied to files:

  • internal/exec/yaml_func_utils.go
  • internal/exec/yaml_func_aws.go
  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-10-13T18:13:54.020Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1622
File: pkg/perf/perf.go:140-184
Timestamp: 2025-10-13T18:13:54.020Z
Learning: In pkg/perf/perf.go, the `trackWithSimpleStack` function intentionally skips ownership checks at call stack depth > 1 to avoid expensive `getGoroutineID()` calls on every nested function. This is a performance optimization for the common single-goroutine execution case (most Atmos commands), accepting the rare edge case of potential metric corruption if multi-goroutine execution occurs at depth > 1. The ~19× performance improvement justifies this trade-off.

Applied to files:

  • internal/exec/yaml_func_utils.go
📚 Learning: 2024-11-19T23:00:45.899Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 795
File: internal/exec/stack_processor_utils.go:378-386
Timestamp: 2024-11-19T23:00:45.899Z
Learning: In the `ProcessYAMLConfigFile` function within `internal/exec/stack_processor_utils.go`, directory traversal in stack imports is acceptable and should not be restricted.

Applied to files:

  • internal/exec/yaml_func_aws.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.

Applied to files:

  • internal/exec/yaml_func_aws.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 764
File: internal/exec/describe_stacks.go:289-295
Timestamp: 2024-11-13T21:37:07.852Z
Learning: In the `internal/exec/describe_stacks.go` file of the `atmos` project written in Go, avoid extracting the stack name handling logic into a helper function within the `ExecuteDescribeStacks` method, even if the logic appears duplicated.

Applied to files:

  • internal/exec/yaml_func_aws.go
📚 Learning: 2024-12-03T05:18:49.169Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: internal/exec/terraform_utils.go:40-213
Timestamp: 2024-12-03T05:18:49.169Z
Learning: In the context of the Atmos project, it's acceptable for functions like `execTerraformOutput` to remain as single functions if they perform a single purpose, such as retrieving Terraform outputs for a component in a stack, even if the function is lengthy.

Applied to files:

  • internal/exec/yaml_func_aws.go
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!include` allows downloading local or remote files from different sources and assigning their contents to sections in stack manifests. It supports various protocols (file, http, git, s3, etc.) and can filter content using YQ expressions.

Applied to files:

  • website/docs/functions/yaml/index.mdx
📚 Learning: 2025-04-25T20:54:19.701Z
Learnt from: mcalhoun
Repo: cloudposse/atmos PR: 963
File: website/docs/core-concepts/projects/configuration/stores.mdx:286-286
Timestamp: 2025-04-25T20:54:19.701Z
Learning: For the AWS SSM Parameter Store implementation in Atmos, support for `read_role_arn` and `write_role_arn` options is essential to enable cross-account access, allowing users to run operations like `terraform plan` in multiple accounts while accessing values across keystores. Azure Key Vault would need similar capabilities for cross-tenant/subscription authentication.

Applied to files:

  • website/docs/functions/yaml/index.mdx
📚 Learning: 2025-11-11T03:47:59.576Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/which_test.go:166-223
Timestamp: 2025-11-11T03:47:59.576Z
Learning: In the cloudposse/atmos repo, tests that manipulate environment variables should use testing.T.Setenv for automatic setup/teardown instead of os.Setenv/Unsetenv.

Applied to files:

  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-11-11T03:47:45.878Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/add_test.go:67-77
Timestamp: 2025-11-11T03:47:45.878Z
Learning: In the cloudposse/atmos codebase, tests should prefer t.Setenv for environment variable setup/teardown instead of os.Setenv/Unsetenv to ensure test-scoped isolation.

Applied to files:

  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-11-10T20:03:56.875Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1775
File: pkg/auth/providers/aws/sso_provisioning.go:40-79
Timestamp: 2025-11-10T20:03:56.875Z
Learning: In the Atmos AWS SSO provider (pkg/auth/providers/aws/sso_provisioning.go), the OAuth access token from the AWS SSO device flow is intentionally stored in the `AccessKeyID` field of `AWSCredentials` during authentication. This token is then extracted and used for ListAccounts and ListAccountRoles API calls during identity provisioning. This design reuses the existing `AWSCredentials` type for token transport rather than creating a separate credential type.

Applied to files:

  • internal/exec/aws_getter.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests. Use interfaces + dependency injection for testability. Generate mocks with go.uber.org/mock/mockgen. Use table-driven tests for comprehensive coverage. Target >80% code coverage.

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*_test.go : Test behavior, not implementation. Never test stub functions. Avoid tautological tests. Make code testable with DI to avoid os.Exit and external systems. Use assert.ErrorIs(err, ErrSentinel) for stdlib/our errors.

Applied to files:

  • internal/exec/yaml_func_aws_test.go
🧬 Code graph analysis (5)
internal/aws_utils/aws_utils.go (2)
errors/errors.go (2)
  • ErrLoadAwsConfig (96-96)
  • ErrAwsGetCallerIdentity (90-90)
pkg/schema/schema.go (2)
  • Context (480-495)
  • AWSAuthContext (583-598)
internal/exec/yaml_func_utils.go (1)
pkg/utils/yaml_utils.go (4)
  • AtmosYamlFuncAwsAccountID (32-32)
  • AtmosYamlFuncAwsCallerIdentityArn (33-33)
  • AtmosYamlFuncAwsCallerIdentityUserID (34-34)
  • AtmosYamlFuncAwsRegion (35-35)
internal/exec/yaml_func_aws.go (4)
pkg/schema/schema.go (2)
  • AWSAuthContext (583-598)
  • AuthContext (569-579)
internal/exec/aws_getter.go (1)
  • AWSCallerIdentity (15-20)
errors/errors.go (1)
  • ErrYamlFuncInvalidArguments (89-89)
pkg/utils/yaml_utils.go (4)
  • AtmosYamlFuncAwsAccountID (32-32)
  • AtmosYamlFuncAwsCallerIdentityArn (33-33)
  • AtmosYamlFuncAwsCallerIdentityUserID (34-34)
  • AtmosYamlFuncAwsRegion (35-35)
pkg/utils/yaml_utils_test.go (1)
pkg/utils/yaml_utils.go (4)
  • AtmosYamlFuncAwsAccountID (32-32)
  • AtmosYamlFuncAwsCallerIdentityArn (33-33)
  • AtmosYamlFuncAwsCallerIdentityUserID (34-34)
  • AtmosYamlFuncAwsRegion (35-35)
internal/exec/aws_getter.go (4)
pkg/schema/schema.go (2)
  • AtmosConfiguration (53-94)
  • AWSAuthContext (583-598)
pkg/perf/perf.go (1)
  • Track (121-138)
pkg/logger/log.go (1)
  • Debug (24-26)
internal/aws_utils/aws_utils.go (1)
  • GetAWSCallerIdentity (141-179)
🪛 LanguageTool
website/docs/functions/yaml/aws.caller-identity-arn.mdx

[typographical] ~35-~35: To join two clauses or introduce examples, consider using an em dash.
Context: ..., Atmos: 1. Loads AWS Configuration - Uses the standard AWS SDK credential res...

(DASH_RULE)


[style] ~185-~185: Using many exclamation marks might seem excessive (in this case: 9 exclamation marks for a text that’s 3767 characters long)
Context: ...d role, etc.) ## Related Functions - !aws.account_id - Get the AWS account ID - !aws.caller_identity_user_id - Get the unique user ID - !aws.region ...

(EN_EXCESSIVE_EXCLAMATION)


[typographical] ~187-~187: To join two clauses or introduce examples, consider using an em dash.
Context: ...!aws.region](/functions/yaml/aws.region) - Get the AWS region

(DASH_RULE)

website/docs/functions/yaml/aws.account-id.mdx

[typographical] ~35-~35: To join two clauses or introduce examples, consider using an em dash.
Context: ..., Atmos: 1. Loads AWS Configuration - Uses the standard AWS SDK credential res...

(DASH_RULE)


[typographical] ~165-~165: To join two clauses or introduce examples, consider using an em dash.
Context: ...ctions/yaml/aws.caller-identity-user-id) - Get the unique user ID - [!aws.region](/...

(DASH_RULE)


[typographical] ~166-~166: To join two clauses or introduce examples, consider using an em dash.
Context: ...!aws.region](/functions/yaml/aws.region) - Get the AWS region

(DASH_RULE)

website/docs/functions/yaml/aws.caller-identity-user-id.mdx

[typographical] ~35-~35: To join two clauses or introduce examples, consider using an em dash.
Context: ..., Atmos: 1. Loads AWS Configuration - Uses the standard AWS SDK credential res...

(DASH_RULE)


[typographical] ~36-~36: To join two clauses or introduce examples, consider using an em dash.
Context: ...chain 2. Calls STS GetCallerIdentity - Makes an API call to retrieve the caller...

(DASH_RULE)


[typographical] ~37-~37: To join two clauses or introduce examples, consider using an em dash.
Context: ...e caller identity 3. Returns User ID - Extracts and returns the unique user ID ...

(DASH_RULE)


[style] ~135-~135: Using many exclamation marks might seem excessive (in this case: 10 exclamation marks for a text that’s 2873 characters long)
Context: ...y` permission ## Related Functions - !aws.account_id - Get the AWS account ID - !aws.caller_identity_arn - Get the full ARN - !aws.region ...

(EN_EXCESSIVE_EXCLAMATION)


[typographical] ~137-~137: To join two clauses or introduce examples, consider using an em dash.
Context: ...!aws.region](/functions/yaml/aws.region) - Get the AWS region

(DASH_RULE)

website/docs/functions/yaml/aws.region.mdx

[typographical] ~35-~35: To join two clauses or introduce examples, consider using an em dash.
Context: ..., Atmos: 1. Loads AWS Configuration - Uses the standard AWS SDK configuration ...

(DASH_RULE)


[style] ~174-~174: Using many exclamation marks might seem excessive (in this case: 9 exclamation marks for a text that’s 2971 characters long)
Context: ...y` permission ## Related Functions - !aws.account_id - Get the AWS account ID - !aws.caller_identity_arn - Get the full ARN - [!aws.caller_identity_user_id](/functions/...

(EN_EXCESSIVE_EXCLAMATION)


[typographical] ~176-~176: To join two clauses or introduce examples, consider using an em dash.
Context: ...ctions/yaml/aws.caller-identity-user-id) - Get the user ID

(DASH_RULE)

website/docs/functions/yaml/index.mdx

[style] ~87-~87: Using many exclamation marks might seem excessive (in this case: 16 exclamation marks for a text that’s 5088 characters long)
Context: ...ity using STS GetCallerIdentity - The [!aws.region](/functions/yaml/aws.regio...

(EN_EXCESSIVE_EXCLAMATION)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Acceptance Tests (linux)
  • GitHub Check: Summary
🔇 Additional comments (20)
.golangci.yml (1)

57-71: Depguard exclusion for internal/aws_utils is appropriate.

Excluding internal/aws_utils/** from the provider-agnostic auth depguard scope cleanly isolates AWS SDK usage to the internal utilities package without weakening the guardrails on pkg/auth. This aligns with the new STS helpers you added there.

errors/errors.go (1)

89-96: New ErrAwsGetCallerIdentity sentinel is well-scoped.

Defining ErrAwsGetCallerIdentity here gives a single, reusable sentinel for STS identity failures and fits neatly with the existing AWS/backend error group. No issues from an error-handling standpoint.

website/docs/functions/yaml/aws.caller-identity-arn.mdx (1)

1-187: Documentation matches the implemented !aws.caller_identity_arn behavior.

The page clearly explains no-arg usage, STS/GetCallerIdentity interaction, ARN formats, caching semantics, and Atmos auth integration, and it lines up with how the helper and shared identity cache are implemented. Looks solid.

website/docs/functions/yaml/index.mdx (1)

78-89: AWS YAML functions are well integrated into the index and examples.

The new bullets and the example stack.yaml clearly introduce !aws.account_id, !aws.caller_identity_arn, !aws.caller_identity_user_id, and !aws.region, and their described behavior matches the underlying implementation (STS for identity fields, config for region). Nicely slotted into the existing YAML function docs.

Also applies to: 164-175

internal/exec/yaml_func_aws.go (1)

1-151: Shared AWS YAML function helper is clean and consistent with existing patterns.

processTagAwsValue nicely centralizes input validation, auth-context extraction, cached identity lookup, and field extraction, and the four processTagAws* wrappers add perf tracking and targeted debug logs without extra complexity. Error handling via ErrYamlFuncInvalidArguments and wrapped identity errors is in line with the rest of the exec layer. No changes needed here.

internal/aws_utils/aws_utils.go (1)

94-119: AWS config and caller-identity helper are structured well and respect error/lint rules.

Switching LoadAWSConfigWithAuth to wrap with %w fixes unwrapping while still using the ErrLoadAwsConfig sentinel, and the new GetAWSCallerIdentity cleanly encapsulates STS usage, returning an AWSCallerIdentityResult with account, ARN, user ID, and region while wrapping failures with ErrAwsGetCallerIdentity. Keeping this logic in aws_utils (with the depguard exclusion you added) is a good separation of concerns from the provider-agnostic auth code.

Also applies to: 130-179

website/docs/functions/yaml/aws.account-id.mdx (1)

1-166: Excellent documentation for the new AWS YAML function!

This documentation is comprehensive and well-structured. The examples are practical, error handling is clearly explained, and the caching behavior is well-documented. Good cross-references to related functions help users discover the full AWS function suite.

website/docs/functions/yaml/aws.caller-identity-user-id.mdx (1)

1-137: Strong documentation with helpful identity format details.

The user ID format table is particularly valuable for understanding what to expect from different identity types. The audit trail example demonstrates a practical use case, and the combined usage example nicely illustrates the shared caching benefit.

website/docs/functions/yaml/aws.region.mdx (1)

1-176: Thorough documentation with excellent region resolution details.

The region resolution order section provides valuable clarity on how the region is determined. The diverse examples (provider config, resource naming, cross-region) cover a good range of real-world use cases.

internal/exec/aws_getter.go (6)

14-34: Clean interface design that enables testability.

The AWSGetter interface with the go:generate directive follows best practices for dependency injection and mock generation. The AWSCallerIdentity struct is straightforward and includes all necessary fields.


36-70: Solid implementation with proper observability.

The defaultAWSGetter delegates to aws_utils correctly and includes appropriate performance tracking and debug logging. Error handling relies on wrapping at the aws_utils layer, which keeps the error handling centralized.


72-86: Well-implemented dependency injection pattern.

The SetAWSGetter function with restore capability makes testing straightforward. This pattern enables test code to inject mocks while ensuring the original getter is properly restored.


104-112: Cache key implementation is appropriate for typical usage.

The cache key uses Profile and CredentialsFile, which works well for standard scenarios where region comes from profile configuration. One edge case: if the same profile is used with different AWS_REGION environment variables during a single CLI invocation, the cached region could be stale. However, this is unlikely given that (1) the cache is per-CLI invocation, (2) changing AWS_REGION mid-invocation is unusual, and (3) region typically comes from profile config rather than separate env vars.


113-153: Excellent caching implementation with proper concurrency handling.

The double-checked locking pattern with RWMutex is implemented correctly and prevents multiple goroutines from making redundant AWS API calls. Caching errors is a smart optimization that prevents repeated failures from hammering the AWS API.


155-163: Clear and straightforward cache clearing function.

The ClearAWSIdentityCache function provides a clean way for tests and edge cases to invalidate the cache. Proper locking ensures thread safety.

pkg/utils/yaml_utils.go (1)

32-35: New AWS function constants follow established patterns.

The four new AWS function constants are properly added to both the AtmosYamlTags slice and the atmosYamlTagsMap. The naming and structure are consistent with existing YAML function definitions.

Also applies to: 53-56, 70-73

internal/exec/yaml_func_aws_test.go (4)

16-51: Well-designed test infrastructure reduces duplication.

The mockAWSGetter and runAWSYamlFuncTest helper eliminate test boilerplate effectively. The countingAWSGetter wrapper is a clever approach for verifying caching behavior without intrusive instrumentation.

Also applies to: 289-302


53-231: Comprehensive table-driven tests for AWS functions.

The tests cover different identity types, ARN formats, user ID patterns, and regions. The table-driven approach makes it easy to add new test cases. Good use of the test helper to eliminate duplication.


233-372: Excellent caching tests verify behavior thoroughly.

The caching tests confirm that cache hits work correctly, different auth contexts get separate entries, cache clearing works, and errors are cached. The countingGetter approach elegantly verifies that AWS API calls are minimized.


374-558: Comprehensive test coverage of integration points and edge cases.

The tests verify interface compliance, auth context handling, integration with processSimpleTags, skip functionality, constant values, error propagation, and dependency injection. This thorough coverage should catch regressions and ensures the AWS functions integrate correctly with the broader YAML processing pipeline.

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 5, 2025
@github-actions
Copy link

github-actions bot commented Dec 6, 2025

Warning

Changelog Entry Required

This PR is labeled minor or major but doesn't include a changelog entry.

Action needed: Add a new blog post in website/blog/ to announce this change.

Example filename: website/blog/2025-12-06-feature-name.mdx

Alternatively: If this change doesn't require a changelog entry, remove the minor or major label.

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 6, 2025
@mergify
Copy link

mergify bot commented Dec 6, 2025

💥 This pull request now has conflicts. Could you fix it @osterman? 🙏

@mergify mergify bot added the conflict This PR has conflicts label Dec 6, 2025
…ws.caller_identity_user_id, and !aws.region

Implement four new AWS YAML functions that retrieve AWS identity and configuration information using the STS GetCallerIdentity API. These functions are equivalent to Terragrunt's corresponding helper functions and provide seamless integration with Atmos authentication contexts. All functions share a unified caching mechanism to minimize API calls.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
internal/exec/aws_getter.go (1)

14-163: AWS identity getter and cache look solid; consider strengthening the cache key.

The AWSGetter abstraction, default implementation, and per-invocation caching are well structured and fit the YAML function use case. One thing to watch: getCacheKey currently keys on authContext.Profile and authContext.CredentialsFile only, but AWSCallerIdentity.Region (and potentially the underlying principal) can vary with other auth-context attributes (e.g., region, role, or account details in schema.AWSAuthContext). If, in the future, multiple distinct auth contexts share the same profile/credentials file but differ in those other fields, they would incorrectly share a cached identity+region. It might be safer long term to derive the key from a more complete, dedicated identifier on AWSAuthContext (or include additional discriminators such as region/role) so each logical identity/region combination gets its own cache entry.

internal/exec/yaml_func_aws_test.go (3)

16-51: Manual test doubles conflict with mockgen guideline (optional to fix now).

mockAWSGetter and countingAWSGetter are straightforward and readable, but they do violate the repo guideline that mocks should be generated via go.uber.org/mock/mockgen rather than hand-written structs.

Given these are simple and local to this file, I’d treat this as non-blocking, but for consistency you may want to:

  • Add a //go:generate for AWSGetter and use the generated mock in these tests, or
  • At least leave a TODO noting an eventual migration to mockgen.

Also applies to: 289-303


53-97: Tidy up unused table fields or add error-path coverage.

In TestProcessTagAwsAccountID, the table struct includes mockErr and shouldReturnNil, but all cases set mockErr to nil and never set shouldReturnNil to true, so that branch is effectively dead.

Either:

  • Remove mockErr and shouldReturnNil from this table (and the conditional on shouldReturnNil), or
  • Add at least one case with a non-nil mockErr and shouldReturnNil = true to exercise the error path and make the fields meaningful.

524-532: Default getter existence/type check is useful but implementation-focused.

TestDefaultAWSGetterExists pins that awsGetter is initialized and of type *defaultAWSGetter. That’s helpful to catch accidental changes to the default wiring, but it does couple the test to the concrete type. If you later want to swap the implementation behind the same interface without breaking tests, you may need to relax this assertion.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0384e20 and cb3bacc.

📒 Files selected for processing (15)
  • .golangci.yml (1 hunks)
  • errors/errors.go (1 hunks)
  • internal/aws_utils/aws_utils.go (2 hunks)
  • internal/exec/aws_getter.go (1 hunks)
  • internal/exec/yaml_func_aws.go (1 hunks)
  • internal/exec/yaml_func_aws_test.go (1 hunks)
  • internal/exec/yaml_func_utils.go (1 hunks)
  • pkg/utils/yaml_utils.go (2 hunks)
  • pkg/utils/yaml_utils_test.go (1 hunks)
  • website/blog/2025-12-05-aws-yaml-functions.mdx (1 hunks)
  • website/docs/functions/yaml/aws.account-id.mdx (1 hunks)
  • website/docs/functions/yaml/aws.caller-identity-arn.mdx (1 hunks)
  • website/docs/functions/yaml/aws.caller-identity-user-id.mdx (1 hunks)
  • website/docs/functions/yaml/aws.region.mdx (1 hunks)
  • website/docs/functions/yaml/index.mdx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • internal/exec/yaml_func_aws.go
  • pkg/utils/yaml_utils_test.go
  • errors/errors.go
  • .golangci.yml
  • pkg/utils/yaml_utils.go
  • internal/aws_utils/aws_utils.go
🧰 Additional context used
📓 Path-based instructions (4)
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: All comments must end with periods (enforced by godot linter)
Import organization: three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages. Maintain aliases: cfg, log, u, errUtils
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig param
Keep files small and focused (<600 lines). One cmd/impl per file. Co-locate tests. Never use //revive:disable:file-length-limit
Use sentinel errors from errors/errors.go with ErrorBuilder for all user-facing errors. Use errors.Is() for checking errors, never string comparison. WithCause() preserves underlying error messages, WithExplanation() adds context, WithHint() provides guidance, WithContext() adds key-value pairs
Use context.Context as first parameter for: cancellation signals (prop...

Files:

  • internal/exec/aws_getter.go
  • internal/exec/yaml_func_utils.go
  • internal/exec/yaml_func_aws_test.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Use assert.ErrorIs(t, err, ErrSentinel) for checking our own errors and stdlib errors. Only use string matching for third-party errors
NEVER use assert.Contains(err.Error(), ...) for error checking. ALWAYS use assert.ErrorIs() instead. NEVER use string comparison: err.Error() == "..." or strings.Contains(err.Error(), ...)
Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoid os.Exit, CheckErrorPrintAndExit, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation. Never create manual mocks. Pattern: //go:generate go run go.uber.org/mock/mockgen@latest -source=filename.go -destination=mock_filename_test.go
Use table-driven tests for comprehensive coverage. Tests must call actual production code, never duplicate logic. Target >80% test coverage (enforced by CodeCov)

Files:

  • internal/exec/yaml_func_aws_test.go
website/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

website/**: Update website documentation in the website/ directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in the website/ directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases

Files:

  • website/blog/2025-12-05-aws-yaml-functions.mdx
  • website/docs/functions/yaml/aws.account-id.mdx
  • website/docs/functions/yaml/aws.caller-identity-arn.mdx
  • website/docs/functions/yaml/aws.caller-identity-user-id.mdx
  • website/docs/functions/yaml/aws.region.mdx
  • website/docs/functions/yaml/index.mdx
website/blog/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

Blog posts require YAML front matter with slug, title, authors, and tags. Use <!--truncate--> after intro. ONLY use existing tags from website/blog/*.mdx - check before writing. Author field must be GitHub username, added to website/blog/authors.yml. Filename format: YYYY-MM-DD-feature-name.mdx. PRs labeled minor/major MUST include blog post

Files:

  • website/blog/2025-12-05-aws-yaml-functions.mdx
🧠 Learnings (24)
📓 Common learnings
Learnt from: mcalhoun
Repo: cloudposse/atmos PR: 963
File: website/docs/core-concepts/projects/configuration/stores.mdx:286-286
Timestamp: 2025-04-25T20:54:19.701Z
Learning: For the AWS SSM Parameter Store implementation in Atmos, support for `read_role_arn` and `write_role_arn` options is essential to enable cross-account access, allowing users to run operations like `terraform plan` in multiple accounts while accessing values across keystores. Azure Key Vault would need similar capabilities for cross-tenant/subscription authentication.
📚 Learning: 2025-09-25T01:02:48.697Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/manager.go:304-312
Timestamp: 2025-09-25T01:02:48.697Z
Learning: The auth manager in pkg/auth/manager.go should remain cloud-agnostic and not contain AWS-specific logic or references to specific cloud providers. Keep the manager generic and extensible.

Applied to files:

  • internal/exec/aws_getter.go
📚 Learning: 2025-11-10T20:03:56.875Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1775
File: pkg/auth/providers/aws/sso_provisioning.go:40-79
Timestamp: 2025-11-10T20:03:56.875Z
Learning: In the Atmos AWS SSO provider (pkg/auth/providers/aws/sso_provisioning.go), the OAuth access token from the AWS SSO device flow is intentionally stored in the `AccessKeyID` field of `AWSCredentials` during authentication. This token is then extracted and used for ListAccounts and ListAccountRoles API calls during identity provisioning. This design reuses the existing `AWSCredentials` type for token transport rather than creating a separate credential type.

Applied to files:

  • internal/exec/aws_getter.go
📚 Learning: 2025-09-30T19:03:50.738Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 1560
File: pkg/utils/string_utils.go:43-64
Timestamp: 2025-09-30T19:03:50.738Z
Learning: In the Atmos codebase, YAML tags like !terraform.output rely on positional arguments, so the SplitStringByDelimiter function in pkg/utils/string_utils.go must preserve empty strings (even after trimming quotes) to maintain the correct number of positional arguments. Filtering out empty values after trimming would collapse the array and break these function calls.

Applied to files:

  • internal/exec/yaml_func_utils.go
📚 Learning: 2024-12-17T07:08:41.288Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 863
File: internal/exec/yaml_func_terraform_output.go:34-38
Timestamp: 2024-12-17T07:08:41.288Z
Learning: In the `processTagTerraformOutput` function within `internal/exec/yaml_func_terraform_output.go`, parameters are separated by spaces and do not contain spaces. Therefore, using `strings.Fields()` for parsing is acceptable, and there's no need to handle parameters with spaces.

Applied to files:

  • internal/exec/yaml_func_utils.go
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • internal/exec/yaml_func_utils.go
📚 Learning: 2025-12-06T19:24:49.329Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.329Z
Learning: Applies to **/*.go : New configs support Go templating with `FuncMap()` from `internal/exec/template_funcs.go`. Implement template functions in `internal/exec/template_funcs.go`, register them, add tests, and update documentation

Applied to files:

  • internal/exec/yaml_func_utils.go
  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-12-06T19:24:49.329Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.329Z
Learning: Applies to **/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` + blank line to all public functions. Use `nil` if no atmosConfig param

Applied to files:

  • internal/exec/yaml_func_utils.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.

Applied to files:

  • internal/exec/yaml_func_utils.go
📚 Learning: 2025-04-11T22:06:46.999Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1147
File: internal/exec/validate_schema.go:42-57
Timestamp: 2025-04-11T22:06:46.999Z
Learning: The "ExecuteAtmosValidateSchemaCmd" function in internal/exec/validate_schema.go has been reviewed and confirmed to have acceptable cognitive complexity despite static analysis warnings. The function uses a clean structure with only three if statements for error handling and delegates complex operations to helper methods.

Applied to files:

  • internal/exec/yaml_func_utils.go
📚 Learning: 2024-11-30T22:07:08.610Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: internal/exec/yaml_func_terraform_output.go:35-40
Timestamp: 2024-11-30T22:07:08.610Z
Learning: In the Go function `processTagTerraformOutput` in `internal/exec/yaml_func_terraform_output.go`, parameters cannot contain spaces. The code splits the input by spaces, and if the parameters contain spaces, `len(parts) != 3` will fail and show an error to the user.

Applied to files:

  • internal/exec/yaml_func_utils.go
📚 Learning: 2025-10-13T18:13:54.020Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1622
File: pkg/perf/perf.go:140-184
Timestamp: 2025-10-13T18:13:54.020Z
Learning: In pkg/perf/perf.go, the `trackWithSimpleStack` function intentionally skips ownership checks at call stack depth > 1 to avoid expensive `getGoroutineID()` calls on every nested function. This is a performance optimization for the common single-goroutine execution case (most Atmos commands), accepting the rare edge case of potential metric corruption if multi-goroutine execution occurs at depth > 1. The ~19× performance improvement justifies this trade-off.

Applied to files:

  • internal/exec/yaml_func_utils.go
📚 Learning: 2025-06-23T02:14:30.937Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1327
File: cmd/terraform.go:111-117
Timestamp: 2025-06-23T02:14:30.937Z
Learning: In cmd/terraform.go, flags for the DescribeAffected function are added dynamically at runtime when info.Affected is true. This is intentional to avoid exposing internal flags like "file", "format", "verbose", "include-spacelift-admin-stacks", "include-settings", and "upload" in the terraform command interface, while still providing them for the shared DescribeAffected function used by both `atmos describe affected` and `atmos terraform apply --affected`.

Applied to files:

  • internal/exec/yaml_func_utils.go
📚 Learning: 2025-12-06T19:24:49.329Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.329Z
Learning: Applies to **/*_test.go : Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoid `os.Exit`, `CheckErrorPrintAndExit`, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-12-06T19:24:49.329Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.329Z
Learning: Applies to **/*_test.go : Use table-driven tests for comprehensive coverage. Tests must call actual production code, never duplicate logic. Target >80% test coverage (enforced by CodeCov)

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-12-06T19:24:49.329Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.329Z
Learning: Applies to pkg/**/*.go : Create focused purpose-built packages in `pkg/` for new functionality, each with clear responsibility. DO NOT add new functions to `pkg/utils/` or `internal/exec/`. Each package should have focused business logic with tests

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-12-06T19:24:49.329Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.329Z
Learning: Applies to tests/**/*.yaml : NEVER modify `tests/test-cases/` or `tests/testdata/` unless explicitly instructed. Golden snapshots are sensitive to minor changes. Use fixtures in `tests/test-cases/`: `atmos.yaml`, `stacks/`, `components/`

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2024-12-03T04:01:16.446Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:0-0
Timestamp: 2024-12-03T04:01:16.446Z
Learning: In the `terraform.output.mdx` documentation file (`website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx`), the cache invalidation and cache scope behavior for the `!terraform.output` function are already described.

Applied to files:

  • website/blog/2025-12-05-aws-yaml-functions.mdx
  • website/docs/functions/yaml/aws.account-id.mdx
  • website/docs/functions/yaml/aws.caller-identity-arn.mdx
  • website/docs/functions/yaml/aws.caller-identity-user-id.mdx
  • website/docs/functions/yaml/aws.region.mdx
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).

Applied to files:

  • website/blog/2025-12-05-aws-yaml-functions.mdx
  • website/docs/functions/yaml/aws.account-id.mdx
  • website/docs/functions/yaml/aws.region.mdx
  • website/docs/functions/yaml/index.mdx
📚 Learning: 2024-12-01T00:33:20.298Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.

Applied to files:

  • website/blog/2025-12-05-aws-yaml-functions.mdx
  • website/docs/functions/yaml/aws.region.mdx
  • website/docs/functions/yaml/index.mdx
📚 Learning: 2025-04-25T20:54:19.701Z
Learnt from: mcalhoun
Repo: cloudposse/atmos PR: 963
File: website/docs/core-concepts/projects/configuration/stores.mdx:286-286
Timestamp: 2025-04-25T20:54:19.701Z
Learning: For the AWS SSM Parameter Store implementation in Atmos, support for `read_role_arn` and `write_role_arn` options is essential to enable cross-account access, allowing users to run operations like `terraform plan` in multiple accounts while accessing values across keystores. Azure Key Vault would need similar capabilities for cross-tenant/subscription authentication.

Applied to files:

  • website/blog/2025-12-05-aws-yaml-functions.mdx
  • website/docs/functions/yaml/index.mdx
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!include` allows downloading local or remote files from different sources and assigning their contents to sections in stack manifests. It supports various protocols (file, http, git, s3, etc.) and can filter content using YQ expressions.

Applied to files:

  • website/blog/2025-12-05-aws-yaml-functions.mdx
  • website/docs/functions/yaml/index.mdx
🧬 Code graph analysis (2)
internal/exec/yaml_func_utils.go (1)
pkg/utils/yaml_utils.go (4)
  • AtmosYamlFuncAwsAccountID (33-33)
  • AtmosYamlFuncAwsCallerIdentityArn (34-34)
  • AtmosYamlFuncAwsCallerIdentityUserID (35-35)
  • AtmosYamlFuncAwsRegion (36-36)
internal/exec/yaml_func_aws_test.go (3)
internal/exec/aws_getter.go (4)
  • AWSCallerIdentity (15-20)
  • ClearAWSIdentityCache (157-163)
  • SetAWSGetter (78-86)
  • AWSGetter (26-34)
pkg/utils/yaml_utils.go (4)
  • AtmosYamlFuncAwsAccountID (33-33)
  • AtmosYamlFuncAwsCallerIdentityArn (34-34)
  • AtmosYamlFuncAwsCallerIdentityUserID (35-35)
  • AtmosYamlFuncAwsRegion (36-36)
errors/errors.go (1)
  • ErrAwsGetCallerIdentity (90-90)
🪛 LanguageTool
website/blog/2025-12-05-aws-yaml-functions.mdx

[typographical] ~74-~74: To join two clauses or introduce examples, consider using an em dash.
Context: ...unt_id](/functions/yaml/aws.account-id) - Full documentation - [!aws.caller_ident...

(DASH_RULE)


[typographical] ~78-~78: To join two clauses or introduce examples, consider using an em dash.
Context: ...ML Functions Overview](/functions/yaml/) - All available YAML functions

(DASH_RULE)

website/docs/functions/yaml/aws.account-id.mdx

[typographical] ~35-~35: To join two clauses or introduce examples, consider using an em dash.
Context: ..., Atmos: 1. Loads AWS Configuration - Uses the standard AWS SDK credential res...

(DASH_RULE)


[typographical] ~165-~165: To join two clauses or introduce examples, consider using an em dash.
Context: ...ctions/yaml/aws.caller-identity-user-id) - Get the unique user ID - [!aws.region](/...

(DASH_RULE)


[typographical] ~166-~166: To join two clauses or introduce examples, consider using an em dash.
Context: ...!aws.region](/functions/yaml/aws.region) - Get the AWS region

(DASH_RULE)

website/docs/functions/yaml/aws.caller-identity-arn.mdx

[typographical] ~35-~35: To join two clauses or introduce examples, consider using an em dash.
Context: ..., Atmos: 1. Loads AWS Configuration - Uses the standard AWS SDK credential res...

(DASH_RULE)


[style] ~185-~185: Using many exclamation marks might seem excessive (in this case: 9 exclamation marks for a text that’s 3773 characters long)
Context: ...d role, etc.) ## Related Functions - !aws.account_id - Get the AWS account ID - !aws.caller_identity_user_id - Get the unique user ID - !aws.region ...

(EN_EXCESSIVE_EXCLAMATION)


[typographical] ~187-~187: To join two clauses or introduce examples, consider using an em dash.
Context: ...!aws.region](/functions/yaml/aws.region) - Get the AWS region

(DASH_RULE)

website/docs/functions/yaml/aws.caller-identity-user-id.mdx

[typographical] ~35-~35: To join two clauses or introduce examples, consider using an em dash.
Context: ..., Atmos: 1. Loads AWS Configuration - Uses the standard AWS SDK credential res...

(DASH_RULE)


[typographical] ~36-~36: To join two clauses or introduce examples, consider using an em dash.
Context: ...chain 2. Calls STS GetCallerIdentity - Makes an API call to retrieve the caller...

(DASH_RULE)


[typographical] ~37-~37: To join two clauses or introduce examples, consider using an em dash.
Context: ...e caller identity 3. Returns User ID - Extracts and returns the unique user ID ...

(DASH_RULE)


[style] ~135-~135: Using many exclamation marks might seem excessive (in this case: 10 exclamation marks for a text that’s 2879 characters long)
Context: ...y` permission ## Related Functions - !aws.account_id - Get the AWS account ID - !aws.caller_identity_arn - Get the full ARN - !aws.region ...

(EN_EXCESSIVE_EXCLAMATION)


[typographical] ~137-~137: To join two clauses or introduce examples, consider using an em dash.
Context: ...!aws.region](/functions/yaml/aws.region) - Get the AWS region

(DASH_RULE)

website/docs/functions/yaml/aws.region.mdx

[typographical] ~35-~35: To join two clauses or introduce examples, consider using an em dash.
Context: ..., Atmos: 1. Loads AWS Configuration - Uses the standard AWS SDK configuration ...

(DASH_RULE)


[style] ~174-~174: Using many exclamation marks might seem excessive (in this case: 9 exclamation marks for a text that’s 2977 characters long)
Context: ...y` permission ## Related Functions - !aws.account_id - Get the AWS account ID - !aws.caller_identity_arn - Get the full ARN - [!aws.caller_identity_user_id](/functions/...

(EN_EXCESSIVE_EXCLAMATION)


[typographical] ~176-~176: To join two clauses or introduce examples, consider using an em dash.
Context: ...ctions/yaml/aws.caller-identity-user-id) - Get the user ID

(DASH_RULE)

website/docs/functions/yaml/index.mdx

[style] ~90-~90: Using many exclamation marks might seem excessive (in this case: 17 exclamation marks for a text that’s 5280 characters long)
Context: ...ity using STS GetCallerIdentity - The [!aws.region](/functions/yaml/aws.regio...

(EN_EXCESSIVE_EXCLAMATION)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Summary
🔇 Additional comments (17)
website/docs/functions/yaml/aws.caller-identity-arn.mdx (1)

12-181: Docs match implementation and are clear.

Flow, caching behavior, and Atmos Auth integration all read consistent with the new AWS getter/caching design; examples and Terragrunt comparison look solid.

internal/exec/yaml_func_utils.go (1)

157-169: AWS tag dispatch looks correct and consistent.

Exact-match checks for the !aws.* tags paired with skipFunc fit the “no-args” contract and align with how other YAML tags are handled; wiring into processSimpleTags is straightforward and maintainable.

website/docs/functions/yaml/index.mdx (1)

81-92: YAML functions index stays in sync with new AWS helpers.

The new bullets and example vars cleanly introduce the !aws.* functions and match their dedicated docs, keeping the overview page coherent.

Also applies to: 169-180

website/docs/functions/yaml/aws.account-id.mdx (1)

12-166: Account ID documentation aligns with behavior and use cases.

Flow, caching semantics, and error handling are accurately described, and the examples give practical patterns for backend naming and shared vars.

website/blog/2025-12-05-aws-yaml-functions.mdx (1)

1-78: Blog post cleanly explains the feature set.

Front matter looks correct, and the narrative, examples, and Terragrunt comparison line up with the new YAML functions and caching behavior.

website/docs/functions/yaml/aws.region.mdx (1)

12-176: Region docs accurately capture resolution and caching behavior.

The resolution order, shared-cache description, and examples reflect how the region is derived and reused alongside the other AWS identity functions.

website/docs/functions/yaml/aws.caller-identity-user-id.mdx (1)

12-137: User ID function documentation is consistent and practical.

Flow, ID formats, caching notes, and audit-focused examples all match the intended behavior and mirror the style of the other AWS YAML function docs.

internal/exec/yaml_func_aws_test.go (10)

99-231: Good table-driven coverage of the basic AWS YAML functions.

The ARN, user ID, and region tests nicely cover both IAM user and assumed-role identities, plus multiple regions. The use of runAWSYamlFuncTest keeps things DRY and focused on behavior.


233-287: Caching behavior tests look solid.

TestAWSIdentityCache exercises first-hit, cache hit, different-auth-context, and post-clear scenarios against the same AWSCallerIdentity, and the countingAWSGetter pattern keeps the assertions precise on call counts. This gives good confidence in the per-auth-context cache semantics.


304-335: Error caching behavior is well covered.

TestAWSCacheWithErrors correctly asserts that an error from the getter is cached and not re-fetched on subsequent calls, including verifying the call count. This is a good complement to the happy-path cache test.


337-372: Cache key generation cases are clear and comprehensive.

TestGetCacheKey covers nil auth context, populated profile+credentials, and empty-profile variants. That should catch most regressions in how cache keys are built.


374-377: Interface conformance check is fine but purely structural.

TestAWSGetterInterface is essentially a compile-time conformance check. It’s harmless and documents the intent, but note that it doesn’t exercise any runtime behavior. I’d keep it as-is, just be aware this is more about guarding refactors than verifying features.


379-414: Nice coverage for AuthContext-driven identity resolution.

TestProcessTagAwsWithAuthContext cleanly verifies that processTagAws* uses the AuthContext from ConfigAndStacksInfo, which is important for multi-account setups. Clearing the cache between the two assertions keeps the test deterministic.


416-463: End-to-end coverage via processSimpleTags looks good.

TestProcessSimpleTagsWithAWSFunctions runs each of the four AWS functions through processSimpleTags, checks handled, and validates the returned values. This is a nice higher-level check on top of the lower-level processTagAws* tests.


465-492: Skip list behavior is clearly exercised.

TestProcessSimpleTagsSkipsAWSFunctions ensures that each AWS YAML function is correctly excluded when present in the skip slice and that handled is false with a nil result. This is valuable to guarantee that “skip” truly short-circuits evaluation (and avoids AWS calls).


494-500: Constant verification test is appropriate.

TestAWSYamlFunctionConstants directly pins the string values of the public YAML function tags, which are part of the external contract. This is a good safeguard against accidental renames that would break user configs.


535-552: Restore behavior for SetAWSGetter is well tested.

TestSetAWSGetterRestore nicely verifies both that awsGetter is swapped to the mock and that the restore func puts the original back. This is important given the global state and cross-test interference risk.

Comment on lines 502 to 523
// TestErrorWrapping verifies that AWS errors are properly wrapped.
func TestErrorWrapping(t *testing.T) {
// Clear cache before test.
ClearAWSIdentityCache()

underlyingErr := errors.New("network timeout")
restore := SetAWSGetter(&mockAWSGetter{
identity: nil,
err: underlyingErr,
})
defer restore()

atmosConfig := &schema.AtmosConfiguration{}
ctx := context.Background()

_, err := getAWSCallerIdentityCached(ctx, atmosConfig, nil)
require.Error(t, err)

// The error should be wrapped with the underlying error accessible.
assert.Contains(t, err.Error(), "network timeout")
}

Copy link
Contributor

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:

rg -A 20 "func getAWSCallerIdentityCached" --type go

Repository: cloudposse/atmos

Length of output: 1316


🏁 Script executed:

fd -e go -x rg -l "getAWSCallerIdentityCached"

Repository: cloudposse/atmos

Length of output: 160


🏁 Script executed:

cat -n internal/exec/yaml_func_aws_test.go | sed -n '480,550p'

Repository: cloudposse/atmos

Length of output: 2834


🏁 Script executed:

ls -la internal/exec/yaml_func_aws_test.go 2>&1 && wc -l internal/exec/yaml_func_aws_test.go

Repository: cloudposse/atmos

Length of output: 185


🏁 Script executed:

find . -name "*aws*test.go" -type f 2>/dev/null

Repository: cloudposse/atmos

Length of output: 301


🏁 Script executed:

rg "TestErrorWrapping" --type go -A 20

Repository: cloudposse/atmos

Length of output: 1453


🏁 Script executed:

ls internal/exec/ | head -20

Repository: cloudposse/atmos

Length of output: 504


🏁 Script executed:

rg "getAWSCallerIdentityCached" --type go

Repository: cloudposse/atmos

Length of output: 1149


🏁 Script executed:

rg "ErrAwsGetCallerIdentity" --type go

Repository: cloudposse/atmos

Length of output: 677


🏁 Script executed:

find . -path "*/errors/errors.go" -o -path "*/error*" -type f | grep -E "(errors\.go|error\.go)" | head -10

Repository: cloudposse/atmos

Length of output: 150


🏁 Script executed:

rg "ErrAws" --type go -B 2 -A 2 | head -50

Repository: cloudposse/atmos

Length of output: 3563


🏁 Script executed:

git status 2>&1 | head -20

Repository: cloudposse/atmos

Length of output: 125


🏁 Script executed:

fd "yaml.*aws" -e go

Repository: cloudposse/atmos

Length of output: 126


🏁 Script executed:

git ls-files internal/exec/ | grep -E "(yaml|aws)" | head -20

Repository: cloudposse/atmos

Length of output: 900


🏁 Script executed:

rg "mockAWSGetter" --type go -B 5 -A 15

Repository: cloudposse/atmos

Length of output: 10573


🏁 Script executed:

rg "SetAWSGetter\|ClearAWSIdentityCache" --type go

Repository: cloudposse/atmos

Length of output: 42


🏁 Script executed:

ls -la internal/exec/*.go | grep -v vendor

Repository: cloudposse/atmos

Length of output: 20710


🏁 Script executed:

find . -type f -name "*test.go" | xargs grep -l "TestErrorWrapping" 2>/dev/null

Repository: cloudposse/atmos

Length of output: 97


🏁 Script executed:

git ls-files | grep -E "test\.go$" | head -20

Repository: cloudposse/atmos

Length of output: 573


🏁 Script executed:

git log --oneline -n 20 2>&1

Repository: cloudposse/atmos

Length of output: 102


🏁 Script executed:

git diff --name-only --cached 2>&1

Repository: cloudposse/atmos

Length of output: 42


🏁 Script executed:

rg "identity|Identity" internal/exec/ --type go -l | head -10

Repository: cloudposse/atmos

Length of output: 396


🏁 Script executed:

rg "network timeout" --type go

Repository: cloudposse/atmos

Length of output: 602


🏁 Script executed:

ls -la

Repository: cloudposse/atmos

Length of output: 3252


🏁 Script executed:

rg "assert.Contains.*err.Error" --type go | head -10

Repository: cloudposse/atmos

Length of output: 1133


🏁 Script executed:

assert.ErrorIs" --type go -B 2 -A 2 | head -40

Repository: cloudposse/atmos

Length of output: 128


🏁 Script executed:

fmt.Errorf.*%w.*%w" --type go | head -10

Repository: cloudposse/atmos

Length of output: 128


🏁 Script executed:

find . -type f -name "*.go" -path "*/errors/*" | head -10

Repository: cloudposse/atmos

Length of output: 305


🏁 Script executed:

find . -type d -name "errors" 2>/dev/null

Repository: cloudposse/atmos

Length of output: 86


🏁 Script executed:

rg "errUtils|errors" --type go | grep "import" | head -10

Repository: cloudposse/atmos

Length of output: 743


🏁 Script executed:

ls -la pkg/ 2>&1 | head -30

Repository: cloudposse/atmos

Length of output: 1724


🏁 Script executed:

cat -n internal/exec/aws_getter.go | head -80

Repository: cloudposse/atmos

Length of output: 3119


🏁 Script executed:

rg -A 30 "func getAWSCallerIdentityCached" internal/exec/aws_getter.go

Repository: cloudposse/atmos

Length of output: 1050


🏁 Script executed:

cat internal/exec/aws_getter.go

Repository: cloudposse/atmos

Length of output: 5063


🏁 Script executed:

rg -B 5 -A 20 "ErrAwsGetCallerIdentity" internal/

Repository: cloudposse/atmos

Length of output: 2133


🏁 Script executed:

cat -n internal/aws_utils/aws_utils.go | grep -A 3 "ErrAwsGetCallerIdentity"

Repository: cloudposse/atmos

Length of output: 202


Use assert.ErrorIs() for sentinel error assertions instead of string matching.

The test is using assert.Contains(t, err.Error(), "network timeout") to verify error wrapping, which violates the guideline against string-based error checking. The codebase requires using assert.ErrorIs() to verify error types while preserving the ability to check underlying causes.

Replace the string assertion with sentinel error checks that verify both the wrapping error and the underlying error is preserved:

assert.ErrorIs(t, err, errUtils.ErrAwsGetCallerIdentity)  // Check sentinel
assert.ErrorIs(t, err, underlyingErr)                      // Check underlying error preserved

This pattern documents the intended error wrapping behavior and follows Go's error handling best practices.

🤖 Prompt for AI Agents
In internal/exec/yaml_func_aws_test.go around lines 502 to 523, the test uses
string matching to check the wrapped error ("network timeout"); replace that
with sentinel-based assertions: assert that the returned error is the expected
sentinel (errUtils.ErrAwsGetCallerIdentity) and that the underlying error is
preserved by using assert.ErrorIs(t, err, errUtils.ErrAwsGetCallerIdentity) and
assert.ErrorIs(t, err, underlyingErr). Ensure both assertions replace the
current assert.Contains line so the test verifies wrapping using ErrorIs rather
than string matching.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
website/blog/2025-12-05-aws-yaml-functions.mdx (1)

26-41: Clarify the bucket_name example.

Line 32 shows a complex pattern using !template with exec "atmos" (list "yaml" "eval" "!aws.account_id"). This seems unnecessarily convoluted when demonstrating the new function. A simpler approach would better illustrate the feature's value.

Consider using a more straightforward example:

        # Name bucket with account ID for uniqueness
-        bucket_name: !template 'app-data-{{ exec "atmos" (list "yaml" "eval" "!aws.account_id") }}'
+        bucket_name_suffix: !aws.account_id

Or if string interpolation is truly needed, show that separately with a note explaining why.

internal/exec/yaml_func_aws_test.go (1)

16-28: Manual mock alongside mockgen directive.

A mockgen directive exists in aws_getter.go. Consider using the generated mock for consistency, though this simple manual mock works fine for these focused tests.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0384e20 and cb3bacc.

📒 Files selected for processing (15)
  • .golangci.yml (1 hunks)
  • errors/errors.go (1 hunks)
  • internal/aws_utils/aws_utils.go (2 hunks)
  • internal/exec/aws_getter.go (1 hunks)
  • internal/exec/yaml_func_aws.go (1 hunks)
  • internal/exec/yaml_func_aws_test.go (1 hunks)
  • internal/exec/yaml_func_utils.go (1 hunks)
  • pkg/utils/yaml_utils.go (2 hunks)
  • pkg/utils/yaml_utils_test.go (1 hunks)
  • website/blog/2025-12-05-aws-yaml-functions.mdx (1 hunks)
  • website/docs/functions/yaml/aws.account-id.mdx (1 hunks)
  • website/docs/functions/yaml/aws.caller-identity-arn.mdx (1 hunks)
  • website/docs/functions/yaml/aws.caller-identity-user-id.mdx (1 hunks)
  • website/docs/functions/yaml/aws.region.mdx (1 hunks)
  • website/docs/functions/yaml/index.mdx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • internal/exec/yaml_func_utils.go
  • internal/exec/yaml_func_aws.go
  • .golangci.yml
  • pkg/utils/yaml_utils_test.go
  • errors/errors.go
🧰 Additional context used
📓 Path-based instructions (5)
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: All comments must end with periods (enforced by godot linter)
Import organization: three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages. Maintain aliases: cfg, log, u, errUtils
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig param
Keep files small and focused (<600 lines). One cmd/impl per file. Co-locate tests. Never use //revive:disable:file-length-limit
Use sentinel errors from errors/errors.go with ErrorBuilder for all user-facing errors. Use errors.Is() for checking errors, never string comparison. WithCause() preserves underlying error messages, WithExplanation() adds context, WithHint() provides guidance, WithContext() adds key-value pairs
Use context.Context as first parameter for: cancellation signals (prop...

Files:

  • internal/exec/aws_getter.go
  • internal/aws_utils/aws_utils.go
  • pkg/utils/yaml_utils.go
  • internal/exec/yaml_func_aws_test.go
website/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

website/**: Update website documentation in the website/ directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in the website/ directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases

Files:

  • website/docs/functions/yaml/aws.caller-identity-user-id.mdx
  • website/docs/functions/yaml/aws.caller-identity-arn.mdx
  • website/blog/2025-12-05-aws-yaml-functions.mdx
  • website/docs/functions/yaml/aws.account-id.mdx
  • website/docs/functions/yaml/aws.region.mdx
  • website/docs/functions/yaml/index.mdx
pkg/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

pkg/**/*.go: Business logic packages must follow the Service-Oriented Architecture pattern with: one Service struct per domain, Provider interfaces for classes of problems, default implementations, mock implementations, and dependency injection for testability
Use interface-driven design: define interfaces for all major functionality, use dependency injection for testability, generate mocks with go.uber.org/mock/mockgen with //go:generate directives, avoid integration tests by mocking external dependencies
Create focused purpose-built packages in pkg/ for new functionality, each with clear responsibility. DO NOT add new functions to pkg/utils/ or internal/exec/. Each package should have focused business logic with tests
Implement registry pattern for extensibility and plugin-like architecture. Define interfaces for provider implementations, register implementations in registry, generate mocks with mockgen. Examples: Command Registry in cmd/internal/registry.go, Store Registry in pkg/store/registry.go

Files:

  • pkg/utils/yaml_utils.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Use assert.ErrorIs(t, err, ErrSentinel) for checking our own errors and stdlib errors. Only use string matching for third-party errors
NEVER use assert.Contains(err.Error(), ...) for error checking. ALWAYS use assert.ErrorIs() instead. NEVER use string comparison: err.Error() == "..." or strings.Contains(err.Error(), ...)
Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoid os.Exit, CheckErrorPrintAndExit, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation. Never create manual mocks. Pattern: //go:generate go run go.uber.org/mock/mockgen@latest -source=filename.go -destination=mock_filename_test.go
Use table-driven tests for comprehensive coverage. Tests must call actual production code, never duplicate logic. Target >80% test coverage (enforced by CodeCov)

Files:

  • internal/exec/yaml_func_aws_test.go
website/blog/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

Blog posts require YAML front matter with slug, title, authors, and tags. Use <!--truncate--> after intro. ONLY use existing tags from website/blog/*.mdx - check before writing. Author field must be GitHub username, added to website/blog/authors.yml. Filename format: YYYY-MM-DD-feature-name.mdx. PRs labeled minor/major MUST include blog post

Files:

  • website/blog/2025-12-05-aws-yaml-functions.mdx
🧠 Learnings (20)
📓 Common learnings
Learnt from: mcalhoun
Repo: cloudposse/atmos PR: 963
File: website/docs/core-concepts/projects/configuration/stores.mdx:286-286
Timestamp: 2025-04-25T20:54:19.701Z
Learning: For the AWS SSM Parameter Store implementation in Atmos, support for `read_role_arn` and `write_role_arn` options is essential to enable cross-account access, allowing users to run operations like `terraform plan` in multiple accounts while accessing values across keystores. Azure Key Vault would need similar capabilities for cross-tenant/subscription authentication.
📚 Learning: 2025-11-10T20:03:56.875Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1775
File: pkg/auth/providers/aws/sso_provisioning.go:40-79
Timestamp: 2025-11-10T20:03:56.875Z
Learning: In the Atmos AWS SSO provider (pkg/auth/providers/aws/sso_provisioning.go), the OAuth access token from the AWS SSO device flow is intentionally stored in the `AccessKeyID` field of `AWSCredentials` during authentication. This token is then extracted and used for ListAccounts and ListAccountRoles API calls during identity provisioning. This design reuses the existing `AWSCredentials` type for token transport rather than creating a separate credential type.

Applied to files:

  • internal/exec/aws_getter.go
📚 Learning: 2025-09-25T01:02:48.697Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/manager.go:304-312
Timestamp: 2025-09-25T01:02:48.697Z
Learning: The auth manager in pkg/auth/manager.go should remain cloud-agnostic and not contain AWS-specific logic or references to specific cloud providers. Keep the manager generic and extensible.

Applied to files:

  • internal/exec/aws_getter.go
📚 Learning: 2024-12-03T04:01:16.446Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:0-0
Timestamp: 2024-12-03T04:01:16.446Z
Learning: In the `terraform.output.mdx` documentation file (`website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx`), the cache invalidation and cache scope behavior for the `!terraform.output` function are already described.

Applied to files:

  • website/docs/functions/yaml/aws.caller-identity-user-id.mdx
  • website/docs/functions/yaml/aws.caller-identity-arn.mdx
  • website/blog/2025-12-05-aws-yaml-functions.mdx
  • website/docs/functions/yaml/aws.account-id.mdx
  • website/docs/functions/yaml/aws.region.mdx
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-12-06T19:24:49.329Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.329Z
Learning: Applies to **/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` + blank line to all public functions. Use `nil` if no atmosConfig param

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-09-30T19:03:50.738Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 1560
File: pkg/utils/string_utils.go:43-64
Timestamp: 2025-09-30T19:03:50.738Z
Learning: In the Atmos codebase, YAML tags like !terraform.output rely on positional arguments, so the SplitStringByDelimiter function in pkg/utils/string_utils.go must preserve empty strings (even after trimming quotes) to maintain the correct number of positional arguments. Filtering out empty values after trimming would collapse the array and break these function calls.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables → Viper unmarshals into atmosConfig.Settings via mapstructure → business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2024-12-01T00:33:20.298Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.

Applied to files:

  • pkg/utils/yaml_utils.go
  • website/blog/2025-12-05-aws-yaml-functions.mdx
  • website/docs/functions/yaml/aws.region.mdx
  • website/docs/functions/yaml/index.mdx
📚 Learning: 2025-09-05T14:57:37.360Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 1448
File: cmd/ansible.go:26-28
Timestamp: 2025-09-05T14:57:37.360Z
Learning: The Atmos codebase uses a consistent pattern for commands that delegate to external tools: `PersistentFlags().Bool("", false, doubleDashHint)` where doubleDashHint provides help text about using double dashes to separate Atmos options from native command arguments. This pattern is used across terraform, packer, helmfile, atlantis, aws, and ansible commands.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2024-10-20T13:12:46.499Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 736
File: pkg/config/const.go:6-6
Timestamp: 2024-10-20T13:12:46.499Z
Learning: In `cmd/cmd_utils.go`, it's acceptable to have hardcoded references to `atmos.yaml` in logs, and it's not necessary to update them to use the `CliConfigFileName` constant.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).

Applied to files:

  • pkg/utils/yaml_utils.go
  • website/blog/2025-12-05-aws-yaml-functions.mdx
  • website/docs/functions/yaml/aws.account-id.mdx
  • website/docs/functions/yaml/aws.region.mdx
  • website/docs/functions/yaml/index.mdx
📚 Learning: 2024-12-17T07:08:41.288Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 863
File: internal/exec/yaml_func_terraform_output.go:34-38
Timestamp: 2024-12-17T07:08:41.288Z
Learning: In the `processTagTerraformOutput` function within `internal/exec/yaml_func_terraform_output.go`, parameters are separated by spaces and do not contain spaces. Therefore, using `strings.Fields()` for parsing is acceptable, and there's no need to handle parameters with spaces.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-12-06T19:24:49.329Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.329Z
Learning: Applies to **/*.go : New configs support Go templating with `FuncMap()` from `internal/exec/template_funcs.go`. Implement template functions in `internal/exec/template_funcs.go`, register them, add tests, and update documentation

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-12-06T19:24:49.329Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.329Z
Learning: Applies to **/*_test.go : Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoid `os.Exit`, `CheckErrorPrintAndExit`, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-04-25T20:54:19.701Z
Learnt from: mcalhoun
Repo: cloudposse/atmos PR: 963
File: website/docs/core-concepts/projects/configuration/stores.mdx:286-286
Timestamp: 2025-04-25T20:54:19.701Z
Learning: For the AWS SSM Parameter Store implementation in Atmos, support for `read_role_arn` and `write_role_arn` options is essential to enable cross-account access, allowing users to run operations like `terraform plan` in multiple accounts while accessing values across keystores. Azure Key Vault would need similar capabilities for cross-tenant/subscription authentication.

Applied to files:

  • website/blog/2025-12-05-aws-yaml-functions.mdx
  • website/docs/functions/yaml/index.mdx
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!include` allows downloading local or remote files from different sources and assigning their contents to sections in stack manifests. It supports various protocols (file, http, git, s3, etc.) and can filter content using YQ expressions.

Applied to files:

  • website/blog/2025-12-05-aws-yaml-functions.mdx
  • website/docs/functions/yaml/index.mdx
🧬 Code graph analysis (2)
internal/aws_utils/aws_utils.go (2)
errors/errors.go (2)
  • ErrLoadAwsConfig (96-96)
  • ErrAwsGetCallerIdentity (90-90)
pkg/schema/schema.go (2)
  • Context (481-496)
  • AWSAuthContext (584-599)
internal/exec/yaml_func_aws_test.go (2)
internal/exec/aws_getter.go (4)
  • AWSCallerIdentity (15-20)
  • ClearAWSIdentityCache (157-163)
  • SetAWSGetter (78-86)
  • AWSGetter (26-34)
errors/errors.go (1)
  • ErrAwsGetCallerIdentity (90-90)
🪛 LanguageTool
website/docs/functions/yaml/aws.caller-identity-user-id.mdx

[typographical] ~35-~35: To join two clauses or introduce examples, consider using an em dash.
Context: ..., Atmos: 1. Loads AWS Configuration - Uses the standard AWS SDK credential res...

(DASH_RULE)


[typographical] ~36-~36: To join two clauses or introduce examples, consider using an em dash.
Context: ...chain 2. Calls STS GetCallerIdentity - Makes an API call to retrieve the caller...

(DASH_RULE)


[typographical] ~37-~37: To join two clauses or introduce examples, consider using an em dash.
Context: ...e caller identity 3. Returns User ID - Extracts and returns the unique user ID ...

(DASH_RULE)


[style] ~135-~135: Using many exclamation marks might seem excessive (in this case: 10 exclamation marks for a text that’s 2879 characters long)
Context: ...y` permission ## Related Functions - !aws.account_id - Get the AWS account ID - !aws.caller_identity_arn - Get the full ARN - !aws.region ...

(EN_EXCESSIVE_EXCLAMATION)


[typographical] ~137-~137: To join two clauses or introduce examples, consider using an em dash.
Context: ...!aws.region](/functions/yaml/aws.region) - Get the AWS region

(DASH_RULE)

website/docs/functions/yaml/aws.caller-identity-arn.mdx

[typographical] ~35-~35: To join two clauses or introduce examples, consider using an em dash.
Context: ..., Atmos: 1. Loads AWS Configuration - Uses the standard AWS SDK credential res...

(DASH_RULE)


[style] ~185-~185: Using many exclamation marks might seem excessive (in this case: 9 exclamation marks for a text that’s 3773 characters long)
Context: ...d role, etc.) ## Related Functions - !aws.account_id - Get the AWS account ID - !aws.caller_identity_user_id - Get the unique user ID - !aws.region ...

(EN_EXCESSIVE_EXCLAMATION)


[typographical] ~187-~187: To join two clauses or introduce examples, consider using an em dash.
Context: ...!aws.region](/functions/yaml/aws.region) - Get the AWS region

(DASH_RULE)

website/blog/2025-12-05-aws-yaml-functions.mdx

[typographical] ~74-~74: To join two clauses or introduce examples, consider using an em dash.
Context: ...unt_id](/functions/yaml/aws.account-id) - Full documentation - [!aws.caller_ident...

(DASH_RULE)


[typographical] ~78-~78: To join two clauses or introduce examples, consider using an em dash.
Context: ...ML Functions Overview](/functions/yaml/) - All available YAML functions

(DASH_RULE)

website/docs/functions/yaml/aws.account-id.mdx

[typographical] ~35-~35: To join two clauses or introduce examples, consider using an em dash.
Context: ..., Atmos: 1. Loads AWS Configuration - Uses the standard AWS SDK credential res...

(DASH_RULE)


[typographical] ~165-~165: To join two clauses or introduce examples, consider using an em dash.
Context: ...ctions/yaml/aws.caller-identity-user-id) - Get the unique user ID - [!aws.region](/...

(DASH_RULE)


[typographical] ~166-~166: To join two clauses or introduce examples, consider using an em dash.
Context: ...!aws.region](/functions/yaml/aws.region) - Get the AWS region

(DASH_RULE)

website/docs/functions/yaml/aws.region.mdx

[typographical] ~35-~35: To join two clauses or introduce examples, consider using an em dash.
Context: ..., Atmos: 1. Loads AWS Configuration - Uses the standard AWS SDK configuration ...

(DASH_RULE)


[style] ~174-~174: Using many exclamation marks might seem excessive (in this case: 9 exclamation marks for a text that’s 2977 characters long)
Context: ...y` permission ## Related Functions - !aws.account_id - Get the AWS account ID - !aws.caller_identity_arn - Get the full ARN - [!aws.caller_identity_user_id](/functions/...

(EN_EXCESSIVE_EXCLAMATION)


[typographical] ~176-~176: To join two clauses or introduce examples, consider using an em dash.
Context: ...ctions/yaml/aws.caller-identity-user-id) - Get the user ID

(DASH_RULE)

website/docs/functions/yaml/index.mdx

[style] ~90-~90: Using many exclamation marks might seem excessive (in this case: 17 exclamation marks for a text that’s 5280 characters long)
Context: ...ity using STS GetCallerIdentity - The [!aws.region](/functions/yaml/aws.regio...

(EN_EXCESSIVE_EXCLAMATION)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Summary
🔇 Additional comments (31)
website/blog/2025-12-05-aws-yaml-functions.mdx (1)

1-78: LGTM!

Blog post is well-structured with proper front matter, clear use cases, and helpful Terragrunt comparison. The caching explanation effectively communicates the performance benefits.

pkg/utils/yaml_utils.go (2)

33-36: LGTM!

New AWS YAML function constants are well-named and follow the established !aws.* naming convention, consistent with the existing patterns.


55-77: LGTM!

AWS function constants consistently added to both AtmosYamlTags slice and atmosYamlTagsMap for O(1) lookups. Good attention to maintaining the optimization pattern.

website/docs/functions/yaml/aws.caller-identity-arn.mdx (1)

1-187: LGTM!

Comprehensive documentation covering usage, caching semantics, examples, and error handling. The ARN format table for different identity types is a helpful addition.

website/docs/functions/yaml/index.mdx (2)

81-92: LGTM!

AWS function entries follow the established documentation pattern. Clear descriptions with appropriate links.


169-180: LGTM!

Examples effectively demonstrate the new AWS functions with clear inline comments explaining each one.

website/docs/functions/yaml/aws.account-id.mdx (1)

70-84: LGTM!

Basic usage example correctly demonstrates the function as a complete value assignment.

website/docs/functions/yaml/aws.region.mdx (1)

62-75: LGTM!

Basic usage and provider configuration examples correctly show the function as complete value assignments.

website/docs/functions/yaml/aws.caller-identity-user-id.mdx (1)

1-137: LGTM!

Documentation is comprehensive with correct usage examples. The user ID format table for different identity types provides helpful context.

internal/aws_utils/aws_utils.go (3)

130-136: LGTM!

Clean struct definition with exported fields. Good choice keeping AWS SDK types internal and exposing simple strings.


141-179: LGTM!

Solid implementation. Context propagation is correct, error wrapping uses sentinel errors properly, and nil pointer handling for AWS SDK responses is defensive. The perf.Track placement follows conventions.


99-99: LGTM!

Good fix using %w for proper error wrapping, enabling errors.Is() checks up the call chain.

internal/exec/aws_getter.go (6)

1-12: LGTM!

Package declaration and imports are well organized - stdlib first, then atmos packages, with proper aliases.


14-34: LGTM!

Clean struct and interface definitions with proper documentation. The mockgen directive follows the project pattern.


36-70: LGTM!

Solid implementation - perf tracking, debug logging, and proper delegation to aws_utils. Error handling trusts the underlying layer which keeps this code focused.


72-86: LGTM!

Nice testability hook. The restore function pattern is clean for test cleanup.


113-153: LGTM!

Double-checked locking is correctly implemented. Caching errors prevents repeated failed STS calls - good for CLI responsiveness.


155-163: LGTM!

Clean cache invalidation with proper locking.

internal/exec/yaml_func_aws_test.go (13)

1-14: LGTM!

Imports are well organized with proper groupings and aliases.


30-51: LGTM!

Clean helper that reduces test duplication. Cache clearing and mock setup/teardown handled properly.


53-97: LGTM!

Solid table-driven tests covering valid account ID scenarios.


99-177: LGTM!

Good coverage for ARN and UserID tag processing with different identity types (IAM user, assumed role).


179-231: LGTM!

Region tests cover multiple AWS regions.


233-302: LGTM!

Excellent caching tests - validates cache hits, misses, different auth contexts, and cache clearing. The counting wrapper is a nice touch.


304-335: LGTM!

Good test ensuring errors are cached to avoid repeated failed calls.


337-372: LGTM!

Cache key tests cover nil context and various field combinations.


374-377: LGTM!

Compile-time interface implementation check - good practice.


379-414: LGTM!

Tests auth context integration properly.


416-492: LGTM!

Good integration tests through processSimpleTags and skip behavior validation.


494-500: LGTM!

Constants verification is useful for catching accidental changes.


524-558: LGTM!

Good tests verifying default getter initialization and restore semantics.

Comment on lines +104 to +111
// getCacheKey generates a cache key based on the auth context.
// Different auth contexts (different credentials) get different cache entries.
func getCacheKey(authContext *schema.AWSAuthContext) string {
if authContext == nil {
return "default"
}
return fmt.Sprintf("%s:%s", authContext.Profile, authContext.CredentialsFile)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

ast-grep --pattern $'type AWSAuthContext struct {
  $$$
}'

Repository: cloudposse/atmos

Length of output: 1228


🏁 Script executed:

cat -n internal/exec/aws_getter.go | head -150

Repository: cloudposse/atmos

Length of output: 5752


🏁 Script executed:

find . -type f -name "*.go" | xargs grep -l "GetAWSCallerIdentity" | grep aws_utils

Repository: cloudposse/atmos

Length of output: 93


🏁 Script executed:

cat -n internal/aws_utils/aws_utils.go | head -200

Repository: cloudposse/atmos

Length of output: 6823


Add ConfigFile to cache key generation.

The cache key only uses Profile and CredentialsFile, but ConfigFile is also used during AWS credential loading (passed to config.WithSharedConfigFiles()). Different ConfigFile values can result in different AWS configurations and may affect identity resolution. Update getCacheKey() to include ConfigFile in the cache key to ensure different configurations don't incorrectly share cache entries.

Additionally, consider whether Region should be included, as it's used during config loading when not explicitly provided (line 82-83 in aws_utils.go).

🤖 Prompt for AI Agents
In internal/exec/aws_getter.go around lines 104 to 111, the cache key currently
only includes Profile and CredentialsFile which can cause cache collisions when
different shared AWS config files are used; update getCacheKey to also
incorporate authContext.ConfigFile (and include Region if authContext.Region may
influence loaded config) so the returned key reflects
Profile:CredentialsFile:ConfigFile (and optionally :Region) to ensure distinct
auth contexts produce distinct cache entries.

Comment on lines +87 to +95
<File title="stack.yaml">
```yaml
terraform:
backend:
s3:
# Use the current account ID in the state bucket name
bucket: "terraform-state-!aws.account_id"
```
</File>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect YAML function usage in example.

Line 93 shows bucket: "terraform-state-!aws.account_id" but YAML tags must be the complete value—they can't be embedded within strings. This example won't interpolate and will produce the literal string.

Consider either:

  1. Showing the account ID as a separate variable that Terraform uses for naming
  2. Using !template if string interpolation is actually needed
  3. Removing this example to avoid confusion
-```yaml
-terraform:
-  backend:
-    s3:
-      # Use the current account ID in the state bucket name
-      bucket: "terraform-state-!aws.account_id"
-```
+```yaml
+terraform:
+  backend:
+    s3:
+      # Pass account ID to construct bucket name in Terraform
+      account_id: !aws.account_id
+```
🤖 Prompt for AI Agents
In website/docs/functions/yaml/aws.account-id.mdx around lines 87–95, the
example embeds the YAML tag inside a quoted string
("terraform-state-!aws.account_id") which is invalid because YAML tags must be
the entire scalar; change the example so the tag is a standalone value (e.g.,
provide account_id: !aws.account_id) or demonstrate passing the account ID as a
separate variable that Terraform composes into the bucket name (show Terraform
interpolation on the Terraform side, not embedding the tag inside the string),
or alternatively replace the example with a note removing the confusing line.

Comment on lines +96 to +109
<File title="stack.yaml">
```yaml
components:
terraform:
s3-bucket:
vars:
# Include region in resource names
bucket_prefix: "myapp-!aws.region"

tags:
Region: !aws.region
Environment: "production"
```
</File>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect YAML function usage in example.

Lines 103 and 106 embed YAML tags within strings ("myapp-!aws.region"). YAML tags must be complete values—string embedding doesn't interpolate. This will produce literal strings, not the expected values.

Same applies to line 125 with "arn:aws:s3:::myapp-!aws.account_id-!aws.region".

       vars:
-        # Include region in resource names
-        bucket_prefix: "myapp-!aws.region"
-
         tags:
           Region: !aws.region
           Environment: "production"
+        # Pass region as separate var for Terraform to construct names
+        aws_region: !aws.region

Address CodeRabbit review feedback: Replace assert.Contains(err.Error(), ...)
with assert.ErrorIs() to properly verify error chain preservation following
the project's error handling guidelines.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
internal/exec/yaml_func_aws_test.go (1)

554-558: Avoid string comparison on sentinel error messages; rely on assert.ErrorIs or just existence.

Line 557 compares the sentinel’s .Error() string directly, which conflicts with the guideline to avoid string‑based error checks (err.Error() == "..."). You’re already validating the sentinel’s presence, so either:

  • Drop the string assertion and keep the existence check:
 func TestErrAwsGetCallerIdentity(t *testing.T) {
-	assert.NotNil(t, errUtils.ErrAwsGetCallerIdentity)
-	assert.Equal(t, "failed to get AWS caller identity", errUtils.ErrAwsGetCallerIdentity.Error())
+	assert.NotNil(t, errUtils.ErrAwsGetCallerIdentity)
 }

Or, if you want a slightly stronger check while still following conventions, assert via ErrorIs:

 func TestErrAwsGetCallerIdentity(t *testing.T) {
-	assert.NotNil(t, errUtils.ErrAwsGetCallerIdentity)
-	assert.Equal(t, "failed to get AWS caller identity", errUtils.ErrAwsGetCallerIdentity.Error())
+	assert.NotNil(t, errUtils.ErrAwsGetCallerIdentity)
+	assert.ErrorIs(t, errUtils.ErrAwsGetCallerIdentity, errUtils.ErrAwsGetCallerIdentity)
 }

This keeps tests resilient to message wording changes and aligns with the project’s assert.ErrorIs guidance for sentinel errors. As per coding guidelines and retrieved learnings, error tests should avoid direct string comparisons.

🧹 Nitpick comments (2)
internal/exec/yaml_func_aws_test.go (2)

53-97: Tighten the account ID table to either exercise error paths or drop unused fields.

The table includes mockErr and shouldReturnNil but all cases use mockErr: nil and the shouldReturnNil flag is never set, so the conditional in Lines 90–94 always takes the non‑nil branch. Either:

  • Add one or more cases where mockErr is non‑nil and shouldReturnNil is true (to exercise the error behavior of processTagAwsAccountID), or
  • Remove mockErr/shouldReturnNil from this table and use the simpler pattern since error behavior is already covered elsewhere.

This keeps the test intent obvious and avoids dead fields in the table.


233-372: Cache behavior and keying tests are thorough; optional idea to assert wrapped error identity.

The TestAWSIdentityCache, TestAWSCacheWithErrors, and TestGetCacheKey suites exercise:

  • hit/miss behavior and ClearAWSIdentityCache,
  • per‑auth‑context keying via getCacheKey, and
  • the fact that both successful identities and errors are cached (via countingAWSGetter).

That gives strong confidence in the cache contract. If you want to go a step further in TestAWSCacheWithErrors, you could also assert that the cached error still matches the expected error via assert.ErrorIs(t, err, expectedErr) in both calls, to document that the underlying cause remains the same. Not mandatory, but it would tighten the spec a bit. Based on learnings, tests should prefer assert.ErrorIs when checking specific error identities.

Also applies to: 304-335

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between cb3bacc and c9bfe8a.

📒 Files selected for processing (1)
  • internal/exec/yaml_func_aws_test.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: All comments must end with periods (enforced by godot linter)
Import organization: three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages. Maintain aliases: cfg, log, u, errUtils
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig param
Keep files small and focused (<600 lines). One cmd/impl per file. Co-locate tests. Never use //revive:disable:file-length-limit
Use sentinel errors from errors/errors.go with ErrorBuilder for all user-facing errors. Use errors.Is() for checking errors, never string comparison. WithCause() preserves underlying error messages, WithExplanation() adds context, WithHint() provides guidance, WithContext() adds key-value pairs
Use context.Context as first parameter for: cancellation signals (prop...

Files:

  • internal/exec/yaml_func_aws_test.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Use assert.ErrorIs(t, err, ErrSentinel) for checking our own errors and stdlib errors. Only use string matching for third-party errors
NEVER use assert.Contains(err.Error(), ...) for error checking. ALWAYS use assert.ErrorIs() instead. NEVER use string comparison: err.Error() == "..." or strings.Contains(err.Error(), ...)
Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoid os.Exit, CheckErrorPrintAndExit, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation. Never create manual mocks. Pattern: //go:generate go run go.uber.org/mock/mockgen@latest -source=filename.go -destination=mock_filename_test.go
Use table-driven tests for comprehensive coverage. Tests must call actual production code, never duplicate logic. Target >80% test coverage (enforced by CodeCov)

Files:

  • internal/exec/yaml_func_aws_test.go
🧠 Learnings (18)
📓 Common learnings
Learnt from: mcalhoun
Repo: cloudposse/atmos PR: 963
File: website/docs/core-concepts/projects/configuration/stores.mdx:286-286
Timestamp: 2025-04-25T20:54:19.701Z
Learning: For the AWS SSM Parameter Store implementation in Atmos, support for `read_role_arn` and `write_role_arn` options is essential to enable cross-account access, allowing users to run operations like `terraform plan` in multiple accounts while accessing values across keystores. Azure Key Vault would need similar capabilities for cross-tenant/subscription authentication.
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : New configs support Go templating with `FuncMap()` from `internal/exec/template_funcs.go`. Implement template functions in `internal/exec/template_funcs.go`, register them, add tests, and update documentation

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoid `os.Exit`, `CheckErrorPrintAndExit`, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : Use table-driven tests for comprehensive coverage. Tests must call actual production code, never duplicate logic. Target >80% test coverage (enforced by CodeCov)

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to pkg/**/*.go : Create focused purpose-built packages in `pkg/` for new functionality, each with clear responsibility. DO NOT add new functions to `pkg/utils/` or `internal/exec/`. Each package should have focused business logic with tests

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : NEVER use `assert.Contains(err.Error(), ...)` for error checking. ALWAYS use `assert.ErrorIs()` instead. NEVER use string comparison: `err.Error() == "..."` or `strings.Contains(err.Error(), ...)`

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : Use `assert.ErrorIs(t, err, ErrSentinel)` for checking our own errors and stdlib errors. Only use string matching for third-party errors

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to tests/**/*_test.go : NEVER use pipe redirection (`2>&1`, `| head`, `| tail`) when running tests. Piping breaks TTY detection → ASCII fallback → wrong snapshots. NEVER manually edit golden snapshot files - always use `-regenerate-snapshots` flag. Snapshots capture exact output including invisible formatting (lipgloss padding, ANSI codes, trailing whitespace)

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Use dependency injection and interface-driven design to make code testable - avoid `os.Exit`, `CheckErrorPrintAndExit`, and direct external system calls in testable functions

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-09-10T22:38:42.212Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: The user confirmed that the errors package has an error string wrapping format, contradicting the previous learning about ErrWrappingFormat being invalid. The current usage of fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) appears to be the correct pattern.

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-03-25T12:23:42.649Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 1149
File: internal/exec/go_getter_utils.go:104-104
Timestamp: 2025-03-25T12:23:42.649Z
Learning: Listener430 plans to add a test for verifying that token injection is skipped for unsupported hosts in a future review or refactoring iteration. This relates to the CustomGitDetector.Detect method in internal/exec/go_getter_utils.go.

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1185
File: internal/exec/yaml_func_store.go:26-26
Timestamp: 2025-04-04T02:03:23.676Z
Learning: The Atmos codebase currently uses `log.Fatal` for error handling in multiple places. The maintainers are aware this isn't an ideal pattern (should only be used in main() or init() functions) and plan to address it comprehensively in a separate PR. CodeRabbit should not flag these issues or push for immediate changes until that refactoring is complete.

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-09-10T22:38:42.212Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: ErrWrappingFormat is correctly defined as "%w: %w" in the errors package and is used throughout the codebase to wrap two error types together. The usage fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) is the correct pattern when both arguments are error types.

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-10-22T14:55:44.014Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1695
File: pkg/auth/manager.go:169-171
Timestamp: 2025-10-22T14:55:44.014Z
Learning: Go 1.20+ supports multiple %w verbs in fmt.Errorf, which returns an error implementing Unwrap() []error. This is valid and does not panic. Atmos uses Go 1.24.8 and configures errorlint with errorf-multi: true to validate this pattern.

Applied to files:

  • internal/exec/yaml_func_aws_test.go
📚 Learning: 2025-11-11T03:47:45.878Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/add_test.go:67-77
Timestamp: 2025-11-11T03:47:45.878Z
Learning: In the cloudposse/atmos codebase, tests should prefer t.Setenv for environment variable setup/teardown instead of os.Setenv/Unsetenv to ensure test-scoped isolation.

Applied to files:

  • internal/exec/yaml_func_aws_test.go
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (5)
internal/exec/yaml_func_aws_test.go (5)

16-51: Helper and mock wiring for AWS YAML tests looks solid.

mockAWSGetter and runAWSYamlFuncTest keep tests focused on behavior and reset global state (ClearAWSIdentityCache, SetAWSGetter/restore) cleanly. No changes needed here.


99-231: Good behavioral coverage for ARN, user ID, and region tag processors.

The table‑driven tests for processTagAwsCallerIdentityArn, processTagAwsCallerIdentityUserID, and processTagAwsRegion cover realistic IAM/STS identities and multiple regions, and they lean on the shared helper to keep setup consistent. This is a nice balance of coverage vs. complexity.


374-414: Auth‑context and simple‑tag integration tests read well and match expected behavior.

TestAWSGetterInterface, TestProcessTagAwsWithAuthContext, TestProcessSimpleTagsWithAWSFunctions, and TestProcessSimpleTagsSkipsAWSFunctions collectively verify:

  • interface implementation of defaultAWSGetter,
  • correct use of stackInfo.AuthContext.AWS,
  • that the !aws.* tags are properly routed through processSimpleTags, and
  • that skip lists are honored for each AWS function.

The repeated ClearAWSIdentityCache calls keep tests independent despite the shared global cache. No changes needed here.

Also applies to: 416-493


494-522: Constants and error‑wrapping tests look good.

TestAWSYamlFunctionConstants locks down the public tag strings, and TestErrorWrapping correctly checks that the underlying error is preserved using assert.ErrorIs instead of string matching, which aligns with the repo’s error‑testing rules. Nicely done.


524-552: Default getter existence and SetAWSGetter restore behavior are well‑covered.

TestDefaultAWSGetterExists and TestSetAWSGetterRestore provide good safeguards around the global awsGetter lifecycle and the restore closure from SetAWSGetter. This will help catch regressions if the default implementation or setter wiring changes later.

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

Labels

minor New features that do not break anything size/xl Extra large size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants