Mat
Mat

Reputation: 2428

Terraform conditional provisioning

I have an issue with Terraform provisioning. When I run terraform first time I am using SSH key generated in AWS console. This key is being added to ubuntu user (it's Ubuntu 16.04 AMI). Then I run remote-exec provisioning:

provisioner "remote-exec" {
  inline = [
  "sudo apt -y update && sudo apt install -y python"
  ]
  connection {
    user = "ubuntu"
    private_key = "${file("${var.aws_default_key_name}.pem")}"
  }
}

I need python being installed so I can use Ansible later. That's the only place where I need this key, never more, because I create my own user with my private key. However, when I try to run terraform later it searches for a file file("${var.aws_default_key_name}.pem". Now I have a question how to skip this provisioning on subsequent runs?

I don't want to store SSH key in the repository.

I could create an empty file to "trick" terraform, but I don't like this solution.

Any better ideas?

Upvotes: 5

Views: 5352

Answers (2)

Alexey Melezhik
Alexey Melezhik

Reputation: 971

Sparrowform is a lightweight provisioner for Terraform based infrastructure. The benefits against other provision tools, is that stage of terraform apply which does infrastructure bootstrap is decoupled from provision stage, so you may do this:

$ terraform apply # does infra bootstrap

$ nano sparrowfile # Sparrowdo equivalent for remote-exec chunk

#!/usr/bin/env perl6

bash 'apt -y update';
package-install 'python';

$ sparrowform --ssh_user=my-user --ssh_private_key=/path/to/key  # do provision stage

Obviously you are free not to run sparrowform in subsequent runs. It does it's job (install ansible related dependencies, that is it). Then you drop your initial ssh_private_key and go with new private key ( ansible related I guess ?)

PS. disclosure - I am the tool author

Upvotes: 1

RaGe
RaGe

Reputation: 23795

Instead of doing provisioning in the aws_instance block, move it out to a null_resource block, with appropriate triggers.

resource "aws_instance" "cluster" {
  count = 3

  # ...
}

resource "null_resource" "cluster" {
  # Changes to any instance of the cluster requires re-provisioning
  triggers {
    cluster_instance_ids = "${join(",", aws_instance.cluster.*.id)}"
  }

  connection {
    host = "${element(aws_instance.cluster.*.public_ip, 0)}"
  }

  provisioner "remote-exec" {
    inline = [something]
  }
}

If your triggers do not change the null_resource provisioning will not be triggered on subsequent runs.

Upvotes: 5

Related Questions