30

I'm a beginner in Terraform.

I have a directory which contains 2 .tf files.

Now I want to run Terraform Apply on a selected .tf file & neglect the other one.

Can I do that? If yes, how? If no, why & what is the best practice?

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
Ajinkya Bapat
  • 619
  • 1
  • 10
  • 26
  • Can you elaborate on why you want to do this? – Aidan Feldman Dec 08 '17 at 06:16
  • Just keep in mind: using the `-target` command gives in the terminal: `The -target option is not for routine use, and is provided only for exceptional situations such as recovering from errors or mistakes, or when Terraform specifically suggests to use it as part of an error message.` But i'm also trying to figure out how to generate stuff based on files vs based on directories and running the `terraform init` everytime ... or maybe i'm not familiar with the "best practice" on how to achieve it – Ricky Levi Jun 26 '22 at 10:39

7 Answers7

23

You can't selectively apply one file and then the other. Two ways of (maybe) achieving what you're going for:

  • Use the -target flag to target resource(s) in one file and then the other.
  • Put each file (or more broadly, group of resources, which might be multiple files) in separate "modules" (folders). You can then apply them separately.
Aidan Feldman
  • 5,205
  • 36
  • 46
13

You can use the terraform -target flag. Or You can have multiple terraform modules in a separate directory. And then you can terraform apply there. As an example, assume you have 3 .tf files separately. But you need to run more than just one of them at the same time. If you also, need to run them more often it's better to have a terraform module.

terraform
    |--frontend
    |  └──main.tf
    |--backend-1
    |  └──main.tf
    |--backend-2
    |  └──main.tf
    |--modules-1
    |  └──module.tf

Inside the module.tf you can define which files you need to apply.

module "frontend" {
  source = "terraform/frontend"
}

module "backend-1" {
  source = "terraform/backend-1"
} 

Then issue terraform apply staying at the module directory. And it will automatically import instances inside those paths and apply it.

Montaro
  • 9,240
  • 6
  • 29
  • 30
panther93
  • 165
  • 2
  • 8
6

Putting each terraform config file into separate directory did the job correctly. So here, is my structure

├── aws
│   └── aws_terraform.tf
├── trash
│   └── main.tf

All you have to do:

  1. enter each folder
  2. terraform init && terraform plan && terraform apply
  3. enter 'yes' to confirm terraform apply

PS: '-target' key didn't help me out.

Taras Vaskiv
  • 2,215
  • 1
  • 18
  • 17
4

Either use a --target option to specify module to run by using below command

terraform apply -target=module.<module_name>

Or another workaround is rename other terraform files with *.tf.disable extension to skip it by loading via Terraform. Currently it's Code loading *.tf files

Mahattam
  • 5,405
  • 4
  • 23
  • 33
1

No, unfortunately, Terraform doesn't have the feature to apply a selected .tf file. Terraform applies all .tf files in the same directory.

But you can apply the selected code with comment out and uncomment. For example, you have 2 .tf files "1st.tf" and "2nd.tf" in the same directory to create the resources for GCP(Google Cloud Platform):

enter image description here

Then, "1st.tf" has this code below:

provider "google" {
  credentials = file("myCredentials.json")
  project     = "myproject-113738"
  region      = "asia-northeast1"
}

resource "google_project_service" "project" {
  service = "iam.googleapis.com"
  disable_dependent_services = true
}

And "2nd.tf" has this code below:

resource "google_service_account" "service_account_1" {
  display_name = "Service Account 1"
  account_id   = "service-account-1"
}

resource "google_service_account" "service_account_2" {
  display_name = "Service Account 2"
  account_id   = "service-account-2"
}

Now, first, you want to only apply the code in "1st.tf" so you need to comment out the code in "2nd.tf":

1st.tf:

provider "google" {
  credentials = file("myCredentials.json")
  project     = "myproject-113738"
  region      = "asia-northeast1"
}

resource "google_project_service" "project" {
  service = "iam.googleapis.com"
  disable_dependent_services = true
}

2nd.tf (Comment Out):

# resource "google_service_account" "service_account_1" {
#   display_name = "Service Account 1"
#   account_id   = "service-account-1"
# }

# resource "google_service_account" "service_account_2" {
#   display_name = "Service Account 2"
#   account_id   = "service-account-2"
# }

Then, you apply:

terraform apply -auto-approve

Next, additionally, you want to apply the code in "2nd.tf" so you need to uncomment the code in "2nd.tf":

1st.tf:

provider "google" {
  credentials = file("myCredentials.json")
  project     = "myproject-113738"
  region      = "asia-northeast1"
}

resource "google_project_service" "project" {
  service = "iam.googleapis.com"
  disable_dependent_services = true
}

2nd.tf (Uncomment):

resource "google_service_account" "service_account_1" {
  display_name = "Service Account 1"
  account_id   = "service-account-1"
}

resource "google_service_account" "service_account_2" {
  display_name = "Service Account 2"
  account_id   = "service-account-2"
}

Then, you apply:

terraform apply -auto-approve

This way, you can apply the selected code with comment out and uncomment.

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
1

If you cant have terraform files in different folders like the other answers stated. You can try using my script GitHub repo for script

Which is a script that runs throughout a specific terraform file and outputs adds "-target=" to all modules names.

1

This is a filler for the data block, as others have already explained resource block

You can also target data block if you're performing a read operation.

Lets say you have two files - create.tf and read.tf

Assuming create.tf is already applied:

resource "hashicups_order" "edu" {
  items {
    coffee {
      id = 3
    }
    quantity = 3
  }
  items {
    coffee {
      id = 2
    }
    quantity = 1
  }
}

output "edu_order" {
  value = hashicups_order.edu
}

And you only want to apply read.tf:

data "hashicups_ingredients" "first_coffee" {
  coffee_id = hashicups_order.edu.items[0].coffee[0].id
}

output "first_coffee_ingredients" {
  value = data.hashicups_ingredients.first_coffee
}

You can create a plan file targeting the read only data block:

terraform plan -target=data.hashicups_ingredients.first_coffee

And similarly, apply the read operation using Terraform:

terraform apply -target=data.hashicups_ingredients.first_coffee -auto-approve

Saurabh
  • 5,176
  • 4
  • 32
  • 46