Ansible inventory script - inventaire dynamique 2 - CSV

Cahier des charges :

Inventaire basé sur un fichier CSV

Voir aussi :

https://docs.ansible.com/ansible/latest/dev_guide/developing_inventory.html#verify-file-method

Les options : Host Filter, Enabled Variable, Enabled Value

Exemple de fichier CSV

inv.csv

hostname;fqdn;env;ip;env;os_system;os_distrib;os_majeur_version srvweb1;srvweb1.acme.local;prod;192.168.1.10;linux;redhat;8 srvweb2;srvweb2.acme.local;dev;192.168.1.11;linux;redhat;8

Script Python d'Inventory Script

inventory_from_csv.py

#!/usr/bin/env python3 """ CSV external inventory script. # Creative Commons CC0 Public Domain Licence """ import sys import csv import argparse import json from ansible.module_utils._text import to_text _GROUP = 'GROUPE1' mapping = {} def parser_args(): parser = argparse.ArgumentParser(description="") parser.add_argument('--list', default=False, dest="list", action="store_true", help="Produce a JSON consumable grouping of servers for Ansible") parser.add_argument('--host', default=None, dest="host", help="Generate additional host specific details for given host for Ansible") return parser def mk_inventory_from_csv(): """ Make inventory from CSV file """ mapping['_meta']={} mapping['_meta']['hostvars']={} mapping[_GROUP]={} mapping[_GROUP]['hosts'] = [] with open('inv.csv', newline='') as csvfile: csvreader = csv.DictReader(csvfile, delimiter=';') for row in csvreader: hostname = to_text(row['hostname'].strip()) mapping['_meta']['hostvars'][hostname]={} mapping['_meta']['hostvars'][hostname]['ansible_host'] = to_text(row['fqdn'].strip()) mapping['_meta']['hostvars'][hostname]['env'] = to_text(row['env'].strip()) mapping[_GROUP]['hosts'].append(hostname) def get_host_details(host): """ Get json hostvars for specified host """ host = mapping['_meta']['hostvars'][host] return json.dumps(host, indent=4) args = parser_args().parse_args() def main(): if args.list: mk_inventory_from_csv() print(json.dumps(mapping, indent=4)) sys.exit(0) elif args.host: mk_inventory_from_csv() print(get_host_details(args.host)) sys.exit(0) else: parser_args.print_help() sys.exit(0) if __name__ == '__main__': main()

On test

chmod +x inventory_from_csv.py ./inventory_from_csv.py --list | jq . ./inventory_from_csv.py --host srvweb1 | jq . ansible-inventory -i inventory_from_csv.py --list ansible-inventory -i inventory_from_csv.py --host srvweb1

Annexes

Script Python sql2csv

sql2csv.py

#! /usr/bin/env python3 """ Make CSV inventory file from SQL query (CMDB) """ import os import pyodbc cfg_csv_path = os.environ["INVENTORY_OPT_CSV_PATH"] cfg_queryname = os.environ["INVENTORY_OPT_QUERYNAME"] db_user = os.environ["MSSQL_LOGIN_USER"] db_pass = os.environ["MSSQL_LOGIN_PASSWORD"] db_name = os.environ["MSSQL_LOGIN_DATABASE"] db_host = os.environ["MSSQL_LOGIN_HOST"] db_port = os.environ["MSSQL_LOGIN_PORT"] def clean_field(field): """ Clean each fields. CSV use ';' as field separator and so all ';' characters must be removed CSV use line break as line separator and so all '\n' and '\r' characters must be replaced """ if field is None or field == "Undefined": ret = "" else: ret = str(field).strip().replace(";", "").replace("\n", ",").replace("\r", ",") return ret with open(f"config/{cfg_queryname}/query.sql", "r") as f: query = f.read().strip() def main(): db = pyodbc.connect( DRIVER="FreeTDS", Server=db_host, Port=db_port, Database=db_name, UID=db_user, PWD=db_pass, ) cursor = db.cursor() result = cursor.execute(query) with open(cfg_csv_path, mode="w") as file_object: headers = [] for row in result.description: headers.append(row[0]) print(";".join(headers), file=file_object) for row in result: print(";".join(list(map(clean_field, row))), file=file_object) main()