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:
parent
2d19150757
commit
200ed25648
3 changed files with 82 additions and 10 deletions
|
@ -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…
Reference in a new issue