Skip to content
This repository was archived by the owner on Sep 12, 2018. It is now read-only.

Commit be5849c

Browse files
committed
Merge pull request #389 from dotcloud/0.7-Cloudfront
Optional cf support
2 parents 3858749 + ba9fb0c commit be5849c

File tree

2 files changed

+65
-11
lines changed

2 files changed

+65
-11
lines changed

docker_registry/drivers/s3.py

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,50 @@
1515
from docker_registry.core import compat
1616
from docker_registry.core import lru
1717

18-
# import gevent.monkey
19-
# gevent.monkey.patch_all()
20-
2118
import logging
19+
import os
20+
import re
21+
import time
2222

23+
import boto.exception
2324
import boto.s3
2425
import boto.s3.connection
2526
import boto.s3.key
2627

2728
logger = logging.getLogger(__name__)
2829

2930

31+
class Cloudfront():
32+
def __init__(self, awsaccess, awssecret, base, keyid, privatekey):
33+
boto.connect_cloudfront(
34+
awsaccess,
35+
awssecret
36+
)
37+
host = re.compile('^https?://([^/]+)').findall(base)
38+
self.dist = boto.cloudfront.distribution.Distribution(domain_name=host)
39+
self.base = base
40+
self.keyid = keyid
41+
self.privatekey = privatekey
42+
try:
43+
self.privatekey = open(privatekey).read()
44+
except Exception:
45+
logger.debug('Passed private key is not readable. Assume string.')
46+
47+
def sign(self, url, expire_time=0):
48+
path = os.path.join(self.base, url)
49+
if expire_time:
50+
expire_time = time.time() + expire_time
51+
return self.dist.create_signed_url(
52+
path,
53+
self.keyid,
54+
private_key_string=self.privatekey,
55+
expire_time=int(expire_time)
56+
)
57+
58+
def pub(self, path):
59+
return os.path.join(self.base, path)
60+
61+
3062
class Storage(coreboto.Base):
3163

3264
def __init__(self, path, config):
@@ -48,6 +80,16 @@ def makeConnection(self):
4880
**kwargs)
4981
logger.warn("No S3 region specified, using boto default region, " +
5082
"this may affect performance and stability.")
83+
# Connect cloudfront if we are required to
84+
if self._config.cloudfront:
85+
self.signer = Cloudfront(
86+
self._config.s3_access_key,
87+
self._config.s3_secret_key,
88+
self._config.cloudfront['base'],
89+
self._config.cloudfront['keyid'],
90+
self._config.cloudfront['keysecret']
91+
).sign
92+
5193
return boto.s3.connection.S3Connection(
5294
self._config.s3_access_key,
5395
self._config.s3_secret_key,
@@ -82,16 +124,22 @@ def stream_write(self, path, fp):
82124
mp.upload_part_from_file(io, num_part)
83125
num_part += 1
84126
io.close()
85-
except IOError:
86-
pass
127+
except IOError as e:
128+
raise e
87129
mp.complete_upload()
88130

89131
def content_redirect_url(self, path):
90132
path = self._init_path(path)
91133
key = self.makeKey(path)
92134
if not key.exists():
93135
raise IOError('No such key: \'{0}\''.format(path))
94-
return key.generate_url(
95-
expires_in=1200,
96-
method='GET',
97-
query_auth=True)
136+
137+
# No cloudfront? Sign to the bucket
138+
if not self.signer:
139+
return key.generate_url(
140+
expires_in=1200,
141+
method='GET',
142+
query_auth=True)
143+
144+
# Have cloudfront? Sign it
145+
return self.signer(path, expire_time=60)

tests/test_s3.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,16 @@ def test_stream_write(self):
6060
content = self.gen_random_string(8 * 1024 * 1024)
6161
io = StringIOWithError(content)
6262
assert not self._storage.exists(filename)
63-
self._storage.stream_write(filename, io)
63+
try:
64+
self._storage.stream_write(filename, io)
65+
except IOError:
66+
pass
6467
assert self._storage.exists(filename)
6568
# Test that EOFed io string throws IOError on lib/storage/s3
66-
self._storage.stream_write(filename, io)
69+
try:
70+
self._storage.stream_write(filename, io)
71+
except IOError:
72+
pass
6773
# Cleanup
6874
io.close()
6975
self._storage.remove(filename)

0 commit comments

Comments
 (0)