ansible / terraform-provider-ansible

community terraform provider for ansible
https://registry.terraform.io/providers/ansible/ansible/latest
GNU General Public License v3.0
201 stars 45 forks source link

Ansible playbook does not run on dynamic added host #94

Open stschmitt opened 9 months ago

stschmitt commented 9 months ago

Trying to get a simple sample running for a playbook.

resource "ansible_playbook" "playbook" {
  playbook   = "./ansible/playbook.yml"
  name       =  ansible_host.basic.name

  #### ignore for demo purpose
  ignore_playbook_failure = true
  replayable = true
  verbosity = 6
  check_mode = true

  extra_vars = {
    var_a = "Some variable"
    var_b = "Another variable"
  }
}

It looks like the playbook is not picking up the dynamic inventory. When I execute the playbook without the terraform , direct with ansible it works, if I trigger it through the ansible provider it seems as if the standard inventory is used.

[WARNING]: Could not match supplied host pattern, ignoring: myhosts\nansible-playbook [core 2.16.3]\n config file = None\n configured module search path = ['/Users/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']\n ansible python module location = /opt/homebrew/Cellar/ansible/9.2.0/libexec/lib/python3.12/site-packages/ansible\n ansible collection location = /Users/user/.ansible/collections:/usr/share/ansible/collections\n executable location = /opt/homebrew/bin/ansible-playbook\n python version = 3.12.2 (main, Feb 6 2024, 20:19:44) [Clang 15.0.0 (clang-1500.1.0.2.5)] (/opt/homebrew/Cellar/ansible/9.2.0/libexec/bin/python)\n jinja version = 3.1.3\n libyaml = True\nNo config file found; using defaults\nsetting up inventory plugins\nLoading collection ansible.builtin from \nhost_list declined parsing /var/folders/nl/bvl07_9s5djgkv2jc_41gj3r0000gn/T/.inventory-2409761638.ini as it did not pass its verify_file() method\nscript declined parsing /var/folders/nl/bvl07_9s5djgkv2jc_41gj3r0000gn/T/.inventory-2409761638.ini as it did not pass its verify_file() method\nauto declined parsing /var/folders/nl/bvl07_9s5djgkv2jc_41gj3r0000gn/T/.inventory-2409761638.ini as it did not pass its verify_file() method\nyaml declined parsing /var/folders/nl/bvl07_9s5djgkv2jc_41gj3r0000gn/T/.inventory-2409761638.ini as it did not pass its verify_file() method\nParsed /var/folders/nl/bvl07_9s5djgkv2jc_41gj3r0000gn/T/.inventory-2409761638.ini inventory source with ini plugin\nLoading callback plugin default of type stdout, v2.0 from /opt/homebrew/Cellar/ansible/9.2.0/libexec/lib/python3.12/site-packages/ansible/plugins/callback/default.py\nAttempting to use 'default' callback.\nSkipping callback 'default', as we already have a stdout callback.\nAttempting to use 'junit' callback.\nAttempting to use 'minimal' callback.\nSkipping callback 'minimal', as we already have a stdout callback.\nAttempting to use 'oneline' callback.\nSkipping callback 'oneline', as we already have a stdout callback.\nAttempting to use 'tree' callback.\n\nPLAYBOOK: playbook.yml *********************************************************\nPositional arguments: ./ansible/playbook.yml\nverbosity: 6\nconnection: ssh\nbecome_method: sudo\ntags: ('all',)\ncheck: True\ninventory: ('/var/folders/nl/bvl07_9s5djgkv2jc_41gj3r0000gn/T/.inventory-2409761638.ini',)\nextra_vars: ('hostname=myIP', 'var_b=Another variable', 'var_a=Some variable')\nforks: 5\n1 plays in ./ansible/playbook.yml\n\nPLAY [My first play] ***********************************************************\nskipping: no hosts matched\n\nPLAY RECAP *********************************************************************\n\n",

gravesm commented 7 months ago

Can you post the playbook you are trying to run?

nnsense commented 7 months ago

I'm experiencing the same behaviour, I suppose that - since you cannot set the inventory_file and the temp_inventory_file is a read-only attribute, you cannot point ansible to the right (dynamically created) inventory, so ansible will probably read some default inventory.

For example with this

resource "ansible_host" "host" {
  name = var.name
  variables = {
    ansible_host                    = var.ip_address
    ansible_user                    = "ubuntu"
    ansible_ssh_private_key_file    = var.ansible_ssh_private_key_file
  }
}

resource "ansible_playbook" "playbook" {
  playbook   = "ansible/playbook.yaml"
  name       = var.ip_address
}

Ansible should read the private key from the dynamic inventory, but it fails (not only the private key is wrong, but also the user, it clearly doesn't read the right inventory)

│ Warning: 
│ PLAY [all] *********************************************************************
│ 
│ TASK [Gathering Facts] *********************************************************
│ fatal: [192.168.2.101]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: root@192.168.2.101: Permission denied (publickey).", "unreachable": true}
│ 
│ PLAY RECAP *********************************************************************
│ 192.168.2.101              : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0  
stschmitt commented 7 months ago

I need to rebuild my environment, but it is like shown above

gravesm commented 7 months ago

If there are additional connection variables needed, you will have to set those on the playbook resource.

mando-intelcom commented 7 months ago

I need those variables to apply to the targeted host only, applied to the playbook they mess up with any connection to localhost. There's no example on how to integrate ansible_host or ansible_groups with ansible_playbook. Documentation is lacking and the options are not intuitive.

dasra commented 3 months ago

any updates on this issue

mando-intelcom commented 3 months ago

Ended up using provisioner local-exec in a terraform_data resource block for both the dynamic inventory creation and the playbook.

dasra commented 3 months ago

did you use something like below or if you have any different config, could you please suggest. Thank you

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"

  tags = {
    Name = "TerraformExample"
  }
}

# Create a dynamic inventory file using the local-exec provisioner
data "local_file" "inventory" {
  content  = <<EOF
[webserver]
${aws_instance.example.public_ip} ansible_user=ubuntu ansible_ssh_private_key_file=/path/to/private/key
EOF
  filename = "${path.module}/inventory.ini"
}

# Run the Ansible playbook using local-exec provisioner
resource "null_resource" "run_playbook" {
  provisioner "local-exec" {
    command = "ansible-playbook -i ${data.local_file.inventory.filename} /path/to/playbook.yml"
  }

  depends_on = [aws_instance.example, data.local_file.inventory]
}
mando-intelcom commented 3 months ago

I use dynamic inventory. And I think null_resource has been deprecated in favor of terraform_data:

resource "terraform_data" "inventory" {
  provisioner "local-exec" {
    command     = "ansible-inventory -i ../inventory/rel.aws_ec2.yml --graph"
    working_dir = "${path.module}/.."
  }
  triggers_replace = {
    always_run = "${timestamp()}"
  }
}

resource "terraform_data" "playbook" {
  provisioner "local-exec" {
    command     = "ansible-playbook -i inventory/rel.aws_ec2.yml configure-ec2.yml -e target=$GROUPS --private-key $PRIVATE_KEY"
    working_dir = "${path.module}/.."
    environment = {
      PRIVATE_KEY = "${abspath(path.root)}/${var.private_key}"
      GROUPS      = "${var.groups}"
    }
  }
  triggers_replace = {
    always_run = "${timestamp()}"
  }
  depends_on = [terraform_data.inventory]
}
ioxam commented 3 months ago

Do I understand correctly that it is currently impossible to use "ansible_playbook" resource with aws_ec2 plugin?

Its-Alex commented 1 month ago

@mando-intelcom What do you think about adding an example in the repository from a MR?