Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set hostname with cloud-init and Terraform?

I am starting with Terraform. I am trying to make it set a friendly hostname, instead of the usual ip-10.10.10.10 that AWS uses. However, I haven't found how to do it.

I tried using provisioners, like this:

provisioner "local-exec" {
   command = "sudo hostnamectl set-hostname friendly.example.com"
}

But that doesn't work, the hostname is not changed.

So now, I'm trying this:

resource "aws_instance" "example" {
  ami           = "ami-XXXXXXXX"
  instance_type = "t2.micro"
  tags = {
    Name    = "friendly.example.com"
  }
  user_data = "${data.template_file.user_data.rendered}"
}

data "template_file" "user_data" {
  template = "${file("user-data.conf")}"
  vars {
    hostname = "${aws_instance.example.tags.Name}"
  }
}

And in user-data.conf I have a line to use the variable, like so:

hostname = ${hostname}

But this gives me a cycle dependency:

$ terraform apply
Error: Error asking for user input: 1 error(s) occurred:
* Cycle: aws_instance.example, data.template_file.user_data

Plus, that would mean I have to create a different user_data resource for each instance, which seems a bit like a pain. Can you not reuse them? That should be the purpose of templates, right?

I must be missing something, but I can't find the answer. Thanks.

like image 247
ilvidel Avatar asked Jan 23 '19 12:01

ilvidel


People also ask

Does Terraform use cloud-init?

Add the cloud-init script to the Terraform configuration user_data data block retrieves the contents of the add-ssh-web-app. yaml file. Then, it is passed into aws_instance. web as a user_data value to be initialized when the instance is created.

How do you give user data in Terraform?

User data inserted in the tf file Open the file that contains your terraform resource parameters, in our case it's a main.tf file. Paste the script to the resource specification and use the format shown in the example. << EOF and EOF frame the script within the user_data argument.

How do I create a private IP address in Terraform?

Terraform provisioners expose a self syntax for getting data about the resource being created. If you were just interested in the instance being created's private IP address you could use ${self. private_ip} to get at this.

Is it possible to configure AWS with Terraform?

The following procedures add Terraform as a registry resource to AWS CloudFormation and create an AWS Service Catalog product for others to use: Make sure Terraform server is available. Create AWS Identity and Access Management (AIM) roles. Install the Cloudsoft Terraform resource.


2 Answers

Using a Terraform provisioner with the local-exec block will execute it on the device from which Terraform is applying: documentation. Note specifically the line:

This invokes a process on the machine running Terraform, not on the resource. See the remote-exec provisioner to run commands on the resource.

Therefore, switching the provisioner from a local-exec to a remote-exec:

provisioner "remote-exec" {
  inline = ["sudo hostnamectl set-hostname friendly.example.com"]
}

should fix your issue with setting the hostname.

like image 181
Matt Schuchard Avatar answered Jan 03 '23 01:01

Matt Schuchard


Since you are supplying the tag to the instance as a string, why not just make that a var?

Replace the string friendly.example.com with ${var.instance-name} in your instance resource and in your data template. Then set the var:

variable "instance-name" {
    default="friendly.example.com"
}
like image 31
James Woolfenden Avatar answered Jan 03 '23 01:01

James Woolfenden