Open jtognazzi opened 1 year ago
It seems like the variables from the host
resource is not used at all anywhere, which is a major bug if true
HI, I've looked into your issue.To use ansible_host
and ansible_playbook
resources, you must manually create an inventory file with:
---
plugin: cloud.terraform.terraform_provider
This is the intended way if you wish to use those two resources together. The same goes for ansible_group
+ ansible_playbook
. This is because those are separate resources. ansible_host
and ansible_group
are used with that terraform_provider
plugin, while ansible_playbook
is not. ansible_playbook
, from provided hostname (name
) creates its own basic temporary inventory file, with (in your case):
[default]
hostname_you_provided
If you were also to define groups
in ansible_playbook
resources, for example ["example_group"]
, that temporary inventory would look like this:
[example_group]
hostname_you_provided
And tihs is the inventory your playbook uses in ansible_playbook
resource and doesn't need to be explicitly provided like you would have to for a custom inventory, such as the one you had to make manually. In this case, what you have to do is, use that manually created inventory file (let's say you named it inventory.yml
) and pass it to your playbook using extra_vars
. You terraform script would then look like this:
resource "vsphere_virtual_machine" "vm" {
# Classic provisioning from template
}
resource "ansible_host" "myserver" {
name = var.vm_hostname
groups = ["dockervms"]
variables = {
ansible_user = "vagrant"
ansible_host = vsphere_virtual_machine.vm.default_ip_address
}
}
resource "ansible_playbook" "test" {
playbook = "test.yml"
name = var.vm_hostname # <- keep this, since it's a required parameter
check_mode = true
replayable = true
# --- the code to add
extra_vars {
ansible_host = var.vm_hostname
inventory_file = "path/to/inventory.yml"
}
# ---
verbosity = 3
ignore_playbook_failure = true
}
In case you're unsure where I got the variables I put in the extra_vars
, you can find info about this here.
Hello!
I'm facing the same issue, but seems that when Ansible don't get the ansible_user var instead it defines the user as None as it follows:
PLAY [Install SQL Server Developer] ********************************************
TASK [Adicionar chave SSH] *****************************************************
task path: <path>/playbook.yml:10
File lookup using <path>/.ssh/id_rsa.pub as file
redirecting (type: modules) ansible.builtin.authorized_key to ansible.posix.authorized_key
<> ESTABLISH SSH CONNECTION FOR USER: None
<> SSH: ansible.cfg set ssh_args: (-C)(-o)(ControlMaster=auto)(-o)(ControlPersist=60s)
<> SSH: ansible_password/ansible_ssh_password not set: (-o)(KbdInteractiveAuthentication=no)(-o)(PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey)(-o)(PasswordAuthentication=no)
<> SSH: ANSIBLE_TIMEOUT/timeout set: (-o)(ConnectTimeout=10)
<> SSH: Set ssh_common_args: ()
<> SSH: Set ssh_extra_args: ()
<> SSH: found only ControlPersist; added ControlPath: (-o)(ControlPath="/home/luckjpg/.ansible/cp/ed48d91177")
<> SSH: EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/home/luckjpg/.ansible/cp/ed48d91177"' <IP>'/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
<>'', b'OpenSSH_8.9p1 Ubuntu-3, OpenSSL 3.0.2 15 Mar 2022\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no files\r\ndebug1: /etc/ssh/ssh_config line 21: Applying options for *\r\ndebug2: resolve_canonicalize: hostname <IP> is address\r\ndebug3: expanded UserKnownHostsFile \'~/.ssh/known_hosts\' -> \'/home/luckjpg/.ssh/known_hosts\'\r\ndebug3: expanded UserKnownHostsFile \'~/.ssh/known_hosts2\' -> \'/home/luckjpg/.ssh/known_hosts2\'\r\ndebug1: auto-mux: Trying existing master\r\ndebug1: Control socket "/home/luckjpg/.ansible/cp/ed48d91177" does not exist\r\ndebug3: ssh_connect_direct: entering\r\ndebug1: Connecting to <IP> port 22.\r\ndebug3: set_sock_tos: set socket 3 IP_TOS 0x10\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug1: connect to address <IP> port 22: Connection refused\r\nssh: connect to host <IP> port 22: Connection refused\r\n')
fatal: [IP]: UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: OpenSSH_8.9p1 Ubuntu-3, OpenSSL 3.0.2 15 Mar 2022\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no files\r\ndebug1: /etc/ssh/ssh_config line 21: Applying options for *\r\ndebug2: resolve_canonicalize: hostname <IP> is address\r\ndebug3: expanded UserKnownHostsFile '~/.ssh/known_hosts' -> '/home/luckjpg/.ssh/known_hosts'\r\ndebug3: expanded UserKnownHostsFile '~/.ssh/known_hosts2' -> '/home/luckjpg/.ssh/known_hosts2'\r\ndebug1: auto-mux: Trying existing master\r\ndebug1: Control socket \"/home/luckjpg/.ansible/cp/ed48d91177\" does not exist\r\ndebug3: ssh_connect_direct: entering\r\ndebug1: Connecting to <IP>] port 22.\r\ndebug3: set_sock_tos: set socket 3 IP_TOS 0x10\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug1: connect to address <IP> port 22: Connection refused\r\nssh: connect to host <IP> port 22: Connection refused",
"unreachable": true
Infos:
This is my main.tf:
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "4.72.1"
}
ansible = {
source = "ansible/ansible"
version = "1.1.0"
}
}
}
provider "google" {
credentials = file(var.google_credentials_path)
project = var.google_project
region = var.google_region
}
resource "google_compute_instance" "vm_instance" {
name = var.instance_name
machine_type = var.machine_type
zone = var.zone
tags = var.instance_tags
boot_disk {
initialize_params {
image = "ubuntu-os-cloud/ubuntu-2004-lts"
}
}
network_interface {
network = "default"
access_config {}
}
metadata = {
ssh-keys = "${var.user}:${file(var.public_key_path)}"
}
}
resource "ansible_host" "sql" {
name = google_compute_instance.vm_instance.network_interface[0].access_config[0].nat_ip
groups = ["databases"]
variables = {
ansible_user = "lucas.matheus",
ansible_ssh_private_key_file = "~/.ssh/id_rsa",
ansible_python_interpreter = "/usr/bin/python3"
}
}
resource "ansible_playbook" "playbook" {
playbook = "playbook.yml"
name = google_compute_instance.vm_instance.network_interface[0].access_config[0].nat_ip
replayable = false
verbosity = "6"
check_mode = true
ignore_playbook_failure = true
extra_vars = {
host_ip = google_compute_instance.vm_instance.network_interface[0].access_config[0].nat_ip
ansible_host = google_compute_instance.vm_instance.network_interface[0].access_config[0].nat_ip
inventory_file = "inventory.yml"
}
}
Due to this limitation and others I ended up forking this repo. If you're just looking for a way to run ansible playbook from terraform check out https://registry.terraform.io/providers/rubencosta/ansible/
Hi @anazobec, I tried https://github.com/ansible/terraform-provider-ansible/issues/37#issuecomment-1628405287 but can't seem to get it working.
Using AWS EC2 instance, S3 tf backend and ff config:
main.tf
...
resource "ansible_host" "ec2_spot_instance" {
name = module.ec2_spot_instance.public_dns
groups = ["default"]
variables = {
ansible_user = "ubuntu"
ansible_ssh_private_key_file = "path/to/key"
ansible_python_interpreter = "/usr/bin/python3"
ansible_host = module.ec2_spot_instance.public_dns
}
}
resource "ansible_playbook" "provision_instance" { playbook = "playbook.yml"
name = module.ec2_spot_instance.public_dns groups = ["default"]
check_mode = true
extra_vars = { ansible_hostname = module.ec2_spot_instance.public_dns inventory_file = "inventory.yml" }
replayable = true
verbosity = 3 ignore_playbook_failure = true }
- `inventory.yml`
```yaml
---
plugin: cloud.terraform.terraform_provider
state_file: ""
I always get this:
...
host_list declined parsing /tmp/.inventory-268034303.ini as it did not pass its verify_file() method
script declined parsing /tmp/.inventory-268034303.ini as it did not pass its verify_file() method
auto declined parsing /tmp/.inventory-268034303.ini as it did not pass its verify_file() method
yaml declined parsing /tmp/.inventory-268034303.ini as it did not pass its verify_file() method
Parsed /tmp/.inventory-268034303.ini inventory source with ini plugin
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.
PLAYBOOK: playbook.yml *********************************************************
1 plays in playbook.yml
Read vars_file 'var-file.yml'
Read vars_file 'var-file.yml'
Read vars_file 'var-file.yml'
PLAY [Build new release] *******************************************************
Read vars_file 'var-file.yml'
TASK [Gathering Facts] *********************************************************
task path: /home/bryan/test-project/playbook.yml:2
<ec2-xx-xx-xx-xx.ap-southeast-2.compute.amazonaws.com> ESTABLISH SSH CONNECTION FOR USER: None
<ec2-xx-xx-xx-xx.ap-southeast-2.compute.amazonaws.com> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/home/bryancs/.ansible/cp/5f9e4b109b"' ec2-xx-xx-xx-xx.ap-southeast-2.compute.amazonaws.com '/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
<ec2-xx-xx-xx-xx.ap-southeast-2.compute.amazonaws.com> (255, b'', b'bryan@ec2-xx-xx-xx-xx.ap-southeast-2.compute.amazonaws.com: Permission denied (publickey).\r\n')
fatal: [ec2-xx-xx-xx-xx.ap-southeast-2.compute.amazonaws.com]: UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: bryan@ec2-xx-xx-xx-xx.ap-southeast-2.compute.amazonaws.com: Permission denied (publickey).",
"unreachable": true
}
PLAY RECAP *********************************************************************
ec2-xx-xx-xx-xx.ap-southeast-2.compute.amazonaws.com : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
Also, I'm wondering why the aws
example from the example directory does not use ansible_playbook
but instead invoke ansible-playbook
directly in a script. It would be great to have an example that uses ansible_playbook
directly within terraform.
The reason the suggestion in https://github.com/ansible/terraform-provider-ansible/issues/37#issuecomment-1628405287 doesn't work is because inventory_file
is not a variable that can be set by the user, as the link to the Ansible docs in the comment states.
It seems that it is impossible to use ansible_host
and ansible_group
with ansible_playbook
, which is a major drawback to this provider. In my use case I am attempting to call a playbook from an internal collection for setting DNS records for the newly created VM, unfortunately becuase I need to set ansible_host
for the new VM (because it is not in DNS yet), that then overrides ansible_host
for all hosts, including a windows host that is set using add_host
in the collection's playbook.
I feel that this provider was released as v1 a bit too prematurely, as there are just too many pieces missing to make it useful yet.
Any updates on this one. I am also exactly stucked on this step where ansible playbook runs agains the groups but ends up with no ssh connection.
I'm probably doing something wrong, but I'm currently struggling with the following case: I'm provisionning a VM from a template with terraform, the resulting VM is not known to the DNS and the IP is assigned dynamically via DHCP.
It seems to me that the below snippet does not work and the resource ansible_playbook exits with error code 4 because it does not use the provided ansible_user ans ansible_host
and this is the result from the tfstate file ansible_playbook_stdout
For info, if I create an inventory file manually with:
and run the playbook manually with it, it works.
but if I use the inventory file created dynamically in /tmp/.inventory-xxxx, which looks like this
I have the same error than with terraform.
Is it a bug ? Or am I doing something wrong ?
PS: are the GH issues the right channel for such user issue ?