diff --git a/PKG-INFO b/PKG-INFO
index 17acbf0..3f500e1 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,25 +1,25 @@
Metadata-Version: 2.1
Name: swh.icinga_plugins
-Version: 0.1.0
+Version: 0.2.0
Summary: Icinga plugins for Software Heritage infrastructure monitoring
Home-page: https://forge.softwareheritage.org/diffusion/swh-icinga-plugins
Author: Software Heritage developers
Author-email: swh-devel@inria.fr
License: UNKNOWN
Project-URL: Bug Reports, https://forge.softwareheritage.org/maniphest
Project-URL: Funding, https://www.softwareheritage.org/donate
Project-URL: Source, https://forge.softwareheritage.org/source/swh-icinga-plugins
Description: swh-icinga-plugins
==================
Scripts for end-to-end monitoring of the SWH infrastructure
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 3 - Alpha
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Provides-Extra: testing
diff --git a/requirements-swh.txt b/requirements-swh.txt
index 8ec47d2..95a7c77 100644
--- a/requirements-swh.txt
+++ b/requirements-swh.txt
@@ -1,3 +1,3 @@
swh.core[http] >= 0.3
-swh.deposit
-swh.storage >= v0.0.162
+swh.deposit >= 0.3
+swh.storage >= 0.0.162
diff --git a/swh.icinga_plugins.egg-info/PKG-INFO b/swh.icinga_plugins.egg-info/PKG-INFO
index 1bdbb68..86b613b 100644
--- a/swh.icinga_plugins.egg-info/PKG-INFO
+++ b/swh.icinga_plugins.egg-info/PKG-INFO
@@ -1,25 +1,25 @@
Metadata-Version: 2.1
Name: swh.icinga-plugins
-Version: 0.1.0
+Version: 0.2.0
Summary: Icinga plugins for Software Heritage infrastructure monitoring
Home-page: https://forge.softwareheritage.org/diffusion/swh-icinga-plugins
Author: Software Heritage developers
Author-email: swh-devel@inria.fr
License: UNKNOWN
Project-URL: Bug Reports, https://forge.softwareheritage.org/maniphest
Project-URL: Funding, https://www.softwareheritage.org/donate
Project-URL: Source, https://forge.softwareheritage.org/source/swh-icinga-plugins
Description: swh-icinga-plugins
==================
Scripts for end-to-end monitoring of the SWH infrastructure
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 3 - Alpha
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Provides-Extra: testing
diff --git a/swh.icinga_plugins.egg-info/requires.txt b/swh.icinga_plugins.egg-info/requires.txt
index 714c3c9..ac6f964 100644
--- a/swh.icinga_plugins.egg-info/requires.txt
+++ b/swh.icinga_plugins.egg-info/requires.txt
@@ -1,10 +1,10 @@
psycopg2
requests
swh.core[http]>=0.3
-swh.deposit
-swh.storage>=v0.0.162
+swh.deposit>=0.3
+swh.storage>=0.0.162
[testing]
pytest
pytest-mock
requests-mock
diff --git a/swh/icinga_plugins/cli.py b/swh/icinga_plugins/cli.py
index 26ce1fa..46017c3 100644
--- a/swh/icinga_plugins/cli.py
+++ b/swh/icinga_plugins/cli.py
@@ -1,103 +1,104 @@
# Copyright (C) 2019-2020 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
# WARNING: do not import unnecessary things here to keep cli startup time under
# control
import sys
import click
-from swh.core.cli import CONTEXT_SETTINGS, swh as swh_cli_group
+from swh.core.cli import CONTEXT_SETTINGS
+from swh.core.cli import swh as swh_cli_group
@swh_cli_group.group(name="icinga_plugins", context_settings=CONTEXT_SETTINGS)
@click.option("-w", "--warning", type=int, help="Warning threshold.")
@click.option("-c", "--critical", type=int, help="Critical threshold.")
@click.pass_context
def icinga_cli_group(ctx, warning, critical):
"""Main command for Icinga plugins
"""
ctx.ensure_object(dict)
if warning:
ctx.obj["warning_threshold"] = int(warning)
if critical:
ctx.obj["critical_threshold"] = int(critical)
@icinga_cli_group.group(name="check-vault")
@click.option(
"--swh-storage-url", type=str, required=True, help="URL to an swh-storage HTTP API"
)
@click.option(
"--swh-web-url", type=str, required=True, help="URL to an swh-web instance"
)
@click.option(
"--poll-interval",
type=int,
default=10,
help="Interval (in seconds) between two polls to the API, "
"to check for cooking status.",
)
@click.pass_context
def check_vault(ctx, **kwargs):
ctx.obj.update(kwargs)
@check_vault.command(name="directory")
@click.pass_context
def check_vault_directory(ctx):
"""Picks a random directory, requests its cooking via swh-web,
and waits for completion."""
from .vault import VaultCheck
sys.exit(VaultCheck(ctx.obj).main())
@icinga_cli_group.group(name="check-deposit")
@click.option(
"--server",
type=str,
default="https://deposit.softwareheritage.org/1",
help="URL to the SWORD server to test",
)
@click.option("--username", type=str, required=True, help="Login for the SWORD server")
@click.option(
"--password", type=str, required=True, help="Password for the SWORD server"
)
@click.option(
"--collection",
type=str,
required=True,
help="Software collection to use on the SWORD server",
)
@click.option(
"--poll-interval",
type=int,
default=10,
help="Interval (in seconds) between two polls to the API, "
"to check for ingestion status.",
)
@click.pass_context
def check_deposit(ctx, **kwargs):
ctx.obj.update(kwargs)
@check_deposit.command(name="single")
@click.option(
"--archive", type=click.Path(), required=True, help="Software artefact to upload"
)
@click.option(
"--metadata",
type=click.Path(),
required=True,
help="Metadata file for the software artefact.",
)
@click.pass_context
def check_deposit_single(ctx, **kwargs):
"""Checks the provided archive and metadata file and be deposited."""
from .deposit import DepositCheck
ctx.obj.update(kwargs)
sys.exit(DepositCheck(ctx.obj).main())
diff --git a/swh/icinga_plugins/deposit.py b/swh/icinga_plugins/deposit.py
index 26271c4..e7221ef 100644
--- a/swh/icinga_plugins/deposit.py
+++ b/swh/icinga_plugins/deposit.py
@@ -1,128 +1,181 @@
-# Copyright (C) 2019 The Software Heritage developers
+# Copyright (C) 2019-2020 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
import datetime
import sys
import time
+from typing import Any, Dict, Optional
from swh.deposit.client import PublicApiDepositClient
from .base_check import BaseCheck
class DepositCheck(BaseCheck):
TYPE = "DEPOSIT"
DEFAULT_WARNING_THRESHOLD = 120
DEFAULT_CRITICAL_THRESHOLD = 3600
def __init__(self, obj):
super().__init__(obj)
self._poll_interval = obj["poll_interval"]
self._archive_path = obj["archive"]
self._metadata_path = obj["metadata"]
self._collection = obj["collection"]
+ self._slug: Optional[str] = None
self._client = PublicApiDepositClient(
{
"url": obj["server"],
"auth": {"username": obj["username"], "password": obj["password"]},
}
)
def upload_deposit(self):
+ slug = "check-deposit-%s" % datetime.datetime.now().isoformat()
result = self._client.deposit_create(
archive=self._archive_path,
metadata=self._metadata_path,
collection=self._collection,
in_progress=False,
- slug="check-deposit-%s" % datetime.datetime.now().isoformat(),
+ slug=slug,
)
+ self._slug = slug
self._deposit_id = result["deposit_id"]
return result
+ def update_deposit_with_metadata(self) -> Dict[str, Any]:
+ """Trigger a metadata update on the deposit once it's completed.
+
+ """
+ deposit = self.get_deposit_status()
+ swhid = deposit["deposit_swh_id"]
+ assert deposit["deposit_id"] == self._deposit_id
+
+ # We can reuse the initial metadata file we already sent
+ return self._client.deposit_update(
+ self._collection,
+ self._deposit_id,
+ self._slug,
+ metadata=self._metadata_path,
+ swhid=swhid,
+ )
+
def get_deposit_status(self):
return self._client.deposit_status(
collection=self._collection, deposit_id=self._deposit_id
)
def wait_while_status(self, statuses, start_time, metrics, result):
while result["deposit_status"] in statuses:
metrics["total_time"] = time.time() - start_time
if metrics["total_time"] > self.critical_threshold:
self.print_result(
"CRITICAL",
f"Timed out while in status "
f'{result["deposit_status"]} '
f'({metrics["total_time"]}s seconds since deposit '
f"started)",
**metrics,
)
sys.exit(2)
time.sleep(self._poll_interval)
result = self.get_deposit_status()
return result
def main(self):
start_time = time.time()
metrics = {}
# Upload the archive and metadata
result = self.upload_deposit()
metrics["upload_time"] = time.time() - start_time
# Wait for validation
result = self.wait_while_status(["deposited"], start_time, metrics, result)
metrics["total_time"] = time.time() - start_time
metrics["validation_time"] = metrics["total_time"] - metrics["upload_time"]
# Check validation succeeded
if result["deposit_status"] == "rejected":
self.print_result(
"CRITICAL",
f'Deposit was rejected: {result["deposit_status_detail"]}',
**metrics,
)
return 2
# Wait for loading
result = self.wait_while_status(
["verified", "loading"], start_time, metrics, result
)
metrics["total_time"] = time.time() - start_time
metrics["load_time"] = (
metrics["total_time"] - metrics["upload_time"] - metrics["validation_time"]
)
# Check loading succeeded
if result["deposit_status"] == "failed":
self.print_result(
"CRITICAL",
f'Deposit loading failed: {result["deposit_status_detail"]}',
**metrics,
)
return 2
# Check for unexpected status
if result["deposit_status"] != "done":
self.print_result(
"CRITICAL",
f'Deposit got unexpected status: {result["deposit_status"]} '
f'({result["deposit_status_detail"]})',
**metrics,
)
return 2
# Everything went fine, check total time wasn't too large and
# print result
(status_code, status) = self.get_status(metrics["total_time"])
self.print_result(
status,
f'Deposit took {metrics["total_time"]:.2f}s and succeeded.',
**metrics,
)
+
+ if status_code != 0: # Stop if any problem in the initial scenario
+ return status_code
+
+ # Initial deposit is now completed, now we can update the deposit with metadata
+ result = self.update_deposit_with_metadata()
+ total_time = time.time() - start_time
+ metrics_update = {
+ "total_time": total_time,
+ "update_time": (
+ total_time
+ - metrics["upload_time"]
+ - metrics["validation_time"]
+ - metrics["load_time"]
+ ),
+ }
+
+ if "error" in result:
+ self.print_result(
+ "CRITICAL",
+ f'Deposit Metadata update failed: {result["error"]} ',
+ **metrics_update,
+ )
+ return 2
+
+ (status_code, status) = self.get_status(metrics_update["total_time"])
+ self.print_result(
+ status,
+ f'Deposit Metadata update took {metrics_update["update_time"]:.2f}s '
+ "and succeeded.",
+ **metrics_update,
+ )
return status_code
diff --git a/swh/icinga_plugins/tests/test_deposit.py b/swh/icinga_plugins/tests/test_deposit.py
index de4327c..d7d8b5b 100644
--- a/swh/icinga_plugins/tests/test_deposit.py
+++ b/swh/icinga_plugins/tests/test_deposit.py
@@ -1,467 +1,621 @@
-# Copyright (C) 2019 The Software Heritage developers
+# Copyright (C) 2019-2020 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
import io
import os
import tarfile
import time
+from typing import Optional
from click.testing import CliRunner
import pytest
from swh.icinga_plugins.cli import icinga_cli_group
from .web_scenario import WebScenario
BASE_URL = "http://swh-deposit.example.org/1"
COMMON_OPTIONS = [
"--server",
BASE_URL,
"--username",
"test",
"--password",
"test",
"--collection",
"testcol",
]
SAMPLE_METADATA = """
Test Software
swh
test-software
No One
"""
ENTRY_TEMPLATE = """
42
2019-12-19 18:11:00
foo.tar.gz
{status}
http://purl.org/net/sword/package/SimpleZip
"""
STATUS_TEMPLATE = """
42
{status}
- {status_detail}
+ {status_detail}%s
"""
+def status_template(
+ status: str, status_detail: str = "", swhid: Optional[str] = None
+) -> str:
+ """Generate a proper status template out of status, status_detail and optional swhid
+
+ """
+ if swhid is not None:
+ template = STATUS_TEMPLATE % f"\n {swhid}"
+ return template.format(status=status, status_detail=status_detail, swhid=swhid)
+ template = STATUS_TEMPLATE % ""
+ return template.format(status=status, status_detail=status_detail)
+
+
+def test_status_template():
+ actual_status = status_template(status="deposited")
+ assert (
+ actual_status
+ == """
+
+ 42
+ deposited
+
+
+"""
+ )
+
+ actual_status = status_template(status="verified", status_detail="detail")
+ assert (
+ actual_status
+ == """
+
+ 42
+ verified
+ detail
+
+"""
+ )
+
+ actual_status = status_template(status="done", swhid="10")
+ assert (
+ actual_status
+ == """
+
+ 42
+ done
+
+ 10
+
+"""
+ )
+
+
@pytest.fixture(scope="session")
def tmp_path(tmp_path_factory):
return tmp_path_factory.mktemp(__name__)
@pytest.fixture(scope="session")
def sample_metadata(tmp_path):
"""Returns a sample metadata file's path
"""
path = os.path.join(tmp_path, "metadata.xml")
with open(path, "w") as fd:
fd.write(SAMPLE_METADATA)
return path
@pytest.fixture(scope="session")
def sample_archive(tmp_path):
"""Returns a sample archive's path
"""
path = os.path.join(tmp_path, "archive.tar.gz")
with tarfile.open(path, "w:gz") as tf:
tf.addfile(tarfile.TarInfo("hello.py"), io.BytesIO(b'print("Hello world")'))
return path
def invoke(args, catch_exceptions=False):
runner = CliRunner()
result = runner.invoke(icinga_cli_group, args)
if not catch_exceptions and result.exception:
print(result.output)
raise result.exception
return result
def test_deposit_immediate_success(
requests_mock, mocker, sample_archive, sample_metadata, mocked_time
):
+ """Both deposit creation and deposit metadata update passed without delays
+
+ """
scenario = WebScenario()
+ status_xml = status_template(
+ status="done",
+ status_detail="",
+ swhid="swh:1:dir:02ed6084fb0e8384ac58980e07548a547431cf74",
+ )
+
+ # Initial deposit
scenario.add_step(
- "post", BASE_URL + "/testcol/", ENTRY_TEMPLATE.format(status="done")
+ "post", f"{BASE_URL}/testcol/", ENTRY_TEMPLATE.format(status="done")
+ )
+ # Then metadata update
+ status_xml = status_template(
+ status="done",
+ status_detail="",
+ swhid="swh:1:dir:02ed6084fb0e8384ac58980e07548a547431cf74",
+ )
+ scenario.add_step("get", f"{BASE_URL}/testcol/42/status/", status_xml)
+ # internal deposit client does call status, then update metadata then status api
+ scenario.add_step(
+ "get", f"{BASE_URL}/testcol/42/status/", status_xml,
+ )
+ scenario.add_step(
+ "put", f"{BASE_URL}/testcol/42/metadata/", status_xml,
+ )
+ scenario.add_step(
+ "get", f"{BASE_URL}/testcol/42/status/", status_xml,
)
scenario.install_mock(requests_mock)
result = invoke(
[
"check-deposit",
*COMMON_OPTIONS,
"single",
"--archive",
sample_archive,
"--metadata",
sample_metadata,
]
)
assert result.output == (
"DEPOSIT OK - Deposit took 0.00s and succeeded.\n"
"| 'load_time' = 0.00s\n"
"| 'total_time' = 0.00s\n"
"| 'upload_time' = 0.00s\n"
"| 'validation_time' = 0.00s\n"
+ "DEPOSIT OK - Deposit Metadata update took 0.00s and succeeded.\n"
+ "| 'total_time' = 0.00s\n"
+ "| 'update_time' = 0.00s\n"
)
- assert result.exit_code == 0, result.output
+ assert result.exit_code == 0, f"Unexpected output: {result.output}"
def test_deposit_delays(
requests_mock, mocker, sample_archive, sample_metadata, mocked_time
):
+ """Deposit creation passed with some delays, deposit metadata update passed without
+ delay
+
+ """
scenario = WebScenario()
scenario.add_step(
- "post", BASE_URL + "/testcol/", ENTRY_TEMPLATE.format(status="deposited")
+ "post", f"{BASE_URL}/testcol/", ENTRY_TEMPLATE.format(status="deposited")
)
scenario.add_step(
- "get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="verified", status_detail=""),
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="verified"),
)
scenario.add_step(
- "get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="loading", status_detail=""),
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="loading"),
)
scenario.add_step(
- "get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="done", status_detail=""),
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="done"),
+ )
+ # Then metadata update
+ status_xml = status_template(
+ status="done",
+ status_detail="",
+ swhid="swh:1:dir:02ed6084fb0e8384ac58980e07548a547431cf74",
+ )
+ scenario.add_step("get", f"{BASE_URL}/testcol/42/status/", status_xml)
+ # internal deposit client does call status, then update metadata then status api
+ scenario.add_step(
+ "get", f"{BASE_URL}/testcol/42/status/", status_xml,
+ )
+ scenario.add_step(
+ "put", f"{BASE_URL}/testcol/42/metadata/", status_xml,
+ )
+ scenario.add_step(
+ "get", f"{BASE_URL}/testcol/42/status/", status_xml,
)
scenario.install_mock(requests_mock)
result = invoke(
[
"check-deposit",
*COMMON_OPTIONS,
"single",
"--archive",
sample_archive,
"--metadata",
sample_metadata,
]
)
assert result.output == (
"DEPOSIT OK - Deposit took 30.00s and succeeded.\n"
"| 'load_time' = 20.00s\n"
"| 'total_time' = 30.00s\n"
"| 'upload_time' = 0.00s\n"
"| 'validation_time' = 10.00s\n"
+ "DEPOSIT OK - Deposit Metadata update took 0.00s and succeeded.\n"
+ "| 'total_time' = 30.00s\n"
+ "| 'update_time' = 0.00s\n"
+ )
+ assert result.exit_code == 0, f"Unexpected output: {result.output}"
+
+
+def test_deposit_then_metadata_update_failed(
+ requests_mock, mocker, sample_archive, sample_metadata, mocked_time
+):
+ """Deposit creation passed, deposit metadata update failed
+
+ """
+ scenario = WebScenario()
+
+ scenario.add_step(
+ "post", f"{BASE_URL}/testcol/", ENTRY_TEMPLATE.format(status="deposited")
+ )
+ scenario.add_step(
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="verified"),
)
- assert result.exit_code == 0, result.output
+ scenario.add_step(
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="loading"),
+ )
+ scenario.add_step(
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="done"),
+ )
+ # Then metadata update calls
+ failed_status_xml = status_template(
+ status="failed", # lying here
+ status_detail="Failure to ingest",
+ swhid="swh:1:dir:02ed6084fb0e8384ac58980e07548a547431cf74",
+ )
+ scenario.add_step("get", f"{BASE_URL}/testcol/42/status/", failed_status_xml)
+ scenario.add_step("get", f"{BASE_URL}/testcol/42/status/", failed_status_xml)
+
+ scenario.install_mock(requests_mock)
+
+ result = invoke(
+ [
+ "check-deposit",
+ *COMMON_OPTIONS,
+ "single",
+ "--archive",
+ sample_archive,
+ "--metadata",
+ sample_metadata,
+ ],
+ catch_exceptions=True,
+ )
+
+ assert result.output == (
+ "DEPOSIT OK - Deposit took 30.00s and succeeded.\n"
+ "| 'load_time' = 20.00s\n"
+ "| 'total_time' = 30.00s\n"
+ "| 'upload_time' = 0.00s\n"
+ "| 'validation_time' = 10.00s\n"
+ "DEPOSIT CRITICAL - Deposit Metadata update failed: You can only update "
+ "metadata on deposit with status 'done' \n"
+ "| 'total_time' = 30.00s\n"
+ "| 'update_time' = 0.00s\n"
+ )
+ assert result.exit_code == 2, f"Unexpected output: {result.output}"
def test_deposit_delay_warning(
requests_mock, mocker, sample_archive, sample_metadata, mocked_time
):
+ """Deposit creation exceeded delays, no deposit update occurred.
+
+ """
scenario = WebScenario()
scenario.add_step(
- "post", BASE_URL + "/testcol/", ENTRY_TEMPLATE.format(status="deposited")
+ "post", f"{BASE_URL}/testcol/", ENTRY_TEMPLATE.format(status="deposited")
)
scenario.add_step(
- "get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="verified", status_detail=""),
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="verified"),
)
scenario.add_step(
- "get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="done", status_detail=""),
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="done"),
)
scenario.install_mock(requests_mock)
result = invoke(
[
"--warning",
"15",
"check-deposit",
*COMMON_OPTIONS,
"single",
"--archive",
sample_archive,
"--metadata",
sample_metadata,
],
catch_exceptions=True,
)
assert result.output == (
"DEPOSIT WARNING - Deposit took 20.00s and succeeded.\n"
"| 'load_time' = 10.00s\n"
"| 'total_time' = 20.00s\n"
"| 'upload_time' = 0.00s\n"
"| 'validation_time' = 10.00s\n"
)
- assert result.exit_code == 1, result.output
+ assert result.exit_code == 1, f"Unexpected output: {result.output}"
def test_deposit_delay_critical(
requests_mock, mocker, sample_archive, sample_metadata, mocked_time
):
scenario = WebScenario()
scenario.add_step(
- "post", BASE_URL + "/testcol/", ENTRY_TEMPLATE.format(status="deposited")
+ "post", f"{BASE_URL}/testcol/", ENTRY_TEMPLATE.format(status="deposited")
)
scenario.add_step(
- "get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="verified", status_detail=""),
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="verified"),
)
scenario.add_step(
"get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="done", status_detail=""),
+ f"{BASE_URL}/testcol/42/status/",
+ status_template(status="done"),
callback=lambda: time.sleep(60),
)
scenario.install_mock(requests_mock)
result = invoke(
[
"--critical",
"50",
"check-deposit",
*COMMON_OPTIONS,
"single",
"--archive",
sample_archive,
"--metadata",
sample_metadata,
],
catch_exceptions=True,
)
assert result.output == (
"DEPOSIT CRITICAL - Deposit took 80.00s and succeeded.\n"
"| 'load_time' = 70.00s\n"
"| 'total_time' = 80.00s\n"
"| 'upload_time' = 0.00s\n"
"| 'validation_time' = 10.00s\n"
)
- assert result.exit_code == 2, result.output
+ assert result.exit_code == 2, f"Unexpected output: {result.output}"
def test_deposit_timeout(
requests_mock, mocker, sample_archive, sample_metadata, mocked_time
):
scenario = WebScenario()
scenario.add_step(
"post",
- BASE_URL + "/testcol/",
+ f"{BASE_URL}/testcol/",
ENTRY_TEMPLATE.format(status="deposited"),
callback=lambda: time.sleep(1500),
)
scenario.add_step(
"get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="verified", status_detail=""),
+ f"{BASE_URL}/testcol/42/status/",
+ status_template(status="verified"),
callback=lambda: time.sleep(1500),
)
scenario.add_step(
"get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="loading", status_detail=""),
+ f"{BASE_URL}/testcol/42/status/",
+ status_template(status="loading"),
callback=lambda: time.sleep(1500),
)
scenario.install_mock(requests_mock)
result = invoke(
[
"check-deposit",
*COMMON_OPTIONS,
"single",
"--archive",
sample_archive,
"--metadata",
sample_metadata,
],
catch_exceptions=True,
)
assert result.output == (
"DEPOSIT CRITICAL - Timed out while in status loading "
"(4520.0s seconds since deposit started)\n"
"| 'total_time' = 4520.00s\n"
"| 'upload_time' = 1500.00s\n"
"| 'validation_time' = 1510.00s\n"
)
- assert result.exit_code == 2, result.output
+ assert result.exit_code == 2, f"Unexpected output: {result.output}"
def test_deposit_rejected(
requests_mock, mocker, sample_archive, sample_metadata, mocked_time
):
scenario = WebScenario()
scenario.add_step(
- "post", BASE_URL + "/testcol/", ENTRY_TEMPLATE.format(status="deposited")
+ "post", f"{BASE_URL}/testcol/", ENTRY_TEMPLATE.format(status="deposited")
)
scenario.add_step(
"get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="rejected", status_detail="booo"),
+ f"{BASE_URL}/testcol/42/status/",
+ status_template(status="rejected", status_detail="booo"),
)
scenario.install_mock(requests_mock)
result = invoke(
[
"check-deposit",
*COMMON_OPTIONS,
"single",
"--archive",
sample_archive,
"--metadata",
sample_metadata,
],
catch_exceptions=True,
)
assert result.output == (
"DEPOSIT CRITICAL - Deposit was rejected: booo\n"
"| 'total_time' = 10.00s\n"
"| 'upload_time' = 0.00s\n"
"| 'validation_time' = 10.00s\n"
)
- assert result.exit_code == 2, result.output
+ assert result.exit_code == 2, f"Unexpected output: {result.output}"
def test_deposit_failed(
requests_mock, mocker, sample_archive, sample_metadata, mocked_time
):
scenario = WebScenario()
scenario.add_step(
- "post", BASE_URL + "/testcol/", ENTRY_TEMPLATE.format(status="deposited")
+ "post", f"{BASE_URL}/testcol/", ENTRY_TEMPLATE.format(status="deposited")
)
scenario.add_step(
- "get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="verified", status_detail=""),
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="verified"),
)
scenario.add_step(
- "get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="loading", status_detail=""),
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="loading"),
)
scenario.add_step(
"get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="failed", status_detail="booo"),
+ f"{BASE_URL}/testcol/42/status/",
+ status_template(status="failed", status_detail="booo"),
)
scenario.install_mock(requests_mock)
result = invoke(
[
"check-deposit",
*COMMON_OPTIONS,
"single",
"--archive",
sample_archive,
"--metadata",
sample_metadata,
],
catch_exceptions=True,
)
assert result.output == (
"DEPOSIT CRITICAL - Deposit loading failed: booo\n"
"| 'load_time' = 20.00s\n"
"| 'total_time' = 30.00s\n"
"| 'upload_time' = 0.00s\n"
"| 'validation_time' = 10.00s\n"
)
- assert result.exit_code == 2, result.output
+ assert result.exit_code == 2, f"Unexpected output: {result.output}"
def test_deposit_unexpected_status(
requests_mock, mocker, sample_archive, sample_metadata, mocked_time
):
scenario = WebScenario()
scenario.add_step(
- "post", BASE_URL + "/testcol/", ENTRY_TEMPLATE.format(status="deposited")
+ "post", f"{BASE_URL}/testcol/", ENTRY_TEMPLATE.format(status="deposited")
)
scenario.add_step(
- "get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="verified", status_detail=""),
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="verified"),
)
scenario.add_step(
- "get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="loading", status_detail=""),
+ "get", f"{BASE_URL}/testcol/42/status/", status_template(status="loading"),
)
scenario.add_step(
"get",
- BASE_URL + "/testcol/42/status/",
- STATUS_TEMPLATE.format(status="what", status_detail="booo"),
+ f"{BASE_URL}/testcol/42/status/",
+ status_template(status="what", status_detail="booo"),
)
scenario.install_mock(requests_mock)
result = invoke(
[
"check-deposit",
*COMMON_OPTIONS,
"single",
"--archive",
sample_archive,
"--metadata",
sample_metadata,
],
catch_exceptions=True,
)
assert result.output == (
"DEPOSIT CRITICAL - Deposit got unexpected status: what (booo)\n"
"| 'load_time' = 20.00s\n"
"| 'total_time' = 30.00s\n"
"| 'upload_time' = 0.00s\n"
"| 'validation_time' = 10.00s\n"
)
- assert result.exit_code == 2, result.output
+ assert result.exit_code == 2, f"Unexpected output: {result.output}"
diff --git a/tox.ini b/tox.ini
index 041cd4a..69383cb 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,34 +1,34 @@
[tox]
envlist=black,flake8,mypy,py3
[testenv:py3]
deps =
.[testing]
pytest-cov
commands =
pytest --doctest-modules \
{envsitepackagesdir}/swh/icinga_plugins \
--cov={envsitepackagesdir}/swh/icinga_plugins \
--cov-branch {posargs}
[testenv:black]
skip_install = true
deps =
- black
+ black==19.10b0
commands =
{envpython} -m black --check swh
[testenv:flake8]
skip_install = true
deps =
flake8
commands =
{envpython} -m flake8
[testenv:mypy]
skip_install = true
deps =
.[testing]
mypy
commands =
mypy swh