test_postgresql.py 9.7 KB

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