aws-sdk-core 2.0.0.rc1 → 2.0.0.rc2

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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/README.md +6 -3
  4. data/Rakefile +2 -0
  5. data/apis/AutoScaling-2011-01-01.json +1 -0
  6. data/apis/CloudFormation-2010-05-15.json +75 -0
  7. data/apis/CloudFront-2012-05-05.json +1 -0
  8. data/apis/CloudFront-2013-05-12.json +1 -0
  9. data/apis/CloudFront-2013-08-26.json +1 -0
  10. data/apis/CloudSearch-2011-02-01.json +1 -0
  11. data/apis/CloudWatch-2010-08-01.json +1 -0
  12. data/apis/DataPipeline-2012-10-29.json +1 -0
  13. data/apis/DirectConnect-2012-10-25.json +1 -0
  14. data/apis/DynamoDB-2011-12-05.json +1 -0
  15. data/apis/DynamoDB-2012-08-10.json +1 -0
  16. data/apis/EC2-2013-06-15.json +1 -0
  17. data/apis/EC2-2013-10-01.json +1 -0
  18. data/apis/EMR-2009-03-31.json +1 -0
  19. data/apis/ElastiCache-2012-11-15.json +1 -0
  20. data/apis/ElastiCache-2013-06-15.json +1 -0
  21. data/apis/ElasticBeanstalk-2010-12-01.json +1 -0
  22. data/apis/ElasticLoadBalancing-2012-06-01.json +73 -0
  23. data/apis/ElasticTranscoder-2012-09-25.json +231 -0
  24. data/apis/Glacier-2012-06-01.json +2 -0
  25. data/apis/IAM-2010-05-08.json +1 -0
  26. data/apis/ImportExport-2010-06-01.json +1 -0
  27. data/apis/OpsWorks-2013-02-18.json +1 -0
  28. data/apis/RDS-2013-01-10.json +1 -0
  29. data/apis/RDS-2013-02-12.json +1 -0
  30. data/apis/RDS-2013-05-15.json +1 -0
  31. data/apis/Redshift-2012-12-01.json +1 -0
  32. data/apis/Route53-2012-12-12.json +1 -0
  33. data/apis/S3-2006-03-01.json +5 -0
  34. data/apis/SDB-2009-04-15.json +1 -0
  35. data/apis/SES-2010-12-01.json +1 -0
  36. data/apis/SNS-2010-03-31.json +1 -0
  37. data/apis/SQS-2012-11-05.json +1 -0
  38. data/apis/STS-2011-06-15.json +1 -0
  39. data/apis/SWF-2012-01-25.json +1 -0
  40. data/apis/StorageGateway-2012-06-30.json +1 -0
  41. data/apis/StorageGateway-2013-06-30.json +2018 -0
  42. data/apis/Support-2013-04-15.json +1 -0
  43. data/apis/source/cloudformation-2010-05-15.json +118 -12
  44. data/apis/source/elasticloadbalancing-2012-06-01.json +347 -220
  45. data/apis/source/elastictranscoder-2012-09-25.json +315 -5
  46. data/apis/source/s3-2006-03-01.json +3 -0
  47. data/apis/source/storagegateway-2013-06-30.json +12560 -0
  48. data/apis/source/storagegateway-2013-06-30.paginators.json +28 -0
  49. data/doc-src/plugins/apis.rb +44 -1
  50. data/doc-src/templates/default/fulldoc/html/setup.rb +1 -1
  51. data/features/common/step_definitions.rb +3 -5
  52. data/features/env.rb +2 -0
  53. data/features/glacier/client.feature +8 -0
  54. data/features/glacier/step_definitions.rb +7 -7
  55. data/features/s3/step_definitions.rb +2 -3
  56. data/lib/aws.rb +75 -69
  57. data/lib/aws/api/service_translators/glacier.rb +1 -0
  58. data/lib/aws/api/translator.rb +13 -8
  59. data/lib/aws/credentials.rb +5 -5
  60. data/lib/aws/instance_profile_credentials.rb +113 -0
  61. data/lib/aws/plugins/credentials.rb +2 -1
  62. data/lib/aws/plugins/glacier_account_id.rb +11 -0
  63. data/lib/aws/plugins/glacier_checksums.rb +7 -3
  64. data/lib/aws/plugins/instance_profile_credentials.rb +14 -0
  65. data/lib/aws/plugins/s3_bucket_dns.rb +17 -14
  66. data/lib/aws/plugins/s3_md5s.rb +3 -3
  67. data/lib/aws/service.rb +10 -9
  68. data/lib/aws/signers/s3.rb +2 -2
  69. data/lib/aws/signers/v2.rb +1 -1
  70. data/lib/aws/signers/v4.rb +2 -2
  71. data/lib/aws/version.rb +1 -1
  72. data/lib/aws/xml/serializer.rb +1 -1
  73. data/spec/aws/instance_profile_credentials_spec.rb +94 -0
  74. data/spec/aws/operations_spec.rb +1 -1
  75. data/spec/aws/plugins/credentials_spec.rb +2 -2
  76. data/spec/fixtures/operations/glacier/account_id_param.yml +13 -0
  77. data/spec/fixtures/operations/glacier/custom_account_id.yml +11 -0
  78. data/spec/fixtures/operations/glacier/default_account_id.yml +10 -0
  79. data/spec/fixtures/operations/s3/content_type_header.yml +12 -0
  80. data/spec/fixtures/operations/s3/md5_checksum_disabled.yml +1 -1
  81. data/tasks/apis.rake +2 -2
  82. data/tasks/docs.rake +2 -1
  83. data/tasks/handlers.rake +30 -0
  84. data/vendor/seahorse/lib/seahorse/client.rb +1 -0
  85. data/vendor/seahorse/lib/seahorse/client/base.rb +0 -18
  86. data/vendor/seahorse/lib/seahorse/client/block_io.rb +0 -7
  87. data/vendor/seahorse/lib/seahorse/client/configuration.rb +57 -37
  88. data/vendor/seahorse/lib/seahorse/client/handler_list.rb +115 -78
  89. data/vendor/seahorse/lib/seahorse/client/http/endpoint.rb +19 -15
  90. data/vendor/seahorse/lib/seahorse/client/http/request.rb +0 -15
  91. data/vendor/seahorse/lib/seahorse/client/logging/formatter.rb +0 -7
  92. data/vendor/seahorse/lib/seahorse/client/managed_file.rb +14 -0
  93. data/vendor/seahorse/lib/seahorse/client/net_http/handler.rb +1 -3
  94. data/vendor/seahorse/lib/seahorse/client/plugins/content_length.rb +1 -1
  95. data/vendor/seahorse/lib/seahorse/client/plugins/endpoint.rb +81 -10
  96. data/vendor/seahorse/lib/seahorse/client/plugins/restful_bindings.rb +1 -71
  97. data/vendor/seahorse/lib/seahorse/client/request.rb +26 -3
  98. data/vendor/seahorse/spec/seahorse/client/base_spec.rb +1 -5
  99. data/vendor/seahorse/spec/seahorse/client/configuration_spec.rb +1 -10
  100. data/vendor/seahorse/spec/seahorse/client/handler_list_spec.rb +10 -10
  101. data/vendor/seahorse/spec/seahorse/client/http/endpoint_spec.rb +46 -14
  102. data/vendor/seahorse/spec/seahorse/client/http/request_spec.rb +1 -42
  103. data/vendor/seahorse/spec/seahorse/client/logging/formatter_spec.rb +1 -6
  104. data/vendor/seahorse/spec/seahorse/client/logging/handler_spec.rb +1 -1
  105. data/vendor/seahorse/spec/seahorse/client/net_http/handler_spec.rb +5 -4
  106. data/vendor/seahorse/spec/seahorse/client/param_converter_spec.rb +1 -0
  107. data/vendor/seahorse/spec/seahorse/client/plugins/{restful_bindings/uri_path_builder_spec.rb → endpoint/request_uri_builder_spec.rb} +3 -3
  108. data/vendor/seahorse/spec/seahorse/client/plugins/endpoint_spec.rb +1 -11
  109. data/vendor/seahorse/spec/seahorse/client/request_spec.rb +63 -13
  110. metadata +21 -3
@@ -31,10 +31,11 @@ module Aws
31
31
  }
32
32
 
33
33
  option(:credentials) do |config|
34
- Aws::Credentials.new(
34
+ credentials = Aws::Credentials.new(
35
35
  config.access_key_id,
36
36
  config.secret_access_key,
37
37
  config.session_token)
38
+ credentials.set? ? credentials : nil
38
39
  end
39
40
 
40
41
  def after_initialize(client)
@@ -0,0 +1,11 @@
1
+ module Aws
2
+ module Plugins
3
+ class GlacierAccountId < Seahorse::Client::Plugin
4
+ option :account_id, '-'
5
+
6
+ handle_request(step: :validate, priority: 99) do |context|
7
+ context.params[:account_id] ||= context.config.account_id
8
+ end
9
+ end
10
+ end
11
+ end
@@ -59,14 +59,18 @@ module Aws
59
59
  tree_digest = OpenSSL::Digest::Digest.new('sha256')
60
60
  tree_parts = []
61
61
 
62
- until body.eof?
62
+ # if the body is empty/EOF, then we should compute the
63
+ # digests of the empty string
64
+ if body.size == 0
65
+ tree_parts << tree_digest.update('').digest
66
+ digest.update('')
67
+ end
63
68
 
69
+ until body.eof?
64
70
  chunk = body.read(1024 * 1024) # read 1MB
65
71
  tree_parts << tree_digest.update(chunk).digest
66
72
  tree_digest.reset
67
-
68
73
  digest.update(chunk)
69
-
70
74
  end
71
75
 
72
76
  body.rewind
@@ -0,0 +1,14 @@
1
+ module Aws
2
+ module Plugins
3
+ # Adds support for loading access credentials from the EC2 instance
4
+ # metada service.
5
+ class InstanceProfileCredentials < Seahorse::Client::Plugin
6
+
7
+ option(:credentials) do
8
+ credentials = Aws::InstanceProfileCredentials.new
9
+ credentials.set? ? credentials : nil
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -19,37 +19,40 @@ module Aws
19
19
  # the classic region.
20
20
  option(:force_path_style, false)
21
21
 
22
+ def add_handlers(handlers, config)
23
+ handlers.add(Handler) unless config.force_path_style
24
+ end
25
+
22
26
  # @api private
23
27
  class Handler < Seahorse::Client::Handler
24
28
 
25
29
  def call(context)
26
- unless context.config.force_path_style
27
- move_dns_compat_bucket_to_subdomain(context)
28
- end
30
+ move_dns_compat_bucket_to_subdomain(context)
29
31
  @handler.call(context)
30
32
  end
31
33
 
32
34
  private
33
35
 
34
36
  def move_dns_compat_bucket_to_subdomain(context)
35
- if bucket_name = context.params[:bucket]
36
- req = context.http_request
37
- if S3BucketDns.dns_compatible?(bucket_name, req.endpoint.https?)
38
- move_bucket_to_subdomain(bucket_name, req)
39
- end
37
+ bucket_name = context.params[:bucket]
38
+ endpoint = context.http_request.endpoint
39
+ if
40
+ bucket_name &&
41
+ S3BucketDns.dns_compatible?(bucket_name, endpoint.https?)
42
+ then
43
+ move_bucket_to_subdomain(bucket_name, endpoint)
40
44
  end
41
45
  end
42
46
 
43
- def move_bucket_to_subdomain(bucket_name, req)
44
- req.endpoint.host = "#{bucket_name}.#{req.endpoint.host}"
45
- req.path = req.path[(bucket_name.size + 1)..-1]
46
- req.path = "/#{req.path}" unless req.path.match(/^\//)
47
+ def move_bucket_to_subdomain(bucket_name, endpoint)
48
+ endpoint.host = "#{bucket_name}.#{endpoint.host}"
49
+ request_uri = endpoint.request_uri.sub("/#{bucket_name}", '')
50
+ request_uri = "/#{request_uri}" unless request_uri.match(/^\//)
51
+ endpoint.request_uri = request_uri
47
52
  end
48
53
 
49
54
  end
50
55
 
51
- handler(Handler)
52
-
53
56
  class << self
54
57
 
55
58
  # @param [String] bucket_name
@@ -4,7 +4,7 @@ require 'base64'
4
4
  module Aws
5
5
  module Plugins
6
6
 
7
- # @seahorse.client.option [Boolean] :compute_optional_md5s (true)
7
+ # @seahorse.client.option [Boolean] :compute_checksums (true)
8
8
  # When `true` a MD5 checksum will be computed for all requests that
9
9
  # accept the optional `Content-MD5` header. Checksum errors returned
10
10
  # by Amazon S3 are automatically retried up to `:retry_limit` times.
@@ -41,7 +41,7 @@ module Aws
41
41
 
42
42
  end
43
43
 
44
- option(:compute_optional_md5s, true)
44
+ option(:compute_checksums, true)
45
45
 
46
46
  def add_handlers(handlers, config)
47
47
  options = {
@@ -49,7 +49,7 @@ module Aws
49
49
  step: :build, # the request is built but before it is signed
50
50
  }
51
51
 
52
- if !config.compute_optional_md5s
52
+ if !config.compute_checksums
53
53
  options[:operations] = REQUIRED_OPERATIONS
54
54
  end
55
55
 
@@ -176,6 +176,16 @@ module Aws
176
176
  klass
177
177
  end
178
178
 
179
+ # @api private
180
+ def const_missing(constant)
181
+ if constant =~ /^V\d{8}$/
182
+ api = api(api_version(constant))
183
+ const_set(constant, Seahorse::Client.define(api: api))
184
+ else
185
+ super
186
+ end
187
+ end
188
+
179
189
  private
180
190
 
181
191
  def svc_locked_version
@@ -196,15 +206,6 @@ module Aws
196
206
  @apis ||= {}
197
207
  end
198
208
 
199
- def const_missing(constant)
200
- if constant =~ /^V\d{8}$/
201
- api = api(api_version(constant))
202
- const_set(constant, Seahorse::Client.define(api: api))
203
- else
204
- super
205
- end
206
- end
207
-
208
209
  def api(api_version)
209
210
  api = apis[api_version]
210
211
  case api
@@ -137,7 +137,7 @@ module Aws
137
137
  end
138
138
 
139
139
  # append the path name (no querystring)
140
- parts << request.path.split('?')[0]
140
+ parts << request.endpoint.path
141
141
 
142
142
  # lastly any sub resource querystring params need to be appened
143
143
  # in lexigraphical ordered joined by '&' and prefixed by '?'
@@ -152,7 +152,7 @@ module Aws
152
152
  end
153
153
 
154
154
  def signed_querystring_params(request)
155
- request.querystring.to_s.split('&').select do |p|
155
+ request.endpoint.querystring.to_s.split('&').select do |p|
156
156
  SIGNED_QUERYSTRING_PARAMS.include?(p.split('=')[0])
157
157
  end.map { |p| URI.decode(p) }
158
158
  end
@@ -26,7 +26,7 @@ module Aws
26
26
  [
27
27
  http_request.http_method,
28
28
  host(http_request),
29
- http_request.pathname,
29
+ http_request.endpoint.path,
30
30
  params.to_s,
31
31
  ].join("\n")
32
32
  end
@@ -77,8 +77,8 @@ module Aws
77
77
  def canonical_request(request)
78
78
  [
79
79
  request.http_method,
80
- request.pathname,
81
- request.querystring,
80
+ request.endpoint.path,
81
+ request.endpoint.querystring,
82
82
  canonical_headers(request) + "\n",
83
83
  signed_headers(request),
84
84
  request.headers['X-Amz-Content-Sha256']
@@ -1,3 +1,3 @@
1
1
  module Aws
2
- VERSION = '2.0.0.rc1'
2
+ VERSION = '2.0.0.rc2'
3
3
  end
@@ -4,7 +4,7 @@ module Aws
4
4
  class Serializer
5
5
 
6
6
  def setup_request(context)
7
- context.http_request.headers['Content-Type'] = 'application/xml'
7
+ context.http_request.headers['Content-Type'] ||= 'application/xml'
8
8
  end
9
9
 
10
10
  def serialize_params(context, rules, params)
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ module Aws
4
+ describe InstanceProfileCredentials do
5
+
6
+ let(:path) { '/latest/meta-data/iam/security-credentials/' }
7
+
8
+ describe 'without instance metadata service present' do
9
+
10
+ [
11
+ Errno::EHOSTUNREACH,
12
+ Errno::ECONNREFUSED,
13
+ SocketError,
14
+ Timeout::Error,
15
+ ].each do |error_class|
16
+ it "returns no credentials for #{error_class}" do
17
+ stub_request(:get, "http://169.254.169.254#{path}").to_raise(error_class)
18
+ expect(InstanceProfileCredentials.new.set?).to be(false)
19
+ end
20
+ end
21
+
22
+ end
23
+
24
+ describe 'with instance metadata service present' do
25
+
26
+ let(:expiration) { Time.now.utc + 3600 }
27
+ let(:expiration2) { expiration + 3600 }
28
+
29
+ let(:resp) { <<-JSON.strip }
30
+ {
31
+ "Code" : "Success",
32
+ "LastUpdated" : "2013-11-22T20:03:48Z",
33
+ "Type" : "AWS-HMAC",
34
+ "AccessKeyId" : "akid",
35
+ "SecretAccessKey" : "secret",
36
+ "Token" : "session-token",
37
+ "Expiration" : "#{expiration.strftime('%Y-%m-%dT%H:%M:%SZ')}"
38
+ }
39
+ JSON
40
+
41
+ let(:resp2) { <<-JSON.strip }
42
+ {
43
+ "Code" : "Success",
44
+ "LastUpdated" : "2013-11-22T20:03:48Z",
45
+ "Type" : "AWS-HMAC",
46
+ "AccessKeyId" : "akid-2",
47
+ "SecretAccessKey" : "secret-2",
48
+ "Token" : "session-token-2",
49
+ "Expiration" : "#{(expiration2).strftime('%Y-%m-%dT%H:%M:%SZ')}"
50
+ }
51
+ JSON
52
+
53
+ before(:each) do
54
+ stub_request(:get, "http://169.254.169.254#{path}").
55
+ to_return(:status => 200, :body => "profile-name\n")
56
+ stub_request(:get, "http://169.254.169.254#{path}profile-name").
57
+ to_return(:status => 200, :body => resp).
58
+ to_return(:status => 200, :body => resp2)
59
+ end
60
+
61
+ it 'populates credentials from the instance profile' do
62
+ c = InstanceProfileCredentials.new
63
+ expect(c.access_key_id).to eq('akid')
64
+ expect(c.secret_access_key).to eq('secret')
65
+ expect(c.session_token).to eq('session-token')
66
+ expect(c.expiration.to_s).to eq(expiration.to_s)
67
+ end
68
+
69
+ it 're-queries the metadata service when #refresh! is called' do
70
+ c = InstanceProfileCredentials.new
71
+ c.refresh!
72
+ expect(c.access_key_id).to eq('akid-2')
73
+ expect(c.secret_access_key).to eq('secret-2')
74
+ expect(c.session_token).to eq('session-token-2')
75
+ expect(c.expiration.to_s).to eq(expiration2.to_s)
76
+ end
77
+
78
+ describe 'auto refreshing' do
79
+
80
+ # expire in 4 minutes
81
+ let(:expiration) { Time.now.utc + 299 }
82
+
83
+ it 'auto-refreshes within 5 minutes from expiration' do
84
+ c = InstanceProfileCredentials.new
85
+ expect(c.access_key_id).to eq('akid-2')
86
+ expect(c.secret_access_key).to eq('secret-2')
87
+ expect(c.session_token).to eq('session-token-2')
88
+ expect(c.expiration.to_s).to eq(expiration2.to_s)
89
+ end
90
+
91
+ end
92
+ end
93
+ end
94
+ end
@@ -84,7 +84,7 @@ module Aws
84
84
  if f.request
85
85
  expect(http_req.endpoint.host).to eq(f.request.host) if f.request.host
86
86
  expect(http_req.http_method).to eq(f.request.method) if f.request.method
87
- expect(http_req.path).to eq(f.request.path) if f.request.path
87
+ expect(http_req.endpoint.request_uri).to eq(f.request.path) if f.request.path
88
88
  if f.request.headers
89
89
  f.request.headers.each_pair do |header, value|
90
90
  expected_value = value.nil? ? nil : value.to_s
@@ -21,9 +21,9 @@ module Aws
21
21
  expect(config.build!).to respond_to(:credentials)
22
22
  end
23
23
 
24
- it 'defaults to a Credentials object' do
24
+ it 'defaults to nil when credentials not set' do
25
25
  plugin.add_options(config)
26
- expect(config.build!.credentials).to be_kind_of(Aws::Credentials)
26
+ expect(config.build!.credentials).to be(nil)
27
27
  end
28
28
 
29
29
  it 'hydrates credentials from the env (AWS_)' do
@@ -0,0 +1,13 @@
1
+ # This test ensures the `:account_id` param can be specified and that
2
+ # it will override the default configured account id.
3
+ config:
4
+ account_id: 'CONFIG-ACCOUNT-ID'
5
+ operation: list_vaults
6
+ params:
7
+ :account_id: 'PARAM-ACCOUNT-ID'
8
+ request:
9
+ path: /PARAM-ACCOUNT-ID/vaults
10
+ response:
11
+ status_code: 200
12
+ body: |
13
+ {"Marker":null,"VaultList":[]}
@@ -0,0 +1,11 @@
1
+ # This test ensures the default `:account_id` of '-' can be replaced via config
2
+ config:
3
+ account_id: 'ACCOUNT-ID'
4
+ operation: list_vaults
5
+ params: {}
6
+ request:
7
+ path: /ACCOUNT-ID/vaults
8
+ response:
9
+ status_code: 200
10
+ body: |
11
+ {"Marker":null,"VaultList":[]}
@@ -0,0 +1,10 @@
1
+ # This test ensures the `:account_id` need not be supplied and that it defaults
2
+ # to the '-' string, which means current account
3
+ operation: list_vaults
4
+ params: {}
5
+ request:
6
+ path: /-/vaults
7
+ response:
8
+ status_code: 200
9
+ body: |
10
+ {"Marker":null,"VaultList":[]}
@@ -0,0 +1,12 @@
1
+ # This test ensures that the content type param makes it to the Content-Type
2
+ # header. There was a bug that caused S3 to always set the content
3
+ # type to application/xml.
4
+ operation: put_object
5
+ params:
6
+ :bucket: 'bucket-name'
7
+ :key: 'key'
8
+ :body: 'abc'
9
+ :content_type: 'text/plain'
10
+ request:
11
+ headers:
12
+ Content-Type: 'text/plain'
@@ -1,5 +1,5 @@
1
1
  config:
2
- compute_optional_md5s: false
2
+ compute_checksums: false
3
3
  operation: put_object
4
4
  params:
5
5
  :bucket: 'bucket-name'
@@ -8,7 +8,6 @@ namespace :api do
8
8
 
9
9
  desc "Lists the supported services and their API versions"
10
10
  task :versions do
11
- require 'aws-sdk-core'
12
11
  supported = []
13
12
  Aws.service_classes.each do |key, svc|
14
13
  name = svc.default_client_class.api.metadata['service_full_name']
@@ -26,6 +25,8 @@ namespace :api do
26
25
  svc_task = "translate:#{svc}"
27
26
  version_task = "translate:#{svc}:#{version}"
28
27
  task(version_task) { translate_api(path) }
28
+
29
+ desc "Translate source APIs for #{svc}" if ENV['ALL']
29
30
  task(svc_task => version_task)
30
31
 
31
32
  desc "Translate source APIs into Seahorse APIs"
@@ -36,7 +37,6 @@ namespace :api do
36
37
  end
37
38
 
38
39
  def translate_api(path)
39
- require 'aws-sdk-core'
40
40
  api = Aws::Api::Translator.translate(
41
41
  JSON.parse(File.read(path), max_nesting: false), documentation: false,
42
42
  errors: false)
@@ -1,11 +1,13 @@
1
1
  namespace :doc do
2
2
 
3
+ desc "Delete the locally generated docs" if ENV['ALL']
3
4
  task :clobber do
4
5
  rm_rf ".yardoc"
5
6
  rm_rf "doc"
6
7
  end
7
8
 
8
9
  # Updates the list of supported services and versions in the README
10
+ desc "Updated the list of supported services in the README" if ENV['ALL']
9
11
  task :readme do
10
12
  lines = []
11
13
  skip = false
@@ -35,7 +37,6 @@ def supported_services_table
35
37
  line = "| %-35s | %-25s | %-30s |\n"
36
38
 
37
39
  lines = []
38
- require 'aws-sdk-core'
39
40
  Aws.service_classes.keys.sort_by(&:downcase).each do |svc|
40
41
  svc = Aws.service_classes[svc]
41
42
  client = svc.default_client_class