From d03fdc8093d4c70dfeb6481fd24d0056bf0b14e1 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 22 Feb 2025 09:20:31 +0100 Subject: [PATCH] [PR #9684/961c9b7f backport][stable-10] Ssh config other options (#9794) Ssh config other options (#9684) * Add other_options support to ssh_config module * Changelog fragment * Fix missing and modified stuff * Minor changes * Update fragment with PR URL * Fix PEP8 issue * Fix idempotency issue * Update changelogs/fragments/ssh_config_add_other_options.yml Co-authored-by: Felix Fontein * Update plugins/modules/ssh_config.py Co-authored-by: Felix Fontein * Update plugins/modules/ssh_config.py Co-authored-by: Felix Fontein * Incorporate suggestions * Missed removing str conversion * PEP8 * Update plugins/modules/ssh_config.py Co-authored-by: Felix Fontein * Add fail condition, fix codestyle * Force lower case key values only --------- Co-authored-by: Felix Fontein (cherry picked from commit 961c9b7f4c064877c6db91d145a6ecc2f18f83eb) Co-authored-by: Stephen Bradshaw --- .../ssh_config_add_other_options.yml | 2 ++ plugins/modules/ssh_config.py | 22 +++++++++++++++ .../targets/ssh_config/tasks/options.yml | 28 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 changelogs/fragments/ssh_config_add_other_options.yml diff --git a/changelogs/fragments/ssh_config_add_other_options.yml b/changelogs/fragments/ssh_config_add_other_options.yml new file mode 100644 index 00000000000..032bd2c0739 --- /dev/null +++ b/changelogs/fragments/ssh_config_add_other_options.yml @@ -0,0 +1,2 @@ +minor_changes: + - ssh_config - add ``other_options`` option (https://github.com/ansible-collections/community.general/issues/8053, https://github.com/ansible-collections/community.general/pull/9684). \ No newline at end of file diff --git a/plugins/modules/ssh_config.py b/plugins/modules/ssh_config.py index 8a478ffd8c3..07637e8003a 100644 --- a/plugins/modules/ssh_config.py +++ b/plugins/modules/ssh_config.py @@ -139,6 +139,13 @@ - Sets the C(DynamicForward) option. type: str version_added: 10.1.0 + other_options: + description: + - Provides the option to specify arbitrary SSH config entry options via a dictionary. + - The key names must be lower case. Keys with upper case values are rejected. + - The values must be strings. Other values are rejected. + type: dict + version_added: 10.4.0 requirements: - paramiko """ @@ -152,6 +159,8 @@ identity_file: "/home/akasurde/.ssh/id_rsa" port: '2223' state: present + other_options: + serveraliveinterval: '30' - name: Delete a host from the configuration community.general.ssh_config: @@ -204,6 +213,7 @@ from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.common.text.converters import to_native +from ansible.module_utils.six import string_types from ansible_collections.community.general.plugins.module_utils._stormssh import ConfigParser, HAS_PARAMIKO, PARAMIKO_IMPORT_ERROR from ansible_collections.community.general.plugins.module_utils.ssh import determine_config_file @@ -274,6 +284,17 @@ def ensure_state(self): controlpersist=fix_bool_str(self.params.get('controlpersist')), dynamicforward=self.params.get('dynamicforward'), ) + if self.params.get('other_options'): + for key, value in self.params.get('other_options').items(): + if key.lower() != key: + self.module.fail_json(msg="The other_options key {key!r} must be lower case".format(key=key)) + if key not in args: + if not isinstance(value, string_types): + self.module.fail_json(msg="The other_options value provided for key {key!r} must be a string, got {type}".format(key=key, + type=type(value))) + args[key] = value + else: + self.module.fail_json(msg="Multiple values provided for key {key!r}".format(key=key)) config_changed = False hosts_changed = [] @@ -361,6 +382,7 @@ def main(): host_key_algorithms=dict(type='str', no_log=False), identity_file=dict(type='path'), identities_only=dict(type='bool'), + other_options=dict(type='dict'), port=dict(type='str'), proxycommand=dict(type='str', default=None), proxyjump=dict(type='str', default=None), diff --git a/tests/integration/targets/ssh_config/tasks/options.yml b/tests/integration/targets/ssh_config/tasks/options.yml index 203c782487f..d342943975d 100644 --- a/tests/integration/targets/ssh_config/tasks/options.yml +++ b/tests/integration/targets/ssh_config/tasks/options.yml @@ -22,6 +22,8 @@ controlpath: "~/.ssh/sockets/%r@%h-%p" controlpersist: yes dynamicforward: '10080' + other_options: + serveraliveinterval: '30' state: present register: options_add check_mode: true @@ -57,6 +59,8 @@ controlpath: "~/.ssh/sockets/%r@%h-%p" controlpersist: yes dynamicforward: '10080' + other_options: + serveraliveinterval: '30' state: present register: options_add @@ -81,6 +85,8 @@ controlpath: "~/.ssh/sockets/%r@%h-%p" controlpersist: yes dynamicforward: '10080' + other_options: + serveraliveinterval: '30' state: present register: options_add_again @@ -109,6 +115,7 @@ - "'controlpath ~/.ssh/sockets/%r@%h-%p' in slurp_ssh_config['content'] | b64decode" - "'controlpersist yes' in slurp_ssh_config['content'] | b64decode" - "'dynamicforward 10080' in slurp_ssh_config['content'] | b64decode" + - "'serveraliveinterval 30' in slurp_ssh_config['content'] | b64decode" - name: Options - Update host community.general.ssh_config: @@ -123,6 +130,8 @@ controlpath: "~/.ssh/new-sockets/%r@%h-%p" controlpersist: "600" dynamicforward: '11080' + other_options: + serveraliveinterval: '30' state: present register: options_update @@ -149,6 +158,8 @@ controlpath: "~/.ssh/new-sockets/%r@%h-%p" controlpersist: "600" dynamicforward: '11080' + other_options: + serveraliveinterval: '30' state: present register: options_update @@ -178,6 +189,7 @@ - "'controlpath ~/.ssh/new-sockets/%r@%h-%p' in slurp_ssh_config['content'] | b64decode" - "'controlpersist 600' in slurp_ssh_config['content'] | b64decode" - "'dynamicforward 11080' in slurp_ssh_config['content'] | b64decode" + - "'serveraliveinterval 30' in slurp_ssh_config['content'] | b64decode" - name: Options - Ensure no update in case option exist in ssh_config file but wasn't defined in playbook community.general.ssh_config: @@ -212,6 +224,7 @@ - "'controlpath ~/.ssh/new-sockets/%r@%h-%p' in slurp_ssh_config['content'] | b64decode" - "'controlpersist 600' in slurp_ssh_config['content'] | b64decode" - "'dynamicforward 11080' in slurp_ssh_config['content'] | b64decode" + - "'serveraliveinterval 30' in slurp_ssh_config['content'] | b64decode" - name: Debug debug: @@ -264,6 +277,7 @@ - "'controlpath ~/.ssh/sockets/%r@%h-%p' not in slurp_ssh_config['content'] | b64decode" - "'controlpersist yes' not in slurp_ssh_config['content'] | b64decode" - "'dynamicforward 10080' not in slurp_ssh_config['content'] | b64decode" + - "'serveraliveinterval 30' not in slurp_ssh_config['content'] | b64decode" # Proxycommand and ProxyJump are mutually exclusive. # Reset ssh_config before testing options with proxyjump @@ -286,6 +300,8 @@ controlpath: "~/.ssh/sockets/%r@%h-%p" controlpersist: yes dynamicforward: '10080' + other_options: + serveraliveinterval: '30' state: present register: options_add check_mode: true @@ -321,6 +337,8 @@ controlpath: "~/.ssh/sockets/%r@%h-%p" controlpersist: yes dynamicforward: '10080' + other_options: + serveraliveinterval: '30' state: present register: options_add @@ -345,6 +363,8 @@ controlpath: "~/.ssh/sockets/%r@%h-%p" controlpersist: yes dynamicforward: '10080' + other_options: + serveraliveinterval: '30' state: present register: options_add_again @@ -373,6 +393,7 @@ - "'controlpath ~/.ssh/sockets/%r@%h-%p' in slurp_ssh_config['content'] | b64decode" - "'controlpersist yes' in slurp_ssh_config['content'] | b64decode" - "'dynamicforward 10080' in slurp_ssh_config['content'] | b64decode" + - "'serveraliveinterval 30' in slurp_ssh_config['content'] | b64decode" - name: Options - Update host community.general.ssh_config: @@ -387,6 +408,8 @@ controlpath: "~/.ssh/new-sockets/%r@%h-%p" controlpersist: "600" dynamicforward: '11080' + other_options: + serveraliveinterval: '30' state: present register: options_update @@ -413,6 +436,8 @@ controlpath: "~/.ssh/new-sockets/%r@%h-%p" controlpersist: "600" dynamicforward: '11080' + other_options: + serveraliveinterval: '30' state: present register: options_update @@ -442,6 +467,7 @@ - "'controlpath ~/.ssh/new-sockets/%r@%h-%p' in slurp_ssh_config['content'] | b64decode" - "'controlpersist 600' in slurp_ssh_config['content'] | b64decode" - "'dynamicforward 11080' in slurp_ssh_config['content'] | b64decode" + - "'serveraliveinterval 30' in slurp_ssh_config['content'] | b64decode" - name: Options - Ensure no update in case option exist in ssh_config file but wasn't defined in playbook community.general.ssh_config: @@ -476,6 +502,7 @@ - "'controlpath ~/.ssh/new-sockets/%r@%h-%p' in slurp_ssh_config['content'] | b64decode" - "'controlpersist 600' in slurp_ssh_config['content'] | b64decode" - "'dynamicforward 11080' in slurp_ssh_config['content'] | b64decode" + - "'serveraliveinterval 30' in slurp_ssh_config['content'] | b64decode" - name: Debug debug: @@ -528,3 +555,4 @@ - "'controlpath ~/.ssh/sockets/%r@%h-%p' not in slurp_ssh_config['content'] | b64decode" - "'controlpersist yes' not in slurp_ssh_config['content'] | b64decode" - "'dynamicforward 10080' not in slurp_ssh_config['content'] | b64decode" + - "'serveraliveinterval 30' not in slurp_ssh_config['content'] | b64decode"