Add support for commit label in iosxr_config (#42931)
* Add support for commit label in iosxr_config * sanity pep8 etc fixes
This commit is contained in:
parent
4f1746ee1d
commit
bf544c2200
4 changed files with 130 additions and 8 deletions
|
@ -27,6 +27,7 @@
|
|||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
import json
|
||||
import re
|
||||
from difflib import Differ
|
||||
from copy import deepcopy
|
||||
from time import sleep
|
||||
|
@ -334,7 +335,8 @@ def discard_config(module):
|
|||
conn.discard_changes()
|
||||
|
||||
|
||||
def commit_config(module, comment=None, confirmed=False, confirm_timeout=None, persist=False, check=False):
|
||||
def commit_config(module, comment=None, confirmed=False, confirm_timeout=None,
|
||||
persist=False, check=False, label=None):
|
||||
conn = get_connection(module)
|
||||
reply = None
|
||||
|
||||
|
@ -344,7 +346,7 @@ def commit_config(module, comment=None, confirmed=False, confirm_timeout=None, p
|
|||
if is_netconf(module):
|
||||
reply = conn.commit(confirmed=confirmed, timeout=confirm_timeout, persist=persist)
|
||||
elif is_cliconf(module):
|
||||
reply = conn.commit(comment=comment)
|
||||
reply = conn.commit(comment=comment, label=label)
|
||||
|
||||
return reply
|
||||
|
||||
|
@ -373,8 +375,18 @@ def get_config(module, config_filter=None, source='running'):
|
|||
return cfg
|
||||
|
||||
|
||||
def check_existing_commit_labels(conn, label):
|
||||
out = conn.get(command='show configuration history detail | include %s' % label)
|
||||
label_exist = re.search(label, out, re.M)
|
||||
if label_exist:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def load_config(module, command_filter, commit=False, replace=False,
|
||||
comment=None, admin=False, running=None, nc_get_filter=None):
|
||||
comment=None, admin=False, running=None, nc_get_filter=None,
|
||||
label=None):
|
||||
|
||||
conn = get_connection(module)
|
||||
|
||||
|
@ -404,6 +416,16 @@ def load_config(module, command_filter, commit=False, replace=False,
|
|||
elif is_cliconf(module):
|
||||
# to keep the pre-cliconf behaviour, make a copy, avoid adding commands to input list
|
||||
cmd_filter = deepcopy(command_filter)
|
||||
# If label is present check if label already exist before entering
|
||||
# config mode
|
||||
if label:
|
||||
old_label = check_existing_commit_labels(conn, label)
|
||||
if old_label:
|
||||
module.fail_json(
|
||||
msg='commit label {%s} is already used for'
|
||||
' an earlier commit, please choose a different label'
|
||||
' and rerun task' % label
|
||||
)
|
||||
cmd_filter.insert(0, 'configure terminal')
|
||||
if admin:
|
||||
cmd_filter.insert(0, 'admin')
|
||||
|
@ -424,7 +446,7 @@ def load_config(module, command_filter, commit=False, replace=False,
|
|||
cmd.append('end')
|
||||
conn.edit_config(cmd)
|
||||
elif commit:
|
||||
commit_config(module, comment=comment)
|
||||
commit_config(module, comment=comment, label=label)
|
||||
conn.edit_config('end')
|
||||
if admin:
|
||||
conn.edit_config('exit')
|
||||
|
|
|
@ -135,6 +135,14 @@ options:
|
|||
type: bool
|
||||
default: 'no'
|
||||
version_added: "2.4"
|
||||
label:
|
||||
description:
|
||||
- Allows a commit label to be specified to be included when the
|
||||
configuration is committed. A valid label must begin with an alphabet
|
||||
and not exceed 30 characters, only alphabets, digits, hyphens and
|
||||
underscores are allowed. If the configuration is not changed or
|
||||
committed, this argument is ignored.
|
||||
version_added: "2.7"
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
|
@ -239,6 +247,18 @@ def check_args(module, warnings):
|
|||
if module.params['comment']:
|
||||
if len(module.params['comment']) > 60:
|
||||
module.fail_json(msg='comment argument cannot be more than 60 characters')
|
||||
if module.params['label']:
|
||||
label = module.params['label']
|
||||
if len(label) > 30:
|
||||
module.fail_json(msg='label argument cannot be more than 30 characters')
|
||||
if not label[0].isalpha():
|
||||
module.fail_json(msg='label argument must begin with an alphabet')
|
||||
valid_chars = re.match(r'[\w-]*$', label)
|
||||
if not valid_chars:
|
||||
module.fail_json(
|
||||
msg='label argument must only contain alphabets,' +
|
||||
'digits, underscores or hyphens'
|
||||
)
|
||||
if module.params['force']:
|
||||
warnings.append('The force argument is deprecated, please use '
|
||||
'match=none instead. This argument will be '
|
||||
|
@ -340,6 +360,7 @@ def run(module, result):
|
|||
comment = module.params['comment']
|
||||
admin = module.params['admin']
|
||||
check_mode = module.check_mode
|
||||
label = module.params['label']
|
||||
|
||||
candidate_config = get_candidate(module)
|
||||
running_config = get_running_config(module)
|
||||
|
@ -376,7 +397,11 @@ def run(module, result):
|
|||
result['commands'] = commands
|
||||
|
||||
commit = not check_mode
|
||||
diff = load_config(module, commands, commit=commit, replace=replace_config, comment=comment, admin=admin)
|
||||
diff = load_config(
|
||||
module, commands, commit=commit,
|
||||
replace=replace_config, comment=comment, admin=admin,
|
||||
label=label
|
||||
)
|
||||
if diff:
|
||||
result['diff'] = dict(prepared=diff)
|
||||
|
||||
|
@ -405,7 +430,8 @@ def main():
|
|||
config=dict(),
|
||||
backup=dict(type='bool', default=False),
|
||||
comment=dict(default=DEFAULT_COMMIT_COMMENT),
|
||||
admin=dict(type='bool', default=False)
|
||||
admin=dict(type='bool', default=False),
|
||||
label=dict()
|
||||
)
|
||||
|
||||
argument_spec.update(iosxr_argument_spec)
|
||||
|
|
|
@ -89,9 +89,13 @@ class Cliconf(CliconfBase):
|
|||
def get(self, command=None, prompt=None, answer=None, sendonly=False, newline=True):
|
||||
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline)
|
||||
|
||||
def commit(self, comment=None):
|
||||
if comment:
|
||||
def commit(self, comment=None, label=None):
|
||||
if comment and label:
|
||||
command = 'commit label {0} comment {1}'.format(label, comment)
|
||||
elif comment:
|
||||
command = 'commit comment {0}'.format(comment)
|
||||
elif label:
|
||||
command = 'commit label {0}'.format(label)
|
||||
else:
|
||||
command = 'commit'
|
||||
self.send_command(command)
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
- debug: msg="START cli/commit_label.yaml on connection={{ ansible_connection }}"
|
||||
|
||||
- name: setup
|
||||
iosxr_config:
|
||||
commands:
|
||||
- no description
|
||||
- no shutdown
|
||||
parents:
|
||||
- interface Loopback999
|
||||
match: none
|
||||
|
||||
- name: get a unique and valid label
|
||||
set_fact:
|
||||
label: "ansible_{{ 1001 | random | to_uuid | truncate(20, true, '_') }}"
|
||||
|
||||
- name: configure device with a label and a comment
|
||||
iosxr_config:
|
||||
src: basic/config.j2
|
||||
comment: "this is sensible commit message"
|
||||
label: "{{ label }}"
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.changed == true"
|
||||
|
||||
- name: setup
|
||||
iosxr_config:
|
||||
commands:
|
||||
- no description
|
||||
- no shutdown
|
||||
parents:
|
||||
- interface Loopback999
|
||||
match: none
|
||||
|
||||
- name: Try to commit with old label, fail with a msg that label is alreay used
|
||||
iosxr_config:
|
||||
src: basic/config.j2
|
||||
label: "{{ label }}"
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.changed == false"
|
||||
- "'already used' in result.msg"
|
||||
|
||||
- name: setup
|
||||
iosxr_config:
|
||||
commands:
|
||||
- no description
|
||||
- no shutdown
|
||||
parents:
|
||||
- interface Loopback999
|
||||
match: none
|
||||
|
||||
- name: Try to commit with invalid chars($) in label
|
||||
iosxr_config:
|
||||
src: basic/config.j2
|
||||
label: 'ansible_iosxr_config_$'
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.changed == false"
|
||||
- "'only contain alphabets' in result.msg"
|
||||
|
||||
- debug: msg="END cli/commit_label.yaml on connection={{ ansible_connection }}"
|
Loading…
Reference in a new issue