This is because Terraspace detects info like AWS account early on during the build phase, not during run/apply phase. You can use the standard AWS profile instead of the Terraform role_arn
. The AWS profile switches earlier, so the same role and AWS account will be used by both terraspace and terraform.
Note, it’s a decent effort for Terraspace to parse for terraform role_arn. Will consider PRs, though. The recommendation is to use ~/.aws
currently.
Docs: Using an IAM role in the AWS CLI - AWS Command Line Interface
Steps:
- Use aws
role_arn
in your.aws/config
and.aws/credentials
instead. - Remove the
role_arn
in your current code
RE: Custom Layering, Complexity, Sweeping Under the Rug
If you’re going down the route of custom layering and porting things as-is, it won’t get rid of code complexity. You’re trading one set of complexities for another. Instead of a complex hierarchical path structure, there’s complexity with env vars. So:
$ export AWS_PROFILE=shared-iam
$ cd teamA/qa/service-01/us-east-1/demo
$ terragrunt plan
Becomes:
$ TEAM=teamA \
TS_ENV=qa \
SERVICE=service-01 \
AWS_REGION=us-east-1 \
AWS_PROFILE=profile1 \
terraspace up demo
It’s actually worse to have to remember all the env vars.
This is the typical course for hierarchical mono-repo setup because they naturally result in more complex systems. There are simply more moving parts. To be clear, this doesn’t necessarily mean micro-repos are better. It depends. Try to find a good balance between the 2 approaches that fit your needs.
You can consider using one env var and using a boot hook to set the rest of them. Note, use version Terraspace v0.6.2. Made some changes:
- PR: Boot hooks by tongueroo · Pull Request #90 · boltops-tools/terraspace · GitHub
- Docs: Boot Hooks - Terraspace
Terraspace offers a lot of control in that you can tap into a full programming language. Example:
config/boot.rb
app = ENV['APP'] || ''
team, ts_env, service, region, profile = app.split('/').map { |x| x.blank? ? nil : x }
ENV['TEAM'] = team || 'teamA'
ENV['TS_ENV'] = ts_env || 'dev'
ENV['SERVICE'] = service || 'service1'
ENV['AWS_REGION'] = region || 'us-east-1'
ENV['AWS_PROFILE'] = profile || 'dev-profile' # or logic to handle the different profiles
This “sweeps the garbage under the rug” to mask the complexity.
APP=teamB/prod/service2/us-east-2/prod-profile terraspace build demo
Generally
Consider reviewing your current structure to see if there are opportunities to remove unnecessary or little-used parts. Sometimes removing even the littlest thing can dramatically decrease complexity.
Of course, it may not be feasible to refactor because of existing statefiles which would require a major “lift-and-shift” migration. So maybe you’ll just have to use the learnings for future setups. That’s what Terraspace’s defaults encapsulate. It’s not perfect, nothing ever is, but it should hopefully account for 80-90% uses.