Fix for junos cli_config replace option (#62131)

* Fix for junos cli_config replace option

*  For device that support replace option by loading
   configuration from a file on device `config` option
   is not required and value of `replace` option is the
   path of configuration file on device. This fix allows
   invoking run() function in cli_config if `config` option
   is None and `replace` option is not boolean

*  The command to replace running config on junos device
   is `load override <filename>` and not `load replace <filename>`
   This is fixed in the junos cliconf plugin.

* Add integration test

(cherry picked from commit 200ed25648)
pull/62378/head
Ganesh Nalawade 5 years ago committed by Toshio Kuratomi
parent 9812e52682
commit f7fed1dacc

@ -0,0 +1,2 @@
bugfixes:
- Fix for junos cli_config replace option (https://github.com/ansible/ansible/pull/62131).

@ -40,10 +40,13 @@ options:
description: description:
- If the C(replace) argument is set to C(yes), it will replace - If the C(replace) argument is set to C(yes), it will replace
the entire running-config of the device with the C(config) the entire running-config of the device with the C(config)
argument value. For NXOS devices, C(replace) argument takes argument value. For devices that support replacing running
path to the file on the device that will be used for replacing configuration from file on device like NXOS/JUNOS, the
the entire running-config. Nexus 9K devices only support replace. C(replace) argument takes path to the file on the device
Use I(net_put) or I(nxos_file_copy) module to copy the flat file that will be used for replacing the entire running-config.
The value of C(config) option should be I(None) for such devices.
Nexus 9K devices only support replace. Use I(net_put) or
I(nxos_file_copy) in case of NXOS module to copy the flat file
to remote device and then use set the fullpath to this argument. to remote device and then use set the fullpath to this argument.
type: 'str' type: 'str'
backup: backup:
@ -168,6 +171,10 @@ EXAMPLES = """
cli_config: cli_config:
replace: 'bootflash:nxoscfg' replace: 'bootflash:nxoscfg'
- name: junos replace config
cli_config:
replace: '/var/home/ansible/junos01.cfg'
- name: commit with comment - name: commit with comment
cli_config: cli_config:
config: set system host-name foo config: set system host-name foo
@ -242,6 +249,11 @@ def run(module, device_operations, connection, candidate, running, rollback_id):
elif replace in ('no', 'false', 'False'): elif replace in ('no', 'false', 'False'):
replace = False replace = False
if replace is not None and replace not in [True, False] and candidate is not None:
module.fail_json(msg="Replace value '%s' is a configuration file path already"
" present on the device. Hence 'replace' and 'config' options"
" are mutually exclusive" % replace)
if rollback_id is not None: if rollback_id is not None:
resp = connection.rollback(rollback_id, commit) resp = connection.rollback(rollback_id, commit)
if 'diff' in resp: if 'diff' in resp:
@ -255,7 +267,7 @@ def run(module, device_operations, connection, candidate, running, rollback_id):
if diff_ignore_lines: if diff_ignore_lines:
module.warn('diff_ignore_lines is ignored as the device supports onbox diff') module.warn('diff_ignore_lines is ignored as the device supports onbox diff')
if not isinstance(candidate, list): if candidate and not isinstance(candidate, list):
candidate = candidate.strip('\n').splitlines() candidate = candidate.strip('\n').splitlines()
kwargs = {'candidate': candidate, 'commit': commit, 'replace': replace, kwargs = {'candidate': candidate, 'commit': commit, 'replace': replace,
@ -375,7 +387,7 @@ def main():
if module.params['backup']: if module.params['backup']:
result['__backup__'] = running result['__backup__'] = running
if candidate or rollback_id: if candidate or rollback_id or module.params['replace']:
try: try:
result.update(run(module, device_operations, connection, candidate, running, rollback_id)) result.update(run(module, device_operations, connection, candidate, running, rollback_id))
except Exception as exc: except Exception as exc:

@ -109,7 +109,7 @@ class Cliconf(CliconfBase):
requests = [] requests = []
if replace: if replace:
candidate = 'load replace {0}'.format(replace) candidate = 'load override {0}'.format(replace)
for line in to_list(candidate): for line in to_list(candidate):
if not isinstance(line, Mapping): if not isinstance(line, Mapping):
@ -133,8 +133,8 @@ class Cliconf(CliconfBase):
self.discard_changes() self.discard_changes()
else: else:
for cmd in ['top', 'exit']: self.send_command('top')
self.send_command(cmd) self.discard_changes()
resp['request'] = requests resp['request'] = requests
resp['response'] = results resp['response'] = results
@ -193,7 +193,7 @@ class Cliconf(CliconfBase):
resp = self.send_command(command) resp = self.send_command(command)
r = resp.splitlines() r = resp.splitlines()
if len(r) == 1 and '[edit]' in r[0]: if len(r) == 1 and '[edit]' in r[0] or len(r) == 4 and r[1].startswith('- version'):
resp = '' resp = ''
return resp return resp

@ -0,0 +1,60 @@
---
- debug: msg="START cli_config/cli_replace.yaml on connection={{ ansible_connection }}"
- name: set interface config
cli_config:
config: "{{ item }}"
loop:
- "delete interfaces ge-0/0/11"
- set interfaces ge-0/0/11 description "test cli_config"
- name: get running configuration
cli_command:
command: show configuration
register: result
- name: copy configuration to file
copy:
content: "{{ result['stdout'] }}"
dest: /tmp/junos01.cfg
- name: "modify interface ge-0/0/11 configuration"
replace:
path: /tmp/junos01.cfg
regexp: 'test cli_config'
replace: 'test cli_config replaced'
- name: copy config file to remote host
net_put:
src: /tmp/junos01.cfg
dest: /var/home/{{ ansible_user }}/junos01.cfg
- name: replace syslog test file configuration
cli_config:
replace: "/var/home/{{ ansible_user }}/junos01.cfg"
- name: get interface configuration
cli_command:
command: show configuration interfaces ge-0/0/11
register: result
- name: assert that interface config change is reflected on device
assert:
that:
- "'test cli_config replaced' in result.stdout"
- name: replace interface configuration (idempotent)
cli_config:
replace: "/var/home/{{ ansible_user }}/junos01.cfg"
register: result
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
- name: delete interface config
cli_config:
config: "delete interfaces ge-0/0/11"
- debug: msg="END cli_config/cli_replace.yaml on connection={{ ansible_connection }}"
Loading…
Cancel
Save