Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial support for CloudFront streaming and private distributions.

  • Loading branch information...
commit 0a8ea52553be5ecdee9693a6bf0091a7c3bd9fdf 1 parent 6ee36ce
Mitch.Garnaat authored
View
181 boto/cloudfront/__init__.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/
+# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
@@ -26,14 +26,16 @@
import boto.utils
from boto.connection import AWSAuthConnection
from boto import handler
-from boto.cloudfront.distribution import Distribution, DistributionConfig, DistributionSummary
+from boto.cloudfront.distribution import *
+from boto.cloudfront.identity import OriginAccessIdentity
+from boto.cloudfront.identity import OriginAccessIdentityConfig
from boto.resultset import ResultSet
from boto.cloudfront.exception import CloudFrontServerError
class CloudFrontConnection(AWSAuthConnection):
DefaultHost = 'cloudfront.amazonaws.com'
- Version = '2008-06-30'
+ Version = '2009-12-01'
def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
port=None, proxy=None, proxy_port=None,
@@ -42,22 +44,46 @@ def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
aws_access_key_id, aws_secret_access_key,
True, port, proxy, proxy_port, debug=debug)
- def get_all_distributions(self):
- response = self.make_request('GET', '/%s/distribution' % self.Version)
+ def get_etag(self, response):
+ response_headers = response.msg
+ for key in response_headers.keys():
+ if key.lower() == 'etag':
+ return response_headers[key]
+ return None
+
+ def add_aws_auth_header(self, headers, method, path):
+ if not headers.has_key('Date'):
+ headers['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
+ time.gmtime())
+
+ hmac = self.hmac.copy()
+ hmac.update(headers['Date'])
+ b64_hmac = base64.encodestring(hmac.digest()).strip()
+ headers['Authorization'] = "AWS %s:%s" % (self.aws_access_key_id, b64_hmac)
+
+ # Generics
+
+ def _get_all_objects(self, resource, tags):
+ if not tags:
+ tags=[('DistributionSummary', DistributionSummary)]
+ response = self.make_request('GET', '/%s/%s' % (self.Version, resource))
body = response.read()
+ print body
if response.status >= 300:
raise CloudFrontServerError(response.status, response.reason, body)
- rs = ResultSet([('DistributionSummary', DistributionSummary)])
+ rs = ResultSet(tags)
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
return rs
- def get_distribution_info(self, distribution_id):
- response = self.make_request('GET', '/%s/distribution/%s' % (self.Version, distribution_id))
+ def _get_info(self, id, resource, dist_class):
+ uri = '/%s/%s/%s' % (self.Version, resource, id)
+ response = self.make_request('GET', uri)
body = response.read()
+ print body
if response.status >= 300:
raise CloudFrontServerError(response.status, response.reason, body)
- d = Distribution(connection=self)
+ d = dist_class(connection=self)
response_headers = response.msg
for key in response_headers.keys():
if key.lower() == 'etag':
@@ -66,60 +92,137 @@ def get_distribution_info(self, distribution_id):
xml.sax.parseString(body, h)
return d
- def get_etag(self, response):
- response_headers = response.msg
- for key in response_headers.keys():
- if key.lower() == 'etag':
- return response_headers[key]
- return None
-
- def get_distribution_config(self, distribution_id):
- response = self.make_request('GET', '/%s/distribution/%s/config' % (self.Version, distribution_id))
+ def _get_config(self, id, resource, config_class):
+ uri = '/%s/%s/%s/config' % (self.Version, resource, id)
+ response = self.make_request('GET', uri)
body = response.read()
+ print body
if response.status >= 300:
raise CloudFrontServerError(response.status, response.reason, body)
- d = DistributionConfig(connection=self)
+ d = config_class(connection=self)
d.etag = self.get_etag(response)
h = handler.XmlHandler(d, self)
xml.sax.parseString(body, h)
return d
- def set_distribution_config(self, distribution_id, etag, config):
- response = self.make_request('PUT', '/%s/distribution/%s/config' % (self.Version, distribution_id),
- {'If-Match' : etag, 'Content-Type' : 'text/xml'}, config.to_xml())
+ def _set_config(self, distribution_id, etag, config):
+ if isinstance(config, StreamingDistributionConfig):
+ resource = 'streaming-distribution'
+ else:
+ resource = 'distribution'
+ uri = '/%s/%s/%s/config' % (self.Version, resource, distribution_id)
+ headers = {'If-Match' : etag, 'Content-Type' : 'text/xml'}
+ response = self.make_request('PUT', uri, headers, config.to_xml())
body = response.read()
+ print body
return self.get_etag(response)
if response.status != 200:
raise CloudFrontServerError(response.status, response.reason, body)
- def create_distribution(self, origin, enabled, caller_reference='', cnames=None, comment=''):
- config = DistributionConfig(origin=origin, enabled=enabled,
- caller_reference=caller_reference,
- cnames=cnames, comment=comment)
- response = self.make_request('POST', '/%s/distribution' % self.Version,
+ def _create_object(self, config, resource, dist_class):
+ response = self.make_request('POST', '/%s/%s' % (self.Version, resource),
{'Content-Type' : 'text/xml'}, data=config.to_xml())
body = response.read()
+ print body
if response.status == 201:
- d = Distribution(connection=self)
+ d = dist_class(connection=self)
h = handler.XmlHandler(d, self)
xml.sax.parseString(body, h)
return d
else:
raise CloudFrontServerError(response.status, response.reason, body)
- def delete_distribution(self, distribution_id, etag):
- response = self.make_request('DELETE', '/%s/distribution/%s' % (self.Version, distribution_id),
- {'If-Match' : etag})
+ def _delete_object(self, id, etag, resource):
+ uri = '/%s/%s/%s' % (self.Version, resource, id)
+ response = self.make_request('DELETE', uri, {'If-Match' : etag})
body = response.read()
+ print body
if response.status != 204:
raise CloudFrontServerError(response.status, response.reason, body)
- def add_aws_auth_header(self, headers, method, path):
- if not headers.has_key('Date'):
- headers['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
- time.gmtime())
+ # Distributions
+
+ def get_all_distributions(self):
+ tags=[('DistributionSummary', DistributionSummary)]
+ return self._get_all_objects('distribution', tags)
+
+ def get_distribution_info(self, distribution_id):
+ return self._get_info(distribution_id, 'distribution', Distribution)
+
+ def get_distribution_config(self, distribution_id):
+ return self._get_config(distribution_id, 'distribution',
+ DistributionConfig)
+
+ def set_distribution_config(self, distribution_id, etag, config):
+ return self._set_config(distribution_id, etag, config)
+
+ def create_distribution(self, origin, enabled, caller_reference='',
+ cnames=None, comment=''):
+ config = DistributionConfig(origin=origin, enabled=enabled,
+ caller_reference=caller_reference,
+ cnames=cnames, comment=comment)
+ return self._create_object(config, 'distribution', Distribution)
+
+ def delete_distribution(self, distribution_id, etag):
+ return self._delete_object(distribution_id, etag, 'distribution')
+
+ # Streaming Distributions
+
+ def get_all_streaming_distributions(self):
+ tags=[('StreamingDistributionSummary', StreamingDistributionSummary)]
+ return self._get_all_objects('streaming-distribution', tags)
+
+ def get_streaming_distribution_info(self, distribution_id):
+ return self._get_info(distribution_id, 'streaming-distribution',
+ StreamingDistribution)
+
+ def get_streaming_distribution_config(self, distribution_id):
+ return self._get_config(distribution_id, 'streaming-distribution',
+ StreamingDistributionConfig)
+
+ def set_streaming_distribution_config(self, distribution_id, etag, config):
+ return self._set_config(distribution_id, etag, config)
+
+ def create_streaming_distribution(self, origin, enabled,
+ caller_reference='',
+ cnames=None, comment=''):
+ config = StreamingDistributionConfig(origin=origin, enabled=enabled,
+ caller_reference=caller_reference,
+ cnames=cnames, comment=comment)
+ return self._create_object(config, 'streaming-distribution',
+ StreamingDistribution)
+
+ def delete_streaming_distribution(self, distribution_id, etag):
+ return self._delete_object(distribution_id, etag, 'streaming-distribution')
+
+ # Origin Access Identity
+
+ def get_all_origin_access_identity(self):
+ tags=[('CloudFrontOriginAccessIdentitySummary',
+ OriginAccessIdentitySummary)]
+ return self._get_all_objects('origin-access-identity/cloudfront', tags)
+
+ def get_origin_access_identity_info(self, access_id):
+ return self._get_info(access_id, 'origin-access-identity/cloudfront',
+ OriginAccessIdentity)
+
+ def get_origin_access_identity_config(self, access_id):
+ return self._get_config(access_id,
+ 'origin-access-identity/cloudfront',
+ OriginAccessIdentityConfig)
+
+ def set_origin_access_identity_config(self, access_id,
+ etag, config):
+ return self._set_config(access_id, etag, config)
+
+ def create_origin_access_identity(self, caller_reference='', comment=''):
+ config = OriginAccessIdentityConfig(caller_reference=caller_reference,
+ comment=comment)
+ return self._create_object(config, 'origin-access-identity/cloudfront',
+ OriginAccessIdentity)
+
+ def delete_origin_access_identity(self, access_id, etag):
+ return self._delete_object(access_id, etag,
+ 'origin-access-identity/cloudfront')
+
- hmac = self.hmac.copy()
- hmac.update(headers['Date'])
- b64_hmac = base64.encodestring(hmac.digest()).strip()
- headers['Authorization'] = "AWS %s:%s" % (self.aws_access_key_id, b64_hmac)
View
392 boto/cloudfront/distribution.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2006-2008 Mitch Garnaat http://garnaat.org/
+# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
@@ -20,64 +20,17 @@
# IN THE SOFTWARE.
import uuid
+from boto.cloudfront.identity import OriginAccessIdentity
+from boto.cloudfront.object import Object
+from boto.cloudfront.signers import Signer, ActiveTrustedSigners, TrustedSigners
+from boto.cloudfront.logging import LoggingInfo
+from boto.s3.acl import ACL
-class Distribution:
-
- def __init__(self, connection=None, config=None, domain_name='',
- id='', last_modified_time=None, status=''):
- self.connection = connection
- self.config = config
- self.domain_name = domain_name
- self.id = id
- self.last_modified_time = last_modified_time
- self.status = status
- self.etag = None
-
- def startElement(self, name, attrs, connection):
- if name == 'DistributionConfig':
- self.config = DistributionConfig()
- return self.config
- else:
- return None
-
- def endElement(self, name, value, connection):
- if name == 'Id':
- self.id = value
- elif name == 'LastModifiedTime':
- self.last_modified_time = value
- elif name == 'Status':
- self.status = value
- elif name == 'DomainName':
- self.domain_name = value
- else:
- setattr(self, name, value)
-
- def update(self, enabled=None, cnames=None, comment=None):
- new_config = DistributionConfig(self.connection, self.config.origin,
- self.config.enabled, self.config.caller_reference,
- self.config.cnames, self.config.comment)
- if enabled != None:
- new_config.enabled = enabled
- if cnames != None:
- new_config.cnames = cnames
- if comment != None:
- new_config.comment = comment
- self.etag = self.connection.set_distribution_config(self.id, self.etag, new_config)
- self.config = new_config
-
- def enable(self):
- self.update(enabled=True)
-
- def disable(self):
- self.update(enabled=False)
-
- def delete(self):
- self.connection.delete_distribution(self.id, self.etag)
-
class DistributionConfig:
def __init__(self, connection=None, origin='', enabled=False,
- caller_reference='', cnames=None, comment=''):
+ caller_reference='', cnames=None, comment='',
+ origin_access_identity=None, trusted_signers=None):
self.connection = connection
self.origin = origin
self.enabled = enabled
@@ -89,10 +42,19 @@ def __init__(self, connection=None, origin='', enabled=False,
if cnames:
self.cnames = cnames
self.comment = comment
+ self.origin_access_identity = origin_access_identity
+ self.trusted_signers = trusted_signers
+ self.logging = None
+ def get_oai_value(self):
+ if isinstance(self.origin_access_identity, OriginAccessIdentity):
+ return self.origin_access_identity.uri()
+ else:
+ return self.origin_access_identity
+
def to_xml(self):
s = '<?xml version="1.0" encoding="UTF-8"?>\n'
- s += '<DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">\n'
+ s += '<DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2008-12-01/">\n'
s += ' <Origin>%s</Origin>\n' % self.origin
s += ' <CallerReference>%s</CallerReference>\n' % self.caller_reference
for cname in self.cnames:
@@ -105,11 +67,34 @@ def to_xml(self):
else:
s += 'false'
s += '</Enabled>\n'
+ if self.origin_access_identity:
+ val = self.get_oai_value()
+ s += '<OriginAccessIdentifier>%s</OriginAccessIdentifier>\n' % val
+ if self.trusted_signers:
+ s += '<TrustedSigners>\n'
+ for signer in self.trusted_signers:
+ if signer == 'Self':
+ s += ' <Self></Self>\n'
+ else:
+ s += ' <AwsAccountNumber>%s</AwsAccountNumber>\n' % signer
+ s += '</TrustedSigners>\n'
+ if self.logging:
+ s += '<Logging>\n'
+ s += ' <Bucket>%s</Bucket>\n' % self.logging.bucket
+ s += ' <Prefix>%s</Prefix>\n' % self.logging.prefix
+ s += '</Logging>\n'
s += '</DistributionConfig>\n'
return s
def startElement(self, name, attrs, connection):
- return None
+ if name == 'TrustedSigners':
+ self.trusted_signers = TrustedSigners()
+ return self.trusted_signers
+ elif name == 'Logging':
+ self.logging = LoggingInfo()
+ return self.logging
+ else:
+ return None
def endElement(self, name, value, connection):
if name == 'CNAME':
@@ -125,10 +110,40 @@ def endElement(self, name, value, connection):
self.enabled = False
elif name == 'CallerReference':
self.caller_reference = value
+ elif name == 'OriginAccessIdentity':
+ self.origin_access_identity = value
else:
setattr(self, name, value)
-
+class StreamingDistributionConfig(DistributionConfig):
+
+ def __init__(self, connection=None, origin='', enabled=False,
+ caller_reference='', cnames=None, comment=''):
+ DistributionConfig.__init__(self, connection, origin,
+ enabled, caller_reference,
+ cnames, comment)
+
+ def to_xml(self):
+ s = '<?xml version="1.0" encoding="UTF-8"?>\n'
+ s += '<StreamingDistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2009-12-01/">\n'
+ s += ' <Origin>%s</Origin>\n' % self.origin
+ s += ' <CallerReference>%s</CallerReference>\n' % self.caller_reference
+ for cname in self.cnames:
+ s += ' <CNAME>%s</CNAME>\n' % cname
+ if self.comment:
+ s += ' <Comment>%s</Comment>\n' % self.comment
+ s += ' <Enabled>'
+ if self.enabled:
+ s += 'true'
+ else:
+ s += 'false'
+ s += '</Enabled>\n'
+ s += '</StreamingDistributionConfig>\n'
+ return s
+
+ def startElement(self, name, attrs, connection):
+ pass
+
class DistributionSummary:
def __init__(self, connection=None, domain_name='', id='',
@@ -145,9 +160,14 @@ def __init__(self, connection=None, domain_name='', id='',
if cname:
self.cnames.append(cname)
self.comment = comment
+ self.trusted_signers = None
self.etag = None
+ self.streaming = False
def startElement(self, name, attrs, connection):
+ if name == 'TrustedSigners':
+ self.trusted_signers = TrustedSigners()
+ return self.trusted_signers
return None
def endElement(self, name, value, connection):
@@ -170,10 +190,266 @@ def endElement(self, name, value, connection):
self.enabled = True
else:
self.enabled = False
+ elif name == 'StreamingDistributionSummary':
+ self.streaming = True
else:
setattr(self, name, value)
def get_distribution(self):
return self.connection.get_distribution_info(self.id)
+class StreamingDistributionSummary(DistributionSummary):
+
+ def get_distribution(self):
+ return self.connection.get_streaming_distribution_info(self.id)
+
+class Distribution:
+
+ def __init__(self, connection=None, config=None, domain_name='',
+ id='', last_modified_time=None, status=''):
+ self.connection = connection
+ self.config = config
+ self.domain_name = domain_name
+ self.id = id
+ self.last_modified_time = last_modified_time
+ self.status = status
+ self.active_signers = None
+ self.etag = None
+ self._bucket = None
+
+ def startElement(self, name, attrs, connection):
+ if name == 'DistributionConfig':
+ self.config = DistributionConfig()
+ return self.config
+ elif name == 'ActiveTrustedSigners':
+ self.active_signers = ActiveTrustedSigners()
+ return self.active_signers
+ else:
+ return None
+
+ def endElement(self, name, value, connection):
+ if name == 'Id':
+ self.id = value
+ elif name == 'LastModifiedTime':
+ self.last_modified_time = value
+ elif name == 'Status':
+ self.status = value
+ elif name == 'DomainName':
+ self.domain_name = value
+ else:
+ setattr(self, name, value)
+
+ def update(self, enabled=None, cnames=None, comment=None,
+ origin_access_identity=None):
+ """
+ Update the configuration of the Distribution.
+
+ :type enabled: bool
+ :param enabled: Whether the Distribution is active or not.
+
+ :type cnames: list of str
+ :param cnames: The DNS CNAME's associated with this
+ Distribution. Maximum of 10 values.
+
+ :type comment: str or unicode
+ :param comment: The comment associated with the Distribution.
+
+ :type origin_access_identity: :class:`boto.cloudfront.identity.OriginAccessIdentity`
+ :param origin_access_identity: The CloudFront origin access identity
+ associated with the distribution. This
+ must be provided if you want the
+ distribution to serve private content.
+
+ """
+ new_config = DistributionConfig(self.connection, self.config.origin,
+ self.config.enabled, self.config.caller_reference,
+ self.config.cnames, self.config.comment,
+ self.config.origin_access_identity)
+ if enabled != None:
+ new_config.enabled = enabled
+ if cnames != None:
+ new_config.cnames = cnames
+ if comment != None:
+ new_config.comment = comment
+ if origin_access_identity != None:
+ new_config.origin_access_identity = origin_access_identity
+ self.etag = self.connection.set_distribution_config(self.id, self.etag, new_config)
+ self.config = new_config
+
+ def enable(self):
+ """
+ Deactivate the Distribution. A convenience wrapper around
+ the update method.
+ """
+ self.update(enabled=True)
+
+ def disable(self):
+ """
+ Activate the Distribution. A convenience wrapper around
+ the update method.
+ """
+ self.update(enabled=False)
+
+ def delete(self):
+ """
+ Delete this CloudFront Distribution. The content
+ associated with the Distribution is not deleted from
+ the underlying Origin bucket in S3.
+ """
+ self.connection.delete_distribution(self.id, self.etag)
+
+ def _get_bucket(self):
+ if not self._bucket:
+ bucket_name = self.config.origin.split('.')[0]
+ from boto.s3.connection import S3Connection
+ s3 = S3Connection(self.connection.aws_access_key_id,
+ self.connection.aws_secret_access_key,
+ proxy=self.connection.proxy,
+ proxy_port=self.connection.proxy_port,
+ proxy_user=self.connection.proxy_user,
+ proxy_pass=self.connection.proxy_pass)
+ self._bucket = s3.get_bucket(bucket_name)
+ self._bucket.distribution = self
+ self._bucket.set_key_class(Object)
+ return self._bucket
+
+ def get_objects(self):
+ """
+ Return a list of all content objects in this distribution.
+
+ :rtype: list of :class:`boto.cloudfront.object.Object`
+ :return: The content objects
+ """
+ bucket = self._get_bucket()
+ objs = []
+ for key in bucket:
+ objs.append(key)
+ return objs
+
+ def set_permissions(self, object, replace=False):
+ """
+ Sets the S3 ACL grants for the given object to the appropriate
+ value based on the type of Distribution. If the Distribution
+ is serving private content the ACL will be set to include the
+ Origin Access Identity associated with the Distribution. If
+ the Distribution is serving public content the content will
+ be set up with "public-read".
+
+ :type object: :class:`boto.cloudfront.object.Object`
+ :param enabled: The Object whose ACL is being set
+
+ :type replace: bool
+ :param replace: If False, the Origin Access Identity will be
+ appended to the existing ACL for the object.
+ If True, the ACL for the object will be
+ completely replaced with one that grants
+ READ permission to the Origin Access Identity.
+
+ """
+ if self.config.origin_access_identity:
+ id = self.config.origin_access_identity.split('/')[-1]
+ oai = self.connection.get_origin_access_identity_info(id)
+ policy = object.get_acl()
+ if replace:
+ policy.acl = ACL()
+ policy.acl.add_user_grant('READ', oai.s3_user_id)
+ object.set_acl(policy)
+ else:
+ object.set_canned_acl('public-read')
+
+ def set_permissions_all(self, replace=False):
+ """
+ Sets the S3 ACL grants for all objects in the Distribution
+ to the appropriate value based on the type of Distribution.
+
+ :type replace: bool
+ :param replace: If False, the Origin Access Identity will be
+ appended to the existing ACL for the object.
+ If True, the ACL for the object will be
+ completely replaced with one that grants
+ READ permission to the Origin Access Identity.
+
+ """
+ bucket = self._get_bucket()
+ for key in bucket:
+ self.set_permissions(key)
+
+ def add_object(self, name, content, headers=None):
+ """
+ Adds a new content object to the Distribution. The content
+ for the object will be copied to a new Key in the S3 Bucket
+ and the permissions will be set appropriately for the type
+ of Distribution.
+
+ :type name: str or unicode
+ :param name: The name or key of the new object.
+
+ :type content: file-like object
+ :param content: A file-like object that contains the content
+ for the new object.
+
+ :type headers: dict
+ :param headers: A dictionary containing additional headers
+ you would like associated with the new
+ object in S3.
+
+ :rtype: :class:`boto.cloudfront.object.Object`
+ :return: The newly created object.
+ """
+ if self.config.origin_access_identity:
+ policy = 'private'
+ else:
+ policy = 'public-read'
+ bucket = self._get_bucket()
+ object = bucket.new_key(name)
+ object.set_contents_from_file(content, headers=headers, policy=policy)
+ if self.config.origin_access_identity:
+ self.set_permissions(object, True)
+ return object
+
+class StreamingDistribution(Distribution):
+
+ def startElement(self, name, attrs, connection):
+ if name == 'StreamingDistributionConfig':
+ self.config = StreamingDistributionConfig()
+ return self.config
+ else:
+ return None
+
+ def update(self, enabled=None, cnames=None, comment=None):
+ """
+ Update the configuration of the Distribution.
+
+ :type enabled: bool
+ :param enabled: Whether the Distribution is active or not.
+
+ :type cnames: list of str
+ :param cnames: The DNS CNAME's associated with this
+ Distribution. Maximum of 10 values.
+
+ :type comment: str or unicode
+ :param comment: The comment associated with the Distribution.
+
+ """
+ new_config = StreamingDistributionConfig(self.connection,
+ self.config.origin,
+ self.config.enabled,
+ self.config.caller_reference,
+ self.config.cnames,
+ self.config.comment)
+ if enabled != None:
+ new_config.enabled = enabled
+ if cnames != None:
+ new_config.cnames = cnames
+ if comment != None:
+ new_config.comment = comment
+
+ self.etag = self.connection.set_streaming_distribution_config(self.id,
+ self.etag,
+ new_config)
+ self.config = new_config
+
+ def delete(self):
+ self.connection.delete_streaming_distribution(self.id, self.etag)
+
View
98 boto/cloudfront/identity.py
@@ -0,0 +1,98 @@
+# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+import uuid
+
+class OriginAccessIdentity:
+
+ def __init__(self, connection=None, config=None, id='',
+ s3_user_id='', comment=''):
+ self.connection = connection
+ self.config = config
+ self.id = id
+ self.s3_user_id = s3_user_id
+ self.comment = comment
+ self.etag = None
+
+ def startElement(self, name, attrs, connection):
+ if name == 'CloudFrontOriginAccessIdentityConfig':
+ self.config = OriginAccessIdentityConfig()
+ return self.config
+ else:
+ return None
+
+ def endElement(self, name, value, connection):
+ if name == 'Id':
+ self.id = value
+ elif name == 'S3CanonicalUserId':
+ self.s3_user_id = value
+ elif name == 'Comment':
+ self.comment = value
+ else:
+ setattr(self, name, value)
+
+ def update(self, comment=None):
+ new_config = OriginAccessIdentifyConfig(self.connection,
+ self.config.caller_reference,
+ self.config.comment)
+ if comment != None:
+ new_config.comment = comment
+ self.etag = self.connection.set_origin_identity_config(self.id, self.etag, new_config)
+ self.config = new_config
+
+ def delete(self):
+ return self.connection.delete_distribution(self.id, self.etag)
+
+ def uri(self):
+ return 'origin-access-identity/cloudfront/%s' % id
+
+class OriginAccessIdentityConfig:
+
+ def __init__(self, connection=None, caller_reference='', comment=''):
+ self.connection = connection
+ if caller_reference:
+ self.caller_reference = caller_reference
+ else:
+ self.caller_reference = str(uuid.uuid4())
+ self.comment = comment
+
+ def to_xml(self):
+ s = '<?xml version="1.0" encoding="UTF-8"?>\n'
+ s += '<CloudFrontOriginAccessIdentityConfig xmlns="http://cloudfront.amazonaws.com/doc/2009-09-09/">\n'
+ s += ' <CallerReference>%s</CallerReference>\n' % self.caller_reference
+ if self.comment:
+ s += ' <Comment>%s</Comment>\n' % self.comment
+ s += '</CloudFrontOriginAccessIdentityConfig>\n'
+ return s
+
+ def startElement(self, name, attrs, connection):
+ return None
+
+ def endElement(self, name, value, connection):
+ if name == 'Comment':
+ self.comment = value
+ elif name == 'CallerReference':
+ self.caller_reference = value
+ else:
+ setattr(self, name, value)
+
+
+
View
38 boto/cloudfront/logging.py
@@ -0,0 +1,38 @@
+# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+class LoggingInfo(object):
+
+ def __init__(self, bucket='', prefix=''):
+ self.bucket = bucket
+ self.prefix = prefix
+
+ def startElement(self, name, attrs, connection):
+ return None
+
+ def endElement(self, name, value, connection):
+ if name == 'Bucket':
+ self.bucket = value
+ elif name == 'Prefix':
+ self.prefix = value
+ else:
+ setattr(self, name, value)
+
View
42 boto/cloudfront/object.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+from boto.s3.key import Key
+
+class Object(Key):
+
+ def __init__(self, bucket, name=None):
+ Key.__init__(self, bucket, name=name)
+ self.distribution = bucket.distribution
+
+ def __repr__(self):
+ return '<Object: %s/%s>' % (self.distribution.config.origin, self.name)
+
+ def url(self, scheme='http'):
+ url = '%s://' % scheme
+ url += self.distribution.domain_name
+ if scheme.lower().startswith('rtmp'):
+ url += '/cfx/st/'
+ else:
+ url += '/'
+ url += self.name
+ return url
+
View
60 boto/cloudfront/signers.py
@@ -0,0 +1,60 @@
+# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+class Signer:
+
+ def __init__(self):
+ self.id = None
+ self.key_pair_ids = []
+
+ def startElement(self, name, attrs, connection):
+ return None
+
+ def endElement(self, name, value, connection):
+ if name == 'Self':
+ self.id = 'Self'
+ elif name == 'AwsAccountNumber':
+ self.id = value
+ elif name == 'KeyPairId':
+ self.key_pair_ids.append(value)
+
+class ActiveTrustedSigners(list):
+
+ def startElement(self, name, attrs, connection):
+ if name == 'Signer':
+ s = Signer()
+ self.append(s)
+ return s
+
+ def endElement(self, name, value, connection):
+ pass
+
+class TrustedSigners(list):
+
+ def startElement(self, name, attrs, connection):
+ return None
+
+ def endElement(self, name, value, connection):
+ if name == 'Self':
+ self.append(name)
+ elif name == 'AwsAccountNumber':
+ self.append(value)
+
Please sign in to comment.
Something went wrong with that request. Please try again.