From fe358166db182e337e43aea1a4f9ae6a05279f16 Mon Sep 17 00:00:00 2001 From: "James E. Blair" Date: Wed, 22 Aug 2018 16:02:46 -0700 Subject: [PATCH] Add write-inventory role Change-Id: Ife274ddcf78398eef730951635ca0a2a78096871 --- roles/write-inventory/README.rst | 26 ++++ roles/write-inventory/__init__.py | 0 roles/write-inventory/library/__init__.py | 0 .../library/test_write_inventory.py | 131 ++++++++++++++++++ .../library/write_inventory.py | 74 ++++++++++ roles/write-inventory/tasks/main.yaml | 6 + 6 files changed, 237 insertions(+) create mode 100644 roles/write-inventory/README.rst create mode 100644 roles/write-inventory/__init__.py create mode 100644 roles/write-inventory/library/__init__.py create mode 100644 roles/write-inventory/library/test_write_inventory.py create mode 100755 roles/write-inventory/library/write_inventory.py create mode 100644 roles/write-inventory/tasks/main.yaml diff --git a/roles/write-inventory/README.rst b/roles/write-inventory/README.rst new file mode 100644 index 000000000..9d465c3f1 --- /dev/null +++ b/roles/write-inventory/README.rst @@ -0,0 +1,26 @@ +Write an abbreviated version of the Zuul inventory to a file + +This writes the minimal information about hosts from the current Zuul +inventory to a file. It may be used to subsequently invoke Ansible +with the inventory for the job. + +**Role Variables** + +.. zuul:rolevar:: write_inventory_dest + + The path of the inventory file to write. + +.. zuul:rolevar:: write_inventory_include_hostvars + :type: list + + A list of facts about the host to include. By default this + parameter is omitted and all variables about a host will be + included. To only include certain variables, list them here. The + empty list will cause no variables to be included. + +.. zuul:rolevar:: write_inventory_exclude_hostvars + :type: list + + A list of facts about the host to include. By default, all + variables about a host will be included. To exclude certain + variables, list them here. diff --git a/roles/write-inventory/__init__.py b/roles/write-inventory/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/roles/write-inventory/library/__init__.py b/roles/write-inventory/library/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/roles/write-inventory/library/test_write_inventory.py b/roles/write-inventory/library/test_write_inventory.py new file mode 100644 index 000000000..7951e84d3 --- /dev/null +++ b/roles/write-inventory/library/test_write_inventory.py @@ -0,0 +1,131 @@ +# Copyright (C) 2018 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import absolute_import +import testtools +import fixtures +import os + +import yaml + +from .write_inventory import run + +INPUT = yaml.safe_load(""" +bionic: + ansible_connection: ssh + ansible_host: 104.130.217.77 + ansible_port: 22 + ansible_user: zuul + nodepool: + az: null + cloud: rax + interface_ip: 104.130.217.77 + label: ubuntu-bionic + private_ipv4: 10.210.196.115 + provider: rax-ord + public_ipv4: 104.130.217.77 + public_ipv6: 2001:4801:7828:101:be76:4eff:fe10:14eb + region: ORD +xenial: + ansible_connection: ssh + ansible_host: 149.202.170.85 + ansible_port: 22 + ansible_user: zuul + nodepool: + az: nova + cloud: ovh + interface_ip: 149.202.170.85 + label: ubuntu-xenial + private_ipv4: 149.202.170.85 + provider: ovh-gra1 + public_ipv4: 149.202.170.85 + public_ipv6: 2001:41d0:302:1000::17:a32b + region: GRA1 +""") + + +class TestWriteInventory(testtools.TestCase): + def assertOutput(self, dest, ref): + with open(dest) as f: + out = yaml.safe_load(f) + self.assertEqual(ref, out) + + def test_all(self): + '''Test passing all variables''' + dest = self.useFixture(fixtures.TempDir()).path + dest = os.path.join(dest, 'out.yaml') + run(dest, INPUT, None, None) + + self.assertOutput(dest, { + 'all': { + 'hosts': { + 'bionic': { + "ansible_connection": "ssh", + "ansible_user": "zuul", + "ansible_host": "104.130.217.77", + "ansible_port": 22 + }, + 'xenial': { + "ansible_connection": "ssh", + "ansible_user": "zuul", + "ansible_host": "149.202.170.85", + "ansible_port": 22, + } + } + } + }) + + def test_include(self): + '''Test incuding vars''' + dest = self.useFixture(fixtures.TempDir()).path + dest = os.path.join(dest, 'out.yaml') + run(dest, INPUT, ['ansible_host'], None) + + self.assertOutput(dest, { + 'all': { + 'hosts': { + 'bionic': { + "ansible_host": "104.130.217.77", + }, + 'xenial': { + "ansible_host": "149.202.170.85", + } + } + } + }) + + def test_exclude(self): + '''Test passing all variables''' + dest = self.useFixture(fixtures.TempDir()).path + dest = os.path.join(dest, 'out.yaml') + run(dest, INPUT, None, ['ansible_user']) + + self.assertOutput(dest, { + 'all': { + 'hosts': { + 'bionic': { + "ansible_connection": "ssh", + "ansible_host": "104.130.217.77", + "ansible_port": 22 + }, + 'xenial': { + "ansible_connection": "ssh", + "ansible_host": "149.202.170.85", + "ansible_port": 22, + } + } + } + }) diff --git a/roles/write-inventory/library/write_inventory.py b/roles/write-inventory/library/write_inventory.py new file mode 100755 index 000000000..0cb966271 --- /dev/null +++ b/roles/write-inventory/library/write_inventory.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +# +# Copyright 2018 Red Hat, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import json + +from ansible.module_utils.basic import AnsibleModule + +# The list of variables we might include +VARS = [ + 'ansible_connection', + 'ansible_host', + 'ansible_port', + 'ansible_user' +] + + +def run(dest, hostvars, include, exclude): + out_all = {} + out = {'all': {'hosts': out_all}} + for host, hvars in hostvars.items(): + d = {} + for v in VARS: + if v not in hvars: + continue + if include is not None: + if v not in include: + continue + if exclude is not None: + if v in exclude: + continue + d[v] = hvars[v] + out_all[host] = d + + with open(dest, 'w') as f: + f.write(json.dumps(out)) + + +def ansible_main(): + module = AnsibleModule( + argument_spec=dict( + dest=dict(required=True, type='path'), + hostvars=dict(required=True, type='raw'), + include_hostvars=dict(type='list'), + exclude_hostvars=dict(type='list'), + ) + ) + + p = module.params + + dest = p.get('dest') + hostvars = p.get('hostvars') + include = p.get('include_hostvars') + exclude = p.get('exclude_hostvars') + + run(dest, hostvars, include, exclude) + + module.exit_json(changed=True) + + +if __name__ == '__main__': + ansible_main() diff --git a/roles/write-inventory/tasks/main.yaml b/roles/write-inventory/tasks/main.yaml new file mode 100644 index 000000000..52ae232dd --- /dev/null +++ b/roles/write-inventory/tasks/main.yaml @@ -0,0 +1,6 @@ +- name: Write inventory file + write_inventory: + dest: "{{ write_inventory_dest }}" + hostvars: "{{ hostvars }}" + include_hostvars: "{{ write_inventory_include_hostvars | default(omit) }}" + exclude_hostvars: "{{ write_inventory_exclude_hostvars | default(omit) }}"