diff --git a/changelogs/fragments/4088-add-constructed-interface-for-icinga2-inventory.yml b/changelogs/fragments/4088-add-constructed-interface-for-icinga2-inventory.yml new file mode 100644 index 0000000000..1b1d24714a --- /dev/null +++ b/changelogs/fragments/4088-add-constructed-interface-for-icinga2-inventory.yml @@ -0,0 +1,2 @@ +minor_changes: + - icinga2 inventory plugin - implemented constructed interface (https://github.com/ansible-collections/community.general/pull/4088). diff --git a/plugins/inventory/icinga2.py b/plugins/inventory/icinga2.py index fdd3da1b0c..5ae565beb9 100644 --- a/plugins/inventory/icinga2.py +++ b/plugins/inventory/icinga2.py @@ -16,7 +16,17 @@ DOCUMENTATION = ''' - Get inventory hosts from the Icinga2 API. - "Uses a configuration file as an inventory source, it must end in C(.icinga2.yml) or C(.icinga2.yaml)." + extends_documentation_fragment: + - constructed options: + strict: + version_added: 4.4.0 + compose: + version_added: 4.4.0 + groups: + version_added: 4.4.0 + keyed_groups: + version_added: 4.4.0 plugin: description: Name of the plugin. required: true @@ -63,6 +73,20 @@ password: secure host_filter: \"linux-servers\" in host.groups validate_certs: false inventory_attr: name +groups: + # simple name matching + webservers: inventory_hostname.startswith('web') + + # using icinga2 template + databaseservers: "'db-template' in (icinga2_attributes.templates|list)" + +compose: + # set all icinga2 attributes to a host variable 'icinga2_attrs' + icinga2_attrs: icinga2_attributes + + # set 'ansible_user' and 'ansible_port' from icinga2 host vars + ansible_user: icinga2_attributes.vars.ansible_user + ansible_port: icinga2_attributes.vars.ansible_port | default(22) ''' import json @@ -180,7 +204,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable): """Query for all hosts """ self.display.vvv("Querying Icinga2 for inventory") query_args = { - "attrs": ["address", "display_name", "state_type", "state", "groups"], + "attrs": ["address", "address6", "name", "display_name", "state_type", "state", "templates", "groups", "vars", "zone"], } if self.host_filter is not None: query_args['host_filter'] = self.host_filter @@ -190,6 +214,12 @@ class InventoryModule(BaseInventoryPlugin, Constructable): ansible_inv = self._convert_inv(results_json) return ansible_inv + def _apply_constructable(self, name, variables): + strict = self.get_option('strict') + self._add_host_to_composed_groups(self.get_option('groups'), variables, name, strict=strict) + self._add_host_to_keyed_groups(self.get_option('keyed_groups'), variables, name, strict=strict) + self._set_composite_vars(self.get_option('compose'), variables, name, strict=strict) + def _populate(self): groups = self._to_json(self.get_inventory_from_icinga()) return groups @@ -232,6 +262,10 @@ class InventoryModule(BaseInventoryPlugin, Constructable): host_attrs['state']) self.inventory.set_variable(host_name, 'state_type', host_attrs['state_type']) + # Adds all attributes to a variable 'icinga2_attributes' + construct_vars = dict(self.inventory.get_host(host_name).get_vars()) + construct_vars['icinga2_attributes'] = host_attrs + self._apply_constructable(host_name, construct_vars) return groups_dict def parse(self, inventory, loader, path, cache=True): diff --git a/tests/unit/plugins/inventory/test_icinga2.py b/tests/unit/plugins/inventory/test_icinga2.py index 93ad8870ca..bcb6aa9614 100644 --- a/tests/unit/plugins/inventory/test_icinga2.py +++ b/tests/unit/plugins/inventory/test_icinga2.py @@ -76,6 +76,19 @@ def query_hosts(hosts=None, attrs=None, joins=None, host_filter=None): return json_host_data +def get_option(option): + if option == 'groups': + return {} + elif option == 'keyed_groups': + return [] + elif option == 'compose': + return {} + elif option == 'strict': + return False + else: + return None + + def test_populate(inventory, mocker): # module settings inventory.icinga2_user = 'ansible' @@ -86,6 +99,7 @@ def test_populate(inventory, mocker): # bypass authentication and API fetch calls inventory._check_api = mocker.MagicMock(side_effect=check_api) inventory._query_hosts = mocker.MagicMock(side_effect=query_hosts) + inventory.get_option = mocker.MagicMock(side_effect=get_option) inventory._populate() # get different hosts