test_healthchecks.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. from flexmock import flexmock
  2. from borgmatic.hooks.monitoring import healthchecks as module
  3. def mock_logger():
  4. logger = flexmock()
  5. logger.should_receive('addHandler')
  6. logger.should_receive('removeHandler')
  7. flexmock(module.logging).should_receive('getLogger').and_return(logger)
  8. def test_initialize_monitor_creates_log_handler_with_ping_body_limit():
  9. ping_body_limit = 100
  10. monitoring_log_level = 1
  11. mock_logger()
  12. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  13. 'Forgetful_buffering_handler'
  14. ).with_args(
  15. module.HANDLER_IDENTIFIER,
  16. ping_body_limit - len(module.borgmatic.hooks.monitoring.logs.PAYLOAD_TRUNCATION_INDICATOR),
  17. monitoring_log_level,
  18. ).once()
  19. module.initialize_monitor(
  20. {'ping_body_limit': ping_body_limit}, {}, 'test.yaml', monitoring_log_level, dry_run=False
  21. )
  22. def test_initialize_monitor_creates_log_handler_with_default_ping_body_limit():
  23. monitoring_log_level = 1
  24. mock_logger()
  25. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  26. 'Forgetful_buffering_handler'
  27. ).with_args(
  28. module.HANDLER_IDENTIFIER,
  29. module.DEFAULT_PING_BODY_LIMIT_BYTES
  30. - len(module.borgmatic.hooks.monitoring.logs.PAYLOAD_TRUNCATION_INDICATOR),
  31. monitoring_log_level,
  32. ).once()
  33. module.initialize_monitor({}, {}, 'test.yaml', monitoring_log_level, dry_run=False)
  34. def test_initialize_monitor_creates_log_handler_with_zero_ping_body_limit():
  35. ping_body_limit = 0
  36. monitoring_log_level = 1
  37. mock_logger()
  38. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  39. 'Forgetful_buffering_handler'
  40. ).with_args(module.HANDLER_IDENTIFIER, ping_body_limit, monitoring_log_level).once()
  41. module.initialize_monitor(
  42. {'ping_body_limit': ping_body_limit}, {}, 'test.yaml', monitoring_log_level, dry_run=False
  43. )
  44. def test_initialize_monitor_creates_log_handler_when_send_logs_true():
  45. mock_logger()
  46. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  47. 'Forgetful_buffering_handler'
  48. ).once()
  49. module.initialize_monitor(
  50. {'send_logs': True}, {}, 'test.yaml', monitoring_log_level=1, dry_run=False
  51. )
  52. def test_initialize_monitor_bails_when_send_logs_false():
  53. mock_logger()
  54. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  55. 'Forgetful_buffering_handler'
  56. ).never()
  57. module.initialize_monitor(
  58. {'send_logs': False}, {}, 'test.yaml', monitoring_log_level=1, dry_run=False
  59. )
  60. def test_ping_monitor_hits_ping_url_for_start_state():
  61. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  62. 'Forgetful_buffering_handler'
  63. ).never()
  64. hook_config = {'ping_url': 'https://example.com'}
  65. flexmock(module.requests).should_receive('post').with_args(
  66. 'https://example.com/start', data=''.encode('utf-8'), verify=True
  67. ).and_return(flexmock(ok=True))
  68. module.ping_monitor(
  69. hook_config,
  70. {},
  71. 'config.yaml',
  72. state=module.monitor.State.START,
  73. monitoring_log_level=1,
  74. dry_run=False,
  75. )
  76. def test_ping_monitor_hits_ping_url_for_finish_state():
  77. hook_config = {'ping_url': 'https://example.com'}
  78. payload = 'data'
  79. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive('get_handler')
  80. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  81. 'format_buffered_logs_for_payload'
  82. ).and_return(payload)
  83. flexmock(module.requests).should_receive('post').with_args(
  84. 'https://example.com', data=payload.encode('utf-8'), verify=True
  85. ).and_return(flexmock(ok=True))
  86. module.ping_monitor(
  87. hook_config,
  88. {},
  89. 'config.yaml',
  90. state=module.monitor.State.FINISH,
  91. monitoring_log_level=1,
  92. dry_run=False,
  93. )
  94. def test_ping_monitor_hits_ping_url_for_fail_state():
  95. hook_config = {'ping_url': 'https://example.com'}
  96. payload = 'data'
  97. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive('get_handler')
  98. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  99. 'format_buffered_logs_for_payload'
  100. ).and_return(payload)
  101. flexmock(module.requests).should_receive('post').with_args(
  102. 'https://example.com/fail', data=payload.encode('utf'), verify=True
  103. ).and_return(flexmock(ok=True))
  104. module.ping_monitor(
  105. hook_config,
  106. {},
  107. 'config.yaml',
  108. state=module.monitor.State.FAIL,
  109. monitoring_log_level=1,
  110. dry_run=False,
  111. )
  112. def test_ping_monitor_hits_ping_url_for_log_state():
  113. hook_config = {'ping_url': 'https://example.com'}
  114. payload = 'data'
  115. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive('get_handler')
  116. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  117. 'format_buffered_logs_for_payload'
  118. ).and_return(payload)
  119. flexmock(module.requests).should_receive('post').with_args(
  120. 'https://example.com/log', data=payload.encode('utf'), verify=True
  121. ).and_return(flexmock(ok=True))
  122. module.ping_monitor(
  123. hook_config,
  124. {},
  125. 'config.yaml',
  126. state=module.monitor.State.LOG,
  127. monitoring_log_level=1,
  128. dry_run=False,
  129. )
  130. def test_ping_monitor_with_ping_uuid_hits_corresponding_url():
  131. hook_config = {'ping_url': 'abcd-efgh-ijkl-mnop'}
  132. payload = 'data'
  133. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive('get_handler')
  134. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  135. 'format_buffered_logs_for_payload'
  136. ).and_return(payload)
  137. flexmock(module.requests).should_receive('post').with_args(
  138. f"https://hc-ping.com/{hook_config['ping_url']}",
  139. data=payload.encode('utf-8'),
  140. verify=True,
  141. ).and_return(flexmock(ok=True))
  142. module.ping_monitor(
  143. hook_config,
  144. {},
  145. 'config.yaml',
  146. state=module.monitor.State.FINISH,
  147. monitoring_log_level=1,
  148. dry_run=False,
  149. )
  150. def test_ping_monitor_skips_ssl_verification_when_verify_tls_false():
  151. hook_config = {'ping_url': 'https://example.com', 'verify_tls': False}
  152. payload = 'data'
  153. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive('get_handler')
  154. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  155. 'format_buffered_logs_for_payload'
  156. ).and_return(payload)
  157. flexmock(module.requests).should_receive('post').with_args(
  158. 'https://example.com', data=payload.encode('utf-8'), verify=False
  159. ).and_return(flexmock(ok=True))
  160. module.ping_monitor(
  161. hook_config,
  162. {},
  163. 'config.yaml',
  164. state=module.monitor.State.FINISH,
  165. monitoring_log_level=1,
  166. dry_run=False,
  167. )
  168. def test_ping_monitor_executes_ssl_verification_when_verify_tls_true():
  169. hook_config = {'ping_url': 'https://example.com', 'verify_tls': True}
  170. payload = 'data'
  171. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive('get_handler')
  172. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  173. 'format_buffered_logs_for_payload'
  174. ).and_return(payload)
  175. flexmock(module.requests).should_receive('post').with_args(
  176. 'https://example.com', data=payload.encode('utf-8'), verify=True
  177. ).and_return(flexmock(ok=True))
  178. module.ping_monitor(
  179. hook_config,
  180. {},
  181. 'config.yaml',
  182. state=module.monitor.State.FINISH,
  183. monitoring_log_level=1,
  184. dry_run=False,
  185. )
  186. def test_ping_monitor_dry_run_does_not_hit_ping_url():
  187. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  188. 'Forgetful_buffering_handler'
  189. ).never()
  190. hook_config = {'ping_url': 'https://example.com'}
  191. flexmock(module.requests).should_receive('post').never()
  192. module.ping_monitor(
  193. hook_config,
  194. {},
  195. 'config.yaml',
  196. state=module.monitor.State.START,
  197. monitoring_log_level=1,
  198. dry_run=True,
  199. )
  200. def test_ping_monitor_does_not_hit_ping_url_when_states_not_matching():
  201. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  202. 'Forgetful_buffering_handler'
  203. ).never()
  204. hook_config = {'ping_url': 'https://example.com', 'states': ['finish']}
  205. flexmock(module.requests).should_receive('post').never()
  206. module.ping_monitor(
  207. hook_config,
  208. {},
  209. 'config.yaml',
  210. state=module.monitor.State.START,
  211. monitoring_log_level=1,
  212. dry_run=True,
  213. )
  214. def test_ping_monitor_hits_ping_url_when_states_matching():
  215. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  216. 'Forgetful_buffering_handler'
  217. ).never()
  218. hook_config = {'ping_url': 'https://example.com', 'states': ['start', 'finish']}
  219. flexmock(module.requests).should_receive('post').with_args(
  220. 'https://example.com/start', data=''.encode('utf-8'), verify=True
  221. ).and_return(flexmock(ok=True))
  222. module.ping_monitor(
  223. hook_config,
  224. {},
  225. 'config.yaml',
  226. state=module.monitor.State.START,
  227. monitoring_log_level=1,
  228. dry_run=False,
  229. )
  230. def test_ping_monitor_adds_create_query_parameter_when_create_slug_true():
  231. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  232. 'Forgetful_buffering_handler'
  233. ).never()
  234. hook_config = {'ping_url': 'https://example.com', 'create_slug': True}
  235. flexmock(module.requests).should_receive('post').with_args(
  236. 'https://example.com/start?create=1', data=''.encode('utf-8'), verify=True
  237. ).and_return(flexmock(ok=True))
  238. module.ping_monitor(
  239. hook_config,
  240. {},
  241. 'config.yaml',
  242. state=module.monitor.State.START,
  243. monitoring_log_level=1,
  244. dry_run=False,
  245. )
  246. def test_ping_monitor_does_not_add_create_query_parameter_when_create_slug_false():
  247. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  248. 'Forgetful_buffering_handler'
  249. ).never()
  250. hook_config = {'ping_url': 'https://example.com', 'create_slug': False}
  251. flexmock(module.requests).should_receive('post').with_args(
  252. 'https://example.com/start', data=''.encode('utf-8'), verify=True
  253. ).and_return(flexmock(ok=True))
  254. module.ping_monitor(
  255. hook_config,
  256. {},
  257. 'config.yaml',
  258. state=module.monitor.State.START,
  259. monitoring_log_level=1,
  260. dry_run=False,
  261. )
  262. def test_ping_monitor_does_not_add_create_query_parameter_when_ping_url_is_uuid():
  263. hook_config = {'ping_url': 'b3611b24-df9c-4d36-9203-fa292820bf2a', 'create_slug': True}
  264. flexmock(module.requests).should_receive('post').with_args(
  265. f"https://hc-ping.com/{hook_config['ping_url']}",
  266. data=''.encode('utf-8'),
  267. verify=True,
  268. ).and_return(flexmock(ok=True))
  269. module.ping_monitor(
  270. hook_config,
  271. {},
  272. 'config.yaml',
  273. state=module.monitor.State.FINISH,
  274. monitoring_log_level=1,
  275. dry_run=False,
  276. )
  277. def test_ping_monitor_issues_warning_when_ping_url_is_uuid_and_create_slug_true():
  278. hook_config = {'ping_url': 'b3611b24-df9c-4d36-9203-fa292820bf2a', 'create_slug': True}
  279. flexmock(module.requests).should_receive('post').and_return(flexmock(ok=True))
  280. flexmock(module.logger).should_receive('warning').once()
  281. module.ping_monitor(
  282. hook_config,
  283. {},
  284. 'config.yaml',
  285. state=module.monitor.State.FINISH,
  286. monitoring_log_level=1,
  287. dry_run=False,
  288. )
  289. def test_ping_monitor_with_connection_error_logs_warning():
  290. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  291. 'Forgetful_buffering_handler'
  292. ).never()
  293. hook_config = {'ping_url': 'https://example.com'}
  294. flexmock(module.requests).should_receive('post').with_args(
  295. 'https://example.com/start', data=''.encode('utf-8'), verify=True
  296. ).and_raise(module.requests.exceptions.ConnectionError)
  297. flexmock(module.logger).should_receive('warning').once()
  298. module.ping_monitor(
  299. hook_config,
  300. {},
  301. 'config.yaml',
  302. state=module.monitor.State.START,
  303. monitoring_log_level=1,
  304. dry_run=False,
  305. )
  306. def test_ping_monitor_with_other_error_logs_warning():
  307. flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
  308. 'Forgetful_buffering_handler'
  309. ).never()
  310. hook_config = {'ping_url': 'https://example.com'}
  311. response = flexmock(ok=False)
  312. response.should_receive('raise_for_status').and_raise(
  313. module.requests.exceptions.RequestException
  314. )
  315. flexmock(module.requests).should_receive('post').with_args(
  316. 'https://example.com/start', data=''.encode('utf-8'), verify=True
  317. ).and_return(response)
  318. flexmock(module.logger).should_receive('warning').once()
  319. module.ping_monitor(
  320. hook_config,
  321. {},
  322. 'config.yaml',
  323. state=module.monitor.State.START,
  324. monitoring_log_level=1,
  325. dry_run=False,
  326. )