Run bash script from template_file

3,177 views
Skip to first unread message

Thorvald Hallvardsson

unread,
May 5, 2017, 8:06:22 AM5/5/17
to Terraform
Hi everyone,

I'm trying to run a bash script from the template_file... as I found that's the only method to run commands without passing a file name. I simply want to keep my terraform file simple. 

So I'm using something like:

resource "aws_instance" "ubuntu" {
  instance_type = "t2.micro"
  key_name = "key1"
  tags {
    Name = "ubuntu"
  }
  security_groups = [ "default" ]
  user_data =  "${data.template_file.bootstrap_shell.rendered}"
}

data "template_file" "bootstrap_shell" {
  template = <<-EOF
              #!/bin/bash
              apt-get install whois
              EOF
}

And absolutely nothing happens.

it returns
#!/bin/bash
apt-get install whois

So everything is good it's just not executing the commands.

Any ideas?

Thank you.

Regards.

David Adams

unread,
May 5, 2017, 8:16:14 AM5/5/17
to terrafo...@googlegroups.com
Does it return exactly what you posted or are there leading spaces in front of the `#!/bin/bash`? If there are leading spaces, that's the problem.

Otherwise, have you checked syslog/dmesg/console output for what cloud-init is saying about running that script?

--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
 
GitHub Issues: https://github.com/hashicorp/terraform/issues
IRC: #terraform-tool on Freenode
---
You received this message because you are subscribed to the Google Groups "Terraform" group.
To unsubscribe from this group and stop receiving emails from it, send an email to terraform-tool+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/0687817c-794e-4d80-b1e3-11542885a269%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Philip Nelson

unread,
May 5, 2017, 8:17:11 AM5/5/17
to terrafo...@googlegroups.com
check out null_resource with it's local-exec option, that's what you are looking for. 

On Fri, May 5, 2017 at 7:06 AM, Thorvald Hallvardsson <thorvald.h...@gmail.com> wrote:

--

Thorvald Hallvardsson

unread,
May 5, 2017, 8:28:12 AM5/5/17
to Terraform
Yes, exactly the same thing no spaces on the front, nothing what would indicate some processing errors etc. No logs at all saying cloud init executed something I asked it to...

I don't want to use local-exec option requires SSH connection to finish the task and I don't want to use SSH session at all.

Thanks!
To unsubscribe from this group and stop receiving emails from it, send an email to terraform-too...@googlegroups.com.

Philip Nelson

unread,
May 5, 2017, 8:54:18 AM5/5/17
to terrafo...@googlegroups.com
I must be missing something here. local-exec runs on the local computer, no ssh. you appear to be wanting to run apt-get install whois, .... somewhere. What you are doing gets you a string with the commands you want in it. Uou could put somewhere, say a remote file, though you haven't used it's rendered output to do that, but nothing to execute it, that isn't it's job. 

If you want to execute that script you "wrote" in data.template_file, the simplest way would be to turn that into an instance startup script, aka userdata in aws. Terraform doesn't give you a way, other than userdata (with aws) or remote-exec, with ssh to do anything on a host. 

To unsubscribe from this group and stop receiving emails from it, send an email to terraform-tool+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/c30abfb2-29c2-4bac-8c74-ef166ae83588%40googlegroups.com.

Thorvald Hallvardsson

unread,
May 5, 2017, 9:10:47 AM5/5/17
to Terraform
Sorry, I got that wrong. Forget about the local-exec.

As you could clearly see from my first example I invoke user_data ... or rather I'm trying to invoke it from terraform. User_data is going to install whois during the bootstrap process. I can run remote-exec or even provision a file and then run remote-exec the thing is... I don't want to use SSH connection at all. By passing a data to user_data my 'script' runs from the cloud-init which doesn't require any SSH connection. It's the part of the booting process (or rather instance creation). 

As soon as I use {$file('filename')} as a user_data it works absolutely fine. But when I'm trying to operate just on a text ... it doesn't work. I want to keep it simple and I don't want to have 100 other files doing something whereas I can just stick everything into a single file and manage just a single file as I really need a simple terraform to spin up one box. That's it. Simple as that. 

Thanks.

Philip Nelson

unread,
May 5, 2017, 9:21:51 AM5/5/17
to terrafo...@googlegroups.com
gah, apologies I hadn't read your initial question closely enough. Your example looks just like working versions I have. 

To unsubscribe from this group and stop receiving emails from it, send an email to terraform-tool+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/97d7a56a-0761-43f1-903b-075464866c05%40googlegroups.com.

David Maze

unread,
May 5, 2017, 9:28:23 AM5/5/17
to Terraform
On Friday, May 5, 2017 at 9:10:47 AM UTC-4, Thorvald Hallvardsson wrote:
As you could clearly see from my first example I invoke user_data ... or rather I'm trying to invoke it from terraform. User_data is going to install whois during the bootstrap process. I can run remote-exec or even provision a file and then run remote-exec the thing is... I don't want to use SSH connection at all. By passing a data to user_data my 'script' runs from the cloud-init which doesn't require any SSH connection. It's the part of the booting process (or rather instance creation). 

Have you read through both the cloud-init documentation and source?  The documentation is pretty incomplete (which is frustrating given how important the "do things at boot time" capability is) but you can install packages using its YAML syntax; that's not necessarily better than running a shell script, but it might work better.

You can use the here-doc syntax pretty much anywhere, and if you're not interpolating anything into the template_file data you could just put it inline as the user_data field.  You can also use the template_cloudinit_multipart resource to wrap up MIME parts in a format cloud-init understands.  So I would probably write out:

user_data = "${data.template_cloudinit.multipart.user_data}"

data "template_cloudinit_multipart" "user_data" {
  part {
    content_type = "text/cloud-config"
    content = <<EOF
packages:
  - whois
EOF
  }
}

You might try adding the MIME wrapper with a `text/x-shellscript` type and seeing if it helps.  The documentation claims just having the shebang line is enough, but it's worth trying.

Thorvald Hallvardsson

unread,
May 5, 2017, 9:40:47 AM5/5/17
to Terraform
Hi Dave,

Thanks for your input. If I would only have to install a single package :). I'm afraid that road leads to a dual carriage way and I really need to execute a bash script which does stuff... not just installing a package but does a lot of configuration bits and pieces before Ansible will run and do the rest. Installing whois was just a simple example to have a PoC that bash script can be executed as a 'line by line' script. 
I'm aware of the yaml format for cloud-init just didn't try it as it's not something I want. I know I can runcmd from cloud init but the syntax is so nasty... Anyway... I will have to try to work this around somehow.

Thank you!

Philip Nelson

unread,
May 5, 2017, 10:08:07 AM5/5/17
to terrafo...@googlegroups.com
As somebody else pointed out earlier the heredoc you have does appear to put space in front of the hashbang, #!/bin/bash. In most of our configurations we use data.template_file and a file rather than a heredoc. 

data "template_file" "user_data" {
  template = "${file("./somefile.sh.tpl")}"
  ...
}

probably makes more sense for you if it is going to be a real script

--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
 
GitHub Issues: https://github.com/hashicorp/terraform/issues
IRC: #terraform-tool on Freenode
---
You received this message because you are subscribed to the Google Groups "Terraform" group.
To unsubscribe from this group and stop receiving emails from it, send an email to terraform-tool+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/95f73cb6-f81f-4b95-8f0a-5dc243c0a302%40googlegroups.com.

David Adams

unread,
May 5, 2017, 10:16:20 AM5/5/17
to terrafo...@googlegroups.com
Thorvald,
Have you tried removing the indentation from the heredoc? I think that's worth a try, as in my experience I've had various issues with heredocs in Terraform and I've given up on trying to make them line up cleanly.

On Fri, May 5, 2017 at 9:08 AM, Philip Nelson <panman...@gmail.com> wrote:
As somebody else pointed out earlier the heredoc you have does appear to put space in front of the hashbang, #!/bin/bash. In most of our configurations we use data.template_file and a file rather than a heredoc. 

data "template_file" "user_data" {
  template = "${file("./somefile.sh.tpl")}"
  ...
}

probably makes more sense for you if it is going to be a real script
Reply all
Reply to author
Forward
0 new messages