Initial Commit

This commit is contained in:
Chris Hammer 2022-09-11 23:27:12 -04:00
commit 1cdd5726c2
22 changed files with 1417 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
collections/ansible_collections
__old
facts.d

26
ansible.cfg Normal file
View File

@ -0,0 +1,26 @@
[defaults]
inventory = hosts
roles_path = roles
collections_path = collections
remote_tmp = /tmp/.ansible-${USER}/tmp
gathering = smart
gather_timeout = 300
fact_path = facts.d
fact_caching = jsonfile
fact_caching_connection = facts.d
fact_caching_timeout = 300
retry_files_enabled = False
forks = 40
timeout = 30
host_key_checking = False
display_skipped_hosts = False
bin_ansible_callbacks = True
callback_whitelist = ansible.posix.profile_tasks, ansible.posix.timer
deprecation_warnings = False
command_warnings = False
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o PreferredAuthentications=publickey

0
collections/.keep Normal file
View File

View File

@ -0,0 +1,5 @@
---
collections:
- name: ansible.posix
- name: community.general

23
csv_inventory_example.yml Normal file
View File

@ -0,0 +1,23 @@
---
- name: CSV Inventory Creation
hosts: all
become: no
gather_facts: no
vars_files:
- vars/defaults.yml
tasks:
- import_tasks: tasks/register_csv.yml
- import_tasks: tasks/fetch_inv_list.yml
- import_tasks: tasks/create_inv.yml
- import_tasks: tasks/fetch_inv_group_list.yml
- import_tasks: tasks/create_inv_group.yml
- import_tasks: tasks/fetch_host_list.yml
- import_tasks: tasks/debug_inv_host.yml
- import_tasks: tasks/add_inv_host.yml
- import_tasks: tasks/update_inv_host.yml
...

View File

@ -0,0 +1,16 @@
inventory_hostname,inventory_name,ansible_host,macaddress,tower_group
hamlin-brenda.etsbv.internal,server000.etsbv.internal,10.14.200.90,02:16:3e:56:a0:f6,eeny
hamlin-brenda.etsbv.internal,server000.etsbv.internal,10.14.200.90,02:16:3e:56:a0:f6,prod
sicilian-michael.etsbv.internal,server001.etsbv.internal,10.183.84.9,02:16:3e:27:9c:64,meeny
sicilian-michael.etsbv.internal,server001.etsbv.internal,10.183.84.9,02:16:3e:27:9c:64,prod
oldham-ethel.etsbv.internal,server002.etsbv.internal,10.175.134.46,02:16:3e:6b:96:56,miney
oldham-ethel.etsbv.internal,server002.etsbv.internal,10.175.134.46,02:16:3e:6b:96:56,prod
maynard-david.etsbv.internal,server003.etsbv.internal,10.223.68.138,02:16:3e:31:48:7d,moe
maynard-david.etsbv.internal,server003.etsbv.internal,10.223.68.138,02:16:3e:31:48:7d,prod
creed-laura.etsbv.internal,server0019.etsbv.internal,10.104.244.30,02:16:3e:72:81:45,tiger
creed-laura.etsbv.internal,server0019.etsbv.internal,10.104.244.30,02:16:3e:72:81:45,prod
doe-john.etsbv.internal,server23421.etsbv.internal,10.87.6.244,aa:f3:e7:66:11:45,whacky
doe-john.etsbv.internal,server23421.etsbv.internal,10.87.6.244,aa:f3:e7:66:11:45,tacky
doe-john.etsbv.internal,server23421.etsbv.internal,10.87.6.244,aa:f3:e7:66:11:45,lacky
doe-john.etsbv.internal,server23421.etsbv.internal,10.87.6.244,aa:f3:e7:66:11:45,hacky
doe-john.etsbv.internal,server23421.etsbv.internal,10.87.6.244,aa:f3:e7:66:11:45,backy
1 inventory_hostname inventory_name ansible_host macaddress tower_group
2 hamlin-brenda.etsbv.internal server000.etsbv.internal 10.14.200.90 02:16:3e:56:a0:f6 eeny
3 hamlin-brenda.etsbv.internal server000.etsbv.internal 10.14.200.90 02:16:3e:56:a0:f6 prod
4 sicilian-michael.etsbv.internal server001.etsbv.internal 10.183.84.9 02:16:3e:27:9c:64 meeny
5 sicilian-michael.etsbv.internal server001.etsbv.internal 10.183.84.9 02:16:3e:27:9c:64 prod
6 oldham-ethel.etsbv.internal server002.etsbv.internal 10.175.134.46 02:16:3e:6b:96:56 miney
7 oldham-ethel.etsbv.internal server002.etsbv.internal 10.175.134.46 02:16:3e:6b:96:56 prod
8 maynard-david.etsbv.internal server003.etsbv.internal 10.223.68.138 02:16:3e:31:48:7d moe
9 maynard-david.etsbv.internal server003.etsbv.internal 10.223.68.138 02:16:3e:31:48:7d prod
10 creed-laura.etsbv.internal server0019.etsbv.internal 10.104.244.30 02:16:3e:72:81:45 tiger
11 creed-laura.etsbv.internal server0019.etsbv.internal 10.104.244.30 02:16:3e:72:81:45 prod
12 doe-john.etsbv.internal server23421.etsbv.internal 10.87.6.244 aa:f3:e7:66:11:45 whacky
13 doe-john.etsbv.internal server23421.etsbv.internal 10.87.6.244 aa:f3:e7:66:11:45 tacky
14 doe-john.etsbv.internal server23421.etsbv.internal 10.87.6.244 aa:f3:e7:66:11:45 lacky
15 doe-john.etsbv.internal server23421.etsbv.internal 10.87.6.244 aa:f3:e7:66:11:45 hacky
16 doe-john.etsbv.internal server23421.etsbv.internal 10.87.6.244 aa:f3:e7:66:11:45 backy

1001
files/sample_inventory_2.csv Normal file

File diff suppressed because it is too large Load Diff

1
hosts Normal file
View File

@ -0,0 +1 @@
localhost ansible_connection=local

33
tasks/add_inv_host.yml Normal file
View File

@ -0,0 +1,33 @@
---
- name: Add hosts from CSV to Tower groups
uri:
method : POST
force_basic_auth : yes
url_username : "{{ __tower_user}}"
url_password : "{{ __tower_pass}}"
url : "{{ __tower_url }}/api/v2/groups/\
{{ r_inv_group_list | selectattr('name', '==', item.tower_group) | map(attribute='id') | flatten | join(',') }}\
/hosts/"
status_code :
- 200
- 201
- 204
headers:
Content-type : application/json
body:
name : "{{ item.inventory_hostname }}"
description : "{{ item.inventory_name }}"
inventory : "{{ r_inv_id.id | default(r_inventory.json.id) }}"
body_format : json
return_content : no
validate_certs : no
ignore_errors : yes
register : r_inventory_host
loop : "{{ r_csv_hosts }}"
loop_control :
label : "{{ item.inventory_hostname }}"
when :
- r_twr_host_list[item.inventory_hostname] is not defined
...

26
tasks/create_inv.yml Normal file
View File

@ -0,0 +1,26 @@
---
- name: Create inventory in Tower
uri:
method : POST
force_basic_auth : yes
url_username : "{{ __tower_user}}"
url_password : "{{ __tower_pass}}"
url : "{{ __tower_url }}/api/v2/inventories/"
status_code :
- 200
- 201
headers:
Content-type : application/json
body:
name : "{{ __inventory }}"
organization : "{{ __organization }}"
body_format : json
return_content : no
validate_certs : no
ignore_errors : yes
register : r_inventory
when :
- __inventory not in r_inventory_list
...

View File

@ -0,0 +1,46 @@
---
- name: Convert CSV groups into a list
set_fact:
r_inv_group_consolidate: |
[
{% for csv_host in r_csv_hosts %}
"{{ csv_host.tower_group }}",
{% endfor %}
]
- name: Create inventory group in Tower
uri:
method : POST
force_basic_auth : yes
url_username : "{{ __tower_user}}"
url_password : "{{ __tower_pass}}"
url : "{{ __tower_url }}/api/v2/groups/"
status_code :
- 200
- 201
headers:
Content-type : application/json
body:
name : "{{ lv_tower_group }}"
inventory : "{{ r_inv_id.id | default(r_inventory.json.id) }}"
body_format : json
return_content : no
validate_certs : no
ignore_errors : yes
register : r_inv_group
loop : "{{ r_inv_group_consolidate | unique }}"
loop_control :
loop_var : lv_tower_group
label : "{{ lv_tower_group }}"
when :
- "r_inv_group_list | selectattr('name', '==', lv_tower_group) | map(attribute='id') | flatten | length < 1"
- name: Re-fetch inventory group info from Tower
import_tasks : tasks/fetch_inv_group_list.yml
when :
- r_inv_group.results | rejectattr('skipped', 'defined')
...

32
tasks/debug_inv_host.yml Normal file
View File

@ -0,0 +1,32 @@
---
- name: Debug Information
block:
- name: Debug r_twr_host_list
debug:
var: r_twr_host_list
- name: Debug add host to tower if not exist
debug:
msg: "[NOT_EXIST] adding {{ item.inventory_hostname }} to tower :: group: {{ item.tower_group }}"
loop: "{{ r_csv_hosts }}"
loop_control:
label: "{{ item.inventory_hostname }}"
when:
- r_twr_host_list[item.inventory_hostname] is not defined
- name: Debug add host to tower, but only if host is not in correct groups
debug:
msg: "[UPDATE] adding {{ item.inventory_hostname }} to tower group {{ item.tower_group }}"
loop: "{{ r_csv_hosts }}"
loop_control:
label: "{{ item.inventory_hostname }}"
when:
- r_twr_host_list[item.inventory_hostname] is defined
- r_twr_host_list[item.inventory_hostname].groups[item.tower_group] is not defined
when:
- __show_debug_msgs | bool
...

21
tasks/fetch_host_list.yml Normal file
View File

@ -0,0 +1,21 @@
---
- name: Fetch list of inventory hosts from Tower
uri:
force_basic_auth : yes
url_username : "{{ __tower_user}}"
url_password : "{{ __tower_pass}}"
url : "{{ __tower_url }}/api/v2/inventories/\
{{ r_inv_id.id | default(r_inventory.json.id) }}/hosts/\
?page_size={{ __api_results | default('20') }}"
validate_certs : no
return_content : no
body_format : json
register : r_get_inv_host_list
- name: Register inventory host list
set_fact:
r_twr_host_list: "{{ lookup('template', 'templates/host_list_w_group.j2') }}"
...

View File

@ -0,0 +1,20 @@
---
- name: Fetch list of inventory groups from Tower
uri:
force_basic_auth : yes
url_username : "{{ __tower_user}}"
url_password : "{{ __tower_pass}}"
url : "{{ __tower_url }}/api/v2/inventories/\
{{ r_inv_id.id | default(r_inventory.json.id) }}/groups/"
validate_certs : no
return_content : no
body_format : json
register : r_get_inv_group_list
- name: Register inventory group list
set_fact:
r_inv_group_list: "{{ lookup('template', 'templates/inv_group_list.j2') }}"
...

30
tasks/fetch_inv_list.yml Normal file
View File

@ -0,0 +1,30 @@
---
- name: Fetch list of inventories from Tower
uri:
force_basic_auth : yes
url_username : "{{ __tower_user}}"
url_password : "{{ __tower_pass}}"
url : "{{ __tower_url }}/api/v2/inventories/"
validate_certs : no
return_content : no
body_format : json
register : r_get_inv_list
- name: Build inventory list from Tower results
set_fact:
r_inventory_list : "{{ r_inventory_list | default([]) + [item.name] }}"
loop : "{{ r_get_inv_list.json.results }}"
loop_control :
label : "{{ item.name }}"
- name: Register inventory ID if available
set_fact:
r_inv_id : "{{ lookup('template', 'templates/get_inventory_id.j2') }}"
when :
- r_inventory_list is defined
- __inventory in r_inventory_list
...

7
tasks/register_csv.yml Normal file
View File

@ -0,0 +1,7 @@
---
- name: Register contents of CSV
set_fact:
r_csv_hosts: "{{ lookup('template', 'templates/csv_inventory.j2') }}"
...

34
tasks/update_inv_host.yml Normal file
View File

@ -0,0 +1,34 @@
---
- name: Update existing host and group membership
uri:
method : POST
force_basic_auth : yes
url_username : "{{ __tower_user}}"
url_password : "{{ __tower_pass}}"
url : "{{ __tower_url }}/api/v2/groups/\
{{ r_inv_group_list | selectattr('name', '==', item.tower_group) | map(attribute='id') | flatten | join(',') }}\
/hosts/"
status_code :
- 200
- 201
- 204
headers:
Content-type : application/json
body:
name : "{{ item.inventory_hostname }}"
description : "{{ item.inventory_name }}"
inventory : "{{ r_inv_id.id | default(r_inventory.json.id) }}"
body_format : json
return_content : no
validate_certs : no
ignore_errors : yes
register : r_inventory_host
loop : "{{ r_csv_hosts }}"
loop_control :
label : "{{ item.inventory_hostname }}"
when :
- r_twr_host_list[item.inventory_hostname] is defined
- r_twr_host_list[item.inventory_hostname].groups[item.tower_group] is not defined
...

View File

@ -0,0 +1,15 @@
[
{% for item in __csv_inventory.split("\n") %}
{% if loop.index != 1 %}
{% set list = item.split(",") %}
{
"{{ __csv_fields[0]}}" : "{{ list[0]|trim() }}",
"{{ __csv_fields[1]}}" : "{{ list[1]|trim() }}",
"{{ __csv_fields[2]}}" : "{{ list[2]|trim() }}",
"{{ __csv_fields[3]}}" : "{{ list[3]|trim() }}",
"{{ __csv_fields[4]}}" : "{{ list[4]|trim() }}",
},
{% endif %}
{% endfor %}
]

View File

@ -0,0 +1,9 @@
{% for inventory_item in r_get_inv_list.json.results %}
{% if inventory_item.name == __inventory %}
{
"name" : "{{ inventory_item.name }}",
"id" : "{{ inventory_item.id }}",
}
{% endif %}
{% endfor %}

View File

@ -0,0 +1,11 @@
{
{% for inv_host in r_get_inv_host_list.json.results %}
"{{ inv_host.name }}": {
"groups" : {
{% for twr_groups in inv_host.summary_fields.groups.results %}
"{{ twr_groups.name }}": "{{ twr_groups.id }}",
{% endfor %}
}
},
{% endfor %}
}

View File

@ -0,0 +1,8 @@
[
{% for inv_group in r_get_inv_group_list.json.results %}
{
"id" : "{{ inv_group.id }}",
"name" : "{{ inv_group.name }}"
},
{% endfor %}
]

50
vars/defaults.yml Normal file
View File

@ -0,0 +1,50 @@
---
__tower_url : https://10.1.1.71
__tower_user : admin
__tower_pass : redhat
# Organization in Tower for inventory
# (must exist in tower)
__organization : 1
# Inventory name
# (will create if it doesnt exist in tower)
__inventory : "CSV-Inventory"
# Inventory file in csv formay to load
__csv_file : "sample_inventory_1.csv"
__csv_inventory : "{{ lookup('file', 'files/' + __csv_file) }}"
# In order to support results of this size
# /etc/tower/settings.py or /etc/tower/conf.d/custom.py
# need to be modified to include: MAX_PAGE_SIZE=XXXX
# and `ansible-tower-service restart` executed.
__api_results : 5000
# This should match the fields in your CSV
#
# NOTE:
# The code will need to be updated to reflect changes
# made here
__csv_fields:
- inventory_name
- inventory_hostname
- ansible_host
- mac_address
- tower_group
# Initialize r_inventory_list list
r_inventory_list: []
# Show debugging messages
__show_debug_msgs: no
...