Specifying Ansible inventory directory - ansible

I have two Ansible projects. One contains common roles and playbooks, the second playbooks, roles specific to a customer including the inventory.
I want to be able to run the common playbooks using the inventory from the second project
ansible-playbook -vvvv -s -K -i \
~/inventory/hosts/staging.int.openbet.com site.yml
~/inventory >
.
├── group_vars
│   └── all
├── hosts
│   └── staging.int.openbet.com
└── host_vars
└── staging.int.openbet.com
This runs against the host correctly but the host_vars aren't picked up. I was expecting the host_vars and group_vars to be relative to the inventory file but this doesn't seem to happen.
http://docs.ansible.com/intro_inventory.html#splitting-out-host-and-group-specific-data
Tip: In Ansible 1.2 or later the group_vars/ and host_vars/ directories can exist in either the playbook directory OR the inventory directory. If both paths exist, variables in the playbook directory will be loaded second.
Any help most appreciated, i'm running 1.7

You need to define the inventory file path in ansible.cfg in your first project where you will define the path of inventory from the second project.
Example:
inventory = ./_inventory/hosts.ini

Related

How to use group_vars from a relative path in Ansible

I have a requirement where i need to use the group_vars in Ansible but it does not need to be on the same path. Basically my playbooks are in SVN and whenever we want to deploy we actually checkout the latest playbook with release version and then deploy.
Playbook which actually executes the deployment has this structure -
/home/ansible/myapp/ansible-myapp-release/deploy/ansible-myapp-5.80.0-05
- bin
- roles
- myapp-main.yml
- myapp-full-deployment.yml
- myapp-config.yml
The other thing which i checkout from SVN is this which contains the configuration for my application and it does not contain any plays and it could be different for different environments like preprod, prod, test etc.
/home/ansible/myapp/ansible-myapp-release/configuration/5.80.0-05/preprod
- config
- group_vars
- preprod.yml
- inventory
- myapp
inventory myapp -
[preprod]
myapp-preprod
Now when i execute my first playbook I want to use this group_vars because that's where my configuration is in preprod.yml which will be loaded into jinja templates at run time.
How can i use this inventory and group_vars from this path OR do i need to copy these folders from here to the original playbook root directory and then execute the playbook?
Please let me know if someone can advice on this.
The documentation says the path should be relative to where your inventory is stored
https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#organizing-host-and-group-variables
Quoting from Organizing host and group variables
Ansible loads host and group variable files by searching paths relative to the inventory file or the playbook file
Below is the example of how to put the group_vars relative to inventory file
shell> tree /home/ansible/myapp/ansible-myapp-release/configuration/5.80.0-05/preprod
/home/ansible/myapp/ansible-myapp-release/configuration/5.80.0-05/preprod
└── inventory
├── group_vars
│   └── preprod.yml
└── myapp

Problem assigning variable per environment in Ansible

I'm building an AMI with packer and providing it with Ansible. The AMI needs to be build with different variables depending on the environment.Therefore I used the below structure based on this article:
├── ansible.cfg
├── bamboo-server-dev.yml
├── environments
├── group_vars
│   ├── bamboo_packer_dev.yml
│   └── bamboo_packer_prod.yml
└── roles/
├── bamboo-server/
│ └── vars/
│   ├── bamboo-dev.yml
│   ├── bamboo-prod.yml
│   └── main.yml
└── ubuntu-server/
My environment file is where I define my inventory and looks like this:
[bamboo_packer_dev]
localhost
[bamboo_packer_prod]
localhost
The group_vars/bamboo_packer_dev.yml looks like the below:
---
# Setup specific variables per environment
environment: "dev"
The playbook bamboo-server-dev.yml looks like this:
---
- hosts: bamboo_packer_dev
become: true
roles:
- ubuntu-server
- bamboo-server
And finally the roles/bamboo-server/vars/main.yml looks like this:
---
# Provide variables according to the environment
- name: provide variables
include_vars:
file: "bamboo-{{ environment }}.yml"
But when I run the playbook I get the following message:
ERROR! failed to combine variables, expected dicts but got a 'dict' and a 'AnsibleSequence':
{}
[{"name": "provide variables", "include_vars": {"file": "bamboo-{{ environment }}.yml"}}]
It seems the "environment" variable is not getting picked up. And I cannot figure it why. Can someone please suggest what might be wrong with my playbook? Or abetter way to achieve this? My Ansible version is 2.9.1 running on Mojave.
Your vars file cannot include ansible tasks, as you have done. Files in vars must be -- as ansible very clearly informed you -- dict and not list, since the keys of the vars file becomes variable names, and [] is not a variable name
Perhaps you meant to put that content into roles/bamboo-server/tasks/main.yml, which will allow you to have include_vars: as an action

Prevent Ansible Synchronize module from creating a temp directory

I am using the Ansible Synchronize module like so:
- name: Synchronization of src on the control machine to dest on the remote hosts
synchronize:
src: http-checks/
dest: "{{ datadog_path }}/conf.d/http_check.d/"
delete: yes
recursive: yes
After the playbook executes, a directory called ~core/ is created with this directory structure:
├── ansible.cfg
├── hosts
├── site.yaml
└── ~core
└── .ansible
└── tmp
└── ansible-tmp-1528320500.98-124390628295059
└── synchronize.py
Question: How do I prevent the directory from being created?
I can't find any reference to this tmp directory in the ansible docs or the rsync docs.
After looking at https://github.com/ansible/ansible/issues/21562
It seems I need to add remote_tmp in ansible.cfg:
# ansible.cfg
...
remote_tmp = $HOME/.ansible/tmp

Where should I be organizing host-specific files/templates?

I'm trying to organize my playbooks according to the Directory Layout structure. The documentation doesn't seem to have a recommendation for host-specific files/templates.
I have 2 plays for a single site
example.com-provision.yml
example.com-deploy.yml
These files are located in the root of my structure. The provisioning playbook simply includes other roles
---
- hosts: example.com
roles:
- common
- application
- database
become: true
become_method: su
become_user: root
The deployment playbook doesn't include roles, but has it's own vars and tasks sections. I have a couple template and copy tasks, and am wondering what the 'best practice' is for where to put these host-specific templates/files within this directory structure.
Right now I have them at ./roles/example.com/templates/ and ./roles/example.com/files/, but need to reference the files with their full path from my deployment playbook, like
- name: deployment | copy httpd config
template:
src: ./roles/example.com/templates/{{ host }}.conf.j2
# ...
instead of
- name: deployment | copy httpd config
template:
src: {{ host }}.conf.j2
# ...
Facing the same problem the cleanest way seems for me the following structure:
In the top-level directory (same level as playbooks) I have a files folder (and if I needed also a templates folder). In the files folder there is a folder for every host with it's own files where the folder's name is the same as the host name in inventory.
(see the structure below: myhost1 myhost2)
.
├── files
│   ├── common
│   ├── myhost1
│ ├── myhost2
|
├── inventory
│   ├── group_vars
│   └── host_vars
├── roles
│   ├── first_role
│   └── second_role
└── my_playbook.yml
Now in any role you can access the files with files modules relatively:
# ./roles/first_role/main.yml
- name: Copy any host based file
copy:
src: "{{ inventory_hostname }}/file1"
dest: /tmp
Explanation:
The magic variable inventory_hostname is to get the host, see here
The any file module (as for example copy) looks up the files directory in the respective role directory and the files directory in the same level as the calling playbook. Of course same applies to templates (but if you have different templates for the same role you should reconsider your design)
Semantically a host specific file does not belong into a role, but somewhere outside (like host_vars).

How can I ignore failures to decrypt a vaulted file?

I have two roles, one of which has a group_vars file that is vaulted, and another that is not. I would like to run the role that does not require any vaulted information, but ansible prompts me for a vault password anyway:
$ tree
├── deploy-home-secure.yml
├── deploy-home.yml
├── group_vars
│   ├── home
│   │   └── unvaulted
│   └── home-secure
│   ├── unvaulted
│   └── vaulted
├── hosts
└── roles
├── home
│   └── tasks
│   └── main.yaml
└── home-secure
└── tasks
└── main.yaml
$ ansible-playbook --version
ansible-playbook 1.8.2
configured module search path = None
$ ansible-playbook -i hosts deploy-home.yml
ERROR: A vault password must be specified to decrypt vaulttest/group_vars/home-secure/vaulted
$ ansible-playbook --vault-password-file=/dev/null -i hosts deploy-home.yml
ERROR: Decryption failed
I have something like this to solve this kind of problem (mine was not different roles, but different hosts, but I think the same principle applies):
This is the simplified file structure:
group_vars
development_vars
staging_vars
vaulted_vars
production_vars
This allows you to deploy development or staging without Ansible asking you to decrypt production_vars.
And then, the production playbook goes like this:
hosts: production
roles:
- role...
vars_files:
- vaulted_vars/production_vars
The vars_files line where you specify the path to the vaulted var is the key.
Ansible will try to load a group_vars file for any group it encounters in your inventory. If you split inventory file (hosts) into one for home group and another for home-secure then it will not try to decrypt vars it is not supposed to.
$ ansible-playbook -i hosts-home deploy-home.yml
$ ansible-playbook --ask-vault-password -i hosts-home-secure deploy-home-secure.yml
Here is another option if you don't always need your vaulted variables.
You can have a folder structure like this:
group_vars
├── all
├── prod
├── dev
│ └── vars.yml
└── dev-vault
└── vault.yml
You store vaulted variables in the '-vault' variant of that inventory.
Then your inventories might be something like the following:
dev:
[servers]
dev.bla.bla
[dev:children]
servers
dev-vault:
[servers]
dev.bla.bla
[dev:children]
servers
[dev-vault:children]
servers
So you're only saving sensitive data in the dev-vault vars, if in most cases you don't actually need passwords etc you can run playbooks without having extra options you're not really using, or storing the vault password in plaintext for convenience, etc.
So the "normal" command might be:
ansible-playbook -i dev some.yml
And the "vaulted" command could be:
ansible-playbook -i dev-vault some.yml --extra-vars="use_vault=true"
Or you could manage the "include vault variables" via tagging, including some.yml in some-vault.yml etc

Resources