test_mysql.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. import sys
  2. from flexmock import flexmock
  3. from borgmatic.hooks import mysql as module
  4. def test_database_names_to_dump_passes_through_name():
  5. extra_environment = flexmock()
  6. log_prefix = ''
  7. dry_run_label = ''
  8. names = module.database_names_to_dump(
  9. {'name': 'foo'}, extra_environment, log_prefix, dry_run_label
  10. )
  11. assert names == ('foo',)
  12. def test_database_names_to_dump_queries_mysql_for_database_names():
  13. extra_environment = flexmock()
  14. log_prefix = ''
  15. dry_run_label = ''
  16. flexmock(module).should_receive('execute_command').with_args(
  17. ('mysql', '--skip-column-names', '--batch', '--execute', 'show schemas'),
  18. output_log_level=None,
  19. extra_environment=extra_environment,
  20. ).and_return('foo\nbar\nmysql\n').once()
  21. names = module.database_names_to_dump(
  22. {'name': 'all'}, extra_environment, log_prefix, dry_run_label
  23. )
  24. assert names == ('foo', 'bar')
  25. def test_dump_databases_runs_mysqldump_for_each_database():
  26. databases = [{'name': 'foo'}, {'name': 'bar'}]
  27. output_file = flexmock()
  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).should_receive('database_names_to_dump').and_return(('foo',)).and_return(
  33. ('bar',)
  34. )
  35. flexmock(module.os).should_receive('makedirs')
  36. flexmock(sys.modules['builtins']).should_receive('open').and_return(output_file)
  37. for name in ('foo', 'bar'):
  38. flexmock(module).should_receive('execute_command').with_args(
  39. ('mysqldump', '--add-drop-database', '--databases', name),
  40. output_file=output_file,
  41. extra_environment=None,
  42. ).once()
  43. module.dump_databases(databases, 'test.yaml', {}, dry_run=False)
  44. def test_dump_databases_with_dry_run_skips_mysqldump():
  45. databases = [{'name': 'foo'}, {'name': 'bar'}]
  46. flexmock(module).should_receive('make_dump_path').and_return('')
  47. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  48. 'databases/localhost/foo'
  49. ).and_return('databases/localhost/bar')
  50. flexmock(module).should_receive('database_names_to_dump').and_return(('foo',)).and_return(
  51. ('bar',)
  52. )
  53. flexmock(module.os).should_receive('makedirs').never()
  54. flexmock(module).should_receive('execute_command').never()
  55. module.dump_databases(databases, 'test.yaml', {}, dry_run=True)
  56. def test_dump_databases_runs_mysqldump_with_hostname_and_port():
  57. databases = [{'name': 'foo', 'hostname': 'database.example.org', 'port': 5433}]
  58. output_file = flexmock()
  59. flexmock(module).should_receive('make_dump_path').and_return('')
  60. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  61. 'databases/database.example.org/foo'
  62. )
  63. flexmock(module).should_receive('database_names_to_dump').and_return(('foo',))
  64. flexmock(module.os).should_receive('makedirs')
  65. flexmock(sys.modules['builtins']).should_receive('open').and_return(output_file)
  66. flexmock(module).should_receive('execute_command').with_args(
  67. (
  68. 'mysqldump',
  69. '--add-drop-database',
  70. '--host',
  71. 'database.example.org',
  72. '--port',
  73. '5433',
  74. '--protocol',
  75. 'tcp',
  76. '--databases',
  77. 'foo',
  78. ),
  79. output_file=output_file,
  80. extra_environment=None,
  81. ).once()
  82. module.dump_databases(databases, 'test.yaml', {}, dry_run=False)
  83. def test_dump_databases_runs_mysqldump_with_username_and_password():
  84. databases = [{'name': 'foo', 'username': 'root', 'password': 'trustsome1'}]
  85. output_file = flexmock()
  86. flexmock(module).should_receive('make_dump_path').and_return('')
  87. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  88. 'databases/localhost/foo'
  89. )
  90. flexmock(module).should_receive('database_names_to_dump').and_return(('foo',))
  91. flexmock(module.os).should_receive('makedirs')
  92. flexmock(sys.modules['builtins']).should_receive('open').and_return(output_file)
  93. flexmock(module).should_receive('execute_command').with_args(
  94. ('mysqldump', '--add-drop-database', '--user', 'root', '--databases', 'foo'),
  95. output_file=output_file,
  96. extra_environment={'MYSQL_PWD': 'trustsome1'},
  97. ).once()
  98. module.dump_databases(databases, 'test.yaml', {}, dry_run=False)
  99. def test_dump_databases_runs_mysqldump_with_options():
  100. databases = [{'name': 'foo', 'options': '--stuff=such'}]
  101. output_file = flexmock()
  102. flexmock(module).should_receive('make_dump_path').and_return('')
  103. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  104. 'databases/localhost/foo'
  105. )
  106. flexmock(module).should_receive('database_names_to_dump').and_return(('foo',))
  107. flexmock(module.os).should_receive('makedirs')
  108. flexmock(sys.modules['builtins']).should_receive('open').and_return(output_file)
  109. flexmock(module).should_receive('execute_command').with_args(
  110. ('mysqldump', '--add-drop-database', '--stuff=such', '--databases', 'foo'),
  111. output_file=output_file,
  112. extra_environment=None,
  113. ).once()
  114. module.dump_databases(databases, 'test.yaml', {}, dry_run=False)
  115. def test_dump_databases_runs_mysqldump_for_all_databases():
  116. databases = [{'name': 'all'}]
  117. output_file = flexmock()
  118. flexmock(module).should_receive('make_dump_path').and_return('')
  119. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  120. 'databases/localhost/all'
  121. )
  122. flexmock(module).should_receive('database_names_to_dump').and_return(('foo', 'bar'))
  123. flexmock(module.os).should_receive('makedirs')
  124. flexmock(sys.modules['builtins']).should_receive('open').and_return(output_file)
  125. flexmock(module).should_receive('execute_command').with_args(
  126. ('mysqldump', '--add-drop-database', '--databases', 'foo', 'bar'),
  127. output_file=output_file,
  128. extra_environment=None,
  129. ).once()
  130. module.dump_databases(databases, 'test.yaml', {}, dry_run=False)
  131. def test_make_database_dump_patterns_converts_names_to_glob_paths():
  132. flexmock(module).should_receive('make_dump_path').and_return('')
  133. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  134. 'databases/*/foo'
  135. ).and_return('databases/*/bar')
  136. assert module.make_database_dump_patterns(flexmock(), flexmock(), {}, ('foo', 'bar')) == [
  137. 'databases/*/foo',
  138. 'databases/*/bar',
  139. ]
  140. def test_make_database_dump_patterns_treats_empty_names_as_matching_all_databases():
  141. flexmock(module).should_receive('make_dump_path').and_return('/dump/path')
  142. flexmock(module.dump).should_receive('make_database_dump_filename').with_args(
  143. '/dump/path', '*', '*'
  144. ).and_return('databases/*/*')
  145. assert module.make_database_dump_patterns(flexmock(), flexmock(), {}, ()) == ['databases/*/*']
  146. def test_restore_database_dumps_restores_each_database():
  147. databases = [{'name': 'foo'}, {'name': 'bar'}]
  148. flexmock(module).should_receive('make_dump_path').and_return('')
  149. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  150. 'databases/localhost/foo'
  151. ).and_return('databases/localhost/bar')
  152. for name in ('foo', 'bar'):
  153. dump_filename = 'databases/localhost/{}'.format(name)
  154. input_file = flexmock()
  155. flexmock(sys.modules['builtins']).should_receive('open').with_args(
  156. dump_filename
  157. ).and_return(input_file)
  158. flexmock(module).should_receive('execute_command').with_args(
  159. ('mysql', '--batch'), input_file=input_file, extra_environment=None
  160. ).once()
  161. module.restore_database_dumps(databases, 'test.yaml', {}, dry_run=False)
  162. def test_restore_database_dumps_runs_mysql_with_hostname_and_port():
  163. databases = [{'name': 'foo', 'hostname': 'database.example.org', 'port': 5433}]
  164. flexmock(module).should_receive('make_dump_path').and_return('')
  165. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  166. 'databases/localhost/foo'
  167. )
  168. dump_filename = 'databases/localhost/foo'
  169. input_file = flexmock()
  170. flexmock(sys.modules['builtins']).should_receive('open').with_args(dump_filename).and_return(
  171. input_file
  172. )
  173. flexmock(module).should_receive('execute_command').with_args(
  174. (
  175. 'mysql',
  176. '--batch',
  177. '--host',
  178. 'database.example.org',
  179. '--port',
  180. '5433',
  181. '--protocol',
  182. 'tcp',
  183. ),
  184. input_file=input_file,
  185. extra_environment=None,
  186. ).once()
  187. module.restore_database_dumps(databases, 'test.yaml', {}, dry_run=False)
  188. def test_restore_database_dumps_runs_mysql_with_username_and_password():
  189. databases = [{'name': 'foo', 'username': 'root', 'password': 'trustsome1'}]
  190. flexmock(module).should_receive('make_dump_path').and_return('')
  191. flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
  192. 'databases/localhost/foo'
  193. )
  194. dump_filename = 'databases/localhost/foo'
  195. input_file = flexmock()
  196. flexmock(sys.modules['builtins']).should_receive('open').with_args(dump_filename).and_return(
  197. input_file
  198. )
  199. flexmock(module).should_receive('execute_command').with_args(
  200. ('mysql', '--batch', '--user', 'root'),
  201. input_file=input_file,
  202. extra_environment={'MYSQL_PWD': 'trustsome1'},
  203. ).once()
  204. module.restore_database_dumps(databases, 'test.yaml', {}, dry_run=False)