Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nxos_snmp_user: platform fixes for get_snmp_user #55832

Merged
merged 2 commits into from
May 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
80 changes: 64 additions & 16 deletions lib/ansible/modules/network/nxos/nxos_snmp_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
sample: ["snmp-server user ntc network-operator auth md5 test_password"]
'''

import re

from ansible.module_utils.network.nxos.nxos import load_config, run_commands
from ansible.module_utils.network.nxos.nxos import nxos_argument_spec, check_args
Expand Down Expand Up @@ -134,6 +135,7 @@ def get_snmp_groups(module):
def get_snmp_user(user, module):
command = 'show snmp user {0}'.format(user)
body = execute_show_command(command, module, text=True)
body_text = body[0]

if 'No such entry' not in body[0]:
body = execute_show_command(command, module)
Expand Down Expand Up @@ -177,28 +179,74 @@ def get_snmp_user(user, module):
else:
resource['encrypt'] = 'none'

group_table = resource_table[tablegrpkey][rowgrpkey]

groups = []
try:
for group in group_table:
groups.append(str(group[grpkey]).strip())
except TypeError:
groups.append(str(group_table[grpkey]).strip())

# Now for the platform bug case, get the groups
if isinstance(rt, list):
# remove 1st element from the list as this is parsed already
rt.pop(0)
# iterate through other elements indexed by
# 'user' and add it to groups.
for each in rt:
groups.append(each['user'].strip())
if tablegrpkey in resource_table:
group_table = resource_table[tablegrpkey][rowgrpkey]
try:
for group in group_table:
groups.append(str(group[grpkey]).strip())
except TypeError:
groups.append(str(group_table[grpkey]).strip())

# Now for the platform bug case, get the groups
if isinstance(rt, list):
# remove 1st element from the list as this is parsed already
rt.pop(0)
# iterate through other elements indexed by
# 'user' and add it to groups.
for each in rt:
groups.append(each['user'].strip())

# Some 'F' platforms use 'group' key instead
elif 'group' in resource_table:
# single group is a string, multiple groups in a list
groups = resource_table['group']
if isinstance(groups, str):
groups = [groups]

resource['group'] = groups

except (KeyError, AttributeError, IndexError, TypeError):
if not resource and body_text and 'No such entry' not in body_text:
# 6K and other platforms may not return structured output;
# attempt to get state from text output
resource = get_non_structured_snmp_user(body_text)

return resource


def get_non_structured_snmp_user(body_text):
# This method is a workaround for platforms that don't support structured
# output for 'show snmp user <foo>'. This workaround may not work on all
# platforms. Sample non-struct output:
#
# User Auth Priv(enforce) Groups acl_filter
# ____ ____ _____________ ______ __________
# sample1 no no network-admin ipv4:my_acl
# network-operator
# priv-11
# -OR-
# sample2 md5 des(no) priv-15
# -OR-
# sample3 md5 aes-128(no) network-admin
resource = {}
output = body_text.rsplit('__________')[-1]
pat = re.compile(r'^(?P<user>\S+)\s+'
r'(?P<auth>\S+)\s+'
r'(?P<priv>[\w\d-]+)(?P<enforce>\([\w\d-]+\))*\s+'
r'(?P<group>\S+)',
re.M)
m = re.search(pat, output)
if not m:
return resource
resource['user'] = m.group('user')
resource['auth'] = m.group('auth')
resource['encrypt'] = 'aes-128' if 'aes' in str(m.group('priv')) else 'none'

resource['group'] = [m.group('group')]
more_groups = re.findall(r'^\s+([\w\d-]+)\s*$', output, re.M)
if more_groups:
resource['group'] += more_groups

return resource

Expand Down
51 changes: 35 additions & 16 deletions test/integration/targets/nxos_snmp_user/tests/common/sanity.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@
when: ansible_connection == "local"

- name: Remove snmp user
nxos_snmp_user: &remove
nxos_snmp_user: &remove_snmp_user
user: ntc
provider: "{{ connection }}"
state: absent
ignore_errors: yes
when: platform is not search('N5K|N6K|N9K-F')

- name: Remove user workaround
# Some platforms will not allow snmp_user to remove the last role
nxos_user: &workaround_remove_user
name: ntc
provider: "{{ connection }}"
state: absent
ignore_errors: yes
when: platform is search('N5K|N6K|N9K-F')

- pause:
seconds: 5
Expand Down Expand Up @@ -64,27 +75,35 @@

- assert: *false

- name: delete snmp user
nxos_snmp_user: &remove1
user: ntc
group: network-operator
provider: "{{ connection }}"
state: absent
register: result
- block:
# Some platforms will not allow snmp_user to remove the last role
- name: delete snmp user
nxos_snmp_user: &remove1
user: ntc
group: network-operator
provider: "{{ connection }}"
state: absent
register: result

- assert: *true
- assert: *true

- pause:
seconds: 5
- pause:
seconds: 5

- name: "Remove Idempotence"
nxos_snmp_user: *remove1
register: result
- name: "Remove Idempotence"
nxos_snmp_user: *remove1
register: result

- assert: *false
- assert: *false
when: platform is not search('N5K|N6K|N9K-F')

always:
- name: delete snmp user
nxos_snmp_user: *remove
nxos_snmp_user: *remove_snmp_user
when: platform is not search('N5K|N6K|N9K-F')

- name: remove user workaround
nxos_user: *workaround_remove_user
when: platform is search('N5K|N6K|N9K-F')

- debug: msg="END connection={{ ansible_connection }} nxos_snmp_user sanity test"