'Is it possible to create GCP resources using terraform without changing main.tf & varaible.tf everytime?
Shared example is for GCP VM creation. Goal here is to create 5 different VM's in a project without changing main.tf & varaible.tf everytime. I am able to successfully create a VM with the below module when i do terraform apply for first time, but to create another VM - what i am doing is, updating new VM "name" in variables.tfvars. Then when i do terraform apply, TF is deleting the existing VM which was created in the first run and then trying to create a new VM. But my aim is to have a module where i shouldn't be changing main.tf & varaible.tf everytime and have different VMs created. Is this achievable via terraform OR any possible solution please?
main.tf
resource "google_compute_instance" "default" {
project = var.project
name = var.name
machine_type = var.machine-type
zone = var.zone
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
disk_encryption_key_raw = "5DPzBhkLSfXk8kg="
}
network_interface {
subnetwork_project = var.host_project_id
subnetwork = var.subnet_name
}
metadata = {
block-project-ssh-keys = true,
enable-oslogin = true,
serial-port-enable = false
}
metadata_startup_script = "sudo apt-get update && sudo apt-get install apache2 -y && echo '<!doctype html><html><body><h1>our collaborative problem-solving ability, and the warm professionalism of our teams.!</h1></body></html>' | sudo tee /var/www/html/index.html"
// Apply the firewall rule to allow external IPs to access this instance
tags = ["http-server"]
}
variable.tf
variable "name" {
type = string
description = "Name of the instance"
}
variable "machine-type" {
type = string
description = "Machine type of the instance"
}
variable "region" {
type = string
description = "Region in which the instance has to be created"
}
variable "zone" {
type = string
description = "Zone in which the instance has to be created"
}
variable "project" {
type = string
description = "Name of the project"
}
variable "network" {
type = string
description = "Name of the subnet"
}
variable "host_project_id" {
type = string
description = "Name of the host project for network"
}
variable "subnet_name" {
type = string
description = "Name of the subnet"
}
variables.tfvars
name = "test-2"
machine-type = "n1-standard-4"
region = "us-east4"
zone = "us-east4-a"
project = "demoapp"
network = "https://www.googleapis.com/compute/v1/projects/network-dev/global/networks/vpc-1"
host_project_id = "network-dev"
subnet_name = "subnet-1"
Created a folder structure module as per below comments however facing issues during deletion.
project
|-- sa-01
| `-- variable.tfvars
|-- sa-02
| `-- variable.tfvars
|-- main.tf
`-- variables.tf
sa-01/variables.tfvars
sa_name = ["sa-test1","sa-test2","sa-test3"]
sa_dis_name = ["sa-test1","sa-test2","sa-test3"]
sa-02/variables.tfvars
sa_name = ["sa-test1","sa-test2","sa-test3"]
sa_dis_name = ["sa-test1","sa-test2","sa-test3"]
main.tf
resource "google_service_account" "sa_npe_policy" {
count = "${length(var.sa_name)}"
project = "tools-npe"
account_id = "${element(var.sa_name, count.index)}"
display_name = "${element(var.sa_dis_name, count.index)}"
}
variables.tf
variable sa_name {
type = list(string)
description = "SA Name"
}
variable sa_dis_name {
type = list(string)
description = "SA Display Name"
}
Solution 1:[1]
There are multiple approaches how you could achieve this, each with their own pros and cons...
Multiple .tfvars files and multiple .tfstatefiles
You define multiple variables files, one for each of your VMs aka environments. When applying your terraform definition, you have to specify which variable file to use and where to store the state file of this terraform config:
terraform apply -var-file=./env1/terraform.tfvars -state ./env1/env1.tfstate
I would recommend to store variables file and state file for each of your environments together in a dedicated folder. In this case you would end up with a folder structure like:
project
|-- env1
| |-- env1.tfstate
| `-- terraform.tfvars
|-- env2
| |-- env2.tfstate
| `-- terraform.tfvars
|-- env3
| |-- env3.tfstate
| `-- terraform.tfvars
|-- main.tf
`-- variables.tf
Pro
- Is close to what I understand your requirements are.
- Might be a good KISS solution for home use.
Con
- In the setup described above, you would store variable definitions of all VMs in one repository together with the module definition (your
*.tffiles). - While you could of course store tour variable files in separate repos instead of a subfolder, I guess this structure would get confusing very quickly.
Nota bene: This works well if you are using a local backend in terraform. I have not tested it with a remote backend, but I assume it would require further improvement.
Working with modules
You create a module folder just with your main.tf and variables.tf but without your variables.tfvars. The you create a separate folder for each of your VMs and each of them with an own main.tf which includes your module as follows:
module "vm" {
source = "../path/to/your/module"
# or: source = "git::https://github.com/yourorg/yourrepo//path/to/your/module"
name = "test-2"
machine-type = "n1-standard-4"
region = "us-east4"
zone = "us-east4-a"
project = "demoapp"
network = "https://www.googleapis.com/compute/v1/projects/network-dev/global/networks/vpc-1"
host_project_id = "network-dev"
subnet_name = "subnet-1"
}
Pro
- Works instantly with remote backends.
- You can separate the infra parameters for different vms/environments/projects from each other and from the module definition.
Con
- Might deviate from your intended solution.
Terraform Workspaces
In general Terraform Workspaces could also be a means to solve this, so I just want to mention them for the sake of completeness. However, I see them more suitable for use cases in which you need to manage equivalent environments in different stages (dev,test, prod) or regions etc.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | stdtom |
