Answers: <p>It sounds like you want to do some configuration management upstream from the terraform.  I would suggest following a pattern of writing <a href="https://www.packer.io/docs/templates/index.html" rel="nofollow noreferrer">Packer templates</a> to build and provision the AMIs <em>before</em> running the terraform plan and apply. By judiciously applying tags to the image name, you can write a <code>data</code> statement to reliably find it.</p>
  
  <p>Your pipeline will be a bit longer (you need to add the packer build step to it), but your configuration will be more reliable and easier to maintain.</p>
  
  <p>Note: I realise that this does not answer your actual question -- it is more along the lines of "don't do what you want, do something else. My opinion is that since terraform is for provisioning infrastructure, it is something of an abuse to extend its use too far into configuration management, and it would be better to use something more suited to the job.</p>
  
Answers: CC BY-SA 4.0
Answers: 2019-10-20T07:28:04.690Z
Answers: 2019-10-20T07:28:04.690Z
Answers: Bruce Becker
Body: <p>I need to use several configs on my EC2 node using Terraform.</p>
  
  <pre><code>data "template_cloudinit_config" "puppetserver_config" {
      gzip             = true
      base64_encode    = true
      part {
          filename     = "initial.sh"
          content_type = "text/x-shellscript"
          content      = "${data.template_file.initial_config.rendered}"
      }
  
      part {
          filename     = "puppetserver_config.cfg"
          content_type = "text/cloud-config"
          content      = "${data.template_file.puppetserver_config.rendered}"
      }
  }
  data "template_file" "puppetserver_config" {
      template = "${file("${path.module}/puppetserver_config.tpl")}"
  }
  
  data "template_file" "initial_config" {
      template = "${file("${path.module}/initial_config.sh")}"
  }
  </code></pre>
  
  <p>node declaration:</p>
  
  <pre><code>resource "aws_instance" "puppetserver" {
      depends_on             = ["aws_security_group.puppetserver"]
      count                  = 1
      key_name               = "${var.key_name}"
      ami                    = "${data.aws_ami.centos7.id}"
      instance_type          = "${var.instance_type}"
      user_data              = "${data.template_cloudinit_config.puppetserver_config.rendered}"
      security_groups        = ["${aws_security_group.puppetserver.name}"]
  
      tags {
          Name = "puppet"
      }
  }
  </code></pre>
  
  <p>But when it's being bootstrapped I see only <code>initial_config</code> worked. <code>puppetserver_config</code> is ignored.
  How to make it work properly? May be I have wrong extensions for my configs? Or I just do not trigger its' launching? Thanks in advance.</p>
  
  <h1>after hours of troubleshooting i found out that there might be something wrong with encoding. <code>/var/log/cloud-init.log</code> says:</h1>
  
  <pre><code>[root@ip-172-31-29-73 ec2-user]# cat /var/log/cloud-init.log
  Aug 10 09:45:24 ip-172-31-29-73 cloud-init: Cloud-init v. 0.7.6 running 'init-local' at Thu, 10 Aug 2017 13:45:24 +0000. Up 5.79 seconds.
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: Cloud-init v. 0.7.6 running 'init' at Thu, 10 Aug 2017 13:45:31 +0000. Up 12.31 seconds.
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: ++++++++++++++++++++++++++Net device info+++++++++++++++++++++++++++
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +--------+------+--------------+---------------+-------------------+
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: | Device |  Up  |   Address    |      Mask     |     Hw-Address
  |
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +--------+------+--------------+---------------+-------------------+
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: |  lo:   | True |  127.0.0.1   |   255.0.0.0   |         .
  |
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: | eth0:  | True | 172.31.29.73 | 255.255.240.0 | 0a:99:c0:8b:b0:60 |
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +--------+------+--------------+---------------+-------------------+
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +++++++++++++++++++++++++++++++Route info++++++++++++++++++++++++++++++++
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +-------+-------------+-------------+---------------+-----------+-------+
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: | Route | Destination |   Gateway   |    Genmask    | Interface | Flags |
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +-------+-------------+-------------+---------------+-----------+-------+
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: |   0   |   0.0.0.0   | 172.31.16.1 |    0.0.0.0    |    eth0   |
   UG  |
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: |   1   | 172.31.16.0 |   0.0.0.0   | 255.255.240.0 |    eth0   |
   U   |
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +-------+-------------+-------------+---------------+-----------+-------+
  Aug 10 09:45:32 ip-172-31-29-73 cloud-init: 2017-08-10 09:45:32,367 - cc_write_files.py[WARNING]: Undecodable permissions None, assuming 420
  Aug 10 09:45:32 ip-172-31-29-73 cloud-init: 2017-08-10 09:45:32,372 - util.py[WARNING]: Running module write-files (&lt;module 'cloudinit.config.cc_write_files' from '/usr/lib/python2.7/site-packages/cloudinit/config/cc_write_files.pyc'&gt;) failed
  </code></pre>
  
  <h1>Edit:</h1>
  
  <p>I have a similar but properly working config for my backend nodes:</p>
  
  <pre><code>data "template_file" "backendnode_config" {
      template = "${file("${path.module}/backendnode_config.tpl")}"
      vars {
          puppetserver_address = "${aws_instance.puppetserver.private_ip}"
          puppet_environment   = "${var.puppet_environment}"
      }
  }
  data "template_cloudinit_config" "backendnode_config" {
      gzip             = true
      base64_encode    = true
      part {
          filename     = "initial.sh"
          content_type = "text/x-shellscript"
          content      = "${data.template_file.initial_config.rendered}"
      }
      part {
          filename     = "backendnode_config.cfg"
          content_type = "text/cloud-config"
          content      = "${data.template_file.backendnode_config.rendered}"
      }
  }
  </code></pre>
  
Tags: <amazon-web-services><amazon-ec2><terraform><cloud-init>
Title: How to provide multiple configs for EC2 node using Terraform and cloud-init?
UserDisplayName: Alexander Nekrasov
ThreadText: # How to provide multiple configs for EC2 node using Terraform and cloud-init?
  
  (Asked by: username_0 on 2017-08-10)
  
  I need to use several configs on my EC2 node using Terraform.
  
  ```
  data "template_cloudinit_config" "puppetserver_config" {
      gzip             = true
      base64_encode    = true
      part {
          filename     = "initial.sh"
          content_type = "text/x-shellscript"
          content      = "${data.template_file.initial_config.rendered}"
      }
  
      part {
          filename     = "puppetserver_config.cfg"
          content_type = "text/cloud-config"
          content      = "${data.template_file.puppetserver_config.rendered}"
      }
  }
  data "template_file" "puppetserver_config" {
      template = "${file("${path.module}/puppetserver_config.tpl")}"
  }
  
  data "template_file" "initial_config" {
      template = "${file("${path.module}/initial_config.sh")}"
  }
  
  ```
  
  node declaration:
  
  ```
  resource "aws_instance" "puppetserver" {
      depends_on             = ["aws_security_group.puppetserver"]
      count                  = 1
      key_name               = "${var.key_name}"
      ami                    = "${data.aws_ami.centos7.id}"
      instance_type          = "${var.instance_type}"
      user_data              = "${data.template_cloudinit_config.puppetserver_config.rendered}"
      security_groups        = ["${aws_security_group.puppetserver.name}"]
  
      tags {
          Name = "puppet"
      }
  }
  
  ```
  
  But when it's being bootstrapped I see only `initial_config` worked. `puppetserver_config` is ignored.
  How to make it work properly? May be I have wrong extensions for my configs? Or I just do not trigger its' launching? Thanks in advance.
  
  # after hours of troubleshooting i found out that there might be something wrong with encoding. `/var/log/cloud-init.log` says:
  
  ```
  [root@ip-172-31-29-73 ec2-user]# cat /var/log/cloud-init.log
  Aug 10 09:45:24 ip-172-31-29-73 cloud-init: Cloud-init v. 0.7.6 running 'init-local' at Thu, 10 Aug 2017 13:45:24 +0000. Up 5.79 seconds.
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: Cloud-init v. 0.7.6 running 'init' at Thu, 10 Aug 2017 13:45:31 +0000. Up 12.31 seconds.
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: ++++++++++++++++++++++++++Net device info+++++++++++++++++++++++++++
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +--------+------+--------------+---------------+-------------------+
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: | Device |  Up  |   Address    |      Mask     |     Hw-Address
  |
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +--------+------+--------------+---------------+-------------------+
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: |  lo:   | True |  127.0.0.1   |   255.0.0.0   |         .
  |
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: | eth0:  | True | 172.31.29.73 | 255.255.240.0 | 0a:99:c0:8b:b0:60 |
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +--------+------+--------------+---------------+-------------------+
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +++++++++++++++++++++++++++++++Route info++++++++++++++++++++++++++++++++
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +-------+-------------+-------------+---------------+-----------+-------+
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: | Route | Destination |   Gateway   |    Genmask    | Interface | Flags |
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +-------+-------------+-------------+---------------+-----------+-------+
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: |   0   |   0.0.0.0   | 172.31.16.1 |    0.0.0.0    |    eth0   |
   UG  |
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: |   1   | 172.31.16.0 |   0.0.0.0   | 255.255.240.0 |    eth0   |
   U   |
  Aug 10 09:45:31 ip-172-31-29-73 cloud-init: ci-info: +-------+-------------+-------------+---------------+-----------+-------+
  Aug 10 09:45:32 ip-172-31-29-73 cloud-init: 2017-08-10 09:45:32,367 - cc_write_files.py[WARNING]: Undecodable permissions None, assuming 420
  Aug 10 09:45:32 ip-172-31-29-73 cloud-init: 2017-08-10 09:45:32,372 - util.py[WARNING]: Running module write-files (<module 'cloudinit.config.cc_write_files' from '/usr/lib/python2.7/site-packages/cloudinit/config/cc_write_files.pyc'>) failed
  
  ```
  
  # Edit:
  
  I have a similar but properly working config for my backend nodes:
  
  ```
  data "template_file" "backendnode_config" {
      template = "${file("${path.module}/backendnode_config.tpl")}"
      vars {
          puppetserver_address = "${aws_instance.puppetserver.private_ip}"
          puppet_environment   = "${var.puppet_environment}"
      }
  }
  data "template_cloudinit_config" "backendnode_config" {
      gzip             = true
      base64_encode    = true
      part {
          filename     = "initial.sh"
          content_type = "text/x-shellscript"
          content      = "${data.template_file.initial_config.rendered}"
      }
      part {
          filename     = "backendnode_config.cfg"
          content_type = "text/cloud-config"
          content      = "${data.template_file.backendnode_config.rendered}"
      }
  }
  
  ```
  
  **Tags:** amazon-web-services, amazon-ec2, terraform, cloud-init
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2019-10-20. Score: 2
  
  It sounds like you want to do some configuration management upstream from the terraform. I would suggest following a pattern of writing [Packer templates](https://www.packer.io/docs/templates/index.html) to build and provision the AMIs *before* running the terraform plan and apply. By judiciously applying tags to the image name, you can write a `data` statement to reliably find it.
  
  Your pipeline will be a bit longer (you need to add the packer build step to it), but your configuration will be more reliable and easier to maintain.
  
  Note: I realise that this does not answer your actual question -- it is more along the lines of "don't do what you want, do something else. My opinion is that since terraform is for provisioning infrastructure, it is something of an abuse to extend its use too far into configuration management, and it would be better to use something more suited to the job.
  
  
  ---
  
  