configure-s3-website 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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