How to pass arrays to AWX/Ansible Tower - ruby

I'm calling AWX template from ManageIQ. I'm passing 9 variables to the playbook (with prompt on launch active). The playbook is successfully called, and all of the vars come through. However two of the vars are supposed to be arrays. Instead they come through to AWX as strings: e.g., '["chefclient"]' instead of ["chefclient"].
I have confirmed that these vars are indeed of type array in ManageIQ before I pass them to the AWX template.
Any clue why this is happening? Do all vars get irresistibly converted to strings? How do I fix this?
Thank you!

According to the RedHat developers on Gitter.im, this is a shortcoming in the launch_ansible_method in ManageIQ. I.e., it always converts arrays to strings. We have opened an issue on GitHub to address this.

I have basically had a variable in ansible tower/awx that takes input as Text with server names as array/List. example: ["node1","node2","node3"] and once job is launched I can see the variable in the extra variables as '["node1","node2","node3"]'. I'm not sure about reason why it does that but it doesn't effect your subsequent ansible operations on that variable. Not all variables gets single quotations only when you use array/List.

I have tried to replicate this on my end with AWX installed locally. I have passed v_packages variables data as ["apache2","nginx"]. I don't see that issue now.

Related

Ansible - include one playbook into another in loop

I am new to ansible and trying to figure out how can I call one playbook from another playbook in loop. I also want to consume the output back in master playbook. Not sure if it could be possible in Ansible.
Below is a stub from other programming languages -
masterplaybook.yml - from where I want to invoke auditplaybook
for devicePair in devicePairList
output = auditdevice.yml -e "d1=devicePair.A d2=devicePair.B"
save/process output
auditdevice.yml playbook is using d1 and d2 as hosts on which it is performing auditing, running commands etc. It is performing audit on dynamic inventory passed as part of argument.
Is it possible to achieve above using Ansible? If yes, can someone point to any example?
Q: "How can I call one playbook from another playbook in the loop?"
A: It is not possible. Quoting from import_playbook
"You cannot use this action inside a play."
See the example.
FWIW. ansible-runner is able to controll playbooks withing projects similar to AWX. See example.

aws_ec2 inventory plugins: Creating host variables based on AWS tags

Is there a way to create host variables based on the (AWS) tags on an instance? (without manually listing each variable and tag under the compose section)
The idea is basically to allow the equivalent of the INI-style inventory file using tags from AWS. (With the relevant variables using a prefix to identify them)
e.g. If an instance has these tags: (The array syntax is assumed from what works in the INI-style inventory and other options are acceptable)
ansible_swapfile_size=4G
ansible_extra_packages=["htop","iotop"]
I want these variables to be configured:
swapfile_size: 4G
extra_packages:
- htop
- iotop
compose seems to be capable of doing it if I list a fixed set of variables, but that means that if a new variable are added, the inventory would need to be edited. (There does not seem to be a way to use a loop to build the keys that is set)
Is there a way to dynamically generate variables based on tags (in the inventory)?
This tries to do the same, but the solution require editing the playbook. I want the logic in the inventory - otherwise the playbook eventually ends up with a hack for every different inventory source.

How to exclude instances of the EC2 inventory in Ansible?

We have an Ansible server using EC2 dynamic inventory:
https://github.com/ansible/ansible/blob/devel/contrib/inventory/ec2.py
https://github.com/ansible/ansible/blob/devel/contrib/inventory/ec2.ini
However, with the number of instances we have, running ./ec2.py --list or ./ec2.py --refresh-cache returns a 28,000 line JSON response.
This I assume, causes it to randomly fail (returns a Python stack trace) as it only receives a partial response when sending a call to AWS, but is then fine if ran again.
Which is why I want to know if there's a way to cut this down.
I know there is a way to include specific instances by tag in the ec2.ini (i.e. # instance_filters = tag:env=staging), but with
the way our instances are tagged, is there a way to exclude
instances instead (something that would look similar to: # instance_filters = tag:name=!dev)?
is there a way to exclude instances instead
Just for completeness, I wanted to point out that the "inventory protocol" for ansible is super straightforward to implement, and they even have a JSON Schema for it.
You can see an example of the output it is expecting by running the newly included ansible-inventory script with --list to see the output it generates from one of the .ini style inventories, and then use that to emit your own:
$ printf 'somehost ansible_user=bob\n\n[some_group]\nsomehost\n' > sample
$ ansible-inventory -i ./sample --list
What I am suggesting is that you might have better luck making a custom inventory script, that does know your local business practices, rather than trying to force ec2.py into running a negation query (which, as best I can tell, it will not do).
To generate dynamic inventory, just make an executable -- as far as I know it can be in any language at all -- and then point the -i at the executable script instead of a "normal" file. Ansible will invoke that program, and operate on the JSON output as the inventory. There are several examples people have posted as gists, in all kinds of languages.
I would still love it if you would file an issue with ansible about ec2.py, because you have the situation that can make the bug report concrete for them in ways that a simple "it doesn't work for large inventories" doesn't capture. But in the mean time, writing your own inventory provider is actually less work than it sounds.
I use the option pattern_exclude in ec2.ini:
# If you want to exclude any hosts that match a certain regular expression
pattern_exclude = staging-*
and
hostname_variable = tag_Name

How to access ansible controller hostname or ip?

I need to know the hostname or IP of the machine where ansible was invoked, not the ones from the inventory.
What is the easiest way to access this? Please note that I need to use this variable in tasks that executed on various hosts.
Note that all these are not valid answers:
- ansible_hostname
- inventory_hostname
Use lookups, they are always executed on localhost.
For example: {{lookup("pipe","hostname")}}
If you use this value extensively, better to do set_fact first, otherwise lookup command will be executed every time it is referenced.
while using in set_fact: use the quotes appropriately I had issue with quotes and below worked for me
controller_host: "{{lookup('pipe','hostname')}}"

How to loop over playbook include?

(I'm currently running Ansible 2.1)
I have a playbook that gathers a list of elements and I have another playbook (that calls different hosts and whatnot) using said element as the basis for most operations. Therefore, whenever I use with_items over the playbook, it causes an error.
The loop control section of the docs say that "In 2.0 you are again able to use with_ loops and task includes (but not playbook includes) ". Is there a workaround? I really need to be able to call multiple hosts in an included playbook that runs over a set of entries. Any workarounds, ideas for such or anything are greatly appreciated!
P.S. I could technically command: ansible-playbook but I dont want to go down that rabbit hole if necessary
I think I faced same issues, and by the way, migrating to shows more than in 'item' already in use.
refering to http://docs.ansible.com/ansible/playbooks_best_practices.html , you should have an inventory (that contains all your hosts), and a master playbook (even if theorical).
A good way, instead of including playbooks, is to design roles, even if empty. Try to find a "common" role for everything that could be applied to most of your hosts.Then, include additional roles depending of usage, this will permit you to trigg on correct hosts.
You can also have roles that do nothing (meaning, nothing in 'tasks'), but that contain set of variables that can be common for two roles (you avoid then duplicate entries).

Resources