├── example.xlsx ├── example_with_formula.xlsx ├── .idea ├── vcs.xml ├── misc.xml ├── modules.xml ├── xlstofacts.iml └── workspace.xml ├── README.md └── xls_to_facts.py /example.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mamullen13316/ansible_xls_to_facts/HEAD/example.xlsx -------------------------------------------------------------------------------- /example_with_formula.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mamullen13316/ansible_xls_to_facts/HEAD/example_with_formula.xlsx -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/xlstofacts.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Ansible module which imports an Excel spreadsheet to Ansible facts. 2 | 3 | Each sheet is represented by "spreadsheet_{sheet_name}" in Ansible. The column headers of each row in the sheet are converted to variable names, and values are populated for each row. 4 | 5 | Copy to the library path as specified in your ansible.cfg file. 6 | 7 | Requires the openpyxl Python module on the Ansible host. 8 | - Default behavior is set for [*data_only*](https://openpyxl.readthedocs.io/en/stable/changes.html#id485) to allow extracting values only from formulae 9 | 10 | Install with PIP: 11 | 12 | sudo pip install openpyxl 13 | -------------------------------------------------------------------------------- /xls_to_facts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Copyright (c) 2016 World Wide Technology, Inc. 5 | All rights reserved. 6 | 7 | Revision history: 8 | 7 Apr 2016 | 1.0 - initial release 9 | 10 | 11 | """ 12 | 13 | DOCUMENTATION = ''' 14 | --- 15 | module: xls_to_facts.py 16 | author: Matt Mullen, World Wide Technology 17 | version_added: "1.0" 18 | short_description: Read an Excel .xlsx file and output Ansible facts 19 | description: 20 | - Read the XLS file specified and output Ansible facts in the form of a list with each 21 | element in the list as a dictionary using the column header as the key and the contents 22 | of the cell as the value. A dictionary is created for each sheet, in the format spreadsheet_SheetName. 23 | 24 | requirements: 25 | - The openpyxl Python module must be installed on the Ansible host. This can be installed using pip: 26 | sudo pip install openpyxl 27 | 28 | options: 29 | src: 30 | description: 31 | - The name of the Excel spreadsheet 32 | required: true 33 | 34 | 35 | ''' 36 | 37 | EXAMPLES = ''' 38 | 39 | Running the module from the command line: 40 | 41 | ansible localhost -m xls_to_facts -a src="example.xlsx" -M ~/ansible/library 42 | 43 | localhost | SUCCESS => { 44 | "ansible_facts": { 45 | "spreadsheet_Sheet1": [ 46 | { 47 | "Hostname": "Switch-1", 48 | "Mgmt_ip": "10.0.0.1" 49 | }, 50 | { 51 | "Hostname": "Switch-2", 52 | "Mgmt_ip": "10.0.0.2" 53 | }, 54 | { 55 | "Hostname": "Switch-3", 56 | "Mgmt_ip": "10.0.0.3" 57 | } 58 | ], 59 | "spreadsheet_Sheet2": [ 60 | { 61 | "Description": "To Spine-1", 62 | "Interface": "Ethernet1/1", 63 | "Interface_IP": "192.168.100.1/30" 64 | }, 65 | { 66 | "Description": "To Spine-2", 67 | "Interface": "Ethernet1/2", 68 | "Interface_IP": "192.168.100.5/30" 69 | } 70 | ] 71 | }, 72 | "changed": false 73 | 74 | In a role configuration, given a group and host entry: 75 | 76 | [access_switch] 77 | 10.0.0.1 ansible_connection=local ansible_ssh_user=ansible_local_user hostname=Switch-1 78 | # 79 | 80 | $ cat xls_to_facts.yml 81 | --- 82 | - name: Test Role to import facts from Excel 83 | hosts: access_switch 84 | 85 | roles: 86 | - {role: xls_to_facts, debug: on} 87 | 88 | 89 | $ ansible-playbook xls_to_facts.yml --ask-vault 90 | 91 | ''' 92 | import openpyxl 93 | 94 | # --------------------------------------------------------------------------- 95 | # read_xls_dict 96 | # --------------------------------------------------------------------------- 97 | 98 | def read_xls_dict(input_file): 99 | "Read the XLS file and return as Ansible facts" 100 | result = {"ansible_facts":{}} 101 | spreadsheet = {} 102 | try: 103 | wb = openpyxl.load_workbook(input_file, data_only=True) 104 | for sheet in wb.get_sheet_names(): 105 | ansible_sheet_name = 'spreadsheet_' + sheet 106 | spreadsheet[ansible_sheet_name] = [] 107 | current_sheet = wb.get_sheet_by_name(sheet) 108 | dict_keys = [] 109 | for c in range(1,current_sheet.max_column + 1): 110 | dict_keys.append(current_sheet.cell(row=1,column=c).value) 111 | for r in range (2,current_sheet.max_row + 1): 112 | temp_dict = {} 113 | for c in range(1,current_sheet.max_column + 1): 114 | temp_dict[dict_keys[c-1]] = current_sheet.cell(row=r,column=c).value 115 | spreadsheet[ansible_sheet_name].append(temp_dict) 116 | except IOError: 117 | return (1, "IOError on input file:%s" % input_file) 118 | 119 | result["ansible_facts"] = spreadsheet 120 | return (0, result) 121 | 122 | # --------------------------------------------------------------------------- 123 | # MAIN 124 | # --------------------------------------------------------------------------- 125 | 126 | def main(): 127 | " " 128 | module = AnsibleModule(argument_spec = dict( 129 | src = dict(required=True) 130 | ), 131 | add_file_common_args=True) 132 | 133 | code, response = read_xls_dict(module.params["src"]) 134 | if code == 1: 135 | module.fail_json(msg=response) 136 | else: 137 | module.exit_json(**response) 138 | 139 | return code 140 | 141 | 142 | from ansible.module_utils.basic import * 143 | main() 144 | # 145 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 50 | 51 | 56 | 57 | 58 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 |