Allow tempurl times to have units
Specifically, let users add a suffix for seconds, minutes, hours, or days. Change-Id: Ibbe7e5aa8aa8e54935da76109c2ea13fb83bc7ab
This commit is contained in:
parent
7f2649bfb7
commit
defbb4a8f3
@ -1381,14 +1381,16 @@ Positional arguments:
|
||||
<method> An HTTP method to allow for this temporary URL.
|
||||
Usually 'GET' or 'PUT'.
|
||||
<time> The amount of time the temporary URL will be
|
||||
valid. The time can be specified in two ways:
|
||||
an integer representing the time in seconds or an
|
||||
ISO 8601 timestamp in a specific format.
|
||||
If --absolute is passed and time
|
||||
is an integer, the seconds are intepreted as the Unix
|
||||
timestamp when the temporary URL will expire. The ISO
|
||||
8601 timestamp can be specified in one of following
|
||||
formats:
|
||||
valid. The time can be specified in three ways:
|
||||
an integer representing the time in seconds;
|
||||
a number with a 's', 'm', 'h', or 'd' suffix to specify
|
||||
the time in seconds, minutes, hours, or days; or
|
||||
an ISO 8601 timestamp in a specific format.
|
||||
If --absolute is passed and time is an integer, the
|
||||
seconds are intepreted as the Unix timestamp when the
|
||||
temporary URL will expire.
|
||||
The ISO 8601 timestamp can be specified in one of
|
||||
following formats:
|
||||
|
||||
i) Complete date: YYYY-MM-DD (eg 1997-07-16)
|
||||
|
||||
|
@ -70,40 +70,7 @@ def prt_bytes(num_bytes, human_flag):
|
||||
return '%.1f%s' % (num, suffix)
|
||||
|
||||
|
||||
def generate_temp_url(path, seconds, key, method, absolute=False,
|
||||
prefix=False, iso8601=False, ip_range=None,
|
||||
digest='sha256'):
|
||||
"""Generates a temporary URL that gives unauthenticated access to the
|
||||
Swift object.
|
||||
|
||||
:param path: The full path to the Swift object or prefix if
|
||||
a prefix-based temporary URL should be generated. Example:
|
||||
/v1/AUTH_account/c/o or /v1/AUTH_account/c/prefix.
|
||||
:param seconds: time in seconds or ISO 8601 timestamp.
|
||||
If absolute is False and this is the string representation of an
|
||||
integer, then this specifies the amount of time in seconds for which
|
||||
the temporary URL will be valid.
|
||||
If absolute is True then this specifies an absolute time at which the
|
||||
temporary URL will expire.
|
||||
:param key: The secret temporary URL key set on the Swift
|
||||
cluster. To set a key, run 'swift post -m
|
||||
"Temp-URL-Key: <substitute tempurl key here>"'
|
||||
:param method: A HTTP method, typically either GET or PUT, to allow
|
||||
for this temporary URL.
|
||||
:param absolute: if True then the seconds parameter is interpreted as a
|
||||
Unix timestamp, if seconds represents an integer.
|
||||
:param prefix: if True then a prefix-based temporary URL will be generated.
|
||||
:param iso8601: if True, a URL containing an ISO 8601 UTC timestamp
|
||||
instead of a UNIX timestamp will be created.
|
||||
:param ip_range: if a valid ip range, restricts the temporary URL to the
|
||||
range of ips.
|
||||
:param digest: digest algorithm to use. Must be one of ``sha1``,
|
||||
``sha256``, or ``sha512``.
|
||||
:raises ValueError: if timestamp or path is not in valid format,
|
||||
or if digest is not one of ``sha1``, ``sha256``, or
|
||||
``sha512``.
|
||||
:return: the path portion of a temporary URL
|
||||
"""
|
||||
def parse_timestamp(seconds, absolute=False):
|
||||
try:
|
||||
try:
|
||||
timestamp = float(seconds)
|
||||
@ -127,6 +94,20 @@ def generate_temp_url(path, seconds, key, method, absolute=False,
|
||||
absolute = True
|
||||
break
|
||||
|
||||
if t is None and not absolute:
|
||||
for suffix, multiplier in (
|
||||
('s', 1),
|
||||
('m', 60),
|
||||
('min', 60),
|
||||
('h', 60 * 60),
|
||||
('hr', 60 * 60),
|
||||
('d', 24 * 60 * 60),
|
||||
):
|
||||
if seconds.endswith(suffix):
|
||||
timestamp = t = int(
|
||||
multiplier * float(seconds[:-len(suffix)]))
|
||||
break
|
||||
|
||||
if t is None:
|
||||
raise ValueError()
|
||||
else:
|
||||
@ -137,6 +118,46 @@ def generate_temp_url(path, seconds, key, method, absolute=False,
|
||||
raise ValueError()
|
||||
except ValueError:
|
||||
raise ValueError(TIME_ERRMSG)
|
||||
return timestamp, absolute
|
||||
|
||||
|
||||
def generate_temp_url(path, seconds, key, method, absolute=False,
|
||||
prefix=False, iso8601=False, ip_range=None,
|
||||
digest='sha256'):
|
||||
"""Generates a temporary URL that gives unauthenticated access to the
|
||||
Swift object.
|
||||
|
||||
:param path: The full path to the Swift object or prefix if
|
||||
a prefix-based temporary URL should be generated. Example:
|
||||
/v1/AUTH_account/c/o or /v1/AUTH_account/c/prefix.
|
||||
:param seconds: time in seconds or ISO 8601 timestamp.
|
||||
If absolute is False and this is the string representation of an
|
||||
integer, then this specifies the amount of time in seconds for which
|
||||
the temporary URL will be valid. This may include a suffix to scale
|
||||
the value: 's' for seconds, 'm' (or 'min') for minutes,
|
||||
'h' (or 'hr') for hours, or 'd' for days.
|
||||
If absolute is True then this specifies an absolute time at which the
|
||||
temporary URL will expire.
|
||||
:param key: The secret temporary URL key set on the Swift
|
||||
cluster. To set a key, run 'swift post -m
|
||||
"Temp-URL-Key: <substitute tempurl key here>"'
|
||||
:param method: A HTTP method, typically either GET or PUT, to allow
|
||||
for this temporary URL.
|
||||
:param absolute: if True then the seconds parameter is interpreted as a
|
||||
Unix timestamp, if seconds represents an integer.
|
||||
:param prefix: if True then a prefix-based temporary URL will be generated.
|
||||
:param iso8601: if True, a URL containing an ISO 8601 UTC timestamp
|
||||
instead of a UNIX timestamp will be created.
|
||||
:param ip_range: if a valid ip range, restricts the temporary URL to the
|
||||
range of ips.
|
||||
:param digest: digest algorithm to use. Must be one of ``sha1``,
|
||||
``sha256``, or ``sha512``.
|
||||
:raises ValueError: if timestamp or path is not in valid format,
|
||||
or if digest is not one of ``sha1``, ``sha256``, or
|
||||
``sha512``.
|
||||
:return: the path portion of a temporary URL
|
||||
"""
|
||||
timestamp, absolute = parse_timestamp(seconds, absolute)
|
||||
|
||||
if isinstance(path, bytes):
|
||||
try:
|
||||
|
@ -2037,6 +2037,14 @@ class TestShell(unittest.TestCase):
|
||||
'/v1/AUTH_account/c/o', "60", 'secret_key', 'GET', absolute=False,
|
||||
iso8601=False, prefix=False, ip_range=None, digest='sha256')
|
||||
|
||||
# sanity check that suffixes will just pass through to utils.py
|
||||
argv = ["", "tempurl", "GET", "2d", "/v1/AUTH_account/c/o",
|
||||
"secret_key"]
|
||||
swiftclient.shell.main(argv)
|
||||
temp_url.assert_called_with(
|
||||
'/v1/AUTH_account/c/o', "2d", 'secret_key', 'GET', absolute=False,
|
||||
iso8601=False, prefix=False, ip_range=None, digest='sha256')
|
||||
|
||||
@mock.patch('swiftclient.shell.generate_temp_url', return_value='')
|
||||
def test_temp_url_prefix_based(self, temp_url):
|
||||
argv = ["", "tempurl", "GET", "60", "/v1/AUTH_account/c/",
|
||||
|
@ -122,6 +122,43 @@ class TestPrtBytes(unittest.TestCase):
|
||||
self.assertEqual('1024Y', u.prt_bytes(bytes_, True).lstrip())
|
||||
|
||||
|
||||
class TestParseTimestamp(unittest.TestCase):
|
||||
def test_int(self):
|
||||
self.assertEqual((1234, False), u.parse_timestamp(1234, False))
|
||||
self.assertEqual((3600, False), u.parse_timestamp('3600', False))
|
||||
|
||||
def test_suffixed(self):
|
||||
self.assertEqual((54, False), u.parse_timestamp('54.321s', False))
|
||||
self.assertEqual((int(54.321 * 60), False),
|
||||
u.parse_timestamp('54.321m', False))
|
||||
self.assertEqual((900, False),
|
||||
u.parse_timestamp('15min', False))
|
||||
self.assertEqual((int(54.321 * 60 * 60), False),
|
||||
u.parse_timestamp('54.321h', False))
|
||||
self.assertEqual((7200, False),
|
||||
u.parse_timestamp('2hr', False))
|
||||
self.assertEqual((60 * 60 * 24, False), u.parse_timestamp('1d', False))
|
||||
|
||||
def test_str(self):
|
||||
self.assertEqual((1615852800, True),
|
||||
u.parse_timestamp('2021-03-16T00:00:00Z', False))
|
||||
|
||||
def test_absolute(self):
|
||||
self.assertEqual((1234, True), u.parse_timestamp(1234, True))
|
||||
self.assertEqual((1615852800, True),
|
||||
u.parse_timestamp('2021-03-16T00:00:00Z', True))
|
||||
|
||||
def test_error(self):
|
||||
with self.assertRaises(ValueError):
|
||||
u.parse_timestamp('asdf', False)
|
||||
with self.assertRaises(ValueError):
|
||||
u.parse_timestamp(12.34, False)
|
||||
with self.assertRaises(ValueError):
|
||||
u.parse_timestamp('54.321', True)
|
||||
with self.assertRaises(ValueError):
|
||||
u.parse_timestamp(-1, False)
|
||||
|
||||
|
||||
class TestTempURL(unittest.TestCase):
|
||||
url = '/v1/AUTH_account/c/o'
|
||||
seconds = 3600
|
||||
@ -422,6 +459,7 @@ class TestTempURL(unittest.TestCase):
|
||||
class TestTempURLUnicodePathAndKey(TestTempURL):
|
||||
url = '/v1/\u00e4/c/\u00f3'
|
||||
key = 'k\u00e9y'
|
||||
seconds = '1hr'
|
||||
expected_body = '\n'.join([
|
||||
'GET',
|
||||
'1400003600',
|
||||
@ -432,6 +470,7 @@ class TestTempURLUnicodePathAndKey(TestTempURL):
|
||||
class TestTempURLUnicodePathBytesKey(TestTempURL):
|
||||
url = '/v1/\u00e4/c/\u00f3'
|
||||
key = 'k\u00e9y'.encode('utf-8')
|
||||
seconds = '60m'
|
||||
expected_body = '\n'.join([
|
||||
'GET',
|
||||
'1400003600',
|
||||
|
Loading…
Reference in New Issue
Block a user