Skip to content

Commit

Permalink
Nojira ansible inventory util (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonhenrik13 authored Nov 22, 2024
1 parent 4586623 commit 090eb19
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 0 deletions.
3 changes: 3 additions & 0 deletions inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,9 @@ type InventoryListItem struct {
// Ancestors - array of ancestor nodes (incl. self).
Ancestors []string `json:"ancestors"`

// AncestorsTitles - array of ancestor nodes' titles (incl. self).
AncestorsTitles []string `json:"ancestors_titles,omitempty" bson:"ancestors_titles"`

// Attributes - device attributes.
Attributes DeviceAttributes `json:"attributes"`

Expand Down
58 changes: 58 additions & 0 deletions utils/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Collection of qbee-cli tools

## qbee-devices-ansible.py

Utility to generate ansible inventory files based on qbee-cli listing. The ansible inventory file will contain
`ProxyCommand` for `ssh` that will use the `qbee-cli` portforwarding functionality to connect to the hosts.
Group and tag names will be converted to ansible compatible group names. You will need to have a valid `qbee-cli`
session setup through `qbee-cli login` in order for this work. Also, you will need to have a valid ssh public key
distributed to the target devices (which can be done by qbee-agent SSH key distribution). Devices will be identified
with their internal qbee id.

### Inventory by groups (hiearchical)
```
qbee-cli devices list --json --limit <n> | python3 qbee-devices-ansible.py --by-groups > ansible_inventory.yml
```

### Inventory by tags (non-hierarchical)
```
qbee-cli devices list --json --limit <n> | python3 qbee-devices-ansible.py --by-tags > ansible_inventory.yml
```

### Example output:
```
example_tag_1:
hosts:
636f6e04f254592cc99a7324f2ba07f2abe3755d5f5c4fd941379c6e5094afd5:
ansible_ssh_common_args: -o StrictHostKeyChecking=no -o ProxyCommand="qbee-cli
connect -d 636f6e04f254592cc99a7324f2ba07f2abe3755d5f5c4fd941379c6e5094afd5
-t stdio:localhost:22"
example_tag_2:
hosts:
d9e6887a16f5c2a1f6e8e3a0970368d9de34f5e8685b19b261dbc438d0649dec:
ansible_ssh_common_args: -o StrictHostKeyChecking=no -o ProxyCommand="qbee-cli
connect -d d9e6887a16f5c2a1f6e8e3a0970368d9de34f5e8685b19b261dbc438d0649dec
-t stdio:localhost:22"
```

### Example: Running a test playbook on RaspberryPI

``` ansible_playbook.yml
---
- name:
gather_facts: false
hosts: example_tag_1
tasks:
- name: get motd
ansible.builtin.command: cat /etc/motd
register: mymotd
- name: debug motd
debug:
msg: "This is my motd: {{ mymotd }}"
```

```
ansible-playbook -i ansible_inventory.yml --user pi ansible_playbook.yml
```
103 changes: 103 additions & 0 deletions utils/qbee-devices-ansible.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env python

import argparse
import json
import sys
import yaml
import re

PROXY_COMMAND = (
'-o StrictHostKeyChecking=no '
'-o ProxyCommand="qbee-cli connect -d {} -t stdio:localhost:22"'
)


# create ansible inventory from qbee.io devices by tags (non-hiararchical)
def qbee_devices_ansible_by_tags():
json_output = json.loads(sys.stdin.read())
ansible_inventory = {}
for device in json_output['items']:
tags = device['tags']
if tags:
for tag in tags:
tag_label = re.sub(r'[ -]+', '_', tag)
_add_device_to_group(device, tag_label, ansible_inventory)
yaml.dump(ansible_inventory, sys.stdout)


# create ansible inventory from qbee.io devices by groups (hiararchical)
def qbee_devices_ansible_by_groups():

json_output = json.loads(sys.stdin.read())
ansible_inventory = {}

for device in json_output['items']:
if 'ancestors_titles' in device:
groups = device['ancestors_titles']
else:
groups = device['ancestors']

if len(groups) == 1:
group_label = re.sub(r'[ -]+', '_', groups[0])
_add_device_to_group(device, group_label, ansible_inventory)
continue

group_names = groups[:-1]
dataref = ansible_inventory
for group in group_names:
group_label = re.sub(r'[ -]+', '_', group)
# Last group
if group == group_names[-1]:
_add_device_to_group(device, group_label, dataref)
break

# Create group if not exists
if group_label not in dataref:
dataref[group_label] = {}
dataref[group_label]['children'] = {}

dataref = dataref[group_label]['children']

yaml.dump(ansible_inventory, sys.stdout)


# add a device to a group
def _add_device_to_group(device, label, dataref):
if label not in dataref:
dataref[label] = {}

if 'hosts' not in dataref[label]:
dataref[label]['hosts'] = {}

node_id = device['node_id']
dataref[label]['hosts'][node_id] = {
'ansible_ssh_common_args': PROXY_COMMAND.format(node_id)
}


if __name__ == "__main__":

parser = argparse.ArgumentParser(
prog='qbee-devices-ansible',
description='Convert qbee.io devices to ansible inventory')

parser.add_argument(
'--by-groups',
action='store_true',
help='Create ansible inventory by groups'
)
parser.add_argument(
'--by-tags',
action='store_true',
help='Create ansible inventory by tags'
)
args = parser.parse_args()

if args.by_groups:
sys.exit(qbee_devices_ansible_by_groups())

if args.by_tags:
sys.exit(qbee_devices_ansible_by_tags())

parser.print_help()
sys.exit(1)

0 comments on commit 090eb19

Please sign in to comment.