test_postgres.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. # -*- coding: utf-8 -*-
  2. # Import python libs
  3. from __future__ import absolute_import, print_function, unicode_literals
  4. # Import salt libs
  5. import salt.modules.postgres as postgresmod
  6. import salt.states.postgres_database as postgres_database
  7. import salt.states.postgres_extension as postgres_extension
  8. import salt.states.postgres_group as postgres_group
  9. import salt.states.postgres_schema as postgres_schema
  10. import salt.states.postgres_user as postgres_user
  11. # Import Salt Testing libs
  12. from tests.support.mixins import LoaderModuleMockMixin
  13. from tests.support.mock import MagicMock, Mock, patch
  14. from tests.support.unit import TestCase
  15. class PostgresUserTestCase(TestCase, LoaderModuleMockMixin):
  16. def setup_loader_modules(self):
  17. patcher = patch("salt.utils.path.which", Mock(return_value="/usr/bin/pgsql"))
  18. patcher.start()
  19. self.addCleanup(patcher.stop)
  20. self.salt_stub = {
  21. "config.option": Mock(),
  22. "cmd.run_all": Mock(),
  23. "file.chown": Mock(),
  24. "file.remove": Mock(),
  25. }
  26. self.addCleanup(delattr, self, "salt_stub")
  27. return {
  28. postgres_database: {},
  29. postgres_group: {},
  30. postgres_extension: {},
  31. postgres_schema: {},
  32. postgres_user: {
  33. "__grains__": {"os_family": "Linux"},
  34. "__salt__": self.salt_stub,
  35. "__opts__": {"test": False},
  36. },
  37. }
  38. def test_present__creation(self):
  39. # test=True
  40. with patch.dict(
  41. postgres_user.__salt__,
  42. {
  43. "postgres.role_get": Mock(return_value=None),
  44. "postgres.user_create": MagicMock(),
  45. },
  46. ):
  47. with patch.dict(postgres_user.__opts__, {"test": True}):
  48. ret = postgres_user.present("foo")
  49. self.assertEqual(
  50. ret,
  51. {
  52. "comment": "User foo is set to be created",
  53. "changes": {},
  54. "name": "foo",
  55. "result": None,
  56. },
  57. )
  58. self.assertEqual(self.salt_stub["postgres.user_create"].call_count, 0)
  59. # test=False
  60. ret = postgres_user.present("foo")
  61. self.assertEqual(
  62. ret,
  63. {
  64. "comment": "The user foo has been created",
  65. "changes": {"foo": "Present"},
  66. "name": "foo",
  67. "result": True,
  68. },
  69. )
  70. self.salt_stub["postgres.user_create"].assert_called_once_with(
  71. username="foo",
  72. superuser=None,
  73. encrypted=True,
  74. runas=None,
  75. inherit=None,
  76. rolepassword=None,
  77. port=None,
  78. replication=None,
  79. host=None,
  80. createroles=None,
  81. user=None,
  82. groups=None,
  83. maintenance_db=None,
  84. login=None,
  85. password=None,
  86. valid_until=None,
  87. createdb=None,
  88. )
  89. def test_present__update(self):
  90. # test=True
  91. with patch.dict(
  92. postgres_user.__salt__,
  93. {
  94. "postgres.role_get": Mock(
  95. return_value={
  96. "can create databases": False,
  97. "can create roles": False,
  98. "can login": False,
  99. "can update system catalogs": False,
  100. "connections": None,
  101. "defaults variables": {},
  102. "expiry time": None,
  103. "inherits privileges": True,
  104. "replication": False,
  105. "superuser": False,
  106. }
  107. ),
  108. "postgres.user_update": MagicMock(),
  109. },
  110. ):
  111. with patch.dict(postgres_user.__opts__, {"test": True}):
  112. ret = postgres_user.present("foo", login=True, replication=False)
  113. self.assertEqual(
  114. ret,
  115. {
  116. "comment": "User foo is set to be updated",
  117. "changes": {"foo": {"login": True}},
  118. "name": "foo",
  119. "result": None,
  120. },
  121. )
  122. self.assertEqual(self.salt_stub["postgres.user_update"].call_count, 0)
  123. # test=False
  124. ret = postgres_user.present("foo", login=True, replication=False)
  125. self.assertEqual(
  126. ret,
  127. {
  128. "comment": "The user foo has been updated",
  129. "changes": {"foo": {"login": True}},
  130. "name": "foo",
  131. "result": True,
  132. },
  133. )
  134. self.salt_stub["postgres.user_update"].assert_called_once_with(
  135. username="foo",
  136. superuser=None,
  137. encrypted=True,
  138. runas=None,
  139. inherit=None,
  140. rolepassword=None,
  141. port=None,
  142. replication=False,
  143. host=None,
  144. createroles=None,
  145. user=None,
  146. groups=None,
  147. maintenance_db=None,
  148. login=True,
  149. password=None,
  150. valid_until=None,
  151. createdb=None,
  152. )
  153. def test_present__no_update(self):
  154. # test=True
  155. with patch.dict(
  156. postgres_user.__salt__,
  157. {
  158. "postgres.role_get": Mock(
  159. return_value={
  160. "can create databases": False,
  161. "can create roles": False,
  162. "can login": False,
  163. "can update system catalogs": False,
  164. "connections": None,
  165. "defaults variables": {},
  166. "expiry time": None,
  167. "inherits privileges": True,
  168. "replication": False,
  169. "superuser": False,
  170. }
  171. ),
  172. "postgres.user_update": MagicMock(),
  173. },
  174. ):
  175. with patch.dict(postgres_user.__opts__, {"test": True}):
  176. ret = postgres_user.present("foo", login=False, replication=False)
  177. self.assertEqual(
  178. ret,
  179. {
  180. "comment": "User foo is already present",
  181. "changes": {},
  182. "name": "foo",
  183. "result": True,
  184. },
  185. )
  186. self.assertEqual(self.salt_stub["postgres.user_update"].call_count, 0)
  187. # test=False
  188. ret = postgres_user.present("foo", login=False, replication=False)
  189. self.assertEqual(
  190. ret,
  191. {
  192. "comment": "User foo is already present",
  193. "changes": {},
  194. "name": "foo",
  195. "result": True,
  196. },
  197. )
  198. self.assertEqual(self.salt_stub["postgres.user_update"].call_count, 0)
  199. class PostgresGroupTestCase(TestCase, LoaderModuleMockMixin):
  200. def setup_loader_modules(self):
  201. patcher = patch("salt.utils.path.which", Mock(return_value="/usr/bin/pgsql"))
  202. patcher.start()
  203. self.addCleanup(patcher.stop)
  204. self.salt_stub = {
  205. "config.option": Mock(),
  206. "cmd.run_all": Mock(),
  207. "file.chown": Mock(),
  208. "file.remove": Mock(),
  209. }
  210. self.addCleanup(delattr, self, "salt_stub")
  211. return {
  212. postgres_database: {},
  213. postgres_user: {},
  214. postgres_extension: {},
  215. postgres_schema: {},
  216. postgres_group: {
  217. "__grains__": {"os_family": "Linux"},
  218. "__salt__": self.salt_stub,
  219. "__opts__": {"test": False},
  220. },
  221. }
  222. def test_present__creation(self):
  223. # test=True
  224. with patch.dict(
  225. postgres_group.__salt__,
  226. {
  227. "postgres.role_get": Mock(return_value=None),
  228. "postgres.group_create": MagicMock(),
  229. },
  230. ):
  231. with patch.dict(postgres_group.__opts__, {"test": True}):
  232. ret = postgres_group.present("foo")
  233. self.assertEqual(
  234. ret,
  235. {
  236. "comment": "Group foo is set to be created",
  237. "changes": {},
  238. "name": "foo",
  239. "result": None,
  240. },
  241. )
  242. self.assertEqual(self.salt_stub["postgres.group_create"].call_count, 0)
  243. # test=False
  244. ret = postgres_group.present("foo")
  245. self.assertEqual(
  246. ret,
  247. {
  248. "comment": "The group foo has been created",
  249. "changes": {},
  250. "name": "foo",
  251. "result": True,
  252. },
  253. )
  254. self.salt_stub["postgres.group_create"].assert_called_once_with(
  255. superuser=None,
  256. replication=None,
  257. encrypted=True,
  258. runas=None,
  259. inherit=None,
  260. rolepassword=None,
  261. port=None,
  262. groupname="foo",
  263. host=None,
  264. createroles=None,
  265. user=None,
  266. groups=None,
  267. maintenance_db=None,
  268. login=None,
  269. password=None,
  270. createdb=None,
  271. )
  272. def test_present__update(self):
  273. # test=True
  274. with patch.dict(
  275. postgres_group.__salt__,
  276. {
  277. "postgres.role_get": Mock(
  278. return_value={
  279. "can create databases": False,
  280. "can create roles": False,
  281. "can login": False,
  282. "can update system catalogs": False,
  283. "connections": None,
  284. "defaults variables": {},
  285. "expiry time": None,
  286. "inherits privileges": True,
  287. "replication": False,
  288. "superuser": False,
  289. }
  290. ),
  291. "postgres.group_update": MagicMock(),
  292. },
  293. ):
  294. with patch.dict(postgres_group.__opts__, {"test": True}):
  295. ret = postgres_group.present("foo", login=True, replication=False)
  296. self.assertEqual(
  297. ret,
  298. {
  299. "comment": "Group foo is set to be updated",
  300. "changes": {"foo": {"login": True}},
  301. "name": "foo",
  302. "result": None,
  303. },
  304. )
  305. self.assertEqual(self.salt_stub["postgres.group_update"].call_count, 0)
  306. # test=False
  307. ret = postgres_group.present("foo", login=True, replication=False)
  308. self.assertEqual(
  309. ret,
  310. {
  311. "comment": "The group foo has been updated",
  312. "changes": {"foo": {"login": True}},
  313. "name": "foo",
  314. "result": True,
  315. },
  316. )
  317. self.salt_stub["postgres.group_update"].assert_called_once_with(
  318. superuser=None,
  319. replication=False,
  320. encrypted=True,
  321. runas=None,
  322. inherit=None,
  323. rolepassword=None,
  324. port=None,
  325. groupname="foo",
  326. host=None,
  327. createroles=None,
  328. user=None,
  329. groups=None,
  330. maintenance_db=None,
  331. login=True,
  332. password=None,
  333. createdb=None,
  334. )
  335. def test_present__no_update(self):
  336. # test=True
  337. with patch.dict(
  338. postgres_group.__salt__,
  339. {
  340. "postgres.role_get": Mock(
  341. return_value={
  342. "can create databases": False,
  343. "can create roles": False,
  344. "can login": False,
  345. "can update system catalogs": False,
  346. "connections": None,
  347. "defaults variables": {},
  348. "expiry time": None,
  349. "inherits privileges": True,
  350. "replication": False,
  351. "superuser": False,
  352. }
  353. ),
  354. "postgres.group_update": MagicMock(),
  355. },
  356. ):
  357. with patch.dict(postgres_group.__opts__, {"test": True}):
  358. ret = postgres_group.present("foo", login=False, replication=False)
  359. self.assertEqual(
  360. ret,
  361. {
  362. "comment": "Group foo is already present",
  363. "changes": {},
  364. "name": "foo",
  365. "result": True,
  366. },
  367. )
  368. self.assertEqual(self.salt_stub["postgres.group_update"].call_count, 0)
  369. # test=False
  370. ret = postgres_group.present("foo", login=False, replication=False)
  371. self.assertEqual(
  372. ret,
  373. {
  374. "comment": "Group foo is already present",
  375. "changes": {},
  376. "name": "foo",
  377. "result": True,
  378. },
  379. )
  380. self.assertEqual(self.salt_stub["postgres.group_update"].call_count, 0)
  381. class PostgresExtensionTestCase(TestCase, LoaderModuleMockMixin):
  382. def setup_loader_modules(self):
  383. patcher = patch("salt.utils.path.which", Mock(return_value="/usr/bin/pgsql"))
  384. patcher.start()
  385. self.addCleanup(patcher.stop)
  386. self.salt_stub = {
  387. "config.option": Mock(),
  388. "cmd.run_all": Mock(),
  389. "file.chown": Mock(),
  390. "file.remove": Mock(),
  391. }
  392. self.addCleanup(delattr, self, "salt_stub")
  393. return {
  394. postgres_database: {},
  395. postgres_user: {},
  396. postgres_group: {},
  397. postgres_schema: {},
  398. postgres_extension: {
  399. "__grains__": {"os_family": "Linux"},
  400. "__salt__": self.salt_stub,
  401. "__opts__": {"test": False},
  402. },
  403. }
  404. def test_present_failed(self):
  405. """
  406. scenario of creating upgrading extensions with possible schema and
  407. version specifications
  408. """
  409. with patch.dict(
  410. postgres_extension.__salt__,
  411. {
  412. "postgres.create_metadata": Mock(
  413. side_effect=[
  414. [postgresmod._EXTENSION_NOT_INSTALLED],
  415. [
  416. postgresmod._EXTENSION_TO_MOVE,
  417. postgresmod._EXTENSION_INSTALLED,
  418. ],
  419. ]
  420. ),
  421. "postgres.create_extension": Mock(side_effect=[False, False]),
  422. },
  423. ):
  424. ret = postgres_extension.present("foo")
  425. self.assertEqual(
  426. ret,
  427. {
  428. "comment": "Failed to install extension foo",
  429. "changes": {},
  430. "name": "foo",
  431. "result": False,
  432. },
  433. )
  434. ret = postgres_extension.present("foo")
  435. self.assertEqual(
  436. ret,
  437. {
  438. "comment": "Failed to upgrade extension foo",
  439. "changes": {},
  440. "name": "foo",
  441. "result": False,
  442. },
  443. )
  444. def test_present(self):
  445. """
  446. scenario of creating upgrading extensions with possible schema and
  447. version specifications
  448. """
  449. with patch.dict(
  450. postgres_extension.__salt__,
  451. {
  452. "postgres.create_metadata": Mock(
  453. side_effect=[
  454. [postgresmod._EXTENSION_NOT_INSTALLED],
  455. [postgresmod._EXTENSION_INSTALLED],
  456. [
  457. postgresmod._EXTENSION_TO_MOVE,
  458. postgresmod._EXTENSION_INSTALLED,
  459. ],
  460. ]
  461. ),
  462. "postgres.create_extension": Mock(side_effect=[True, True, True]),
  463. },
  464. ):
  465. ret = postgres_extension.present("foo")
  466. self.assertEqual(
  467. ret,
  468. {
  469. "comment": "The extension foo has been installed",
  470. "changes": {"foo": "Installed"},
  471. "name": "foo",
  472. "result": True,
  473. },
  474. )
  475. ret = postgres_extension.present("foo")
  476. self.assertEqual(
  477. ret,
  478. {
  479. "comment": "Extension foo is already present",
  480. "changes": {},
  481. "name": "foo",
  482. "result": True,
  483. },
  484. )
  485. ret = postgres_extension.present("foo")
  486. self.assertEqual(
  487. ret,
  488. {
  489. "comment": "The extension foo has been upgraded",
  490. "changes": {"foo": "Upgraded"},
  491. "name": "foo",
  492. "result": True,
  493. },
  494. )
  495. def test_presenttest(self):
  496. """
  497. scenario of creating upgrading extensions with possible schema and
  498. version specifications
  499. """
  500. with patch.dict(
  501. postgres_extension.__salt__,
  502. {
  503. "postgres.create_metadata": Mock(
  504. side_effect=[
  505. [postgresmod._EXTENSION_NOT_INSTALLED],
  506. [postgresmod._EXTENSION_INSTALLED],
  507. [
  508. postgresmod._EXTENSION_TO_MOVE,
  509. postgresmod._EXTENSION_INSTALLED,
  510. ],
  511. ]
  512. ),
  513. "postgres.create_extension": Mock(side_effect=[True, True, True]),
  514. },
  515. ):
  516. with patch.dict(postgres_extension.__opts__, {"test": True}):
  517. ret = postgres_extension.present("foo")
  518. self.assertEqual(
  519. ret,
  520. {
  521. "comment": "Extension foo is set to be installed",
  522. "changes": {},
  523. "name": "foo",
  524. "result": None,
  525. },
  526. )
  527. ret = postgres_extension.present("foo")
  528. self.assertEqual(
  529. ret,
  530. {
  531. "comment": "Extension foo is already present",
  532. "changes": {},
  533. "name": "foo",
  534. "result": True,
  535. },
  536. )
  537. ret = postgres_extension.present("foo")
  538. self.assertEqual(
  539. ret,
  540. {
  541. "comment": "Extension foo is set to be upgraded",
  542. "changes": {},
  543. "name": "foo",
  544. "result": None,
  545. },
  546. )
  547. def test_absent(self):
  548. """
  549. scenario of creating upgrading extensions with possible schema and
  550. version specifications
  551. """
  552. with patch.dict(
  553. postgres_extension.__salt__,
  554. {
  555. "postgres.is_installed_extension": Mock(side_effect=[True, False]),
  556. "postgres.drop_extension": Mock(side_effect=[True, True]),
  557. },
  558. ):
  559. ret = postgres_extension.absent("foo")
  560. self.assertEqual(
  561. ret,
  562. {
  563. "comment": "Extension foo has been removed",
  564. "changes": {"foo": "Absent"},
  565. "name": "foo",
  566. "result": True,
  567. },
  568. )
  569. ret = postgres_extension.absent("foo")
  570. self.assertEqual(
  571. ret,
  572. {
  573. "comment": (
  574. "Extension foo is not present, " "so it cannot be removed"
  575. ),
  576. "changes": {},
  577. "name": "foo",
  578. "result": True,
  579. },
  580. )
  581. def test_absent_failed(self):
  582. """
  583. scenario of creating upgrading extensions with possible schema and
  584. version specifications
  585. """
  586. with patch.dict(postgres_extension.__opts__, {"test": False}):
  587. with patch.dict(
  588. postgres_extension.__salt__,
  589. {
  590. "postgres.is_installed_extension": Mock(side_effect=[True, True]),
  591. "postgres.drop_extension": Mock(side_effect=[False, False]),
  592. },
  593. ):
  594. ret = postgres_extension.absent("foo")
  595. self.assertEqual(
  596. ret,
  597. {
  598. "comment": "Extension foo failed to be removed",
  599. "changes": {},
  600. "name": "foo",
  601. "result": False,
  602. },
  603. )
  604. def test_absent_failedtest(self):
  605. with patch.dict(
  606. postgres_extension.__salt__,
  607. {
  608. "postgres.is_installed_extension": Mock(side_effect=[True, True]),
  609. "postgres.drop_extension": Mock(side_effect=[False, False]),
  610. },
  611. ):
  612. with patch.dict(postgres_extension.__opts__, {"test": True}):
  613. ret = postgres_extension.absent("foo")
  614. self.assertEqual(
  615. ret,
  616. {
  617. "comment": "Extension foo is set to be removed",
  618. "changes": {},
  619. "name": "foo",
  620. "result": None,
  621. },
  622. )
  623. class PostgresSchemaTestCase(TestCase, LoaderModuleMockMixin):
  624. def setup_loader_modules(self):
  625. patcher = patch("salt.utils.path.which", Mock(return_value="/usr/bin/pgsql"))
  626. patcher.start()
  627. self.addCleanup(patcher.stop)
  628. self.salt_stub = {
  629. "config.option": Mock(),
  630. "cmd.run_all": Mock(),
  631. "file.chown": Mock(),
  632. "file.remove": Mock(),
  633. }
  634. self.addCleanup(delattr, self, "salt_stub")
  635. return {
  636. postgres_database: {},
  637. postgres_user: {},
  638. postgres_extension: {},
  639. postgres_group: {},
  640. postgres_schema: {
  641. "__grains__": {"os_family": "Linux"},
  642. "__salt__": self.salt_stub,
  643. "__opts__": {"test": False},
  644. },
  645. }
  646. def test_present_creation(self):
  647. with patch.dict(
  648. postgres_schema.__salt__,
  649. {
  650. "postgres.schema_get": Mock(return_value=None),
  651. "postgres.schema_create": MagicMock(),
  652. },
  653. ):
  654. ret = postgres_schema.present("dbname", "foo")
  655. self.assertEqual(
  656. ret,
  657. {
  658. "comment": "Schema foo has been created in database dbname",
  659. "changes": {"foo": "Present"},
  660. "dbname": "dbname",
  661. "name": "foo",
  662. "result": True,
  663. },
  664. )
  665. self.assertEqual(self.salt_stub["postgres.schema_create"].call_count, 1)
  666. def test_present_nocreation(self):
  667. with patch.dict(
  668. postgres_schema.__salt__,
  669. {
  670. "postgres.schema_get": Mock(
  671. return_value={"foo": {"acl": "", "owner": "postgres"}}
  672. ),
  673. "postgres.schema_create": MagicMock(),
  674. },
  675. ):
  676. ret = postgres_schema.present("dbname", "foo")
  677. self.assertEqual(
  678. ret,
  679. {
  680. "comment": "Schema foo already exists in database dbname",
  681. "changes": {},
  682. "dbname": "dbname",
  683. "name": "foo",
  684. "result": True,
  685. },
  686. )
  687. self.assertEqual(self.salt_stub["postgres.schema_create"].call_count, 0)
  688. def test_absent_remove(self):
  689. with patch.dict(
  690. postgres_schema.__salt__,
  691. {
  692. "postgres.schema_exists": Mock(return_value=True),
  693. "postgres.schema_remove": MagicMock(),
  694. },
  695. ):
  696. ret = postgres_schema.absent("dbname", "foo")
  697. self.assertEqual(
  698. ret,
  699. {
  700. "comment": "Schema foo has been removed from database dbname",
  701. "changes": {"foo": "Absent"},
  702. "dbname": "dbname",
  703. "name": "foo",
  704. "result": True,
  705. },
  706. )
  707. self.assertEqual(self.salt_stub["postgres.schema_remove"].call_count, 1)
  708. def test_absent_noremove(self):
  709. with patch.dict(
  710. postgres_schema.__salt__,
  711. {
  712. "postgres.schema_exists": Mock(return_value=False),
  713. "postgres.schema_remove": MagicMock(),
  714. },
  715. ):
  716. ret = postgres_schema.absent("dbname", "foo")
  717. self.assertEqual(
  718. ret,
  719. {
  720. "comment": "Schema foo is not present in database dbname,"
  721. " so it cannot be removed",
  722. "changes": {},
  723. "dbname": "dbname",
  724. "name": "foo",
  725. "result": True,
  726. },
  727. )
  728. self.assertEqual(self.salt_stub["postgres.schema_remove"].call_count, 0)