File backport-add-maintain-m-privilege-to-postgres-module.patch of Package venv-salt-minion

From f859336115190e3b41569fa3c52cd6f804b3afad Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Fri, 16 Jan 2026 11:07:48 +0100
Subject: [PATCH] Backport "Add MAINTAIN (m) privilege to postgres
 module lookup tables"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Initial port of test/unit/module/test_postgres.py to pytests

(cherry picked from commit a919a3ea8782b252a3e65ad8787f73a906cf7fa5)

* Added tablespace_create test

(cherry picked from commit 452f6bdf855ae4484145f48d3a433dc949e2a775)

* Updated test per reviewer suggestion

(cherry picked from commit d2481582f4879ab0ddc52a9c0415b3e5dbf55326)

* Further update to test per reviewer comment

(cherry picked from commit 4dbd8caec2bfd2bbaf4526320ad9583b8e17e6bc)

* Migrated test_deb_postgre.py to pytests

(cherry picked from commit 0963209cc3e20ba6dfa3abdd5d716f400dafa910)

* Updates tests for tablespace_list, tablespace_exists and tablespace_remove

(cherry picked from commit 7714b22f075b81150deb87cd7c2bed9b49f55d74)

* Updated tests with tablespace alter tests

(cherry picked from commit 3c4aa715ba8bb8f8533e3e1ff081e57db746d1f4)

* Updated asserts and limit testing to Linux only

(cherry picked from commit e919e8f63e0b2e72a531cfce0b3bbc052f14ca69)

* Converted global constants to pytest fixtures per reviewer comments

(cherry picked from commit c6e8fa3b1781c997bc9e1c83e28d3950c7507ad5)

* add 'm = MAINTAIN' privilege to the maps in the postgres module

(cherry picked from commit a6b8fe4e8ebe8a15a68852eeda64a045f6ff5e46)

* add changelog entry for bugfix to #66962

(cherry picked from commit d422032f21fde7cec8c4ac3f9d628dc24c1cc3da)

* add reference to MAINTAIN to the docs

(cherry picked from commit 0a77c112a15e5d98ef50e6492e2cac9adbde0449)

* add MAINTAIN privilege to PostgreSQL tests

(cherry picked from commit cb26d8d0eef62e08a7581f2a03b1a4bb17176c04)

---------

Co-authored-by: David Murphy < dmurphy@saltstack.com>
Co-authored-by: Jonas Maurus <jonas-github@maurus.net>
---
 changelog/66962.fixed.md                      |    1 +
 salt/modules/postgres.py                      |    3 +-
 salt/states/postgres_privileges.py            |    2 +
 .../pytests/unit/modules/test_deb_postgres.py |  165 ++
 tests/pytests/unit/modules/test_postgres.py   | 2398 ++++++++++++++++-
 tests/unit/modules/test_deb_postgres.py       |  184 --
 tests/unit/modules/test_postgres.py           | 2086 --------------
 7 files changed, 2562 insertions(+), 2277 deletions(-)
 create mode 100644 changelog/66962.fixed.md
 create mode 100644 tests/pytests/unit/modules/test_deb_postgres.py
 delete mode 100644 tests/unit/modules/test_deb_postgres.py
 delete mode 100644 tests/unit/modules/test_postgres.py

diff --git a/changelog/66962.fixed.md b/changelog/66962.fixed.md
new file mode 100644
index 0000000000..a1ebb56f41
--- /dev/null
+++ b/changelog/66962.fixed.md
@@ -0,0 +1 @@
+Added support for MAINTAIN (m) privilege to salt.modules.postgres
diff --git a/salt/modules/postgres.py b/salt/modules/postgres.py
index f73959a92e..a2b6b8adc1 100644
--- a/salt/modules/postgres.py
+++ b/salt/modules/postgres.py
@@ -100,6 +100,7 @@ _PRIVILEGES_MAP = {
     "X": "EXECUTE",
     "x": "REFERENCES",
     "d": "DELETE",
+    "m": "MAINTAIN",
     "*": "GRANT",
 }
 _PRIVILEGES_OBJECTS = frozenset(
@@ -115,7 +116,7 @@ _PRIVILEGES_OBJECTS = frozenset(
     )
 )
 _PRIVILEGE_TYPE_MAP = {
-    "table": "arwdDxt",
+    "table": "arwdDxtm",
     "tablespace": "C",
     "language": "U",
     "sequence": "rwU",
diff --git a/salt/states/postgres_privileges.py b/salt/states/postgres_privileges.py
index 9241c2de6e..e6542077db 100644
--- a/salt/states/postgres_privileges.py
+++ b/salt/states/postgres_privileges.py
@@ -130,6 +130,7 @@ def present(
        - EXECUTE
        - REFERENCES
        - DELETE
+       - MAINTAIN
        - ALL
 
        :note: privileges should not be set when granting group membership
@@ -260,6 +261,7 @@ def absent(
        - EXECUTE
        - REFERENCES
        - DELETE
+       - MAINTAIN
        - ALL
 
        :note: privileges should not be set when revoking group membership
diff --git a/tests/pytests/unit/modules/test_deb_postgres.py b/tests/pytests/unit/modules/test_deb_postgres.py
new file mode 100644
index 0000000000..f125f96707
--- /dev/null
+++ b/tests/pytests/unit/modules/test_deb_postgres.py
@@ -0,0 +1,165 @@
+import logging
+
+import pytest
+
+import salt.modules.deb_postgres as deb_postgres
+from tests.support.mock import Mock, patch
+
+log = logging.getLogger(__name__)
+
+pytestmark = [
+    pytest.mark.skip_unless_on_linux(reason="Only supported on Linux family"),
+]
+
+
+@pytest.fixture
+def get_lscuster():
+    return """\
+8.4 main 5432 online postgres /srv/8.4/main \
+        /var/log/postgresql/postgresql-8.4-main.log
+9.1 main 5433 online postgres /srv/9.1/main \
+        /var/log/postgresql/postgresql-9.1-main.log
+"""
+
+
+@pytest.fixture
+def configure_loader_modules(get_lscuster):
+    return {
+        deb_postgres: {
+            "__salt__": {
+                "config.option": Mock(),
+                "cmd.run_all": Mock(return_value={"stdout": get_lscuster}),
+                "file.chown": Mock(),
+                "file.remove": Mock(),
+            }
+        }
+    }
+
+
+def test_cluster_create():
+    with patch("salt.utils.path.which", Mock(return_value="/usr/bin/pg_createcluster")):
+        expected_cmdstr = (
+            "/usr/bin/pg_createcluster "
+            "--port 5432 --locale fr_FR --encoding UTF-8 "
+            "--datadir /opt/postgresql "
+            "9.3 main"
+        )
+
+        deb_postgres.cluster_create(
+            "9.3",
+            "main",
+            port="5432",
+            locale="fr_FR",
+            encoding="UTF-8",
+            datadir="/opt/postgresql",
+        )
+        assert deb_postgres.__salt__["cmd.run_all"].call_args[0][0] == expected_cmdstr
+
+
+def test_cluster_create_with_initdb_options():
+    with patch("salt.utils.path.which", Mock(return_value="/usr/bin/pg_createcluster")):
+        expected_cmdstr = (
+            "/usr/bin/pg_createcluster "
+            "--port 5432 --locale fr_FR --encoding UTF-8 "
+            "--datadir /opt/postgresql "
+            "11 main "
+            "-- "
+            "--allow-group-access "
+            "--data-checksums "
+            "--wal-segsize 32"
+        )
+
+        deb_postgres.cluster_create(
+            "11",
+            "main",
+            port="5432",
+            locale="fr_FR",
+            encoding="UTF-8",
+            datadir="/opt/postgresql",
+            allow_group_access=True,
+            data_checksums=True,
+            wal_segsize="32",
+        )
+        assert deb_postgres.__salt__["cmd.run_all"].call_args[0][0] == expected_cmdstr
+
+
+def test_cluster_create_with_float():
+    with patch("salt.utils.path.which", Mock(return_value="/usr/bin/pg_createcluster")):
+        expected_cmdstr = (
+            "/usr/bin/pg_createcluster "
+            "--port 5432 --locale fr_FR --encoding UTF-8 "
+            "--datadir /opt/postgresql "
+            "9.3 main"
+        )
+
+        deb_postgres.cluster_create(
+            9.3,
+            "main",
+            port="5432",
+            locale="fr_FR",
+            encoding="UTF-8",
+            datadir="/opt/postgresql",
+        )
+        assert deb_postgres.__salt__["cmd.run_all"].call_args[0][0] == expected_cmdstr
+
+
+def test_parse_pg_lsclusters(get_lscuster):
+    with patch("salt.utils.path.which", Mock(return_value="/usr/bin/pg_lsclusters")):
+        stdout = get_lscuster
+        maxDiff = None
+        expected = {
+            "8.4/main": {
+                "port": 5432,
+                "status": "online",
+                "user": "postgres",
+                "datadir": "/srv/8.4/main",
+                "log": "/var/log/postgresql/postgresql-8.4-main.log",
+            },
+            "9.1/main": {
+                "port": 5433,
+                "status": "online",
+                "user": "postgres",
+                "datadir": "/srv/9.1/main",
+                "log": "/var/log/postgresql/postgresql-9.1-main.log",
+            },
+        }
+        assert deb_postgres._parse_pg_lscluster(stdout) == expected
+
+
+def test_cluster_list():
+    with patch("salt.utils.path.which", Mock(return_value="/usr/bin/pg_lsclusters")):
+        return_list = deb_postgres.cluster_list()
+        assert (
+            deb_postgres.__salt__["cmd.run_all"].call_args[0][0]
+            == "/usr/bin/pg_lsclusters --no-header"
+        )
+
+        return_dict = deb_postgres.cluster_list(verbose=True)
+        assert isinstance(return_dict, dict)
+
+
+def test_cluster_exists():
+    assert deb_postgres.cluster_exists("8.4")
+    assert deb_postgres.cluster_exists("8.4", "main")
+    assert not deb_postgres.cluster_exists("3.4", "main")
+
+
+def test_cluster_delete():
+    with patch("salt.utils.path.which", Mock(return_value="/usr/bin/pg_dropcluster")):
+        deb_postgres.cluster_remove("9.3", "main")
+        assert (
+            deb_postgres.__salt__["cmd.run_all"].call_args[0][0]
+            == "/usr/bin/pg_dropcluster 9.3 main"
+        )
+
+        deb_postgres.cluster_remove("9.3", "main", stop=True)
+        assert (
+            deb_postgres.__salt__["cmd.run_all"].call_args[0][0]
+            == "/usr/bin/pg_dropcluster --stop 9.3 main"
+        )
+
+        deb_postgres.cluster_remove(9.3, "main", stop=True)
+        assert (
+            deb_postgres.__salt__["cmd.run_all"].call_args[0][0]
+            == "/usr/bin/pg_dropcluster --stop 9.3 main"
+        )
diff --git a/tests/pytests/unit/modules/test_postgres.py b/tests/pytests/unit/modules/test_postgres.py
index 393c087d16..be9e05fc96 100644
--- a/tests/pytests/unit/modules/test_postgres.py
+++ b/tests/pytests/unit/modules/test_postgres.py
@@ -1,8 +1,17 @@
+import datetime
+import re
+
 import pytest
 
 import salt.modules.config as configmod
 import salt.modules.postgres as postgres
-from tests.support.mock import MagicMock, patch
+from salt.exceptions import SaltInvocationError
+from tests.support.mock import MagicMock, Mock, call, patch
+
+pytestmark = [
+    pytest.mark.skip_unless_on_linux(reason="Only supported on Linux family"),
+]
+
 
 # 'md5' + md5('password' + 'username')
 md5_pw = "md55a231fcdb710d73268c4f44283487ba2"
@@ -13,9 +22,47 @@ scram_pw = (
     "LzAh/MGUdjYkdbDzcOKpfGwa3WwPUsyGcY+TEnSpcto="
 )
 
-test_privileges_list_function_csv = (
-    'name\n"{baruwatest=X/baruwatest,bayestest=r/baruwatest,baruwa=X*/baruwatest}"\n'
-)
+
+@pytest.fixture
+def get_test_privileges_list_function_csv():
+    return """name
+"{baruwatest=X/baruwatest,bayestest=r/baruwatest,baruwa=X*/baruwatest}"
+"""
+
+
+@pytest.fixture
+def get_test_list_db_csv():
+    return """Name,Owner,Encoding,Collate,Ctype,Access privileges,Tablespace
+template1,postgres,LATIN1,en_US,en_US,"{=c/postgres,postgres=CTc/postgres}",pg_default
+template0,postgres,LATIN1,en_US,en_US,"{=c/postgres,postgres=CTc/postgres}",pg_default
+postgres,postgres,LATIN1,en_US,en_US,,pg_default
+test_db,postgres,LATIN1,en_US,en_US,,pg_default
+"""
+
+
+@pytest.fixture
+def get_test_list_schema_csv():
+    return """name,owner,acl
+public,postgres,"{postgres=UC/postgres,=UC/postgres}"
+pg_toast,postgres,""
+"""
+
+
+@pytest.fixture
+def get_test_list_language_csv():
+    return "Name\ninternal\nc\nsql\nplpgsql\n"
+
+
+@pytest.fixture
+def get_test_privileges_list_table_csv():
+    return """name
+"{baruwatest=arwdDxtm/baruwatest,bayestest=arwd/baruwatest,baruwa=a*r*w*d*D*x*t*m*/baruwatest}"
+"""
+
+
+@pytest.fixture
+def get_test_privileges_list_group_csv():
+    return "rolname,admin_option\nbaruwa,f\nbaruwatest2,t\nbaruwatest,f\n"
 
 
 @pytest.fixture
@@ -73,11 +120,11 @@ def test_verify_password(role, password, verifier, method, result):
     assert postgres._verify_password(role, password, verifier, method) == result
 
 
-def test_has_privileges_with_function():
+def test_has_privileges_with_function(get_test_privileges_list_function_csv):
     with patch(
         "salt.modules.postgres._run_psql",
         MagicMock(
-            return_value={"retcode": 0, "stdout": test_privileges_list_function_csv}
+            return_value={"retcode": 0, "stdout": get_test_privileges_list_function_csv}
         ),
     ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
         ret = postgres.has_privileges(
@@ -181,3 +228,2342 @@ def test__run_initdb_with_timeout():
             with patch.dict(configmod.__opts__, {"postgres.pass": None}):
                 postgres._run_initdb("fakename", runas="saltuser")
                 cmd_run_mock.assert_called_with(cmd_str, timeout=0, **kwargs)
+
+
+def test_run_psql():
+    postgres._run_psql('echo "hi"')
+    cmd = postgres.__salt__["cmd.run_all"]
+    assert cmd.call_args[1]["runas"] == "postgres"
+
+
+def test_db_alter():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        ret = postgres.db_alter(
+            "dbname",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            tablespace="testspace",
+            owner="otheruser",
+            runas="foo",
+        )
+        assert ret is True
+
+        postgres._run_psql.assert_has_calls(
+            [
+                call(
+                    [
+                        "/usr/bin/pgsql",
+                        "--no-align",
+                        "--no-readline",
+                        "--no-psqlrc",
+                        "--no-password",
+                        "--username",
+                        "testuser",
+                        "--host",
+                        "testhost",
+                        "--port",
+                        "testport",
+                        "--dbname",
+                        "maint_db",
+                        "-c",
+                        'ALTER DATABASE "dbname" OWNER TO "otheruser"',
+                    ],
+                    host="testhost",
+                    user="testuser",
+                    password="foo",
+                    runas="foo",
+                    port="testport",
+                ),
+                call(
+                    [
+                        "/usr/bin/pgsql",
+                        "--no-align",
+                        "--no-readline",
+                        "--no-psqlrc",
+                        "--no-password",
+                        "--username",
+                        "testuser",
+                        "--host",
+                        "testhost",
+                        "--port",
+                        "testport",
+                        "--dbname",
+                        "maint_db",
+                        "-c",
+                        'ALTER DATABASE "dbname" SET TABLESPACE "testspace"',
+                    ],
+                    host="testhost",
+                    user="testuser",
+                    password="foo",
+                    runas="foo",
+                    port="testport",
+                ),
+            ]
+        )
+
+
+def test_db_alter_owner_recurse():
+    with patch(
+        "salt.modules.postgres.owner_to", Mock(return_value={"retcode": None})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        postgres.db_alter(
+            "dbname",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            tablespace="testspace",
+            owner="otheruser",
+            owner_recurse=True,
+            runas="foo",
+        )
+        postgres.owner_to.assert_called_once_with(
+            "dbname",
+            "otheruser",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            password="foo",
+            runas="foo",
+        )
+
+
+def test_db_create():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        postgres.db_create(
+            "dbname",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            tablespace="testspace",
+            owner="otheruser",
+            runas="foo",
+        )
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "maint_db",
+                "-c",
+                'CREATE DATABASE "dbname" WITH TABLESPACE = "testspace" '
+                'OWNER = "otheruser"',
+            ],
+            host="testhost",
+            user="testuser",
+            password="foo",
+            runas="foo",
+            port="testport",
+        )
+
+
+def test_db_create_empty_string_param():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        postgres.db_create(
+            "dbname",
+            lc_collate="",
+            encoding="utf8",
+            user="testuser",
+            host="testhost",
+            port=1234,
+            maintenance_db="maint_db",
+            password="foo",
+        )
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "1234",
+                "--dbname",
+                "maint_db",
+                "-c",
+                "CREATE DATABASE \"dbname\" WITH ENCODING = 'utf8' LC_COLLATE = ''",
+            ],
+            host="testhost",
+            password="foo",
+            port=1234,
+            runas=None,
+            user="testuser",
+        )
+
+
+def test_db_create_with_trivial_sql_injection():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        pytest.raises(
+            SaltInvocationError,
+            postgres.db_create,
+            "dbname",
+            lc_collate="foo' ENCODING='utf8",
+        )
+
+
+def test_db_exists(get_test_list_db_csv):
+    with patch(
+        "salt.modules.postgres._run_psql",
+        Mock(return_value={"retcode": 0, "stdout": get_test_list_db_csv}),
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        ret = postgres.db_exists(
+            "test_db",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            runas="foo",
+        )
+        assert ret is True
+
+
+def test_db_list(get_test_list_db_csv):
+    with patch(
+        "salt.modules.postgres._run_psql",
+        Mock(return_value={"retcode": 0, "stdout": get_test_list_db_csv}),
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        ret = postgres.db_list(
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            runas="foo",
+        )
+        assert ret == {
+            "test_db": {
+                "Encoding": "LATIN1",
+                "Ctype": "en_US",
+                "Tablespace": "pg_default",
+                "Collate": "en_US",
+                "Owner": "postgres",
+                "Access privileges": "",
+            },
+            "template1": {
+                "Encoding": "LATIN1",
+                "Ctype": "en_US",
+                "Tablespace": "pg_default",
+                "Collate": "en_US",
+                "Owner": "postgres",
+                "Access privileges": "{=c/postgres,postgres=CTc/postgres}",
+            },
+            "template0": {
+                "Encoding": "LATIN1",
+                "Ctype": "en_US",
+                "Tablespace": "pg_default",
+                "Collate": "en_US",
+                "Owner": "postgres",
+                "Access privileges": "{=c/postgres,postgres=CTc/postgres}",
+            },
+            "postgres": {
+                "Encoding": "LATIN1",
+                "Ctype": "en_US",
+                "Tablespace": "pg_default",
+                "Collate": "en_US",
+                "Owner": "postgres",
+                "Access privileges": "",
+            },
+        }
+
+
+def test_db_remove():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        postgres.db_remove(
+            "test_db",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            runas="foo",
+        )
+
+        calls = (
+            call(
+                [
+                    "/usr/bin/pgsql",
+                    "--no-align",
+                    "--no-readline",
+                    "--no-psqlrc",
+                    "--no-password",
+                    "--username",
+                    "testuser",
+                    "--host",
+                    "testhost",
+                    "--port",
+                    "testport",
+                    "--dbname",
+                    "maint_db",
+                    "-c",
+                    'REVOKE CONNECT ON DATABASE "test_db" FROM public;',
+                ],
+                host="testhost",
+                password="foo",
+                port="testport",
+                runas="foo",
+                user="testuser",
+            ),
+            call(
+                [
+                    "/usr/bin/pgsql",
+                    "--no-align",
+                    "--no-readline",
+                    "--no-psqlrc",
+                    "--no-password",
+                    "--username",
+                    "testuser",
+                    "--host",
+                    "testhost",
+                    "--port",
+                    "testport",
+                    "--dbname",
+                    "maint_db",
+                    "-c",
+                    "SELECT pid, pg_terminate_backend(pid) FROM pg_stat_activity"
+                    " WHERE datname = 'test_db' AND pid <> pg_backend_pid();",
+                ],
+                host="testhost",
+                password="foo",
+                port="testport",
+                runas="foo",
+                user="testuser",
+            ),
+            call(
+                [
+                    "/usr/bin/pgsql",
+                    "--no-align",
+                    "--no-readline",
+                    "--no-psqlrc",
+                    "--no-password",
+                    "--username",
+                    "testuser",
+                    "--host",
+                    "testhost",
+                    "--port",
+                    "testport",
+                    "--dbname",
+                    "maint_db",
+                    "-c",
+                    'DROP DATABASE "test_db";',
+                ],
+                host="testhost",
+                password="foo",
+                port="testport",
+                runas="foo",
+                user="testuser",
+            ),
+        )
+
+        postgres._run_psql.assert_has_calls(calls, any_order=True)
+
+
+def test_group_create():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")), patch(
+        "salt.modules.postgres.user_exists", Mock(return_value=False)
+    ):
+        postgres.group_create(
+            "testgroup",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            createdb=False,
+            encrypted=False,
+            superuser=False,
+            replication=False,
+            rolepassword="testrolepass",
+            groups="testgroup",
+            runas="foo",
+        )
+        # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
+        # The first 14 elements of this list are initial args used in all (or
+        # virtually all) commands run through _run_psql(), so the actual SQL
+        # query will be in the 15th argument.
+        assert postgres._run_psql.call_args[0][0][14].startswith("CREATE ROLE")
+
+
+def test_group_remove():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")), patch(
+        "salt.modules.postgres.user_exists", Mock(return_value=True)
+    ):
+        postgres.group_remove(
+            "testgroup",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            runas="foo",
+        )
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "maint_db",
+                "-c",
+                'DROP ROLE "testgroup"',
+            ],
+            host="testhost",
+            user="testuser",
+            password="foo",
+            runas="foo",
+            port="testport",
+        )
+
+
+def test_group_update():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch(
+        "salt.modules.postgres.role_get",
+        Mock(return_value={"superuser": False}),
+    ):
+        postgres.group_update(
+            "testgroup",
+            user='"testuser"',
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            createdb=False,
+            encrypted=False,
+            replication=False,
+            rolepassword="test_role_pass",
+            groups="testgroup",
+            runas="foo",
+        )
+        # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
+        # The first 14 elements of this list are initial args used in all (or
+        # virtually all) commands run through _run_psql(), so the actual SQL
+        # query will be in the 15th argument.
+        assert re.match(
+            'ALTER.* "testgroup" .* UNENCRYPTED PASSWORD',
+            postgres._run_psql.call_args[0][0][14],
+        )
+
+
+def test_user_create():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.modules.postgres.user_exists", Mock(return_value=False)):
+        postgres.user_create(
+            "testuser",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_test",
+            password="test_pass",
+            login=True,
+            createdb=False,
+            createroles=False,
+            encrypted=False,
+            superuser=False,
+            replication=False,
+            rolepassword="test_role_pass",
+            valid_until="2042-07-01",
+            groups="test_groups",
+            runas="foo",
+        )
+        # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
+        # The first 14 elements of this list are initial args used in all (or
+        # virtually all) commands run through _run_psql(), so the actual SQL
+        # query will be in the 15th argument.
+        call = postgres._run_psql.call_args[0][0][14]
+        assert re.match('CREATE ROLE "testuser"', call)
+        for i in (
+            "INHERIT",
+            "NOCREATEDB",
+            "NOCREATEROLE",
+            "NOSUPERUSER",
+            "NOREPLICATION",
+            "LOGIN",
+            "UNENCRYPTED",
+            "PASSWORD",
+            "VALID UNTIL",
+        ):
+            assert i in call, f"{i} not in {call}"
+
+
+def test_user_exists():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.modules.postgres.version", Mock(return_value="9.1")), patch(
+        "salt.modules.postgres.psql_query",
+        Mock(
+            return_value=[
+                {
+                    "name": "test_user",
+                    "superuser": "t",
+                    "inherits privileges": "t",
+                    "can create roles": "t",
+                    "can create databases": "t",
+                    "can update system catalogs": "t",
+                    "can login": "t",
+                    "replication": None,
+                    "password": "test_password",
+                    "connections": "-1",
+                    "groups": "",
+                    "expiry time": "",
+                    "defaults variables": None,
+                }
+            ]
+        ),
+    ):
+        ret = postgres.user_exists(
+            "test_user",
+            user="test_user",
+            host="test_host",
+            port="test_port",
+            maintenance_db="maint_db",
+            password="test_password",
+            runas="foo",
+        )
+        assert ret is True
+
+
+def test_user_list():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.modules.postgres.version", Mock(return_value="9.1")), patch(
+        "salt.modules.postgres.psql_query",
+        Mock(
+            return_value=[
+                {
+                    "name": "test_user",
+                    "superuser": "t",
+                    "inherits privileges": "t",
+                    "can create roles": "t",
+                    "can create databases": "t",
+                    "can update system catalogs": "t",
+                    "can login": "t",
+                    "replication": None,
+                    "connections": "-1",
+                    "groups": "",
+                    "expiry time": "2017-08-16 08:57:46",
+                    "defaults variables": None,
+                }
+            ]
+        ),
+    ):
+        ret = postgres.user_list(
+            "test_user",
+            host="test_host",
+            port="test_port",
+            maintenance_db="maint_db",
+            password="test_password",
+            runas="foo",
+        )
+
+        assert ret == {
+            "test_user": {
+                "superuser": True,
+                "defaults variables": None,
+                "can create databases": True,
+                "can create roles": True,
+                "connections": None,
+                "replication": None,
+                "expiry time": datetime.datetime(2017, 8, 16, 8, 57, 46),
+                "can login": True,
+                "can update system catalogs": True,
+                "groups": [],
+                "inherits privileges": True,
+            }
+        }
+
+
+def test_user_remove():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")), patch(
+        "salt.modules.postgres.version", Mock(return_value="9.1")
+    ), patch(
+        "salt.modules.postgres.user_exists", Mock(return_value=True)
+    ):
+        postgres.user_remove(
+            "testuser",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="testpassword",
+            runas="foo",
+        )
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "maint_db",
+                "-c",
+                'DROP ROLE "testuser"',
+            ],
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+            runas="foo",
+        )
+
+
+def test_user_update():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch(
+        "salt.modules.postgres.role_get",
+        Mock(return_value={"superuser": False}),
+    ):
+        postgres.user_update(
+            "test_username",
+            user="test_user",
+            host="test_host",
+            port="test_port",
+            maintenance_db="test_maint",
+            password="test_pass",
+            createdb=False,
+            createroles=False,
+            encrypted=False,
+            inherit=True,
+            login=True,
+            replication=False,
+            rolepassword="test_role_pass",
+            valid_until="2017-07-01",
+            groups="test_groups",
+            runas="foo",
+        )
+        # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
+        # The first 14 elements of this list are initial args used in all (or
+        # virtually all) commands run through _run_psql(), so the actual SQL
+        # query will be in the 15th argument.
+        assert re.match(
+            'ALTER ROLE "test_username" WITH  INHERIT NOCREATEDB '
+            "NOCREATEROLE NOREPLICATION LOGIN "
+            "UNENCRYPTED PASSWORD ['\"]{0,5}test_role_pass['\"]{0,5} "
+            "VALID UNTIL '2017-07-01';"
+            ' GRANT "test_groups" TO "test_username"',
+            postgres._run_psql.call_args[0][0][14],
+        )
+
+
+def test_user_update2():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch(
+        "salt.modules.postgres.role_get",
+        Mock(return_value={"superuser": False}),
+    ):
+        postgres.user_update(
+            "test_username",
+            user="test_user",
+            host="test_host",
+            port="test_port",
+            maintenance_db="test_maint",
+            password="test_pass",
+            createdb=False,
+            createroles=True,
+            encrypted=False,
+            inherit=True,
+            login=True,
+            replication=False,
+            groups="test_groups",
+            runas="foo",
+        )
+        # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
+        # The first 14 elements of this list are initial args used in all (or
+        # virtually all) commands run through _run_psql(), so the actual SQL
+        # query will be in the 15th argument.
+        assert re.match(
+            'ALTER ROLE "test_username" WITH  INHERIT NOCREATEDB '
+            "CREATEROLE NOREPLICATION LOGIN;"
+            ' GRANT "test_groups" TO "test_username"',
+            postgres._run_psql.call_args[0][0][14],
+        )
+
+
+def test_user_update3():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch(
+        "salt.modules.postgres.role_get",
+        Mock(return_value={"superuser": False}),
+    ):
+        postgres.user_update(
+            "test_username",
+            user="test_user",
+            host="test_host",
+            port="test_port",
+            maintenance_db="test_maint",
+            password="test_pass",
+            createdb=False,
+            createroles=True,
+            encrypted=False,
+            inherit=True,
+            login=True,
+            rolepassword=False,
+            replication=False,
+            groups="test_groups",
+            runas="foo",
+        )
+        # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
+        # The first 14 elements of this list are initial args used in all (or
+        # virtually all) commands run through _run_psql(), so the actual SQL
+        # query will be in the 15th argument.
+        assert re.match(
+            'ALTER ROLE "test_username" WITH  INHERIT NOCREATEDB '
+            "CREATEROLE NOREPLICATION LOGIN NOPASSWORD;"
+            ' GRANT "test_groups" TO "test_username"',
+            postgres._run_psql.call_args[0][0][14],
+        )
+
+
+def test_user_update_encrypted_passwd():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch(
+        "salt.modules.postgres.role_get",
+        Mock(return_value={"superuser": False}),
+    ):
+        postgres.user_update(
+            "test_username",
+            user="test_user",
+            host="test_host",
+            port="test_port",
+            maintenance_db="test_maint",
+            password="test_pass",
+            createdb=False,
+            createroles=True,
+            encrypted=True,
+            inherit=True,
+            login=True,
+            rolepassword="foobar",
+            replication=False,
+            groups="test_groups",
+            runas="foo",
+        )
+        # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
+        # The first 14 elements of this list are initial args used in all (or
+        # virtually all) commands run through _run_psql(), so the actual SQL
+        # query will be in the 15th argument.
+        assert re.match(
+            'ALTER ROLE "test_username" WITH  INHERIT NOCREATEDB '
+            "CREATEROLE NOREPLICATION LOGIN "
+            "ENCRYPTED PASSWORD "
+            "['\"]{0,5}md531c27e68d3771c392b52102c01be1da1['\"]{0,5}"
+            '; GRANT "test_groups" TO "test_username"',
+            postgres._run_psql.call_args[0][0][14],
+        )
+
+
+def test_version():
+    with patch(
+        "salt.modules.postgres._run_psql",
+        Mock(return_value={"retcode": 0, "stdout": "9.1.9"}),
+    ):
+        postgres.version(
+            user="test_user",
+            host="test_host",
+            port="test_port",
+            maintenance_db="test_maint",
+            password="test_pass",
+            runas="foo",
+        )
+        # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
+        # The first 14 elements of this list are initial args used in all (or
+        # virtually all) commands run through _run_psql(), so the actual SQL
+        # query will be in the 15th argument.
+        assert re.match(
+            "SELECT setting FROM pg_catalog.pg_settings",
+            postgres._run_psql.call_args[0][0][14],
+        )
+
+
+def test_installed_extensions():
+    with patch(
+        "salt.modules.postgres.psql_query",
+        Mock(return_value=[{"extname": "foo", "extversion": "1"}]),
+    ):
+        exts = postgres.installed_extensions()
+        assert exts == {"foo": {"extversion": "1", "extname": "foo"}}
+
+
+def test_available_extensions():
+    with patch(
+        "salt.modules.postgres.psql_query",
+        Mock(return_value=[{"name": "foo", "default_version": "1"}]),
+    ):
+        exts = postgres.available_extensions()
+        assert exts == {"foo": {"default_version": "1", "name": "foo"}}
+
+
+def test_drop_extension2():
+    with patch(
+        "salt.modules.postgres.installed_extensions", Mock(side_effect=[{}, {}])
+    ):
+        with patch(
+            "salt.modules.postgres._psql_prepare_and_run", Mock(return_value=None)
+        ):
+            with patch(
+                "salt.modules.postgres.available_extensions",
+                Mock(return_value={"foo": {"default_version": "1", "name": "foo"}}),
+            ):
+                assert postgres.drop_extension("foo")
+
+
+def test_drop_extension3():
+    with patch(
+        "salt.modules.postgres.installed_extensions",
+        Mock(side_effect=[{"foo": {"extversion": "1", "extname": "foo"}}, {}]),
+    ):
+        with patch(
+            "salt.modules.postgres._psql_prepare_and_run", Mock(return_value=None)
+        ):
+            with patch(
+                "salt.modules.postgres.available_extensions",
+                Mock(return_value={"foo": {"default_version": "1", "name": "foo"}}),
+            ):
+                assert postgres.drop_extension("foo")
+
+
+def test_drop_extension1():
+    with patch(
+        "salt.modules.postgres.installed_extensions",
+        Mock(
+            side_effect=[
+                {"foo": {"extversion": "1", "extname": "foo"}},
+                {"foo": {"extversion": "1", "extname": "foo"}},
+            ]
+        ),
+    ):
+        with patch(
+            "salt.modules.postgres._psql_prepare_and_run", Mock(return_value=None)
+        ):
+            with patch(
+                "salt.modules.postgres.available_extensions",
+                Mock(return_value={"foo": {"default_version": "1", "name": "foo"}}),
+            ):
+                assert not postgres.drop_extension("foo")
+
+
+def test_create_mtdata():
+    with patch(
+        "salt.modules.postgres.installed_extensions",
+        Mock(
+            return_value={
+                "foo": {
+                    "extversion": "0.8",
+                    "extrelocatable": "t",
+                    "schema_name": "foo",
+                    "extname": "foo",
+                }
+            },
+        ),
+    ):
+        with patch(
+            "salt.modules.postgres.available_extensions",
+            Mock(return_value={"foo": {"default_version": "1.4", "name": "foo"}}),
+        ):
+            ret = postgres.create_metadata("foo", schema="bar", ext_version="1.4")
+            assert postgres._EXTENSION_INSTALLED in ret
+            assert postgres._EXTENSION_TO_UPGRADE in ret
+            assert postgres._EXTENSION_TO_MOVE in ret
+
+            ret = postgres.create_metadata("foo", schema="foo", ext_version="0.4")
+            assert postgres._EXTENSION_INSTALLED in ret
+            assert postgres._EXTENSION_TO_UPGRADE not in ret
+            assert postgres._EXTENSION_TO_MOVE not in ret
+
+            ret = postgres.create_metadata("foo")
+            assert postgres._EXTENSION_INSTALLED in ret
+            assert postgres._EXTENSION_TO_UPGRADE not in ret
+            assert postgres._EXTENSION_TO_MOVE not in ret
+
+            ret = postgres.create_metadata("foobar")
+            assert postgres._EXTENSION_NOT_INSTALLED in ret
+            assert postgres._EXTENSION_INSTALLED not in ret
+            assert postgres._EXTENSION_TO_UPGRADE not in ret
+            assert postgres._EXTENSION_TO_MOVE not in ret
+
+
+def test_create_extension_newerthan():
+    """
+    scenario of creating upgrading extensions with possible schema and
+    version specifications
+    """
+    with patch(
+        "salt.modules.postgres.create_metadata",
+        Mock(
+            side_effect=[
+                # create succeeded
+                [postgres._EXTENSION_NOT_INSTALLED],
+                [postgres._EXTENSION_INSTALLED],
+                [postgres._EXTENSION_NOT_INSTALLED],
+                [postgres._EXTENSION_INSTALLED],
+                # create failed
+                [postgres._EXTENSION_NOT_INSTALLED],
+                [postgres._EXTENSION_NOT_INSTALLED],
+                # move+upgrade succeeded
+                [
+                    postgres._EXTENSION_TO_MOVE,
+                    postgres._EXTENSION_TO_UPGRADE,
+                    postgres._EXTENSION_INSTALLED,
+                ],
+                [postgres._EXTENSION_INSTALLED],
+                # move succeeded
+                [postgres._EXTENSION_TO_MOVE, postgres._EXTENSION_INSTALLED],
+                [postgres._EXTENSION_INSTALLED],
+                # upgrade succeeded
+                [postgres._EXTENSION_TO_UPGRADE, postgres._EXTENSION_INSTALLED],
+                [postgres._EXTENSION_INSTALLED],
+                # upgrade failed
+                [postgres._EXTENSION_TO_UPGRADE, postgres._EXTENSION_INSTALLED],
+                [postgres._EXTENSION_TO_UPGRADE, postgres._EXTENSION_INSTALLED],
+                # move failed
+                [postgres._EXTENSION_TO_MOVE, postgres._EXTENSION_INSTALLED],
+                [postgres._EXTENSION_TO_MOVE, postgres._EXTENSION_INSTALLED],
+            ]
+        ),
+    ):
+        with patch(
+            "salt.modules.postgres._psql_prepare_and_run", Mock(return_value=None)
+        ):
+            with patch(
+                "salt.modules.postgres.available_extensions",
+                Mock(return_value={"foo": {"default_version": "1.4", "name": "foo"}}),
+            ):
+                assert postgres.create_extension("foo")
+                assert re.match(
+                    'CREATE EXTENSION IF NOT EXISTS "foo" ;',
+                    postgres._psql_prepare_and_run.call_args[0][0][1],
+                )
+
+                assert postgres.create_extension(
+                    "foo", schema="a", ext_version="b", from_version="c"
+                )
+                assert re.match(
+                    'CREATE EXTENSION IF NOT EXISTS "foo" '
+                    'WITH SCHEMA "a" VERSION b FROM c ;',
+                    postgres._psql_prepare_and_run.call_args[0][0][1],
+                )
+                assert not postgres.create_extension("foo")
+
+                ret = postgres.create_extension("foo", ext_version="a", schema="b")
+                assert ret is True
+                assert re.match(
+                    'ALTER EXTENSION "foo" SET SCHEMA "b";'
+                    ' ALTER EXTENSION "foo" UPDATE TO a;',
+                    postgres._psql_prepare_and_run.call_args[0][0][1],
+                )
+
+                ret = postgres.create_extension("foo", ext_version="a", schema="b")
+                assert ret is True
+                assert re.match(
+                    'ALTER EXTENSION "foo" SET SCHEMA "b";',
+                    postgres._psql_prepare_and_run.call_args[0][0][1],
+                )
+
+                ret = postgres.create_extension("foo", ext_version="a", schema="b")
+                assert ret is True
+                assert re.match(
+                    'ALTER EXTENSION "foo" UPDATE TO a;',
+                    postgres._psql_prepare_and_run.call_args[0][0][1],
+                )
+                assert not postgres.create_extension("foo", ext_version="a", schema="b")
+                assert not postgres.create_extension("foo", ext_version="a", schema="b")
+
+
+def test_encrypt_passwords():
+    assert postgres._maybe_encrypt_password("foo", "bar", False) == "bar"
+    assert (
+        postgres._maybe_encrypt_password("foo", "bar", True)
+        == "md596948aad3fcae80c08a35c9b5958cd89"
+    )
+
+
+def test_schema_list(get_test_list_schema_csv):
+    with patch(
+        "salt.modules.postgres._run_psql",
+        Mock(return_value={"retcode": 0, "stdout": get_test_list_schema_csv}),
+    ):
+        ret = postgres.schema_list(
+            "maint_db",
+            db_user="testuser",
+            db_host="testhost",
+            db_port="testport",
+            db_password="foo",
+        )
+        assert ret == {
+            "public": {
+                "acl": "{postgres=UC/postgres,=UC/postgres}",
+                "owner": "postgres",
+            },
+            "pg_toast": {"acl": "", "owner": "postgres"},
+        }
+
+
+def test_schema_exists():
+    with patch("salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})):
+        with patch(
+            "salt.modules.postgres.psql_query",
+            Mock(
+                return_value=[
+                    {
+                        "name": "public",
+                        "acl": "{postgres=UC/postgres,=UC/postgres}",
+                        "owner": "postgres",
+                    }
+                ]
+            ),
+        ):
+            ret = postgres.schema_exists("template1", "public")
+            assert ret is True
+
+
+def test_schema_get():
+    with patch("salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})):
+        with patch(
+            "salt.modules.postgres.psql_query",
+            Mock(
+                return_value=[
+                    {
+                        "name": "public",
+                        "acl": "{postgres=UC/postgres,=UC/postgres}",
+                        "owner": "postgres",
+                    }
+                ]
+            ),
+        ):
+            ret = postgres.schema_get("template1", "public")
+            assert ret == {
+                "acl": "{postgres=UC/postgres,=UC/postgres}",
+                "owner": "postgres",
+            }
+
+
+def test_schema_get_again():
+    with patch("salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})):
+        with patch(
+            "salt.modules.postgres.psql_query",
+            Mock(
+                return_value=[
+                    {
+                        "name": "public",
+                        "acl": "{postgres=UC/postgres,=UC/postgres}",
+                        "owner": "postgres",
+                    }
+                ]
+            ),
+        ):
+            ret = postgres.schema_get("template1", "pg_toast")
+            assert ret is None
+
+
+def test_schema_create():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        with patch("salt.modules.postgres.schema_exists", Mock(return_value=False)):
+            postgres.schema_create(
+                "maint_db",
+                "testschema",
+                user="user",
+                db_host="testhost",
+                db_port="testport",
+                db_user="testuser",
+                db_password="testpassword",
+            )
+            postgres._run_psql.assert_called_once_with(
+                [
+                    "/usr/bin/pgsql",
+                    "--no-align",
+                    "--no-readline",
+                    "--no-psqlrc",
+                    "--no-password",
+                    "--username",
+                    "testuser",
+                    "--host",
+                    "testhost",
+                    "--port",
+                    "testport",
+                    "--dbname",
+                    "maint_db",
+                    "-c",
+                    'CREATE SCHEMA "testschema"',
+                ],
+                host="testhost",
+                port="testport",
+                password="testpassword",
+                user="testuser",
+                runas="user",
+            )
+
+
+def test_schema_create2():
+    with patch("salt.modules.postgres.schema_exists", Mock(return_value=True)):
+        ret = postgres.schema_create(
+            "test_db",
+            "test_schema",
+            user="user",
+            db_host="test_host",
+            db_port="test_port",
+            db_user="test_user",
+            db_password="test_password",
+        )
+        assert ret is False
+
+
+def test_schema_remove():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        with patch("salt.modules.postgres.schema_exists", Mock(return_value=True)):
+            postgres.schema_remove(
+                "maint_db",
+                "testschema",
+                user="user",
+                db_host="testhost",
+                db_port="testport",
+                db_user="testuser",
+                db_password="testpassword",
+            )
+            postgres._run_psql.assert_called_once_with(
+                [
+                    "/usr/bin/pgsql",
+                    "--no-align",
+                    "--no-readline",
+                    "--no-psqlrc",
+                    "--no-password",
+                    "--username",
+                    "testuser",
+                    "--host",
+                    "testhost",
+                    "--port",
+                    "testport",
+                    "--dbname",
+                    "maint_db",
+                    "-c",
+                    'DROP SCHEMA "testschema"',
+                ],
+                host="testhost",
+                port="testport",
+                password="testpassword",
+                user="testuser",
+                runas="user",
+            )
+
+
+def test_schema_remove2():
+    with patch("salt.modules.postgres.schema_exists", Mock(return_value=False)):
+        ret = postgres.schema_remove(
+            "test_db",
+            "test_schema",
+            user="user",
+            db_host="test_host",
+            db_port="test_port",
+            db_user="test_user",
+            db_password="test_password",
+        )
+        assert ret is False
+
+
+def test_language_list(get_test_list_language_csv):
+    """
+    Test language listing
+    """
+    with patch(
+        "salt.modules.postgres._run_psql",
+        Mock(return_value={"retcode": 0, "stdout": get_test_list_language_csv}),
+    ):
+        ret = postgres.language_list(
+            "testdb",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            password="foo",
+        )
+        assert ret == {
+            "c": "c",
+            "internal": "internal",
+            "plpgsql": "plpgsql",
+            "sql": "sql",
+        }
+
+
+def test_language_exists():
+    """
+    Test language existence check
+    """
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch(
+        "salt.modules.postgres.psql_query",
+        Mock(
+            return_value=[
+                {"Name": "internal"},
+                {"Name": "c"},
+                {"Name": "sql"},
+                {"Name": "plpgsql"},
+            ]
+        ),
+    ), patch(
+        "salt.modules.postgres.language_exists", Mock(return_value=True)
+    ):
+        ret = postgres.language_exists("sql", "testdb")
+        assert ret is True
+
+
+def test_language_create():
+    """
+    Test language creation - does not exist in db
+    """
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        with patch("salt.modules.postgres.language_exists", Mock(return_value=False)):
+            postgres.language_create(
+                "plpythonu",
+                "testdb",
+                runas="user",
+                host="testhost",
+                port="testport",
+                user="testuser",
+                password="testpassword",
+            )
+            postgres._run_psql.assert_called_once_with(
+                [
+                    "/usr/bin/pgsql",
+                    "--no-align",
+                    "--no-readline",
+                    "--no-psqlrc",
+                    "--no-password",
+                    "--username",
+                    "testuser",
+                    "--host",
+                    "testhost",
+                    "--port",
+                    "testport",
+                    "--dbname",
+                    "testdb",
+                    "-c",
+                    "CREATE LANGUAGE plpythonu",
+                ],
+                host="testhost",
+                port="testport",
+                password="testpassword",
+                user="testuser",
+                runas="user",
+            )
+
+
+def test_language_create_exists():
+    """
+    Test language creation - already exists in db
+    """
+    with patch("salt.modules.postgres.language_exists", Mock(return_value=True)):
+        ret = postgres.language_create(
+            "plpythonu",
+            "testdb",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+        assert ret is False
+
+
+def test_language_remove():
+    """
+    Test language removal - exists in db
+    """
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        with patch("salt.modules.postgres.language_exists", Mock(return_value=True)):
+            postgres.language_remove(
+                "plpgsql",
+                "testdb",
+                runas="user",
+                host="testhost",
+                port="testport",
+                user="testuser",
+                password="testpassword",
+            )
+            postgres._run_psql.assert_called_once_with(
+                [
+                    "/usr/bin/pgsql",
+                    "--no-align",
+                    "--no-readline",
+                    "--no-psqlrc",
+                    "--no-password",
+                    "--username",
+                    "testuser",
+                    "--host",
+                    "testhost",
+                    "--port",
+                    "testport",
+                    "--dbname",
+                    "testdb",
+                    "-c",
+                    "DROP LANGUAGE plpgsql",
+                ],
+                host="testhost",
+                port="testport",
+                password="testpassword",
+                user="testuser",
+                runas="user",
+            )
+
+
+def test_language_remove_non_exist():
+    """
+    Test language removal - does not exist in db
+    """
+    with patch("salt.modules.postgres.language_exists", Mock(return_value=False)):
+        ret = postgres.language_remove(
+            "plpgsql",
+            "testdb",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+        assert ret is False
+
+
+def test_privileges_list_table(get_test_privileges_list_table_csv):
+    """
+    Test privilege listing on a table
+    """
+    with patch(
+        "salt.modules.postgres._run_psql",
+        Mock(return_value={"retcode": 0, "stdout": get_test_privileges_list_table_csv}),
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        ret = postgres.privileges_list(
+            "awl",
+            "table",
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+        expected = {
+            "bayestest": {
+                "INSERT": False,
+                "UPDATE": False,
+                "SELECT": False,
+                "DELETE": False,
+            },
+            "baruwa": {
+                "INSERT": True,
+                "TRUNCATE": True,
+                "UPDATE": True,
+                "TRIGGER": True,
+                "REFERENCES": True,
+                "SELECT": True,
+                "DELETE": True,
+                "MAINTAIN": True,
+            },
+            "baruwatest": {
+                "INSERT": False,
+                "TRUNCATE": False,
+                "UPDATE": False,
+                "TRIGGER": False,
+                "REFERENCES": False,
+                "SELECT": False,
+                "DELETE": False,
+                "MAINTAIN": False,
+            },
+        }
+        assert ret == expected
+
+        query = (
+            "COPY (SELECT relacl AS name FROM pg_catalog.pg_class c "
+            "JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace "
+            "WHERE nspname = 'public' AND relname = 'awl' AND relkind in ('r', 'v') "
+            "ORDER BY relname) TO STDOUT WITH CSV HEADER"
+        )
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "db_name",
+                "-v",
+                "datestyle=ISO,MDY",
+                "-c",
+                query,
+            ],
+            host="testhost",
+            port="testport",
+            password="testpassword",
+            user="testuser",
+            runas="user",
+        )
+
+
+def test_privileges_list_group(get_test_privileges_list_group_csv):
+    """
+    Test privilege listing on a group
+    """
+    with patch(
+        "salt.modules.postgres._run_psql",
+        Mock(return_value={"retcode": 0, "stdout": get_test_privileges_list_group_csv}),
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        ret = postgres.privileges_list(
+            "admin",
+            "group",
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+        expected = {
+            "baruwa": False,
+            "baruwatest": False,
+            "baruwatest2": True,
+        }
+        assert ret == expected
+
+        query = (
+            "COPY (SELECT rolname, admin_option "
+            "FROM pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles r "
+            "ON m.member=r.oid WHERE m.roleid IN (SELECT oid FROM "
+            "pg_catalog.pg_roles WHERE rolname='admin') ORDER BY rolname) "
+            "TO STDOUT WITH CSV HEADER"
+        )
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "db_name",
+                "-v",
+                "datestyle=ISO,MDY",
+                "-c",
+                query,
+            ],
+            host="testhost",
+            port="testport",
+            password="testpassword",
+            user="testuser",
+            runas="user",
+        )
+
+
+def test_has_privileges_on_table(get_test_privileges_list_table_csv):
+    """
+    Test privilege checks on table
+    """
+    with patch(
+        "salt.modules.postgres._run_psql",
+        Mock(return_value={"retcode": 0, "stdout": get_test_privileges_list_table_csv}),
+    ):
+        ret = postgres.has_privileges(
+            "baruwa",
+            "awl",
+            "table",
+            "SELECT,INSERT",
+            grant_option=True,
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+        assert ret is True
+
+        ret = postgres.has_privileges(
+            "baruwa",
+            "awl",
+            "table",
+            "ALL",
+            grant_option=True,
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+        assert ret is True
+
+        ret = postgres.has_privileges(
+            "baruwa",
+            "awl",
+            "table",
+            "ALL",
+            grant_option=False,
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+        assert ret is True
+
+        ret = postgres.has_privileges(
+            "bayestest",
+            "awl",
+            "table",
+            "SELECT,INSERT,TRUNCATE",
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+        assert ret is False
+
+        ret = postgres.has_privileges(
+            "bayestest",
+            "awl",
+            "table",
+            "SELECT,INSERT",
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+        assert ret is True
+
+
+def test_has_privileges_on_group(get_test_privileges_list_group_csv):
+    """
+    Test privilege checks on group
+    """
+    with patch(
+        "salt.modules.postgres._run_psql",
+        Mock(return_value={"retcode": 0, "stdout": get_test_privileges_list_group_csv}),
+    ):
+        ret = postgres.has_privileges(
+            "baruwa",
+            "admin",
+            "group",
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+        assert ret is True
+
+        ret = postgres.has_privileges(
+            "baruwa",
+            "admin",
+            "group",
+            grant_option=True,
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+        assert ret is False
+
+        ret = postgres.has_privileges(
+            "tony",
+            "admin",
+            "group",
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+        assert ret is False
+
+
+def test_privileges_grant_table():
+    """
+    Test granting privileges on table
+    """
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        with patch("salt.modules.postgres.has_privileges", Mock(return_value=False)):
+            ret = postgres.privileges_grant(
+                "baruwa",
+                "awl",
+                "table",
+                "ALL",
+                grant_option=True,
+                maintenance_db="db_name",
+                runas="user",
+                host="testhost",
+                port="testport",
+                user="testuser",
+                password="testpassword",
+            )
+
+            query = 'GRANT ALL ON TABLE public."awl" TO "baruwa" WITH GRANT OPTION'
+
+            postgres._run_psql.assert_called_once_with(
+                [
+                    "/usr/bin/pgsql",
+                    "--no-align",
+                    "--no-readline",
+                    "--no-psqlrc",
+                    "--no-password",
+                    "--username",
+                    "testuser",
+                    "--host",
+                    "testhost",
+                    "--port",
+                    "testport",
+                    "--dbname",
+                    "db_name",
+                    "-c",
+                    query,
+                ],
+                host="testhost",
+                port="testport",
+                password="testpassword",
+                user="testuser",
+                runas="user",
+            )
+
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")), patch(
+        "salt.modules.postgres.has_privileges", Mock(return_value=False)
+    ):
+        ret = postgres.privileges_grant(
+            "baruwa",
+            "awl",
+            "table",
+            "ALL",
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+
+        query = 'GRANT ALL ON TABLE public."awl" TO "baruwa"'
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "db_name",
+                "-c",
+                query,
+            ],
+            host="testhost",
+            port="testport",
+            password="testpassword",
+            user="testuser",
+            runas="user",
+        )
+
+    # Test grant on all tables
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")), patch(
+        "salt.modules.postgres.has_privileges", Mock(return_value=False)
+    ):
+        ret = postgres.privileges_grant(
+            "baruwa",
+            "ALL",
+            "table",
+            "SELECT",
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+
+        query = 'GRANT SELECT ON ALL TABLES IN SCHEMA public TO "baruwa"'
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "db_name",
+                "-c",
+                query,
+            ],
+            host="testhost",
+            port="testport",
+            password="testpassword",
+            user="testuser",
+            runas="user",
+        )
+
+
+def test_privileges_grant_group():
+    """
+    Test granting privileges on group
+    """
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")), patch(
+        "salt.modules.postgres.has_privileges", Mock(return_value=False)
+    ):
+        ret = postgres.privileges_grant(
+            "baruwa",
+            "admins",
+            "group",
+            grant_option=True,
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+
+        query = 'GRANT admins TO "baruwa" WITH ADMIN OPTION'
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "db_name",
+                "-c",
+                query,
+            ],
+            host="testhost",
+            port="testport",
+            password="testpassword",
+            user="testuser",
+            runas="user",
+        )
+
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")), patch(
+        "salt.modules.postgres.has_privileges", Mock(return_value=False)
+    ):
+        ret = postgres.privileges_grant(
+            "baruwa",
+            "admins",
+            "group",
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+
+        query = 'GRANT admins TO "baruwa"'
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "db_name",
+                "-c",
+                query,
+            ],
+            host="testhost",
+            port="testport",
+            password="testpassword",
+            user="testuser",
+            runas="user",
+        )
+
+
+def test_privileges_revoke_table():
+    """
+    Test revoking privileges on table
+    """
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")), patch(
+        "salt.modules.postgres.has_privileges", Mock(return_value=True)
+    ):
+        ret = postgres.privileges_revoke(
+            "baruwa",
+            "awl",
+            "table",
+            "ALL",
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+
+        query = "REVOKE ALL ON TABLE public.awl FROM baruwa"
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "db_name",
+                "-c",
+                query,
+            ],
+            host="testhost",
+            port="testport",
+            password="testpassword",
+            user="testuser",
+            runas="user",
+        )
+
+
+def test_privileges_revoke_group():
+    """
+    Test revoking privileges on group
+    """
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")), patch(
+        "salt.modules.postgres.has_privileges", Mock(return_value=True)
+    ):
+        ret = postgres.privileges_revoke(
+            "baruwa",
+            "admins",
+            "group",
+            maintenance_db="db_name",
+            runas="user",
+            host="testhost",
+            port="testport",
+            user="testuser",
+            password="testpassword",
+        )
+
+        query = "REVOKE admins FROM baruwa"
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "db_name",
+                "-c",
+                query,
+            ],
+            host="testhost",
+            port="testport",
+            password="testpassword",
+            user="testuser",
+            runas="user",
+        )
+
+
+def test_datadir_init():
+    """
+    Test Initializing a postgres data directory
+    """
+    with patch("salt.modules.postgres._run_initdb", Mock(return_value={"retcode": 0})):
+        with patch("salt.modules.postgres.datadir_exists", Mock(return_value=False)):
+            name = "/var/lib/pgsql/data"
+            ret = postgres.datadir_init(
+                name, user="postgres", password="test", runas="postgres"
+            )
+            postgres._run_initdb.assert_called_once_with(
+                name,
+                auth="password",
+                encoding="UTF8",
+                locale=None,
+                password="test",
+                runas="postgres",
+                checksums=False,
+                waldir=None,
+                user="postgres",
+            )
+            assert ret is True
+
+
+def test_datadir_exists():
+    """
+    Test Checks if postgres data directory has been initialized
+    """
+    with patch("os.path.isfile", Mock(return_value=True)):
+        name = "/var/lib/pgsql/data"
+        ret = postgres.datadir_exists(name)
+        assert ret is True
+
+
+@pytest.mark.parametrize(
+    "v1,v2,result",
+    (
+        ("8.5", "9.5", True),
+        ("8.5", "8.6", True),
+        ("8.5.2", "8.5.3", True),
+        ("9.5", "8.5", False),
+        ("9.5", "9.6", True),
+        ("9.5.0", "9.5.1", True),
+        ("9.5", "9.5.1", True),
+        ("9.5.1", "9.5", False),
+        ("9.5b", "9.5a", False),
+        ("10a", "10b", True),
+        ("1.2.3.4", "1.2.3.5", True),
+        ("10dev", "10next", True),
+        ("10next", "10dev", False),
+    ),
+)
+def test_pg_is_older_ext_ver(v1, v2, result):
+    """
+    Test Checks if postgres extension version string is older
+    """
+    assert postgres._pg_is_older_ext_ver(v1, v2) is result
+
+
+def test_tablespace_create():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        postgres.tablespace_create(
+            "test_tablespace",
+            "/tmp/postgres_test_tablespace",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            owner="otheruser",
+            runas="foo",
+        )
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "maint_db",
+                "-c",
+                'CREATE TABLESPACE "test_tablespace" OWNER "otheruser" LOCATION \'/tmp/postgres_test_tablespace\' ',
+            ],
+            runas="foo",
+            password="foo",
+            host="testhost",
+            port="testport",
+            user="testuser",
+        )
+
+
+def test_tablespace_list():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch(
+        "salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")
+    ), patch.dict(
+        postgres.__salt__,
+        {
+            "postgres.psql_query": MagicMock(
+                return_value=[
+                    {
+                        "Name": "pg_global",
+                        "Owner": "postgres",
+                        "ACL": "",
+                        "Opts": "",
+                        "Location": "",
+                    },
+                    {
+                        "Name": "pg_default",
+                        "Owner": "postgres",
+                        "ACL": "",
+                        "Opts": "",
+                        "Location": "",
+                    },
+                    {
+                        "Name": "test_tablespace",
+                        "Owner": "testuser",
+                        "ACL": "",
+                        "Opts": "",
+                        "Location": "/tmp/posgrest_test_tablespace",
+                    },
+                ]
+            ),
+        },
+    ):
+        ret = postgres.tablespace_list(
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            runas="foo",
+        )
+
+        expected_data = {
+            "pg_global": {"Owner": "postgres", "ACL": "", "Opts": "", "Location": ""},
+            "pg_default": {"Owner": "postgres", "ACL": "", "Opts": "", "Location": ""},
+            "test_tablespace": {
+                "Owner": "testuser",
+                "ACL": "",
+                "Opts": "",
+                "Location": "/tmp/posgrest_test_tablespace",
+            },
+        }
+        assert ret == expected_data
+
+
+def test_tablespace_exists_true():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch(
+        "salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")
+    ), patch.dict(
+        postgres.__salt__,
+        {
+            "postgres.psql_query": MagicMock(
+                return_value=[
+                    {
+                        "Name": "pg_global",
+                        "Owner": "postgres",
+                        "ACL": "",
+                        "Opts": "",
+                        "Location": "",
+                    },
+                    {
+                        "Name": "pg_default",
+                        "Owner": "postgres",
+                        "ACL": "",
+                        "Opts": "",
+                        "Location": "",
+                    },
+                    {
+                        "Name": "test_tablespace",
+                        "Owner": "testuser",
+                        "ACL": "",
+                        "Opts": "",
+                        "Location": "/tmp/posgrest_test_tablespace",
+                    },
+                ]
+            ),
+        },
+    ):
+        ret = postgres.tablespace_exists(
+            "test_tablespace",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            runas="foo",
+        )
+        assert ret is True
+
+
+def test_tablespace_exists_false():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch(
+        "salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")
+    ), patch.dict(
+        postgres.__salt__,
+        {
+            "postgres.psql_query": MagicMock(
+                return_value=[
+                    {
+                        "Name": "pg_global",
+                        "Owner": "postgres",
+                        "ACL": "",
+                        "Opts": "",
+                        "Location": "",
+                    },
+                    {
+                        "Name": "pg_default",
+                        "Owner": "postgres",
+                        "ACL": "",
+                        "Opts": "",
+                        "Location": "",
+                    },
+                    {
+                        "Name": "test_tablespace",
+                        "Owner": "testuser",
+                        "ACL": "",
+                        "Opts": "",
+                        "Location": "/tmp/posgrest_test_tablespace",
+                    },
+                ]
+            ),
+        },
+    ):
+        ret = postgres.tablespace_exists(
+            "bad_test_tablespace",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            runas="foo",
+        )
+        assert ret is False
+
+
+def test_tablespace_alter_new_owner():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        postgres.tablespace_alter(
+            "test_tablespace",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            runas="foo",
+            new_owner="testuser",
+        )
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "maint_db",
+                "-c",
+                'ALTER TABLESPACE "test_tablespace" OWNER TO "testuser"',
+            ],
+            runas="foo",
+            password="foo",
+            host="testhost",
+            port="testport",
+            user="testuser",
+        )
+
+
+def test_tablespace_alter_new_name():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        postgres.tablespace_alter(
+            "test_tablespace",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            runas="foo",
+            new_name="test_tablespace2",
+        )
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "maint_db",
+                "-c",
+                'ALTER TABLESPACE "test_tablespace" RENAME TO "test_tablespace2"',
+            ],
+            runas="foo",
+            password="foo",
+            host="testhost",
+            port="testport",
+            user="testuser",
+        )
+
+
+def test_tablespace_remove():
+    with patch(
+        "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
+    ), patch("salt.utils.path.which", MagicMock(return_value="/usr/bin/pgsql")):
+        postgres.tablespace_remove(
+            "test_tablespace",
+            user="testuser",
+            host="testhost",
+            port="testport",
+            maintenance_db="maint_db",
+            password="foo",
+            runas="foo",
+        )
+
+        postgres._run_psql.assert_called_once_with(
+            [
+                "/usr/bin/pgsql",
+                "--no-align",
+                "--no-readline",
+                "--no-psqlrc",
+                "--no-password",
+                "--username",
+                "testuser",
+                "--host",
+                "testhost",
+                "--port",
+                "testport",
+                "--dbname",
+                "maint_db",
+                "-c",
+                'DROP TABLESPACE "test_tablespace"',
+            ],
+            runas="foo",
+            password="foo",
+            host="testhost",
+            port="testport",
+            user="testuser",
+        )
diff --git a/tests/unit/modules/test_deb_postgres.py b/tests/unit/modules/test_deb_postgres.py
deleted file mode 100644
index 37e276fdff..0000000000
--- a/tests/unit/modules/test_deb_postgres.py
+++ /dev/null
@@ -1,184 +0,0 @@
-import salt.modules.deb_postgres as deb_postgres
-from tests.support.mixins import LoaderModuleMockMixin
-from tests.support.mock import Mock, patch
-from tests.support.unit import TestCase
-
-LSCLUSTER = """\
-8.4 main 5432 online postgres /srv/8.4/main \
-        /var/log/postgresql/postgresql-8.4-main.log
-9.1 main 5433 online postgres /srv/9.1/main \
-        /var/log/postgresql/postgresql-9.1-main.log
-"""
-
-
-class PostgresClusterTestCase(TestCase, LoaderModuleMockMixin):
-    def setup_loader_modules(self):
-        self.cmd_run_all_mock = Mock(return_value={"stdout": LSCLUSTER})
-        self.addCleanup(delattr, self, "cmd_run_all_mock")
-        patcher = patch(
-            "salt.utils.path.which", Mock(return_value="/usr/bin/pg_createcluster")
-        )
-        patcher.start()
-        self.addCleanup(patcher.stop)
-        return {
-            deb_postgres: {
-                "__salt__": {
-                    "config.option": Mock(),
-                    "cmd.run_all": self.cmd_run_all_mock,
-                    "file.chown": Mock(),
-                    "file.remove": Mock(),
-                }
-            }
-        }
-
-    def test_cluster_create(self):
-        deb_postgres.cluster_create(
-            "9.3",
-            "main",
-            port="5432",
-            locale="fr_FR",
-            encoding="UTF-8",
-            datadir="/opt/postgresql",
-        )
-        cmdstr = (
-            "/usr/bin/pg_createcluster "
-            "--port 5432 --locale fr_FR --encoding UTF-8 "
-            "--datadir /opt/postgresql "
-            "9.3 main"
-        )
-        self.assertEqual(cmdstr, self.cmd_run_all_mock.call_args[0][0])
-
-    def test_cluster_create_with_initdb_options(self):
-        deb_postgres.cluster_create(
-            "11",
-            "main",
-            port="5432",
-            locale="fr_FR",
-            encoding="UTF-8",
-            datadir="/opt/postgresql",
-            allow_group_access=True,
-            data_checksums=True,
-            wal_segsize="32",
-        )
-        cmdstr = (
-            "/usr/bin/pg_createcluster "
-            "--port 5432 --locale fr_FR --encoding UTF-8 "
-            "--datadir /opt/postgresql "
-            "11 main "
-            "-- "
-            "--allow-group-access "
-            "--data-checksums "
-            "--wal-segsize 32"
-        )
-        self.assertEqual(cmdstr, self.cmd_run_all_mock.call_args[0][0])
-
-    def test_cluster_create_with_float(self):
-        deb_postgres.cluster_create(
-            9.3,
-            "main",
-            port="5432",
-            locale="fr_FR",
-            encoding="UTF-8",
-            datadir="/opt/postgresql",
-        )
-        cmdstr = (
-            "/usr/bin/pg_createcluster "
-            "--port 5432 --locale fr_FR --encoding UTF-8 "
-            "--datadir /opt/postgresql "
-            "9.3 main"
-        )
-        self.assertEqual(cmdstr, self.cmd_run_all_mock.call_args[0][0])
-
-
-class PostgresLsClusterTestCase(TestCase, LoaderModuleMockMixin):
-    def setup_loader_modules(self):
-        self.cmd_run_all_mock = Mock(return_value={"stdout": LSCLUSTER})
-        self.addCleanup(delattr, self, "cmd_run_all_mock")
-        patcher = patch(
-            "salt.utils.path.which", Mock(return_value="/usr/bin/pg_lsclusters")
-        )
-        patcher.start()
-        self.addCleanup(patcher.stop)
-        return {
-            deb_postgres: {
-                "__salt__": {
-                    "config.option": Mock(),
-                    "cmd.run_all": self.cmd_run_all_mock,
-                    "file.chown": Mock(),
-                    "file.remove": Mock(),
-                }
-            }
-        }
-
-    def test_parse_pg_lsclusters(self):
-        stdout = LSCLUSTER
-        self.maxDiff = None
-        self.assertDictEqual(
-            {
-                "8.4/main": {
-                    "port": 5432,
-                    "status": "online",
-                    "user": "postgres",
-                    "datadir": "/srv/8.4/main",
-                    "log": "/var/log/postgresql/postgresql-8.4-main.log",
-                },
-                "9.1/main": {
-                    "port": 5433,
-                    "status": "online",
-                    "user": "postgres",
-                    "datadir": "/srv/9.1/main",
-                    "log": "/var/log/postgresql/postgresql-9.1-main.log",
-                },
-            },
-            deb_postgres._parse_pg_lscluster(stdout),
-        )
-
-    def test_cluster_list(self):
-        return_list = deb_postgres.cluster_list()
-        self.assertEqual(
-            "/usr/bin/pg_lsclusters --no-header", self.cmd_run_all_mock.call_args[0][0]
-        )
-        return_dict = deb_postgres.cluster_list(verbose=True)
-        self.assertIsInstance(return_dict, dict)
-
-    def test_cluster_exists(self):
-        self.assertTrue(deb_postgres.cluster_exists("8.4") is True)
-        self.assertTrue(deb_postgres.cluster_exists("8.4", "main") is True)
-        self.assertFalse(deb_postgres.cluster_exists("3.4", "main"))
-
-
-class PostgresDeleteClusterTestCase(TestCase, LoaderModuleMockMixin):
-    def setup_loader_modules(self):
-        self.cmd_run_all_mock = Mock(return_value={"stdout": LSCLUSTER})
-        self.addCleanup(delattr, self, "cmd_run_all_mock")
-        patcher = patch(
-            "salt.utils.path.which", Mock(return_value="/usr/bin/pg_dropcluster")
-        )
-        patcher.start()
-        self.addCleanup(patcher.stop)
-        return {
-            deb_postgres: {
-                "__salt__": {
-                    "config.option": Mock(),
-                    "cmd.run_all": self.cmd_run_all_mock,
-                    "file.chown": Mock(),
-                    "file.remove": Mock(),
-                }
-            }
-        }
-
-    def test_cluster_delete(self):
-        deb_postgres.cluster_remove("9.3", "main")
-        self.assertEqual(
-            "/usr/bin/pg_dropcluster 9.3 main", self.cmd_run_all_mock.call_args[0][0]
-        )
-        deb_postgres.cluster_remove("9.3", "main", stop=True)
-        self.assertEqual(
-            "/usr/bin/pg_dropcluster --stop 9.3 main",
-            self.cmd_run_all_mock.call_args[0][0],
-        )
-        deb_postgres.cluster_remove(9.3, "main", stop=True)
-        self.assertEqual(
-            "/usr/bin/pg_dropcluster --stop 9.3 main",
-            self.cmd_run_all_mock.call_args[0][0],
-        )
diff --git a/tests/unit/modules/test_postgres.py b/tests/unit/modules/test_postgres.py
deleted file mode 100644
index 6f77fc0390..0000000000
--- a/tests/unit/modules/test_postgres.py
+++ /dev/null
@@ -1,2086 +0,0 @@
-import datetime
-import logging
-import re
-
-import salt.modules.postgres as postgres
-from salt.exceptions import SaltInvocationError
-from tests.support.mixins import LoaderModuleMockMixin
-from tests.support.mock import Mock, call, patch
-from tests.support.unit import TestCase
-
-test_list_db_csv = (
-    "Name,Owner,Encoding,Collate,Ctype,Access privileges,Tablespace\n"
-    "template1,postgres,LATIN1,en_US,en_US"
-    ',"{=c/postgres,postgres=CTc/postgres}",pg_default\n'
-    "template0,postgres,LATIN1,en_US,en_US"
-    ',"{=c/postgres,postgres=CTc/postgres}",pg_default\n'
-    "postgres,postgres,LATIN1,en_US,en_US,,pg_default\n"
-    "test_db,postgres,LATIN1,en_US,en_US,,pg_default"
-)
-
-test_list_schema_csv = (
-    "name,owner,acl\n"
-    'public,postgres,"{postgres=UC/postgres,=UC/postgres}"\n'
-    'pg_toast,postgres,""'
-)
-
-test_list_language_csv = "Name\ninternal\nc\nsql\nplpgsql\n"
-
-test_privileges_list_table_csv = (
-    "name\n"
-    '"{baruwatest=arwdDxt/baruwatest,bayestest=arwd/baruwatest,baruwa=a*r*w*d*D*x*t*/baruwatest}"\n'
-)
-
-test_privileges_list_group_csv = (
-    "rolname,admin_option\nbaruwa,f\nbaruwatest2,t\nbaruwatest,f\n"
-)
-
-log = logging.getLogger(__name__)
-
-
-class PostgresTestCase(TestCase, LoaderModuleMockMixin):
-    def setup_loader_modules(self):
-        patcher = patch("salt.utils.path.which", Mock(return_value="/usr/bin/pgsql"))
-        patcher.start()
-        self.addCleanup(patcher.stop)
-        return {
-            postgres: {
-                "__grains__": {"os_family": "Linux"},
-                "__salt__": {
-                    "config.option": Mock(),
-                    "cmd.run_all": Mock(),
-                    "file.chown": Mock(),
-                    "file.remove": Mock(),
-                },
-            }
-        }
-
-    def test_run_psql(self):
-        postgres._run_psql('echo "hi"')
-        cmd = postgres.__salt__["cmd.run_all"]
-
-        self.assertEqual("postgres", cmd.call_args[1]["runas"])
-
-    def test_db_alter(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            postgres.db_alter(
-                "dbname",
-                user="testuser",
-                host="testhost",
-                port="testport",
-                maintenance_db="maint_db",
-                password="foo",
-                tablespace="testspace",
-                owner="otheruser",
-                runas="foo",
-            )
-            postgres._run_psql.assert_has_calls(
-                [
-                    call(
-                        [
-                            "/usr/bin/pgsql",
-                            "--no-align",
-                            "--no-readline",
-                            "--no-psqlrc",
-                            "--no-password",
-                            "--username",
-                            "testuser",
-                            "--host",
-                            "testhost",
-                            "--port",
-                            "testport",
-                            "--dbname",
-                            "maint_db",
-                            "-c",
-                            'ALTER DATABASE "dbname" OWNER TO "otheruser"',
-                        ],
-                        host="testhost",
-                        user="testuser",
-                        password="foo",
-                        runas="foo",
-                        port="testport",
-                    ),
-                    call(
-                        [
-                            "/usr/bin/pgsql",
-                            "--no-align",
-                            "--no-readline",
-                            "--no-psqlrc",
-                            "--no-password",
-                            "--username",
-                            "testuser",
-                            "--host",
-                            "testhost",
-                            "--port",
-                            "testport",
-                            "--dbname",
-                            "maint_db",
-                            "-c",
-                            'ALTER DATABASE "dbname" SET TABLESPACE "testspace"',
-                        ],
-                        host="testhost",
-                        user="testuser",
-                        password="foo",
-                        runas="foo",
-                        port="testport",
-                    ),
-                ]
-            )
-
-    def test_db_alter_owner_recurse(self):
-        with patch(
-            "salt.modules.postgres.owner_to", Mock(return_value={"retcode": None})
-        ):
-            postgres.db_alter(
-                "dbname",
-                user="testuser",
-                host="testhost",
-                port="testport",
-                maintenance_db="maint_db",
-                password="foo",
-                tablespace="testspace",
-                owner="otheruser",
-                owner_recurse=True,
-                runas="foo",
-            )
-            postgres.owner_to.assert_called_once_with(
-                "dbname",
-                "otheruser",
-                user="testuser",
-                host="testhost",
-                port="testport",
-                password="foo",
-                runas="foo",
-            )
-
-    def test_db_create(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            postgres.db_create(
-                "dbname",
-                user="testuser",
-                host="testhost",
-                port="testport",
-                maintenance_db="maint_db",
-                password="foo",
-                tablespace="testspace",
-                owner="otheruser",
-                runas="foo",
-            )
-
-            postgres._run_psql.assert_called_once_with(
-                [
-                    "/usr/bin/pgsql",
-                    "--no-align",
-                    "--no-readline",
-                    "--no-psqlrc",
-                    "--no-password",
-                    "--username",
-                    "testuser",
-                    "--host",
-                    "testhost",
-                    "--port",
-                    "testport",
-                    "--dbname",
-                    "maint_db",
-                    "-c",
-                    'CREATE DATABASE "dbname" WITH TABLESPACE = "testspace" '
-                    'OWNER = "otheruser"',
-                ],
-                host="testhost",
-                user="testuser",
-                password="foo",
-                runas="foo",
-                port="testport",
-            )
-
-    def test_db_create_empty_string_param(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            postgres.db_create(
-                "dbname",
-                lc_collate="",
-                encoding="utf8",
-                user="testuser",
-                host="testhost",
-                port=1234,
-                maintenance_db="maint_db",
-                password="foo",
-            )
-
-            postgres._run_psql.assert_called_once_with(
-                [
-                    "/usr/bin/pgsql",
-                    "--no-align",
-                    "--no-readline",
-                    "--no-psqlrc",
-                    "--no-password",
-                    "--username",
-                    "testuser",
-                    "--host",
-                    "testhost",
-                    "--port",
-                    "1234",
-                    "--dbname",
-                    "maint_db",
-                    "-c",
-                    "CREATE DATABASE \"dbname\" WITH ENCODING = 'utf8' LC_COLLATE = ''",
-                ],
-                host="testhost",
-                password="foo",
-                port=1234,
-                runas=None,
-                user="testuser",
-            )
-
-    def test_db_create_with_trivial_sql_injection(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            self.assertRaises(
-                SaltInvocationError,
-                postgres.db_create,
-                "dbname",
-                lc_collate="foo' ENCODING='utf8",
-            )
-
-    def test_db_exists(self):
-        with patch(
-            "salt.modules.postgres._run_psql",
-            Mock(return_value={"retcode": 0, "stdout": test_list_db_csv}),
-        ):
-            ret = postgres.db_exists(
-                "test_db",
-                user="testuser",
-                host="testhost",
-                port="testport",
-                maintenance_db="maint_db",
-                password="foo",
-                runas="foo",
-            )
-            self.assertTrue(ret)
-
-    def test_db_list(self):
-        with patch(
-            "salt.modules.postgres._run_psql",
-            Mock(return_value={"retcode": 0, "stdout": test_list_db_csv}),
-        ):
-            ret = postgres.db_list(
-                user="testuser",
-                host="testhost",
-                port="testport",
-                maintenance_db="maint_db",
-                password="foo",
-                runas="foo",
-            )
-            self.assertDictEqual(
-                ret,
-                {
-                    "test_db": {
-                        "Encoding": "LATIN1",
-                        "Ctype": "en_US",
-                        "Tablespace": "pg_default",
-                        "Collate": "en_US",
-                        "Owner": "postgres",
-                        "Access privileges": "",
-                    },
-                    "template1": {
-                        "Encoding": "LATIN1",
-                        "Ctype": "en_US",
-                        "Tablespace": "pg_default",
-                        "Collate": "en_US",
-                        "Owner": "postgres",
-                        "Access privileges": "{=c/postgres,postgres=CTc/postgres}",
-                    },
-                    "template0": {
-                        "Encoding": "LATIN1",
-                        "Ctype": "en_US",
-                        "Tablespace": "pg_default",
-                        "Collate": "en_US",
-                        "Owner": "postgres",
-                        "Access privileges": "{=c/postgres,postgres=CTc/postgres}",
-                    },
-                    "postgres": {
-                        "Encoding": "LATIN1",
-                        "Ctype": "en_US",
-                        "Tablespace": "pg_default",
-                        "Collate": "en_US",
-                        "Owner": "postgres",
-                        "Access privileges": "",
-                    },
-                },
-            )
-
-    def test_db_remove(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            postgres.db_remove(
-                "test_db",
-                user="testuser",
-                host="testhost",
-                port="testport",
-                maintenance_db="maint_db",
-                password="foo",
-                runas="foo",
-            )
-
-            calls = (
-                call(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "maint_db",
-                        "-c",
-                        'REVOKE CONNECT ON DATABASE "test_db" FROM public;',
-                    ],
-                    host="testhost",
-                    password="foo",
-                    port="testport",
-                    runas="foo",
-                    user="testuser",
-                ),
-                call(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "maint_db",
-                        "-c",
-                        "SELECT pid, pg_terminate_backend(pid) FROM pg_stat_activity"
-                        " WHERE datname = 'test_db' AND pid <> pg_backend_pid();",
-                    ],
-                    host="testhost",
-                    password="foo",
-                    port="testport",
-                    runas="foo",
-                    user="testuser",
-                ),
-                call(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "maint_db",
-                        "-c",
-                        'DROP DATABASE "test_db";',
-                    ],
-                    host="testhost",
-                    password="foo",
-                    port="testport",
-                    runas="foo",
-                    user="testuser",
-                ),
-            )
-
-            postgres._run_psql.assert_has_calls(calls, any_order=True)
-
-    def test_group_create(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch("salt.modules.postgres.user_exists", Mock(return_value=False)):
-                postgres.group_create(
-                    "testgroup",
-                    user="testuser",
-                    host="testhost",
-                    port="testport",
-                    maintenance_db="maint_db",
-                    password="foo",
-                    createdb=False,
-                    encrypted=False,
-                    superuser=False,
-                    replication=False,
-                    rolepassword="testrolepass",
-                    groups="testgroup",
-                    runas="foo",
-                )
-                # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
-                # The first 14 elements of this list are initial args used in all (or
-                # virtually all) commands run through _run_psql(), so the actual SQL
-                # query will be in the 15th argument.
-                self.assertTrue(
-                    postgres._run_psql.call_args[0][0][14].startswith("CREATE ROLE")
-                )
-
-    def test_group_remove(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch("salt.modules.postgres.user_exists", Mock(return_value=True)):
-                postgres.group_remove(
-                    "testgroup",
-                    user="testuser",
-                    host="testhost",
-                    port="testport",
-                    maintenance_db="maint_db",
-                    password="foo",
-                    runas="foo",
-                )
-                postgres._run_psql.assert_called_once_with(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "maint_db",
-                        "-c",
-                        'DROP ROLE "testgroup"',
-                    ],
-                    host="testhost",
-                    user="testuser",
-                    password="foo",
-                    runas="foo",
-                    port="testport",
-                )
-
-    def test_group_update(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.role_get",
-                Mock(return_value={"superuser": False}),
-            ):
-                postgres.group_update(
-                    "testgroup",
-                    user='"testuser"',
-                    host="testhost",
-                    port="testport",
-                    maintenance_db="maint_db",
-                    password="foo",
-                    createdb=False,
-                    encrypted=False,
-                    replication=False,
-                    rolepassword="test_role_pass",
-                    groups="testgroup",
-                    runas="foo",
-                )
-                # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
-                # The first 14 elements of this list are initial args used in all (or
-                # virtually all) commands run through _run_psql(), so the actual SQL
-                # query will be in the 15th argument.
-                self.assertTrue(
-                    re.match(
-                        'ALTER.* "testgroup" .* UNENCRYPTED PASSWORD',
-                        postgres._run_psql.call_args[0][0][14],
-                    )
-                )
-
-    def test_user_create(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch("salt.modules.postgres.user_exists", Mock(return_value=False)):
-                postgres.user_create(
-                    "testuser",
-                    user="testuser",
-                    host="testhost",
-                    port="testport",
-                    maintenance_db="maint_test",
-                    password="test_pass",
-                    login=True,
-                    createdb=False,
-                    createroles=False,
-                    encrypted=False,
-                    superuser=False,
-                    replication=False,
-                    rolepassword="test_role_pass",
-                    valid_until="2042-07-01",
-                    groups="test_groups",
-                    runas="foo",
-                )
-                # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
-                # The first 14 elements of this list are initial args used in all (or
-                # virtually all) commands run through _run_psql(), so the actual SQL
-                # query will be in the 15th argument.
-                call = postgres._run_psql.call_args[0][0][14]
-                self.assertTrue(re.match('CREATE ROLE "testuser"', call))
-                for i in (
-                    "INHERIT",
-                    "NOCREATEDB",
-                    "NOCREATEROLE",
-                    "NOSUPERUSER",
-                    "NOREPLICATION",
-                    "LOGIN",
-                    "UNENCRYPTED",
-                    "PASSWORD",
-                    "VALID UNTIL",
-                ):
-                    self.assertTrue(i in call, "{} not in {}".format(i, call))
-
-    def test_user_exists(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch("salt.modules.postgres.version", Mock(return_value="9.1")):
-                with patch(
-                    "salt.modules.postgres.psql_query",
-                    Mock(
-                        return_value=[
-                            {
-                                "name": "test_user",
-                                "superuser": "t",
-                                "inherits privileges": "t",
-                                "can create roles": "t",
-                                "can create databases": "t",
-                                "can update system catalogs": "t",
-                                "can login": "t",
-                                "replication": None,
-                                "password": "test_password",
-                                "connections": "-1",
-                                "groups": "",
-                                "expiry time": "",
-                                "defaults variables": None,
-                            }
-                        ]
-                    ),
-                ):
-                    ret = postgres.user_exists(
-                        "test_user",
-                        user="test_user",
-                        host="test_host",
-                        port="test_port",
-                        maintenance_db="maint_db",
-                        password="test_password",
-                        runas="foo",
-                    )
-                    self.assertTrue(ret)
-
-    def test_user_list(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch("salt.modules.postgres.version", Mock(return_value="9.1")):
-                with patch(
-                    "salt.modules.postgres.psql_query",
-                    Mock(
-                        return_value=[
-                            {
-                                "name": "test_user",
-                                "superuser": "t",
-                                "inherits privileges": "t",
-                                "can create roles": "t",
-                                "can create databases": "t",
-                                "can update system catalogs": "t",
-                                "can login": "t",
-                                "replication": None,
-                                "connections": "-1",
-                                "groups": "",
-                                "expiry time": "2017-08-16 08:57:46",
-                                "defaults variables": None,
-                            }
-                        ]
-                    ),
-                ):
-                    ret = postgres.user_list(
-                        "test_user",
-                        host="test_host",
-                        port="test_port",
-                        maintenance_db="maint_db",
-                        password="test_password",
-                        runas="foo",
-                    )
-
-                    self.assertDictEqual(
-                        ret,
-                        {
-                            "test_user": {
-                                "superuser": True,
-                                "defaults variables": None,
-                                "can create databases": True,
-                                "can create roles": True,
-                                "connections": None,
-                                "replication": None,
-                                "expiry time": datetime.datetime(
-                                    2017, 8, 16, 8, 57, 46
-                                ),
-                                "can login": True,
-                                "can update system catalogs": True,
-                                "groups": [],
-                                "inherits privileges": True,
-                            }
-                        },
-                    )
-
-    def test_user_remove(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch("salt.modules.postgres.version", Mock(return_value="9.1")):
-                with patch(
-                    "salt.modules.postgres.user_exists", Mock(return_value=True)
-                ):
-                    postgres.user_remove(
-                        "testuser",
-                        user="testuser",
-                        host="testhost",
-                        port="testport",
-                        maintenance_db="maint_db",
-                        password="testpassword",
-                        runas="foo",
-                    )
-                    postgres._run_psql.assert_called_once_with(
-                        [
-                            "/usr/bin/pgsql",
-                            "--no-align",
-                            "--no-readline",
-                            "--no-psqlrc",
-                            "--no-password",
-                            "--username",
-                            "testuser",
-                            "--host",
-                            "testhost",
-                            "--port",
-                            "testport",
-                            "--dbname",
-                            "maint_db",
-                            "-c",
-                            'DROP ROLE "testuser"',
-                        ],
-                        host="testhost",
-                        port="testport",
-                        user="testuser",
-                        password="testpassword",
-                        runas="foo",
-                    )
-
-    def test_user_update(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.role_get",
-                Mock(return_value={"superuser": False}),
-            ):
-                postgres.user_update(
-                    "test_username",
-                    user="test_user",
-                    host="test_host",
-                    port="test_port",
-                    maintenance_db="test_maint",
-                    password="test_pass",
-                    createdb=False,
-                    createroles=False,
-                    encrypted=False,
-                    inherit=True,
-                    login=True,
-                    replication=False,
-                    rolepassword="test_role_pass",
-                    valid_until="2017-07-01",
-                    groups="test_groups",
-                    runas="foo",
-                )
-                # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
-                # The first 14 elements of this list are initial args used in all (or
-                # virtually all) commands run through _run_psql(), so the actual SQL
-                # query will be in the 15th argument.
-                self.assertTrue(
-                    re.match(
-                        'ALTER ROLE "test_username" WITH  INHERIT NOCREATEDB '
-                        "NOCREATEROLE NOREPLICATION LOGIN "
-                        "UNENCRYPTED PASSWORD ['\"]{0,5}test_role_pass['\"]{0,5} "
-                        "VALID UNTIL '2017-07-01';"
-                        ' GRANT "test_groups" TO "test_username"',
-                        postgres._run_psql.call_args[0][0][14],
-                    )
-                )
-
-    def test_user_update2(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.role_get",
-                Mock(return_value={"superuser": False}),
-            ):
-                postgres.user_update(
-                    "test_username",
-                    user="test_user",
-                    host="test_host",
-                    port="test_port",
-                    maintenance_db="test_maint",
-                    password="test_pass",
-                    createdb=False,
-                    createroles=True,
-                    encrypted=False,
-                    inherit=True,
-                    login=True,
-                    replication=False,
-                    groups="test_groups",
-                    runas="foo",
-                )
-                # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
-                # The first 14 elements of this list are initial args used in all (or
-                # virtually all) commands run through _run_psql(), so the actual SQL
-                # query will be in the 15th argument.
-                self.assertTrue(
-                    re.match(
-                        'ALTER ROLE "test_username" WITH  INHERIT NOCREATEDB '
-                        "CREATEROLE NOREPLICATION LOGIN;"
-                        ' GRANT "test_groups" TO "test_username"',
-                        postgres._run_psql.call_args[0][0][14],
-                    )
-                )
-
-    def test_user_update3(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.role_get",
-                Mock(return_value={"superuser": False}),
-            ):
-                postgres.user_update(
-                    "test_username",
-                    user="test_user",
-                    host="test_host",
-                    port="test_port",
-                    maintenance_db="test_maint",
-                    password="test_pass",
-                    createdb=False,
-                    createroles=True,
-                    encrypted=False,
-                    inherit=True,
-                    login=True,
-                    rolepassword=False,
-                    replication=False,
-                    groups="test_groups",
-                    runas="foo",
-                )
-                # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
-                # The first 14 elements of this list are initial args used in all (or
-                # virtually all) commands run through _run_psql(), so the actual SQL
-                # query will be in the 15th argument.
-                self.assertTrue(
-                    re.match(
-                        'ALTER ROLE "test_username" WITH  INHERIT NOCREATEDB '
-                        "CREATEROLE NOREPLICATION LOGIN NOPASSWORD;"
-                        ' GRANT "test_groups" TO "test_username"',
-                        postgres._run_psql.call_args[0][0][14],
-                    )
-                )
-
-    def test_user_update_encrypted_passwd(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.role_get",
-                Mock(return_value={"superuser": False}),
-            ):
-                postgres.user_update(
-                    "test_username",
-                    user="test_user",
-                    host="test_host",
-                    port="test_port",
-                    maintenance_db="test_maint",
-                    password="test_pass",
-                    createdb=False,
-                    createroles=True,
-                    encrypted=True,
-                    inherit=True,
-                    login=True,
-                    rolepassword="foobar",
-                    replication=False,
-                    groups="test_groups",
-                    runas="foo",
-                )
-                # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
-                # The first 14 elements of this list are initial args used in all (or
-                # virtually all) commands run through _run_psql(), so the actual SQL
-                # query will be in the 15th argument.
-                self.assertTrue(
-                    re.match(
-                        'ALTER ROLE "test_username" WITH  INHERIT NOCREATEDB '
-                        "CREATEROLE NOREPLICATION LOGIN "
-                        "ENCRYPTED PASSWORD "
-                        "['\"]{0,5}md531c27e68d3771c392b52102c01be1da1['\"]{0,5}"
-                        '; GRANT "test_groups" TO "test_username"',
-                        postgres._run_psql.call_args[0][0][14],
-                    )
-                )
-
-    def test_version(self):
-        with patch(
-            "salt.modules.postgres._run_psql",
-            Mock(return_value={"retcode": 0, "stdout": "9.1.9"}),
-        ):
-            postgres.version(
-                user="test_user",
-                host="test_host",
-                port="test_port",
-                maintenance_db="test_maint",
-                password="test_pass",
-                runas="foo",
-            )
-            # postgres._run_psql.call_args[0][0] will contain the list of CLI args.
-            # The first 14 elements of this list are initial args used in all (or
-            # virtually all) commands run through _run_psql(), so the actual SQL
-            # query will be in the 15th argument.
-            self.assertTrue(
-                re.match(
-                    "SELECT setting FROM pg_catalog.pg_settings",
-                    postgres._run_psql.call_args[0][0][14],
-                )
-            )
-
-    def test_installed_extensions(self):
-        with patch(
-            "salt.modules.postgres.psql_query",
-            Mock(return_value=[{"extname": "foo", "extversion": "1"}]),
-        ):
-            exts = postgres.installed_extensions()
-            self.assertEqual(exts, {"foo": {"extversion": "1", "extname": "foo"}})
-
-    def test_available_extensions(self):
-        with patch(
-            "salt.modules.postgres.psql_query",
-            Mock(return_value=[{"name": "foo", "default_version": "1"}]),
-        ):
-            exts = postgres.available_extensions()
-            self.assertEqual(exts, {"foo": {"default_version": "1", "name": "foo"}})
-
-    def test_drop_extension2(self):
-        with patch(
-            "salt.modules.postgres.installed_extensions", Mock(side_effect=[{}, {}])
-        ):
-            with patch(
-                "salt.modules.postgres._psql_prepare_and_run", Mock(return_value=None)
-            ):
-                with patch(
-                    "salt.modules.postgres.available_extensions",
-                    Mock(return_value={"foo": {"default_version": "1", "name": "foo"}}),
-                ):
-                    self.assertEqual(postgres.drop_extension("foo"), True)
-
-    def test_drop_extension3(self):
-        with patch(
-            "salt.modules.postgres.installed_extensions",
-            Mock(side_effect=[{"foo": {"extversion": "1", "extname": "foo"}}, {}]),
-        ):
-            with patch(
-                "salt.modules.postgres._psql_prepare_and_run", Mock(return_value=None)
-            ):
-                with patch(
-                    "salt.modules.postgres.available_extensions",
-                    Mock(return_value={"foo": {"default_version": "1", "name": "foo"}}),
-                ):
-                    self.assertEqual(postgres.drop_extension("foo"), True)
-
-    def test_drop_extension1(self):
-        with patch(
-            "salt.modules.postgres.installed_extensions",
-            Mock(
-                side_effect=[
-                    {"foo": {"extversion": "1", "extname": "foo"}},
-                    {"foo": {"extversion": "1", "extname": "foo"}},
-                ]
-            ),
-        ):
-            with patch(
-                "salt.modules.postgres._psql_prepare_and_run", Mock(return_value=None)
-            ):
-                with patch(
-                    "salt.modules.postgres.available_extensions",
-                    Mock(return_value={"foo": {"default_version": "1", "name": "foo"}}),
-                ):
-                    self.assertEqual(postgres.drop_extension("foo"), False)
-
-    def test_create_mtdata(self):
-        with patch(
-            "salt.modules.postgres.installed_extensions",
-            Mock(
-                return_value={
-                    "foo": {
-                        "extversion": "0.8",
-                        "extrelocatable": "t",
-                        "schema_name": "foo",
-                        "extname": "foo",
-                    }
-                },
-            ),
-        ):
-            with patch(
-                "salt.modules.postgres.available_extensions",
-                Mock(return_value={"foo": {"default_version": "1.4", "name": "foo"}}),
-            ):
-                ret = postgres.create_metadata("foo", schema="bar", ext_version="1.4")
-                self.assertTrue(postgres._EXTENSION_INSTALLED in ret)
-                self.assertTrue(postgres._EXTENSION_TO_UPGRADE in ret)
-                self.assertTrue(postgres._EXTENSION_TO_MOVE in ret)
-                ret = postgres.create_metadata("foo", schema="foo", ext_version="0.4")
-                self.assertTrue(postgres._EXTENSION_INSTALLED in ret)
-                self.assertFalse(postgres._EXTENSION_TO_UPGRADE in ret)
-                self.assertFalse(postgres._EXTENSION_TO_MOVE in ret)
-                ret = postgres.create_metadata("foo")
-                self.assertTrue(postgres._EXTENSION_INSTALLED in ret)
-                self.assertFalse(postgres._EXTENSION_TO_UPGRADE in ret)
-                self.assertFalse(postgres._EXTENSION_TO_MOVE in ret)
-                ret = postgres.create_metadata("foobar")
-                self.assertTrue(postgres._EXTENSION_NOT_INSTALLED in ret)
-                self.assertFalse(postgres._EXTENSION_INSTALLED in ret)
-                self.assertFalse(postgres._EXTENSION_TO_UPGRADE in ret)
-                self.assertFalse(postgres._EXTENSION_TO_MOVE in ret)
-
-    def test_create_extension_newerthan(self):
-        """
-        scenario of creating upgrading extensions with possible schema and
-        version specifications
-        """
-        with patch(
-            "salt.modules.postgres.create_metadata",
-            Mock(
-                side_effect=[
-                    # create succeeded
-                    [postgres._EXTENSION_NOT_INSTALLED],
-                    [postgres._EXTENSION_INSTALLED],
-                    [postgres._EXTENSION_NOT_INSTALLED],
-                    [postgres._EXTENSION_INSTALLED],
-                    # create failed
-                    [postgres._EXTENSION_NOT_INSTALLED],
-                    [postgres._EXTENSION_NOT_INSTALLED],
-                    # move+upgrade succeeded
-                    [
-                        postgres._EXTENSION_TO_MOVE,
-                        postgres._EXTENSION_TO_UPGRADE,
-                        postgres._EXTENSION_INSTALLED,
-                    ],
-                    [postgres._EXTENSION_INSTALLED],
-                    # move succeeded
-                    [postgres._EXTENSION_TO_MOVE, postgres._EXTENSION_INSTALLED],
-                    [postgres._EXTENSION_INSTALLED],
-                    # upgrade succeeded
-                    [postgres._EXTENSION_TO_UPGRADE, postgres._EXTENSION_INSTALLED],
-                    [postgres._EXTENSION_INSTALLED],
-                    # upgrade failed
-                    [postgres._EXTENSION_TO_UPGRADE, postgres._EXTENSION_INSTALLED],
-                    [postgres._EXTENSION_TO_UPGRADE, postgres._EXTENSION_INSTALLED],
-                    # move failed
-                    [postgres._EXTENSION_TO_MOVE, postgres._EXTENSION_INSTALLED],
-                    [postgres._EXTENSION_TO_MOVE, postgres._EXTENSION_INSTALLED],
-                ]
-            ),
-        ):
-            with patch(
-                "salt.modules.postgres._psql_prepare_and_run", Mock(return_value=None)
-            ):
-                with patch(
-                    "salt.modules.postgres.available_extensions",
-                    Mock(
-                        return_value={"foo": {"default_version": "1.4", "name": "foo"}}
-                    ),
-                ):
-                    self.assertTrue(postgres.create_extension("foo"))
-                    self.assertTrue(
-                        re.match(
-                            'CREATE EXTENSION IF NOT EXISTS "foo" ;',
-                            postgres._psql_prepare_and_run.call_args[0][0][1],
-                        )
-                    )
-                    self.assertTrue(
-                        postgres.create_extension(
-                            "foo", schema="a", ext_version="b", from_version="c"
-                        )
-                    )
-                    self.assertTrue(
-                        re.match(
-                            'CREATE EXTENSION IF NOT EXISTS "foo" '
-                            'WITH SCHEMA "a" VERSION b FROM c ;',
-                            postgres._psql_prepare_and_run.call_args[0][0][1],
-                        )
-                    )
-                    self.assertFalse(postgres.create_extension("foo"))
-                    ret = postgres.create_extension("foo", ext_version="a", schema="b")
-                    self.assertTrue(ret)
-                    self.assertTrue(
-                        re.match(
-                            'ALTER EXTENSION "foo" SET SCHEMA "b";'
-                            ' ALTER EXTENSION "foo" UPDATE TO a;',
-                            postgres._psql_prepare_and_run.call_args[0][0][1],
-                        )
-                    )
-                    ret = postgres.create_extension("foo", ext_version="a", schema="b")
-                    self.assertTrue(ret)
-                    self.assertTrue(
-                        re.match(
-                            'ALTER EXTENSION "foo" SET SCHEMA "b";',
-                            postgres._psql_prepare_and_run.call_args[0][0][1],
-                        )
-                    )
-                    ret = postgres.create_extension("foo", ext_version="a", schema="b")
-                    self.assertTrue(ret)
-                    self.assertTrue(
-                        re.match(
-                            'ALTER EXTENSION "foo" UPDATE TO a;',
-                            postgres._psql_prepare_and_run.call_args[0][0][1],
-                        )
-                    )
-                    self.assertFalse(
-                        postgres.create_extension("foo", ext_version="a", schema="b")
-                    )
-                    self.assertFalse(
-                        postgres.create_extension("foo", ext_version="a", schema="b")
-                    )
-
-    def test_encrypt_passwords(self):
-        self.assertEqual(postgres._maybe_encrypt_password("foo", "bar", False), "bar")
-        self.assertEqual(
-            postgres._maybe_encrypt_password("foo", "bar", True),
-            "md596948aad3fcae80c08a35c9b5958cd89",
-        )
-
-    def test_schema_list(self):
-        with patch(
-            "salt.modules.postgres._run_psql",
-            Mock(return_value={"retcode": 0, "stdout": test_list_schema_csv}),
-        ):
-            ret = postgres.schema_list(
-                "maint_db",
-                db_user="testuser",
-                db_host="testhost",
-                db_port="testport",
-                db_password="foo",
-            )
-            self.assertDictEqual(
-                ret,
-                {
-                    "public": {
-                        "acl": "{postgres=UC/postgres,=UC/postgres}",
-                        "owner": "postgres",
-                    },
-                    "pg_toast": {"acl": "", "owner": "postgres"},
-                },
-            )
-
-    def test_schema_exists(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.psql_query",
-                Mock(
-                    return_value=[
-                        {
-                            "name": "public",
-                            "acl": "{postgres=UC/postgres,=UC/postgres}",
-                            "owner": "postgres",
-                        }
-                    ]
-                ),
-            ):
-                ret = postgres.schema_exists("template1", "public")
-                self.assertTrue(ret)
-
-    def test_schema_get(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.psql_query",
-                Mock(
-                    return_value=[
-                        {
-                            "name": "public",
-                            "acl": "{postgres=UC/postgres,=UC/postgres}",
-                            "owner": "postgres",
-                        }
-                    ]
-                ),
-            ):
-                ret = postgres.schema_get("template1", "public")
-                self.assertTrue(ret)
-
-    def test_schema_get_again(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.psql_query",
-                Mock(
-                    return_value=[
-                        {
-                            "name": "public",
-                            "acl": "{postgres=UC/postgres,=UC/postgres}",
-                            "owner": "postgres",
-                        }
-                    ]
-                ),
-            ):
-                ret = postgres.schema_get("template1", "pg_toast")
-                self.assertFalse(ret)
-
-    def test_schema_create(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch("salt.modules.postgres.schema_exists", Mock(return_value=False)):
-                postgres.schema_create(
-                    "maint_db",
-                    "testschema",
-                    user="user",
-                    db_host="testhost",
-                    db_port="testport",
-                    db_user="testuser",
-                    db_password="testpassword",
-                )
-                postgres._run_psql.assert_called_once_with(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "maint_db",
-                        "-c",
-                        'CREATE SCHEMA "testschema"',
-                    ],
-                    host="testhost",
-                    port="testport",
-                    password="testpassword",
-                    user="testuser",
-                    runas="user",
-                )
-
-    def test_schema_create2(self):
-        with patch("salt.modules.postgres.schema_exists", Mock(return_value=True)):
-            ret = postgres.schema_create(
-                "test_db",
-                "test_schema",
-                user="user",
-                db_host="test_host",
-                db_port="test_port",
-                db_user="test_user",
-                db_password="test_password",
-            )
-            self.assertFalse(ret)
-
-    def test_schema_remove(self):
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch("salt.modules.postgres.schema_exists", Mock(return_value=True)):
-                postgres.schema_remove(
-                    "maint_db",
-                    "testschema",
-                    user="user",
-                    db_host="testhost",
-                    db_port="testport",
-                    db_user="testuser",
-                    db_password="testpassword",
-                )
-                postgres._run_psql.assert_called_once_with(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "maint_db",
-                        "-c",
-                        'DROP SCHEMA "testschema"',
-                    ],
-                    host="testhost",
-                    port="testport",
-                    password="testpassword",
-                    user="testuser",
-                    runas="user",
-                )
-
-    def test_schema_remove2(self):
-        with patch("salt.modules.postgres.schema_exists", Mock(return_value=False)):
-            ret = postgres.schema_remove(
-                "test_db",
-                "test_schema",
-                user="user",
-                db_host="test_host",
-                db_port="test_port",
-                db_user="test_user",
-                db_password="test_password",
-            )
-            self.assertFalse(ret)
-
-    def test_language_list(self):
-        """
-        Test language listing
-        """
-        with patch(
-            "salt.modules.postgres._run_psql",
-            Mock(return_value={"retcode": 0, "stdout": test_list_language_csv}),
-        ):
-            ret = postgres.language_list(
-                "testdb",
-                user="testuser",
-                host="testhost",
-                port="testport",
-                password="foo",
-            )
-            self.assertDictEqual(
-                ret,
-                {"c": "c", "internal": "internal", "plpgsql": "plpgsql", "sql": "sql"},
-            )
-
-    def test_language_exists(self):
-        """
-        Test language existence check
-        """
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.psql_query",
-                Mock(
-                    return_value=[
-                        {"Name": "internal"},
-                        {"Name": "c"},
-                        {"Name": "sql"},
-                        {"Name": "plpgsql"},
-                    ]
-                ),
-            ):
-                with patch(
-                    "salt.modules.postgres.language_exists", Mock(return_value=True)
-                ):
-                    ret = postgres.language_exists("sql", "testdb")
-                    self.assertTrue(ret)
-
-    def test_language_create(self):
-        """
-        Test language creation - does not exist in db
-        """
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.language_exists", Mock(return_value=False)
-            ):
-                postgres.language_create(
-                    "plpythonu",
-                    "testdb",
-                    runas="user",
-                    host="testhost",
-                    port="testport",
-                    user="testuser",
-                    password="testpassword",
-                )
-                postgres._run_psql.assert_called_once_with(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "testdb",
-                        "-c",
-                        "CREATE LANGUAGE plpythonu",
-                    ],
-                    host="testhost",
-                    port="testport",
-                    password="testpassword",
-                    user="testuser",
-                    runas="user",
-                )
-
-    def test_language_create_exists(self):
-        """
-        Test language creation - already exists in db
-        """
-        with patch("salt.modules.postgres.language_exists", Mock(return_value=True)):
-            ret = postgres.language_create(
-                "plpythonu",
-                "testdb",
-                runas="user",
-                host="testhost",
-                port="testport",
-                user="testuser",
-                password="testpassword",
-            )
-            self.assertFalse(ret)
-
-    def test_language_remove(self):
-        """
-        Test language removal - exists in db
-        """
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.language_exists", Mock(return_value=True)
-            ):
-                postgres.language_remove(
-                    "plpgsql",
-                    "testdb",
-                    runas="user",
-                    host="testhost",
-                    port="testport",
-                    user="testuser",
-                    password="testpassword",
-                )
-                postgres._run_psql.assert_called_once_with(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "testdb",
-                        "-c",
-                        "DROP LANGUAGE plpgsql",
-                    ],
-                    host="testhost",
-                    port="testport",
-                    password="testpassword",
-                    user="testuser",
-                    runas="user",
-                )
-
-    def test_language_remove_non_exist(self):
-        """
-        Test language removal - does not exist in db
-        """
-        with patch("salt.modules.postgres.language_exists", Mock(return_value=False)):
-            ret = postgres.language_remove(
-                "plpgsql",
-                "testdb",
-                runas="user",
-                host="testhost",
-                port="testport",
-                user="testuser",
-                password="testpassword",
-            )
-            self.assertFalse(ret)
-
-    def test_privileges_list_table(self):
-        """
-        Test privilege listing on a table
-        """
-        with patch(
-            "salt.modules.postgres._run_psql",
-            Mock(return_value={"retcode": 0, "stdout": test_privileges_list_table_csv}),
-        ):
-            ret = postgres.privileges_list(
-                "awl",
-                "table",
-                maintenance_db="db_name",
-                runas="user",
-                host="testhost",
-                port="testport",
-                user="testuser",
-                password="testpassword",
-            )
-            expected = {
-                "bayestest": {
-                    "INSERT": False,
-                    "UPDATE": False,
-                    "SELECT": False,
-                    "DELETE": False,
-                },
-                "baruwa": {
-                    "INSERT": True,
-                    "TRUNCATE": True,
-                    "UPDATE": True,
-                    "TRIGGER": True,
-                    "REFERENCES": True,
-                    "SELECT": True,
-                    "DELETE": True,
-                },
-                "baruwatest": {
-                    "INSERT": False,
-                    "TRUNCATE": False,
-                    "UPDATE": False,
-                    "TRIGGER": False,
-                    "REFERENCES": False,
-                    "SELECT": False,
-                    "DELETE": False,
-                },
-            }
-
-            self.assertDictEqual(ret, expected)
-
-            query = (
-                "COPY (SELECT relacl AS name FROM pg_catalog.pg_class c "
-                "JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace "
-                "WHERE nspname = 'public' AND relname = 'awl' AND relkind in ('r', 'v') "
-                "ORDER BY relname) TO STDOUT WITH CSV HEADER"
-            )
-
-            postgres._run_psql.assert_called_once_with(
-                [
-                    "/usr/bin/pgsql",
-                    "--no-align",
-                    "--no-readline",
-                    "--no-psqlrc",
-                    "--no-password",
-                    "--username",
-                    "testuser",
-                    "--host",
-                    "testhost",
-                    "--port",
-                    "testport",
-                    "--dbname",
-                    "db_name",
-                    "-v",
-                    "datestyle=ISO,MDY",
-                    "-c",
-                    query,
-                ],
-                host="testhost",
-                port="testport",
-                password="testpassword",
-                user="testuser",
-                runas="user",
-            )
-
-    def test_privileges_list_group(self):
-        """
-        Test privilege listing on a group
-        """
-        with patch(
-            "salt.modules.postgres._run_psql",
-            Mock(return_value={"retcode": 0, "stdout": test_privileges_list_group_csv}),
-        ):
-            ret = postgres.privileges_list(
-                "admin",
-                "group",
-                maintenance_db="db_name",
-                runas="user",
-                host="testhost",
-                port="testport",
-                user="testuser",
-                password="testpassword",
-            )
-            expected = {
-                "baruwa": False,
-                "baruwatest": False,
-                "baruwatest2": True,
-            }
-
-            self.assertDictEqual(ret, expected)
-
-            query = (
-                "COPY (SELECT rolname, admin_option "
-                "FROM pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles r "
-                "ON m.member=r.oid WHERE m.roleid IN (SELECT oid FROM "
-                "pg_catalog.pg_roles WHERE rolname='admin') ORDER BY rolname) "
-                "TO STDOUT WITH CSV HEADER"
-            )
-
-            postgres._run_psql.assert_called_once_with(
-                [
-                    "/usr/bin/pgsql",
-                    "--no-align",
-                    "--no-readline",
-                    "--no-psqlrc",
-                    "--no-password",
-                    "--username",
-                    "testuser",
-                    "--host",
-                    "testhost",
-                    "--port",
-                    "testport",
-                    "--dbname",
-                    "db_name",
-                    "-v",
-                    "datestyle=ISO,MDY",
-                    "-c",
-                    query,
-                ],
-                host="testhost",
-                port="testport",
-                password="testpassword",
-                user="testuser",
-                runas="user",
-            )
-
-    def test_has_privileges_on_table(self):
-        """
-        Test privilege checks on table
-        """
-        with patch(
-            "salt.modules.postgres._run_psql",
-            Mock(return_value={"retcode": 0, "stdout": test_privileges_list_table_csv}),
-        ):
-            ret = postgres.has_privileges(
-                "baruwa",
-                "awl",
-                "table",
-                "SELECT,INSERT",
-                grant_option=True,
-                maintenance_db="db_name",
-                runas="user",
-                host="testhost",
-                port="testport",
-                user="testuser",
-                password="testpassword",
-            )
-
-            self.assertTrue(ret)
-
-            ret = postgres.has_privileges(
-                "baruwa",
-                "awl",
-                "table",
-                "ALL",
-                grant_option=True,
-                maintenance_db="db_name",
-                runas="user",
-                host="testhost",
-                port="testport",
-                user="testuser",
-                password="testpassword",
-            )
-
-            self.assertTrue(ret)
-
-            ret = postgres.has_privileges(
-                "baruwa",
-                "awl",
-                "table",
-                "ALL",
-                grant_option=False,
-                maintenance_db="db_name",
-                runas="user",
-                host="testhost",
-                port="testport",
-                user="testuser",
-                password="testpassword",
-            )
-
-            self.assertTrue(ret)
-
-            ret = postgres.has_privileges(
-                "bayestest",
-                "awl",
-                "table",
-                "SELECT,INSERT,TRUNCATE",
-                maintenance_db="db_name",
-                runas="user",
-                host="testhost",
-                port="testport",
-                user="testuser",
-                password="testpassword",
-            )
-
-            self.assertFalse(ret)
-
-            ret = postgres.has_privileges(
-                "bayestest",
-                "awl",
-                "table",
-                "SELECT,INSERT",
-                maintenance_db="db_name",
-                runas="user",
-                host="testhost",
-                port="testport",
-                user="testuser",
-                password="testpassword",
-            )
-
-            self.assertTrue(ret)
-
-    def test_has_privileges_on_group(self):
-        """
-        Test privilege checks on group
-        """
-        with patch(
-            "salt.modules.postgres._run_psql",
-            Mock(return_value={"retcode": 0, "stdout": test_privileges_list_group_csv}),
-        ):
-            ret = postgres.has_privileges(
-                "baruwa",
-                "admin",
-                "group",
-                maintenance_db="db_name",
-                runas="user",
-                host="testhost",
-                port="testport",
-                user="testuser",
-                password="testpassword",
-            )
-
-            self.assertTrue(ret)
-
-            ret = postgres.has_privileges(
-                "baruwa",
-                "admin",
-                "group",
-                grant_option=True,
-                maintenance_db="db_name",
-                runas="user",
-                host="testhost",
-                port="testport",
-                user="testuser",
-                password="testpassword",
-            )
-
-            self.assertFalse(ret)
-
-            ret = postgres.has_privileges(
-                "tony",
-                "admin",
-                "group",
-                maintenance_db="db_name",
-                runas="user",
-                host="testhost",
-                port="testport",
-                user="testuser",
-                password="testpassword",
-            )
-
-            self.assertFalse(ret)
-
-    def test_privileges_grant_table(self):
-        """
-        Test granting privileges on table
-        """
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.has_privileges", Mock(return_value=False)
-            ):
-                ret = postgres.privileges_grant(
-                    "baruwa",
-                    "awl",
-                    "table",
-                    "ALL",
-                    grant_option=True,
-                    maintenance_db="db_name",
-                    runas="user",
-                    host="testhost",
-                    port="testport",
-                    user="testuser",
-                    password="testpassword",
-                )
-
-                query = 'GRANT ALL ON TABLE public."awl" TO "baruwa" WITH GRANT OPTION'
-
-                postgres._run_psql.assert_called_once_with(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "db_name",
-                        "-c",
-                        query,
-                    ],
-                    host="testhost",
-                    port="testport",
-                    password="testpassword",
-                    user="testuser",
-                    runas="user",
-                )
-
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.has_privileges", Mock(return_value=False)
-            ):
-                ret = postgres.privileges_grant(
-                    "baruwa",
-                    "awl",
-                    "table",
-                    "ALL",
-                    maintenance_db="db_name",
-                    runas="user",
-                    host="testhost",
-                    port="testport",
-                    user="testuser",
-                    password="testpassword",
-                )
-
-                query = 'GRANT ALL ON TABLE public."awl" TO "baruwa"'
-
-                postgres._run_psql.assert_called_once_with(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "db_name",
-                        "-c",
-                        query,
-                    ],
-                    host="testhost",
-                    port="testport",
-                    password="testpassword",
-                    user="testuser",
-                    runas="user",
-                )
-
-        # Test grant on all tables
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.has_privileges", Mock(return_value=False)
-            ):
-                ret = postgres.privileges_grant(
-                    "baruwa",
-                    "ALL",
-                    "table",
-                    "SELECT",
-                    maintenance_db="db_name",
-                    runas="user",
-                    host="testhost",
-                    port="testport",
-                    user="testuser",
-                    password="testpassword",
-                )
-
-                query = 'GRANT SELECT ON ALL TABLES IN SCHEMA public TO "baruwa"'
-
-                postgres._run_psql.assert_called_once_with(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "db_name",
-                        "-c",
-                        query,
-                    ],
-                    host="testhost",
-                    port="testport",
-                    password="testpassword",
-                    user="testuser",
-                    runas="user",
-                )
-
-    def test_privileges_grant_group(self):
-        """
-        Test granting privileges on group
-        """
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.has_privileges", Mock(return_value=False)
-            ):
-                ret = postgres.privileges_grant(
-                    "baruwa",
-                    "admins",
-                    "group",
-                    grant_option=True,
-                    maintenance_db="db_name",
-                    runas="user",
-                    host="testhost",
-                    port="testport",
-                    user="testuser",
-                    password="testpassword",
-                )
-
-                query = 'GRANT admins TO "baruwa" WITH ADMIN OPTION'
-
-                postgres._run_psql.assert_called_once_with(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "db_name",
-                        "-c",
-                        query,
-                    ],
-                    host="testhost",
-                    port="testport",
-                    password="testpassword",
-                    user="testuser",
-                    runas="user",
-                )
-
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.has_privileges", Mock(return_value=False)
-            ):
-                ret = postgres.privileges_grant(
-                    "baruwa",
-                    "admins",
-                    "group",
-                    maintenance_db="db_name",
-                    runas="user",
-                    host="testhost",
-                    port="testport",
-                    user="testuser",
-                    password="testpassword",
-                )
-
-                query = 'GRANT admins TO "baruwa"'
-
-                postgres._run_psql.assert_called_once_with(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "db_name",
-                        "-c",
-                        query,
-                    ],
-                    host="testhost",
-                    port="testport",
-                    password="testpassword",
-                    user="testuser",
-                    runas="user",
-                )
-
-    def test_privileges_revoke_table(self):
-        """
-        Test revoking privileges on table
-        """
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch("salt.modules.postgres.has_privileges", Mock(return_value=True)):
-                ret = postgres.privileges_revoke(
-                    "baruwa",
-                    "awl",
-                    "table",
-                    "ALL",
-                    maintenance_db="db_name",
-                    runas="user",
-                    host="testhost",
-                    port="testport",
-                    user="testuser",
-                    password="testpassword",
-                )
-
-                query = "REVOKE ALL ON TABLE public.awl FROM baruwa"
-
-                postgres._run_psql.assert_called_once_with(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "db_name",
-                        "-c",
-                        query,
-                    ],
-                    host="testhost",
-                    port="testport",
-                    password="testpassword",
-                    user="testuser",
-                    runas="user",
-                )
-
-    def test_privileges_revoke_group(self):
-        """
-        Test revoking privileges on group
-        """
-        with patch(
-            "salt.modules.postgres._run_psql", Mock(return_value={"retcode": 0})
-        ):
-            with patch("salt.modules.postgres.has_privileges", Mock(return_value=True)):
-                ret = postgres.privileges_revoke(
-                    "baruwa",
-                    "admins",
-                    "group",
-                    maintenance_db="db_name",
-                    runas="user",
-                    host="testhost",
-                    port="testport",
-                    user="testuser",
-                    password="testpassword",
-                )
-
-                query = "REVOKE admins FROM baruwa"
-
-                postgres._run_psql.assert_called_once_with(
-                    [
-                        "/usr/bin/pgsql",
-                        "--no-align",
-                        "--no-readline",
-                        "--no-psqlrc",
-                        "--no-password",
-                        "--username",
-                        "testuser",
-                        "--host",
-                        "testhost",
-                        "--port",
-                        "testport",
-                        "--dbname",
-                        "db_name",
-                        "-c",
-                        query,
-                    ],
-                    host="testhost",
-                    port="testport",
-                    password="testpassword",
-                    user="testuser",
-                    runas="user",
-                )
-
-    def test_datadir_init(self):
-        """
-        Test Initializing a postgres data directory
-        """
-        with patch(
-            "salt.modules.postgres._run_initdb", Mock(return_value={"retcode": 0})
-        ):
-            with patch(
-                "salt.modules.postgres.datadir_exists", Mock(return_value=False)
-            ):
-                name = "/var/lib/pgsql/data"
-                ret = postgres.datadir_init(
-                    name, user="postgres", password="test", runas="postgres"
-                )
-                postgres._run_initdb.assert_called_once_with(
-                    name,
-                    auth="password",
-                    encoding="UTF8",
-                    locale=None,
-                    password="test",
-                    runas="postgres",
-                    checksums=False,
-                    waldir=None,
-                    user="postgres",
-                )
-                self.assertTrue(ret)
-
-    def test_datadir_exists(self):
-        """
-        Test Checks if postgres data directory has been initialized
-        """
-        with patch("os.path.isfile", Mock(return_value=True)):
-            name = "/var/lib/pgsql/data"
-            ret = postgres.datadir_exists(name)
-            self.assertTrue(ret)
-
-    def test_pg_is_older_ext_ver(self):
-        """
-        Test Checks if postgres extension version string is older
-        """
-        self.assertTrue(postgres._pg_is_older_ext_ver("8.5", "9.5"))
-        self.assertTrue(postgres._pg_is_older_ext_ver("8.5", "8.6"))
-        self.assertTrue(postgres._pg_is_older_ext_ver("8.5.2", "8.5.3"))
-        self.assertFalse(postgres._pg_is_older_ext_ver("9.5", "8.5"))
-        self.assertTrue(postgres._pg_is_older_ext_ver("9.5", "9.6"))
-        self.assertTrue(postgres._pg_is_older_ext_ver("9.5.0", "9.5.1"))
-        self.assertTrue(postgres._pg_is_older_ext_ver("9.5", "9.5.1"))
-        self.assertFalse(postgres._pg_is_older_ext_ver("9.5.1", "9.5"))
-        self.assertFalse(postgres._pg_is_older_ext_ver("9.5b", "9.5a"))
-        self.assertTrue(postgres._pg_is_older_ext_ver("10a", "10b"))
-        self.assertTrue(postgres._pg_is_older_ext_ver("1.2.3.4", "1.2.3.5"))
-        self.assertTrue(postgres._pg_is_older_ext_ver("10dev", "10next"))
-        self.assertFalse(postgres._pg_is_older_ext_ver("10next", "10dev"))
-- 
2.52.0

openSUSE Build Service is sponsored by