Browse code

* s3cmd, S3/CloudFront.py, S3/Config.py: Added support for CloudFront DefaultRootObject. Thanks to Luke Andrew.

git-svn-id: https://s3tools.svn.sourceforge.net/svnroot/s3tools/s3cmd/trunk@446 830e0280-6d2a-0410-9c65-932aecc39d9d

Michal Ludvig authored on 2010/10/26 10:15:43
Showing 4 changed files
... ...
@@ -1,3 +1,8 @@
1
+2010-10-26  Michal Ludvig  <mludvig@logix.net.nz>
2
+
3
+	* s3cmd, S3/CloudFront.py, S3/Config.py: Added support
4
+	  for CloudFront DefaultRootObject. Thanks to Luke Andrew.
5
+
1 6
 2010-10-25  Michal Ludvig  <mludvig@logix.net.nz>
2 7
 
3 8
 	* s3cmd: Improved 'fixbucket' command. Thanks to Srinivasa
... ...
@@ -53,7 +53,7 @@ class DistributionSummary(object):
53 53
 class DistributionList(object):
54 54
 	## Example:
55 55
 	## 
56
-	## <DistributionList xmlns="http://cloudfront.amazonaws.com/doc/2010-06-01/">
56
+	## <DistributionList xmlns="http://cloudfront.amazonaws.com/doc/2010-07-15/">
57 57
 	##	<Marker />
58 58
 	##	<MaxItems>100</MaxItems>
59 59
 	##	<IsTruncated>false</IsTruncated>
... ...
@@ -80,7 +80,7 @@ class DistributionList(object):
80 80
 class Distribution(object):
81 81
 	## Example:
82 82
 	##
83
-	## <Distribution xmlns="http://cloudfront.amazonaws.com/doc/2010-06-01/">
83
+	## <Distribution xmlns="http://cloudfront.amazonaws.com/doc/2010-07-15/">
84 84
 	##	<Id>1234567890ABC</Id>
85 85
 	##	<Status>InProgress</Status>
86 86
 	##	<LastModifiedTime>2009-01-16T13:07:11.319Z</LastModifiedTime>
... ...
@@ -121,7 +121,7 @@ class DistributionConfig(object):
121 121
 	## </DistributionConfig>
122 122
 
123 123
 	EMPTY_CONFIG = "<DistributionConfig><Origin/><CallerReference/><Enabled>true</Enabled></DistributionConfig>"
124
-	xmlns = "http://cloudfront.amazonaws.com/doc/2010-06-01/"
124
+	xmlns = "http://cloudfront.amazonaws.com/doc/2010-07-15/"
125 125
 	def __init__(self, xml = None, tree = None):
126 126
 		if not xml:
127 127
 			xml = DistributionConfig.EMPTY_CONFIG
... ...
@@ -143,6 +143,8 @@ class DistributionConfig(object):
143 143
 		self.info['CNAME'] = [cname.lower() for cname in self.info['CNAME']]
144 144
 		if not self.info.has_key("Comment"):
145 145
 			self.info['Comment'] = ""
146
+		if not self.info.has_key("DefaultRootObject"):
147
+			self.info['DefaultRootObject'] = ""
146 148
 		## Figure out logging - complex node not parsed by getDictFromTree()
147 149
 		logging_nodes = tree.findall(".//Logging")
148 150
 		if logging_nodes:
... ...
@@ -166,6 +168,9 @@ class DistributionConfig(object):
166 166
 		if self.info['Comment']:
167 167
 			appendXmlTextNode("Comment", self.info['Comment'], tree)
168 168
 		appendXmlTextNode("Enabled", str(self.info['Enabled']).lower(), tree)
169
+		# don't create a empty DefaultRootObject element as it would result in a MalformedXML error
170
+		if str(self.info['DefaultRootObject']):
171
+			appendXmlTextNode("DefaultRootObject", str(self.info['DefaultRootObject']), tree)
169 172
 		if self.info['Logging']:
170 173
 			logging_el = ET.Element("Logging")
171 174
 			appendXmlTextNode("Bucket", getHostnameFromBucket(self.info['Logging'].bucket()), logging_el)
... ...
@@ -201,11 +206,12 @@ class CloudFront(object):
201 201
 		## TODO: handle Truncated 
202 202
 		return response
203 203
 	
204
-	def CreateDistribution(self, uri, cnames_add = [], comment = None, logging = None):
204
+	def CreateDistribution(self, uri, cnames_add = [], comment = None, logging = None, default_root_object = None):
205 205
 		dist_config = DistributionConfig()
206 206
 		dist_config.info['Enabled'] = True
207 207
 		dist_config.info['Origin'] = uri.host_name()
208 208
 		dist_config.info['CallerReference'] = str(uri)
209
+		dist_config.info['DefaultRootObject'] = default_root_object
209 210
 		if comment == None:
210 211
 			dist_config.info['Comment'] = uri.public_url()
211 212
 		else:
... ...
@@ -222,7 +228,8 @@ class CloudFront(object):
222 222
 		return response
223 223
 	
224 224
 	def ModifyDistribution(self, cfuri, cnames_add = [], cnames_remove = [],
225
-	                       comment = None, enabled = None, logging = None):
225
+	                       comment = None, enabled = None, logging = None,
226
+                           default_root_object = None):
226 227
 		if cfuri.type != "cf":
227 228
 			raise ValueError("Expected CFUri instead of: %s" % cfuri)
228 229
 		# Get current dist status (enabled/disabled) and Etag
... ...
@@ -233,6 +240,8 @@ class CloudFront(object):
233 233
 			dc.info['Enabled'] = enabled
234 234
 		if comment != None:
235 235
 			dc.info['Comment'] = comment
236
+		if default_root_object != None:
237
+			dc.info['DefaultRootObject'] = default_root_object
236 238
 		for cname in cnames_add:
237 239
 			if dc.info['CNAME'].count(cname) == 0:
238 240
 				dc.info['CNAME'].append(cname)
... ...
@@ -390,6 +399,7 @@ class Cmd(object):
390 390
 		cf_comment = None
391 391
 		cf_enable = None
392 392
 		cf_logging = None
393
+		cf_default_root_object = None
393 394
 
394 395
 		def option_list(self):
395 396
 			return [opt for opt in dir(self) if opt.startswith("cf_")]
... ...
@@ -454,6 +464,7 @@ class Cmd(object):
454 454
 				pretty_output("CNAMEs", ", ".join(dc.info['CNAME']))
455 455
 				pretty_output("Comment", dc.info['Comment'])
456 456
 				pretty_output("Enabled", dc.info['Enabled'])
457
+				pretty_output("DfltRootObject", dc.info['DefaultRootObject'])
457 458
 				pretty_output("Logging", dc.info['Logging'] or "Disabled")
458 459
 				pretty_output("Etag", response['headers']['etag'])
459 460
 
... ...
@@ -476,7 +487,8 @@ class Cmd(object):
476 476
 			info("Creating distribution from: %s" % uri)
477 477
 			response = cf.CreateDistribution(uri, cnames_add = Cmd.options.cf_cnames_add, 
478 478
 			                                 comment = Cmd.options.cf_comment,
479
-			                                 logging = Cmd.options.cf_logging)
479
+			                                 logging = Cmd.options.cf_logging,
480
+                                             default_root_object = Cmd.options.cf_default_root_object)
480 481
 			d = response['distribution']
481 482
 			dc = d.info['DistributionConfig']
482 483
 			output("Distribution created:")
... ...
@@ -487,6 +499,7 @@ class Cmd(object):
487 487
 			pretty_output("Comment", dc.info['Comment'])
488 488
 			pretty_output("Status", d.info['Status'])
489 489
 			pretty_output("Enabled", dc.info['Enabled'])
490
+			pretty_output("DefaultRootObject", dc.info['DefaultRootObject'])
490 491
 			pretty_output("Etag", response['headers']['etag'])
491 492
 
492 493
 	@staticmethod
... ...
@@ -513,7 +526,8 @@ class Cmd(object):
513 513
 		                                 cnames_remove = Cmd.options.cf_cnames_remove,
514 514
 		                                 comment = Cmd.options.cf_comment,
515 515
 		                                 enabled = Cmd.options.cf_enable,
516
-		                                 logging = Cmd.options.cf_logging)
516
+		                                 logging = Cmd.options.cf_logging,
517
+                                         default_root_object = Cmd.options.cf_default_root_object)
517 518
 		if response['status'] >= 400:
518 519
 			error("Distribution %s could not be modified: %s" % (cfuri, response['reason']))
519 520
 		output("Distribution modified: %s" % cfuri)
... ...
@@ -527,4 +541,5 @@ class Cmd(object):
527 527
 		pretty_output("CNAMEs", ", ".join(dc.info['CNAME']))
528 528
 		pretty_output("Comment", dc.info['Comment'])
529 529
 		pretty_output("Enabled", dc.info['Enabled'])
530
+		pretty_output("DefaultRootObject", dc.info['DefaultRootObject'])
530 531
 		pretty_output("Etag", response['headers']['etag'])
... ...
@@ -19,7 +19,7 @@ class Config(object):
19 19
 	host_bucket = "%(bucket)s.s3.amazonaws.com"
20 20
 	simpledb_host = "sdb.amazonaws.com"
21 21
 	cloudfront_host = "cloudfront.amazonaws.com"
22
-	cloudfront_resource = "/2010-06-01/distribution"
22
+	cloudfront_resource = "/2010-07-15/distribution"
23 23
 	verbosity = logging.WARNING
24 24
 	progress_meter = True
25 25
 	progress_class = Progress.ProgressCR
... ...
@@ -1662,6 +1662,7 @@ def main():
1662 1662
 	optparser.add_option(      "--cf-add-cname", dest="cf_cnames_add", action="append", metavar="CNAME", help="Add given CNAME to a CloudFront distribution (only for [cfcreate] and [cfmodify] commands)")
1663 1663
 	optparser.add_option(      "--cf-remove-cname", dest="cf_cnames_remove", action="append", metavar="CNAME", help="Remove given CNAME from a CloudFront distribution (only for [cfmodify] command)")
1664 1664
 	optparser.add_option(      "--cf-comment", dest="cf_comment", action="store", metavar="COMMENT", help="Set COMMENT for a given CloudFront distribution (only for [cfcreate] and [cfmodify] commands)")
1665
+	optparser.add_option(      "--cf-default-root-object", dest="cf_default_root_object", action="store", metavar="DEFAULT_ROOT_OBJECT", help="Set the default root object to return when no object is specified in the URL. Use a relative path, i.e. default/index.html instead of /default/index.html or s3://bucket/default/index.html (only for [cfcreate] and [cfmodify] commands)")
1665 1666
 	optparser.add_option("-v", "--verbose", dest="verbosity", action="store_const", const=logging.INFO, help="Enable verbose output.")
1666 1667
 	optparser.add_option("-d", "--debug", dest="verbosity", action="store_const", const=logging.DEBUG, help="Enable debug output.")
1667 1668
 	optparser.add_option(      "--version", dest="show_version", action="store_true", help="Show s3cmd version (%s) and exit." % (PkgInfo.version))