Changeset View
Changeset View
Standalone View
Standalone View
swh/icinga_plugins/tests/test_vault.py
# Copyright (C) 2019 The Software Heritage developers | # Copyright (C) 2019 The Software Heritage developers | ||||
# See the AUTHORS file at the top-level directory of this distribution | # See the AUTHORS file at the top-level directory of this distribution | ||||
# License: GNU General Public License version 3, or any later version | # License: GNU General Public License version 3, or any later version | ||||
# See top-level LICENSE file for more information | # See top-level LICENSE file for more information | ||||
import enum | |||||
import json | |||||
import re | import re | ||||
import time | import time | ||||
from click.testing import CliRunner | from click.testing import CliRunner | ||||
from swh.icinga_plugins.cli import cli | from swh.icinga_plugins.cli import cli | ||||
from .web_scenario import WebScenario | |||||
dir_id = 'ab'*20 | dir_id = 'ab'*20 | ||||
response_pending = { | response_pending = { | ||||
"obj_id": dir_id, | "obj_id": dir_id, | ||||
"obj_type": "directory", | "obj_type": "directory", | ||||
"progress_message": "foo", | "progress_message": "foo", | ||||
Show All 29 Lines | def invoke(args, catch_exceptions=False): | ||||
result = runner.invoke(cli, args) | result = runner.invoke(cli, args) | ||||
if not catch_exceptions and result.exception: | if not catch_exceptions and result.exception: | ||||
print(result.output) | print(result.output) | ||||
raise result.exception | raise result.exception | ||||
return result | return result | ||||
def test_vault_immediate_success(requests_mock, mocker): | def test_vault_immediate_success(requests_mock, mocker): | ||||
scenario = WebScenario() | |||||
class Step(enum.Enum): | url = f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/' | ||||
NOTHING_DONE = 0 | |||||
CHECKED_UNCOOKED = 1 | scenario.add_step('get', url, {}, status_code=404) | ||||
REQUESTED_COOKING = 2 | scenario.add_step('post', url, response_pending) | ||||
scenario.add_step('get', url, response_done) | |||||
step = Step.NOTHING_DONE | |||||
scenario.install_mock(requests_mock) | |||||
def post_callback(request, context): | |||||
nonlocal step | |||||
if step == Step.CHECKED_UNCOOKED: | |||||
step = Step.REQUESTED_COOKING | |||||
return json.dumps(response_pending) | |||||
else: | |||||
assert False, step | |||||
def get_callback(request, context): | |||||
context.json = True | |||||
nonlocal step | |||||
if step == Step.NOTHING_DONE: | |||||
context.status_code = 404 | |||||
step = Step.CHECKED_UNCOOKED | |||||
elif step == Step.CHECKED_UNCOOKED: | |||||
assert False | |||||
elif step == Step.REQUESTED_COOKING: | |||||
return json.dumps(response_done) | |||||
else: | |||||
assert False, step | |||||
requests_mock.get( | |||||
f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/', | |||||
text=get_callback) | |||||
requests_mock.post( | |||||
f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/', | |||||
text=post_callback) | |||||
get_storage_mock = mocker.patch('swh.icinga_plugins.vault.get_storage') | get_storage_mock = mocker.patch('swh.icinga_plugins.vault.get_storage') | ||||
get_storage_mock.side_effect = FakeStorage | get_storage_mock.side_effect = FakeStorage | ||||
sleep_mock = mocker.patch('time.sleep') | sleep_mock = mocker.patch('time.sleep') | ||||
result = invoke([ | result = invoke([ | ||||
'--swh-web-url', 'mock://swh-web.example.org', | '--swh-web-url', 'mock://swh-web.example.org', | ||||
'--swh-storage-url', 'foo://example.org', | '--swh-storage-url', 'foo://example.org', | ||||
'check-vault', 'directory', | 'check-vault', 'directory', | ||||
]) | ]) | ||||
assert re.match( | assert re.match( | ||||
rf'VAULT OK - cooking directory {dir_id} took ' | rf'VAULT OK - cooking directory {dir_id} took ' | ||||
r'[0-9]\.[0-9]{2}s and succeeded.\n' | r'[0-9]\.[0-9]{2}s and succeeded.\n' | ||||
r"| 'total time' = [0-9]\.[0-9]{2}s", | r"| 'total time' = [0-9]\.[0-9]{2}s", | ||||
result.output) | result.output) | ||||
assert result.exit_code == 0, result.output | assert result.exit_code == 0, result.output | ||||
sleep_mock.assert_called_once_with(10) | sleep_mock.assert_called_once_with(10) | ||||
def test_vault_delayed_success(requests_mock, mocker): | def test_vault_delayed_success(requests_mock, mocker): | ||||
scenario = WebScenario() | |||||
url = f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/' | |||||
class Step(enum.Enum): | scenario.add_step('get', url, {}, status_code=404) | ||||
NOTHING_DONE = 0 | scenario.add_step('post', url, response_pending) | ||||
CHECKED_UNCOOKED = 1 | scenario.add_step('get', url, response_pending) | ||||
REQUESTED_COOKING = 2 | scenario.add_step('get', url, response_done) | ||||
PENDING = 3 | |||||
scenario.install_mock(requests_mock) | |||||
step = Step.NOTHING_DONE | |||||
def post_callback(request, context): | |||||
nonlocal step | |||||
if step == Step.CHECKED_UNCOOKED: | |||||
step = Step.REQUESTED_COOKING | |||||
return json.dumps(response_pending) | |||||
else: | |||||
assert False, step | |||||
def get_callback(request, context): | |||||
context.json = True | |||||
nonlocal step | |||||
if step == Step.NOTHING_DONE: | |||||
context.status_code = 404 | |||||
step = Step.CHECKED_UNCOOKED | |||||
elif step == Step.CHECKED_UNCOOKED: | |||||
assert False | |||||
elif step == Step.REQUESTED_COOKING: | |||||
step = Step.PENDING | |||||
return json.dumps(response_pending) | |||||
elif step == Step.PENDING: | |||||
return json.dumps(response_done) | |||||
else: | |||||
assert False, step | |||||
requests_mock.get( | |||||
f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/', | |||||
text=get_callback) | |||||
requests_mock.post( | |||||
f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/', | |||||
text=post_callback) | |||||
get_storage_mock = mocker.patch('swh.icinga_plugins.vault.get_storage') | get_storage_mock = mocker.patch('swh.icinga_plugins.vault.get_storage') | ||||
get_storage_mock.side_effect = FakeStorage | get_storage_mock.side_effect = FakeStorage | ||||
sleep_mock = mocker.patch('time.sleep') | sleep_mock = mocker.patch('time.sleep') | ||||
result = invoke([ | result = invoke([ | ||||
'--swh-web-url', 'mock://swh-web.example.org', | '--swh-web-url', 'mock://swh-web.example.org', | ||||
'--swh-storage-url', 'foo://example.org', | '--swh-storage-url', 'foo://example.org', | ||||
'check-vault', 'directory', | 'check-vault', 'directory', | ||||
]) | ]) | ||||
assert re.match( | assert re.match( | ||||
rf'VAULT OK - cooking directory {dir_id} took ' | rf'VAULT OK - cooking directory {dir_id} took ' | ||||
r'[0-9]\.[0-9]{2}s and succeeded.\n' | r'[0-9]\.[0-9]{2}s and succeeded.\n' | ||||
r"| 'total time' = [0-9]\.[0-9]{2}s", | r"| 'total time' = [0-9]\.[0-9]{2}s", | ||||
result.output) | result.output) | ||||
assert result.exit_code == 0, result.output | assert result.exit_code == 0, result.output | ||||
assert sleep_mock.call_count == 2 | assert sleep_mock.call_count == 2 | ||||
def test_vault_failure(requests_mock, mocker): | def test_vault_failure(requests_mock, mocker): | ||||
scenario = WebScenario() | |||||
url = f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/' | |||||
scenario.add_step('get', url, {}, status_code=404) | |||||
scenario.add_step('post', url, response_pending) | |||||
scenario.add_step('get', url, response_failed) | |||||
class Step(enum.Enum): | scenario.install_mock(requests_mock) | ||||
NOTHING_DONE = 0 | |||||
CHECKED_UNCOOKED = 1 | |||||
REQUESTED_COOKING = 2 | |||||
step = Step.NOTHING_DONE | |||||
def post_callback(request, context): | |||||
nonlocal step | |||||
if step == Step.CHECKED_UNCOOKED: | |||||
step = Step.REQUESTED_COOKING | |||||
return json.dumps(response_pending) | |||||
else: | |||||
assert False, step | |||||
def get_callback(request, context): | |||||
context.json = True | |||||
nonlocal step | |||||
if step == Step.NOTHING_DONE: | |||||
context.status_code = 404 | |||||
step = Step.CHECKED_UNCOOKED | |||||
elif step == Step.CHECKED_UNCOOKED: | |||||
assert False | |||||
elif step == Step.REQUESTED_COOKING: | |||||
return json.dumps(response_failed) | |||||
else: | |||||
assert False, step | |||||
requests_mock.get( | |||||
f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/', | |||||
text=get_callback) | |||||
requests_mock.post( | |||||
f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/', | |||||
text=post_callback) | |||||
get_storage_mock = mocker.patch('swh.icinga_plugins.vault.get_storage') | get_storage_mock = mocker.patch('swh.icinga_plugins.vault.get_storage') | ||||
get_storage_mock.side_effect = FakeStorage | get_storage_mock.side_effect = FakeStorage | ||||
sleep_mock = mocker.patch('time.sleep') | sleep_mock = mocker.patch('time.sleep') | ||||
result = invoke([ | result = invoke([ | ||||
'--swh-web-url', 'mock://swh-web.example.org', | '--swh-web-url', 'mock://swh-web.example.org', | ||||
'--swh-storage-url', 'foo://example.org', | '--swh-storage-url', 'foo://example.org', | ||||
'check-vault', 'directory', | 'check-vault', 'directory', | ||||
], catch_exceptions=True) | ], catch_exceptions=True) | ||||
assert re.match( | assert re.match( | ||||
rf'VAULT CRITICAL - cooking directory {dir_id} took ' | rf'VAULT CRITICAL - cooking directory {dir_id} took ' | ||||
r'[0-9]\.[0-9]{2}s and failed with: foobar\n' | r'[0-9]\.[0-9]{2}s and failed with: foobar\n' | ||||
r"| 'total time' = [0-9]\.[0-9]{2}s", | r"| 'total time' = [0-9]\.[0-9]{2}s", | ||||
result.output) | result.output) | ||||
assert result.exit_code == 2, result.output | assert result.exit_code == 2, result.output | ||||
sleep_mock.assert_called_once_with(10) | sleep_mock.assert_called_once_with(10) | ||||
def test_vault_timeout(requests_mock, mocker): | def test_vault_timeout(requests_mock, mocker): | ||||
time_offset = 0 | |||||
def increment_time(): | |||||
nonlocal time_offset | |||||
time_offset += 4000 | |||||
scenario = WebScenario() | |||||
class Step(enum.Enum): | url = f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/' | ||||
NOTHING_DONE = 0 | |||||
CHECKED_UNCOOKED = 1 | scenario.add_step('get', url, {}, status_code=404) | ||||
REQUESTED_COOKING = 2 | scenario.add_step('post', url, response_pending) | ||||
PENDING = 3 | scenario.add_step('get', url, response_pending) | ||||
scenario.add_step('get', url, response_pending, | |||||
step = Step.NOTHING_DONE | callback=increment_time) | ||||
def post_callback(request, context): | scenario.install_mock(requests_mock) | ||||
nonlocal step | |||||
if step == Step.CHECKED_UNCOOKED: | |||||
step = Step.REQUESTED_COOKING | |||||
return json.dumps(response_pending) | |||||
else: | |||||
assert False, step | |||||
def get_callback(request, context): | |||||
context.json = True | |||||
nonlocal step, time_offset | |||||
if step == Step.NOTHING_DONE: | |||||
context.status_code = 404 | |||||
step = Step.CHECKED_UNCOOKED | |||||
elif step == Step.CHECKED_UNCOOKED: | |||||
assert False | |||||
elif step == Step.REQUESTED_COOKING: | |||||
step = Step.PENDING | |||||
return json.dumps(response_pending) | |||||
elif step == Step.PENDING: | |||||
time_offset += 4000 # jump forward in time more than 1h | |||||
return json.dumps(response_pending) | |||||
else: | |||||
assert False, step | |||||
requests_mock.get( | |||||
f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/', | |||||
text=get_callback) | |||||
requests_mock.post( | |||||
f'mock://swh-web.example.org/api/1/vault/directory/{dir_id}/', | |||||
text=post_callback) | |||||
get_storage_mock = mocker.patch('swh.icinga_plugins.vault.get_storage') | get_storage_mock = mocker.patch('swh.icinga_plugins.vault.get_storage') | ||||
get_storage_mock.side_effect = FakeStorage | get_storage_mock.side_effect = FakeStorage | ||||
sleep_mock = mocker.patch('time.sleep') | sleep_mock = mocker.patch('time.sleep') | ||||
real_time = time.time | real_time = time.time | ||||
time_offset = 0 | |||||
mocker.patch( | mocker.patch( | ||||
'time.time', side_effect=lambda: real_time() + time_offset) | 'time.time', side_effect=lambda: real_time() + time_offset) | ||||
result = invoke([ | result = invoke([ | ||||
'--swh-web-url', 'mock://swh-web.example.org', | '--swh-web-url', 'mock://swh-web.example.org', | ||||
'--swh-storage-url', 'foo://example.org', | '--swh-storage-url', 'foo://example.org', | ||||
'check-vault', 'directory', | 'check-vault', 'directory', | ||||
], catch_exceptions=True) | ], catch_exceptions=True) | ||||
Show All 9 Lines |