configure-s3-website 1.1.2 → 1.2.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.
data/README.md CHANGED
@@ -44,6 +44,29 @@ configuration file a row like this:
44
44
  The valid *s3_endpoint* values consist of the [S3 location constraint
45
45
  values](http://docs.amazonwebservices.com/general/latest/gr/rande.html#s3_region).
46
46
 
47
+ ### Configuring redirects
48
+
49
+ You can configure redirects on your S3 website by adding `routing_rules` into
50
+ the config file.
51
+
52
+ Here is an example:
53
+
54
+ ````yaml
55
+ routing_rules:
56
+ - condition:
57
+ key_prefix_equals: blog/some_path
58
+ redirect:
59
+ host_name: blog.example.com
60
+ replace_key_prefix_with: some_new_path/
61
+ http_redirect_code: 301
62
+ ````
63
+
64
+ You can use any routing rule property that the [REST
65
+ API](http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTwebsite.html)
66
+ supports. All you have to do is to replace the uppercase letter in AWS XML with
67
+ an underscore and an undercase version of the same letter. For example,
68
+ `KeyPrefixEquals` becomes `key_prefix_equals` in the config file.
69
+
47
70
  ## How does `configure-s3-website` work?
48
71
 
49
72
  It calls the [PUT Bucket
@@ -79,10 +102,22 @@ API with the following JSON:
79
102
  }
80
103
  ```
81
104
 
105
+ If you define `routing_rules` in the config file, `configure-s3-website` will
106
+ make an additional call to the AWS API.
107
+
82
108
  ## Development
83
109
 
84
110
  * This project uses [Semantic Versioning](http://semver.org)
85
111
 
112
+ ## Credit
113
+
114
+ Created by Lauri Lehmijoki.
115
+
116
+ Big thanks to the following contributors (in alphabetical order):
117
+
118
+ * SlawD
119
+ * Steve Schwartz
120
+
86
121
  ## License
87
122
 
88
123
  See the file LICENSE.
@@ -2,6 +2,10 @@
2
2
 
3
3
  This project uses [Semantic Versioning](http://semver.org).
4
4
 
5
+ ## 1.2.0
6
+
7
+ * Support configuring redirects on the S3 website
8
+
5
9
  ## 1.1.2
6
10
 
7
11
  * Use UTC time when signing requests
@@ -0,0 +1,203 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: put
5
+ uri: https://s3.amazonaws.com/website-with-redirects/?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, 05 May 2013 17:15:13 EEST
15
+ Content-Type:
16
+ - ''
17
+ Content-Length:
18
+ - '298'
19
+ Authorization:
20
+ - AWS
21
+ response:
22
+ status:
23
+ code: 404
24
+ message: Not Found
25
+ headers:
26
+ X-Amz-Request-Id:
27
+ - 2DFD9AF9459D6EBA
28
+ X-Amz-Id-2:
29
+ - xuu
30
+ Content-Type:
31
+ - application/xml
32
+ Transfer-Encoding:
33
+ - chunked
34
+ Date:
35
+ - Sun, 05 May 2013 14:15:16 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>website-with-redirects</BucketName><RequestId>2DFD9AF9459D6EBA</RequestId><HostId>+mKBZUngt5PWBeABkXaUZFengM23XP683j5NXVkvIlDnfkfsYdU6jJuoRMJaQZF/</HostId></Error>'
45
+ http_version:
46
+ recorded_at: Sun, 05 May 2013 14:15:14 GMT
47
+ - request:
48
+ method: put
49
+ uri: https://s3.amazonaws.com/website-with-redirects
50
+ body:
51
+ encoding: US-ASCII
52
+ string: ''
53
+ headers:
54
+ Date:
55
+ - Sun, 05 May 2013 17:15:14 EEST
56
+ Content-Type:
57
+ - ''
58
+ Content-Length:
59
+ - '0'
60
+ Authorization:
61
+ - AWS
62
+ response:
63
+ status:
64
+ code: 200
65
+ message: OK
66
+ headers:
67
+ X-Amz-Id-2:
68
+ - Hn9luS/t3JpOkwnXRnyVOJ+HlYVS1PNZ//XVrAiZjP95xY4Aot5X0X8S+rQ8eDwp
69
+ X-Amz-Request-Id:
70
+ - 60B4854F860963D6
71
+ Date:
72
+ - Sun, 05 May 2013 14:15:18 GMT
73
+ Location:
74
+ - /website-with-redirects
75
+ Content-Length:
76
+ - '0'
77
+ Server:
78
+ - AmazonS3
79
+ body:
80
+ encoding: US-ASCII
81
+ string: ''
82
+ http_version:
83
+ recorded_at: Sun, 05 May 2013 14:15:15 GMT
84
+ - request:
85
+ method: put
86
+ uri: https://s3.amazonaws.com/website-with-redirects/?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, 05 May 2013 17:15:15 EEST
96
+ Content-Type:
97
+ - ''
98
+ Content-Length:
99
+ - '298'
100
+ Authorization:
101
+ - AWS
102
+ response:
103
+ status:
104
+ code: 200
105
+ message: OK
106
+ headers:
107
+ X-Amz-Id-2:
108
+ - bBCMImUYwikvIu5M1aFYsEyouPNM3xQoLsNpKeXjSVbe3ZJJZLUdR0OMF+3zFX+y
109
+ X-Amz-Request-Id:
110
+ - 2E4F04F9CB9F14F9
111
+ Date:
112
+ - Sun, 05 May 2013 14:15:19 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, 05 May 2013 14:15:16 GMT
122
+ - request:
123
+ method: put
124
+ uri: https://s3.amazonaws.com/website-with-redirects/?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:::website-with-redirects/*\"]\n }]\n
131
+ \ }"
132
+ headers:
133
+ Date:
134
+ - Sun, 05 May 2013 17:15:16 EEST
135
+ Content-Type:
136
+ - ''
137
+ Content-Length:
138
+ - '291'
139
+ Authorization:
140
+ - AWS
141
+ response:
142
+ status:
143
+ code: 204
144
+ message: No Content
145
+ headers:
146
+ X-Amz-Id-2:
147
+ - ijsq/+jpLhfwLnUJF2xKj5x+1x9YhapYBVk38FDb7BYQ2vRsiFUydmrYD8PIfr0b
148
+ X-Amz-Request-Id:
149
+ - EA0FDFDE47845326
150
+ Date:
151
+ - Sun, 05 May 2013 14:15:19 GMT
152
+ Server:
153
+ - AmazonS3
154
+ body:
155
+ encoding: US-ASCII
156
+ string: ''
157
+ http_version:
158
+ recorded_at: Sun, 05 May 2013 14:15:17 GMT
159
+ - request:
160
+ method: put
161
+ uri: https://s3.amazonaws.com/website-with-redirects/?website
162
+ body:
163
+ encoding: US-ASCII
164
+ string: ! "\n <WebsiteConfiguration xmlns='http://s3.amazonaws.com/doc/2006-03-01/'>\n
165
+ \ <IndexDocument>\n <Suffix>index.html</Suffix>\n </IndexDocument>\n
166
+ \ <ErrorDocument>\n <Key>error.html</Key>\n </ErrorDocument>\n
167
+ \ <RoutingRules>\n \n <RoutingRule>\n \n
168
+ \ <Condition>\n <KeyPrefixEquals>blog/some_path</KeyPrefixEquals></Condition>\n
169
+ \ <Redirect>\n <HostName>blog.example.com</HostName>\n
170
+ \ <ReplaceKeyPrefixWith>some_new_path/</ReplaceKeyPrefixWith>\n
171
+ \ <HttpRedirectCode>301</HttpRedirectCode></Redirect>\n </RoutingRule>\n
172
+ \ \n </RoutingRules>\n </WebsiteConfiguration>\n
173
+ \ "
174
+ headers:
175
+ Date:
176
+ - Sun, 05 May 2013 17:15:17 EEST
177
+ Content-Type:
178
+ - ''
179
+ Content-Length:
180
+ - '786'
181
+ Authorization:
182
+ - AWS
183
+ response:
184
+ status:
185
+ code: 200
186
+ message: OK
187
+ headers:
188
+ X-Amz-Id-2:
189
+ - aAt1wLoQJwkJHLmF8wHSX8fbfyVVacGEv3PO/Cx6y4kDkEqzp2v33l99ZWBH4dVt
190
+ X-Amz-Request-Id:
191
+ - 1C1A5EB5ABB7198A
192
+ Date:
193
+ - Sun, 05 May 2013 14:15:20 GMT
194
+ Content-Length:
195
+ - '0'
196
+ Server:
197
+ - AmazonS3
198
+ body:
199
+ encoding: US-ASCII
200
+ string: ''
201
+ http_version:
202
+ recorded_at: Sun, 05 May 2013 14:15:18 GMT
203
+ recorded_with: VCR 2.3.0
@@ -9,6 +9,7 @@ Feature: configure an S3 bucket to function as a website
9
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
+ No redirects to configure for name-of-a-new-bucket bucket
12
13
 
13
14
  """
14
15
 
@@ -38,5 +39,19 @@ Feature: configure an S3 bucket to function as a website
38
39
  """
39
40
  Bucket name-of-an-existing-bucket now functions as a website
40
41
  Bucket name-of-an-existing-bucket is now readable to the whole world
42
+ No redirects to configure for name-of-an-existing-bucket bucket
43
+
44
+ """
45
+
46
+ @redirects
47
+ Scenario: The user wants to configure redirects for the S3 website
48
+ Given my config file is in "features/support/sample_config_files/redirects.yml"
49
+ When I run the configure-s3-website command
50
+ Then the output should be
51
+ """
52
+ Created bucket website-with-redirects in the US Standard Region
53
+ Bucket website-with-redirects now functions as a website
54
+ Bucket website-with-redirects is now readable to the whole world
55
+ 1 redirects configured for website-with-redirects bucket
41
56
 
42
57
  """
@@ -0,0 +1,10 @@
1
+ s3_id: foo
2
+ s3_secret: xuu
3
+ s3_bucket: website-with-redirects
4
+ routing_rules:
5
+ - condition:
6
+ key_prefix_equals: blog/some_path
7
+ redirect:
8
+ host_name: blog.example.com
9
+ replace_key_prefix_with: some_new_path/
10
+ http_redirect_code: 301
@@ -9,4 +9,5 @@ VCR.cucumber_tags do |t|
9
9
  t.tag '@bucket-does-not-exist'
10
10
  t.tag '@bucket-does-not-exist-in-tokyo'
11
11
  t.tag '@bucket-exists'
12
+ t.tag '@redirects'
12
13
  end
@@ -11,5 +11,8 @@ module ConfigureS3Website
11
11
 
12
12
  def s3_endpoint
13
13
  end
14
+
15
+ def routing_rules
16
+ end
14
17
  end
15
18
  end
@@ -23,6 +23,10 @@ module ConfigureS3Website
23
23
  @config['s3_endpoint']
24
24
  end
25
25
 
26
+ def routing_rules
27
+ @config['routing_rules']
28
+ end
29
+
26
30
  private
27
31
 
28
32
  def parse_config(yaml_file_path)
@@ -10,6 +10,7 @@ module ConfigureS3Website
10
10
  begin
11
11
  enable_website_configuration(config_source)
12
12
  make_bucket_readable_to_everyone(config_source)
13
+ configure_bucket_redirects(config_source)
13
14
  rescue NoSuchBucketError
14
15
  create_bucket(config_source)
15
16
  retry
@@ -58,6 +59,45 @@ module ConfigureS3Website
58
59
  puts "Bucket #{config_source.s3_bucket_name} is now readable to the whole world"
59
60
  end
60
61
 
62
+ def self.configure_bucket_redirects(config_source)
63
+ routing_rules = config_source.routing_rules
64
+ if routing_rules.is_a?(Array) && routing_rules.any?
65
+ body = %|
66
+ <WebsiteConfiguration xmlns='http://s3.amazonaws.com/doc/2006-03-01/'>
67
+ <IndexDocument>
68
+ <Suffix>index.html</Suffix>
69
+ </IndexDocument>
70
+ <ErrorDocument>
71
+ <Key>error.html</Key>
72
+ </ErrorDocument>
73
+ <RoutingRules>
74
+ |
75
+ routing_rules.each do |routing_rule|
76
+ body << %|
77
+ <RoutingRule>
78
+ |
79
+ body << self.hash_to_api_xml(routing_rule, 7)
80
+ body << %|
81
+ </RoutingRule>
82
+ |
83
+ end
84
+ body << %|
85
+ </RoutingRules>
86
+ </WebsiteConfiguration>
87
+ |
88
+
89
+ call_s3_api(
90
+ path = "/#{config_source.s3_bucket_name}/?website",
91
+ method = Net::HTTP::Put,
92
+ body = body,
93
+ config_source = config_source
94
+ )
95
+ puts "#{routing_rules.size} redirects configured for #{config_source.s3_bucket_name} bucket"
96
+ else
97
+ puts "No redirects to configure for #{config_source.s3_bucket_name} bucket"
98
+ end
99
+ end
100
+
61
101
  def self.create_bucket(config_source)
62
102
  endpoint = Endpoint.new(config_source.s3_endpoint || '')
63
103
  body = if endpoint.region == 'US Standard'
@@ -115,6 +155,18 @@ module ConfigureS3Website
115
155
  hmac = OpenSSL::HMAC.digest(digest, config_source.s3_secret_access_key, can_string)
116
156
  signature = Base64.encode64(hmac).strip
117
157
  end
158
+
159
+ def self.hash_to_api_xml(hash={}, indent=0)
160
+ "".tap do |body|
161
+ hash.each do |key, value|
162
+ key_name = key.sub(/^[a-z\d]*/) { $&.capitalize }.gsub(/(?:_|(\/))([a-z\d]*)/) { $2.capitalize }
163
+ value = value.is_a?(Hash) ? self.hash_to_api_xml(value, indent+1) : value
164
+ body << "\n"
165
+ body << " " * indent * 2 # 2-space indentation formatting for xml
166
+ body << "<#{key_name}>#{value}</#{key_name}>"
167
+ end
168
+ end
169
+ end
118
170
  end
119
171
  end
120
172
 
@@ -1,3 +1,3 @@
1
1
  module ConfigureS3Website
2
- VERSION = '1.1.2'
2
+ VERSION = '1.2.0'
3
3
  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.1.2
4
+ version: 1.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -142,11 +142,13 @@ files:
142
142
  - features/cassettes/cucumber_tags/bucket-does-not-exist-in-tokyo.yml
143
143
  - features/cassettes/cucumber_tags/bucket-does-not-exist.yml
144
144
  - features/cassettes/cucumber_tags/bucket-exists.yml
145
+ - features/cassettes/cucumber_tags/redirects.yml
145
146
  - features/config_file.feature
146
147
  - features/configure_bucket.feature
147
148
  - features/step_definitions/steps.rb
148
149
  - features/support/env.rb
149
150
  - features/support/sample_config_files/endpoint_tokyo.yml
151
+ - features/support/sample_config_files/redirects.yml
150
152
  - features/support/sample_config_files/s3_config_with_existing_bucket.yml
151
153
  - features/support/sample_config_files/s3_config_with_non-existing_bucket.yml
152
154
  - features/support/vcr.rb
@@ -174,7 +176,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
174
176
  version: '0'
175
177
  segments:
176
178
  - 0
177
- hash: 925918613448529982
179
+ hash: -1020516680573187683
178
180
  required_rubygems_version: !ruby/object:Gem::Requirement
179
181
  none: false
180
182
  requirements:
@@ -183,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
183
185
  version: '0'
184
186
  segments:
185
187
  - 0
186
- hash: 925918613448529982
188
+ hash: -1020516680573187683
187
189
  requirements: []
188
190
  rubyforge_project:
189
191
  rubygems_version: 1.8.25
@@ -194,11 +196,13 @@ test_files:
194
196
  - features/cassettes/cucumber_tags/bucket-does-not-exist-in-tokyo.yml
195
197
  - features/cassettes/cucumber_tags/bucket-does-not-exist.yml
196
198
  - features/cassettes/cucumber_tags/bucket-exists.yml
199
+ - features/cassettes/cucumber_tags/redirects.yml
197
200
  - features/config_file.feature
198
201
  - features/configure_bucket.feature
199
202
  - features/step_definitions/steps.rb
200
203
  - features/support/env.rb
201
204
  - features/support/sample_config_files/endpoint_tokyo.yml
205
+ - features/support/sample_config_files/redirects.yml
202
206
  - features/support/sample_config_files/s3_config_with_existing_bucket.yml
203
207
  - features/support/sample_config_files/s3_config_with_non-existing_bucket.yml
204
208
  - features/support/vcr.rb