2

I'm trying to generate a ip list from within a yaml cloud init but keep failing.
Here is what I'd like to do

 - path: /etc/hosts
   owner: root:root
   permissions: '0644'
   defer: true
   append: true
   content: |
     %{for i in range(10,19) ~}10.0.10.${i} compute-${i-9}%{endfor ~}

But I get the error:

Call to unknown function; There is no function named "range".

I also tried to pass a list of string and do

%{for str in ${iplst} ~} ${str} %{endfor ~}

But in this case I get

Error: Incorrect attribute value type  
│  
│   on modules/nfsdbs/nfsdb.tf line 19, in data "template_file" "config":  
│   19:   vars = {  
│   20:     ...  
│   30:     iplst = "${var.ip_list}"  
│   31:     ...  
│   33:   }  
│     ├────────────────  
│     │ count.index is a number  
│     │ var.aws_access_key_id is a string  
│     │ var.aws_region is a string  
│     │ var.aws_secret_access_key is a string  
│     │ var.aws_session_token is a string  
│     │ var.hostname_prefix is a string  
│     │ var.ip_list is a list of string  
│     │ var.slurmdb_password is a string  
│     │ var.ssh_private_key is a string  
│     │ var.ssh_public_key is a string  
│     │ var.username is a string  
│  
│ Inappropriate value for attribute "vars": element "iplst": string required.  
Marko E
  • 13,362
  • 2
  • 19
  • 28
Éric
  • 419
  • 5
  • 17

1 Answers1

2

Based on the requirements in the question, this can be achieved by using the templatefile built-in function [1]. The templated file should look like this:

 - path: /etc/hosts
   owner: root:root
   permissions: '0644'
   defer: true
   append: true
   content: |
%{for i in range(10,19) ~}
     10.0.10.${i} ${format("compute-%d", i - 9)}
%{endfor ~}

Then, for demonstration purposes, using a local_file resource, this is how the output of plan looks like:

Terraform will perform the following actions:

  # local_file.cloud_init will be created
  + resource "local_file" "cloud_init" {
      + content              = <<-EOT
             - path: /etc/hosts
               owner: root:root
               permissions: '0644'
               defer: true
               append: true
               content: |
                 10.0.10.10 compute-1
                 10.0.10.11 compute-2
                 10.0.10.12 compute-3
                 10.0.10.13 compute-4
                 10.0.10.14 compute-5
                 10.0.10.15 compute-6
                 10.0.10.16 compute-7
                 10.0.10.17 compute-8
                 10.0.10.18 compute-9
        EOT
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "./cloud.init.yml"
      + id                   = (known after apply)
    }

Finally, if you want to use the local_file resource, here's the code that yields above output:

resource "local_file" "cloud_init" {
  content  = templatefile("${path.root}/cloud.init.yml.tpl", {})
  filename = "${path.module}/cloud.init.yml"
}

Of course, since the question does not show all the variables you are trying to pass to the template_file data source, the above call to the templatefile function works without adding any variables, but you would have to adjust that to use all the necessary variables.


[1] https://developer.hashicorp.com/terraform/language/functions/templatefile

Marko E
  • 13,362
  • 2
  • 19
  • 28