Table des matières

, , ,

Ansible inventory script - inventaire dynamique 2 - CSV

Cahier des charges :

Voir aussi :

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()