How to use Terraform include / exclude with Makefile
Posted onInDevOps
,
SRE
,
TerraformViews: Disqus: Symbols count in article: 4.1kReading time ≈4 mins.
Background
When using make plan command, if there’re too many resources need to be applied, together with other unrelated resources that we don’t want to touch, then we need to use Terraform resource targeting:
1
PLAN_OPTIONS="-target="A" -target="B"... -target="N"" make plan
But Terraform doesn’t support –exclude feature for the target at the moment (and we don’t want to copy & paste over 50 times for the targets), that’s why need to find a way to implement exclude / include features within Makefile.
How-to
make plan
Run make plan to show pending changes, also generate current.plan that we use later to filter targets.
filter targets
Then pick the resources you want by using [INCLUDE | EXCLUDE] which support POSIX Extended Regular Expressions (ERE)
E.g.
1 2 3 4 5 6 7 8 9 10 11
# use include to specify only the targets you want to apply $ make plan_include INCLUDE='mark3a' # output terraform plan -out current.plan -target="aws_alb_target_group_attachment.routers-mark3a"-target="module.routers-mark3a.aws_instance.main"-target="module.routers-mark3a.aws_route53_record.main_instance" # exclude the targets $ make plan_exclude EXCLUDE='aws_security_group|mark3b' # output terraform plan -out current.plan -target="aws_alb_target_group_attachment.routers-mark3a"-target="aws_alb_target_group_attachment.routers-mark3c"-target="module.asg_databus_production.aws_autoscaling_group.main"-target="module.asg_router_production.aws_autoscaling_group.main"-target="module.asg_router_production.aws_launch_configuration.main"-target="module.routers-mark3a.aws_instance.main"-target="module.routers-mark3a.aws_route53_record.main_instance"-target="module.routers-mark3c.aws_instance.main"-target="module.routers-mark3c.aws_route53_record.main_instance"
make apply
Finally can use make apply to apply the changes based on new current.plan
Explain
Show the output generated by make plan, then process the output (e.g. clear ANSI color / match resource names after empty line etc.) to generate the final format (e.g. -target=”A” -target=”B” -target=”C” …)
and then the macro PLAN_OPTIONS_EXCLUDE / PLAN_OPTIONS_INCLUDE can be triggered by plan_exclude / plan_include in Makefile:
1 2 3 4 5
plan_exclude: terraform plan -out current.plan $(strip $(call PLAN_OPTIONS_EXCLUDE,$(EXCLUDE)))
plan_include: terraform plan -out current.plan $(strip $(call PLAN_OPTIONS_INCLUDE,$(INCLUDE)))
Gist
Final gist could be find here
Limitations
Unfortunately, when the target list becomes very long (e.g. 49) You start to see Too many command line arguments. Configuration path expected, so this workaround is not enough…
Anyway Inverse targeting is becoming more and more important / necessary in huge terraform plans with lots of modules managed by different teams, so hope there’s an official solution for that in the new future.