Repository: ansible/ansible

Issue:
AttributeError: 'NoneType' object has no attribute 'group' iosxr_logging
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
iosxr_logging

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.4.0 (devel aed35aba70) last updated 2017/07/20 09:27:04 (GMT -400)
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/Users/dnewswan/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/dnewswan/code/ansible/lib/ansible
  executable location = /Users/dnewswan/code/ansible/bin/ansible
  python version = 2.7.13 (default, Apr  4 2017, 08:47:57) [GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.38)]
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->

##### SUMMARY
<!--- Explain the problem briefly -->

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->
` ansible-playbook -i inventory.network  iosxr.yaml -vvvv -u root -k -e limit_to=iosxr_logging`

<!--- Paste example playbooks or commands between quotes below -->
```yaml

```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
TASK [iosxr_logging : Set up host logging] ***********************************************************************************************************************************************************************************************************************************
task path: /Users/dnewswan/code/ansible/test/integration/targets/iosxr_logging/tests/cli/basic.yaml:2
<iosxr01> using connection plugin network_cli
<iosxr01> socket_path: /Users/dnewswan/.ansible/pc/c519def7ce
Using module_utils file /Users/dnewswan/code/ansible/lib/ansible/module_utils/basic.py
Using module_utils file /Users/dnewswan/code/ansible/lib/ansible/module_utils/iosxr.py
Using module_utils file /Users/dnewswan/code/ansible/lib/ansible/module_utils/_text.py
Using module_utils file /Users/dnewswan/code/ansible/lib/ansible/module_utils/parsing/convert_bool.py
Using module_utils file /Users/dnewswan/code/ansible/lib/ansible/module_utils/parsing/__init__.py
Using module_utils file /Users/dnewswan/code/ansible/lib/ansible/module_utils/pycompat24.py
Using module_utils file /Users/dnewswan/code/ansible/lib/ansible/module_utils/six/__init__.py
Using module_utils file /Users/dnewswan/code/ansible/lib/ansible/module_utils/six/_six.py
Using module_utils file /Users/dnewswan/code/ansible/lib/ansible/module_utils/connection.py
Using module_utils file /Users/dnewswan/code/ansible/lib/ansible/module_utils/network_common.py
Using module file /Users/dnewswan/code/ansible/lib/ansible/modules/network/iosxr/iosxr_logging.py
<iosxr01> ESTABLISH LOCAL CONNECTION FOR USER: dnewswan
<iosxr01> EXEC /bin/sh -c 'echo ~ && sleep 0'
<iosxr01> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /Users/dnewswan/.ansible/tmp/ansible-tmp-1500565779.7-23570874379006 `" && echo ansible-tmp-1500565779.7-23570874379006="` echo /Users/dnewswan/.ansible/tmp/ansible-tmp-1500565779.7-23570874379006 `" ) && sleep 0'
<iosxr01> PUT /var/folders/ql/d9_087wj4cd10grvwzxmk4hc0000gn/T/tmpRiQQSF TO /Users/dnewswan/.ansible/tmp/ansible-tmp-1500565779.7-23570874379006/iosxr_logging.py
<iosxr01> EXEC /bin/sh -c 'chmod u+x /Users/dnewswan/.ansible/tmp/ansible-tmp-1500565779.7-23570874379006/ /Users/dnewswan/.ansible/tmp/ansible-tmp-1500565779.7-23570874379006/iosxr_logging.py && sleep 0'
<iosxr01> EXEC /bin/sh -c 'python /Users/dnewswan/.ansible/tmp/ansible-tmp-1500565779.7-23570874379006/iosxr_logging.py; rm -rf "/Users/dnewswan/.ansible/tmp/ansible-tmp-1500565779.7-23570874379006/" > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/var/folders/ql/d9_087wj4cd10grvwzxmk4hc0000gn/T/ansible_GQ9W8l/ansible_module_iosxr_logging.py", line 358, in <module>
    main()
  File "/var/folders/ql/d9_087wj4cd10grvwzxmk4hc0000gn/T/ansible_GQ9W8l/ansible_module_iosxr_logging.py", line 344, in main
    have = map_config_to_obj(module)
  File "/var/folders/ql/d9_087wj4cd10grvwzxmk4hc0000gn/T/ansible_GQ9W8l/ansible_module_iosxr_logging.py", line 240, in map_config_to_obj
    if match.group(1) in dest_group:
AttributeError: 'NoneType' object has no attribute 'group'

fatal: [iosxr01]: FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "Traceback (most recent call last):\n  File \"/var/folders/ql/d9_087wj4cd10grvwzxmk4hc0000gn/T/ansible_GQ9W8l/ansible_module_iosxr_logging.py\", line 358, in <module>\n    main()\n  File \"/var/folders/ql/d9_087wj4cd10grvwzxmk4hc0000gn/T/ansible_GQ9W8l/ansible_module_iosxr_logging.py\", line 344, in main\n    have = map_config_to_obj(module)\n  File \"/var/folders/ql/d9_087wj4cd10grvwzxmk4hc0000gn/T/ansible_GQ9W8l/ansible_module_iosxr_logging.py\", line 240, in map_config_to_obj\n    if match.group(1) in dest_group:\nAttributeError: 'NoneType' object has no attribute 'group'\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE",
    "rc": 0
}
```



Discussion:
cc @privateip @rcarrillocruz @trishnag
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/network/iosxr/iosxr_logging.py b/lib/ansible/modules/network/iosxr/iosxr_logging.py
--- a/lib/ansible/modules/network/iosxr/iosxr_logging.py
+++ b/lib/ansible/modules/network/iosxr/iosxr_logging.py
@@ -122,7 +122,6 @@ def validate_size(value, module):
 def map_obj_to_commands(updates, module):
     commands = list()
     want, have = updates
-
     for w in want:
         dest = w['dest']
         name = w['name']
@@ -162,7 +161,6 @@ def map_obj_to_commands(updates, module):
                     dest_cmd += ' {}'.format(level)
 
                 commands.append(dest_cmd)
-
     return commands
 
 
@@ -208,7 +206,7 @@ def parse_name(line, dest):
 
 
 def parse_level(line, dest):
-    level_group = ('emergencies', 'alerts', 'critical', 'errors', 'warnings',
+    level_group = ('emergencies', 'alerts', 'critical', 'errors', 'warning',
                    'notifications', 'informational', 'debugging')
 
     if dest == 'hostnameprefix':
@@ -228,25 +226,25 @@ def parse_level(line, dest):
 
 
 def map_config_to_obj(module):
+
     obj = []
     dest_group = ('console', 'hostnameprefix', 'monitor', 'buffered', 'on')
 
     data = get_config(module, flags=['logging'])
+    lines = data.split("\n")
 
-    for line in data.split('\n'):
-
+    for line in lines:
         match = re.search(r'logging (\S+)', line, re.M)
-
-        if match.group(1) in dest_group:
-            dest = match.group(1)
-        else:
-            pass
-
-        obj.append({'dest': dest,
+        if match:
+            if match.group(1) in dest_group:
+                dest = match.group(1)
+                obj.append({
+                    'dest': dest,
                     'name': parse_name(line, dest),
                     'size': parse_size(line, dest),
                     'facility': parse_facility(line),
-                    'level': parse_level(line, dest)})
+                    'level': parse_level(line, dest)
+                })
 
     return obj
 


Test patch:
diff --git a/test/integration/targets/ios_logging/tests/cli/basic.yaml b/test/integration/targets/ios_logging/tests/cli/basic.yaml
--- a/test/integration/targets/ios_logging/tests/cli/basic.yaml
+++ b/test/integration/targets/ios_logging/tests/cli/basic.yaml
@@ -10,7 +10,7 @@
 
 - assert:
     that:
-      - 'result.chaned == true'
+      - 'result.changed == true'
       - '"logging host 172.16.0.1" in result.commands'
       - '"logging facility local7" in result.commands'
 
diff --git a/test/integration/targets/iosxr_logging/tests/cli/basic.yaml b/test/integration/targets/iosxr_logging/tests/cli/basic.yaml
--- a/test/integration/targets/iosxr_logging/tests/cli/basic.yaml
+++ b/test/integration/targets/iosxr_logging/tests/cli/basic.yaml
@@ -1,4 +1,29 @@
 ---
+# Remove old logging entries so that they don't conflict with tests
+- name: Remove host logging
+  iosxr_logging:
+    dest: hostnameprefix
+    name: 172.16.0.1
+    state: absent
+    provider: "{{ cli }}"
+
+- name: Remove console logging
+  iosxr_logging:
+    dest: console
+    level: warning
+    state: absent
+    provider: "{{ cli }}"
+  register: result
+
+- name: Remove buffer
+  iosxr_logging:
+    dest: buffered
+    size: 4800000
+    state: absent
+    provider: "{{ cli }}"
+  register: result
+
+# Start tests
 - name: Set up host logging
   iosxr_logging:
     dest: hostnameprefix
@@ -9,7 +34,7 @@
 
 - assert:
     that:
-      - 'result.chaned == true'
+      - 'result.changed == true'
       - '"logging hostnameprefix 172.16.0.1" in result.commands'
       - '"logging facility local7" in result.commands'
 
@@ -50,10 +75,10 @@
     that:
       - 'result.changed == false'
 
-- name: Console logging with level warnings
+- name: Console logging with level warning
   iosxr_logging:
     dest: console
-    level: warnings
+    level: warning
     state: present
     provider: "{{ cli }}"
   register: result
@@ -61,7 +86,7 @@
 - assert:
     that:
       - 'result.changed == true'
-      - '"logging console warnings" in result.commands'
+      - '"logging console warning" in result.commands'
 
 - name: Configure Buffer size
   iosxr_logging:
@@ -78,7 +103,7 @@
 - name: remove logging as collection tearDown
   iosxr_logging:
     aggregate:
-      - { dest: console, level: warnings, state: absent }
+      - { dest: console, level: warning, state: absent }
       - { dest: buffered, size: 4800000, state: absent }
     provider: "{{ cli }}"
   register: result