Browse code

Improved WebSite support

* Renamed ws-list to ws-info
* Prettyfied ws-info output
* Include website endpoint in ws-info output
* Fixed --ws-error handling

Michal Ludvig authored on 2011/06/07 15:07:14
Showing 4 changed files
... ...
@@ -2,6 +2,8 @@ s3cmd 1.1.0   -   ???
2 2
 ===========
3 3
 * CloudFront invalidation via [sync --cf-invalidate] and [cfinvalinfo].
4 4
 * Increased socket_timeout from 10 secs to 5 mins.
5
+* Added "Static WebSite" support [ws-create / ws-delete / ws-info]
6
+  (contributed by Jens Braeuer)
5 7
 
6 8
 s3cmd 1.0.0   -   2011-01-18
7 9
 ===========
... ...
@@ -77,7 +77,8 @@ class Config(object):
77 77
 	socket_timeout = 300
78 78
 	invalidate_on_cf = False
79 79
 	website_index = "index.html"
80
-	website_error = None
80
+	website_error = ""
81
+	website_endpoint = "http://%(bucket)s.s3-website-%(location)s.amazonaws.com/"
81 82
 
82 83
 	## Creating a singleton
83 84
 	def __new__(self, configfile = None):
... ...
@@ -238,27 +238,41 @@ class S3(object):
238 238
 		response = self.send_request(request)
239 239
 		return response
240 240
 
241
-	def bucket_info(self, uri):
241
+	def get_bucket_location(self, uri):
242 242
 		request = self.create_request("BUCKET_LIST", bucket = uri.bucket(), extra = "?location")
243 243
 		response = self.send_request(request)
244
-		response['bucket-location'] = getTextFromXml(response['data'], "LocationConstraint") or "any"
244
+		location = getTextFromXml(response['data'], "LocationConstraint")
245
+		if not location or location in [ "", "US" ]:
246
+			location = "us-east-1"
247
+		elif location == "EU":
248
+			location = "eu-west-1"
249
+		return location
250
+
251
+	def bucket_info(self, uri):
252
+		# For now reports only "Location". One day perhaps more.
253
+		response = {}
254
+		response['bucket-location'] = self.get_bucket_location(uri)
245 255
 		return response
246 256
 
247
-	def website_list(self, uri, bucket_location = None):
257
+	def website_info(self, uri, bucket_location = None):
248 258
 		headers = SortedDict(ignore_case = True)
249 259
 		bucket = uri.bucket()
250 260
 		body = ""
251 261
 
252 262
 		request = self.create_request("BUCKET_LIST", bucket = bucket, extra="?website")
253
-		response = None
254 263
 		try:
255 264
 			response = self.send_request(request, body)
265
+			response['index_document'] = getTextFromXml(response['data'], ".//IndexDocument//Suffix")
266
+			response['error_document'] = getTextFromXml(response['data'], ".//ErrorDocument//Key")
267
+			response['website_endpoint'] = self.config.website_endpoint % {
268
+				"bucket" : uri.bucket(),
269
+				"location" : self.get_bucket_location(uri)}
270
+			return response
256 271
 		except S3Error, e:
257 272
 			if e.status == 404:
258
-				debug("Could not get ?website. Assuming none set.")
259
-			else:
260
-				raise
261
-		return response
273
+				debug("Could not get /?website - website probably not configured for this bucket")
274
+				return None
275
+			raise
262 276
 
263 277
 	def website_create(self, uri, bucket_location = None):
264 278
 		headers = SortedDict(ignore_case = True)
... ...
@@ -164,20 +164,21 @@ def cmd_bucket_create(args):
164 164
 			else:
165 165
 				raise
166 166
 
167
-def cmd_website_list(args):
167
+def cmd_website_info(args):
168 168
 	s3 = S3(Config())
169 169
 	for arg in args:
170 170
 		uri = S3Uri(arg)
171 171
 		if not uri.type == "s3" or not uri.has_bucket() or uri.has_object():
172 172
 			raise ParameterError("Expecting S3 URI with just the bucket name set instead of '%s'" % arg)
173 173
 		try:
174
-			response = s3.website_list(uri, cfg.bucket_location)
174
+			response = s3.website_info(uri, cfg.bucket_location)
175 175
 			if response:
176
-				import xml.dom.minidom
177
-				xml = xml.dom.minidom.parseString(response['data'])
178
-				output(u"Bucket '%s': website configuration:\n%s" % (uri.uri(), xml.toprettyxml()))
176
+				output(u"Bucket %s: Website configuration" % uri.uri())
177
+				output(u"Website endpoint: %s" % response['website_endpoint'])
178
+				output(u"Index document:   %s" % response['index_document'])
179
+				output(u"Error document:   %s" % response['error_document'])
179 180
 			else:
180
-				output(u"Bucket '%s': unable to receive website configuration. None set?" % (uri.uri()))
181
+				output(u"Bucket %s: Unable to receive website configuration." % (uri.uri()))
181 182
 		except S3Error, e:
182 183
 			if S3.codes.has_key(e.info["Code"]):
183 184
 				error(S3.codes[e.info["Code"]] % uri.bucket())
... ...
@@ -1379,7 +1380,7 @@ def get_commands_list():
1379 1379
 	## Website commands
1380 1380
 	{"cmd":"ws-create", "label":"Create Website from bucket", "param":"s3://BUCKET", "func":cmd_website_create, "argc":1},
1381 1381
 	{"cmd":"ws-delete", "label":"Delete Website", "param":"s3://BUCKET", "func":cmd_website_delete, "argc":1},
1382
-	{"cmd":"ws-list", "label":"List Websites", "param":"s3://BUCKET", "func":cmd_website_list, "argc":1},
1382
+	{"cmd":"ws-info", "label":"Info about Website", "param":"s3://BUCKET", "func":cmd_website_info, "argc":1},
1383 1383
 
1384 1384
 	## CloudFront commands
1385 1385
 	{"cmd":"cflist", "label":"List CloudFront distribution points", "param":"", "func":CfCmd.info, "argc":0},