ansible / terraform-provider-ansible

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

temporary inventory generated by provider is invalid #44

Closed ashleyghooper closed 1 year ago

ashleyghooper commented 1 year ago

Hi, I've got the provider working such that it's able to use the terraform state (in a storage bucket) as inventory. And when I run a simple playbook consisting of just a ping task it works:

ansible-playbook -i inventory.yml playbook.yml

However, when using the ansible_playbook Terraform resource, the temporary inventory file that it generates seems to be invalid. Although Terraform reports no errors (and Terraform's ansible_playbook.playbook: Creating... does not fail, but nor produces the expected playbook output), on reviewing my TF state file I see the below error:

[WARNING]:  * Failed to parse /tmp/.inventory-2565028586.ini with\nansible_collections.cloud.terraform.plugins.inventory.terraform_provider\nplugin: expected '\u003cdocument start\u003e', but found '\u003cscalar\u003e'   in\n\"/tmp/.inventory-2565028586.ini\", line 2, column 1\n[WARNING]: Unable to parse /tmp/.inventory-2565028586.ini as an inventory\nsource\n[WARNING]: No inventory was parsed, only implicit localhost is available\n[WARNING]: provided hosts list is empty, only localhost is available. Note that\nthe implicit localhost does not match 'all'

Project files

ansible.cfg

[inventory]
enable_plugins = cloud.terraform.terraform_provider  # I needed to add ", ini" here

backend.tf

terraform {
  backend "gcs" {}
}

inventory.yml

---
plugin: cloud.terraform.terraform_provider
state_file: ""  # Required to use remote (backend) state

main.tf

data "google_compute_subnetwork" "subnet" {
  provider = google
  name     = "my-subnet"
  project  = "my-project"
  region   = "us-central1"
}

# Create network adapter
resource "google_compute_address" "nic0" {
  provider     = google
  project      = "my-project"
  region       = "us-central1"
  name         = "ansible-provider-test-nic0"
  subnetwork   = data.google_compute_subnetwork.subnet.self_link
  address_type = "INTERNAL"
}

# Create vm
resource "google_compute_instance" "ansible_test" {
  name         = "ansible-provider-test"
  machine_type = "e2-small"
  project      = "my-project"
  zone         = "us-central1${-b}"

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-11"
    }
  }

  network_interface {
    subnetwork         = google_compute_address.nic0.subnetwork
    network_ip         = google_compute_address.nic0.address
    subnetwork_project = data.google_compute_subnetwork.subnet.project
  }

  service_account {
    # Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles.
    email  = "my-sa-email@my-project.iam.gserviceaccount.com"
    scopes = ["cloud-platform"]
  }
}

resource "ansible_group" "group" {
  name     = "ansible-test"
  children = ["ansible-provider-test"]
}

resource "ansible_host" "host" {
  name   = google_compute_instance.ansible_test.name
  groups = ["ansible_test"]
  variables = {
    zone = google_compute_instance.ansible_test.zone
  }
}

resource "ansible_playbook" "playbook" {
  playbook   = "playbook.yml"
  name       = google_compute_instance.ansible_test.name
  replayable = true
}

playbook.yml

---
- name: Ping
  hosts: all
  tasks:
    - ansible.builtin.ping:

Results

As mentioned, if I run the playbook directly everything works fine:

$ ansible-playbook -i inventory.yml playbook.yml

PLAY [Configure] *******************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************
ok: [ansible-provider-test]

TASK [ansible.builtin.ping] ********************************************************************************************************************************
ok: [ansible-provider-test]

PLAY RECAP *************************************************************************************************************************************************
ansible-provider-test      : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
ashleyghooper commented 1 year ago

Okay, I was able to fix my immediate issue by amending ansible.cfg to include the ini plugin as below:

[inventory]
enable_plugins = cloud.terraform.terraform_provider, ini

My next issue was this error on applying the playbook:

The plugin.(*GRPCProvider).ApplyResourceChange request was cancelled.

On checking the Terraform debug logs and the generated .ini inventory file in /tmp, I saw the host vars I defined in my ansible_host are not present. I'll log another issue for that.