aws-sdk 1.11.3 → 1.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/aws-rb +151 -0
- data/lib/aws/api_config/ElasticTranscoder-2012-09-25.yml +257 -0
- data/lib/aws/auto_scaling/group.rb +2 -0
- data/lib/aws/auto_scaling/group_options.rb +9 -0
- data/lib/aws/cloud_watch/metric_collection.rb +1 -3
- data/lib/aws/core.rb +107 -166
- data/lib/aws/core/configuration.rb +22 -4
- data/lib/aws/core/http/curb_handler.rb +2 -9
- data/lib/aws/core/http/net_http_handler.rb +15 -15
- data/lib/aws/core/region.rb +11 -7
- data/lib/aws/dynamo_db/client.rb +766 -400
- data/lib/aws/dynamo_db/client_v2.rb +125 -23
- data/lib/aws/elastic_transcoder/client.rb +578 -54
- data/lib/aws/iam/virtual_mfa_device.rb +1 -1
- data/lib/aws/route_53/change_batch.rb +3 -1
- data/lib/aws/route_53/resource_record_set.rb +17 -3
- data/lib/aws/s3/client.rb +10 -5
- data/lib/aws/s3/encryption_utils.rb +8 -1
- data/lib/aws/s3/object_collection.rb +7 -4
- data/lib/aws/simple_email_service.rb +5 -2
- data/lib/aws/sns.rb +1 -0
- data/lib/aws/sns/message.rb +175 -0
- data/lib/aws/sns/originators/from_auto_scaling.rb +68 -0
- data/lib/aws/version.rb +1 -1
- metadata +12 -16
@@ -114,7 +114,7 @@ module AWS
|
|
114
114
|
# @return [String]
|
115
115
|
attr_reader :type
|
116
116
|
|
117
|
-
# Build query
|
117
|
+
# Build query for change request.
|
118
118
|
# @return [Hash]
|
119
119
|
def to_hash
|
120
120
|
q = {}
|
@@ -128,6 +128,8 @@ module AWS
|
|
128
128
|
q[:resource_record_set][:ttl] = @change_options[:ttl] if @change_options[:ttl]
|
129
129
|
q[:resource_record_set][:resource_records] = @change_options[:resource_records] if @change_options[:resource_records]
|
130
130
|
q[:resource_record_set][:alias_target] = @change_options[:alias_target] if @change_options[:alias_target]
|
131
|
+
q[:resource_record_set][:failover] = @change_options[:failover] if @change_options[:failover]
|
132
|
+
q[:resource_record_set][:health_check_id] = @change_options[:health_check_id] if @change_options[:health_check_id]
|
131
133
|
q
|
132
134
|
end
|
133
135
|
end
|
@@ -119,6 +119,18 @@ module AWS
|
|
119
119
|
@create_options[:ttl] = new_ttl
|
120
120
|
end
|
121
121
|
|
122
|
+
attribute :failover
|
123
|
+
|
124
|
+
def failover= new_failover
|
125
|
+
@create_options[:failover] = new_failover
|
126
|
+
end
|
127
|
+
|
128
|
+
attribute :health_check_id
|
129
|
+
|
130
|
+
def health_check_id= new_health_check_id
|
131
|
+
@create_options[:health_check_id] = new_health_check_id
|
132
|
+
end
|
133
|
+
|
122
134
|
attribute :resource_records
|
123
135
|
|
124
136
|
# @param [Array<Hash>] new_rrs
|
@@ -159,9 +171,9 @@ module AWS
|
|
159
171
|
end
|
160
172
|
|
161
173
|
@change_info = batch.call()
|
162
|
-
@name = @create_options[:name]
|
163
|
-
@type = @create_options[:type]
|
164
|
-
@set_identifier = @create_options[:set_identifier]
|
174
|
+
@name = @create_options[:name] || @name
|
175
|
+
@type = @create_options[:type] || @type
|
176
|
+
@set_identifier = @create_options[:set_identifier] || @set_identifier
|
165
177
|
@create_options = {}
|
166
178
|
self
|
167
179
|
end
|
@@ -229,6 +241,8 @@ module AWS
|
|
229
241
|
options[:region] = region if region
|
230
242
|
options[:ttl] = ttl if ttl
|
231
243
|
options[:resource_records] = resource_records if resource_records && !resource_records.empty?
|
244
|
+
options[:failover] = failover if failover
|
245
|
+
options[:health_check_id] = health_check_id if health_check_id
|
232
246
|
end
|
233
247
|
options
|
234
248
|
end
|
data/lib/aws/s3/client.rb
CHANGED
@@ -1403,11 +1403,16 @@ module AWS
|
|
1403
1403
|
|
1404
1404
|
def retryable_error? response
|
1405
1405
|
super or
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1406
|
+
failed_multipart_upload?(response) or
|
1407
|
+
response.error.is_a?(Errors::RequestTimeout)
|
1408
|
+
end
|
1409
|
+
|
1410
|
+
# S3 may return a 200 response code in response to complete_multipart_upload
|
1411
|
+
# and then start streaming whitespace until it knows the final result.
|
1412
|
+
# At that time it sends an XML message with success or failure.
|
1413
|
+
def failed_multipart_upload? response
|
1414
|
+
response.request_type == :complete_multipart_upload &&
|
1415
|
+
extract_error_details(response)
|
1411
1416
|
end
|
1412
1417
|
|
1413
1418
|
def new_request
|
@@ -20,22 +20,29 @@ module AWS
|
|
20
20
|
|
21
21
|
protected
|
22
22
|
|
23
|
+
UNSAFE_MSG = "Unsafe encryption, data is longer than key length"
|
23
24
|
|
24
25
|
# @param [OpenSSL::PKey::RSA, String] key Key used to encrypt.
|
25
26
|
#
|
26
27
|
# @param [String] data Data to be encrypted.
|
27
28
|
#
|
28
29
|
# @note Use check_encryption_materials before this method to check
|
29
|
-
# formatting of keys
|
30
|
+
# formatting of keys.
|
31
|
+
# @note This should not be used for data longer than the key length as
|
32
|
+
# it will not be cryptographically safe.
|
30
33
|
#
|
31
34
|
# @return [String] Returns the data encrypted with the key given.
|
32
35
|
def encrypt data, key
|
33
36
|
rsa = OpenSSL::PKey::RSA
|
37
|
+
data_cipher_size = get_cipher_size(data.length)
|
38
|
+
|
34
39
|
# Encrypting data key
|
35
40
|
case key
|
36
41
|
when rsa # Asymmetric encryption
|
42
|
+
warn UNSAFE_MSG if key.public_key.n.num_bits < data_cipher_size
|
37
43
|
key.public_encrypt(data)
|
38
44
|
when String # Symmetric encryption
|
45
|
+
warn UNSAFE_MSG if get_cipher_size(key.length) < data_cipher_size
|
39
46
|
cipher = get_aes_cipher(:encrypt, :ECB, key)
|
40
47
|
cipher.update(data) + cipher.final
|
41
48
|
end
|
@@ -306,12 +306,15 @@ module AWS
|
|
306
306
|
# @api private
|
307
307
|
protected
|
308
308
|
def next_markers page
|
309
|
-
|
310
|
-
|
311
|
-
|
309
|
+
if page[:next_marker]
|
310
|
+
marker = page[:next_marker]
|
311
|
+
elsif page[:contents].size > 0
|
312
|
+
marker = page[:contents].last[:key]
|
312
313
|
else
|
313
|
-
|
314
|
+
raise 'Unable to find marker in S3 list objects response'
|
314
315
|
end
|
316
|
+
|
317
|
+
{ :marker => marker }
|
315
318
|
end
|
316
319
|
|
317
320
|
# processes items in batches of 1k items
|
@@ -342,9 +342,12 @@ module AWS
|
|
342
342
|
end
|
343
343
|
send_opts[:destinations] = [options[:to]].flatten if options[:to]
|
344
344
|
|
345
|
-
client.send_raw_email(send_opts)
|
346
|
-
|
345
|
+
response = client.send_raw_email(send_opts)
|
346
|
+
if raw_message.respond_to?(:message_id=)
|
347
|
+
raw_message.message_id = "#{response.data[:message_id]}@email.amazonses.com"
|
348
|
+
end
|
347
349
|
|
350
|
+
nil
|
348
351
|
end
|
349
352
|
|
350
353
|
# for compatability with ActionMailer
|
data/lib/aws/sns.rb
CHANGED
@@ -0,0 +1,175 @@
|
|
1
|
+
# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
4
|
+
# may not use this file except in compliance with the License. A copy of
|
5
|
+
# the License is located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is
|
10
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
11
|
+
# ANY KIND, either express or implied. See the License for the specific
|
12
|
+
# language governing permissions and limitations under the License.
|
13
|
+
|
14
|
+
require 'base64'
|
15
|
+
require 'json'
|
16
|
+
require 'net/http'
|
17
|
+
require 'net/https'
|
18
|
+
require 'openssl'
|
19
|
+
Dir.glob("#{File.dirname __FILE__}/originators/*.rb").each { |rb| require rb }
|
20
|
+
|
21
|
+
module AWS
|
22
|
+
class SNS
|
23
|
+
class MessageWasNotAuthenticError < StandardError
|
24
|
+
end
|
25
|
+
|
26
|
+
# Represents a single SNS message.
|
27
|
+
#
|
28
|
+
# See also http://docs.amazonwebservices.com/sns/latest/gsg/json-formats.html
|
29
|
+
#
|
30
|
+
# = Originators
|
31
|
+
# Originators are sources of SNS messages. {FromAutoScaling} is one. {Message}
|
32
|
+
# can be extended by originators if their #applicable? method returns true when
|
33
|
+
# passed the raw message.
|
34
|
+
# Originator modules must implement `applicable? sns` module function.
|
35
|
+
# If an originator is applicable, it should set the `@origin` accessor to denote
|
36
|
+
# itself.
|
37
|
+
class Message
|
38
|
+
attr_reader :raw
|
39
|
+
attr_accessor :origin
|
40
|
+
|
41
|
+
# @return {Message} Constructs a new {Message} from the raw SNS, sets origin
|
42
|
+
def initialize sns
|
43
|
+
if sns.is_a? String
|
44
|
+
@raw = parse_from sns
|
45
|
+
else
|
46
|
+
@raw = sns
|
47
|
+
end
|
48
|
+
@origin = :sns
|
49
|
+
self.extend FromAutoScaling if FromAutoScaling.applicable? @raw
|
50
|
+
end
|
51
|
+
|
52
|
+
# @param [String] indexer into raw SNS JSON message
|
53
|
+
# @return [String] the value of the SNS' field
|
54
|
+
def [] key
|
55
|
+
@raw[key]
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Boolean] true when the {Message} is authentic:
|
59
|
+
# SigningCert is hosted at amazonaws.com, on https
|
60
|
+
# correctly cryptographically signed by sender
|
61
|
+
# nothing went wrong during authenticating the {Message}
|
62
|
+
#
|
63
|
+
# See http://docs.amazonwebservices.com/sns/latest/gsg/SendMessageToHttp.verify.signature.html
|
64
|
+
def authentic?
|
65
|
+
begin
|
66
|
+
decoded_from_base64 = decode signature
|
67
|
+
public_key = get_public_key_from signing_cert_url
|
68
|
+
public_key.verify OpenSSL::Digest::SHA1.new, decoded_from_base64, canonical_string
|
69
|
+
rescue MessageWasNotAuthenticError
|
70
|
+
false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return[Symbol] the message type
|
75
|
+
def type
|
76
|
+
case when @raw['Type'] =~ /SubscriptionConfirmation/i
|
77
|
+
then :SubscriptionConfirmation
|
78
|
+
when @raw['Type'] =~ /Notification/i
|
79
|
+
then :Notification
|
80
|
+
when @raw['Type'] =~ /UnsubscribeConfirmation/i
|
81
|
+
then :UnsubscribeConfirmation
|
82
|
+
else
|
83
|
+
:unknown
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def message_id
|
88
|
+
@raw['MessageId']
|
89
|
+
end
|
90
|
+
|
91
|
+
def topic_arn
|
92
|
+
@raw['TopicArn']
|
93
|
+
end
|
94
|
+
|
95
|
+
def subject
|
96
|
+
@raw['Subject']
|
97
|
+
end
|
98
|
+
|
99
|
+
def message
|
100
|
+
@raw['Message']
|
101
|
+
end
|
102
|
+
|
103
|
+
def timestamp
|
104
|
+
@raw['Timestamp']
|
105
|
+
end
|
106
|
+
|
107
|
+
def signature
|
108
|
+
@raw['Signature']
|
109
|
+
end
|
110
|
+
|
111
|
+
def signature_version
|
112
|
+
@raw['SignatureVersion']
|
113
|
+
end
|
114
|
+
|
115
|
+
def signing_cert_url
|
116
|
+
@raw['SigningCertURL']
|
117
|
+
end
|
118
|
+
|
119
|
+
def unsubscribe_url
|
120
|
+
@raw['UnsubscribeURL']
|
121
|
+
end
|
122
|
+
|
123
|
+
def parse_from json
|
124
|
+
JSON.parse json
|
125
|
+
end
|
126
|
+
|
127
|
+
protected
|
128
|
+
def decode raw
|
129
|
+
Base64.decode64 raw
|
130
|
+
end
|
131
|
+
|
132
|
+
def get_public_key_from(x509_pem_url)
|
133
|
+
cert_pem = download x509_pem_url
|
134
|
+
x509 = OpenSSL::X509::Certificate.new(cert_pem)
|
135
|
+
OpenSSL::PKey::RSA.new(x509.public_key)
|
136
|
+
end
|
137
|
+
|
138
|
+
def canonical_string
|
139
|
+
# TODO: Support SubscriptionConfirmation and UnsubscribeConfirmation messages
|
140
|
+
text = "Message\n#{message}\n"
|
141
|
+
text += "MessageId\n#{message_id}\n"
|
142
|
+
text += "Subject\n#{subject}\n" unless subject.nil? or subject.empty?
|
143
|
+
text += "Timestamp\n#{timestamp}\n"
|
144
|
+
text += "TopicArn\n#{topic_arn}\n"
|
145
|
+
text += "Type\n#{type}\n"
|
146
|
+
text
|
147
|
+
end
|
148
|
+
|
149
|
+
def download url
|
150
|
+
raise MessageWasNotAuthenticError, "cert is not hosted at AWS URL (https): #{url}" unless url =~ /^https.*amazonaws\.com\/.*$/i
|
151
|
+
tries = 0
|
152
|
+
begin
|
153
|
+
resp = https_get(url)
|
154
|
+
resp.body
|
155
|
+
rescue => error
|
156
|
+
tries += 1
|
157
|
+
retry if tries < 3
|
158
|
+
raise error
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def https_get(url)
|
163
|
+
uri = URI.parse(url)
|
164
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
165
|
+
http.use_ssl = true
|
166
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
167
|
+
http.start
|
168
|
+
resp = http.request(Net::HTTP::Get.new(uri.request_uri))
|
169
|
+
http.finish
|
170
|
+
resp
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
4
|
+
# may not use this file except in compliance with the License. A copy of
|
5
|
+
# the License is located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is
|
10
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
11
|
+
# ANY KIND, either express or implied. See the License for the specific
|
12
|
+
# language governing permissions and limitations under the License.
|
13
|
+
|
14
|
+
module AWS
|
15
|
+
class SNS
|
16
|
+
|
17
|
+
# A module to enrich {Message} based on it originating from AutoScaling,
|
18
|
+
# which have a particular subject and message payload.
|
19
|
+
# Parses such messages into a more rich representation.
|
20
|
+
module FromAutoScaling
|
21
|
+
def self.extended base
|
22
|
+
base.origin = :autoscaling
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Boolean] true when the SNS originates from auto-scaling
|
26
|
+
def applicable? sns
|
27
|
+
sns['Subject'] =~ /.*autoscaling:.*/i
|
28
|
+
end
|
29
|
+
|
30
|
+
module_function :applicable?
|
31
|
+
|
32
|
+
def body
|
33
|
+
return @body if defined? @body
|
34
|
+
@body = self.parse_from self.raw['Message']
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Symbol] the auto-scaling event name
|
38
|
+
def event
|
39
|
+
return @event if defined? @event
|
40
|
+
e = body['Event']
|
41
|
+
@event = case
|
42
|
+
when e =~ /EC2_INSTANCE_TERMINATE/ then :ec2_instance_terminate
|
43
|
+
when e =~ /EC2_INSTANCE_TERMINATE_ERROR/ then :ec2_instance_terminate_error
|
44
|
+
when e =~ /EC2_INSTANCE_LAUNCH/ then :ec2_instance_launch
|
45
|
+
when e =~ /EC2_INSTANCE_LAUNCH_ERROR/ then :ec2_instance_launch_error
|
46
|
+
when e =~ /TEST_NOTIFICATION/ then :test_notification
|
47
|
+
else :unknown
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [String] the auto-scaling group name
|
52
|
+
def group_name
|
53
|
+
body['AutoScalingGroupName']
|
54
|
+
end
|
55
|
+
|
56
|
+
def status_code
|
57
|
+
body['StatusCode']
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [String] the instance-ID that is the subject of this event
|
61
|
+
def instance_id
|
62
|
+
body['EC2InstanceId']
|
63
|
+
end
|
64
|
+
|
65
|
+
# TODO: Further methods to fully expose what AS-SNS' carry as payload.
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/aws/version.rb
CHANGED
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.12.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Amazon Web Services
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-07-09 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: uuidtools
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,7 +20,6 @@ dependencies:
|
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
@@ -30,7 +27,6 @@ dependencies:
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: nokogiri
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
31
|
- - <
|
36
32
|
- !ruby/object:Gem::Version
|
@@ -38,7 +34,6 @@ dependencies:
|
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - <
|
44
39
|
- !ruby/object:Gem::Version
|
@@ -46,7 +41,6 @@ dependencies:
|
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: json
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
45
|
- - ~>
|
52
46
|
- !ruby/object:Gem::Version
|
@@ -54,14 +48,14 @@ dependencies:
|
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
52
|
- - ~>
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '1.4'
|
62
55
|
description: AWS SDK for Ruby
|
63
56
|
email:
|
64
|
-
executables:
|
57
|
+
executables:
|
58
|
+
- aws-rb
|
65
59
|
extensions: []
|
66
60
|
extra_rdoc_files: []
|
67
61
|
files:
|
@@ -546,6 +540,8 @@ files:
|
|
546
540
|
- lib/aws/sns/config.rb
|
547
541
|
- lib/aws/sns/errors.rb
|
548
542
|
- lib/aws/sns/has_delivery_policy.rb
|
543
|
+
- lib/aws/sns/message.rb
|
544
|
+
- lib/aws/sns/originators/from_auto_scaling.rb
|
549
545
|
- lib/aws/sns/policy.rb
|
550
546
|
- lib/aws/sns/request.rb
|
551
547
|
- lib/aws/sns/subscription.rb
|
@@ -615,30 +611,30 @@ files:
|
|
615
611
|
- lib/aws/api_config/StorageGateway-2012-06-30.yml
|
616
612
|
- lib/aws/api_config/STS-2011-06-15.yml
|
617
613
|
- lib/aws/api_config/Support-2013-04-15.yml
|
614
|
+
- bin/aws-rb
|
618
615
|
homepage: http://aws.amazon.com/sdkforruby
|
619
616
|
licenses:
|
620
617
|
- Apache 2.0
|
618
|
+
metadata: {}
|
621
619
|
post_install_message:
|
622
620
|
rdoc_options: []
|
623
621
|
require_paths:
|
624
622
|
- lib
|
625
623
|
required_ruby_version: !ruby/object:Gem::Requirement
|
626
|
-
none: false
|
627
624
|
requirements:
|
628
|
-
- -
|
625
|
+
- - '>='
|
629
626
|
- !ruby/object:Gem::Version
|
630
627
|
version: '0'
|
631
628
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
632
|
-
none: false
|
633
629
|
requirements:
|
634
|
-
- -
|
630
|
+
- - '>='
|
635
631
|
- !ruby/object:Gem::Version
|
636
632
|
version: '0'
|
637
633
|
requirements: []
|
638
634
|
rubyforge_project:
|
639
|
-
rubygems_version:
|
635
|
+
rubygems_version: 2.0.3
|
640
636
|
signing_key:
|
641
|
-
specification_version:
|
637
|
+
specification_version: 4
|
642
638
|
summary: AWS SDK for Ruby
|
643
639
|
test_files: []
|
644
640
|
has_rdoc:
|