Repository: saltstack/salt
Pull request: Fixing rabbitmq.list_user_permissions

### What does this PR do?
Fixing rabbitmq.list_user_permissions to ensure we are returning a permission list with three elements even when some values are empty.

### What issues does this PR fix or reference?
Fixes: #49115

### Merge requirements satisfied?
**[NOTICE] Bug fixes or features added to Salt require tests.**
<!-- Please review the [test documentation](https://docs.saltstack.com/en/master/topics/tutorials/writing_tests.html) for details on how to implement tests into Salt's test suite. -->
- [ ] Docs
- [x] Changelog - https://docs.saltstack.com/en/master/topics/development/changelog.html
- [x] Tests written/updated

### Commits signed with GPG?
Yes/No

Please review [Salt's Contributing Guide](https://docs.saltstack.com/en/master/topics/development/contributing.html) for best practices.

See GitHub's [page on GPG signing](https://help.github.com/articles/signing-commits-using-gpg/) for more information about signing commits with GPG.


Problem statement:
'rabbitmq_user.present' always report changes when read permisson is empty
### Description of Issue/Question

The state 'salt.states.rabbitmq_user' always report changes when the read permission is set to empty for a user.

### Setup
```
rabbit_user:
  rabbitmq_user.present:
    - name: user
    - password: password
    - perms:
      - 'test':
        - '.*'
        - '.*'
        - ''
```

### Steps to Reproduce Issue
Apply the state and it will always report changes:
```
----------
          ID: rabbit_user
    Function: rabbitmq_user.present
        Name: user
      Result: True
     Comment: 'user' was configured.
     Started: 15:47:08.424798
    Duration: 2112.54 ms
     Changes:   
              ----------
              perms:
                  ----------
                  new:
                      ----------
                      test:
                          - .*
                          - .*
                  old:
                      ----------
                      test:
                          - .*
                          - .*

Summary for local
------------
Succeeded: 1 (changed=1)
Failed:    0
------------
Total states run:     1
Total run time:   2.113 s
```

### Versions Report
(Provided by running `salt --versions-report`. Please also mention any differences in master/minion versions.)

```
Salt Version:
           Salt: 2017.7.7
 
Dependency Versions:
           cffi: 1.5.2
       cherrypy: Not Installed
       dateutil: 2.4.2
      docker-py: Not Installed
          gitdb: 0.6.4
      gitpython: 1.0.1
          ioflo: Not Installed
         Jinja2: 2.8
        libgit2: 0.24.0
        libnacl: Not Installed
       M2Crypto: 0.21.1
           Mako: 1.0.3
   msgpack-pure: Not Installed
 msgpack-python: 0.4.6
   mysql-python: Not Installed
      pycparser: 2.14
       pycrypto: 2.6.1
   pycryptodome: Not Installed
         pygit2: 0.24.0
         Python: 2.7.12 (default, Dec  4 2017, 14:50:18)
   python-gnupg: 0.3.8
         PyYAML: 3.11
          PyZMQ: 15.2.0
           RAET: Not Installed
          smmap: 0.9.0
        timelib: Not Installed
        Tornado: 4.2.1
            ZMQ: 4.1.4
 
System Versions:
           dist: Ubuntu 16.04 xenial
         locale: UTF-8
        machine: x86_64
        release: 4.4.0-131-generic
         system: Linux
        version: Ubuntu 16.04 xenial
```

Hints from issue discussion:
@polak785 thanks for the report.
Hello,

Any update on this bug? 

We still have it on Salt 3002.1 and with RabbitMQ 3.8.9
@polak785 Apologies for the delay on this one.  The issue is that when only two permissions are specified in the initial state run and the third is left as an empty string, on the second run the data returned from RabbitMQ only includes the non-empty permissions that were specified.  The change in the PR that is now linked checks that the returned data has three values, adding empty strings when necessary.
:star_struck:  Thanks a lot for fixing this bug and the explanations

Commit message: removing debugging lines.

Patch to review:
diff --git a/changelog/49115.fixed b/changelog/49115.fixed
new file mode 100644
index 000000000000..30ebe3c585c0
--- /dev/null
+++ b/changelog/49115.fixed
@@ -0,0 +1,2 @@
+
+Fixing rabbitmq.list_user_permissions to ensure we are returning a permission list with three elements even when some values are empty.
diff --git a/salt/modules/rabbitmq.py b/salt/modules/rabbitmq.py
index 7a4f9b4467c7..ff3fa70d74f3 100644
--- a/salt/modules/rabbitmq.py
+++ b/salt/modules/rabbitmq.py
@@ -1,11 +1,8 @@
-# -*- coding: utf-8 -*-
 """
 Module to provide RabbitMQ compatibility to Salt.
 Todo: A lot, need to add cluster support, logging, and minion configuration
 data.
 """
-# Import Python libs
-from __future__ import absolute_import, print_function, unicode_literals
 
 import logging
 import os
@@ -13,16 +10,12 @@
 import re
 import string
 
-# Import Salt libs
 import salt.utils.itertools
 import salt.utils.json
 import salt.utils.path
 import salt.utils.platform
 import salt.utils.user
 from salt.exceptions import CommandExecutionError, SaltInvocationError
-
-# Import 3rd-party libs
-from salt.ext import six
 from salt.ext.six.moves import range
 from salt.utils.versions import LooseVersion as _LooseVersion
 
@@ -53,10 +46,10 @@ def __virtual__():
             (dir_path, value_type) = winreg.QueryValueEx(key, "Install_Dir")
             if value_type != winreg.REG_SZ:
                 raise TypeError(
-                    "Invalid RabbitMQ Server directory type: {0}".format(value_type)
+                    "Invalid RabbitMQ Server directory type: {}".format(value_type)
                 )
             if not os.path.isdir(dir_path):
-                raise IOError("RabbitMQ directory not found: {0}".format(dir_path))
+                raise OSError("RabbitMQ directory not found: {}".format(dir_path))
             subdir_match = ""
             for name in os.listdir(dir_path):
                 if name.startswith("rabbitmq_server-"):
@@ -65,10 +58,8 @@ def __virtual__():
                     if os.path.isdir(subdir_path) and subdir_path > subdir_match:
                         subdir_match = subdir_path
             if not subdir_match:
-                raise IOError(
-                    '"rabbitmq_server-*" subdirectory not found in: {0}'.format(
-                        dir_path
-                    )
+                raise OSError(
+                    '"rabbitmq_server-*" subdirectory not found in: {}'.format(dir_path)
                 )
             RABBITMQCTL = os.path.join(subdir_match, "sbin", "rabbitmqctl.bat")
             RABBITMQ_PLUGINS = os.path.join(
@@ -92,24 +83,24 @@ def _check_response(response):
     if isinstance(response, dict):
         if response["retcode"] != 0 or response["stderr"]:
             raise CommandExecutionError(
-                "RabbitMQ command failed: {0}".format(response["stderr"])
+                "RabbitMQ command failed: {}".format(response["stderr"])
             )
     else:
         if "Error" in response:
-            raise CommandExecutionError("RabbitMQ command failed: {0}".format(response))
+            raise CommandExecutionError("RabbitMQ command failed: {}".format(response))
 
 
 def _format_response(response, msg):
     if isinstance(response, dict):
         if response["retcode"] != 0 or response["stderr"]:
             raise CommandExecutionError(
-                "RabbitMQ command failed: {0}".format(response["stderr"])
+                "RabbitMQ command failed: {}".format(response["stderr"])
             )
         else:
             response = response["stdout"]
     else:
         if "Error" in response:
-            raise CommandExecutionError("RabbitMQ command failed: {0}".format(response))
+            raise CommandExecutionError("RabbitMQ command failed: {}".format(response))
     return {msg: response}
 
 
@@ -125,7 +116,7 @@ def _get_rabbitmq_plugin():
     if RABBITMQ_PLUGINS is None:
         version = __salt__["pkg.version"]("rabbitmq-server").split("-")[0]
         RABBITMQ_PLUGINS = (
-            "/usr/lib/rabbitmq/lib/rabbitmq_server-{0}" "/sbin/rabbitmq-plugins"
+            "/usr/lib/rabbitmq/lib/rabbitmq_server-{}" "/sbin/rabbitmq-plugins"
         ).format(version)
 
     return RABBITMQ_PLUGINS
@@ -167,7 +158,7 @@ def _output_to_dict(cmdoutput, values_mapper=None):
     if isinstance(cmdoutput, dict):
         if cmdoutput["retcode"] != 0 or cmdoutput["stderr"]:
             raise CommandExecutionError(
-                "RabbitMQ command failed: {0}".format(cmdoutput["stderr"])
+                "RabbitMQ command failed: {}".format(cmdoutput["stderr"])
             )
         cmdoutput = cmdoutput["stdout"]
 
@@ -386,7 +377,7 @@ def add_user(name, password=None, runas=None):
         #         command,\r\noperable program or batch file.
         # Work around this by using a shell and a quoted command.
         python_shell = True
-        cmd = '"{0}" add_user "{1}" "{2}"'.format(RABBITMQCTL, name, password)
+        cmd = '"{}" add_user "{}" "{}"'.format(RABBITMQCTL, name, password)
     else:
         python_shell = False
         cmd = [RABBITMQCTL, "add_user", name, password]
@@ -456,7 +447,7 @@ def change_password(name, password, runas=None):
         #         command,\r\noperable program or batch file.
         # Work around this by using a shell and a quoted command.
         python_shell = True
-        cmd = '"{0}" change_password "{1}" "{2}"'.format(RABBITMQCTL, name, password)
+        cmd = '"{}" change_password "{}" "{}"'.format(RABBITMQCTL, name, password)
     else:
         python_shell = False
         cmd = [RABBITMQCTL, "change_password", name, password]
@@ -547,9 +538,7 @@ def check_password(name, password, runas=None):
             #         command,\r\noperable program or batch file.
             # Work around this by using a shell and a quoted command.
             python_shell = True
-            cmd = '"{0}" authenticate_user "{1}" "{2}"'.format(
-                RABBITMQCTL, name, password
-            )
+            cmd = '"{}" authenticate_user "{}" "{}"'.format(RABBITMQCTL, name, password)
         else:
             python_shell = False
             cmd = [RABBITMQCTL, "authenticate_user", name, password]
@@ -669,13 +658,19 @@ def list_permissions(vhost, runas=None):
     if runas is None and not salt.utils.platform.is_windows():
         runas = salt.utils.user.get_user()
     res = __salt__["cmd.run_all"](
-        [RABBITMQCTL, "list_permissions", "-q", "-p", vhost],
+        [RABBITMQCTL, "list_permissions", "--formatter=json", "-p", vhost],
         reset_system_locale=False,
         runas=runas,
         python_shell=False,
     )
 
-    return _output_to_dict(res)
+    perms = salt.utils.json.loads(res["stdout"])
+    perms_dict = {}
+    for perm in perms:
+        user = perm["user"]
+        perms_dict[user] = perm
+        del perms_dict[user]["user"]
+    return perms_dict
 
 
 def list_user_permissions(name, runas=None):
@@ -691,13 +686,19 @@ def list_user_permissions(name, runas=None):
     if runas is None and not salt.utils.platform.is_windows():
         runas = salt.utils.user.get_user()
     res = __salt__["cmd.run_all"](
-        [RABBITMQCTL, "list_user_permissions", name, "-q"],
+        [RABBITMQCTL, "list_user_permissions", name, "--formatter=json"],
         reset_system_locale=False,
         runas=runas,
         python_shell=False,
     )
 
-    return _output_to_dict(res)
+    perms = salt.utils.json.loads(res["stdout"])
+    perms_dict = {}
+    for perm in perms:
+        vhost = perm["vhost"]
+        perms_dict[vhost] = perm
+        del perms_dict[vhost]["vhost"]
+    return perms_dict
 
 
 def set_user_tags(name, tags, runas=None):
@@ -782,7 +783,7 @@ def join_cluster(host, user="rabbit", ram_node=None, runas=None):
     cmd = [RABBITMQCTL, "join_cluster"]
     if ram_node:
         cmd.append("--ram")
-    cmd.append("{0}@{1}".format(user, host))
+    cmd.append("{}@{}".format(user, host))
 
     if runas is None and not salt.utils.platform.is_windows():
         runas = salt.utils.user.get_user()
@@ -1013,7 +1014,7 @@ def set_policy(
         runas = salt.utils.user.get_user()
     if isinstance(definition, dict):
         definition = salt.utils.json.dumps(definition)
-    if not isinstance(definition, six.string_types):
+    if not isinstance(definition, str):
         raise SaltInvocationError(
             "The 'definition' argument must be a dictionary or JSON string"
         )
diff --git a/salt/states/rabbitmq_user.py b/salt/states/rabbitmq_user.py
index d1b8bd4273eb..9b243e7e5e74 100644
--- a/salt/states/rabbitmq_user.py
+++ b/salt/states/rabbitmq_user.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 """
 Manage RabbitMQ Users
 =====================
@@ -22,15 +21,11 @@
         - runas: rabbitmq
 """
 
-# Import python libs
-from __future__ import absolute_import, print_function, unicode_literals
 
 import logging
 
-# Import salt libs
 import salt.utils.path
 from salt.exceptions import CommandExecutionError
-from salt.ext import six
 
 log = logging.getLogger(__name__)
 
@@ -58,16 +53,18 @@ def _check_perms_changes(name, newperms, runas=None, existing=None):
             log.error("Error: %s", err)
             return False
 
+    empty_perms = {"configure": "", "write": "", "read": ""}
     perm_need_change = False
     for vhost_perms in newperms:
-        for vhost, perms in six.iteritems(vhost_perms):
+        for vhost, perms in vhost_perms.items():
             if vhost in existing:
+                new_perms = {"configure": perms[0], "write": perms[1], "read": perms[2]}
                 existing_vhost = existing[vhost]
-                if perms != existing_vhost:
+                if new_perms != existing_vhost:
                     # This checks for setting permissions to nothing in the state,
                     # when previous state runs have already set permissions to
                     # nothing. We don't want to report a change in this case.
-                    if existing_vhost == "" and perms == ["", "", ""]:
+                    if existing_vhost == empty_perms and perms == empty_perms:
                         continue
                     perm_need_change = True
             else:
@@ -109,7 +106,7 @@ def present(name, password=None, force=False, tags=None, perms=(), runas=None):
     try:
         user = __salt__["rabbitmq.user_exists"](name, runas=runas)
     except CommandExecutionError as err:
-        ret["comment"] = "Error: {0}".format(err)
+        ret["comment"] = "Error: {}".format(err)
         return ret
 
     passwd_reqs_update = False
@@ -119,7 +116,7 @@ def present(name, password=None, force=False, tags=None, perms=(), runas=None):
                 passwd_reqs_update = True
                 log.debug("RabbitMQ user %s password update required", name)
         except CommandExecutionError as err:
-            ret["comment"] = "Error: {0}".format(err)
+            ret["comment"] = "Error: {}".format(err)
             return ret
 
     if user and not any((force, perms, tags, passwd_reqs_update)):
@@ -130,7 +127,7 @@ def present(name, password=None, force=False, tags=None, perms=(), runas=None):
             ),
             name,
         )
-        ret["comment"] = "User '{0}' is already present.".format(name)
+        ret["comment"] = "User '{}' is already present.".format(name)
         ret["result"] = True
         return ret
 
@@ -138,14 +135,14 @@ def present(name, password=None, force=False, tags=None, perms=(), runas=None):
         ret["changes"].update({"user": {"old": "", "new": name}})
         if __opts__["test"]:
             ret["result"] = None
-            ret["comment"] = "User '{0}' is set to be created.".format(name)
+            ret["comment"] = "User '{}' is set to be created.".format(name)
             return ret
 
         log.debug("RabbitMQ user '%s' doesn't exist - Creating.", name)
         try:
             __salt__["rabbitmq.add_user"](name, password, runas=runas)
         except CommandExecutionError as err:
-            ret["comment"] = "Error: {0}".format(err)
+            ret["comment"] = "Error: {}".format(err)
             return ret
     else:
         log.debug("RabbitMQ user '%s' exists", name)
@@ -157,7 +154,7 @@ def present(name, password=None, force=False, tags=None, perms=(), runas=None):
                             name, password, runas=runas
                         )
                     except CommandExecutionError as err:
-                        ret["comment"] = "Error: {0}".format(err)
+                        ret["comment"] = "Error: {}".format(err)
                         return ret
                 ret["changes"].update({"password": {"old": "", "new": "Set password."}})
             else:
@@ -166,7 +163,7 @@ def present(name, password=None, force=False, tags=None, perms=(), runas=None):
                     try:
                         __salt__["rabbitmq.clear_password"](name, runas=runas)
                     except CommandExecutionError as err:
-                        ret["comment"] = "Error: {0}".format(err)
+                        ret["comment"] = "Error: {}".format(err)
                         return ret
                 ret["changes"].update(
                     {"password": {"old": "Removed password.", "new": ""}}
@@ -174,7 +171,7 @@ def present(name, password=None, force=False, tags=None, perms=(), runas=None):
 
     if tags is not None:
         current_tags = _get_current_tags(name, runas=runas)
-        if isinstance(tags, six.string_types):
+        if isinstance(tags, str):
             tags = tags.split()
         # Diff the tags sets. Symmetric difference operator ^ will give us
         # any element in one set, but not both
@@ -183,44 +180,50 @@ def present(name, password=None, force=False, tags=None, perms=(), runas=None):
                 try:
                     __salt__["rabbitmq.set_user_tags"](name, tags, runas=runas)
                 except CommandExecutionError as err:
-                    ret["comment"] = "Error: {0}".format(err)
+                    ret["comment"] = "Error: {}".format(err)
                     return ret
             ret["changes"].update({"tags": {"old": current_tags, "new": tags}})
     try:
         existing_perms = __salt__["rabbitmq.list_user_permissions"](name, runas=runas)
     except CommandExecutionError as err:
-        ret["comment"] = "Error: {0}".format(err)
+        ret["comment"] = "Error: {}".format(err)
         return ret
 
     if _check_perms_changes(name, perms, runas=runas, existing=existing_perms):
         for vhost_perm in perms:
-            for vhost, perm in six.iteritems(vhost_perm):
+            for vhost, perm in vhost_perm.items():
                 if not __opts__["test"]:
                     try:
                         __salt__["rabbitmq.set_permissions"](
                             vhost, name, perm[0], perm[1], perm[2], runas=runas
                         )
                     except CommandExecutionError as err:
-                        ret["comment"] = "Error: {0}".format(err)
+                        ret["comment"] = "Error: {}".format(err)
                         return ret
-                new_perms = {vhost: perm}
-                if existing_perms != new_perms:
-                    if ret["changes"].get("perms") is None:
-                        ret["changes"].update({"perms": {"old": {}, "new": {}}})
-                    ret["changes"]["perms"]["old"].update(existing_perms)
+                new_perms = {
+                    vhost: {"configure": perm[0], "write": perm[1], "read": perm[2]}
+                }
+                if vhost in existing_perms:
+                    if existing_perms[vhost] != new_perms[vhost]:
+                        if ret["changes"].get("perms") is None:
+                            ret["changes"].update({"perms": {"old": {}, "new": {}}})
+                        ret["changes"]["perms"]["old"].update(existing_perms[vhost])
+                        ret["changes"]["perms"]["new"].update(new_perms)
+                else:
+                    ret["changes"].update({"perms": {"new": {}}})
                     ret["changes"]["perms"]["new"].update(new_perms)
 
     ret["result"] = True
     if ret["changes"] == {}:
-        ret["comment"] = "'{0}' is already in the desired state.".format(name)
+        ret["comment"] = "'{}' is already in the desired state.".format(name)
         return ret
 
     if __opts__["test"]:
         ret["result"] = None
-        ret["comment"] = "Configuration for '{0}' will change.".format(name)
+        ret["comment"] = "Configuration for '{}' will change.".format(name)
         return ret
 
-    ret["comment"] = "'{0}' was configured.".format(name)
+    ret["comment"] = "'{}' was configured.".format(name)
     return ret
 
 
@@ -238,7 +241,7 @@ def absent(name, runas=None):
     try:
         user_exists = __salt__["rabbitmq.user_exists"](name, runas=runas)
     except CommandExecutionError as err:
-        ret["comment"] = "Error: {0}".format(err)
+        ret["comment"] = "Error: {}".format(err)
         return ret
 
     if user_exists:
@@ -246,19 +249,19 @@ def absent(name, runas=None):
             try:
                 __salt__["rabbitmq.delete_user"](name, runas=runas)
             except CommandExecutionError as err:
-                ret["comment"] = "Error: {0}".format(err)
+                ret["comment"] = "Error: {}".format(err)
                 return ret
         ret["changes"].update({"name": {"old": name, "new": ""}})
     else:
         ret["result"] = True
-        ret["comment"] = "The user '{0}' is not present.".format(name)
+        ret["comment"] = "The user '{}' is not present.".format(name)
         return ret
 
     if __opts__["test"] and ret["changes"]:
         ret["result"] = None
-        ret["comment"] = "The user '{0}' will be removed.".format(name)
+        ret["comment"] = "The user '{}' will be removed.".format(name)
         return ret
 
     ret["result"] = True
-    ret["comment"] = "The user '{0}' was removed.".format(name)
+    ret["comment"] = "The user '{}' was removed.".format(name)
     return ret
diff --git a/tests/pytests/functional/states/rabbitmq/conftest.py b/tests/pytests/functional/states/rabbitmq/conftest.py
new file mode 100644
index 000000000000..c625614441b3
--- /dev/null
+++ b/tests/pytests/functional/states/rabbitmq/conftest.py
@@ -0,0 +1,116 @@
+import logging
+import time
+
+import attr
+import pytest
+from saltfactories.daemons.container import Container
+from saltfactories.utils import random_string
+from saltfactories.utils.ports import get_unused_localhost_port
+
+docker = pytest.importorskip("docker")
+docker_errors = pytest.importorskip("docker.errors")
+
+log = logging.getLogger(__name__)
+
+
+@attr.s(kw_only=True, slots=True)
+class RabbitMQImage:
+    name = attr.ib()
+    tag = attr.ib()
+    container_id = attr.ib()
+
+    def __str__(self):
+        return "{}:{}".format(self.name, self.tag)
+
+
+@attr.s(kw_only=True, slots=True)
+class RabbitMQCombo:
+    rabbitmq_name = attr.ib()
+    rabbitmq_version = attr.ib()
+    rabbitmq_port = attr.ib()
+
+    @rabbitmq_port.default
+    def _rabbitmq_port(self):
+        return get_unused_localhost_port()
+
+
+def get_test_versions():
+    test_versions = []
+    name = "rabbitmq"
+    for version in ("3.8",):
+        test_versions.append(
+            RabbitMQImage(
+                name=name,
+                tag=version,
+                container_id=random_string("rabbitmq-{}-".format(version)),
+            )
+        )
+    return test_versions
+
+
+def get_test_version_id(value):
+    return "container={}".format(value)
+
+
+@pytest.fixture(scope="module", params=get_test_versions(), ids=get_test_version_id)
+def rabbitmq_container(request, salt_factories, modules):
+
+    try:
+        docker_client = docker.from_env()
+    except docker_errors.DockerException:
+        pytest.skip("Failed to get a connection to docker running on the system")
+    connectable = Container.client_connectable(docker_client)
+    if connectable is not True:  # pragma: no cover
+        pytest.skip(connectable)
+
+    rabbitmq_image = request.param
+
+    combo = RabbitMQCombo(
+        rabbitmq_name=rabbitmq_image.name, rabbitmq_version=rabbitmq_image.tag,
+    )
+    container = salt_factories.get_container(
+        rabbitmq_image.container_id,
+        "{}:{}".format(combo.rabbitmq_name, combo.rabbitmq_version),
+        docker_client=docker_client,
+    )
+    with container.started():
+        # Sleep
+        log.debug("=== initial sleep")
+        time.sleep(10)
+
+        authenticated = False
+        login_attempts = 6
+        while login_attempts:
+            log.debug("=== login attempt %s ===", login_attempts)
+            login_attempts -= 1
+            ret = container.run("rabbitmqctl status --formatter=json")
+            log.debug("=== ret %s ===", ret)
+            authenticated = ret.exitcode == 0
+            if authenticated:
+                break
+
+            log.debug("=== sleep ===")
+            time.sleep(10)
+
+        if authenticated:
+            yield container
+        else:
+            pytest.fail(
+                "Failed to connect to rabbitmq in container(id: {})".format(
+                    rabbitmq_image.container_id
+                )
+            )
+
+
+@pytest.fixture(scope="module")
+def docker_cmd_run_all_wrapper(rabbitmq_container):
+    def run_command(cmd, **kwargs):
+        # Update rabbitmqctl location
+        if cmd[0] is None:
+            cmd[0] = "/opt/rabbitmq/sbin/rabbitmqctl"
+
+        ret = rabbitmq_container.run(cmd)
+        res = {"retcode": ret.exitcode, "stdout": ret.stdout, "stderr": ret.stderr}
+        return res
+
+    return run_command
diff --git a/tests/pytests/functional/states/rabbitmq/test_cluster.py b/tests/pytests/functional/states/rabbitmq/test_cluster.py
new file mode 100644
index 000000000000..f27911c6af5e
--- /dev/null
+++ b/tests/pytests/functional/states/rabbitmq/test_cluster.py
@@ -0,0 +1,55 @@
+"""
+Integration tests for the rabbitmq_cluster states
+"""
+
+import logging
+
+import pytest
+import salt.modules.rabbitmq as rabbitmq
+import salt.states.rabbitmq_cluster as rabbitmq_cluster
+
+log = logging.getLogger(__name__)
+
+pytestmark = [
+    pytest.mark.slow_test,
+    pytest.mark.skip_on_freebsd(reason="No Docker on FreeBSD available"),
+    pytest.mark.skip_if_binaries_missing(
+        "docker", "dockerd", reason="Docker not installed"
+    ),
+]
+
+
+@pytest.fixture
+def configure_loader_modules(docker_cmd_run_all_wrapper):
+    return {
+        rabbitmq_cluster: {
+            "__salt__": {
+                "rabbitmq.cluster_status": rabbitmq.cluster_status,
+                "rabbitmq.join_cluster": rabbitmq.join_cluster,
+            },
+            "__opts__": {"test": False},
+            "_utils__": {},
+        },
+        rabbitmq: {
+            "__salt__": {"cmd.run_all": docker_cmd_run_all_wrapper},
+            "__opts__": {},
+            "_utils__": {},
+        },
+    }
+
+
+@pytest.mark.slow_test
+def test_joined(rabbitmq_container):
+    """
+    Test rabbitmq_cluster.joined
+    """
+
+    hostname = rabbitmq_container.container.attrs["Config"]["Hostname"]
+    ret = rabbitmq_cluster.joined("name", host=hostname)
+    expected = {
+        "name": "name",
+        "result": True,
+        "comment": "Already in cluster",
+        "changes": {},
+    }
+    assert ret == expected
diff --git a/tests/pytests/functional/states/rabbitmq/test_plugin.py b/tests/pytests/functional/states/rabbitmq/test_plugin.py
new file mode 100644
index 000000000000..512a5af98e8f
--- /dev/null
+++ b/tests/pytests/functional/states/rabbitmq/test_plugin.py
@@ -0,0 +1,132 @@
+"""
+Integration tests for the rabbitmq_plugin states
+"""
+
+import logging
+
+import pytest
+import salt.modules.rabbitmq as rabbitmq
+import salt.states.rabbitmq_plugin as rabbitmq_plugin
+from tests.support.mock import patch
+
+log = logging.getLogger(__name__)
+
+pytestmark = [
+    pytest.mark.slow_test,
+    pytest.mark.skip_on_freebsd(reason="No Docker on FreeBSD available"),
+    pytest.mark.skip_if_binaries_missing(
+        "docker", "dockerd", reason="Docker not installed"
+    ),
+]
+
+
+def mock_get_rabbitmq_plugin():
+    return "/opt/rabbitmq/sbin/rabbitmq-plugins"
+
+
+@pytest.fixture
+def configure_loader_modules(docker_cmd_run_all_wrapper):
+    return {
+        rabbitmq_plugin: {
+            "__salt__": {
+                "rabbitmq.plugin_is_enabled": rabbitmq.plugin_is_enabled,
+                "rabbitmq.enable_plugin": rabbitmq.enable_plugin,
+                "rabbitmq.disable_plugin": rabbitmq.disable_plugin,
+            },
+            "__opts__": {"test": False},
+            "_utils__": {},
+        },
+        rabbitmq: {
+            "__salt__": {"cmd.run_all": docker_cmd_run_all_wrapper},
+            "__opts__": {},
+            "_utils__": {},
+        },
+    }
+
+
+@pytest.mark.slow_test
+def test_enabled_enabled_disabled(rabbitmq_container):
+    """
+    Test rabbitmq_plugin.enabled and rabbitmq_plugin_disabled
+
+    First enable the plugin.
+
+    Second try to enable the plugin again.
+
+    Third, try to disable the plugin.
+    """
+
+    with patch.object(rabbitmq, "_get_rabbitmq_plugin", mock_get_rabbitmq_plugin):
+        # Enable the plugin
+        ret = rabbitmq_plugin.enabled("rabbitmq_auth_backend_http")
+        expected = {
+            "name": "rabbitmq_auth_backend_http",
+            "result": True,
+            "comment": "Plugin 'rabbitmq_auth_backend_http' was enabled.",
+            "changes": {"old": "", "new": "rabbitmq_auth_backend_http"},
+        }
+        assert ret == expected
+
+        # Try to enable the plugin again
+        ret = rabbitmq_plugin.enabled("rabbitmq_auth_backend_http")
+        expected = {
+            "name": "rabbitmq_auth_backend_http",
+            "result": True,
+            "comment": "Plugin 'rabbitmq_auth_backend_http' is already enabled.",
+            "changes": {},
+        }
+        assert ret == expected
+
+        # Disable the plugin
+        ret = rabbitmq_plugin.disabled("rabbitmq_auth_backend_http")
+        expected = {
+            "name": "rabbitmq_auth_backend_http",
+            "result": True,
+            "comment": "Plugin 'rabbitmq_auth_backend_http' was disabled.",
+            "changes": {"new": "", "old": "rabbitmq_auth_backend_http"},
+        }
+        assert ret == expected
+
+
+@pytest.mark.slow_test
+def test_disabled(rabbitmq_container):
+    """
+    Test rabbitmq_plugin.enabled and rabbitmq_plugin_disabled
+
+    First try to disable the plugin.
+
+    Second enable the plugin again.
+
+    Third disable the plugin.
+    """
+
+    with patch.object(rabbitmq, "_get_rabbitmq_plugin", mock_get_rabbitmq_plugin):
+        # Try to disable the plugin
+        ret = rabbitmq_plugin.disabled("rabbitmq_auth_backend_http")
+        expected = {
+            "name": "rabbitmq_auth_backend_http",
+            "result": True,
+            "comment": "Plugin 'rabbitmq_auth_backend_http' is already disabled.",
+            "changes": {},
+        }
+        assert ret == expected
+
+        # Enable the plugin
+        ret = rabbitmq_plugin.enabled("rabbitmq_auth_backend_http")
+        expected = {
+            "name": "rabbitmq_auth_backend_http",
+            "result": True,
+            "comment": "Plugin 'rabbitmq_auth_backend_http' was enabled.",
+            "changes": {"old": "", "new": "rabbitmq_auth_backend_http"},
+        }
+        assert ret == expected
+
+        # Disable the plugin
+        ret = rabbitmq_plugin.disabled("rabbitmq_auth_backend_http")
+        expected = {
+            "name": "rabbitmq_auth_backend_http",
+            "result": True,
+            "comment": "Plugin 'rabbitmq_auth_backend_http' was disabled.",
+            "changes": {"new": "", "old": "rabbitmq_auth_backend_http"},
+        }
+        assert ret == expected
diff --git a/tests/pytests/functional/states/rabbitmq/test_policy.py b/tests/pytests/functional/states/rabbitmq/test_policy.py
new file mode 100644
index 000000000000..46ea381c93f5
--- /dev/null
+++ b/tests/pytests/functional/states/rabbitmq/test_policy.py
@@ -0,0 +1,94 @@
+"""
+Integration tests for the rabbitmq_policy states
+"""
+
+import logging
+
+import pytest
+import salt.modules.rabbitmq as rabbitmq
+import salt.states.rabbitmq_policy as rabbitmq_policy
+from tests.support.mock import MagicMock, patch
+
+log = logging.getLogger(__name__)
+
+pytestmark = [
+    pytest.mark.slow_test,
+    pytest.mark.skip_on_freebsd(reason="No Docker on FreeBSD available"),
+    pytest.mark.skip_if_binaries_missing(
+        "docker", "dockerd", reason="Docker not installed"
+    ),
+]
+
+
+@pytest.fixture
+def configure_loader_modules(docker_cmd_run_all_wrapper):
+    return {
+        rabbitmq_policy: {
+            "__salt__": {
+                "rabbitmq.set_policy": rabbitmq.set_policy,
+                "rabbitmq.delete_policy": rabbitmq.delete_policy,
+                "rabbitmq.policy_exists": rabbitmq.policy_exists,
+                "rabbitmq.list_policies": rabbitmq.list_policies,
+            },
+            "__opts__": {"test": False},
+            "_utils__": {},
+        },
+        rabbitmq: {
+            "__salt__": {
+                "rabbitmq.list_policies": rabbitmq.list_policies,
+                "cmd.run_all": docker_cmd_run_all_wrapper,
+            },
+            "__grains__": {"os_family": "Linux"},
+            "__opts__": {},
+            "_utils__": {},
+        },
+    }
+
+
+@pytest.mark.slow_test
+def test_present_absent(rabbitmq_container):
+    """
+    Test rabbitmq_policy.present and rabbitmq_policy.absent
+    """
+
+    with patch.dict(rabbitmq.__salt__, {"pkg.version": MagicMock(return_value="3.8")}):
+        # Clear the policy
+        ret = rabbitmq_policy.present(
+            name="HA", pattern=".*", definition={"ha-mode": "all"}
+        )
+        expected = {
+            "name": "HA",
+            "result": True,
+            "comment": 'Setting policy "HA" for pattern ".*" to "{"ha-mode": "all"}" with priority "0" for vhost "/" ...\n',
+            "changes": {"old": {}, "new": "HA"},
+        }
+        assert ret == expected
+
+        # Delete the policy
+        ret = rabbitmq_policy.absent("HA")
+        expected = {
+            "name": "HA",
+            "result": True,
+            "comment": "Deleted",
+            "changes": {"new": "", "old": "HA"},
+        }
+
+        assert ret == expected
+
+
+def test_absent(rabbitmq_container):
+    """
+    Test rabbitmq_policy.absent
+    """
+
+    with patch.dict(rabbitmq.__salt__, {"pkg.version": MagicMock(return_value="3.8")}):
+        # Delete the policy
+        ret = rabbitmq_policy.absent("HA")
+        expected = {
+            "name": "HA",
+            "result": True,
+            "comment": "Policy '/ HA' is not present.",
+            "changes": {},
+        }
+
+        assert ret == expected
diff --git a/tests/pytests/functional/states/rabbitmq/test_upstream.py b/tests/pytests/functional/states/rabbitmq/test_upstream.py
new file mode 100644
index 000000000000..f8f53757c15d
--- /dev/null
+++ b/tests/pytests/functional/states/rabbitmq/test_upstream.py
@@ -0,0 +1,54 @@
+"""
+Integration tests for the rabbitmq_user states
+"""
+
+import logging
+
+import pytest
+import salt.modules.rabbitmq as rabbitmq
+import salt.states.rabbitmq_upstream as rabbitmq_upstream
+
+log = logging.getLogger(__name__)
+
+pytestmark = [
+    pytest.mark.slow_test,
+    pytest.mark.skip_on_freebsd(reason="No Docker on FreeBSD available"),
+    pytest.mark.skip_if_binaries_missing(
+        "docker", "dockerd", reason="Docker not installed"
+    ),
+]
+
+
+@pytest.fixture
+def configure_loader_modules(docker_cmd_run_all_wrapper):
+    return {
+        rabbitmq_upstream: {
+            "__salt__": {
+                "rabbitmq.upstream_exists": rabbitmq.upstream_exists,
+                "rabbitmq.list_user_permissions": rabbitmq.list_user_permissions,
+            },
+            "__opts__": {"test": False},
+            "_utils__": {},
+        },
+        rabbitmq: {
+            "__salt__": {"cmd.run_all": docker_cmd_run_all_wrapper},
+            "__opts__": {},
+            "_utils__": {},
+        },
+    }
+
+
+def test_absent(rabbitmq_container):
+    """
+    Test rabbitmq_upstream.absent
+    """
+
+    # Delete the user
+    ret = rabbitmq_upstream.absent("upstream")
+    expected = {
+        "name": "upstream",
+        "result": True,
+        "comment": 'The upstream "upstream" is already absent.',
+        "changes": {},
+    }
+    assert ret == expected
diff --git a/tests/pytests/functional/states/rabbitmq/test_user.py b/tests/pytests/functional/states/rabbitmq/test_user.py
new file mode 100644
index 000000000000..a2d215427533
--- /dev/null
+++ b/tests/pytests/functional/states/rabbitmq/test_user.py
@@ -0,0 +1,91 @@
+"""
+Integration tests for the rabbitmq_user states
+"""
+
+import logging
+
+import pytest
+import salt.modules.rabbitmq as rabbitmq
+import salt.states.rabbitmq_user as rabbitmq_user
+
+log = logging.getLogger(__name__)
+
+pytestmark = [
+    pytest.mark.slow_test,
+    pytest.mark.skip_on_freebsd(reason="No Docker on FreeBSD available"),
+    pytest.mark.skip_if_binaries_missing(
+        "docker", "dockerd", reason="Docker not installed"
+    ),
+]
+
+
+@pytest.fixture
+def configure_loader_modules(docker_cmd_run_all_wrapper):
+    return {
+        rabbitmq_user: {
+            "__salt__": {
+                "rabbitmq.user_exists": rabbitmq.user_exists,
+                "rabbitmq.add_user": rabbitmq.add_user,
+                "rabbitmq.delete_user": rabbitmq.delete_user,
+                "rabbitmq.list_user_permissions": rabbitmq.list_user_permissions,
+            },
+            "__opts__": {"test": False},
+            "_utils__": {},
+        },
+        rabbitmq: {
+            "__salt__": {
+                "rabbitmq.user_exists": rabbitmq.user_exists,
+                "rabbitmq.add_user": rabbitmq.add_user,
+                "rabbitmq.list_user_permissions": rabbitmq.list_user_permissions,
+                "cmd.run_all": docker_cmd_run_all_wrapper,
+            },
+            "__opts__": {},
+            "_utils__": {},
+        },
+    }
+
+
+@pytest.mark.slow_test
+def test_present_absent(docker_cmd_run_all_wrapper, rabbitmq_container):
+    """
+    Test rabbitmq_user.present
+
+    Create user then delete it.
+    """
+
+    # Clear the user
+    ret = rabbitmq_user.present("myuser")
+    expected = {
+        "name": "myuser",
+        "result": True,
+        "comment": "'myuser' was configured.",
+        "changes": {"user": {"old": "", "new": "myuser"}},
+    }
+    assert ret == expected
+
+    # Delete the user
+    ret = rabbitmq_user.absent("myuser")
+    expected = {
+        "name": "myuser",
+        "result": True,
+        "comment": "The user 'myuser' was removed.",
+        "changes": {"name": {"old": "myuser", "new": ""}},
+    }
+
+    assert ret == expected
+
+
+def test_absent(docker_cmd_run_all_wrapper, rabbitmq_container):
+    """
+    Test rabbitmq_user.absent
+    """
+
+    # Delete the user
+    ret = rabbitmq_user.absent("myuser")
+    expected = {
+        "name": "myuser",
+        "result": True,
+        "comment": "The user 'myuser' is not present.",
+        "changes": {},
+    }
+    assert ret == expected
diff --git a/tests/pytests/functional/states/rabbitmq/test_vhost.py b/tests/pytests/functional/states/rabbitmq/test_vhost.py
new file mode 100644
index 000000000000..54e5653857fe
--- /dev/null
+++ b/tests/pytests/functional/states/rabbitmq/test_vhost.py
@@ -0,0 +1,83 @@
+"""
+Integration tests for the rabbitmq_user states
+"""
+
+import logging
+
+import pytest
+import salt.modules.rabbitmq as rabbitmq
+import salt.states.rabbitmq_vhost as rabbitmq_vhost
+
+log = logging.getLogger(__name__)
+
+pytestmark = [
+    pytest.mark.slow_test,
+    pytest.mark.skip_on_freebsd(reason="No Docker on FreeBSD available"),
+    pytest.mark.skip_if_binaries_missing(
+        "docker", "dockerd", reason="Docker not installed"
+    ),
+]
+
+
+@pytest.fixture
+def configure_loader_modules(docker_cmd_run_all_wrapper):
+    return {
+        rabbitmq_vhost: {
+            "__salt__": {
+                "rabbitmq.vhost_exists": rabbitmq.vhost_exists,
+                "rabbitmq.add_vhost": rabbitmq.add_vhost,
+                "rabbitmq.delete_vhost": rabbitmq.delete_vhost,
+            },
+            "__opts__": {"test": False},
+            "_utils__": {},
+        },
+        rabbitmq: {
+            "__salt__": {"cmd.run_all": docker_cmd_run_all_wrapper},
+            "__opts__": {},
+            "_utils__": {},
+        },
+    }
+
+
+@pytest.mark.slow_test
+def test_present_absent(docker_cmd_run_all_wrapper):
+    """
+    Test rabbitmq_vhost.present
+    """
+
+    # Clear the user
+    ret = rabbitmq_vhost.present("vhost")
+    expected = {
+        "name": "vhost",
+        "result": True,
+        "comment": 'Adding vhost "vhost" ...\n',
+        "changes": {"old": "", "new": "vhost"},
+    }
+    assert ret == expected
+
+    # Delete the user
+    ret = rabbitmq_vhost.absent("vhost")
+    expected = {
+        "name": "vhost",
+        "result": True,
+        "comment": 'Deleting vhost "vhost" ...\n',
+        "changes": {"old": "vhost", "new": ""},
+    }
+
+    assert ret == expected
+
+
+def test_absent(docker_cmd_run_all_wrapper):
+    """
+    Test rabbitmq_vhost.present
+    """
+
+    # Delete the user
+    ret = rabbitmq_vhost.absent("vhost")
+    expected = {
+        "name": "vhost",
+        "result": True,
+        "comment": "Virtual Host 'vhost' is not present.",
+        "changes": {},
+    }
+    assert ret == expected
diff --git a/tests/pytests/unit/modules/test_rabbitmq.py b/tests/pytests/unit/modules/test_rabbitmq.py
new file mode 100644
index 000000000000..fa2affaf57f1
--- /dev/null
+++ b/tests/pytests/unit/modules/test_rabbitmq.py
@@ -0,0 +1,832 @@
+"""
+    :codeauthor: Jayesh Kariya <jayeshk@saltstack.com>
+"""
+
+
+import logging
+
+import pytest
+import salt.modules.rabbitmq as rabbitmq
+from salt.exceptions import CommandExecutionError
+from tests.support.mock import MagicMock, patch
+
+log = logging.getLogger(__name__)
+
+
+@pytest.fixture
+def configure_loader_modules():
+    return {rabbitmq: {"__context__": {"rabbitmqctl": None, "rabbitmq-plugins": None}}}
+
+
+# 'list_users_rabbitmq2' function tests: 1
+def test_list_users_rabbitmq2():
+    """
+    Test if it return a list of users based off of rabbitmqctl user_list.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": "Listing users ...\nguest\t[administrator, user]\njustAnAdmin\t[administrator]\n",
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.list_users() == {
+            "guest": ["administrator", "user"],
+            "justAnAdmin": ["administrator"],
+        }
+
+
+# 'list_users_rabbitmq3' function tests: 1
+def test_list_users_rabbitmq3():
+    """
+    Test if it return a list of users based off of rabbitmqctl user_list.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": "guest\t[administrator user]\r\nother\t[a b]\r\n",
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.list_users() == {
+            "guest": ["administrator", "user"],
+            "other": ["a", "b"],
+        }
+
+
+# 'list_users_with_warning_rabbitmq2' function tests: 1
+def test_list_users_with_warning_rabbitmq2():
+    """
+    Test if having a leading WARNING returns the user_list anyway.
+    """
+    rtn_stdout = "\n".join(
+        [
+            "WARNING: ignoring /etc/rabbitmq/rabbitmq.conf -- location has moved to /etc/rabbitmq/rabbitmq-env.conf",
+            "Listing users ...",
+            "guest\t[administrator, user]\n",
+        ]
+    )
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": rtn_stdout, "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.list_users() == {"guest": ["administrator", "user"]}
+
+
+# 'list_users_with_warning_rabbitmq3' function tests: 1
+def test_list_users_with_warning_rabbitmq3():
+    """
+    Test if having a leading WARNING returns the user_list anyway.
+    """
+    rtn_stdout = "\n".join(
+        [
+            "WARNING: ignoring /etc/rabbitmq/rabbitmq.conf -- location has moved to /etc/rabbitmq/rabbitmq-env.conf",
+            "Listing users ...",
+            "guest\t[administrator user]\n",
+        ]
+    )
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": rtn_stdout, "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.list_users() == {"guest": ["administrator", "user"]}
+
+
+# 'list_vhosts' function tests: 2
+def test_list_vhosts():
+    """
+    Test if it return a list of vhost based on rabbitmqctl list_vhosts.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "/\nsaltstack\n...", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.list_vhosts() == ["/", "saltstack", "..."]
+
+
+def test_list_vhosts_with_warning():
+    """
+    Test if it return a list of vhost based on rabbitmqctl list_vhosts even with a leading WARNING.
+    """
+    rtn_stdout = "\n".join(
+        [
+            "WARNING: ignoring /etc/rabbitmq/rabbitmq.conf -- location has moved to /etc/rabbitmq/rabbitmq-env.conf",
+            "Listing users ...",
+            "/",
+            "saltstack",
+            "...\n",
+        ]
+    )
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": rtn_stdout, "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.list_vhosts() == ["/", "saltstack", "..."]
+
+
+# 'user_exists' function tests: 2
+def test_user_exists():
+    """
+    Test whether a given rabbitmq-internal user exists based
+    on rabbitmqctl list_users.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": "Listing users ...\n" "saltstack\t[administrator]\n...done",
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.user_exists("saltstack")
+
+
+def test_user_exists_negative():
+    """
+    Negative test of whether rabbitmq-internal user exists based
+    on rabbitmqctl list_users.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": "Listing users ...\n" "saltstack\t[administrator]\n...done",
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert not rabbitmq.user_exists("salt")
+
+
+# 'vhost_exists' function tests: 2
+def test_vhost_exists():
+    """
+    Test if it return whether the vhost exists based
+    on rabbitmqctl list_vhosts.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": "Listing vhosts ...\nsaltstack",
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.vhost_exists("saltstack")
+
+
+def test_vhost_exists_negative():
+    """
+    Test if it return whether the vhost exists based
+    on rabbitmqctl list_vhosts.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": "Listing vhosts ...\nsaltstack",
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert not rabbitmq.vhost_exists("salt")
+
+
+# 'add_user' function tests: 1
+def test_add_user():
+    """
+    Test if it add a rabbitMQ user via rabbitmqctl
+    user_add <user> <password>
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.add_user("saltstack") == {"Added": "saltstack"}
+
+    mock_run = MagicMock(return_value="Error")
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        with patch.object(
+            rabbitmq, "clear_password", return_value={"Error": "Error", "retcode": 1},
+        ):
+            pytest.raises(CommandExecutionError, rabbitmq.add_user, "saltstack")
+
+
+# 'delete_user' function tests: 1
+def test_delete_user():
+    """
+    Test if it deletes a user via rabbitmqctl delete_user.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.delete_user("saltstack") == {"Deleted": "saltstack"}
+
+
+# 'check_password' function tests: 2
+def test_check_password_lt_38():
+    """
+    Test if it checks a user's password for RabbitMQ less than v3.8.
+    """
+    mock_run = MagicMock(return_value='{rabbit,"RabbitMQ","3.5.7"}')
+    mock_run2 = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": 'Authenticating user "saltstack" ...\nSuccess',
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run": mock_run, "cmd.run_all": mock_run2}):
+        assert rabbitmq.check_password("saltstack", "salt@123")
+
+
+def test_check_password_gt_38():
+    """
+    Test if it checks a user's password for RabbitMQ greater than v3.8.
+    """
+    mock_run = MagicMock(return_value="RabbitMQ version: 3.8.3")
+    mock_run2 = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": 'Authenticating user "saltstack" ...\nSuccess',
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run": mock_run, "cmd.run_all": mock_run2}):
+        assert rabbitmq.check_password("saltstack", "salt@123")
+
+
+# 'change_password' function tests: 1
+def test_change_password():
+    """
+    Test if it changes a user's password.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.change_password("saltstack", "salt@123") == {
+            "Password Changed": "saltstack"
+        }
+
+
+# 'clear_password' function tests: 1
+def test_clear_password():
+    """
+    Test if it removes a user's password.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.clear_password("saltstack") == {"Password Cleared": "saltstack"}
+
+
+# 'add_vhost' function tests: 1
+def test_add_vhost():
+    """
+    Test if it adds a vhost via rabbitmqctl add_vhost.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.add_vhost("saltstack") == {"Added": "saltstack"}
+
+
+# 'delete_vhost' function tests: 1
+def test_delete_vhost():
+    """
+    Test if it deletes a vhost rabbitmqctl delete_vhost.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.delete_vhost("saltstack") == {"Deleted": "saltstack"}
+
+
+# 'set_permissions' function tests: 1
+def test_set_permissions():
+    """
+    Test if it sets permissions for vhost via rabbitmqctl set_permissions.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.set_permissions("myvhost", "myuser") == {
+            "Permissions Set": "saltstack"
+        }
+
+
+# 'list_permissions' function tests: 1
+def test_list_permissions():
+    """
+    Test if it lists permissions for a vhost
+    via rabbitmqctl list_permissions.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": '[{"user":"myuser","configure":"saltstack","write":".*","read":"1"}]',
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.list_permissions("saltstack") == {
+            "myuser": {"configure": "saltstack", "write": ".*", "read": "1"},
+        }
+
+
+# 'list_user_permissions' function tests: 1
+def test_list_user_permissions():
+    """
+    Test if it list permissions for a user
+    via rabbitmqctl list_user_permissions.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": '[{"vhost":"saltstack","configure":"saltstack","write":"0","read":"1"},{"vhost":"guest","configure":"0","write":"one","read":""}]',
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.list_user_permissions("myuser") == {
+            "saltstack": {"configure": "saltstack", "write": "0", "read": "1"},
+            "guest": {"configure": "0", "write": "one", "read": ""},
+        }
+
+
+# 'set_user_tags' function tests: 1
+def test_set_user_tags():
+    """
+    Test if it add user tags via rabbitmqctl set_user_tags.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.set_user_tags("myadmin", "admin") == {"Tag(s) set": "saltstack"}
+
+
+# 'status' function tests: 1
+def test_status():
+    """
+    Test if it return rabbitmq status.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.status() == "saltstack"
+
+
+# 'cluster_status' function tests: 1
+def test_cluster_status():
+    """
+    Test if it return rabbitmq cluster_status.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.cluster_status() == "saltstack"
+
+
+# 'join_cluster' function tests: 1
+def test_join_cluster():
+    """
+    Test if it join a rabbit cluster.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.join_cluster("rabbit.example.com") == {"Join": "saltstack"}
+
+
+# 'stop_app' function tests: 1
+def test_stop_app():
+    """
+    Test if it stops the RabbitMQ application,
+    leaving the Erlang node running.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.stop_app() == "saltstack"
+
+
+# 'start_app' function tests: 1
+def test_start_app():
+    """
+    Test if it start the RabbitMQ application.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.start_app() == "saltstack"
+
+
+# 'reset' function tests: 1
+def test_reset():
+    """
+    Test if it return a RabbitMQ node to its virgin state
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.reset() == "saltstack"
+
+
+# 'force_reset' function tests: 1
+def test_force_reset():
+    """
+    Test if it forcefully Return a RabbitMQ node to its virgin state
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.force_reset() == "saltstack"
+
+
+# 'list_queues' function tests: 1
+def test_list_queues():
+    """
+    Test if it returns queue details of the / virtual host
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": "saltstack\t0\nceleryev.234-234\t10",
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.list_queues() == {
+            "saltstack": ["0"],
+            "celeryev.234-234": ["10"],
+        }
+
+
+# 'list_queues_vhost' function tests: 1
+def test_list_queues_vhost():
+    """
+    Test if it returns queue details of specified virtual host.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": "saltstack\t0\nceleryev.234-234\t10",
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.list_queues_vhost("consumers") == {
+            "saltstack": ["0"],
+            "celeryev.234-234": ["10"],
+        }
+
+
+# 'list_policies' function tests: 3
+def test_list_policies():
+    """
+    Test if it return a dictionary of policies nested by vhost
+    and name based on the data returned from rabbitmqctl list_policies.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    mock_pkg = MagicMock(return_value="3.7")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ), patch.dict(rabbitmq.__grains__, {"os_family": ""}):
+        assert rabbitmq.list_policies() == {}
+
+
+def test_list_policies_freebsd():
+    """
+    Test if it return a dictionary of policies nested by vhost
+    and name based on the data returned from rabbitmqctl list_policies.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    mock_pkg = MagicMock(return_value="3.7")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ), patch.dict(rabbitmq.__grains__, {"os_family": "FreeBSD"}):
+        assert rabbitmq.list_policies() == {}
+
+
+def test_list_policies_old_version():
+    """
+    Test if it return a dictionary of policies nested by vhost
+    and name based on the data returned from rabbitmqctl list_policies.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    mock_pkg = MagicMock(return_value="3.0")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ), patch.dict(rabbitmq.__grains__, {"os_family": ""}):
+        assert rabbitmq.list_policies() == {}
+
+
+# 'set_policy' function tests: 1
+def test_set_policy():
+    """
+    Test if it set a policy based on rabbitmqctl set_policy.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.set_policy("/", "HA", ".*", '{"ha-mode": "all"}') == {
+            "Set": "saltstack"
+        }
+
+
+# 'delete_policy' function tests: 1
+def test_delete_policy():
+    """
+    Test if it delete a policy based on rabbitmqctl clear_policy.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.delete_policy("/", "HA") == {"Deleted": "saltstack"}
+
+
+# 'policy_exists' function tests: 1
+def test_policy_exists():
+    """
+    Test if it return whether the policy exists
+    based on rabbitmqctl list_policies.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    mock_pkg = MagicMock(return_value="3.0")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ), patch.dict(rabbitmq.__grains__, {"os_family": ""}):
+        assert not rabbitmq.policy_exists("/", "HA")
+
+
+# 'list_available_plugins' function tests: 2
+def test_list_available_plugins():
+    """
+    Test if it returns a list of plugins.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack\nsalt\nother", "stderr": ""}
+    )
+    mock_pkg = MagicMock(return_value="")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ):
+        assert rabbitmq.list_available_plugins() == ["saltstack", "salt", "other"]
+
+
+def test_list_available_plugins_space_delimited():
+    """
+    Test if it returns a list of plugins.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack salt other", "stderr": ""}
+    )
+    mock_pkg = MagicMock(return_value="")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ):
+        assert rabbitmq.list_available_plugins() == ["saltstack", "salt", "other"]
+
+
+# 'list_enabled_plugins' function tests: 2
+def test_list_enabled_plugins():
+    """
+    Test if it returns a list of plugins.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack\nsalt\nother", "stderr": ""}
+    )
+    mock_pkg = MagicMock(return_value="")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ):
+        assert rabbitmq.list_enabled_plugins() == ["saltstack", "salt", "other"]
+
+
+def test_list_enabled_plugins_space_delimited():
+    """
+    Test if it returns a list of plugins.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack salt other", "stderr": ""}
+    )
+    mock_pkg = MagicMock(return_value="")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ):
+        assert rabbitmq.list_enabled_plugins() == ["saltstack", "salt", "other"]
+
+
+# 'plugin_is_enabled' function tests: 2
+def test_plugin_is_enabled():
+    """
+    Test if it returns true for an enabled plugin.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack\nsalt\nother", "stderr": ""}
+    )
+    mock_pkg = MagicMock(return_value="")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ):
+        assert rabbitmq.plugin_is_enabled("saltstack")
+        assert rabbitmq.plugin_is_enabled("salt")
+        assert rabbitmq.plugin_is_enabled("other")
+
+
+def test_plugin_is_enabled_negative():
+    """
+    Test if it returns false for a disabled plugin.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack\nother", "stderr": ""}
+    )
+    mock_pkg = MagicMock(return_value="")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ):
+        assert not rabbitmq.plugin_is_enabled("salt")
+        assert not rabbitmq.plugin_is_enabled("stack")
+        assert not rabbitmq.plugin_is_enabled("random")
+
+
+# 'enable_plugin' function tests: 1
+def test_enable_plugin():
+    """
+    Test if it enable a RabbitMQ plugin via the rabbitmq-plugins command.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    mock_pkg = MagicMock(return_value="")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ):
+        assert rabbitmq.enable_plugin("salt") == {"Enabled": "saltstack"}
+
+
+# 'disable_plugin' function tests: 1
+def test_disable_plugin():
+    """
+    Test if it disable a RabbitMQ plugin via the rabbitmq-plugins command.
+    """
+    mock_run = MagicMock(
+        return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
+    )
+    mock_pkg = MagicMock(return_value="")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ):
+        assert rabbitmq.disable_plugin("salt") == {"Disabled": "saltstack"}
+
+
+# 'list_upstreams' function tests: 1
+def test_list_upstreams():
+    """
+    Test if it returns a list of upstreams.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": 'federation-upstream\tremote-name\t{"ack-mode":"on-confirm"'
+            ',"max-hops":1,"trust-user-id":true,"uri":"amqp://username:'
+            'password@remote.fqdn"}',
+            "stderr": "",
+        }
+    )
+    mock_pkg = MagicMock(return_value="")
+    with patch.dict(
+        rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
+    ):
+        assert rabbitmq.list_upstreams() == {
+            "remote-name": (
+                '{"ack-mode":"on-confirm","max-hops":1,'
+                '"trust-user-id":true,"uri":"amqp://username:'
+                'password@remote.fqdn"}'
+            )
+        }
+
+
+# 'upstream_exists' function tests: 2
+def test_upstream_exists():
+    """
+    Test whether a given rabbitmq-internal upstream exists based
+    on rabbitmqctl list_upstream.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": 'federation-upstream\tremote-name\t{"ack-mode":"on-confirm"'
+            ',"max-hops":1,"trust-user-id":true,"uri":"amqp://username:'
+            'password@remote.fqdn"}',
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.upstream_exists("remote-name")
+
+
+def test_upstream_exists_negative():
+    """
+    Negative test of whether rabbitmq-internal upstream exists based
+    on rabbitmqctl list_upstream.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": 'federation-upstream\tremote-name\t{"ack-mode":"on-confirm"'
+            ',"max-hops":1,"trust-user-id":true,"uri":"amqp://username:'
+            'password@remote.fqdn"}',
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert not rabbitmq.upstream_exists("does-not-exist")
+
+
+# 'add_upstream' function tests: 1
+def test_set_upstream():
+    """
+    Test if a rabbitMQ upstream gets configured properly.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": (
+                'Setting runtime parameter "federation-upstream" for component '
+                '"remote-name" to "{"trust-user-id": true, "uri": '
+                '"amqp://username:password@remote.fqdn", "ack-mode": "on-confirm", '
+                '"max-hops": 1}" in vhost "/" ...'
+            ),
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.set_upstream(
+            "remote-name",
+            "amqp://username:password@remote.fqdn",
+            ack_mode="on-confirm",
+            max_hops=1,
+            trust_user_id=True,
+        )
+
+
+# 'delete_upstream' function tests: 2
+def test_delete_upstream():
+    """
+    Test if an upstream gets deleted properly using rabbitmqctl delete_upstream.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 0,
+            "stdout": (
+                'Clearing runtime parameter "remote-name" for component '
+                '"federation-upstream" on vhost "/" ...'
+            ),
+            "stderr": "",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        assert rabbitmq.delete_upstream("remote-name")
+
+
+def test_delete_upstream_negative():
+    """
+    Negative test trying to delete a non-existant upstream.
+    """
+    mock_run = MagicMock(
+        return_value={
+            "retcode": 70,
+            "stdout": (
+                'Clearing runtime parameter "remote-name" for component '
+                '"federation-upstream" on vhost "/" ...'
+            ),
+            "stderr": "Error:\nParameter does not exist",
+        }
+    )
+    with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
+        pytest.raises(CommandExecutionError, rabbitmq.delete_upstream, "remote-name")
diff --git a/tests/unit/modules/test_rabbitmq.py b/tests/unit/modules/test_rabbitmq.py
deleted file mode 100644
index edadf2ef6ec6..000000000000
--- a/tests/unit/modules/test_rabbitmq.py
+++ /dev/null
@@ -1,888 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    :codeauthor: Jayesh Kariya <jayeshk@saltstack.com>
-"""
-
-# Import Python Libs
-from __future__ import absolute_import, print_function, unicode_literals
-
-# Import Salt Libs
-import salt.modules.rabbitmq as rabbitmq
-from salt.exceptions import CommandExecutionError
-
-# Import Salt Testing Libs
-from tests.support.mixins import LoaderModuleMockMixin
-from tests.support.mock import MagicMock, patch
-from tests.support.unit import TestCase
-
-
-class RabbitmqTestCase(TestCase, LoaderModuleMockMixin):
-    """
-    Test cases for salt.modules.rabbitmq
-    """
-
-    def setup_loader_modules(self):
-        return {
-            rabbitmq: {"__context__": {"rabbitmqctl": None, "rabbitmq-plugins": None}}
-        }
-
-    # 'list_users_rabbitmq2' function tests: 1
-
-    def test_list_users_rabbitmq2(self):
-        """
-        Test if it return a list of users based off of rabbitmqctl user_list.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "Listing users ...\nguest\t[administrator, user]\njustAnAdmin\t[administrator]\n",
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.list_users(),
-                {"guest": ["administrator", "user"], "justAnAdmin": ["administrator"]},
-            )
-
-    # 'list_users_rabbitmq3' function tests: 1
-
-    def test_list_users_rabbitmq3(self):
-        """
-        Test if it return a list of users based off of rabbitmqctl user_list.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "guest\t[administrator user]\r\nother\t[a b]\r\n",
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.list_users(),
-                {"guest": ["administrator", "user"], "other": ["a", "b"]},
-            )
-
-    # 'list_users_with_warning_rabbitmq2' function tests: 1
-
-    def test_list_users_with_warning_rabbitmq2(self):
-        """
-        Test if having a leading WARNING returns the user_list anyway.
-        """
-        rtn_stdout = "\n".join(
-            [
-                "WARNING: ignoring /etc/rabbitmq/rabbitmq.conf -- location has moved to /etc/rabbitmq/rabbitmq-env.conf",
-                "Listing users ...",
-                "guest\t[administrator, user]\n",
-            ]
-        )
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": rtn_stdout, "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.list_users(), {"guest": ["administrator", "user"]}
-            )
-
-    # 'list_users_with_warning_rabbitmq3' function tests: 1
-
-    def test_list_users_with_warning_rabbitmq3(self):
-        """
-        Test if having a leading WARNING returns the user_list anyway.
-        """
-        rtn_stdout = "\n".join(
-            [
-                "WARNING: ignoring /etc/rabbitmq/rabbitmq.conf -- location has moved to /etc/rabbitmq/rabbitmq-env.conf",
-                "Listing users ...",
-                "guest\t[administrator user]\n",
-            ]
-        )
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": rtn_stdout, "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.list_users(), {"guest": ["administrator", "user"]}
-            )
-
-    # 'list_vhosts' function tests: 2
-
-    def test_list_vhosts(self):
-        """
-        Test if it return a list of vhost based on rabbitmqctl list_vhosts.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "/\nsaltstack\n...", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertListEqual(rabbitmq.list_vhosts(), ["/", "saltstack", "..."])
-
-    def test_list_vhosts_with_warning(self):
-        """
-        Test if it return a list of vhost based on rabbitmqctl list_vhosts even with a leading WARNING.
-        """
-        rtn_stdout = "\n".join(
-            [
-                "WARNING: ignoring /etc/rabbitmq/rabbitmq.conf -- location has moved to /etc/rabbitmq/rabbitmq-env.conf",
-                "Listing users ...",
-                "/",
-                "saltstack",
-                "...\n",
-            ]
-        )
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": rtn_stdout, "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertListEqual(rabbitmq.list_vhosts(), ["/", "saltstack", "..."])
-
-    # 'user_exists' function tests: 2
-
-    def test_user_exists(self):
-        """
-        Test whether a given rabbitmq-internal user exists based
-        on rabbitmqctl list_users.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "Listing users ...\n" "saltstack\t[administrator]\n...done",
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertTrue(rabbitmq.user_exists("saltstack"))
-
-    def test_user_exists_negative(self):
-        """
-        Negative test of whether rabbitmq-internal user exists based
-        on rabbitmqctl list_users.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "Listing users ...\n" "saltstack\t[administrator]\n...done",
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertFalse(rabbitmq.user_exists("salt"))
-
-    # 'vhost_exists' function tests: 2
-
-    def test_vhost_exists(self):
-        """
-        Test if it return whether the vhost exists based
-        on rabbitmqctl list_vhosts.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "Listing vhosts ...\nsaltstack",
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertTrue(rabbitmq.vhost_exists("saltstack"))
-
-    def test_vhost_exists_negative(self):
-        """
-        Test if it return whether the vhost exists based
-        on rabbitmqctl list_vhosts.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "Listing vhosts ...\nsaltstack",
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertFalse(rabbitmq.vhost_exists("salt"))
-
-    # 'add_user' function tests: 1
-
-    def test_add_user(self):
-        """
-        Test if it add a rabbitMQ user via rabbitmqctl
-        user_add <user> <password>
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(rabbitmq.add_user("saltstack"), {"Added": "saltstack"})
-
-        mock_run = MagicMock(return_value="Error")
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            with patch.object(
-                rabbitmq,
-                "clear_password",
-                return_value={"Error": "Error", "retcode": 1},
-            ):
-                self.assertRaises(CommandExecutionError, rabbitmq.add_user, "saltstack")
-
-    # 'delete_user' function tests: 1
-
-    def test_delete_user(self):
-        """
-        Test if it deletes a user via rabbitmqctl delete_user.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.delete_user("saltstack"), {"Deleted": "saltstack"}
-            )
-
-    # 'check_password' function tests: 2
-
-    def test_check_password_lt_38(self):
-        """
-        Test if it checks a user's password for RabbitMQ less than v3.8.
-        """
-        mock_run = MagicMock(return_value='{rabbit,"RabbitMQ","3.5.7"}')
-        mock_run2 = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": 'Authenticating user "saltstack" ...\nSuccess',
-                "stderr": "",
-            }
-        )
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run": mock_run, "cmd.run_all": mock_run2}
-        ):
-            self.assertEqual(rabbitmq.check_password("saltstack", "salt@123"), True)
-
-    def test_check_password_gt_38(self):
-        """
-        Test if it checks a user's password for RabbitMQ greater than v3.8.
-        """
-        mock_run = MagicMock(return_value="RabbitMQ version: 3.8.3")
-        mock_run2 = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": 'Authenticating user "saltstack" ...\nSuccess',
-                "stderr": "",
-            }
-        )
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run": mock_run, "cmd.run_all": mock_run2}
-        ):
-            self.assertEqual(rabbitmq.check_password("saltstack", "salt@123"), True)
-
-    # 'change_password' function tests: 1
-
-    def test_change_password(self):
-        """
-        Test if it changes a user's password.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.change_password("saltstack", "salt@123"),
-                {"Password Changed": "saltstack"},
-            )
-
-    # 'clear_password' function tests: 1
-
-    def test_clear_password(self):
-        """
-        Test if it removes a user's password.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.clear_password("saltstack"), {"Password Cleared": "saltstack"}
-            )
-
-    # 'add_vhost' function tests: 1
-
-    def test_add_vhost(self):
-        """
-        Test if it adds a vhost via rabbitmqctl add_vhost.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.add_vhost("saltstack"), {"Added": "saltstack"}
-            )
-
-    # 'delete_vhost' function tests: 1
-
-    def test_delete_vhost(self):
-        """
-        Test if it deletes a vhost rabbitmqctl delete_vhost.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.delete_vhost("saltstack"), {"Deleted": "saltstack"}
-            )
-
-    # 'set_permissions' function tests: 1
-
-    def test_set_permissions(self):
-        """
-        Test if it sets permissions for vhost via rabbitmqctl set_permissions.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.set_permissions("myvhost", "myuser"),
-                {"Permissions Set": "saltstack"},
-            )
-
-    # 'list_permissions' function tests: 1
-
-    def test_list_permissions(self):
-        """
-        Test if it lists permissions for a vhost
-        via rabbitmqctl list_permissions.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "Listing stuff ...\nsaltstack\tsaltstack\t.*\t1\nguest\t0\tone\n...done",
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.list_user_permissions("myuser"),
-                {"saltstack": ["saltstack", ".*", "1"], "guest": ["0", "one"]},
-            )
-
-    # 'list_user_permissions' function tests: 1
-
-    def test_list_user_permissions(self):
-        """
-        Test if it list permissions for a user
-        via rabbitmqctl list_user_permissions.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "Listing stuff ...\nsaltstack\tsaltstack\t0\t1\nguest\t0\tone\n...done",
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.list_user_permissions("myuser"),
-                {"saltstack": ["saltstack", "0", "1"], "guest": ["0", "one"]},
-            )
-
-    # 'set_user_tags' function tests: 1
-
-    def test_set_user_tags(self):
-        """
-        Test if it add user tags via rabbitmqctl set_user_tags.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.set_user_tags("myadmin", "admin"), {"Tag(s) set": "saltstack"}
-            )
-
-    # 'status' function tests: 1
-
-    def test_status(self):
-        """
-        Test if it return rabbitmq status.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertEqual(rabbitmq.status(), "saltstack")
-
-    # 'cluster_status' function tests: 1
-
-    def test_cluster_status(self):
-        """
-        Test if it return rabbitmq cluster_status.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertEqual(rabbitmq.cluster_status(), "saltstack")
-
-    # 'join_cluster' function tests: 1
-
-    def test_join_cluster(self):
-        """
-        Test if it join a rabbit cluster.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.join_cluster("rabbit.example.com"), {"Join": "saltstack"}
-            )
-
-    # 'stop_app' function tests: 1
-
-    def test_stop_app(self):
-        """
-        Test if it stops the RabbitMQ application,
-        leaving the Erlang node running.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertEqual(rabbitmq.stop_app(), "saltstack")
-
-    # 'start_app' function tests: 1
-
-    def test_start_app(self):
-        """
-        Test if it start the RabbitMQ application.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertEqual(rabbitmq.start_app(), "saltstack")
-
-    # 'reset' function tests: 1
-
-    def test_reset(self):
-        """
-        Test if it return a RabbitMQ node to its virgin state
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertEqual(rabbitmq.reset(), "saltstack")
-
-    # 'force_reset' function tests: 1
-
-    def test_force_reset(self):
-        """
-        Test if it forcefully Return a RabbitMQ node to its virgin state
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertEqual(rabbitmq.force_reset(), "saltstack")
-
-    # 'list_queues' function tests: 1
-
-    def test_list_queues(self):
-        """
-        Test if it returns queue details of the / virtual host
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "saltstack\t0\nceleryev.234-234\t10",
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.list_queues(), {"saltstack": ["0"], "celeryev.234-234": ["10"]}
-            )
-
-    # 'list_queues_vhost' function tests: 1
-
-    def test_list_queues_vhost(self):
-        """
-        Test if it returns queue details of specified virtual host.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "saltstack\t0\nceleryev.234-234\t10",
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.list_queues_vhost("consumers"),
-                {"saltstack": ["0"], "celeryev.234-234": ["10"]},
-            )
-
-    # 'list_policies' function tests: 3
-
-    def test_list_policies(self):
-        """
-        Test if it return a dictionary of policies nested by vhost
-        and name based on the data returned from rabbitmqctl list_policies.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        mock_pkg = MagicMock(return_value="3.7")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ), patch.dict(rabbitmq.__grains__, {"os_family": ""}):
-            self.assertDictEqual(rabbitmq.list_policies(), {})
-
-    def test_list_policies_freebsd(self):
-        """
-        Test if it return a dictionary of policies nested by vhost
-        and name based on the data returned from rabbitmqctl list_policies.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        mock_pkg = MagicMock(return_value="3.7")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ), patch.dict(rabbitmq.__grains__, {"os_family": "FreeBSD"}):
-            self.assertDictEqual(rabbitmq.list_policies(), {})
-
-    def test_list_policies_old_version(self):
-        """
-        Test if it return a dictionary of policies nested by vhost
-        and name based on the data returned from rabbitmqctl list_policies.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        mock_pkg = MagicMock(return_value="3.0")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ), patch.dict(rabbitmq.__grains__, {"os_family": ""}):
-            self.assertDictEqual(rabbitmq.list_policies(), {})
-
-    # 'set_policy' function tests: 1
-
-    def test_set_policy(self):
-        """
-        Test if it set a policy based on rabbitmqctl set_policy.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.set_policy("/", "HA", ".*", '{"ha-mode": "all"}'),
-                {"Set": "saltstack"},
-            )
-
-    # 'delete_policy' function tests: 1
-
-    def test_delete_policy(self):
-        """
-        Test if it delete a policy based on rabbitmqctl clear_policy.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertDictEqual(
-                rabbitmq.delete_policy("/", "HA"), {"Deleted": "saltstack"}
-            )
-
-    # 'policy_exists' function tests: 1
-
-    def test_policy_exists(self):
-        """
-        Test if it return whether the policy exists
-        based on rabbitmqctl list_policies.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        mock_pkg = MagicMock(return_value="3.0")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ), patch.dict(rabbitmq.__grains__, {"os_family": ""}):
-            self.assertFalse(rabbitmq.policy_exists("/", "HA"))
-
-    # 'list_available_plugins' function tests: 2
-
-    def test_list_available_plugins(self):
-        """
-        Test if it returns a list of plugins.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "saltstack\nsalt\nother",
-                "stderr": "",
-            }
-        )
-        mock_pkg = MagicMock(return_value="")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ):
-            self.assertListEqual(
-                rabbitmq.list_available_plugins(), ["saltstack", "salt", "other"]
-            )
-
-    def test_list_available_plugins_space_delimited(self):
-        """
-        Test if it returns a list of plugins.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack salt other", "stderr": ""}
-        )
-        mock_pkg = MagicMock(return_value="")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ):
-            self.assertListEqual(
-                rabbitmq.list_available_plugins(), ["saltstack", "salt", "other"]
-            )
-
-    # 'list_enabled_plugins' function tests: 2
-
-    def test_list_enabled_plugins(self):
-        """
-        Test if it returns a list of plugins.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "saltstack\nsalt\nother",
-                "stderr": "",
-            }
-        )
-        mock_pkg = MagicMock(return_value="")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ):
-            self.assertListEqual(
-                rabbitmq.list_enabled_plugins(), ["saltstack", "salt", "other"]
-            )
-
-    def test_list_enabled_plugins_space_delimited(self):
-        """
-        Test if it returns a list of plugins.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack salt other", "stderr": ""}
-        )
-        mock_pkg = MagicMock(return_value="")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ):
-            self.assertListEqual(
-                rabbitmq.list_enabled_plugins(), ["saltstack", "salt", "other"]
-            )
-
-    # 'plugin_is_enabled' function tests: 2
-
-    def test_plugin_is_enabled(self):
-        """
-        Test if it returns true for an enabled plugin.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": "saltstack\nsalt\nother",
-                "stderr": "",
-            }
-        )
-        mock_pkg = MagicMock(return_value="")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ):
-            self.assertTrue(rabbitmq.plugin_is_enabled("saltstack"))
-            self.assertTrue(rabbitmq.plugin_is_enabled("salt"))
-            self.assertTrue(rabbitmq.plugin_is_enabled("other"))
-
-    def test_plugin_is_enabled_negative(self):
-        """
-        Test if it returns false for a disabled plugin.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack\nother", "stderr": ""}
-        )
-        mock_pkg = MagicMock(return_value="")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ):
-            self.assertFalse(rabbitmq.plugin_is_enabled("salt"))
-            self.assertFalse(rabbitmq.plugin_is_enabled("stack"))
-            self.assertFalse(rabbitmq.plugin_is_enabled("random"))
-
-    # 'enable_plugin' function tests: 1
-
-    def test_enable_plugin(self):
-        """
-        Test if it enable a RabbitMQ plugin via the rabbitmq-plugins command.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        mock_pkg = MagicMock(return_value="")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ):
-            self.assertDictEqual(
-                rabbitmq.enable_plugin("salt"), {"Enabled": "saltstack"}
-            )
-
-    # 'disable_plugin' function tests: 1
-
-    def test_disable_plugin(self):
-        """
-        Test if it disable a RabbitMQ plugin via the rabbitmq-plugins command.
-        """
-        mock_run = MagicMock(
-            return_value={"retcode": 0, "stdout": "saltstack", "stderr": ""}
-        )
-        mock_pkg = MagicMock(return_value="")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ):
-            self.assertDictEqual(
-                rabbitmq.disable_plugin("salt"), {"Disabled": "saltstack"}
-            )
-
-    # 'list_upstreams' function tests: 1
-
-    def test_list_upstreams(self):
-        """
-        Test if it returns a list of upstreams.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": 'federation-upstream\tremote-name\t{"ack-mode":"on-confirm"'
-                ',"max-hops":1,"trust-user-id":true,"uri":"amqp://username:'
-                'password@remote.fqdn"}',
-                "stderr": "",
-            }
-        )
-        mock_pkg = MagicMock(return_value="")
-        with patch.dict(
-            rabbitmq.__salt__, {"cmd.run_all": mock_run, "pkg.version": mock_pkg}
-        ):
-            self.assertDictEqual(
-                rabbitmq.list_upstreams(),
-                {
-                    "remote-name": (
-                        '{"ack-mode":"on-confirm","max-hops":1,'
-                        '"trust-user-id":true,"uri":"amqp://username:'
-                        'password@remote.fqdn"}'
-                    )
-                },
-            )
-
-    # 'upstream_exists' function tests: 2
-
-    def test_upstream_exists(self):
-        """
-        Test whether a given rabbitmq-internal upstream exists based
-        on rabbitmqctl list_upstream.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": 'federation-upstream\tremote-name\t{"ack-mode":"on-confirm"'
-                ',"max-hops":1,"trust-user-id":true,"uri":"amqp://username:'
-                'password@remote.fqdn"}',
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertTrue(rabbitmq.upstream_exists("remote-name"))
-
-    def test_upstream_exists_negative(self):
-        """
-        Negative test of whether rabbitmq-internal upstream exists based
-        on rabbitmqctl list_upstream.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": 'federation-upstream\tremote-name\t{"ack-mode":"on-confirm"'
-                ',"max-hops":1,"trust-user-id":true,"uri":"amqp://username:'
-                'password@remote.fqdn"}',
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertFalse(rabbitmq.upstream_exists("does-not-exist"))
-
-    # 'add_upstream' function tests: 1
-
-    def test_set_upstream(self):
-        """
-        Test if a rabbitMQ upstream gets configured properly.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": (
-                    'Setting runtime parameter "federation-upstream" for component '
-                    '"remote-name" to "{"trust-user-id": true, "uri": '
-                    '"amqp://username:password@remote.fqdn", "ack-mode": "on-confirm", '
-                    '"max-hops": 1}" in vhost "/" ...'
-                ),
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertTrue(
-                rabbitmq.set_upstream(
-                    "remote-name",
-                    "amqp://username:password@remote.fqdn",
-                    ack_mode="on-confirm",
-                    max_hops=1,
-                    trust_user_id=True,
-                )
-            )
-
-    # 'delete_upstream' function tests: 2
-
-    def test_delete_upstream(self):
-        """
-        Test if an upstream gets deleted properly using rabbitmqctl delete_upstream.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 0,
-                "stdout": (
-                    'Clearing runtime parameter "remote-name" for component '
-                    '"federation-upstream" on vhost "/" ...'
-                ),
-                "stderr": "",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertTrue(rabbitmq.delete_upstream("remote-name"))
-
-    def test_delete_upstream_negative(self):
-        """
-        Negative test trying to delete a non-existant upstream.
-        """
-        mock_run = MagicMock(
-            return_value={
-                "retcode": 70,
-                "stdout": (
-                    'Clearing runtime parameter "remote-name" for component '
-                    '"federation-upstream" on vhost "/" ...'
-                ),
-                "stderr": "Error:\nParameter does not exist",
-            }
-        )
-        with patch.dict(rabbitmq.__salt__, {"cmd.run_all": mock_run}):
-            self.assertRaises(
-                CommandExecutionError, rabbitmq.delete_upstream, "remote-name"
-            )


Code review comments:
diff_hunk: @@ -0,0 +1,116 @@
+import logging
+import time
+
+import attr
+import pytest
+from saltfactories.daemons.container import Container
+from saltfactories.utils import random_string
+from saltfactories.utils.ports import get_unused_localhost_port
+
+docker = pytest.importorskip("docker")
+docker_errors = pytest.importorskip("docker.errors")
+
+log = logging.getLogger(__name__)
+
+
+@attr.s(kw_only=True, slots=True)
+class RabbitMQImage:
+    name = attr.ib()
+    tag = attr.ib()
+    container_id = attr.ib()
+
+    def __str__(self):
+        return "{}:{}".format(self.name, self.tag)
+
+
+@attr.s(kw_only=True, slots=True)
+class RabbitMQCombo:
+    rabbitmq_name = attr.ib()
+    rabbitmq_version = attr.ib()
+    rabbitmq_port = attr.ib()
+
+    @rabbitmq_port.default
+    def _rabbitmq_port(self):
+        return get_unused_localhost_port()
+
+
+def get_test_versions():
+    test_versions = []
+    name = "rabbitmq"
+    for version in ("3.8",):
+        test_versions.append(
+            RabbitMQImage(
+                name=name,
+                tag=version,
+                container_id=random_string("rabbitmq-{}-".format(version)),
+            )
+        )
+    return test_versions
+
+
+def get_test_version_id(value):
+    return "container={}".format(value)
+
+
+@pytest.fixture(scope="module", params=get_test_versions(), ids=get_test_version_id)
+def rabbitmq_container(request, salt_factories, modules):
+
+    try:
+        docker_client = docker.from_env()
+    except docker_errors.DockerException:
+        pytest.skip("Failed to get a connection to docker running on the system")
+    connectable = Container.client_connectable(docker_client)
+    if connectable is not True:  # pragma: no cover
+        pytest.skip(connectable)
+
+    rabbitmq_image = request.param
+
+    combo = RabbitMQCombo(
+        rabbitmq_name=rabbitmq_image.name, rabbitmq_version=rabbitmq_image.tag,
+    )
+    container = salt_factories.get_container(
+        rabbitmq_image.container_id,
+        "{}:{}".format(combo.rabbitmq_name, combo.rabbitmq_version),
+        docker_client=docker_client,
+    )
+    with container.started():
+        # Sleep
+        log.debug("=== initial sleep")
path: tests/pytests/functional/states/rabbitmq/conftest.py
text: @user1:
looks like there are a couple of log statements in this function that could be removed, that were used only for troubleshooting.