Skip to content

Commit bef7265

Browse files
committed
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: theupdateframework/python-tuf#1009 Signed-off-by: Joshua Lock <[email protected]>
1 parent 12e8041 commit bef7265

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed

securesystemslib/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,7 @@ class InvalidConfigurationError(Error):
121121
"""If a configuration object does not match the expected format."""
122122
pass
123123

124+
class StorageError(Error):
125+
"""Indicate an error occured during interaction with an abstracted storage
126+
backend."""
127+
pass

securesystemslib/storage.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
"""
2+
<Program Name>
3+
storage.py
4+
5+
<Author>
6+
Joshua Lock <[email protected]>
7+
8+
<Started>
9+
April 9, 2020
10+
11+
<Copyright>
12+
See LICENSE for licensing information.
13+
14+
<Purpose>
15+
Provides an interface for filesystem interactions, StorageBackendInterface.
16+
"""
17+
18+
from __future__ import absolute_import
19+
from __future__ import unicode_literals
20+
21+
import abc
22+
import errno
23+
import logging
24+
import os
25+
import shutil
26+
27+
import securesystemslib.exceptions
28+
29+
logger = logging.getLogger(__name__)
30+
31+
32+
33+
class StorageBackendInterface():
34+
"""
35+
<Purpose>
36+
Defines an interface for abstract storage operations which can be implemented
37+
for a variety of storage solutions, such as remote and local filesystems.
38+
"""
39+
40+
__metaclass__ = abc.ABCMeta
41+
42+
43+
@abc.abstractmethod
44+
def get(self, filepath):
45+
"""
46+
<Purpose>
47+
Retrieve a file from the storage backend.
48+
49+
<Arguments>
50+
filepath:
51+
The full path of the file to be retrieved.
52+
53+
<Exceptions>
54+
securesystemslib.exceptions.StorageError, if the file does not exist or is
55+
no accessible.
56+
57+
<Returns>
58+
A file-like object of the file at 'filepath'.
59+
"""
60+
raise NotImplementedError # pragma: no cover
61+
62+
63+
@abc.abstractmethod
64+
def put(self, fileobj, filepath):
65+
"""
66+
<Purpose>
67+
Store a file-like object in the storage backend.
68+
69+
<Arguments>
70+
fileobj:
71+
The file-like object to be stored.
72+
73+
filepath:
74+
The full path to the location where 'fileobj' will be stored.
75+
76+
<Exceptions>
77+
securesystemslib.exceptions.StorageError, if the file can not be stored.
78+
79+
<Returns>
80+
None
81+
"""
82+
raise NotImplementedError # pragma: no cover
83+
84+
85+
@abc.abstractmethod
86+
def getsize(self, filepath):
87+
"""
88+
<Purpose>
89+
Retrieve the size, in bytes, of the file at 'filepath'.
90+
91+
<Arguments>
92+
filepath:
93+
The full path to the file.
94+
95+
<Exceptions>
96+
securesystemslib.exceptions.StorageError, if the file does not exist or is
97+
not accessible.
98+
99+
<Returns>
100+
The size in bytes of the file at 'filepath'.
101+
"""
102+
raise NotImplementedError # pragma: no cover
103+
104+
105+
@abc.abstractmethod
106+
def create_folder(self, filepath):
107+
"""
108+
<Purpose>
109+
Create a folder at filepath and ensure all intermediate components of the
110+
path exist.
111+
112+
<Arguments>
113+
filepath:
114+
The full path of the folder to be created.
115+
116+
<Exceptions>
117+
securesystemslib.exceptions.StorageError, if the folder can not be
118+
created.
119+
120+
<Returns>
121+
None
122+
"""
123+
raise NotImplementedError # pragma: no cover
124+
125+
126+
@abc.abstractmethod
127+
def list_folder(self, filepath):
128+
"""
129+
<Purpose>
130+
List the contents of the folder at 'filepath'.
131+
132+
<Arguments>
133+
filepath:
134+
The full path of the folder to be listed.
135+
136+
<Exceptions>
137+
securesystemslib.exceptions.StorageError, if the file does not exist or is
138+
not accessible.
139+
140+
<Returns>
141+
A list containing the names of the files in the folder. May be an empty
142+
list.
143+
"""
144+
raise NotImplementedError # pragma: no cover

0 commit comments

Comments
 (0)