0

I'm trying to pass string parameter(s) to a Terraform map variable, but receiving error "Invalid number literal". It's not quite clear how to access keys and values in Terraform maps when passing a Jenkins parameter via terraform apply -var ...

Jenkinsfile:

pipeline {
    agent any

    parameters {
        string(name: 'IP1', defaultValue: '', description: 'Enter first IP address')
    }
    
    stages {
        stage('Git Checkout') {
            steps {
                git branch: 'branch1', credentialsId: '', url: 'http://<redacted>.git'
            }
        }
        stage('Deploy Terraform') {
            steps {
                script {
                        dir('Linux') {
                                sh """
                                terraform init
                                terraform plan
                                terraform apply -var 'vms=${params.IP1}' \
                                --auto-approve
                                """
                            }
                    } 
                }
            }
        }
    }
}

variables.tf

variable "vm_map" {
  type = map(object({
    name = string
    ip   = string
  }))
  default = {
    "first" = {
      name = "ubuntu-jenkins1"
      ip   = "172.30.100.160"
    }
    "second" = {
      name = "ubuntu-jenkins2"
      ip   = "172.30.100.161"
    }
    "third" = {
      name = "ubuntu-jenkins3"
      ip   = "172.30.100.162"
    }
  }
}
markalex
  • 8,623
  • 2
  • 7
  • 32
Mark Matlock
  • 149
  • 1
  • 10
  • Maybe this will help: https://stackoverflow.com/a/54178737/3730626 – M B Aug 05 '23 at 04:23
  • Your immediate problem: incorrect syntax of passing string variable. It should be `terraform apply -var vms="${params.IP1}"` – markalex Aug 05 '23 at 13:22
  • Additionally, I'm not sure simple string with ip will be successfully applied to variable of described type, but I'm not an SME on terraform, so you'll need to wait for more informed opinion on that. – markalex Aug 05 '23 at 13:24
  • Your JP code and TF config are both completely fine unto themselves, and so you would need to add the error message so that we could assist with the difference between your expected and actual results when the two interface. Without the necessary information in the question the best guess is that the `Map` needs to be converted to a JSON string in the JP code for the TF CLI to parse it into a `map` within the `sh` step method. – Matthew Schuchard Aug 05 '23 at 19:42
  • @MattSchuchard Here's the error output: Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now. + terraform apply -var vms=172.30.100.161 --auto-approve [31m╷[0m[0m [31m│[0m [0m[1m[31mError: [0m[0m[1mInvalid number literal[0m [31m│[0m [0m [31m│[0m [0m[0m on line 1: [31m│[0m [0m (source code not available) [31m│[0m [0m [31m│[0m [0mFailed to recognize the value of this number literal. [31m╵[0m[0m – Mark Matlock Aug 07 '23 at 12:31
  • @markalex That still resulted in this error: [31m│[0m [0m[1m[31mError: [0m[0m[1mInvalid number literal[0m [31m│[0m [0m [31m│[0m [0m[0m on line 1: [31m│[0m [0m (source code not available) [31m│[0m [0m [31m│[0m [0mFailed to recognize the value of this number literal. – Mark Matlock Aug 07 '23 at 12:33

1 Answers1

1

I figured it out! You can substitute 'vm1' for any value that identifies the first map object.

terraform apply -var vms='''{vm1: {name: "ubuntu",ip: "${params.IP1}"}}''' --auto-approve

If you also wanted to add a name string parameter for the vm name, it would look like

terraform apply -var vms='''{vm1: {name: "${params.VM_NAME1}",ip: "${params.IP1}"}}''' --auto-approve

Here's the terraform apply for multiple vm's

terraform apply -var 'vm_map={"first": {"name": "ubuntu-jenkins1", "ip": "172.30.100.160"}, \
      "second": {"name": "ubuntu-jenkins2", "ip": "172.30.100.161"}, \
      "third": {"name": "ubuntu-jenkins3", "ip": "172.30.100.162"}}' --auto-approve
rene
  • 41,474
  • 78
  • 114
  • 152
Mark Matlock
  • 149
  • 1
  • 10