How to deploy a specific tf file (Terraform)

I have 3 .tf files in my terraform root directory:

I would like to deploy only vpc.tf running something like:

terraform apply vpc.tf #here, vpc.tf is a terraform file

But it doesn't work (I get a Go error: "zip: not a valid zip file"). If I just run

terraform apply

it will try to apply all configurations in all 3 terraform files (vpc.tf, subnets.tf and instances.tf) which is not what I want. It seems that the way to have this to work is, have a completely different folder, and run something like

terraform apply vpc/ #here, vpc/ is a folder that containers vpc.tf file

which works. The problem with this approach, is that if I have 2 or more terraform files within the vpc/ folder, I come back to the first problem all over again. It seems the solution for this is to have a specific resource in a specific folder, but this doesn't seem clean, as I can foresee that if the infrastructure grows, I will end up with several folders containing a few terraform files. So the question is:

Is there a way to "terraform apply" a specific terraform file, and ignore all the rest within a folder? Am I missing something basic about terraform?

Upvotes: 3

Views: 8738

Answers (3)

George Smith
George Smith

Reputation: 584

I read the entire discussion and honestly, it turned into an argument about proper ways to perform network segmentation. What the original question really asked was "how do I test standing up only a subset of resources, so that I don't have to bring the entire infrastructure up just to test a small piece of it?". Please, correct me if I am wrong, but that is what I feel the gist is. In the end, you will have to build up based on dependencies and throw in the rest of the pieces together, but at least you save time when testing the initial pieces that don't have any dependencies. Example: I am testing standing up a Cognito user pool that will eventually be used to authenticate requests sent to an API gateway, but I don't want to stand up that gateway while ironing out the kinks of the user pool.

Answer:

  1. Use -target as manojlds suggested (not best practice, but efficient)

  2. Put the file in a separate folder and go through the motions of init, plan, apply as ydaetskcoR suggested in his quite extensive answer (aligned with best practice)

  3. Use AWS CLI equivalent to create what you want. This brings you out of the Terraform lifecycle and allows you to perform quick-and-dirty changes to state of the resources without wearing the Terraform lifecycle straightjacket :). If, for some reason, you wish couple Terraform with the AWS CLI, use this (sorry, the code formatting is not that good here):

    resource "null_resource" "create-endpoint" { provisioner "local-exec" { command = "aws route53resolver create-resolver-endpoint --creator-request-id ${var.creator-request-id} --security-group-ids ${local.security-groups} --direction ${var.direction} --ip-addresses ${local.list-ip-template} --name ${var.endpoint-name} --tags ${var.tags} --profile ${var.aws-profile} > ${data.template_file.log_name.rendered}" } }

Upvotes: 0

ydaetskcoR
ydaetskcoR

Reputation: 56877

While you can use -target as mentioned in manojlds' answer to target specific resources to run against at each time this is meant as a bit of an escape hatch for when you have something odd happening and need to ignore changes that would be applied to other resources in that area.

This is directly mentioned in the Terraform documentation for -target:

This targeting capability is provided for exceptional circumstances, such as recovering from mistakes or working around Terraform limitations. It is not recommended to use -target for routine operations, since this can lead to undetected configuration drift and confusion about how the true state of resources relates to configuration.

Instead you should think about what things you are willing to change as a set and place .tf Terraform files that should be changed as a unit in the same directory and use the same state file for them.

If you don't want two things to be changed at the same time (eg setting up a VPC and also setting up an app that lives in that VPC or setting up test and production versions of an app) then these should be in different directories and use different state files.

This provides a nice separation of things, minimising blast radius, but still making it easier to apply out chunks of things that are related at the same time.

In your specific case I would question why you wouldn't want to apply both the VPC and subnets at the same time as this would typically just be considered part of the base networking config required for things to run in. Managing these together would normally make a lot of sense and allows you to do things like changing the name of the VPC also renaming the subnets in the same apply.

Upvotes: 3

manojlds
manojlds

Reputation: 301147

Another option, which doesn't solve the exact need you have, but is doable is resource targeting using the -target argument, ex:

terraform plan -target digitalocean_loadbalancer.public -out run.plan

https://www.terraform.io/docs/commands/plan.html#resource-targeting

Upvotes: 0

Related Questions