<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>

CC BY-SA 4.0
2019-10-20T07:28:04.690Z
2019-10-20T07:28:04.690Z
Bruce Becker
<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>

<amazon-web-services><amazon-ec2><terraform><cloud-init>
How to provide multiple configs for EC2 node using Terraform and cloud-init?
Alexander Nekrasov
# 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 () 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.


---

