1

I am trying to dynamically populate an inventory group called cloned_group in my current inventory . I passed the hostnames through the survey by the following names clone_machine_1, clone_machine_2, clone_machine_3. I used the ansible module add_host.The tasks were executed successfully but I did not see the expected hostnames in my inventory.

---
- name: Stage source vm
  hosts: localhost
  gather_facts: false
  vars_files: 
    - common-vars.yml
  vars: 
    localusername: testlocal

  tasks:
    - name: Add host to the cloned group from the survey list 
      ansible.builtin.add_host:
        name: "{{ item }}"
        groups: cloned_group
      with_items:
        - "{{ clone_machine_1 }}"
        - "{{ clone_machine_2 }}"
        - "{{ clone_machine_3 }}"

and the output takes the below pattern

changed: [localhost] => (item=x.y.s) => {
    "add_host": {
        "groups": [
            "cloned_group"
        ],
        "host_name": "x.y.s",
        "host_vars": {}
    },
    "ansible_loop_var": "item",
    "changed": true,
    "item": "x.y.s"
}

1 Answer 1

2

The add_host task works as expected. For example (simplified a bit), given the list of the groups

  my_groups: [cloned_group]
    - add_host:
        name: "{{ item }}"
        groups: "{{ my_groups }}"
      loop: [cm_1, cm_2, cm_3]

will create the inventory group cloned_group. Let's take a look

    - debug:
        var: groups.cloned_group

gives as expected

  groups.cloned_group:
  - cm_1
  - cm_2
  - cm_3

See the special variable group. Quoting:

A dictionary/map with all the groups in inventory and each group has the list of hosts that belong to it


Example of a complete playbook for testing

- hosts: localhost

  vars:

    my_groups: [cloned_group]

  tasks:

    - add_host:
        name: "{{ item }}"
        groups: "{{ my_groups }}"
      loop: [cm_1, cm_2, cm_3]

    - debug:
        var: groups.cloned_group

Q: "No hosts added to the cloned_group in the inventory."

A: If you by "in the inventory" mean "in the inventory file" then this is correct. No hosts will be added to an inventory file.

For example, given the below inventory file

shell> cat hosts
[test]
test_01
test_02
test_03

[test:vars]
ansible_user=admin
ansible_become=true
ansible_python_interpreter=/usr/local/bin/python3.8
ansible_perl_interpreter=/usr/local/bin/perl

If you want to update the inventory file:

  • Get the path to the file. See the special variable ansible_inventory_sources. There might be more files in the list, hence take the first one
  my_file: "{{ ansible_inventory_sources.0 }}"

gives

  my_file: /scratch/tmp1/test-024/hosts
  • Create the block with your group(s)
  my_inventory: |
    {% for group in my_groups %}
    [{{ group }}]
    {% for host in groups[group] %}
    {{ host }}
    {% endfor %}
    {% endfor %}

gives

  my_inventory: |-
    [cloned_group]
    cm_1
    cm_2
    cm_3
  • Backup the inventory file
    - command:
        cmd: "cp {{ my_file }} {{ my_file }}.backup"
        creates: "{{ my_file }}.backup"
  • Update the inventory file
    - blockinfile:
        path: "{{ my_file }}"
        block: "{{ my_inventory }}"

gives what you (probably) want

shell> cat hosts
[test]
test_01
test_02
test_03

[test:vars]
ansible_user=admin
ansible_become=true
ansible_python_interpreter=/usr/local/bin/python3.8
ansible_perl_interpreter=/usr/local/bin/perl
# BEGIN ANSIBLE MANAGED BLOCK
[cloned_group]
cm_1
cm_2
cm_3
# END ANSIBLE MANAGED BLOCK

Example of a complete playbook for testing

- hosts: localhost

  vars:

    my_file: "{{ ansible_inventory_sources.0 }}"
    my_groups: [cloned_group]
    my_inventory: |
      {% for group in my_groups %}
      [{{ group }}]
      {% for host in groups[group] %}
      {{ host }}
      {% endfor %}
      {% endfor %}

  tasks:

    - add_host:
        name: "{{ item }}"
        groups: "{{ my_groups }}"
      loop: [cm_1, cm_2, cm_3]

    - debug:
        var: groups.cloned_group

    - debug:
        var: ansible_inventory_sources
    - debug:
        var: my_file
    - debug:
        var: my_inventory

    - command:
        cmd: "cp {{ my_file }} {{ my_file }}.backup"
        creates: "{{ my_file }}.backup"

    - blockinfile:
        path: "{{ my_file }}"
        block: "{{ my_inventory }}"
4
  • it gives me the same output but still no hosts added to the cloned_group in the inventory .what does this output indicates ? Commented Jan 10 at 14:08
  • 1
    The module add_host does not change the inventory file. The module will "Add a host (and alternatively a group) to the ansible-playbook in-memory inventory". The hosts are added to the inventory "for use in later plays of the same playbook". These hosts and the groups are not in the inventory anymore after the playbook terminates. Commented Jan 10 at 14:54
  • I added an example of how to update the inventory file. Commented Jan 10 at 15:34
  • Can I run the necessary steps to clone the a vm after updating the inventory like above in the same playbook Commented Jan 16 at 8:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.