summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Moyer <kopertop@MacPro.local>2010-09-02 11:04:34 -0400
committerChris Moyer <kopertop@MacPro.local>2010-09-02 11:04:34 -0400
commit8ff181af25d3a4018d1fb29fa78a0d745046f900 (patch)
tree1bd6a6e3d234f97a3d8ff95202e9cf8b226914e2
parentfc8305c0fe7fcec69fe841bb004b580f60dd1e43 (diff)
downloadboto-8ff181af25d3a4018d1fb29fa78a0d745046f900.tar.gz
Added initial support for invalidation.
Invalidations can be done by creating a new "Invalidation Request": >>> import boto >>> cf = boto.connect_cloudfront() >>> cf.create_invalidation_request("distribution_id", ["/path1","/path2"])
-rwxr-xr-x[-rw-r--r--]bin/cfadmin14
-rw-r--r--boto/cloudfront/__init__.py23
-rw-r--r--boto/cloudfront/invalidation.py97
3 files changed, 133 insertions, 1 deletions
diff --git a/bin/cfadmin b/bin/cfadmin
index d44e7405..c3db35f8 100644..100755
--- a/bin/cfadmin
+++ b/bin/cfadmin
@@ -46,6 +46,20 @@ def ls(cf):
print "Streaming Distributions"
_print_distributions(cf.get_all_streaming_distributions())
+def invalidate(cf, origin_or_id, *paths):
+ """Create a cloudfront invalidation request"""
+ if not paths:
+ print "Usage: cfadmin invalidate distribution_origin_or_id [path] [path2]..."
+ sys.exit(1)
+ dist = None
+ for d in cf.get_all_distributions():
+ if d.id == origin_or_id or d.origin == origin_or_id:
+ dist = d
+ break
+ if not dist:
+ print "Distribution not found: %s" % origin_or_id
+ sys.exit(1)
+ cf.create_invalidation_request(dist.id, paths)
if __name__ == "__main__":
import boto
diff --git a/boto/cloudfront/__init__.py b/boto/cloudfront/__init__.py
index 1e872ecd..8996c507 100644
--- a/boto/cloudfront/__init__.py
+++ b/boto/cloudfront/__init__.py
@@ -30,13 +30,14 @@ from boto.cloudfront.distribution import StreamingDistribution, StreamingDistrib
from boto.cloudfront.identity import OriginAccessIdentity
from boto.cloudfront.identity import OriginAccessIdentitySummary
from boto.cloudfront.identity import OriginAccessIdentityConfig
+from boto.cloudfront.invalidation import InvalidationBatch
from boto.resultset import ResultSet
from boto.cloudfront.exception import CloudFrontServerError
class CloudFrontConnection(AWSAuthConnection):
DefaultHost = 'cloudfront.amazonaws.com'
- Version = '2010-07-15'
+ Version = '2010-08-01'
def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
port=None, proxy=None, proxy_port=None,
@@ -220,4 +221,24 @@ class CloudFrontConnection(AWSAuthConnection):
return self._delete_object(access_id, etag,
'origin-access-identity/cloudfront')
+ # Object Invalidation
+
+ def create_invalidation_request(self, distribution_id, paths, caller_reference=None):
+ """Creates a new invalidation request
+ :see: http://docs.amazonwebservices.com/AmazonCloudFront/2010-08-01/APIReference/index.html?CreateInvalidation.html
+ """
+ # We allow you to pass in either an array or
+ # an InvalidationBatch object
+ if not isinstance(paths, InvalidationBatch):
+ paths = InvalidationBatch(paths)
+ paths.connection = self
+ response = self.make_request('POST', '/%s/distribution/%s/invalidation' % (self.Version, distribution_id),
+ {'Content-Type' : 'text/xml'}, data=paths.to_xml())
+ body = response.read()
+ if response.status == 201:
+ h = handler.XmlHandler(paths, self)
+ xml.sax.parseString(body, h)
+ return paths
+ else:
+ raise CloudFrontServerError(response.status, response.reason, body)
diff --git a/boto/cloudfront/invalidation.py b/boto/cloudfront/invalidation.py
new file mode 100644
index 00000000..4a0f2059
--- /dev/null
+++ b/boto/cloudfront/invalidation.py
@@ -0,0 +1,97 @@
+# Copyright (c) 2006-2010 Chris Moyer http://coredumped.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
+import urllib
+
+class InvalidationBatch(object):
+ """A simple invalidation request.
+ :see: http://docs.amazonwebservices.com/AmazonCloudFront/2010-08-01/APIReference/index.html?InvalidationBatchDatatype.html
+ """
+
+ def __init__(self, paths=[], connection=None, distribution=None, caller_reference=''):
+ """Create a new invalidation request:
+ :paths: An array of paths to invalidate
+ """
+ self.paths = paths
+ self.distribution = distribution
+ self.caller_reference = caller_reference
+ if not self.caller_reference:
+ self.caller_reference = str(uuid.uuid4())
+
+ # If we passed in a distribution,
+ # then we use that as the connection object
+ if distribution:
+ self.connection = connection
+ else:
+ self.connection = connection
+
+ def add(self, path):
+ """Add another path to this invalidation request"""
+ return self.paths.append(path)
+
+ def remove(self, path):
+ """Remove a path from this invalidation request"""
+ return self.paths.remove(path)
+
+ def __iter__(self):
+ return iter(self.paths)
+
+ def __getitem__(self, i):
+ return self.paths[i]
+
+ def __setitem__(self, k, v):
+ self.paths[k] = v
+
+ def escape(self, p):
+ """Escape a path, make sure it begins with a slash and contains no invalid characters"""
+ if not p[0] == "/":
+ p = "/%s" % p
+ return urllib.quote(p)
+
+ def to_xml(self):
+ """Get this batch as XML"""
+ assert self.connection != None
+ s = '<?xml version="1.0" encoding="UTF-8"?>\n'
+ s += '<InvalidationBatch xmlns="http://cloudfront.amazonaws.com/doc/%s/">\n' % self.connection.Version
+ for p in self.paths:
+ s += ' <Path>%s</Path>\n' % self.escape(p)
+ s += ' <CallerReference>%s</CallerReference>\n' % self.caller_reference
+ s += '</InvalidationBatch>\n'
+ return s
+
+ def startElement(self, name, attrs, connection):
+ if name == "InvalidationBatch":
+ self.paths = []
+ return None
+
+ def endElement(self, name, value, connection):
+ if name == 'Path':
+ self.paths.append(value)
+ elif name == "Status":
+ self.status = value
+ elif name == "Id":
+ self.id = id
+ elif name == "CreateTime":
+ self.create_time = value
+ elif name == "CallerReference":
+ self.caller_reference = value
+ return None