From 81f4f6cb05901543c770baebce9a79d7ff1f41e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Krienb=C3=BChl?= Date: Wed, 12 Jun 2024 11:02:26 +0200 Subject: [PATCH] Add ability to rename host inventory variables using patterns Certain environments may have conflicts with the variables given by Netbox, and the variables used in the existing Ansible codebase. With this change, such cases can be worked around by renaming individual variables, or whole groups of them. For example, this will rename all `cluster*` variables to have a `netbox__` prefix instead (e.g., `cluster_group` -> `netbox__cluster_group`): ```yaml rename_variables: - pattern: 'cluster(.*)' repl: 'netbox__cluster\1' ``` Uses a list, instead of a dict, to ensure that the order of evaluation is strictly defined across all Python versions, and to add the ability to exclude certain variables from being rewritten. For example: ```yaml rename_variables: # Keep cluster_type the same - pattern: 'cluster_type' repl: 'cluster_type' # Rename all other cluster* variables - pattern: 'cluster(.*)' repl: 'netbox__cluster\1' ``` --- plugins/inventory/nb_inventory.py | 41 +++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/plugins/inventory/nb_inventory.py b/plugins/inventory/nb_inventory.py index 0aac76a8..943f4f93 100644 --- a/plugins/inventory/nb_inventory.py +++ b/plugins/inventory/nb_inventory.py @@ -3,6 +3,8 @@ from __future__ import absolute_import, division, print_function +import re + __metaclass__ = type DOCUMENTATION = """ @@ -249,6 +251,15 @@ description: Use out of band IP as `ansible host` type: boolean default: false + rename_variables: + description: + - Rename variables evaluated by nb_inventory, before writing them. + - Each list entry contains a dict with a 'pattern' and a 'repl'. + - Both 'pattern' and 'repl' are regular expressions. + - The first matching expression is used, subsequent matches are ignored. + - Internally `re.sub` is used. + type: list + defaut: [] """ EXAMPLES = """ @@ -1905,31 +1916,39 @@ def _setup_nested_groups(self, group, lookup, parent_lookup): return transformed_group_names + def _set_variable(self, hostname, key, value): + for item in self.rename_variables: + if item['pattern'].match(key): + key = item['pattern'].sub(item['repl'], key) + break + + self.inventory.set_variable(hostname, key, value) + def _fill_host_variables(self, host, hostname): extracted_primary_ip = self.extract_primary_ip(host=host) if extracted_primary_ip: - self.inventory.set_variable(hostname, "ansible_host", extracted_primary_ip) + self._set_variable(hostname, "ansible_host", extracted_primary_ip) if self.ansible_host_dns_name: extracted_dns_name = self.extract_dns_name(host=host) if extracted_dns_name: - self.inventory.set_variable( + self._set_variable( hostname, "ansible_host", extracted_dns_name ) extracted_primary_ip4 = self.extract_primary_ip4(host=host) if extracted_primary_ip4: - self.inventory.set_variable(hostname, "primary_ip4", extracted_primary_ip4) + self._set_variable(hostname, "primary_ip4", extracted_primary_ip4) extracted_primary_ip6 = self.extract_primary_ip6(host=host) if extracted_primary_ip6: - self.inventory.set_variable(hostname, "primary_ip6", extracted_primary_ip6) + self._set_variable(hostname, "primary_ip6", extracted_primary_ip6) extracted_oob_ip = self.extract_oob_ip(host=host) if extracted_oob_ip: - self.inventory.set_variable(hostname, "oob_ip", extracted_oob_ip) + self._set_variable(hostname, "oob_ip", extracted_oob_ip) if self.oob_ip_as_primary_ip: - self.inventory.set_variable(hostname, "ansible_host", extracted_oob_ip) + self._set_variable(hostname, "ansible_host", extracted_oob_ip) for attribute, extractor in self.group_extractors.items(): extracted_value = extractor(host) @@ -1965,9 +1984,9 @@ def _fill_host_variables(self, host, hostname): ) ): for key, value in extracted_value.items(): - self.inventory.set_variable(hostname, key, value) + self._set_variable(hostname, key, value) else: - self.inventory.set_variable(hostname, attribute, extracted_value) + self._set_variable(hostname, attribute, extracted_value) def _get_host_virtual_chassis_master(self, host): virtual_chassis = host.get("virtual_chassis", None) @@ -2146,4 +2165,10 @@ def parse(self, inventory, loader, path, cache=True): self.ansible_host_dns_name = self.get_option("ansible_host_dns_name") self.racks = self.get_option("racks") + # Compile regular expressions, if any + self.rename_variables = [{ + 'pattern': re.compile(i['pattern']), + 'repl': i['repl'] + } for i in self.get_option("rename_variables") or ()] + self.main()