test_postgresql.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. from flexmock import flexmock
  2. from borgmatic.hooks import postgresql as module
  3. def test_dump_databases_runs_pg_dump_for_each_database():
  4. databases = [{'name': 'foo'}, {'name': 'bar'}]
  5. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  6. 'databases/localhost/foo'
  7. ).and_return('databases/localhost/bar')
  8. flexmock(module.os).should_receive('makedirs')
  9. for name in ('foo', 'bar'):
  10. flexmock(module).should_receive('execute_command').with_args(
  11. (
  12. 'pg_dump',
  13. '--no-password',
  14. '--clean',
  15. '--file',
  16. 'databases/localhost/{}'.format(name),
  17. '--format',
  18. 'custom',
  19. name,
  20. ),
  21. extra_environment=None,
  22. ).once()
  23. module.dump_databases(databases, 'test.yaml', dry_run=False)
  24. def test_dump_databases_with_dry_run_skips_pg_dump():
  25. databases = [{'name': 'foo'}, {'name': 'bar'}]
  26. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  27. 'databases/localhost/foo'
  28. ).and_return('databases/localhost/bar')
  29. flexmock(module.os).should_receive('makedirs').never()
  30. flexmock(module).should_receive('execute_command').never()
  31. module.dump_databases(databases, 'test.yaml', dry_run=True)
  32. def test_dump_databases_runs_pg_dump_with_hostname_and_port():
  33. databases = [{'name': 'foo', 'hostname': 'database.example.org', 'port': 5433}]
  34. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  35. 'databases/database.example.org/foo'
  36. )
  37. flexmock(module.os).should_receive('makedirs')
  38. flexmock(module).should_receive('execute_command').with_args(
  39. (
  40. 'pg_dump',
  41. '--no-password',
  42. '--clean',
  43. '--file',
  44. 'databases/database.example.org/foo',
  45. '--host',
  46. 'database.example.org',
  47. '--port',
  48. '5433',
  49. '--format',
  50. 'custom',
  51. 'foo',
  52. ),
  53. extra_environment=None,
  54. ).once()
  55. module.dump_databases(databases, 'test.yaml', dry_run=False)
  56. def test_dump_databases_runs_pg_dump_with_username_and_password():
  57. databases = [{'name': 'foo', 'username': 'postgres', 'password': 'trustsome1'}]
  58. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  59. 'databases/localhost/foo'
  60. )
  61. flexmock(module.os).should_receive('makedirs')
  62. flexmock(module).should_receive('execute_command').with_args(
  63. (
  64. 'pg_dump',
  65. '--no-password',
  66. '--clean',
  67. '--file',
  68. 'databases/localhost/foo',
  69. '--username',
  70. 'postgres',
  71. '--format',
  72. 'custom',
  73. 'foo',
  74. ),
  75. extra_environment={'PGPASSWORD': 'trustsome1'},
  76. ).once()
  77. module.dump_databases(databases, 'test.yaml', dry_run=False)
  78. def test_dump_databases_runs_pg_dump_with_format():
  79. databases = [{'name': 'foo', 'format': 'tar'}]
  80. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  81. 'databases/localhost/foo'
  82. )
  83. flexmock(module.os).should_receive('makedirs')
  84. flexmock(module).should_receive('execute_command').with_args(
  85. (
  86. 'pg_dump',
  87. '--no-password',
  88. '--clean',
  89. '--file',
  90. 'databases/localhost/foo',
  91. '--format',
  92. 'tar',
  93. 'foo',
  94. ),
  95. extra_environment=None,
  96. ).once()
  97. module.dump_databases(databases, 'test.yaml', dry_run=False)
  98. def test_dump_databases_runs_pg_dump_with_options():
  99. databases = [{'name': 'foo', 'options': '--stuff=such'}]
  100. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  101. 'databases/localhost/foo'
  102. )
  103. flexmock(module.os).should_receive('makedirs')
  104. flexmock(module).should_receive('execute_command').with_args(
  105. (
  106. 'pg_dump',
  107. '--no-password',
  108. '--clean',
  109. '--file',
  110. 'databases/localhost/foo',
  111. '--format',
  112. 'custom',
  113. '--stuff=such',
  114. 'foo',
  115. ),
  116. extra_environment=None,
  117. ).once()
  118. module.dump_databases(databases, 'test.yaml', dry_run=False)
  119. def test_dump_databases_runs_pg_dumpall_for_all_databases():
  120. databases = [{'name': 'all'}]
  121. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  122. 'databases/localhost/all'
  123. )
  124. flexmock(module.os).should_receive('makedirs')
  125. flexmock(module).should_receive('execute_command').with_args(
  126. ('pg_dumpall', '--no-password', '--clean', '--file', 'databases/localhost/all'),
  127. extra_environment=None,
  128. ).once()
  129. module.dump_databases(databases, 'test.yaml', dry_run=False)
  130. def test_make_database_dump_patterns_converts_names_to_glob_paths():
  131. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  132. 'databases/*/foo'
  133. ).and_return('databases/*/bar')
  134. assert module.make_database_dump_patterns(flexmock(), flexmock(), ('foo', 'bar')) == [
  135. 'databases/*/foo',
  136. 'databases/*/bar',
  137. ]
  138. def test_make_database_dump_patterns_treats_empty_names_as_matching_all_databases():
  139. flexmock(module.dump).should_receive('make_database_dump_filename').with_args(
  140. module.DUMP_PATH, '*', '*'
  141. ).and_return('databases/*/*')
  142. assert module.make_database_dump_patterns(flexmock(), flexmock(), ()) == ['databases/*/*']
  143. def test_restore_database_dumps_restores_each_database():
  144. databases = [{'name': 'foo'}, {'name': 'bar'}]
  145. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  146. 'databases/localhost/foo'
  147. ).and_return('databases/localhost/bar')
  148. for name in ('foo', 'bar'):
  149. flexmock(module).should_receive('execute_command').with_args(
  150. (
  151. 'pg_restore',
  152. '--no-password',
  153. '--clean',
  154. '--if-exists',
  155. '--exit-on-error',
  156. '--dbname',
  157. name,
  158. 'databases/localhost/{}'.format(name),
  159. ),
  160. extra_environment=None,
  161. ).once()
  162. flexmock(module).should_receive('execute_command').with_args(
  163. ('psql', '--no-password', '--quiet', '--dbname', name, '--command', 'ANALYZE'),
  164. extra_environment=None,
  165. ).once()
  166. module.restore_database_dumps(databases, 'test.yaml', dry_run=False)
  167. def test_restore_database_dumps_runs_pg_restore_with_hostname_and_port():
  168. databases = [{'name': 'foo', 'hostname': 'database.example.org', 'port': 5433}]
  169. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  170. 'databases/localhost/foo'
  171. )
  172. flexmock(module).should_receive('execute_command').with_args(
  173. (
  174. 'pg_restore',
  175. '--no-password',
  176. '--clean',
  177. '--if-exists',
  178. '--exit-on-error',
  179. '--host',
  180. 'database.example.org',
  181. '--port',
  182. '5433',
  183. '--dbname',
  184. 'foo',
  185. 'databases/localhost/foo',
  186. ),
  187. extra_environment=None,
  188. ).once()
  189. flexmock(module).should_receive('execute_command').with_args(
  190. (
  191. 'psql',
  192. '--no-password',
  193. '--quiet',
  194. '--host',
  195. 'database.example.org',
  196. '--port',
  197. '5433',
  198. '--dbname',
  199. 'foo',
  200. '--command',
  201. 'ANALYZE',
  202. ),
  203. extra_environment=None,
  204. ).once()
  205. module.restore_database_dumps(databases, 'test.yaml', dry_run=False)
  206. def test_restore_database_dumps_runs_pg_restore_with_username_and_password():
  207. databases = [{'name': 'foo', 'username': 'postgres', 'password': 'trustsome1'}]
  208. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  209. 'databases/localhost/foo'
  210. )
  211. flexmock(module).should_receive('execute_command').with_args(
  212. (
  213. 'pg_restore',
  214. '--no-password',
  215. '--clean',
  216. '--if-exists',
  217. '--exit-on-error',
  218. '--username',
  219. 'postgres',
  220. '--dbname',
  221. 'foo',
  222. 'databases/localhost/foo',
  223. ),
  224. extra_environment={'PGPASSWORD': 'trustsome1'},
  225. ).once()
  226. flexmock(module).should_receive('execute_command').with_args(
  227. (
  228. 'psql',
  229. '--no-password',
  230. '--quiet',
  231. '--username',
  232. 'postgres',
  233. '--dbname',
  234. 'foo',
  235. '--command',
  236. 'ANALYZE',
  237. ),
  238. extra_environment={'PGPASSWORD': 'trustsome1'},
  239. ).once()
  240. module.restore_database_dumps(databases, 'test.yaml', dry_run=False)