Open sean-freeman opened 1 year ago
I'm having the engineers look at this.
Just to be clear this provisioner is only for local ansible-playbook execution. TF to AAP is not supported. AAP's containerized distributed architecture requires additional consideration and logic.
Hi, in resource ansible_playbook
, name
does not refer a hostname dynamically created by ansible_host
nor do groups
refer to groups
from ansible_group
. Resource ansible_host
and group
are used separately to create a dynamic inventory which you then specify in your manually created inventory file with:
---
plugin: cloud.terraform.terraform_provider
Then you execute your ansible-playbook
by providing this inventory file.
The name
string is a hostname, which is used to create a basic temporary inventory ini file. If groups
is also provided, then that hostnmae will be added to those groups. By default, there is only one group, named default
. This temporary inventory can then be used upon executing the ansible playbook using ansible_playbook
resource. (you must also set ansible_host
to the same string as name
(if that's the host you wish your playbook to be executed on).
For example, (in ansible_playbook
resource), if you set name
to my_hostname
without also specifying groups
, the temporary inventory created would then look like this:
[default]
my_hostname
If groups
was also specified, for example ["my_group"]
, then the temporary inventory created would look like this:
[my_group]
my_hostname
If you do wish to use groups and hosts which were dynamically created by Terraform resources ansible_host
and ansible_group
, then (as explained at the top), you must create a custom inventory with the specified terraform_provider
plugin and then pass that custom inventory into ansible_playbook
resource using extra_vars
.
For example: inventory.yml
---
plugin: cloud.terraform.terraform_provider
main.tf
resource "ansible_host" "my_host" {
name = "my_host"
groups = ["my_groups"]
variables = {
# ...
}
}
resource "ansible_playbook" "my_playbook" {
# ...
extra_vars {
ansible_host = ansible_host.my_host.name
inventory_file = "path/to/inventory.yml"
}
# ...
}
Hi @anazobec, thank you for a detailed explanation of the logic. This is good for documentation purposes.
However I would still strongly recommend that name
variable for the Terraform Resource ansible_playbook
is renamed.
See below a breakdown of the logical descriptors:
ansible_host
, define 1 host with a name.ansible_group
, define 1 group with a name, and children as 1..n host names.ansible_playbook
, define 1 playbook execution, excute to target hosts; either single host as name
(but Ansible would describe this as 'host', 'host path' or 'host list') or multiple hosts as groups
.Perhaps ansible_playbook
Terraform Resource for clarity purposes should use 3 non-overlapping variables for clarity:
inventory_host_single = "my_hostname"
inventory_host_list = [ "my_hostname1" , "my_hostname2" ]
inventory_groups = [ "my_group" ]
See the documentation of binary ansible-playbook
as an example:
-i INVENTORY, --inventory INVENTORY
specify inventory host path or comma separated host list.
This is very confusing. I've read it three times and I still don't think I understand it.
If someone could help me understand the intent of this provider I would appreciate it.
In my opinion, 99% (or probably 100%) of the use-case for ansible provider is to do the following:
From what I can tell this is not what this provider is meant for? If that's correct please explain further.
Thanks!
@anazobec @tima
This needs to be addressed sooner than later. It heavily impacts initial user experience therefore limiting success, and has an exponential increase to technical debt as other code/projects or how-to guides/content are created based upon the initial releases (v1.0.0/v1.1.0).
It has been several months since this GH Issue was opened with no additional releases, this needs to be addressed urgently and trigger v1.2.0
if we use ansible_host and ansible_group resources, and then specify the inventory_file var in extra_vars under the ansible_playbook resource, what do we specify for the "name" argument which is required? the usage of this provider is not intuitive nor is the documentation sufficient on this topic
First off, thank you @anazobec for the time writing ansible_playbook, and taking the time to respond above.
Perhaps you could edit the above response or provide some clarity with an additional response?
Name is required as per the schema documentation. https://github.com/ansible/terraform-provider-ansible/blob/main/docs/resources/playbook.md
Can you please add what you would set "name =" to in this example since name is required?
resource "ansible_playbook" "my_playbook" {
# ...
extra_vars {
ansible_host = ansible_host.my_host.name
inventory_file = "path/to/inventory.yml"
}
# ...
}
In the other examples, I see simply:
name = "example"
Does this mean name within ansible_playbook resource is required but is just arbitrary text?
Is it the name terraform ties to the "playbook" construct when it writes it into the tfstate file?
For additional context, I am trying to run from GHA pipeline jobs/workflows from GH runners. So I want the GH runner to execute the ansible against the inventory generated from the cloud.terraform.terraform_provider inventory plugin.
Just need some clarity so everyone understands what "name" is here and how to use it correctly.
Thank you
I don't think that this works as described by @anazobec
The extra_vars
will be passed as -e
arguments to ansible-playbook
.
So, given this resource:
resource "ansible_playbook" "install-docker-swarm" {
extra_vars = {
inventory_file = "/src/constructs/AnsibleInventory.yaml"
ansible_hostname = "localhost"
ansible_connection = "local"
}
ignore_playbook_failure = false
name = "localhost"
playbook = "/src/constructs/DockerSwarmNodePlaybook.yaml"
}
will result in this call: ansible-playbook -e hostname=localhost -e ansible_hostname=localhost -e ansible_connection=local -e inventory_file=/src/constructs/AnsibleInventory.yaml /src/constructs/DockerSwarmNodePlaybook.yaml
Executing this doesn't use the specified inventory file. Instead, the inventory file should be specified with -i <inventory file>
, but I see no way of making the provider actually do that. In fact, it creates a temporary inventory file which is totally useless when using our own dynamic inventory file.
My feeling is that the ansible_playbook
is not meant to work together with the dynamic inventory created by ansible_host
and ansible_group
resources.
Given these limitations, I've forked this repository. My fork introduces ansible_playbook2
which automatically generates and uses an inventory file as specified above, i.e. an inventory file with the cloud.terraform inventory plugin.
I ran into this as well. It would seem this provider is best suited for defining an ansible inventory via ansible_host
/ansible_group
, but running Ansible outside of Terraform using the cloud.terraform.terraform_provider
inventory plugin.
Given this issue and others I ended up writing a provider of my own, with a number of new features -- including the ability to run Ansible as a part of the Terraform lifecycle: https://github.com/marshallford/terraform-provider-ansible.
ansible_playbook: unclear execution method
Documentation:
Clarity required:
Is
name
string referring to the Ansible Controller, the host on which the Ansible Playbook will be executed?And the
playbook
string must be the path to the YAML file on the chosen Ansible Controller?Therefore each Ansible Play
hosts:
will refer to groups of hosts which were dynamically created by the Terraform Resourcesansible_group
+ansible_host
?If so, surely
name
should be replaced byansible_controller_host
to remove all doubt?TL;DR
Clearer documentation required, and examples of different scenarios for executing Ansible Playbooks from where the Terraform execution is happening, from another host (i.e. Ansible Controller, which could be a bastion host or could be AWX etc etc).