From 0ab77c4cd1913b3691de09bcb9b8e7f52e59c633 Mon Sep 17 00:00:00 2001 From: Joshua Lock Date: Fri, 17 Apr 2020 11:03:23 +0100 Subject: [PATCH] Define an interface for storage access Implement an abstract base class (ABC) which defined an abstract interface for storage operations, regardless of backend. The aim is to enable securesystemslib functions to operate as normal on local filesystems by implementing the interface for local filesystem operations within securesystemslib, with users of the library able to provide implementations for use with their storage backend of choice when this is not a local filesystem, i.e. S3 buckets as used by Warehouse for the PEP 458 implementation. For more context see tuf issue #1009: https://github.com/theupdateframework/tuf/issues/1009 Signed-off-by: Joshua Lock --- securesystemslib/exceptions.py | 4 + securesystemslib/storage.py | 150 +++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 securesystemslib/storage.py diff --git a/securesystemslib/exceptions.py b/securesystemslib/exceptions.py index 7aa63674..e847f2a7 100755 --- a/securesystemslib/exceptions.py +++ b/securesystemslib/exceptions.py @@ -121,3 +121,7 @@ class InvalidConfigurationError(Error): """If a configuration object does not match the expected format.""" pass +class StorageError(Error): + """Indicate an error occured during interaction with an abstracted storage + backend.""" + pass diff --git a/securesystemslib/storage.py b/securesystemslib/storage.py new file mode 100644 index 00000000..1b4c3cbb --- /dev/null +++ b/securesystemslib/storage.py @@ -0,0 +1,150 @@ +""" + + storage.py + + + Joshua Lock + + + April 9, 2020 + + + See LICENSE for licensing information. + + + Provides an interface for filesystem interactions, StorageBackendInterface. +""" + +from __future__ import absolute_import +from __future__ import unicode_literals + +import abc +import errno +import logging +import os +import shutil + +import securesystemslib.exceptions + +logger = logging.getLogger(__name__) + + + +class StorageBackendInterface(): + """ + + Defines an interface for abstract storage operations which can be implemented + for a variety of storage solutions, such as remote and local filesystems. + """ + + __metaclass__ = abc.ABCMeta + + + @abc.abstractmethod + def get(self, filepath): + """ + + A context manager for 'with' statements that is used for retrieving files + from a storage backend and cleans up the files upon exit. + + with storage_backend.get('/path/to/file') as file_object: + # operations + # file is now closed + + + filepath: + The full path of the file to be retrieved. + + + securesystemslib.exceptions.StorageError, if the file does not exist or is + no accessible. + + + A ContextManager object that emits a file-like object for the file at + 'filepath'. + """ + raise NotImplementedError # pragma: no cover + + + @abc.abstractmethod + def put(self, fileobj, filepath): + """ + + Store a file-like object in the storage backend. + + + fileobj: + The file-like object to be stored. + + filepath: + The full path to the location where 'fileobj' will be stored. + + + securesystemslib.exceptions.StorageError, if the file can not be stored. + + + None + """ + raise NotImplementedError # pragma: no cover + + + @abc.abstractmethod + def getsize(self, filepath): + """ + + Retrieve the size, in bytes, of the file at 'filepath'. + + + filepath: + The full path to the file. + + + securesystemslib.exceptions.StorageError, if the file does not exist or is + not accessible. + + + The size in bytes of the file at 'filepath'. + """ + raise NotImplementedError # pragma: no cover + + + @abc.abstractmethod + def create_folder(self, filepath): + """ + + Create a folder at filepath and ensure all intermediate components of the + path exist. + + + filepath: + The full path of the folder to be created. + + + securesystemslib.exceptions.StorageError, if the folder can not be + created. + + + None + """ + raise NotImplementedError # pragma: no cover + + + @abc.abstractmethod + def list_folder(self, filepath): + """ + + List the contents of the folder at 'filepath'. + + + filepath: + The full path of the folder to be listed. + + + securesystemslib.exceptions.StorageError, if the file does not exist or is + not accessible. + + + A list containing the names of the files in the folder. May be an empty + list. + """ + raise NotImplementedError # pragma: no cover