Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2022-06-15T09:50:18.093Z
Answers: 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.
Answers: Tanuki
Answers: CC BY-SA 4.0
Answers: 2022-06-15T04:56:30.583Z
Answers: 2022-06-15T04:56:30.583Z
Answers: Vladimir Botka
Body: <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>
  
Tags: <ansible><ansible-inventory>
Title: Ansible: How to run ad-hoc command with multiple environnements?
UserDisplayName: Tanuki
ThreadText: # 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 @username_1-username_1, I was expecting a solution that just involves passing the correct inventory in the ad-hoc command somehow, but this works.  
  
  ---
  
  