tempaccount as
tempaccount as

Reputation: 193

edit .tf variable files using bash script

I have a big file of variables in .tf file and I want to change values using bash script .

like my file have many chunks like this and I want to change each one step by step .what will be best practice to change terraform file variables values ?

variable "azure_spoke_gateways" {
  default = {
    spoke1 = {
      name         = "name"
      size         = "size"
      vpc          = ""
    },
    spoke2 = {
      name         = "dummy"
      size         = "size2"
    }
  }
}

Upvotes: 1

Views: 2588

Answers (3)

Olesya Bolobova
Olesya Bolobova

Reputation: 1653

If you own the file and can produce it from scratch, rather than editing an existing one, you could use the following approach.

cat << EOF > main.tf.sh
variable "azure_spoke_gateways" {
  default = {
    spoke1 = {
      name    = "AZ-${region}-Spoke1-GW"
      size       = "Standard_B1ms"
      .. 
    }
  }
}
EOF
chmod +x main.tf.sh

export region=EU
. ./main.tf.sh > main.tf

Though it's limited to a certain kind of scenarios, but very simple and straightforward.

Upvotes: 3

Raman Sailopal
Raman Sailopal

Reputation: 12877

Using GNU awk:

Set the variables before proceeding

spke="spoke1" # The spoke we are concerned with
var="size" # The variable within the spoke section we are concerned with
val="size1" # The value we want to change to.
clp="azure" # Either azure or aws

Pass these variable into GNU awk with -v

awk -v spke="$spke" -v var="$var" -v val="$val" -v clp="$clp"'
      /variable/ { 
                                      cloudp=gensub(/(^variable[[:space:]]")(.*)(".*$)/,"\\2",$0) # Pull out the cloud provider
                 }
      /spoke[[:digit:]][[:space:]]=/ { 
                                        spoke=$1 # Track the spoke section
                                     } 
          spoke==spke && $1==var && cloudp ~ clp { # If spoke is equal to the passed spoke and the first space separated field is equal to the variable and clp is equal to the passed cloud provider (clp) we want to change (var)
                                        $0=gensub(/(^.*=[[:space:]]")(.*)(".*$)/,"\\1"val"\\3",$0) # Substitute the value for the value passed (val)
                                     }1' file

One liner

awk -v spke="$spke" -v var="$var" -v val="$val" -v clp="$clp" '/variable/ { cloudp=gensub(/(^variable[[:space:]]")(.*)(".*$)/,"\\2",$0) } /spoke[[:digit:]][[:space:]]=/ { spoke=$1 } spoke==spke && $1==var && cloudp ~ clp { $0=gensub(/(^.*=[[:space:]]")(.*)(".*$)/,"\\1"val"\\3",$0) }1' file

If you have a recent version of GNU awk, you can commit the changes to the file by simply adding the -i flag and so:

awk -i -v spke="$spke" -v var="$var" -v val="$val" -v clp="$clp" '/variable/ { cloudp=gensub(/(^variable[[:space:]]")(.*)(".*$)/,"\\2",$0) } /spoke[[:digit:]][[:space:]]=/ { spoke=$1 } spoke==spke && $1==var && cloudp ~ clp { $0=gensub(/(^.*=[[:space:]]")(.*)(".*$)/,"\\1"val"\\3",$0) }1' file

Otherwise:

awk -v spke="$spke" -v var="$var" -v val="$val" -v clp="$clp" '/variable/ { cloudp=gensub(/(^variable[[:space:]]")(.*)(".*$)/,"\\2",$0) } /spoke[[:digit:]][[:space:]]=/ { spoke=$1 } spoke==spke && $1==var && cloudp ~ clp { $0=gensub(/(^.*=[[:space:]]")(.*)(".*$)/,"\\1"val"\\3",$0) }1' file > file.tmp && mv -f file.tmp file 

Upvotes: 2

Brian Agnew
Brian Agnew

Reputation: 272267

If you store your variables in a Terraform JSON format, I'd recommend using something JSON-aware, such as JQ, rather than naively modifying the JSON using sed/awk etc. That way you should be able to reliably maintain your JSON format.

If you need to maintain the original format, which I understand is HCL, maybe write a script using an HCL parser, such as this one

Upvotes: 1

Related Questions