Given the following architecture:
├── ansible.cfg
├── hosts
│ ├── production
│ └── staging
├── production
│ ├── group_vars
│ │ ├── all.yml
│ │ ├── mygroup.yml
│ │ └── mygroup2.yml
│ ├── host_vars
│ │ ├── mhost1.yml
│ │ └── mhost2.yml
│ └── production_playbook.yml
└── staging
├── group_vars
│ ├── all.yml
│ ├── mygroup.yml
│ └── mygroup2.yml
├── host_vars
│ ├── mhost1.yml
│ └── mhost2.yml
└── staging_playbook.yml
The content of ansible.cfg is:
[defaults]
inventory=hosts
The content of the hosts/production and hosts/staging file is the same:
[all]
[mygroup]
mhost1
[mygroup2]
mhost2
staging/group_vars/all.yml, mygroup.yml, mygroup2.yml contains all:
ansible_user: root
staging/host_vars/mhost1.yml and mhost2.yml contains both (with their respective ip):
ansible_host: xxx.xxx.xxx.xx
staging_playbook.yml contains:
---
- hosts: all
tasks:
- name: ping all in staging
ping:
- hosts: mhost1
tasks:
- name: ping mhost1 in staging
ping:
- hosts: mhost2
tasks:
- name: ping mhost2 in staging
ping:
In the production environment, the production_playbook.yml is similar:
---
- hosts: all
tasks:
- name: ping all in production
ping:
- hosts: mhost1
tasks:
- name: ping mhost1 in production
ping:
- hosts: mhost2
tasks:
- name: ping mhost2 in production
ping:
The only differences are in production/host_vars where I have different IP addresses.
If I run:
ansible-playbook staging/staging_playbook.yml
or
ansible-playbook production/production_playbook.yml
it all works fine so I guess the architecture is correct.
Now, my question is: how can I target a specific host in a specific environment with an Ansible ad-hoc command?
for example:
ansible mhost1 -i hosts/staging -m ping
which is not working and gives the output:
mhost1 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname mhost1: nodename nor servname provided, or not known",
"unreachable": true
}
EDIT:
I found out that if I move my inventory to their respective environments like:
├── ansible.cfg
├── production
│ ├── group_vars
│ │ ├── all.yml
│ │ ├── mygroup.yml
│ │ └── mygroup2.yml
│ ├── host_vars
│ │ ├── mhost1.yml
│ │ └── mhost2.yml
│ ├── hosts
│ └── production_playbook.yml
└── staging
├── group_vars
│ ├── all.yml
│ ├── mygroup.yml
│ └── mygroup2.yml
├── host_vars
│ ├── mhost1.yml
│ └── mhost2.yml
├── hosts
└── staging_playbook.yml
and remove from ansible.cfg:
inventory=hosts
I can execute my ad-hocs command however to run the playbook I have to specify the inventory like:
ansible-playbook staging/staging_playbook.yml -i staging/hosts
The architecture I found allowing me to execute my playbooks per environment without having to specify an inventory while executing the command and allowing me to execute ad-hoc commands on a specific host in a specific environnement is this one:
├── ansible.cfg
├── hosts
│ ├── production
│ └── staging
├── production
│ ├── group_vars
│ │ ├── all.yml
│ │ ├── mygroup.yml
│ │ └── mygroup2.yml
│ ├── host_vars
│ │ ├── mhost1.yml
│ │ └── mhost2.yml
│ ├── hosts
│ └── production_playbook.yml
└── staging
├── group_vars
│ ├── all.yml
│ ├── mygroup.yml
│ └── mygroup2.yml
├── host_vars
│ ├── mhost1.yml
│ └── mhost2.yml
├── hosts
└── staging_playbook.yml
This seems weird since I have an inventory per environment and an inventory outside containing the same code. What is the proper way to achieve the same thing?