test_postgresql.py 11 KB

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