-
-
Notifications
You must be signed in to change notification settings - Fork 135
Add AWS YAML functions for identity and region retrieval #1843
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
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. |
📝 WalkthroughWalkthroughAdds 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
Sequence DiagramsequenceDiagram
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
Dependency Review✅ No vulnerabilities or license issues found.Scanned FilesNone |
ca45d16 to
a7f353d
Compare
Codecov Report❌ Patch coverage is ❌ 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@@ 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
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this 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 toexpectedTagskeeps 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 inTestAtmosYamlTagsMap_O1Lookupso 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 foowill fall through and be returned as a raw string. GivenprocessTagAwsValuealready validatesinput != expectedTagand returnsErrYamlFuncInvalidArguments, you could instead route onmatchesPrefix(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.
📒 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.gointernal/aws_utils/aws_utils.gopkg/utils/yaml_utils.gointernal/exec/yaml_func_utils.gointernal/exec/yaml_func_aws.gopkg/utils/yaml_utils_test.gointernal/exec/aws_getter.gointernal/exec/yaml_func_aws_test.go
.golangci.yml
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Configure golangci-lint in
.golangci.ymlwith 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 thewebsite/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 thewebsite/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.mdxwebsite/docs/functions/yaml/aws.account-id.mdxwebsite/docs/functions/yaml/aws.caller-identity-user-id.mdxwebsite/docs/functions/yaml/aws.region.mdxwebsite/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.gointernal/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.gopkg/utils/yaml_utils.gointernal/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.ymlinternal/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.mdxwebsite/docs/functions/yaml/aws.account-id.mdxwebsite/docs/functions/yaml/aws.caller-identity-user-id.mdxwebsite/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.mdxwebsite/docs/functions/yaml/aws.region.mdxpkg/utils/yaml_utils.gowebsite/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.mdxpkg/utils/yaml_utils.gowebsite/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.gointernal/exec/yaml_func_utils.gopkg/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.gointernal/exec/yaml_func_utils.gointernal/exec/yaml_func_aws.gopkg/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.gointernal/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.gointernal/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.gointernal/exec/yaml_func_utils.gointernal/exec/yaml_func_aws.gopkg/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.gointernal/exec/yaml_func_aws.gointernal/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.gointernal/exec/yaml_func_aws.gopkg/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 onpkg/auth. This aligns with the new STS helpers you added there.errors/errors.go (1)
89-96: New ErrAwsGetCallerIdentity sentinel is well-scoped.Defining
ErrAwsGetCallerIdentityhere 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.yamlclearly 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.
processTagAwsValuenicely centralizes input validation, auth-context extraction, cached identity lookup, and field extraction, and the fourprocessTagAws*wrappers add perf tracking and targeted debug logs without extra complexity. Error handling viaErrYamlFuncInvalidArgumentsand 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
LoadAWSConfigWithAuthto wrap with%wfixes unwrapping while still using theErrLoadAwsConfigsentinel, and the newGetAWSCallerIdentitycleanly encapsulates STS usage, returning anAWSCallerIdentityResultwith account, ARN, user ID, and region while wrapping failures withErrAwsGetCallerIdentity. Keeping this logic inaws_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.
a7f353d to
b3745a7
Compare
|
Warning Changelog Entry RequiredThis PR is labeled Action needed: Add a new blog post in Example filename: Alternatively: If this change doesn't require a changelog entry, remove the |
b3745a7 to
0384e20
Compare
|
💥 This pull request now has conflicts. Could you fix it @osterman? 🙏 |
…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]>
0384e20 to
dbf661b
Compare
There was a problem hiding this 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:
getCacheKeycurrently keys onauthContext.ProfileandauthContext.CredentialsFileonly, butAWSCallerIdentity.Region(and potentially the underlying principal) can vary with other auth-context attributes (e.g., region, role, or account details inschema.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 onAWSAuthContext(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).
mockAWSGetterandcountingAWSGetterare straightforward and readable, but they do violate the repo guideline that mocks should be generated viago.uber.org/mock/mockgenrather 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:generateforAWSGetterand 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 includesmockErrandshouldReturnNil, but all cases setmockErrtoniland never setshouldReturnNiltotrue, so that branch is effectively dead.Either:
- Remove
mockErrandshouldReturnNilfrom this table (and the conditional onshouldReturnNil), or- Add at least one case with a non-
nilmockErrandshouldReturnNil = trueto exercise the error path and make the fields meaningful.
524-532: Default getter existence/type check is useful but implementation-focused.
TestDefaultAWSGetterExistspins thatawsGetteris 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.
📒 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 usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto 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 bygodotlinter)
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
Adddefer perf.Track(atmosConfig, "pkg.FuncName")()+ blank line to all public functions. Usenilif 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 fromerrors/errors.gowith ErrorBuilder for all user-facing errors. Useerrors.Is()for checking errors, never string comparison.WithCause()preserves underlying error messages,WithExplanation()adds context,WithHint()provides guidance,WithContext()adds key-value pairs
Usecontext.Contextas first parameter for: cancellation signals (prop...
Files:
internal/exec/aws_getter.gointernal/exec/yaml_func_utils.gointernal/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: Useassert.ErrorIs(t, err, ErrSentinel)for checking our own errors and stdlib errors. Only use string matching for third-party errors
NEVER useassert.Contains(err.Error(), ...)for error checking. ALWAYS useassert.ErrorIs()instead. NEVER use string comparison:err.Error() == "..."orstrings.Contains(err.Error(), ...)
Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoidos.Exit,CheckErrorPrintAndExit, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios
Usego.uber.org/mock/mockgenwith//go:generatedirectives 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 thewebsite/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 thewebsite/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.mdxwebsite/docs/functions/yaml/aws.account-id.mdxwebsite/docs/functions/yaml/aws.caller-identity-arn.mdxwebsite/docs/functions/yaml/aws.caller-identity-user-id.mdxwebsite/docs/functions/yaml/aws.region.mdxwebsite/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 fromwebsite/blog/*.mdx- check before writing. Author field must be GitHub username, added towebsite/blog/authors.yml. Filename format:YYYY-MM-DD-feature-name.mdx. PRs labeledminor/majorMUST 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.gointernal/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.mdxwebsite/docs/functions/yaml/aws.account-id.mdxwebsite/docs/functions/yaml/aws.caller-identity-arn.mdxwebsite/docs/functions/yaml/aws.caller-identity-user-id.mdxwebsite/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.mdxwebsite/docs/functions/yaml/aws.account-id.mdxwebsite/docs/functions/yaml/aws.region.mdxwebsite/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.mdxwebsite/docs/functions/yaml/aws.region.mdxwebsite/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.mdxwebsite/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.mdxwebsite/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 withskipFuncfit the “no-args” contract and align with how other YAML tags are handled; wiring intoprocessSimpleTagsis 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
runAWSYamlFuncTestkeeps things DRY and focused on behavior.
233-287: Caching behavior tests look solid.
TestAWSIdentityCacheexercises first-hit, cache hit, different-auth-context, and post-clear scenarios against the sameAWSCallerIdentity, and thecountingAWSGetterpattern 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.
TestAWSCacheWithErrorscorrectly 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.
TestGetCacheKeycovers 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.
TestAWSGetterInterfaceis 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.
TestProcessTagAwsWithAuthContextcleanly verifies thatprocessTagAws*uses theAuthContextfromConfigAndStacksInfo, which is important for multi-account setups. Clearing the cache between the two assertions keeps the test deterministic.
416-463: End-to-end coverage viaprocessSimpleTagslooks good.
TestProcessSimpleTagsWithAWSFunctionsruns each of the four AWS functions throughprocessSimpleTags, checkshandled, and validates the returned values. This is a nice higher-level check on top of the lower-levelprocessTagAws*tests.
465-492: Skip list behavior is clearly exercised.
TestProcessSimpleTagsSkipsAWSFunctionsensures that each AWS YAML function is correctly excluded when present in theskipslice and thathandledisfalsewith anilresult. This is valuable to guarantee that “skip” truly short-circuits evaluation (and avoids AWS calls).
494-500: Constant verification test is appropriate.
TestAWSYamlFunctionConstantsdirectly 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 forSetAWSGetteris well tested.
TestSetAWSGetterRestorenicely verifies both thatawsGetteris 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.
| // 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") | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
rg -A 20 "func getAWSCallerIdentityCached" --type goRepository: 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.goRepository: cloudposse/atmos
Length of output: 185
🏁 Script executed:
find . -name "*aws*test.go" -type f 2>/dev/nullRepository: cloudposse/atmos
Length of output: 301
🏁 Script executed:
rg "TestErrorWrapping" --type go -A 20Repository: cloudposse/atmos
Length of output: 1453
🏁 Script executed:
ls internal/exec/ | head -20Repository: cloudposse/atmos
Length of output: 504
🏁 Script executed:
rg "getAWSCallerIdentityCached" --type goRepository: cloudposse/atmos
Length of output: 1149
🏁 Script executed:
rg "ErrAwsGetCallerIdentity" --type goRepository: 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 -10Repository: cloudposse/atmos
Length of output: 150
🏁 Script executed:
rg "ErrAws" --type go -B 2 -A 2 | head -50Repository: cloudposse/atmos
Length of output: 3563
🏁 Script executed:
git status 2>&1 | head -20Repository: cloudposse/atmos
Length of output: 125
🏁 Script executed:
fd "yaml.*aws" -e goRepository: cloudposse/atmos
Length of output: 126
🏁 Script executed:
git ls-files internal/exec/ | grep -E "(yaml|aws)" | head -20Repository: cloudposse/atmos
Length of output: 900
🏁 Script executed:
rg "mockAWSGetter" --type go -B 5 -A 15Repository: cloudposse/atmos
Length of output: 10573
🏁 Script executed:
rg "SetAWSGetter\|ClearAWSIdentityCache" --type goRepository: cloudposse/atmos
Length of output: 42
🏁 Script executed:
ls -la internal/exec/*.go | grep -v vendorRepository: cloudposse/atmos
Length of output: 20710
🏁 Script executed:
find . -type f -name "*test.go" | xargs grep -l "TestErrorWrapping" 2>/dev/nullRepository: cloudposse/atmos
Length of output: 97
🏁 Script executed:
git ls-files | grep -E "test\.go$" | head -20Repository: cloudposse/atmos
Length of output: 573
🏁 Script executed:
git log --oneline -n 20 2>&1Repository: cloudposse/atmos
Length of output: 102
🏁 Script executed:
git diff --name-only --cached 2>&1Repository: cloudposse/atmos
Length of output: 42
🏁 Script executed:
rg "identity|Identity" internal/exec/ --type go -l | head -10Repository: cloudposse/atmos
Length of output: 396
🏁 Script executed:
rg "network timeout" --type goRepository: cloudposse/atmos
Length of output: 602
🏁 Script executed:
ls -laRepository: cloudposse/atmos
Length of output: 3252
🏁 Script executed:
rg "assert.Contains.*err.Error" --type go | head -10Repository: cloudposse/atmos
Length of output: 1133
🏁 Script executed:
assert.ErrorIs" --type go -B 2 -A 2 | head -40Repository: cloudposse/atmos
Length of output: 128
🏁 Script executed:
fmt.Errorf.*%w.*%w" --type go | head -10Repository: cloudposse/atmos
Length of output: 128
🏁 Script executed:
find . -type f -name "*.go" -path "*/errors/*" | head -10Repository: cloudposse/atmos
Length of output: 305
🏁 Script executed:
find . -type d -name "errors" 2>/dev/nullRepository: cloudposse/atmos
Length of output: 86
🏁 Script executed:
rg "errUtils|errors" --type go | grep "import" | head -10Repository: cloudposse/atmos
Length of output: 743
🏁 Script executed:
ls -la pkg/ 2>&1 | head -30Repository: cloudposse/atmos
Length of output: 1724
🏁 Script executed:
cat -n internal/exec/aws_getter.go | head -80Repository: cloudposse/atmos
Length of output: 3119
🏁 Script executed:
rg -A 30 "func getAWSCallerIdentityCached" internal/exec/aws_getter.goRepository: cloudposse/atmos
Length of output: 1050
🏁 Script executed:
cat internal/exec/aws_getter.goRepository: 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 preservedThis 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.
There was a problem hiding this 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
!templatewithexec "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_idOr 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.
📒 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 usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto 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 bygodotlinter)
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
Adddefer perf.Track(atmosConfig, "pkg.FuncName")()+ blank line to all public functions. Usenilif 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 fromerrors/errors.gowith ErrorBuilder for all user-facing errors. Useerrors.Is()for checking errors, never string comparison.WithCause()preserves underlying error messages,WithExplanation()adds context,WithHint()provides guidance,WithContext()adds key-value pairs
Usecontext.Contextas first parameter for: cancellation signals (prop...
Files:
internal/exec/aws_getter.gointernal/aws_utils/aws_utils.gopkg/utils/yaml_utils.gointernal/exec/yaml_func_aws_test.go
website/**
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
website/**: Update website documentation in thewebsite/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 thewebsite/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.mdxwebsite/docs/functions/yaml/aws.caller-identity-arn.mdxwebsite/blog/2025-12-05-aws-yaml-functions.mdxwebsite/docs/functions/yaml/aws.account-id.mdxwebsite/docs/functions/yaml/aws.region.mdxwebsite/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 withgo.uber.org/mock/mockgenwith//go:generatedirectives, avoid integration tests by mocking external dependencies
Create focused purpose-built packages inpkg/for new functionality, each with clear responsibility. DO NOT add new functions topkg/utils/orinternal/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 incmd/internal/registry.go, Store Registry inpkg/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: Useassert.ErrorIs(t, err, ErrSentinel)for checking our own errors and stdlib errors. Only use string matching for third-party errors
NEVER useassert.Contains(err.Error(), ...)for error checking. ALWAYS useassert.ErrorIs()instead. NEVER use string comparison:err.Error() == "..."orstrings.Contains(err.Error(), ...)
Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoidos.Exit,CheckErrorPrintAndExit, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios
Usego.uber.org/mock/mockgenwith//go:generatedirectives 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 fromwebsite/blog/*.mdx- check before writing. Author field must be GitHub username, added towebsite/blog/authors.yml. Filename format:YYYY-MM-DD-feature-name.mdx. PRs labeledminor/majorMUST 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.mdxwebsite/docs/functions/yaml/aws.caller-identity-arn.mdxwebsite/blog/2025-12-05-aws-yaml-functions.mdxwebsite/docs/functions/yaml/aws.account-id.mdxwebsite/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.gowebsite/blog/2025-12-05-aws-yaml-functions.mdxwebsite/docs/functions/yaml/aws.region.mdxwebsite/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.gowebsite/blog/2025-12-05-aws-yaml-functions.mdxwebsite/docs/functions/yaml/aws.account-id.mdxwebsite/docs/functions/yaml/aws.region.mdxwebsite/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.mdxwebsite/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.mdxwebsite/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
AtmosYamlTagsslice andatmosYamlTagsMapfor 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.Trackplacement follows conventions.
99-99: LGTM!Good fix using
%wfor proper error wrapping, enablingerrors.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
processSimpleTagsand 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.
| // 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) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 -150Repository: cloudposse/atmos
Length of output: 5752
🏁 Script executed:
find . -type f -name "*.go" | xargs grep -l "GetAWSCallerIdentity" | grep aws_utilsRepository: cloudposse/atmos
Length of output: 93
🏁 Script executed:
cat -n internal/aws_utils/aws_utils.go | head -200Repository: 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.
| <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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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:
- Showing the account ID as a separate variable that Terraform uses for naming
- Using
!templateif string interpolation is actually needed - 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.
| <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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.regionAddress 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]>
There was a problem hiding this 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 onassert.ErrorIsor 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.ErrorIsguidance 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
mockErrandshouldReturnNilbut all cases usemockErr: niland theshouldReturnNilflag is never set, so the conditional in Lines 90–94 always takes the non‑nil branch. Either:
- Add one or more cases where
mockErris non‑nil andshouldReturnNilistrue(to exercise the error behavior ofprocessTagAwsAccountID), or- Remove
mockErr/shouldReturnNilfrom 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, andTestGetCacheKeysuites 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 viaassert.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 preferassert.ErrorIswhen 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.
📒 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 usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto 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 bygodotlinter)
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
Adddefer perf.Track(atmosConfig, "pkg.FuncName")()+ blank line to all public functions. Usenilif 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 fromerrors/errors.gowith ErrorBuilder for all user-facing errors. Useerrors.Is()for checking errors, never string comparison.WithCause()preserves underlying error messages,WithExplanation()adds context,WithHint()provides guidance,WithContext()adds key-value pairs
Usecontext.Contextas 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: Useassert.ErrorIs(t, err, ErrSentinel)for checking our own errors and stdlib errors. Only use string matching for third-party errors
NEVER useassert.Contains(err.Error(), ...)for error checking. ALWAYS useassert.ErrorIs()instead. NEVER use string comparison:err.Error() == "..."orstrings.Contains(err.Error(), ...)
Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoidos.Exit,CheckErrorPrintAndExit, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios
Usego.uber.org/mock/mockgenwith//go:generatedirectives 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.
mockAWSGetterandrunAWSYamlFuncTestkeep 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, andprocessTagAwsRegioncover 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, andTestProcessSimpleTagsSkipsAWSFunctionscollectively verify:
- interface implementation of
defaultAWSGetter,- correct use of
stackInfo.AuthContext.AWS,- that the
!aws.*tags are properly routed throughprocessSimpleTags, and- that skip lists are honored for each AWS function.
The repeated
ClearAWSIdentityCachecalls 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.
TestAWSYamlFunctionConstantslocks down the public tag strings, andTestErrorWrappingcorrectly checks that the underlying error is preserved usingassert.ErrorIsinstead 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.
TestDefaultAWSGetterExistsandTestSetAWSGetterRestoreprovide good safeguards around the globalawsGetterlifecycle and the restore closure fromSetAWSGetter. This will help catch regressions if the default implementation or setter wiring changes later.
what
!aws.account_id,!aws.caller_identity_arn,!aws.caller_identity_user_id, and!aws.regionwhy
get_aws_account_id(),get_aws_caller_identity_arn(),get_aws_caller_identity_user_id(), and similar functions!execcalls to AWS CLIreferences
pkg/utils/yaml_utils.goandinternal/exec/yaml_func_utils.goSummary by CodeRabbit
New Features
Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.