I have a playbook that reads in a custom config file and creates a valid Ansible inventory in YAML then continues with other Ansible roles. The problem is when I specify the not-yet-created hosts file in my ansible.cfg, it only reads the file in the beginning so when I want to continue with my tasks, I get a "provided hosts list is empty" warning. Is there a way I can get the inventory file to "reload"? I attempted a dynamic inventory script in python, but the syntax is more complicated then the simple static YAML or INI configuration.
Use a meta task:
- meta: refresh_inventory
Docs:
https://docs.ansible.com/ansible/latest/modules/meta_module.html
Related
I get my network inventory for ansible dynamicly from the netbox plugin and I want to use this data to edit the /etc/hosts file and run a script on a special host (librenms) to add all the network devices there.
Has anyone an idea how to run a playbook only on the librenms host with the data of the netbox inventory plugin?
Here my inventory (the librenms host is not part of it)
plugin: netbox
api_endpoint: https://netbox.mydomain.com
token: abcdefghijklmopqrstuvwxyz
validate_certs: False
config_context: True
group_by:
- device_roles
query_filters:
- role: test-switch
- has_primary_ip: True
Many, many thanks in advance!
If the host you want to run the playbook on is not part of your dynamic inventory and at the same time you want to use variables defined in the dynamic inventory in a play for that host, you have to construct an "hybrid" inventory containing both your dynamic inventory ans other static entries.
This is covered in the documentation on inventories: Using multiple inventory sources.
Very basically you have two solutions:
Use two different inventories on the command line:
ansible-playbook -i dynamic_inventory -i static_inventory your_playbook.yml
Create a compound inventory with different sources in a directory. See chapter "Aggregating inventory sources with a directory" in the above documentation.
I am trying to translate some shell scripts to ansible playbooks.
In the shell scripts there are a lot of variables that are read from a separate properties file in which these variables are defined.
Is there some module or some other way that I can do this. For example,
if in the properties file I have
$WORKDIR=/opt/app defined and in the ansible playbook I want to call some module for example,
copy:
src: /tmp/app
dest: $WORKDIR/
Is there a way to do this?
Thanks
Use lookup (doc)
Example:
{{ lookup('ini', 'user.name type=properties file=user.properties') }}
user.name, property key you want to read
user.properties, property file you want to read from
Yes, in ansible the inventory is the file where we define the hostname or ips along with variables.
Whenever we execute ansible playbook we pass a file using --inventory inventory ----> this is the default way of passing an inventory file
The playbook will source this file and all the variables defined inside it can be used.
In ansible the variable substitution happens using {{ WORKDIR }}
There are other ways of passing variable to playbook.
Such as
-- include_vars
-- using roles
-- defining vars inside playbook.
-- extra vars
So from what I gather, we can use ansible.cfg to set the default inventory file that ansible looks for when running a playbook.
We can also override that inventory by using the -i parameter when running an ansible playbook via the command line.
Is there a way for me to specify a specific special inventory file inside a playbook without using the command line or changing the ansible.cfg file?
You can form a dynamic inventory from inside your playbook using add_host module.
But you will have to write some inventory files parsers to feed correct parameters to add_host.
In general this is the wrong way to go. You should have playbooks and inventories separated.
I am using ec2.py and specific tag on ec2 instances to get my hosts, the results are shown as list of IP addresses, for example:
The results from ec2.py:
"tag_test_staging": [
"10_80_20_47"
],
I define the tag in my playbook - hosts: tag_Name_test and it is run on all the instances with tag_Name_test.
Is there a way to define the hosts/tag in the hosts file under the inventory/ folder and the playbook will take the hosts from there instead of specify the ec2 tag directly on the playbook like now ?
Any suggestions would be appreciated.
You already go to the right direction.
Suppose you got dynamic inventory by ec2.py and it is tag_test_staging. So you can build inventory folder and files as below
inventory
staging
hosts
group_vars
all.yml
tag_test_staging.yml
tag_Name_test.yml
You add the variable define in each YAML file. the variable in tag_test_staging.yml will be only applied to the instance with that tag.
So now you can apply your playbook as:
ansible-playbook -i inventory/staging your_playbook.yml
There is a best practices document on how to use dynamic inventory with clouds, please take a look as well.
In my all.yml file, I have some global variables that are used throughout my project. One of these is a list of redis hosts. My inventory files look like this:
[dev_redis]
host.abc.com
[prod_redis]
host.xyz.com
So what I'd like to do in my all.yml file is something like the following:
---
global__:
app_user: root
app_group: root
redis_hosts: "{% for host in groups[{{env}}_redis] %}{{host}}:5544,{% endfor %}"
This doesn't work though -- I get an error:
FAILED! => {"failed": true, "msg": "ERROR! template error while templating string: expected token ':', got '}'"}
My questions are:
(1) Why am I getting this error?
(2) Will I be able to do this if I'm not sourcing the inventory file which contains my redis nodes? For each run of the deploy scripts, I reference which inventory files to use for that service type (this all happens within a python wrapper) -- so if I'm deploying a service other than redis, can I still access the groups from the redis inventory file? Can I pass in multiple inventory files with -i?
I see you have used loop in main yml whereas this way we define the loop when we need to access the vars in templates.
The hosts can be accessed as :
---
global__:
app_user: root
app_group: root
redis_hosts: "{{[groups['dev_redis'][0]]}}:5544"
dev can be replaced with your variable {{env}}
Answers to your question:
You are getting this error due to some syntax issue. In ansible when a variable is used it should be given in "{}" and at some places its a bare var. Depending on the usage of var if its not used correctly ansible throws this error.
No thats not possible. You need to pass the inventory/variable file from which you want to use.
Yes you can access the groups from the redis inventory file even if you are deploying any other service but that should be passed
Multiple inventory files can be passed using -i in a way that you refer a folder.
eg: ansible-playbook -i /home/ubuntu/inventory/ test.yml
And in inventory directory there can be multiple inventory files.
like /home/ubuntu/inventory/host1,/home/ubuntu/inventory/host2,/home/ubuntu/inventory/var1 etc.