* Renamed ws-list to ws-info
* Prettyfied ws-info output
* Include website endpoint in ws-info output
* Fixed --ws-error handling
... | ... |
@@ -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}, |