Repository: saltstack/salt
Pull request: Fix empty reactor traceback in reactor.py

### What does this PR do?

This PR prevent traceback when trying to list reactors when none are configured

### What issues does this PR fix or reference?

Fixes #53334
### Previous Behavior

`Passed invalid arguments: 'NoneType' object has no attribute '__getitem__'`

### New Behavior
`None`

### Tests written?

No



Problem statement:
reactor.list return "Passed invalid arguments" when no reactor are configured
### Description of Issue
When no reactors are configured, running `salt-run reactor.list` return:

```commandline

Passed invalid arguments: 'NoneType' object has no attribute '__getitem__'

Usage:

    List currently configured reactors

    CLI Example:

    .. code-block:: bash

        salt-run reactor.list
```

### Setup
Simple master minion setup without any reactor.

### Steps to Reproduce Issue
Logs:
```commandline
[DEBUG   ] Sending event: tag = salt/run/20190601094717037315/new; data = {u'fun': u'runner.reactor.list', u'fun_args': [], u'jid': u'20190601094717037315', u'user': u'root', u'_stamp': '2019-06-01T09:47:23.595386'}
[DEBUG   ] Sending event: tag = salt/run/20190601094717037315/salt/reactors/manage/list; data = {u'_stamp': '2019-06-01T09:47:23.597237'}
[DEBUG   ] LazyLoaded nested.output
event:
    ----------
    _stamp:
        2019-06-01T09:47:23.597237
suffix:
    salt/reactors/manage/list
[DEBUG   ] Sending event: tag = salt/run/20190601094717037315/ret; data = {u'fun_args': [], u'jid': u'20190601094717037315', u'return': u"\nPassed invalid arguments: 'NoneType' object has no attribute '__getitem__'\n\nUsage:\n\n    List currently configured reactors\n\n    CLI Example:\n\n    .. code-block:: bash\n\n        salt-run reactor.list\n    ", u'success': True, u'_stamp': '2019-06-01T09:47:53.675161', u'user': u'root', u'fun': u'runner.reactor.list'}
[DEBUG   ] LazyLoaded nested.output

Passed invalid arguments: 'NoneType' object has no attribute '__getitem__'

Usage:

    List currently configured reactors

    CLI Example:

    .. code-block:: bash

        salt-run reactor.list
    
[INFO    ] Runner completed: 20190601094717037315


```
### Versions Report
```commandline
Salt Version:
           Salt: 2019.2.0
 
Dependency Versions:
           cffi: Not Installed
       cherrypy: 3.5.0
       dateutil: 2.5.3
      docker-py: Not Installed
          gitdb: 2.0.0
      gitpython: 2.1.1
          ioflo: Not Installed
         Jinja2: 2.9.4
        libgit2: Not Installed
        libnacl: Not Installed
       M2Crypto: Not Installed
           Mako: Not Installed
   msgpack-pure: Not Installed
 msgpack-python: 0.4.8
   mysql-python: 1.3.7
      pycparser: Not Installed
       pycrypto: 2.6.1
   pycryptodome: Not Installed
         pygit2: Not Installed
         Python: 2.7.13 (default, Sep 26 2018, 18:42:22)
   python-gnupg: Not Installed
         PyYAML: 3.12
          PyZMQ: 16.0.2
           RAET: Not Installed
          smmap: 2.0.1
        timelib: Not Installed
        Tornado: 4.4.3
            ZMQ: 4.2.1
 
System Versions:
           dist: debian 9.8 
         locale: UTF-8
        machine: x86_64
        release: 5.0.17-300.fc30.x86_64
         system: Linux
        version: debian 9.8 

```

Hints from issue discussion:
I have replicated the bug.

Commit message: Merge branch 'master' into fix-empty-reactor

Patch to review:
diff --git a/salt/runners/reactor.py b/salt/runners/reactor.py
index 7e845127c608..3f25fcd5a19e 100644
--- a/salt/runners/reactor.py
+++ b/salt/runners/reactor.py
@@ -67,8 +67,8 @@ def list_(saltenv="base", test=None):
 
         __jid_event__.fire_event({"key": master_key}, "salt/reactors/manage/list")
 
-        results = sevent.get_event(wait=30, tag="salt/reactors/manage/list-results")
-        reactors = results["reactors"]
+        results = sevent.get_event(wait=30, tag="salt/reactors/manage/list-results")    
+        reactors = results.get('reactors', None)
         return reactors
 
 
@@ -105,6 +105,7 @@ def add(event, reactors, saltenv="base", test=None):
 
         res = sevent.get_event(wait=30, tag="salt/reactors/manage/add-complete")
         return res["result"]
+        return res.get('result', None)
 
 
 def delete(event, saltenv="base", test=None):
@@ -135,7 +136,7 @@ def delete(event, saltenv="base", test=None):
         )
 
         res = sevent.get_event(wait=30, tag="salt/reactors/manage/delete-complete")
-        return res["result"]
+        return res.get('result', None)
 
 
 def is_leader():


Code review comments:
diff_hunk: @@ -135,7 +136,7 @@ def delete(event, saltenv="base", test=None):
         )
 
         res = sevent.get_event(wait=30, tag="salt/reactors/manage/delete-complete")
-        return res["result"]
+        return res.get('result', None)
path: salt/runners/reactor.py
text: @user1:
```suggestion
        return res.get("result")
```

diff_hunk: @@ -105,6 +105,7 @@ def add(event, reactors, saltenv="base", test=None):
 
         res = sevent.get_event(wait=30, tag="salt/reactors/manage/add-complete")
         return res["result"]
+        return res.get('result', None)
path: salt/runners/reactor.py
text: @user1:
```suggestion
        return res.get("result")
```

diff_hunk: @@ -67,8 +67,8 @@ def list_(saltenv="base", test=None):
 
         __jid_event__.fire_event({"key": master_key}, "salt/reactors/manage/list")
 
-        results = sevent.get_event(wait=30, tag="salt/reactors/manage/list-results")
-        reactors = results["reactors"]
+        results = sevent.get_event(wait=30, tag="salt/reactors/manage/list-results")    
+        reactors = results.get('reactors', None)
path: salt/runners/reactor.py
text: @user1:
```suggestion
        reactors = results.get('reactors')
```
This does exactly the same.