From cebd5bb3c81ad8ba25c66ac7f6250b0dcc6432c2 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 22:23:42 +0100 Subject: [PATCH] [PR #9651/fdd1331e backport][stable-10] Implement #9650 Add parameter hooks to inventory plugin iocage (#9731) Implement #9650 Add parameter hooks to inventory plugin iocage (#9651) * Add parameter hooks to inventory plugin iocage. * Add changelog fragment. * Update plugins/inventory/iocage.py Co-authored-by: Felix Fontein * Parameter renamed to hooks_results * Fix DOCUMENTATION YAML 4-space indentation. * Fix DOCUMENTATION YAML 2-space indentation. * Update changelogs/fragments/9651-iocage-inventory-hooks.yml Co-authored-by: Felix Fontein * Add note about activated pool mountpoint. --------- Co-authored-by: Felix Fontein (cherry picked from commit fdd1331e4a333499cb21886f5f68dcbd3d4fa32a) Co-authored-by: Vladimir Botka --- .../fragments/9651-iocage-inventory-hooks.yml | 2 + plugins/inventory/iocage.py | 223 ++++++++++++------ 2 files changed, 149 insertions(+), 76 deletions(-) create mode 100644 changelogs/fragments/9651-iocage-inventory-hooks.yml diff --git a/changelogs/fragments/9651-iocage-inventory-hooks.yml b/changelogs/fragments/9651-iocage-inventory-hooks.yml new file mode 100644 index 0000000000..268348ba3c --- /dev/null +++ b/changelogs/fragments/9651-iocage-inventory-hooks.yml @@ -0,0 +1,2 @@ +minor_changes: + - iocage inventory plugin - the new parameter ``hooks_results`` of the plugin is a list of files inside a jail that provide configuration parameters for the inventory. The inventory plugin reads the files from the jails and put the contents into the items of created variable ``iocage_hooks`` (https://github.com/ansible-collections/community.general/issues/9650, https://github.com/ansible-collections/community.general/pull/9651). diff --git a/plugins/inventory/iocage.py b/plugins/inventory/iocage.py index 31aad309f5..6edac6d005 100644 --- a/plugins/inventory/iocage.py +++ b/plugins/inventory/iocage.py @@ -6,85 +6,99 @@ from __future__ import annotations -DOCUMENTATION = ''' - name: iocage - short_description: iocage inventory source - version_added: 10.2.0 - author: - - Vladimir Botka (@vbotka) - requirements: - - iocage >= 1.8 +DOCUMENTATION = r''' +name: iocage +short_description: iocage inventory source +version_added: 10.2.0 +author: + - Vladimir Botka (@vbotka) +requirements: + - iocage >= 1.8 +description: + - Get inventory hosts from the iocage jail manager running on O(host). + - By default, O(host) is V(localhost). If O(host) is not V(localhost) it + is expected that the user running Ansible on the controller can + connect to the O(host) account O(user) with SSH non-interactively and + execute the command C(iocage list). + - Uses a configuration file as an inventory source, it must end + in C(.iocage.yml) or C(.iocage.yaml). +extends_documentation_fragment: + - ansible.builtin.constructed + - ansible.builtin.inventory_cache +options: + plugin: description: - - Get inventory hosts from the iocage jail manager running on O(host). - - By default, O(host) is V(localhost). If O(host) is not V(localhost) it - is expected that the user running Ansible on the controller can - connect to the O(host) account O(user) with SSH non-interactively and - execute the command C(iocage list). - - Uses a configuration file as an inventory source, it must end - in C(.iocage.yml) or C(.iocage.yaml). - extends_documentation_fragment: - - ansible.builtin.constructed - - ansible.builtin.inventory_cache - options: - plugin: - description: - - The name of this plugin, it should always be set to - V(community.general.iocage) for this plugin to recognize - it as its own. - required: true - choices: ['community.general.iocage'] - type: str - host: - description: The IP/hostname of the C(iocage) host. - type: str - default: localhost - user: - description: - - C(iocage) user. - It is expected that the O(user) is able to connect to the - O(host) with SSH and execute the command C(iocage list). - This option is not required if O(host) is V(localhost). - type: str - sudo: - description: - - Enable execution as root. - - This requires passwordless sudo of the command C(iocage list*). - type: bool - default: false - version_added: 10.3.0 - sudo_preserve_env: - description: - - Preserve environment if O(sudo) is enabled. - - This requires C(SETENV) sudoers tag. - type: bool - default: false - version_added: 10.3.0 - get_properties: - description: - - Get jails' properties. - Creates dictionary C(iocage_properties) for each added host. - type: bool - default: false - env: - description: - - O(user)'s environment on O(host). - - Enable O(sudo_preserve_env) if O(sudo) is enabled. - type: dict - default: {} - notes: - - You might want to test the command C(ssh user@host iocage list -l) on - the controller before using this inventory plugin with O(user) specified - and with O(host) other than V(localhost). - - If you run this inventory plugin on V(localhost) C(ssh) is not used. - In this case, test the command C(iocage list -l). - - This inventory plugin creates variables C(iocage_*) for each added host. - - The values of these variables are collected from the output of the - command C(iocage list -l). - - The names of these variables correspond to the output columns. - - The column C(NAME) is used to name the added host. + - The name of this plugin, it should always be set to + V(community.general.iocage) for this plugin to recognize + it as its own. + required: true + choices: ['community.general.iocage'] + type: str + host: + description: The IP/hostname of the C(iocage) host. + type: str + default: localhost + user: + description: + - C(iocage) user. + It is expected that the O(user) is able to connect to the + O(host) with SSH and execute the command C(iocage list). + This option is not required if O(host) is V(localhost). + type: str + sudo: + description: + - Enable execution as root. + - This requires passwordless sudo of the command C(iocage list*). + type: bool + default: false + version_added: 10.3.0 + sudo_preserve_env: + description: + - Preserve environment if O(sudo) is enabled. + - This requires C(SETENV) sudoers tag. + type: bool + default: false + version_added: 10.3.0 + get_properties: + description: + - Get jails' properties. + Creates dictionary C(iocage_properties) for each added host. + type: bool + default: false + env: + description: + - O(user)'s environment on O(host). + - Enable O(sudo_preserve_env) if O(sudo) is enabled. + type: dict + default: {} + hooks_results: + description: + - List of paths to the files in a jail. + - Content of the files is stored in the items of the list C(iocage_hooks). + - If a file is not available the item keeps the dash character C(-). + - The variable C(iocage_hooks) is not created if O(hooks_results) is empty. + type: list + elements: path + version_added: 10.4.0 +notes: + - You might want to test the command C(ssh user@host iocage list -l) on + the controller before using this inventory plugin with O(user) specified + and with O(host) other than V(localhost). + - If you run this inventory plugin on V(localhost) C(ssh) is not used. + In this case, test the command C(iocage list -l). + - This inventory plugin creates variables C(iocage_*) for each added host. + - The values of these variables are collected from the output of the + command C(iocage list -l). + - The names of these variables correspond to the output columns. + - The column C(NAME) is used to name the added host. + - The option O(hooks_results) expects the C(poolname) of a jail is mounted to + C(/poolname). For example, if you activate the pool C(iocage) this plugin + expects to find the O(hooks_results) items in the path + C(/iocage/iocage/jails//root). If you mount the C(poolname) to a + different path the easiest remedy is to create a symlink. ''' -EXAMPLES = ''' +EXAMPLES = r''' --- # file name must end with iocage.yaml or iocage.yml plugin: community.general.iocage @@ -142,6 +156,18 @@ keyed_groups: key: iocage_release - prefix: state key: iocage_state + +--- +# Read the file /var/db/dhclient-hook.address.epair0b in the jails and use it as ansible_host +plugin: community.general.iocage +host: 10.1.0.73 +user: admin +hooks_results: + - /var/db/dhclient-hook.address.epair0b +compose: + ansible_host: iocage_hooks.0 +groups: + test: inventory_hostname.startswith('test') ''' import re @@ -226,6 +252,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable): sudo_preserve_env = self.get_option('sudo_preserve_env') env = self.get_option('env') get_properties = self.get_option('get_properties') + hooks_results = self.get_option('hooks_results') cmd = [] my_env = os.environ.copy() @@ -286,6 +313,50 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable): self.get_properties(t_stdout, results, hostname) + if hooks_results: + cmd_get_pool = cmd.copy() + cmd_get_pool.append(self.IOCAGE) + cmd_get_pool.append('get') + cmd_get_pool.append('--pool') + try: + p = Popen(cmd_get_pool, stdout=PIPE, stderr=PIPE, env=my_env) + stdout, stderr = p.communicate() + if p.returncode != 0: + raise AnsibleError( + f'Failed to run cmd={cmd_get_pool}, rc={p.returncode}, stderr={to_native(stderr)}') + try: + iocage_pool = to_text(stdout, errors='surrogate_or_strict').strip() + except UnicodeError as e: + raise AnsibleError(f'Invalid (non unicode) input returned: {e}') from e + except Exception as e: + raise AnsibleError(f'Failed to get pool: {e}') from e + + for hostname, host_vars in results['_meta']['hostvars'].items(): + iocage_hooks = [] + for hook in hooks_results: + path = "/" + iocage_pool + "/iocage/jails/" + hostname + "/root" + hook + cmd_cat_hook = cmd.copy() + cmd_cat_hook.append('cat') + cmd_cat_hook.append(path) + try: + p = Popen(cmd_cat_hook, stdout=PIPE, stderr=PIPE, env=my_env) + stdout, stderr = p.communicate() + if p.returncode != 0: + iocage_hooks.append('-') + continue + + try: + iocage_hook = to_text(stdout, errors='surrogate_or_strict').strip() + except UnicodeError as e: + raise AnsibleError(f'Invalid (non unicode) input returned: {e}') from e + + except Exception: + iocage_hooks.append('-') + else: + iocage_hooks.append(iocage_hook) + + results['_meta']['hostvars'][hostname]['iocage_hooks'] = iocage_hooks + return results def get_jails(self, t_stdout, results):