produce ansible hosts inventory from yaml file python

Viewed 90

I have source of truth stored in yaml file sot-inventory.yaml

- Hostname: NY-SW1
  IP mgmt address: 10.1.1.1
  OS: IOS
  Operational status: Install
  Role of work: Switch
  Site: New_York
- Hostname: MI-SW1
  IP mgmt address: 11.1.1.1
  OS: NX-OS
  Operational status: Install
  Role of work: Switch
  Site: Maiami
- Hostname: PA-SW1
  IP mgmt address: 12.1.1.1
  OS: Arista
  Operational status: Install
  Role of work: Witch
  Site: Paris

I would like to get yaml ansible hosts inventory from file above with python script like this:

hosts.yaml

---
  new_york:
    hosts:
      ny-sw1:
        ansible_host: 10.1.1.1
        os: ios
        'role of work': switch
  maiami:
    hosts:
      mi-sw1:
        ansible_host: 11.1.1.1
        os: nxos
        'role of work': switch
  paris:
    hosts:
      pa-sw1:
        ansible_host: 12.1.1.1
        os: arista
        'role of work': switch

Could someone give an advice - which python structure or sample of scrypt may help to automate this staff?

2 Answers

Different ways

Parse YAML with PyYaml

Install with pip install pyyaml and then

import yaml

with open("sot-inventory.yaml", "r") as stream:
    try:
        print(yaml.safe_load(stream))
    except yaml.YAMLError as exc:
        print(exc)

Regex old school method

You can use a regex with multiple matching and named groups, and the print the output with the format you want

Example:

r"- Hostname: (?P<hostname>.*)\n\s*IP mgmt address: (?P<ip>.*)\n"gm

will create 3 matches with 2 groups (group hostname and group IP).

See how group works : https://docs.python.org/3/howto/regex.html#grouping

You can try your regex here : https://regex101.com/r/7Gz3JQ/2

Don't hesitate to paste your script here if you're stuck. We will help.

For example, the Ansible playbook

- hosts: localhost
  tasks:
    - set_fact:
        sot: "{{ lookup('file', 'sot-inventory.yaml')|from_yaml }}"
    - template:
        src: hosts.yaml.j2
        dest: hosts.yaml

and the template

shell> cat hosts.yaml.j2
---
{% for i in sot|groupby('Site') %}
  {{ i.0|lower }}:
    hosts:
{% for j in i.1 %}
      {{ j['Hostname']|lower }}:
         ansible_host: {{ j['IP mgmt address'] }}
         os: {{ j['OS']|lower }}
         'role of work': {{ j['Role of work']|lower }}
{% endfor %}
{% endfor %}

create the file hosts.yaml

shell> cat hosts.yaml
---
  maiami:
    hosts:
      mi-sw1:
         ansible_host: 11.1.1.1
         os: nx-os
         'role of work': switch
  new_york:
    hosts:
      ny-sw1:
         ansible_host: 10.1.1.1
         os: ios
         'role of work': switch
  paris:
    hosts:
      pa-sw1:
         ansible_host: 12.1.1.1
         os: arista
         'role of work': witch

Test it

shell> ansible-inventory -i hosts.yaml --list --yaml
all:
  children:
    maiami:
      hosts:
        mi-sw1:
          ansible_host: 11.1.1.1
          os: nx-os
          role of work: switch
    new_york:
      hosts:
        ny-sw1:
          ansible_host: 10.1.1.1
          os: ios
          role of work: switch
    paris:
      hosts:
        pa-sw1:
          ansible_host: 12.1.1.1
          os: arista
          role of work: witch
    ungrouped: {}
Related