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
This commit is contained in:
Ganesh Nalawade 2019-09-13 18:52:33 +05:30 committed by GitHub
parent 2d19150757
commit 200ed25648
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 82 additions and 10 deletions

View file

@ -40,10 +40,13 @@ options:
description:
- If the C(replace) argument is set to C(yes), it will replace
the entire running-config of the device with the C(config)
argument value. For NXOS devices, C(replace) argument takes
path to the file on the device that will be used for replacing
the entire running-config. Nexus 9K devices only support replace.
Use I(net_put) or I(nxos_file_copy) module to copy the flat file
argument value. For devices that support replacing running
configuration from file on device like NXOS/JUNOS, the
C(replace) argument takes path to the file on the device
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.
type: 'str'
backup:
@ -168,6 +171,10 @@ EXAMPLES = """
cli_config:
replace: 'bootflash:nxoscfg'
- name: junos replace config
cli_config:
replace: '/var/home/ansible/junos01.cfg'
- name: commit with comment
cli_config:
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'):
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:
resp = connection.rollback(rollback_id, commit)
if 'diff' in resp:
@ -255,7 +267,7 @@ def run(module, device_operations, connection, candidate, running, rollback_id):
if diff_ignore_lines:
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()
kwargs = {'candidate': candidate, 'commit': commit, 'replace': replace,
@ -375,7 +387,7 @@ def main():
if module.params['backup']:
result['__backup__'] = running
if candidate or rollback_id:
if candidate or rollback_id or module.params['replace']:
try:
result.update(run(module, device_operations, connection, candidate, running, rollback_id))
except Exception as exc:

View file

@ -109,7 +109,7 @@ class Cliconf(CliconfBase):
requests = []
if replace:
candidate = 'load replace {0}'.format(replace)
candidate = 'load override {0}'.format(replace)
for line in to_list(candidate):
if not isinstance(line, Mapping):
@ -133,8 +133,8 @@ class Cliconf(CliconfBase):
self.discard_changes()
else:
for cmd in ['top', 'exit']:
self.send_command(cmd)
self.send_command('top')
self.discard_changes()
resp['request'] = requests
resp['response'] = results
@ -193,7 +193,7 @@ class Cliconf(CliconfBase):
resp = self.send_command(command)
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 = ''
return resp

View file

@ -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 }}"