diff --git a/changelogs/fragments/junos_commit_error_fix.yaml b/changelogs/fragments/junos_commit_error_fix.yaml new file mode 100644 index 00000000000..21b677abcf4 --- /dev/null +++ b/changelogs/fragments/junos_commit_error_fix.yaml @@ -0,0 +1,2 @@ +bugfixes: +- Fix mandatory statement error for junos modules (https://github.com/ansible/ansible/pull/50138) diff --git a/lib/ansible/plugins/cliconf/junos.py b/lib/ansible/plugins/cliconf/junos.py index eb92d8132f6..4c03ca8b945 100644 --- a/lib/ansible/plugins/cliconf/junos.py +++ b/lib/ansible/plugins/cliconf/junos.py @@ -26,6 +26,7 @@ import re from itertools import chain from functools import wraps +from ansible.errors import AnsibleConnectionFailure from ansible.module_utils._text import to_text from ansible.module_utils.network.common.utils import to_list from ansible.plugins.cliconf import CliconfBase @@ -103,7 +104,12 @@ class Cliconf(CliconfBase): if not isinstance(line, collections.Mapping): line = {'command': line} cmd = line['command'] - results.append(self.send_command(**line)) + try: + results.append(self.send_command(**line)) + except AnsibleConnectionFailure as exc: + if "error: commit failed" in exc.message: + self.discard_changes() + raise requests.append(cmd) diff = self.compare_configuration() @@ -149,12 +155,19 @@ class Cliconf(CliconfBase): command += ' peers-synchronize' command += ' and-quit' - return self.send_command(command) + + try: + response = self.send_command(command) + except AnsibleConnectionFailure: + self.discard_changes() + raise + + return response @configure def discard_changes(self): command = 'rollback 0' - for cmd in chain(to_list(command), 'exit'): + for cmd in chain(to_list(command), ['exit']): self.send_command(cmd) @configure diff --git a/lib/ansible/plugins/terminal/junos.py b/lib/ansible/plugins/terminal/junos.py index 2878e1ec600..50c9fc5d21b 100644 --- a/lib/ansible/plugins/terminal/junos.py +++ b/lib/ansible/plugins/terminal/junos.py @@ -41,7 +41,8 @@ class TerminalModule(TerminalBase): terminal_stderr_re = [ re.compile(br"unknown command"), - re.compile(br"syntax error,") + re.compile(br"syntax error"), + re.compile(br"[\r\n]error:") ] def on_open_shell(self): diff --git a/test/integration/targets/junos_config/tests/cli_config/cli_basic.yaml b/test/integration/targets/junos_config/tests/cli_config/cli_basic.yaml index e7a413b5a25..4782c87a611 100644 --- a/test/integration/targets/junos_config/tests/cli_config/cli_basic.yaml +++ b/test/integration/targets/junos_config/tests/cli_config/cli_basic.yaml @@ -43,6 +43,17 @@ - "result.changed == true" - "'ge-0/0/2' in result.diff.prepared" +- name: remove root-authethication (test error scenario) + cli_config: + config: "delete system root-authentication" + ignore_errors: True + register: result + +- assert: + that: + - "result.failed == true" + - "'Missing mandatory statement' in result.msg" + - name: teardown cli_config: *rm1