radekg / terraform-provisioner-ansible

Ansible with Terraform 0.14.x
Apache License 2.0
572 stars 100 forks source link

How to manage host files #143

Closed andoneve closed 3 years ago

andoneve commented 4 years ago

This is a question about usage because I'm new to the provisioner.

How do I dynamically generate the hosts file? The below configuration doesn't provide me with a hosts file.

If I want to change something in my ansible 'users' role, for instance, and run only the ansible code again, how do I do that? The code below generates no 'hosts' file. Should it? It wasn't clear from the documentation. Or it's at least not working for me.

Thanks in advance!

resource "hcloud_server" "control_plane" {
  count       = 3
  name        = "${var.cluster_name}-control-plane-${count.index + 1}"
  server_type = var.control_plane_type
  image       = var.image
  location    = var.datacenter

  ssh_keys = keys(var.ssh_public_keys)

  labels = {
    "kubeone_cluster_name" = var.cluster_name
    "role"                 = "api"
  }

  provisioner "remote-exec" {
    inline = [var.install_ansible_dependencies ? var.ansible_dependencies_install_command : "sleep 0"]

    connection {
      host        = "${self.ipv4_address}"
      type        = "ssh"
      user        = "root"
      private_key = "${file(var.ssh_private_key)}"
    }
  }

  provisioner "ansible" {
    ansible_ssh_settings {
      insecure_no_strict_host_key_checking = true
    }

    plays {
      enabled = var.run_ansible_playbook
      vault_password_file = var.ansible_password_file
      groups = ["nodes"]
      hosts = [self.ipv4_address]

      playbook {
        file_path = "../ansible/node.yml"
      }

      extra_vars = {
        cluster_name = "${var.cluster_name}"
        server_name  = "${var.cluster_name}-control-plane-${count.index + 1}"
        ansible_user = "root"
      }
    }

    connection {
      host = "${self.ipv4_address}"
      type = "ssh"
      user = "root"
    }
  }
}
andoneve commented 4 years ago

@radekg any ideas? or from users?

radekg commented 4 years ago

Hi @laurawadden. Apologies for delayed answer. By design, the provisioner does not expose the hosts file. This is because the provisioner is designed for provisioning the hosts created by Terraform during the Terraform run, and only those hosts. Exposing the hosts file directly to the users potentially opens a can of worms where the complete Ansible functionality would have to be reimplemented inside of the provisioner.

For the local provisioner, at this moment in time, there is no way to get hold of the hosts file. For the remote provisioner, if remote.skip_cleanup is true, the file would be left in the temp bootstrap directory.

Having said all of that, if I understand correctly, what you would like to achieve is: provision the host with Terraform Ansible provisioner and potentially afterwards use Ansible directly to run against the already existing host?

andoneve commented 4 years ago

Thanks for replying! No worries about being late.

Having said all of that, if I understand correctly, what you would like to achieve is: provision the host with Terraform Ansible provisioner and potentially afterwards use Ansible directly to run against the already existing host?

Yes, this is exactly my use case. But I'm coming from a background using only static hosts with Ansible, so maybe using dynamic hosts is the way to go. Still looking into it.

If you have any ideas/tips on how to set this up, I would very much appreciate it :)

radekg commented 4 years ago

I think, due to the nature of how Terraform is intended to be used, this is not possible out of the box. With Terraform, the intent is to promote immutable infrastructure. To apply changes on a running host, one would have to run Ansible independent from Terraform.

What could be done here, the remote.skip_cleanup could be promoted to a top level skip_cleanup, such that it would be possible to get hold of the hosts file after the local provisioner run. That could be an intermediate solution, at least giving a chance to have the hosts file available.

Alternatively, maybe a mix of outputs with Ansible dynamic inventory operating on Terraform outputs is a good option? The dynamic inventory could use a method similar to https://github.com/radekg/terraform-state-ansible-module for constructing the inventory file from outputs.

The intermediate solution with the cleanup tweaks is easy to implement. In the long run the dynamic inventory would be definitely preferred.

radekg commented 3 years ago

Closing due to inactivity.