Created
September 13, 2010 15:34
-
-
Save elgreg/577468 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: S3/CloudFront.py | |
=================================================================== | |
--- S3/CloudFront.py (revision 392) | |
+++ S3/CloudFront.py (working copy) | |
@@ -155,6 +155,104 @@ | |
return ET.tostring(tree) | |
+class InvalidationList(object): | |
+ ## <InvalidationList> | |
+ ## <Marker/> | |
+ ## <NextMarker>[Invalidation ID]</NextMarker> | |
+ ## <MaxItems>2</MaxItems> | |
+ ## <IsTruncated>true</IsTruncated> | |
+ ## <InvalidationSummary> | |
+ ## <Id>[Second Invalidation ID]</Id> | |
+ ## <Status>Completed</Status> | |
+ ## </InvalidationSummary> | |
+ ## <InvalidationSummary> | |
+ ## <Id>[First Invalidation ID]</Id> | |
+ ## <Status>Completed</Status> | |
+ ## </InvalidationSummary> | |
+ ## </InvalidationList> | |
+ | |
+ def __init__(self, xml): | |
+ tree = getTreeFromXml(xml) | |
+ if tree.tag != "InvalidationList": | |
+ raise ValueError("Expected <InvalidationList /> xml, got: <%s />" % tree.tag) | |
+ self.parse(tree) | |
+ | |
+ def parse(self, tree): | |
+ self.info = getDictFromTree(tree) | |
+ | |
+ def uri(self): | |
+ return S3Uri("cf://%s" % self.info['Id']) | |
+ | |
+ | |
+ | |
+class Invalidation(object): | |
+ ## <Invalidation xmlns="http://cloudfront.amazonaws.com/doc/2010-08-01/"> | |
+ ## <Status>InProgress</Status> | |
+ ## <Id>I456</Id> | |
+ ## <CreateTime>[date]</CreateTime> | |
+ ## <InvalidationBatch> | |
+ ## ... | |
+ ## See the description of the InvalidationBatch element | |
+ ## for a list of child elements that can appear here | |
+ ## ... | |
+ ## </InvalidationBatch> | |
+ ## </Invalidation> | |
+ | |
+ EMPTY_CONFIG = "<Invalidation><Status/><Id/><CreateTime/><InvalidationBatch/></Invalidation>" | |
+ xmlns = "http://cloudfront.amazonaws.com/doc/2010-08-01/" | |
+ def __init__(self, xml = None, tree = None): | |
+ if not xml: | |
+ xml = Invalidation.EMPTY_CONFIG | |
+ | |
+ if not tree: | |
+ tree = getTreeFromXml(xml) | |
+ | |
+ if tree.tag != "Invalidation": | |
+ raise ValueError("Expected <Invalidation /> xml, got: <%s />" % tree.tag) | |
+ self.parse(tree) | |
+ | |
+ def parse(self, tree): | |
+ self.info = getDictFromTree(tree) | |
+ | |
+ | |
+class InvalidationBatch(object): | |
+ ## <InvalidationBatch xmlns="http://cloudfront.amazonaws.com/doc/2010-08-01/"> | |
+ ## <Path>/image1.jpg</Path> | |
+ ## <CallerReference>my-batch</CallerReference> | |
+ ## </InvalidationBatch> | |
+ | |
+ EMPTY_CONFIG = "<InvalidationBatch><Path/><CallerReference/></InvalidationBatch>" | |
+ xmlns = "http://cloudfront.amazonaws.com/doc/2010-08-01/" | |
+ def __init__(self, xml = None, tree = None, CallerReference = None, Paths = []): | |
+ if not xml: | |
+ xml = InvalidationBatch.EMPTY_CONFIG | |
+ | |
+ if not tree: | |
+ tree = getTreeFromXml(xml) | |
+ | |
+ if tree.tag != "InvalidationBatch": | |
+ raise ValueError("Expected <InvalidationBatch /> xml, got: <%s />" % tree.tag) | |
+ | |
+ self.parse(tree, CallerReference, Paths) | |
+ | |
+ def parse(self, tree, CallerReference = None, Paths = []): | |
+ self.info = getDictFromTree(tree) | |
+ if CallerReference: | |
+ self.info['CallerReference'] = CallerReference | |
+ if len(Paths) > 0: | |
+ self.info['Paths'] = [] | |
+ for path in Paths: | |
+ self.info['Paths'].append(path) | |
+ | |
+ | |
+ def __str__(self): | |
+ tree = ET.Element("InvalidationBatch") | |
+ tree.attrib['xmlns'] = InvalidationBatch.xmlns | |
+ for path in self.info['Paths']: | |
+ appendXmlTextNode("Path", path, tree) | |
+ appendXmlTextNode("CallerReference", self.info['CallerReference'], tree) | |
+ return ET.tostring(tree) | |
+ | |
class CloudFront(object): | |
operations = { | |
"CreateDist" : { 'method' : "POST", 'resource' : "" }, | |
@@ -163,6 +261,9 @@ | |
"GetDistInfo" : { 'method' : "GET", 'resource' : "/%(dist_id)s" }, | |
"GetDistConfig" : { 'method' : "GET", 'resource' : "/%(dist_id)s/config" }, | |
"SetDistConfig" : { 'method' : "PUT", 'resource' : "/%(dist_id)s/config" }, | |
+ "Invalidate" : { 'method' : "POST", 'resource' : "/%(dist_id)s/invalidation"}, | |
+ "InvalidationList" : { 'method' : "GET", 'resource' : "/%(dist_id)s/invalidation"}, | |
+ "InvalidationInfo" : { 'method' : "GET", 'resource' : "/%(dist_id)s/invalidation/%(inv_id)s"}, | |
} | |
## Maximum attempts of re-issuing failed requests | |
@@ -280,11 +381,11 @@ | |
## Low-level methods for handling CloudFront requests | |
## -------------------------------------------------- | |
- def send_request(self, op_name, dist_id = None, body = None, headers = {}, retries = _max_retries): | |
+ def send_request(self, op_name, dist_id = None, inv_id = None, body = None, headers = {}, retries = _max_retries): | |
operation = self.operations[op_name] | |
if body: | |
headers['content-type'] = 'text/plain' | |
- request = self.create_request(operation, dist_id, headers) | |
+ request = self.create_request(operation, dist_id, inv_id, headers) | |
conn = self.get_connection() | |
debug("send_request(): %s %s" % (request['method'], request['resource'])) | |
conn.request(request['method'], request['resource'], body, request['headers']) | |
@@ -314,9 +415,13 @@ | |
return response | |
- def create_request(self, operation, dist_id = None, headers = None): | |
- resource = self.config.cloudfront_resource + ( | |
- operation['resource'] % { 'dist_id' : dist_id }) | |
+ def create_request(self, operation, dist_id = None, inv_id = None, headers = None): | |
+ if(inv_id): | |
+ resource = self.config.cloudfront_resource + ( | |
+ operation['resource'] % { 'dist_id' : dist_id, 'inv_id' : inv_id }) | |
+ else: | |
+ resource = self.config.cloudfront_resource + ( | |
+ operation['resource'] % { 'dist_id' : dist_id }) | |
if not headers: | |
headers = {} | |
@@ -477,3 +582,48 @@ | |
pretty_output("Comment", dc.info['Comment']) | |
pretty_output("Enabled", dc.info['Enabled']) | |
pretty_output("Etag", response['headers']['etag']) | |
+ | |
+ @staticmethod | |
+ def invlist(args): | |
+ cf = CloudFront(Config()) | |
+ cfuris = [] | |
+ | |
+ for arg in args: | |
+ cfuris.append(S3Uri(arg)) | |
+ if cfuris[-1].type != 'cf': | |
+ raise ParameterError("CloudFront URI required instead of: %s" % arg) | |
+ for cfuri in cfuris: | |
+ response = cf.InvalidationList(cfuri) | |
+ pprint.PrettyPrinter(indent=2).pprint(response) | |
+ | |
+ @staticmethod | |
+ def inv(args): | |
+ cf = CloudFront(Config()) | |
+ files = [] | |
+ # First arg should be the cf uri | |
+ # next args should be strings of files | |
+ pprint.PrettyPrinter().pprint(args) | |
+ | |
+ cfuri = S3Uri(args[0]) | |
+ | |
+ if cfuri.type != 'cf': | |
+ raise ParameterError("CloudFront URI required instead of: %s" % args[0]) | |
+ | |
+ | |
+ for filePath in args[1:]: | |
+ files.append(filePath) | |
+ | |
+ response = cf.Invalidate(cfuri, files) | |
+ | |
+ @staticmethod | |
+ def invinfo(args): | |
+ cf = CloudFront(Config()) | |
+ | |
+ cfuri = S3Uri(args[0]) | |
+ | |
+ if cfuri.type != 'cf': | |
+ raise ParameterError("CloudFront URI required instead of: %s" % args[0]) | |
+ | |
+ invid = args[1] | |
+ | |
+ response = cf.InvalidationInfo(cfuri, invid) | |
Index: S3/Config.py | |
=================================================================== | |
--- S3/Config.py (revision 392) | |
+++ S3/Config.py (working copy) | |
@@ -19,7 +19,7 @@ | |
host_bucket = "%(bucket)s.s3.amazonaws.com" | |
simpledb_host = "sdb.amazonaws.com" | |
cloudfront_host = "cloudfront.amazonaws.com" | |
- cloudfront_resource = "/2008-06-30/distribution" | |
+ cloudfront_resource = "/2010-08-01/distribution" | |
verbosity = logging.WARNING | |
progress_meter = True | |
progress_class = Progress.ProgressCR | |
Index: s3cmd | |
=================================================================== | |
--- s3cmd (revision 392) | |
+++ s3cmd (working copy) | |
@@ -1356,6 +1356,9 @@ | |
{"cmd":"cfcreate", "label":"Create CloudFront distribution point", "param":"s3://BUCKET", "func":CfCmd.create, "argc":1}, | |
{"cmd":"cfdelete", "label":"Delete CloudFront distribution point", "param":"cf://DIST_ID", "func":CfCmd.delete, "argc":1}, | |
{"cmd":"cfmodify", "label":"Change CloudFront distribution point parameters", "param":"cf://DIST_ID", "func":CfCmd.modify, "argc":1}, | |
+ {"cmd":"cfinv", "label":"Invalidate a file for a distribution", "param":"cf://DIST_ID FILE [FILE...]", "func":CfCmd.inv, "argc":2}, | |
+ {"cmd":"cfinvlist", "label":"List invalidation requests for a distribution", "param":"cf://DIST_ID", "func":CfCmd.invlist, "argc":1}, | |
+ {"cmd":"cfinvinfo", "label":"Get the status of a particular invalidation requestion for a distirbution", "param":"cf://DIST_ID cf:INV_ID", "func":CfCmd.invinfo, "argc":2}, | |
] | |
def format_commands(progname, commands_list): |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment