aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbinary <me@rgoncalves.se>2021-02-08 14:30:33 +0100
committerbinary <me@rgoncalves.se>2021-02-08 14:30:33 +0100
commitba54cc5fc68926597b308d585d812160d8f5938f (patch)
tree6cbd42a7d4f11339f576504a83434cad0c3212c3
parent027606884d613f0daf0bd0e876bfba22a4954fa3 (diff)
downloadinfrastructure-ba54cc5fc68926597b308d585d812160d8f5938f.tar.gz
Implement dynamic inventory based on files only
-rwxr-xr-xdynamic.py194
-rw-r--r--group_vars/bsd.yml4
-rw-r--r--group_vars/linux.yml5
-rw-r--r--host_vars/dc0.yml3
-rw-r--r--host_vars/emb0.yml3
-rw-r--r--host_vars/guest0.yml1
-rw-r--r--host_vars/guest1.yml1
-rw-r--r--host_vars/guest2.yml1
-rw-r--r--host_vars/st0cld0.yml3
-rw-r--r--host_vars/st0dev0.yml2
-rw-r--r--host_vars/st0gme0.yml2
-rw-r--r--host_vars/st0gme1.yml2
-rw-r--r--host_vars/st0sbx0.yml2
-rw-r--r--host_vars/st0sbx1.yml2
-rw-r--r--host_vars/stack0.yml10
-rw-r--r--host_vars/ws-bentonite.yml1
-rw-r--r--host_vars/ws-think01.yml1
-rw-r--r--host_vars/ws-xps01.yml1
18 files changed, 223 insertions, 15 deletions
diff --git a/dynamic.py b/dynamic.py
new file mode 100755
index 0000000..78ebdb2
--- /dev/null
+++ b/dynamic.py
@@ -0,0 +1,194 @@
+#!/usr/bin/env python3
+#
+# This is a dynamic inventory script for Ansible at
+# rgoncalves.se infrastructure.
+#
+# Only groups_vars/ and host_vars/ directory are used for setting up devices
+# and nodes.
+# > Files, files, files, ... only files, everything files!
+#
+# The main goal here is to allow flexible code reviews and edits, POSIX
+# compliant actions over files, and using "less is more" moto. Moreover, each
+# host/group/node is individually track on version control.
+
+import os
+import yaml
+import logging
+import json
+
+from typing import Final
+from optparse import OptionParser
+
+
+HOST_DIR: Final = "./host_vars"
+GROUP_DIR: Final = "./group_vars"
+
+
+class AnsibleInput:
+ """
+ AnsibleInput class mixin.
+ Meta methods and inits for reading and processing yaml files.
+ """
+
+ data = None
+ name = None
+
+ def __init__(self, filepath):
+ with open(filepath) as file:
+ self.data = yaml.load(file, Loader=yaml.FullLoader)
+ self.name = os.path.splitext(os.path.basename(filepath))[0]
+
+
+def pprint(data):
+ """
+ Json pretty print for ansible hosts/groups or whatever output we get.
+ """
+
+ try:
+ print(json.dumps(data, indent=4, sort_keys=True))
+ except TypeError:
+ print(data)
+
+
+def create_nodes(directory):
+ """
+ Build-up and ansible node (Host or Group),
+ then return the full type list.
+ """
+
+ nodes = {}
+ for file in os.scandir(directory):
+ node = AnsibleInput(file.path)
+ nodes[node.name] = node
+ return nodes
+
+
+def get_hostvars(host):
+ """
+ Retrieve and build dynamic variables for a specific host.
+ """
+
+ data = host.data
+ if "ansible_host" not in host.data:
+ data["ansible_host"] = host.name
+ return data
+
+
+def get_subgroups(groups, og):
+ """
+ Get and return all children of a specific group, in a given subset.
+ """
+
+ # specific return for group "all"
+ if og.name in "all":
+ groups = list(groups.keys())
+ groups.remove("all")
+ return groups
+
+ # usual behavior
+ valid_groups = []
+ if "_groups" not in og.data:
+ logging.warning(f"group { og.name } does not have any _groups var!")
+ else:
+ for group in og.data["_groups"]:
+ if group in groups:
+ valid_groups.append(group)
+ return valid_groups
+
+
+def get_meta(hosts):
+ """
+ For performance reasons, return all the hosts in a meta dict.
+ """
+
+ _meta = {}
+ _meta["hostvars"] = {}
+ for hostname, host in hosts.items():
+ _meta["hostvars"][hostname] = get_hostvars(host)
+ # _meta["hostvars"][hostname] = host.data
+ return "{}"
+ return _meta
+
+
+def get_list(hosts, groups):
+ """
+ Return list of groups with all hosts.
+ """
+
+ _list = {}
+ _list["_meta"] = get_meta(hosts)
+ # init group array
+ for groupname, group in groups.items():
+ _list[groupname] = {}
+ _list[groupname]["hosts"] = []
+ _list[groupname]["vars"] = {}
+ _list[groupname]["children"] = get_subgroups(groups, group)
+ # append each hosts to their corresponding groups
+ for hostname, host in hosts.items():
+ _list["all"]["hosts"].append(hostname)
+ if "_groups" not in host.data:
+ logging.info(f"no _groups data found for host { hostname }")
+ continue
+ # retrieve _groups variables and force conversion to list
+ cleangr = host.data["_groups"]
+ cleangr = [cleangr] if isinstance(cleangr, str) else cleangr
+ for group in cleangr:
+ # skip group assignement on non-existence!
+ logging.info(f"searching for group : { group }")
+ if group not in groups:
+ logging.error(f"group { group } does not exist!")
+ continue
+ _list[group]["hosts"].append(hostname)
+ return _list
+
+
+def main():
+ """
+ Main entry.
+ """
+
+ # logging config
+ logging.basicConfig(level=logging.INFO)
+ logging.disable()
+
+ # parse cli arguments
+ parser = OptionParser()
+ parser.add_option("--host",
+ dest="host",
+ default="_empty",
+ help="show specific host")
+ parser.add_option("--list",
+ action="store_true",
+ help="list all groups")
+ parser.add_option("--debug",
+ action="store_true",
+ help="show logging informations")
+ (options, args) = parser.parse_args()
+
+ # enable debug if required
+ if options.debug:
+ logging.disable(0)
+
+ # retrieve hosts and groups
+ hosts = create_nodes(HOST_DIR)
+ groups = create_nodes(GROUP_DIR)
+
+ # return specific hostname
+ if options.host != "_empty":
+ if options.host in hosts:
+ pprint(get_hostvars(hosts[options.host]))
+ else:
+ pprint("{}")
+ exit(0)
+
+ # return all groups
+ if options.list:
+ pprint(get_list(hosts, groups))
+ exit(0)
+
+ # return all hosts
+ exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/group_vars/bsd.yml b/group_vars/bsd.yml
index d2027af..95f6a17 100644
--- a/group_vars/bsd.yml
+++ b/group_vars/bsd.yml
@@ -4,6 +4,10 @@
---
+_groups:
+ - openbsd
+ - freebsd
+
ansible_become_method: "doas"
group_root: "wheel"
diff --git a/group_vars/linux.yml b/group_vars/linux.yml
index c11daa7..81ffaf1 100644
--- a/group_vars/linux.yml
+++ b/group_vars/linux.yml
@@ -4,6 +4,11 @@
---
+_groups:
+ - alpine
+ - archlinux
+ - debian
+
ansible_become_method: "sudo"
group_root: "root"
diff --git a/host_vars/dc0.yml b/host_vars/dc0.yml
index 3ef714b..c2b9df6 100644
--- a/host_vars/dc0.yml
+++ b/host_vars/dc0.yml
@@ -1,4 +1,5 @@
-ansible_host: dc0
+_groups: openbsd
+
virtual: true
ip:
diff --git a/host_vars/emb0.yml b/host_vars/emb0.yml
index 1895e48..ddb8695 100644
--- a/host_vars/emb0.yml
+++ b/host_vars/emb0.yml
@@ -1,4 +1,5 @@
-ansible_host: emb0
+_groups: debian
+
virtual: false
ip:
diff --git a/host_vars/guest0.yml b/host_vars/guest0.yml
index 76f7242..60300c2 100644
--- a/host_vars/guest0.yml
+++ b/host_vars/guest0.yml
@@ -1,4 +1,3 @@
-ansible_host: guest0
ip:
in: 10.10.0.100
out: 192.168.5.100
diff --git a/host_vars/guest1.yml b/host_vars/guest1.yml
index 48702bd..8df6714 100644
--- a/host_vars/guest1.yml
+++ b/host_vars/guest1.yml
@@ -1,4 +1,3 @@
-ansible_host: guest1
ip:
in: 10.10.0.101
out: 192.168.5.101
diff --git a/host_vars/guest2.yml b/host_vars/guest2.yml
index ee49906..0c10ace 100644
--- a/host_vars/guest2.yml
+++ b/host_vars/guest2.yml
@@ -1,4 +1,3 @@
-ansible_host: guest2
ip:
in: 10.10.0.102
out: 192.168.5.102
diff --git a/host_vars/st0cld0.yml b/host_vars/st0cld0.yml
index 40abf08..45b4f8e 100644
--- a/host_vars/st0cld0.yml
+++ b/host_vars/st0cld0.yml
@@ -1,4 +1,5 @@
-ansible_host: st0cld0
+_groups: openbsd
+
ip:
in: 10.10.0.61
out: 192.168.5.61
diff --git a/host_vars/st0dev0.yml b/host_vars/st0dev0.yml
index 2487ab6..88ddd14 100644
--- a/host_vars/st0dev0.yml
+++ b/host_vars/st0dev0.yml
@@ -1,4 +1,4 @@
-ansible_host: st0dev0
+_groups: openbsd
ip:
in: 10.10.0.60
out: 192.168.5.60
diff --git a/host_vars/st0gme0.yml b/host_vars/st0gme0.yml
index 6db5411..1bdd70d 100644
--- a/host_vars/st0gme0.yml
+++ b/host_vars/st0gme0.yml
@@ -1,4 +1,4 @@
-ansible_host: st0gme0
+_groups: openbsd
ip:
in: 10.10.0.62
out: 192.168.5.62
diff --git a/host_vars/st0gme1.yml b/host_vars/st0gme1.yml
index 8875f68..ad68490 100644
--- a/host_vars/st0gme1.yml
+++ b/host_vars/st0gme1.yml
@@ -1,4 +1,4 @@
-ansible_host: st0gme1
+_groups: alpine
ip:
in: 10.10.0.63
out: 192.168.5.63
diff --git a/host_vars/st0sbx0.yml b/host_vars/st0sbx0.yml
index 09f9c46..e67d1cc 100644
--- a/host_vars/st0sbx0.yml
+++ b/host_vars/st0sbx0.yml
@@ -1,4 +1,4 @@
-ansible_host: st0sbx0
+_groups: openbsd
ip:
in: 10.10.0.64
out: 192.168.5.64
diff --git a/host_vars/st0sbx1.yml b/host_vars/st0sbx1.yml
index 6f71178..c4f692f 100644
--- a/host_vars/st0sbx1.yml
+++ b/host_vars/st0sbx1.yml
@@ -1,4 +1,4 @@
-ansible_host: st0sbx1
+_groups: alpine
ip:
in: 10.10.0.65
out: 192.168.5.65
diff --git a/host_vars/stack0.yml b/host_vars/stack0.yml
index 46afa0d..3c89dd1 100644
--- a/host_vars/stack0.yml
+++ b/host_vars/stack0.yml
@@ -1,4 +1,5 @@
-ansible_host: stack0
+_groups: freebsd
+
ip:
in: 10.10.0.40
out: 192.168.5.40
@@ -20,6 +21,13 @@ vms:
disks:
- { id: 0, size: "32G" }
+ - name: st0dev1
+ image: openbsd
+ memory: 1G
+ cpu: 1
+ disks:
+ - { id: 0, size: "8G" }
+
- name: st0cld0
image: openbsd
memory: 4G
diff --git a/host_vars/ws-bentonite.yml b/host_vars/ws-bentonite.yml
index d911ba1..755df94 100644
--- a/host_vars/ws-bentonite.yml
+++ b/host_vars/ws-bentonite.yml
@@ -1,4 +1,3 @@
-ansible_host: ws-bentonite
ip:
in: 10.10.0.81
out: 192.168.5.81
diff --git a/host_vars/ws-think01.yml b/host_vars/ws-think01.yml
index 8fab600..724cfb3 100644
--- a/host_vars/ws-think01.yml
+++ b/host_vars/ws-think01.yml
@@ -1,4 +1,3 @@
-ansible_host: ws-think01
ip:
in: 10.10.0.82
out: 192.168.5.82
diff --git a/host_vars/ws-xps01.yml b/host_vars/ws-xps01.yml
index ee09d6b..448ae10 100644
--- a/host_vars/ws-xps01.yml
+++ b/host_vars/ws-xps01.yml
@@ -1,4 +1,3 @@
-ansible_host: ws-xps01
ip:
in: 10.10.0.80
out: 192.168.5.80
remember that computers suck.