diff --git a/swh/objstorage/api/server.py b/swh/objstorage/api/server.py --- a/swh/objstorage/api/server.py +++ b/swh/objstorage/api/server.py @@ -255,6 +255,9 @@ % (", ".join(missing_keys),) ) + elif cls == "noop": + raise EnvironmentError("Noop implementations should not be used in production.") + return cfg diff --git a/swh/objstorage/backends/noop.py b/swh/objstorage/backends/noop.py new file mode 100644 --- /dev/null +++ b/swh/objstorage/backends/noop.py @@ -0,0 +1,35 @@ +# Copyright (C) 2021 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 + +from swh.objstorage.objstorage import ObjStorage + + +class NoopObjStorage(ObjStorage): + """Noop objstorage. Basic implementation which does no operations at all. + + Only intended for test purposes to avoid either memory or i/o operations. This + allows swh clients to use the swh stack without having to deal with objstorage + configuration. So users can concentrate on testing the remaining part of the stack + without the objstorage. + + """ + + def check_config(self, *, check_write): + return True + + def __contains__(self, obj_id, *args, **kwargs): + return False + + def add(self, content, obj_id=None, check_presence=True, *args, **kwargs): + pass + + def get(self, obj_id, *args, **kwargs): + return None + + def check(self, obj_id, *args, **kwargs): + pass + + def delete(self, obj_id, *args, **kwargs): + pass diff --git a/swh/objstorage/factory.py b/swh/objstorage/factory.py --- a/swh/objstorage/factory.py +++ b/swh/objstorage/factory.py @@ -1,4 +1,4 @@ -# Copyright (C) 2016-2020 The Software Heritage developers +# Copyright (C) 2016-2021 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 @@ -10,6 +10,7 @@ from swh.objstorage.backends.generator import RandomGeneratorObjStorage from swh.objstorage.backends.http import HTTPReadOnlyObjStorage from swh.objstorage.backends.in_memory import InMemoryObjStorage +from swh.objstorage.backends.noop import NoopObjStorage from swh.objstorage.backends.pathslicing import PathSlicingObjStorage from swh.objstorage.backends.seaweedfs import SeaweedFilerObjStorage from swh.objstorage.multiplexer import MultiplexerObjStorage, StripingObjStorage @@ -26,6 +27,7 @@ "seaweedfs": SeaweedFilerObjStorage, "random": RandomGeneratorObjStorage, "http": HTTPReadOnlyObjStorage, + "noop": NoopObjStorage, } _STORAGE_CLASSES_MISSING = {} diff --git a/swh/objstorage/tests/test_objstorage_noop.py b/swh/objstorage/tests/test_objstorage_noop.py new file mode 100644 --- /dev/null +++ b/swh/objstorage/tests/test_objstorage_noop.py @@ -0,0 +1,13 @@ +# Copyright (C) 2021 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 + +from swh.objstorage.factory import get_objstorage +from swh.objstorage.objstorage import ObjStorage + + +def test_instantiate_noop_objstorage(): + objstorage = get_objstorage(cls="noop") + assert objstorage is not None + assert isinstance(objstorage, ObjStorage) diff --git a/swh/objstorage/tests/test_server.py b/swh/objstorage/tests/test_server.py --- a/swh/objstorage/tests/test_server.py +++ b/swh/objstorage/tests/test_server.py @@ -1,4 +1,4 @@ -# Copyright (C) 2019 The Software Heritage developers +# Copyright (C) 2019-2021 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 @@ -113,3 +113,13 @@ config_path = prepare_config_file(tmpdir, config) cfg = load_and_check_config(config_path) assert cfg == config + + +@pytest.mark.parametrize( + "config", [pytest.param({"objstorage": {"cls": "noop",}}, id="noop",),], +) +def test_load_and_check_config_raise(tmpdir, config): + """pathslicing configuration fine loads ok""" + config_path = prepare_config_file(tmpdir, config) + with pytest.raises(EnvironmentError, match="not be used in production"): + load_and_check_config(config_path)