{{tag>Ansible Python CSV CA}}
= 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()