How to parse a Terraform file (versions.tf) in Bash?

Viewed 1467

I'd like to parse a Terraform file named versions.tf which give provider requirements for the project. This should be in bash script. This file is formatted like this :

terraform {
  required_providers {
    archive = {
      source = "hashicorp/archive"
      version = "~> 1.3.0"
    }
    aws = {
      source = "hashicorp/aws"
      version = "~> 3.0.0"
    }
    local = {
      source = "hashicorp/local"
      version = "~> 2.0.0"
    }
    template = {
      source = "hashicorp/template"
      version = "~> 2.2.0"
    }
    random = {
      source = "hashicorp/random"
      version = "~> 3.0.1" 
    }
  }
  required_version = ">= 0.13"
}

The goal is to have 3 variables likes so in a for loop :

$name = "archive"
$source = "hashicorp/archive"
$version = "1.3.0" # we don't take care of the version constraints

The structure is almost the same for different projects we have.

I've already tried to parse it, but as I'm a noob in text parsing, nothing concrete.

I also tried to use the command terraform providers schema -json but it doesn't work while you don't have initialized the terraform script (it need to be not initialized).

As I will use the script in my corporate Jenkins pipeline, I can't access Internet and I don't have access to binaries like jq or something not "red hat" native.

Thanks you for your help !

2 Answers

This script scans for the lines with the name, which are identifiable by the third field being {, and after each of these reads the two lines with source and version, assigning to variables with the same name:

while read name _ rest
do  if [ "$rest" = "{" ]
    then    read var _ val; eval $var=$val
            read var _ val; eval $var=$val
            echo $name $source ${version#~> }
    fi
done <versions.tf

Might do what you wanted.

#!/usr/bin/env bash

while read -r line; do
  [[ $line != *'='* ]] && continue
  if [[ $line == *'= {' ]]; then
    line=${line%=*\{}
    printf '$name = "%s"\n' "${line% }"
  else
    printf '$%s\n' "${line//~> }"
  fi
done < versions.tf

If the required_version line needs to be omitted add

[[ $line == 'required_version'* ]] && continue

Below the line that has continue

Related