<p>One of the options would be to change the current directory. This simplifies the structure and lets you keep common configuration and inventory for production and staging. For example, to run the commands,</p>
<ul>
<li>either change the working directory for all commands</li>
</ul>
<pre><code>shell&gt; cd staging
shell&gt; ansible-playbook playbook.yml
shell&gt; ansible mhost1 -m ping
</code></pre>
<ul>
<li>, or change the working directory for each command</li>
</ul>
<pre><code>shell&gt; (cd staging; ansible-playbook playbook.yml)
shell&gt; (cd staging; ansible mhost1 -m ping)
</code></pre>
<p>Make the changes below</p>
<ul>
<li>Use inventory file from the current directory. Put into the ansible.cfg</li>
</ul>
<pre><code>inventory=$PWD/hosts
</code></pre>
<ul>
<li><p>Link <em>ansible.cfg</em> to both <em>production/ansible.cfg</em> and <em>staging/ansible.cfg</em></p>
</li>
<li><p>Link <em>hosts</em> to both <em>production/hosts</em> and <em>staging/hosts</em></p>
</li>
<li><p>You can rename both <em>production_playbook.yml</em> and <em>staging_playbook.yml</em> to <em>playbook.yml</em></p>
</li>
</ul>
<pre><code>├── ansible.cfg
├── hosts
├── production
│   ├── group_vars
│   │   ├── all.yml
│   │   ├── mygroup.yml
│   │   └── mygroup2.yml
│   ├── host_vars
│   │   ├── mhost1.yml
│   │   └── mhost2.yml
|   ├── ansible.cfg -&gt; ../ansible.cfg
│   ├── hosts -&gt; ../hosts
│   └── playbook.yml
└── staging
    ├── group_vars
    │   ├── all.yml
    │   ├── mygroup.yml
    │   └── mygroup2.yml
    ├── host_vars
    │   ├── mhost1.yml
    │   └── mhost2.yml
    ├── ansible.cfg -&gt; ../ansible.cfg
    ├── hosts -&gt; ../hosts
    └── playbook.yml
</code></pre>
<sup>
<p><strong>WARNING</strong></p>
<p>In a critical environment separate <em>production</em> and <em>staging</em> physically.</p>
</sup>

CC BY-SA 4.0
2022-06-15T09:50:18.093Z
Thank you @vladimir-botka, I was expecting a solution that just involves passing the correct inventory in the ad-hoc command somehow, but this works.
Tanuki
CC BY-SA 4.0
2022-06-15T04:56:30.583Z
2022-06-15T04:56:30.583Z
Vladimir Botka
<p>Given the following architecture:</p>
<pre><code>├── 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
</code></pre>
<p>The content of ansible.cfg is:</p>
<pre><code>[defaults]

inventory=hosts
</code></pre>
<p>The content of the hosts/production and hosts/staging file is the same:</p>
<pre><code>[all] 
[mygroup]
mhost1

[mygroup2]
mhost2
</code></pre>
<p>staging/group_vars/all.yml, mygroup.yml, mygroup2.yml contains all:</p>
<pre><code>ansible_user: root
</code></pre>
<p>staging/host_vars/mhost1.yml and mhost2.yml contains both (with their respective ip):</p>
<pre><code>ansible_host: xxx.xxx.xxx.xx
</code></pre>
<p>staging_playbook.yml contains:</p>
<pre><code>---
- 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:
</code></pre>
<p>In the production environment, the production_playbook.yml is similar:</p>
<pre><code>---
- 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:
</code></pre>
<p>The only differences are in production/host_vars where I have different IP addresses.</p>
<p>If I run:</p>
<p>ansible-playbook staging/staging_playbook.yml</p>
<p>or</p>
<p>ansible-playbook production/production_playbook.yml</p>
<p>it all works fine so I guess the architecture is correct.</p>
<p>Now, my question is: how can I target a specific host in a specific environment with an Ansible ad-hoc command?</p>
<p>for example:</p>
<pre><code>ansible mhost1 -i hosts/staging -m ping
</code></pre>
<p>which is not working and gives the output:</p>
<pre><code>mhost1 | UNREACHABLE! =&gt; {
    &quot;changed&quot;: false,
    &quot;msg&quot;: &quot;Failed to connect to the host via ssh: ssh: Could not resolve hostname mhost1: nodename nor servname provided, or not known&quot;,
    &quot;unreachable&quot;: true
}
</code></pre>
<p>EDIT:</p>
<p>I found out that if I move my inventory to their respective environments like:</p>
<pre><code>├── 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
</code></pre>
<p>and remove from ansible.cfg:</p>
<pre><code>inventory=hosts
</code></pre>
<p>I can execute my ad-hocs command however to run the playbook I have to specify the inventory like:</p>
<p>ansible-playbook staging/staging_playbook.yml -i staging/hosts</p>
<p>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:</p>
<pre><code>├── 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
</code></pre>
<p>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?</p>

<ansible><ansible-inventory>
Ansible: How to run ad-hoc command with multiple environnements?
Tanuki
# Ansible: How to run ad-hoc command with multiple environnements?

(Asked by: username_0 on 2022-06-14)

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?

**Tags:** ansible, ansible-inventory


---

## 1 answers

### Answer by username_1 on 2022-06-15. Score: 2 | Accepted answer

One of the options would be to change the current directory. This simplifies the structure and lets you keep common configuration and inventory for production and staging. For example, to run the commands,

either change the working directory for all commands

shell> cd staging
shell> ansible-playbook playbook.yml
shell> ansible mhost1 -m ping


, or change the working directory for each command

shell> (cd staging; ansible-playbook playbook.yml)
shell> (cd staging; ansible mhost1 -m ping)

Make the changes below

Use inventory file from the current directory. Put into the ansible.cfg

inventory=$PWD/hosts


Link ansible.cfg to both production/ansible.cfg and staging/ansible.cfg

Link hosts to both production/hosts and staging/hosts

You can rename both production_playbook.yml and staging_playbook.yml to playbook.yml


├── ansible.cfg
├── hosts
├── production
│   ├── group_vars
│   │   ├── all.yml
│   │   ├── mygroup.yml
│   │   └── mygroup2.yml
│   ├── host_vars
│   │   ├── mhost1.yml
│   │   └── mhost2.yml
|   ├── ansible.cfg -> ../ansible.cfg
│   ├── hosts -> ../hosts
│   └── playbook.yml
└── staging
    ├── group_vars
    │   ├── all.yml
    │   ├── mygroup.yml
    │   └── mygroup2.yml
    ├── host_vars
    │   ├── mhost1.yml
    │   └── mhost2.yml
    ├── ansible.cfg -> ../ansible.cfg
    ├── hosts -> ../hosts
    └── playbook.yml


WARNING
In a critical environment separate production and staging physically.

> **Comments:**
> **username_0**: Thank you @vladimir-botka, I was expecting a solution that just involves passing the correct inventory in the ad-hoc command somehow, but this works.  

---

