right_aws 1.10.0 → 2.0.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.
Files changed (39) hide show
  1. data/History.txt +53 -15
  2. data/Manifest.txt +16 -0
  3. data/README.txt +10 -9
  4. data/Rakefile +13 -15
  5. data/lib/acf/right_acf_interface.rb +224 -118
  6. data/lib/acf/right_acf_origin_access_identities.rb +230 -0
  7. data/lib/acf/right_acf_streaming_interface.rb +236 -0
  8. data/lib/acw/right_acw_interface.rb +249 -0
  9. data/lib/as/right_as_interface.rb +699 -0
  10. data/lib/awsbase/right_awsbase.rb +232 -51
  11. data/lib/awsbase/support.rb +4 -0
  12. data/lib/ec2/right_ec2.rb +33 -1375
  13. data/lib/ec2/right_ec2_ebs.rb +452 -0
  14. data/lib/ec2/right_ec2_images.rb +373 -0
  15. data/lib/ec2/right_ec2_instances.rb +755 -0
  16. data/lib/ec2/right_ec2_monitoring.rb +70 -0
  17. data/lib/ec2/right_ec2_reserved_instances.rb +170 -0
  18. data/lib/ec2/right_ec2_security_groups.rb +280 -0
  19. data/lib/ec2/right_ec2_spot_instances.rb +399 -0
  20. data/lib/ec2/right_ec2_vpc.rb +571 -0
  21. data/lib/elb/right_elb_interface.rb +496 -0
  22. data/lib/rds/right_rds_interface.rb +998 -0
  23. data/lib/right_aws.rb +18 -4
  24. data/lib/s3/right_s3.rb +39 -7
  25. data/lib/s3/right_s3_interface.rb +77 -53
  26. data/lib/sdb/active_sdb.rb +203 -11
  27. data/lib/sdb/right_sdb_interface.rb +68 -45
  28. data/lib/sqs/right_sqs_gen2.rb +73 -16
  29. data/lib/sqs/right_sqs_gen2_interface.rb +131 -51
  30. data/lib/sqs/right_sqs_interface.rb +2 -4
  31. data/test/acf/test_right_acf.rb +10 -18
  32. data/test/rds/test_helper.rb +2 -0
  33. data/test/rds/test_right_rds.rb +120 -0
  34. data/test/s3/test_right_s3.rb +10 -8
  35. data/test/s3/test_right_s3_stubbed.rb +6 -4
  36. data/test/sdb/test_active_sdb.rb +70 -12
  37. data/test/sdb/test_right_sdb.rb +13 -7
  38. data/test/sqs/test_right_sqs_gen2.rb +104 -49
  39. metadata +103 -14
@@ -223,24 +223,62 @@ the source key.
223
223
  === 1.10.0
224
224
 
225
225
  Release Notes:
226
-
227
- The big new features are SDB's SQL-like query and query_with_attributes
228
- support as well as signature v2 support for all services. There are also
229
- numerous bug fixes, many of them reported and patched by users and
230
- customers.
231
-
232
226
  - AwsBase: signature v2 support added
233
- - AwsBase: fix the regex matching for xmlpath which didn't work in Ruby
234
- 1.8.7 (thanks to a customer report)
235
227
  - Ec2: describe_availability_zones improved to support regions
236
- - Ec2: Disabled retries when EC2 returns "ServiceUnavailable: Request limit
237
- exceeded"
238
- - Ec2: Use POST for large queries; this avoids truncation of large user data
239
- when launching instances (thanks to Bob for the report)
240
228
  - CloudFront: docs fixes
241
229
  - SDB: added: SQL-like query, select and query_with_attributes support
242
230
  - SDB: fixed no method error when searching for id that doesn't exist
243
- (thanks to multiple users for reporting this)
244
- - S3: Fixed overzealous URL-encoding when generating URLs for S3 keys
245
- (thanks to a bug report on the RubyForge forum)
246
231
 
232
+ === 1.11.0
233
+
234
+ Release Notes:
235
+ - Full Amazon RDS instances support added with RightAws::RdsInterface
236
+ - Boot from EBS support added
237
+ - VPC support added
238
+ - Latest EC2 API 2009-10-31 support added
239
+ - Some of bugs fixed
240
+
241
+ === 2.0.0
242
+
243
+ Release Notes:
244
+ - Added:
245
+ - Ruby 1.9 support
246
+ - Ec2:
247
+ - SpotInstances support
248
+ - m2.xlarge instances
249
+ - GetPasswordData API call (see get_password_data_v2)
250
+ - SecurityGroups support for Eucalyptus clouds
251
+ - EBS:
252
+ - :delete_on_termination field for volumes
253
+ - SimpleDB:
254
+ - BatchPutAttributes support
255
+ - ActiveSDB:
256
+ - Dynamic attribute accessors
257
+ - "Columns" support
258
+ - Simple Type Casting support
259
+ - ELB:
260
+ - API '2009-11-25' support (stickiness policies)
261
+ - ACF:
262
+ - API '2010-03-01' support (origin access policy and streaming distributions)
263
+ - Bunch of small issues were fixed
264
+ - Time objects were replaced by Strings (as Amazon returns them) to make the gem more consistent:
265
+ - :last_modified_time in:
266
+ RightAws::AcfInterface#incrementally_list_distributions,
267
+ RightAws::AcfInterface#create_distribution_by_config,
268
+ RightAws::AcfInterface#get_distribution,
269
+ RightAws::AcfInterface#get_distribution_config
270
+ - :timestamp in:
271
+ RightAws::AcwInterface#get_metric_statistics
272
+ - :aws_created_at in:
273
+ RightAws::Ec2#create_volume,
274
+ RightAws::Ec2#describe_volumes
275
+ - :aws_attached_at in:
276
+ RightAws::Ec2#attach_volume,
277
+ RightAws::Ec2#detach_volume,
278
+ RightAws::Ec2#describe_volumes
279
+ - :aws_started_at in:
280
+ RightAws::Ec2#describe_snapshots,
281
+ RightAws::Ec2#create_snapshot,
282
+ RightAws::Ec2#try_create_snapshot
283
+ - :created_time in:
284
+ RightAws::ElbInterface#describe_load_balancers
@@ -6,8 +6,19 @@ lib/awsbase/benchmark_fix.rb
6
6
  lib/awsbase/right_awsbase.rb
7
7
  lib/awsbase/support.rb
8
8
  lib/ec2/right_ec2.rb
9
+ lib/ec2/right_ec2_images.rb
10
+ lib/ec2/right_ec2_instances.rb
11
+ lib/ec2/right_ec2_security_groups.rb
12
+ lib/ec2/right_ec2_spot_instances.rb
13
+ lib/ec2/right_ec2_ebs.rb
14
+ lib/ec2/right_ec2_reserved_instances.rb
15
+ lib/ec2/right_ec2_vpc.rb
16
+ lib/ec2/right_ec2_monitoring.rb
9
17
  lib/right_aws.rb
10
18
  lib/s3/right_s3.rb
19
+ lib/acw/right_acw_interface.rb
20
+ lib/elb/right_elb_interface.rb
21
+ lib/as/right_as_interface.rb
11
22
  lib/s3/right_s3_interface.rb
12
23
  lib/sdb/active_sdb.rb
13
24
  lib/sdb/right_sdb_interface.rb
@@ -16,6 +27,9 @@ lib/sqs/right_sqs_gen2.rb
16
27
  lib/sqs/right_sqs_gen2_interface.rb
17
28
  lib/sqs/right_sqs_interface.rb
18
29
  lib/acf/right_acf_interface.rb
30
+ lib/acf/right_acf_streaming_interface.rb
31
+ lib/acf/right_acf_origin_access_identities.rb
32
+ lib/rds/right_rds_interface.rb
19
33
  test/ec2/test_helper.rb
20
34
  test/ec2/test_right_ec2.rb
21
35
  test/http_connection.rb
@@ -32,3 +46,5 @@ test/test_credentials.rb
32
46
  test/ts_right_aws.rb
33
47
  test/acf/test_helper.rb
34
48
  test/acf/test_right_acf.rb
49
+ test/rds/test_helper.rb
50
+ test/rds/test_right_rds.rb
data/README.txt CHANGED
@@ -9,17 +9,20 @@ The RightScale AWS gems have been designed to provide a robust, fast, and secure
9
9
  These gems have been used in production by RightScale since late 2006 and are being maintained to track enhancements made by Amazon.
10
10
  The RightScale AWS gems comprise:
11
11
 
12
- - RightAws::Ec2 -- interface to Amazon EC2 (Elastic Compute Cloud) and the
13
- associated EBS (Elastic Block Store)
12
+ - RightAws::Ec2 -- interface to Amazon EC2 (Elastic Compute Cloud), VPC (Virtual Private Cloud) and the associated EBS (Elastic Block Store)
14
13
  - RightAws::S3 and RightAws::S3Interface -- interface to Amazon S3 (Simple Storage Service)
15
- - RightAws::Sqs and RightAws::SqsInterface -- interface to first-generation Amazon SQS (Simple Queue Service) (API version 2007-05-01)
16
- - RightAws::SqsGen2 and RightAws::SqsGen2Interface -- interface to second-generation Amazon SQS (Simple Queue Service) (API version 2008-01-01)
14
+ - RightAws::Sqs and RightAws::SqsInterface -- interface to first-generation Amazon SQS (Simple Queue Service)
15
+ - RightAws::SqsGen2 and RightAws::SqsGen2Interface -- interface to second-generation Amazon SQS (Simple Queue Service)
17
16
  - RightAws::SdbInterface and RightAws::ActiveSdb -- interface to Amazon SDB (SimpleDB)
18
17
  - RightAws::AcfInterface -- interface to Amazon CloudFront, a content distribution service
18
+ - RightAws::AsInterface -- interface to Amazon Auto Scaling
19
+ - RightAws::AcwInterface -- interface to Amazon Cloud Watch
20
+ - RightAws::ElbInterface -- interface to Amazon Elastic Load Balancer
21
+ - RightAws::RdsInterface -- interface to Amazon RDS instances
19
22
 
20
23
  == FEATURES:
21
24
 
22
- - Full programmmatic access to EC2, EBS, S3, SQS, SDB, and CloudFront.
25
+ - Full programmmatic access to EC2, EBS, S3, SQS, SDB, CloudFront, AS, ACW, ELB and RDS.
23
26
  - Complete error handling: all operations check for errors and report complete
24
27
  error information by raising an AwsError.
25
28
  - Persistent HTTP connections with robust network-level retry layer using
@@ -38,7 +41,7 @@ The RightScale AWS gems comprise:
38
41
  AWS accounts.
39
42
  - Support for both first- and second-generation SQS (API versions 2007-05-01
40
43
  and 2008-01-01). These versions of SQS are not compatible.
41
- - Support for signature versions 0, 1 and 2 on all services.
44
+ - Support for signature versions 0 and 1 on SQS, SDB, and EC2.
42
45
  - Interoperability with any cloud running Eucalyptus (http://eucalyptus.cs.ucsb.edu)
43
46
  - Test suite (requires AWS account to do "live" testing).
44
47
 
@@ -119,9 +122,7 @@ multithreaded mode.
119
122
  'incompatible Net::HTTP monkey-patch'
120
123
 
121
124
  This is due to a conflict between the right_http_connection gem and another
122
- gem required by attachment_fu. It may be possible to require right_aws (and
123
- thus right_http_connection) in the .after_initialize method of the config object in
124
- environment.rb (check the docs for Rails::Configuration.after_initialize).
125
+ gem required by attachment_fu.
125
126
 
126
127
  - 8/07: Amazon has changed the semantics of the SQS service. A
127
128
  new queue may not be created within 60 seconds of the destruction of any
data/Rakefile CHANGED
@@ -10,36 +10,27 @@ require 'lib/right_aws.rb'
10
10
  testglobs = ["test/ts_right_aws.rb"]
11
11
 
12
12
 
13
- # Suppress Hoe's self-inclusion as a dependency for our Gem. This also keeps
14
- # Rake & rubyforge out of the dependency list. Users must manually install
13
+ # Suppress Hoe's self-inclusion as a dependency for our Gem. This also keeps
14
+ # Rake & rubyforge out of the dependency list. Users must manually install
15
15
  # these gems to run tests, etc.
16
- # TRB 2/24/09: also do this for the extra_dev_deps array present in newer hoes.
17
- # Older versions of RubyGems will try to install developer-dependencies as
18
- # required runtime dependencies. It would be great to take advantage of the extra dev deps, but not
19
- # at the cost of requiring many additional dependencies if the user is running an older RubyGems.
20
16
  class Hoe
21
17
  def extra_deps
22
18
  @extra_deps.reject do |x|
23
19
  Array(x).first == 'hoe'
24
20
  end
25
21
  end
26
- def extra_dev_deps
27
- @extra_dev_deps.reject do |x|
28
- Array(x).first == 'hoe'
29
- end
30
- end
31
22
  end
32
23
 
33
24
  Hoe.new('right_aws', RightAws::VERSION::STRING) do |p|
34
- p.rubyforge_name = 'rightscale'
25
+ p.rubyforge_name = 'rightaws'
35
26
  p.author = 'RightScale, Inc.'
36
- p.email = 'rubygems@rightscale.com'
37
- p.summary = 'Interface classes for the Amazon EC2/EBS, SQS, S3, SDB, and ACF Web Services'
27
+ p.email = 'support@rightscale.com'
28
+ p.summary = 'Interface classes for the Amazon EC2, SQS, and S3 Web Services'
38
29
  p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
39
30
  p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
40
31
  p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
41
32
  p.remote_rdoc_dir = "/right_aws_gem_doc"
42
- p.extra_deps = [['right_http_connection','>= 1.2.4']]
33
+ p.extra_deps = [['right_http_connection','>= 1.2.1']]
43
34
  p.test_globs = testglobs
44
35
  end
45
36
 
@@ -109,4 +100,11 @@ task :testacf do
109
100
  require 'test/acf/test_right_acf.rb'
110
101
  end
111
102
 
103
+ desc "Test RDS interface"
104
+ task :testrds do
105
+ require 'test/test_credentials'
106
+ TestCredentials.get_credentials
107
+ require 'test/rds/test_right_rds.rb'
108
+ end
109
+
112
110
  # vim: syntax=Ruby
@@ -20,7 +20,6 @@
20
20
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #
23
-
24
23
  module RightAws
25
24
 
26
25
  # = RightAws::AcfInterface -- RightScale Amazon's CloudFront interface
@@ -42,7 +41,7 @@ module RightAws
42
41
  # :origin => "my-bucket.s3.amazonaws.com",
43
42
  # :cnames => ["x1.my-awesome-site.net", "x1.my-awesome-site.net"]
44
43
  # :comment => "My comments",
45
- # :last_modified_time => Wed Sep 10 17:00:04 UTC 2008 }, ..., {...} ]
44
+ # :last_modified_time => "2008-09-10T17:00:04.000Z" }, ..., {...} ]
46
45
  #
47
46
  # distibution = list.first
48
47
  #
@@ -56,7 +55,7 @@ module RightAws
56
55
  # :aws_id => "E2REJM3VUN5RSI",
57
56
  # :comment => "Woo-Hoo!",
58
57
  # :origin => "my-bucket.s3.amazonaws.com",
59
- # :last_modified_time => Wed Sep 10 17:00:54 UTC 2008 }
58
+ # :last_modified_time => "2008-09-10T17:00:54.000Z" }
60
59
  #
61
60
  # config = acf.get_distribution_config(distibution[:aws_id]) #=>
62
61
  # {:enabled => true,
@@ -76,7 +75,7 @@ module RightAws
76
75
 
77
76
  include RightAwsBaseInterface
78
77
 
79
- API_VERSION = "2008-06-30"
78
+ API_VERSION = "2010-03-01"
80
79
  DEFAULT_HOST = 'cloudfront.amazonaws.com'
81
80
  DEFAULT_PORT = 443
82
81
  DEFAULT_PROTOCOL = 'https'
@@ -93,22 +92,23 @@ module RightAws
93
92
  # Create a new handle to a CloudFront account. All handles share the same per process or per thread
94
93
  # HTTP connection to CloudFront. Each handle is for a specific account. The params have the
95
94
  # following options:
95
+ # * <tt>:endpoint_url</tt> a fully qualified url to Amazon API endpoint (this overwrites: :server, :port, :service, :protocol). Example: 'https://cloudfront.amazonaws.com'
96
96
  # * <tt>:server</tt>: CloudFront service host, default: DEFAULT_HOST
97
97
  # * <tt>:port</tt>: CloudFront service port, default: DEFAULT_PORT
98
98
  # * <tt>:protocol</tt>: 'http' or 'https', default: DEFAULT_PROTOCOL
99
99
  # * <tt>:multi_thread</tt>: true=HTTP connection per thread, false=per process
100
100
  # * <tt>:logger</tt>: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT
101
- # * <tt>:cache</tt>: true/false: caching for list_distributions method, default: false.
102
101
  #
103
102
  # acf = RightAws::AcfInterface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX',
104
- # {:multi_thread => true, :logger => Logger.new('/tmp/x.log')}) #=> #<RightAws::AcfInterface::0xb7b3c30c>
103
+ # {:logger => Logger.new('/tmp/x.log')}) #=> #<RightAws::AcfInterface::0xb7b3c30c>
105
104
  #
106
105
  def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
107
- init({ :name => 'ACF',
108
- :default_host => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).host : DEFAULT_HOST,
109
- :default_port => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).port : DEFAULT_PORT,
110
- :default_service => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).path : DEFAULT_PATH,
111
- :default_protocol => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).scheme : DEFAULT_PROTOCOL },
106
+ init({ :name => 'ACF',
107
+ :default_host => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).host : DEFAULT_HOST,
108
+ :default_port => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).port : DEFAULT_PORT,
109
+ :default_service => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).path : DEFAULT_PATH,
110
+ :default_protocol => ENV['ACF_URL'] ? URI.parse(ENV['ACF_URL']).scheme : DEFAULT_PROTOCOL,
111
+ :default_api_version => ENV['ACF_API_VERSION'] || API_VERSION },
112
112
  aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'],
113
113
  aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'],
114
114
  params)
@@ -119,14 +119,20 @@ module RightAws
119
119
  #-----------------------------------------------------------------
120
120
 
121
121
  # Generates request hash for REST API.
122
- def generate_request(method, path, body=nil, headers={}) # :nodoc:
122
+ def generate_request(method, path, params={}, body=nil, headers={}) # :nodoc:
123
+ # Params
124
+ params.delete_if{ |key, val| val.blank? }
125
+ unless params.blank?
126
+ path += "?" + params.to_a.collect{ |key,val| "#{AwsUtils::amz_escape(key)}=#{AwsUtils::amz_escape(val.to_s)}" }.join("&")
127
+ end
128
+ # Headers
123
129
  headers['content-type'] ||= 'text/xml' if body
124
130
  headers['date'] = Time.now.httpdate
125
131
  # Auth
126
132
  signature = AwsUtils::sign(@aws_secret_access_key, headers['date'])
127
133
  headers['Authorization'] = "AWS #{@aws_access_key_id}:#{signature}"
128
134
  # Request
129
- path = "#{@params[:default_service]}/#{API_VERSION}/#{path}"
135
+ path = "#{@params[:service]}#{@params[:api_version]}/#{path}"
130
136
  request = "Net::HTTP::#{method.capitalize}".constantize.new(path)
131
137
  request.body = body if body
132
138
  # Set request headers
@@ -141,9 +147,7 @@ module RightAws
141
147
  # Sends request to Amazon and parses the response.
142
148
  # Raises AwsError if any banana happened.
143
149
  def request_info(request, parser, &block) # :nodoc:
144
- thread = @params[:multi_thread] ? Thread.current : Thread.main
145
- thread[:acf_connection] ||= Rightscale::HttpConnection.new(:exception => RightAws::AwsError, :logger => @logger)
146
- request_info_impl(thread[:acf_connection], @@bench, request, parser, &block)
150
+ request_info_impl(:acf_connection, @@bench, request, parser, &block)
147
151
  end
148
152
 
149
153
  #-----------------------------------------------------------------
@@ -158,10 +162,6 @@ module RightAws
158
162
  REXML::Text::unnormalize(text)
159
163
  end
160
164
 
161
- def xmlns # :nodoc:
162
- %Q{"http://#{@params[:server]}/doc/#{API_VERSION}/"}
163
- end
164
-
165
165
  def generate_call_reference # :nodoc:
166
166
  result = Time.now.strftime('%Y%m%d%H%M%S')
167
167
  10.times{ result << rand(10).to_s }
@@ -174,11 +174,62 @@ module RightAws
174
174
  hash
175
175
  end
176
176
 
177
+ def distribution_config_to_xml(config, xml_wrapper='DistributionConfig') # :nodoc:
178
+ cnames = ''
179
+ logging = ''
180
+ origin_access_identity = ''
181
+ trusted_signers = ''
182
+ # CNAMES
183
+ unless config[:cnames].blank?
184
+ Array(config[:cnames]).each { |cname| cnames += " <CNAME>#{cname}</CNAME>\n" }
185
+ end
186
+ # Logging
187
+ unless config[:logging].blank?
188
+ logging = " <Logging>\n" +
189
+ " <Bucket>#{config[:logging][:bucket]}</Bucket>\n" +
190
+ " <Prefix>#{config[:logging][:prefix]}</Prefix>\n" +
191
+ " </Logging>\n"
192
+ end
193
+ # Origin Access Identity
194
+ unless config[:origin_access_identity].blank?
195
+ origin_access_identity = config[:origin_access_identity]
196
+ unless origin_access_identity[%r{^origin-access-identity}]
197
+ origin_access_identity = "origin-access-identity/cloudfront/#{origin_access_identity}"
198
+ end
199
+ origin_access_identity = " <OriginAccessIdentity>#{origin_access_identity}</OriginAccessIdentity>\n"
200
+ end
201
+ # Trusted Signers
202
+ unless config[:trusted_signers].blank?
203
+ trusted_signers = " <TrustedSigners>\n"
204
+ Array(config[:trusted_signers]).each do |trusted_signer|
205
+ trusted_signers += if trusted_signer.to_s[/self/i]
206
+ " <Self/>\n"
207
+ else
208
+ " <AwsAccountNumber>#{trusted_signer}</AwsAccountNumber>\n"
209
+ end
210
+ end
211
+ trusted_signers += " </TrustedSigners>\n"
212
+ end
213
+
214
+ # XML
215
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
216
+ "<#{xml_wrapper} xmlns=\"http://#{@params[:server]}/doc/#{API_VERSION}/\">\n" +
217
+ " <Origin>#{config[:origin]}</Origin>\n" +
218
+ " <CallerReference>#{config[:caller_reference]}</CallerReference>\n" +
219
+ " <Comment>#{AcfInterface::escape(config[:comment].to_s)}</Comment>\n" +
220
+ " <Enabled>#{config[:enabled]}</Enabled>\n" +
221
+ cnames +
222
+ logging +
223
+ origin_access_identity +
224
+ trusted_signers +
225
+ "</#{xml_wrapper}>"
226
+ end
227
+
177
228
  #-----------------------------------------------------------------
178
229
  # API Calls:
179
230
  #-----------------------------------------------------------------
180
231
 
181
- # List distributions.
232
+ # List all distributions.
182
233
  # Returns an array of distributions or RightAws::AwsError exception.
183
234
  #
184
235
  # acf.list_distributions #=>
@@ -191,14 +242,62 @@ module RightAws
191
242
  # :last_modified_time => Wed Sep 10 17:00:04 UTC 2008 }, ..., {...} ]
192
243
  #
193
244
  def list_distributions
194
- request_hash = generate_request('GET', 'distribution')
195
- request_cache_or_info :list_distributions, request_hash, AcfDistributionListParser, @@bench
245
+ result = []
246
+ incrementally_list_distributions do |response|
247
+ result += response[:distributions]
248
+ true
249
+ end
250
+ result
251
+ end
252
+
253
+ # Incrementally list distributions.
254
+ #
255
+ # Optional params: +:marker+ and +:max_items+.
256
+ #
257
+ # # get first distribution
258
+ # incrementally_list_distributions(:max_items => 1) #=>
259
+ # {:distributions=>
260
+ # [{:status=>"Deployed",
261
+ # :aws_id=>"E2Q0AOOMFNPSYL",
262
+ # :origin=>"my-bucket.s3.amazonaws.com",
263
+ # :domain_name=>"d1s5gmdtmafnre.6hops.net",
264
+ # :comment=>"ONE LINE OF COMMENT",
265
+ # :last_modified_time=>"2008-10-22T19:31:23.000Z",
266
+ # :enabled=>true,
267
+ # :cnames=>[]}],
268
+ # :is_truncated=>true,
269
+ # :max_items=>1,
270
+ # :marker=>"",
271
+ # :next_marker=>"E2Q0AOOMFNPSYL"}
272
+ #
273
+ # # get max 100 distributions (the list will be restricted by a default MaxItems value ==100 )
274
+ # incrementally_list_distributions
275
+ #
276
+ # # list distributions by 10
277
+ # incrementally_list_distributions(:max_items => 10) do |response|
278
+ # puts response.inspect # a list of 10 distributions
279
+ # true # return false if the listing should be broken otherwise use true
280
+ # end
281
+ #
282
+ def incrementally_list_distributions(params={}, &block)
283
+ opts = {}
284
+ opts['MaxItems'] = params[:max_items] if params[:max_items]
285
+ opts['Marker'] = params[:marker] if params[:marker]
286
+ last_response = nil
287
+ loop do
288
+ link = generate_request('GET', 'distribution', opts)
289
+ last_response = request_info(link, AcfDistributionListParser.new(:logger => @logger))
290
+ opts['Marker'] = last_response[:next_marker]
291
+ break unless block && block.call(last_response) && !last_response[:next_marker].blank?
292
+ end
293
+ last_response
196
294
  end
197
295
 
198
296
  # Create a new distribution.
199
297
  # Returns the just created distribution or RightAws::AwsError exception.
200
298
  #
201
- # acf.create_distribution('bucket-for-k-dzreyev.s3.amazonaws.com', 'Woo-Hoo!', true, ['web1.my-awesome-site.net'] ) #=>
299
+ # acf.create_distribution('my-bucket.s3.amazonaws.com', 'Woo-Hoo!', true, ['web1.my-awesome-site.net'], nil,
300
+ # { :prefix=>"log/", :bucket=>"my-logs.s3.amazonaws.com" } ) #=>
202
301
  # {:comment => "Woo-Hoo!",
203
302
  # :enabled => true,
204
303
  # :location => "https://cloudfront.amazonaws.com/2008-06-30/distribution/E2REJM3VUN5RSI",
@@ -206,30 +305,26 @@ module RightAws
206
305
  # :aws_id => "E2REJM3VUN5RSI",
207
306
  # :domain_name => "d3dxv71tbbt6cd.6hops.net",
208
307
  # :origin => "my-bucket.s3.amazonaws.com",
209
- # :cnames => ["web1.my-awesome-site.net"]
210
- # :last_modified_time => Wed Sep 10 17:00:54 UTC 2008,
308
+ # :cnames => ["web1.my-awesome-site.net"],
309
+ # :logging => { :prefix => "log/",
310
+ # :bucket => "my-logs.s3.amazonaws.com"},
311
+ # :last_modified_time => "2008-10-22T19:31:23.000Z",
211
312
  # :caller_reference => "200809102100536497863003"}
212
313
  #
213
- def create_distribution(origin, comment='', enabled=true, cnames=[], caller_reference=nil)
214
- # join CNAMES
215
- cnames_str = ''
216
- unless cnames.blank?
217
- cnames.to_a.each { |cname| cnames_str += "\n <CNAME>#{cname}</CNAME>" }
218
- end
219
- # reference
220
- caller_reference ||= generate_call_reference
221
- body = <<-EOXML
222
- <?xml version="1.0" encoding="UTF-8"?>
223
- <DistributionConfig xmlns=#{xmlns}>
224
- <Origin>#{origin}</Origin>
225
- <CallerReference>#{caller_reference}</CallerReference>
226
- #{cnames_str.lstrip}
227
- <Comment>#{AcfInterface::escape(comment.to_s)}</Comment>
228
- <Enabled>#{enabled}</Enabled>
229
- </DistributionConfig>
230
- EOXML
231
- request_hash = generate_request('POST', 'distribution', body.strip)
232
- merge_headers(request_info(request_hash, AcfDistributionParser.new))
314
+ def create_distribution(origin, comment='', enabled=true, cnames=[], caller_reference=nil, logging={})
315
+ config = { :origin => origin,
316
+ :comment => comment,
317
+ :enabled => enabled,
318
+ :cnames => Array(cnames),
319
+ :caller_reference => caller_reference }
320
+ config[:logging] = logging unless logging.blank?
321
+ create_distribution_by_config(config)
322
+ end
323
+
324
+ def create_distribution_by_config(config)
325
+ config[:caller_reference] ||= generate_call_reference
326
+ link = generate_request('POST', 'distribution', {}, distribution_config_to_xml(config))
327
+ merge_headers(request_info(link, AcfDistributionListParser.new(:logger => @logger))[:distributions].first)
233
328
  end
234
329
 
235
330
  # Get a distribution's information.
@@ -245,11 +340,30 @@ module RightAws
245
340
  # :aws_id => "E2REJM3VUN5RSI",
246
341
  # :comment => "Woo-Hoo!",
247
342
  # :origin => "my-bucket.s3.amazonaws.com",
248
- # :last_modified_time => Wed Sep 10 17:00:54 UTC 2008 }
343
+ # :last_modified_time => "2008-09-10T17:00:54.000Z" }
344
+ #
345
+ # acf.get_distribution('E2FNSBHNVVF11E') #=>
346
+ # {:e_tag=>"E1Q2DJEPTQOLJD",
347
+ # :status=>"InProgress",
348
+ # :last_modified_time=>"2010-04-17T17:24:25.000Z",
349
+ # :cnames=>["web1.my-awesome-site.net", "web2.my-awesome-site.net"],
350
+ # :aws_id=>"E2FNSBHNVVF11E",
351
+ # :logging=>{:prefix=>"xlog/", :bucket=>"my-bucket.s3.amazonaws.com"},
352
+ # :enabled=>true,
353
+ # :active_trusted_signers=>
354
+ # [{:aws_account_number=>"120288270000",
355
+ # :key_pair_ids=>["APKAJTD5OHNDX0000000", "APKAIK74BJWCL0000000"]},
356
+ # {:aws_account_number=>"self"},
357
+ # {:aws_account_number=>"648772220000"}],
358
+ # :caller_reference=>"201004171154450740700072",
359
+ # :domain_name=>"d1f6lpevremt5m.cloudfront.net",
360
+ # :origin_access_identity=>"origin-access-identity/cloudfront/E3JPJZ80ZBX24G",
361
+ # :trusted_signers=>["self", "648772220000", "120288270000"],
362
+ # :origin=>"my-bucket.s3.amazonaws.com"}
249
363
  #
250
364
  def get_distribution(aws_id)
251
- request_hash = generate_request('GET', "distribution/#{aws_id}")
252
- merge_headers(request_info(request_hash, AcfDistributionParser.new))
365
+ link = generate_request('GET', "distribution/#{aws_id}")
366
+ merge_headers(request_info(link, AcfDistributionListParser.new(:logger => @logger))[:distributions].first)
253
367
  end
254
368
 
255
369
  # Get a distribution's configuration.
@@ -263,9 +377,18 @@ module RightAws
263
377
  # :comment => "Woo-Hoo!",
264
378
  # :origin => "my-bucket.s3.amazonaws.com"}
265
379
  #
380
+ # acf.get_distribution_config('E2FNSBHNVVF11E') #=>
381
+ # {:e_tag=>"E1Q2DJEPTQOLJD",
382
+ # :logging=>{:prefix=>"xlog/", :bucket=>"my-bucket.s3.amazonaws.com"},
383
+ # :enabled=>true,
384
+ # :caller_reference=>"201004171154450740700072",
385
+ # :origin_access_identity=>"origin-access-identity/cloudfront/E3JPJZ80ZBX24G",
386
+ # :trusted_signers=>["self", "648772220000", "120288270000"],
387
+ # :origin=>"my-bucket.s3.amazonaws.com"}
388
+ #
266
389
  def get_distribution_config(aws_id)
267
- request_hash = generate_request('GET', "distribution/#{aws_id}/config")
268
- merge_headers(request_info(request_hash, AcfDistributionConfigParser.new))
390
+ link = generate_request('GET', "distribution/#{aws_id}/config")
391
+ merge_headers(request_info(link, AcfDistributionListParser.new(:logger => @logger))[:distributions].first)
269
392
  end
270
393
 
271
394
  # Set a distribution's configuration
@@ -279,30 +402,21 @@ module RightAws
279
402
  # :cnames => ["web1.my-awesome-site.net", "web2.my-awesome-site.net"]
280
403
  # :comment => "Woo-Hoo!",
281
404
  # :origin => "my-bucket.s3.amazonaws.com"}
282
- # config[:comment] = 'Olah-lah!'
283
- # config[:enabled] = false
405
+ #
406
+ # config[:comment] = 'Olah-lah!'
407
+ # config[:enabled] = false
408
+ # config[:origin_access_identity] = "origin-access-identity/cloudfront/E3JPJZ80ZBX24G"
409
+ # # or just
410
+ # # config[:origin_access_identity] = "E3JPJZ80ZBX24G"
411
+ # config[:trusted_signers] = ['self', '648772220000', '120288270000']
412
+ # config[:logging] = { :bucket => 'my-bucket.s3.amazonaws.com', :prefix => 'xlog/' }
413
+ #
284
414
  # acf.set_distribution_config('E2REJM3VUN5RSI', config) #=> true
285
415
  #
286
416
  def set_distribution_config(aws_id, config)
287
- # join CNAMES
288
- cnames_str = ''
289
- unless config[:cnames].blank?
290
- config[:cnames].to_a.each { |cname| cnames_str += "\n <CNAME>#{cname}</CNAME>" }
291
- end
292
- # format request's XML body
293
- body = <<-EOXML
294
- <?xml version="1.0" encoding="UTF-8"?>
295
- <DistributionConfig xmlns=#{xmlns}>
296
- <Origin>#{config[:origin]}</Origin>
297
- <CallerReference>#{config[:caller_reference]}</CallerReference>
298
- #{cnames_str.lstrip}
299
- <Comment>#{AcfInterface::escape(config[:comment].to_s)}</Comment>
300
- <Enabled>#{config[:enabled]}</Enabled>
301
- </DistributionConfig>
302
- EOXML
303
- request_hash = generate_request('PUT', "distribution/#{aws_id}/config", body.strip,
304
- 'If-Match' => config[:e_tag])
305
- request_info(request_hash, RightHttp2xxParser.new)
417
+ link = generate_request('PUT', "distribution/#{aws_id}/config", {}, distribution_config_to_xml(config),
418
+ 'If-Match' => config[:e_tag])
419
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
306
420
  end
307
421
 
308
422
  # Delete a distribution. The enabled distribution cannot be deleted.
@@ -311,9 +425,9 @@ module RightAws
311
425
  # acf.delete_distribution('E2REJM3VUN5RSI', 'E39OHHU1ON65SI') #=> true
312
426
  #
313
427
  def delete_distribution(aws_id, e_tag)
314
- request_hash = generate_request('DELETE', "distribution/#{aws_id}", nil,
315
- 'If-Match' => e_tag)
316
- request_info(request_hash, RightHttp2xxParser.new)
428
+ link = generate_request('DELETE', "distribution/#{aws_id}", {}, nil,
429
+ 'If-Match' => e_tag)
430
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
317
431
  end
318
432
 
319
433
  #-----------------------------------------------------------------
@@ -322,58 +436,50 @@ module RightAws
322
436
 
323
437
  class AcfDistributionListParser < RightAWSParser # :nodoc:
324
438
  def reset
325
- @result = []
439
+ @result = { :distributions => [] }
326
440
  end
327
441
  def tagstart(name, attributes)
328
- @distribution = { :cnames => [] } if name == 'DistributionSummary'
329
- end
330
- def tagend(name)
331
- case name
332
- when 'Id' then @distribution[:aws_id] = @text
333
- when 'Status' then @distribution[:status] = @text
334
- when 'LastModifiedTime' then @distribution[:last_modified_time] = Time.parse(@text)
335
- when 'DomainName' then @distribution[:domain_name] = @text
336
- when 'Origin' then @distribution[:origin] = @text
337
- when 'Comment' then @distribution[:comment] = AcfInterface::unescape(@text)
338
- when 'CNAME' then @distribution[:cnames] << @text
339
- when 'DistributionSummary' then @result << @distribution
442
+ case full_tag_name
443
+ when %r{/Signer$}
444
+ @active_signer = {}
445
+ when %r{(Streaming)?DistributionSummary$},
446
+ %r{^(Streaming)?Distribution$},
447
+ %r{^(Streaming)?DistributionConfig$}
448
+ @distribution = { }
340
449
  end
341
450
  end
342
- end
343
-
344
- class AcfDistributionParser < RightAWSParser # :nodoc:
345
- def reset
346
- @result = { :cnames => [] }
347
- end
348
451
  def tagend(name)
349
452
  case name
350
- when 'Id' then @result[:aws_id] = @text
351
- when 'Status' then @result[:status] = @text
352
- when 'LastModifiedTime' then @result[:last_modified_time] = Time.parse(@text)
353
- when 'DomainName' then @result[:domain_name] = @text
354
- when 'Origin' then @result[:origin] = @text
355
- when 'CallerReference' then @result[:caller_reference] = @text
356
- when 'Comment' then @result[:comment] = AcfInterface::unescape(@text)
357
- when 'Enabled' then @result[:enabled] = @text == 'true' ? true : false
358
- when 'CNAME' then @result[:cnames] << @text
453
+ when 'Marker' then @result[:marker] = @text
454
+ when 'NextMarker' then @result[:next_marker] = @text
455
+ when 'MaxItems' then @result[:max_items] = @text.to_i
456
+ when 'IsTruncated' then @result[:is_truncated] = (@text == 'true')
457
+ when 'Id' then @distribution[:aws_id] = @text
458
+ when 'Status' then @distribution[:status] = @text
459
+ when 'LastModifiedTime' then @distribution[:last_modified_time] = @text
460
+ when 'DomainName' then @distribution[:domain_name] = @text
461
+ when 'Origin' then @distribution[:origin] = @text
462
+ when 'Comment' then @distribution[:comment] = AcfInterface::unescape(@text)
463
+ when 'CallerReference' then @distribution[:caller_reference] = @text
464
+ when 'CNAME' then (@distribution[:cnames] ||= []) << @text
465
+ when 'Enabled' then @distribution[:enabled] = (@text == 'true')
466
+ when 'Bucket' then (@distribution[:logging] ||= {})[:bucket] = @text
467
+ when 'Prefix' then (@distribution[:logging] ||= {})[:prefix] = @text
468
+ when 'OriginAccessIdentity' then @distribution[:origin_access_identity] = @text
359
469
  end
360
- end
361
- end
362
-
363
- class AcfDistributionConfigParser < RightAWSParser # :nodoc:
364
- def reset
365
- @result = { :cnames => [] }
366
- end
367
- def tagend(name)
368
- case name
369
- when 'Origin' then @result[:origin] = @text
370
- when 'CallerReference' then @result[:caller_reference] = @text
371
- when 'Comment' then @result[:comment] = AcfInterface::unescape(@text)
372
- when 'Enabled' then @result[:enabled] = @text == 'true' ? true : false
373
- when 'CNAME' then @result[:cnames] << @text
470
+ case full_tag_name
471
+ when %r{/TrustedSigners/Self$} then (@distribution[:trusted_signers] ||= []) << 'self'
472
+ when %r{/TrustedSigners/AwsAccountNumber$} then (@distribution[:trusted_signers] ||= []) << @text
473
+ when %r{/Signer/Self$} then @active_signer[:aws_account_number] = 'self'
474
+ when %r{/Signer/AwsAccountNumber$} then @active_signer[:aws_account_number] = @text
475
+ when %r{/Signer/KeyPairId$} then (@active_signer[:key_pair_ids] ||= []) << @text
476
+ when %r{/Signer$} then (@distribution[:active_trusted_signers] ||= []) << @active_signer
477
+ when %r{(Streaming)?DistributionSummary$},
478
+ %r{^(Streaming)?Distribution$},
479
+ %r{^(Streaming)?DistributionConfig$}
480
+ @result[:distributions] << @distribution
374
481
  end
375
482
  end
376
483
  end
377
-
378
484
  end
379
485
  end