configure-s3-website 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- configure-s3-website (0.0.1)
4
+ configure-s3-website (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/README.md CHANGED
@@ -6,8 +6,7 @@
6
6
  Configure an AWS S3 bucket to function as a website. Easily from the
7
7
  command-line interface.
8
8
 
9
- The Ruby gem `configure-s3-website` can configure an S3 bucket to function as a
10
- website. The bucket may or may not exist. If the bucket does not exist,
9
+ The bucket may or may not exist. If the bucket does not exist,
11
10
  `configure-s3-website` will create it.
12
11
 
13
12
  ## Install
@@ -32,6 +31,19 @@ following command:
32
31
  Congratulations! You now have an S3 bucket that can act as a website server for
33
32
  you.
34
33
 
34
+ ### Specifying a non-standard S3 endpoint
35
+
36
+ By default, `configure-s3-website` creates the S3 website into the US Standard
37
+ region.
38
+
39
+ If you want to create the website into another region, add into the
40
+ configuration file a row like this:
41
+
42
+ s3_endpoint: EU
43
+
44
+ The valid *s3_endpoint* values consist of the [S3 location constraint
45
+ values](http://docs.amazonwebservices.com/general/latest/gr/rande.html#s3_region).
46
+
35
47
  ## How does `configure-s3-website` work?
36
48
 
37
49
  It calls the [PUT Bucket
@@ -69,4 +81,4 @@ API with the following JSON:
69
81
 
70
82
  ## License
71
83
 
72
- See file LICENSE.
84
+ See the file LICENSE.
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## 1.1.0
4
+
5
+ * Add support for non-standard AWS regions
@@ -6,7 +6,7 @@ spec = Gem::Specification.new do |s|
6
6
  s.email = 'lauri.lehmijoki@iki.fi'
7
7
  s.homepage = 'https://github.com/laurilehmijoki/configure-s3-website'
8
8
  s.platform = Gem::Platform::RUBY
9
- s.summary = 'Configure your S3 bucket to function as a web site'
9
+ s.summary = 'Configure your AWS S3 bucket to function as a web site'
10
10
  s.bindir = 'bin'
11
11
 
12
12
  s.add_development_dependency 'rspec', '~> 2.10.0'
@@ -0,0 +1,159 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: put
5
+ uri: https://s3-ap-northeast-1.amazonaws.com/name-of-a-new-bucket/?website
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ! "\n <WebsiteConfiguration xmlns='http://s3.amazonaws.com/doc/2006-03-01/'>\n
9
+ \ <IndexDocument>\n <Suffix>index.html</Suffix>\n </IndexDocument>\n
10
+ \ <ErrorDocument>\n <Key>error.html</Key>\n </ErrorDocument>\n
11
+ \ </WebsiteConfiguration>\n "
12
+ headers:
13
+ Date:
14
+ - Sun, 30 Dec 2012 19:59:34 EET
15
+ Content-Type:
16
+ - ''
17
+ Content-Length:
18
+ - '298'
19
+ Authorization:
20
+ - AWS foo
21
+ response:
22
+ status:
23
+ code: 404
24
+ message: Not Found
25
+ headers:
26
+ X-Amz-Request-Id:
27
+ - CD16DF6FF66B5922
28
+ X-Amz-Id-2:
29
+ - Xu30q0VM0aaYY091koYh8FIUDPB2KWOQLRPqnLulIK3ScIrMWgOwF7M2XRYIi5Vs
30
+ Content-Type:
31
+ - application/xml
32
+ Transfer-Encoding:
33
+ - chunked
34
+ Date:
35
+ - Sun, 30 Dec 2012 17:59:34 GMT
36
+ Connection:
37
+ - close
38
+ Server:
39
+ - AmazonS3
40
+ body:
41
+ encoding: US-ASCII
42
+ string: ! '<?xml version="1.0" encoding="UTF-8"?>
43
+
44
+ <Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>name-of-a-new-bucket</BucketName><RequestId>CD16DF6FF66B5922</RequestId><HostId>Xu30q0VM0aaYY091koYh8FIUDPB2KWOQLRPqnLulIK3ScIrMWgOwF7M2XRYIi5Vs</HostId></Error>'
45
+ http_version:
46
+ recorded_at: Sun, 30 Dec 2012 17:59:37 GMT
47
+ - request:
48
+ method: put
49
+ uri: https://s3-ap-northeast-1.amazonaws.com/name-of-a-new-bucket
50
+ body:
51
+ encoding: US-ASCII
52
+ string: ''
53
+ headers:
54
+ Date:
55
+ - Sun, 30 Dec 2012 19:59:37 EET
56
+ Content-Type:
57
+ - ''
58
+ Content-Length:
59
+ - '0'
60
+ Authorization:
61
+ - AWS foo
62
+ response:
63
+ status:
64
+ code: 200
65
+ message: OK
66
+ headers:
67
+ X-Amz-Id-2:
68
+ - 7HuGyurBPI/HV8DVtjtRufaMaLRJLU+vCch+BPuBAysYAlE7XS4Eavz7srhB2dTx
69
+ X-Amz-Request-Id:
70
+ - 431755651DECBBC5
71
+ Date:
72
+ - Sun, 30 Dec 2012 17:59:39 GMT
73
+ Location:
74
+ - /name-of-a-new-bucket
75
+ Content-Length:
76
+ - '0'
77
+ Server:
78
+ - AmazonS3
79
+ body:
80
+ encoding: US-ASCII
81
+ string: ''
82
+ http_version:
83
+ recorded_at: Sun, 30 Dec 2012 17:59:39 GMT
84
+ - request:
85
+ method: put
86
+ uri: https://s3-ap-northeast-1.amazonaws.com/name-of-a-new-bucket/?website
87
+ body:
88
+ encoding: US-ASCII
89
+ string: ! "\n <WebsiteConfiguration xmlns='http://s3.amazonaws.com/doc/2006-03-01/'>\n
90
+ \ <IndexDocument>\n <Suffix>index.html</Suffix>\n </IndexDocument>\n
91
+ \ <ErrorDocument>\n <Key>error.html</Key>\n </ErrorDocument>\n
92
+ \ </WebsiteConfiguration>\n "
93
+ headers:
94
+ Date:
95
+ - Sun, 30 Dec 2012 19:59:39 EET
96
+ Content-Type:
97
+ - ''
98
+ Content-Length:
99
+ - '298'
100
+ Authorization:
101
+ - AWS foo
102
+ response:
103
+ status:
104
+ code: 200
105
+ message: OK
106
+ headers:
107
+ X-Amz-Id-2:
108
+ - XZE0T/tWFNuRi6/yu1O+O3A7fJ/j2oas8ZqK4p6rLbaRxevXe44K/pAOsrB381ei
109
+ X-Amz-Request-Id:
110
+ - 514396AE3C1BB2C1
111
+ Date:
112
+ - Sun, 30 Dec 2012 17:59:41 GMT
113
+ Content-Length:
114
+ - '0'
115
+ Server:
116
+ - AmazonS3
117
+ body:
118
+ encoding: US-ASCII
119
+ string: ''
120
+ http_version:
121
+ recorded_at: Sun, 30 Dec 2012 17:59:42 GMT
122
+ - request:
123
+ method: put
124
+ uri: https://s3-ap-northeast-1.amazonaws.com/name-of-a-new-bucket/?policy
125
+ body:
126
+ encoding: US-ASCII
127
+ string: ! "{\n \"Version\":\"2008-10-17\",\n \"Statement\":[{\n
128
+ \ \"Sid\":\"PublicReadForGetBucketObjects\",\n \"Effect\":\"Allow\",\n
129
+ \ \"Principal\": { \"AWS\": \"*\" },\n \"Action\":[\"s3:GetObject\"],\n
130
+ \ \"Resource\":[\"arn:aws:s3:::name-of-a-new-bucket/*\"]\n }]\n
131
+ \ }"
132
+ headers:
133
+ Date:
134
+ - Sun, 30 Dec 2012 19:59:42 EET
135
+ Content-Type:
136
+ - ''
137
+ Content-Length:
138
+ - '289'
139
+ Authorization:
140
+ - AWS foo
141
+ response:
142
+ status:
143
+ code: 204
144
+ message: No Content
145
+ headers:
146
+ X-Amz-Id-2:
147
+ - z/XdtqiOW0ihAGadAXwCNCAuE0OLeFisy4TN5e/3OmEI72dQxQjfftyXFSNNwOQN
148
+ X-Amz-Request-Id:
149
+ - 82E8EBABB5D150C5
150
+ Date:
151
+ - Sun, 30 Dec 2012 17:59:44 GMT
152
+ Server:
153
+ - AmazonS3
154
+ body:
155
+ encoding: US-ASCII
156
+ string: ''
157
+ http_version:
158
+ recorded_at: Sun, 30 Dec 2012 17:59:44 GMT
159
+ recorded_with: VCR 2.3.0
@@ -6,12 +6,30 @@ Feature: configure an S3 bucket to function as a website
6
6
  When I run the configure-s3-website command
7
7
  Then the output should be
8
8
  """
9
- Created bucket name-of-a-new-bucket
9
+ Created bucket name-of-a-new-bucket in the US Standard Region
10
10
  Bucket name-of-a-new-bucket now functions as a website
11
11
  Bucket name-of-a-new-bucket is now readable to the whole world
12
12
 
13
13
  """
14
14
 
15
+ @bucket-does-not-exist
16
+ Scenario: The configuration does not contain the 's3_endpoint' setting
17
+ Given my config file is in "features/support/sample_config_files/s3_config_with_non-existing_bucket.yml"
18
+ When I run the configure-s3-website command
19
+ Then the output should include
20
+ """
21
+ Created bucket name-of-a-new-bucket in the US Standard Region
22
+ """
23
+
24
+ @bucket-does-not-exist-in-tokyo
25
+ Scenario: Create bucket into the Tokyo region
26
+ Given my config file is in "features/support/sample_config_files/endpoint_tokyo.yml"
27
+ When I run the configure-s3-website command
28
+ Then the output should include
29
+ """
30
+ Created bucket name-of-a-new-bucket in the Asia Pacific (Tokyo) Region
31
+ """
32
+
15
33
  @bucket-exists
16
34
  Scenario: The bucket already exists
17
35
  Given my config file is in "features/support/sample_config_files/s3_config_with_existing_bucket.yml"
@@ -15,6 +15,10 @@ Then /^the output should be$/ do |expected_console_output|
15
15
  @console_output.should eq(expected_console_output)
16
16
  end
17
17
 
18
+ Then /^the output should include$/ do |expected_console_output|
19
+ @console_output.should include(expected_console_output)
20
+ end
21
+
18
22
  module Kernel
19
23
  require 'stringio'
20
24
 
@@ -0,0 +1,4 @@
1
+ s3_id: foo
2
+ s3_secret: foo
3
+ s3_bucket: name-of-a-new-bucket
4
+ s3_endpoint: ap-northeast-1
@@ -7,5 +7,6 @@ end
7
7
 
8
8
  VCR.cucumber_tags do |t|
9
9
  t.tag '@bucket-does-not-exist'
10
+ t.tag '@bucket-does-not-exist-in-tokyo'
10
11
  t.tag '@bucket-exists'
11
12
  end
@@ -8,5 +8,8 @@ module ConfigureS3Website
8
8
 
9
9
  def s3_bucket_name
10
10
  end
11
+
12
+ def s3_endpoint
13
+ end
11
14
  end
12
15
  end
@@ -19,6 +19,10 @@ module ConfigureS3Website
19
19
  @config['s3_bucket']
20
20
  end
21
21
 
22
+ def s3_endpoint
23
+ @config['s3_endpoint']
24
+ end
25
+
22
26
  private
23
27
 
24
28
  def parse_config(yaml_file_path)
@@ -59,19 +59,30 @@ module ConfigureS3Website
59
59
  end
60
60
 
61
61
  def self.create_bucket(config_source)
62
+ endpoint = Endpoint.new(config_source.s3_endpoint || '')
63
+ body = %|
64
+ <CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
65
+ <LocationConstraint>#{endpoint.location_constraint}</LocationConstraint>
66
+ </CreateBucketConfiguration >
67
+ |
62
68
  call_s3_api(
63
69
  path = "/#{config_source.s3_bucket_name}",
64
70
  method = Net::HTTP::Put,
65
- body = '',
71
+ body = body,
66
72
  config_source = config_source
67
73
  )
68
- puts "Created bucket #{config_source.s3_bucket_name}"
74
+ puts "Created bucket %s in the %s Region" %
75
+ [
76
+ config_source.s3_bucket_name,
77
+ endpoint.region
78
+ ]
69
79
  end
70
80
 
71
81
  def self.call_s3_api(path, method, body, config_source)
82
+ endpoint = Endpoint.new(config_source.s3_endpoint || '')
72
83
  date = Time.now.strftime("%a, %d %b %Y %H:%M:%S %Z")
73
84
  digest = create_digest(path, method, config_source, date)
74
- url = "https://s3.amazonaws.com#{path}"
85
+ url = "https://#{endpoint.hostname}#{path}"
75
86
  uri = URI.parse(url)
76
87
  req = method.new(uri.to_s)
77
88
  req.initialize_http_header({
@@ -104,6 +115,34 @@ end
104
115
 
105
116
  private
106
117
 
118
+ module ConfigureS3Website
119
+ class Endpoint
120
+ attr_reader :region, :location_constraint, :hostname
121
+
122
+ def initialize(location_constraint)
123
+ raise InvalidS3LocationConstraintError unless
124
+ location_constraints.has_key?location_constraint
125
+ @region = location_constraints.fetch(location_constraint)[:region]
126
+ @hostname = location_constraints.fetch(location_constraint)[:endpoint]
127
+ @location_constraint = location_constraint
128
+ end
129
+
130
+ # http://docs.amazonwebservices.com/general/latest/gr/rande.html#s3_region
131
+ def location_constraints
132
+ {
133
+ '' => { :region => 'US Standard', :endpoint => 's3.amazonaws.com' },
134
+ 'us-west-2' => { :region => 'US West (Oregon)', :endpoint => 's3-us-west-2.amazonaws.com' },
135
+ 'us-west-1' => { :region => 'US West (Northern California)', :endpoint => 's3-us-west-1.amazonaws.com' },
136
+ 'EU' => { :region => 'EU (Ireland)', :endpoint => 's3-eu-west-1.amazonaws.com' },
137
+ 'ap-southeast-1' => { :region => 'Asia Pacific (Singapore)', :endpoint => 's3-ap-southeast-1.amazonaws.com' },
138
+ 'ap-southeast-2' => { :region => 'Asia Pacific (Sydney)', :endpoint => 's3-ap-southeast-2.amazonaws.com' },
139
+ 'ap-northeast-1' => { :region => 'Asia Pacific (Tokyo)', :endpoint => 's3-ap-northeast-1.amazonaws.com' },
140
+ 'sa-east-1' => { :region => 'South America (Sao Paulo)', :endpoint => 's3-sa-east-1.amazonaws.com' }
141
+ }
142
+ end
143
+ end
144
+ end
145
+
107
146
  module ConfigureS3Website
108
147
  class ErrorParser
109
148
  def self.create_error(amazon_error_xml)
@@ -117,6 +156,9 @@ module ConfigureS3Website
117
156
  end
118
157
  end
119
158
 
159
+ class InvalidS3LocationConstraintError < StandardError
160
+ end
161
+
120
162
  class NoSuchBucketError < StandardError
121
163
  end
122
164
 
@@ -1,3 +1,3 @@
1
1
  module ConfigureS3Website
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -0,0 +1,18 @@
1
+ require 'rspec'
2
+ require 'configure-s3-website'
3
+
4
+ describe ConfigureS3Website::S3Client do
5
+ context '#create_bucket' do
6
+ let(:config_source) {
7
+ mock = double('config_source')
8
+ mock.stub(:s3_endpoint).and_return('invalid-location-constraint')
9
+ mock
10
+ }
11
+ it 'throws an error if the config contains an invalid S3 location constraint' do
12
+ expect {
13
+ extractor = ConfigureS3Website::S3Client.
14
+ send(:create_bucket, config_source)
15
+ }.to raise_error(InvalidS3LocationConstraintError)
16
+ end
17
+ end
18
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configure-s3-website
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-30 00:00:00.000000000 Z
12
+ date: 2013-01-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -138,13 +138,16 @@ files:
138
138
  - README.md
139
139
  - Rakefile
140
140
  - bin/configure-s3-website
141
+ - changelog.md
141
142
  - configure-s3-website.gemspec
143
+ - features/cassettes/cucumber_tags/bucket-does-not-exist-in-tokyo.yml
142
144
  - features/cassettes/cucumber_tags/bucket-does-not-exist.yml
143
145
  - features/cassettes/cucumber_tags/bucket-exists.yml
144
146
  - features/config_file.feature
145
147
  - features/configure_bucket.feature
146
148
  - features/step_definitions/steps.rb
147
149
  - features/support/env.rb
150
+ - features/support/sample_config_files/endpoint_tokyo.yml
148
151
  - features/support/sample_config_files/s3_config_with_existing_bucket.yml
149
152
  - features/support/sample_config_files/s3_config_with_non-existing_bucket.yml
150
153
  - features/support/vcr.rb
@@ -154,6 +157,7 @@ files:
154
157
  - lib/configure-s3-website/s3_client.rb
155
158
  - lib/configure-s3-website/version.rb
156
159
  - spec/config_extractor/file_config_extractor_spec.rb
160
+ - spec/s3_client_spec.rb
157
161
  - spec/sample_files/_config_file_with_eruby.yml
158
162
  homepage: https://github.com/laurilehmijoki/configure-s3-website
159
163
  licenses: []
@@ -178,16 +182,19 @@ rubyforge_project:
178
182
  rubygems_version: 1.8.24
179
183
  signing_key:
180
184
  specification_version: 3
181
- summary: Configure your S3 bucket to function as a web site
185
+ summary: Configure your AWS S3 bucket to function as a web site
182
186
  test_files:
187
+ - features/cassettes/cucumber_tags/bucket-does-not-exist-in-tokyo.yml
183
188
  - features/cassettes/cucumber_tags/bucket-does-not-exist.yml
184
189
  - features/cassettes/cucumber_tags/bucket-exists.yml
185
190
  - features/config_file.feature
186
191
  - features/configure_bucket.feature
187
192
  - features/step_definitions/steps.rb
188
193
  - features/support/env.rb
194
+ - features/support/sample_config_files/endpoint_tokyo.yml
189
195
  - features/support/sample_config_files/s3_config_with_existing_bucket.yml
190
196
  - features/support/sample_config_files/s3_config_with_non-existing_bucket.yml
191
197
  - features/support/vcr.rb
192
198
  - spec/config_extractor/file_config_extractor_spec.rb
199
+ - spec/s3_client_spec.rb
193
200
  - spec/sample_files/_config_file_with_eruby.yml