Files
salt/backport-add-maintain-m-privilege-to-postgres-module.patch
Alexander Graul a3e2ae1f65 - Make syntax in httputil_test compatible with Python 3.6
- Fix KeyError in postgres module with PostgreSQL 17 (bsc#1254325)
- Added:
  * fix-tornado-s-httputil_test-syntax-for-python-3.6.patch
  * backport-add-maintain-m-privilege-to-postgres-module.patch

OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=304
2026-01-19 12:50:04 +00:00

5015 lines
171 KiB
Diff
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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