aws-sdk 1.5.2 → 1.5.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/aws/api_config/AutoScaling-2011-01-01.yml +6 -2
- data/lib/aws/api_config/{EC2-2012-04-01.yml → EC2-2012-06-01.yml} +12 -0
- data/lib/aws/api_config/STS-2011-06-15.yml +0 -4
- data/lib/aws/auto_scaling/client.rb +6 -2
- data/lib/aws/auto_scaling/launch_configuration.rb +8 -0
- data/lib/aws/auto_scaling/launch_configuration_collection.rb +14 -4
- data/lib/aws/auto_scaling/scaling_policy.rb +17 -0
- data/lib/aws/auto_scaling/scaling_policy_options.rb +2 -0
- data/lib/aws/core.rb +13 -11
- data/lib/aws/core/cacheable.rb +1 -1
- data/lib/aws/core/client.rb +40 -39
- data/lib/aws/core/configuration.rb +24 -15
- data/lib/aws/core/credential_providers.rb +395 -0
- data/lib/aws/core/http/net_http_handler.rb +1 -0
- data/lib/aws/core/http/request.rb +4 -4
- data/lib/aws/core/log_formatter.rb +2 -0
- data/lib/aws/core/signature/version_2.rb +18 -5
- data/lib/aws/core/signature/version_3.rb +10 -10
- data/lib/aws/core/signature/version_4.rb +13 -13
- data/lib/aws/core/signer.rb +46 -0
- data/lib/aws/dynamo_db/batch_write.rb +2 -1
- data/lib/aws/dynamo_db/client.rb +9 -24
- data/lib/aws/dynamo_db/table.rb +0 -23
- data/lib/aws/ec2/client.rb +19 -1
- data/lib/aws/ec2/image.rb +4 -4
- data/lib/aws/ec2/instance.rb +17 -5
- data/lib/aws/ec2/instance_collection.rb +16 -1
- data/lib/aws/errors.rb +40 -0
- data/lib/aws/s3/client.rb +2 -1
- data/lib/aws/s3/presigned_post.rb +10 -8
- data/lib/aws/s3/request.rb +7 -5
- data/lib/aws/s3/s3_object.rb +10 -9
- data/lib/aws/simple_email_service.rb +1 -1
- data/lib/aws/simple_email_service/identity_collection.rb +1 -1
- data/lib/aws/sts.rb +2 -6
- data/lib/aws/sts/client.rb +14 -17
- metadata +7 -9
- data/lib/aws/api_config/EC2-2011-12-15.yml +0 -3638
- data/lib/aws/core/default_signer.rb +0 -67
- data/lib/aws/core/session_signer.rb +0 -90
- data/lib/aws/core/signature/version_3_http.rb +0 -72
@@ -19,37 +19,37 @@ module AWS
|
|
19
19
|
module Signature
|
20
20
|
module Version3
|
21
21
|
|
22
|
-
def
|
22
|
+
def self.included base
|
23
|
+
base.send(:include, Signer)
|
24
|
+
end
|
23
25
|
|
24
|
-
|
26
|
+
def add_authorization! credentials
|
25
27
|
|
26
28
|
headers["x-amz-date"] ||= (headers["date"] ||= Time.now.rfc822)
|
27
29
|
headers["host"] ||= host
|
28
30
|
|
29
|
-
headers["x-amz-security-token"] =
|
30
|
-
|
31
|
+
headers["x-amz-security-token"] = credentials.session_token if
|
32
|
+
credentials.session_token
|
31
33
|
|
32
34
|
# compute the authorization
|
33
|
-
request_hash = OpenSSL::Digest::SHA256.digest(string_to_sign)
|
34
|
-
signature = signer.sign(request_hash)
|
35
35
|
headers["x-amzn-authorization"] =
|
36
36
|
"AWS3 "+
|
37
|
-
"AWSAccessKeyId=#{
|
37
|
+
"AWSAccessKeyId=#{credentials.access_key_id},"+
|
38
38
|
"Algorithm=HmacSHA256,"+
|
39
39
|
"SignedHeaders=#{headers_to_sign.join(';')},"+
|
40
|
-
"Signature=#{
|
40
|
+
"Signature=#{sign(credentials.secret_access_key, string_to_sign)}"
|
41
41
|
end
|
42
42
|
|
43
43
|
protected
|
44
44
|
|
45
45
|
def string_to_sign
|
46
|
-
[
|
46
|
+
OpenSSL::Digest::SHA256.digest([
|
47
47
|
http_method,
|
48
48
|
"/",
|
49
49
|
"",
|
50
50
|
canonical_headers,
|
51
51
|
body
|
52
|
-
].join("\n")
|
52
|
+
].join("\n"))
|
53
53
|
end
|
54
54
|
|
55
55
|
def canonical_headers
|
@@ -20,28 +20,32 @@ module AWS
|
|
20
20
|
module Signature
|
21
21
|
module Version4
|
22
22
|
|
23
|
-
def
|
24
|
-
|
23
|
+
def self.included base
|
24
|
+
base.send(:include, Signer)
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_authorization! credentials
|
25
28
|
datetime = Time.now.utc.strftime("%Y%m%dT%H%M%SZ")
|
26
29
|
headers['content-type'] ||= 'application/x-www-form-urlencoded'
|
27
30
|
headers['host'] = host
|
28
31
|
headers['x-amz-date'] = datetime
|
29
|
-
headers['x-amz-security-token'] =
|
30
|
-
|
32
|
+
headers['x-amz-security-token'] = credentials.session_token if
|
33
|
+
credentials.session_token
|
34
|
+
headers['authorization'] = authorization(credentials, datetime)
|
31
35
|
end
|
32
36
|
|
33
37
|
protected
|
34
38
|
|
35
|
-
def authorization
|
39
|
+
def authorization credentials, datetime
|
36
40
|
parts = []
|
37
|
-
parts << "AWS4-HMAC-SHA256 Credential=#{access_key_id}/#{credential_string(datetime)}"
|
41
|
+
parts << "AWS4-HMAC-SHA256 Credential=#{credentials.access_key_id}/#{credential_string(datetime)}"
|
38
42
|
parts << "SignedHeaders=#{signed_headers}"
|
39
|
-
parts << "Signature=#{hex16(signature(
|
43
|
+
parts << "Signature=#{hex16(signature(credentials, datetime))}"
|
40
44
|
parts.join(', ')
|
41
45
|
end
|
42
46
|
|
43
|
-
def signature
|
44
|
-
k_secret =
|
47
|
+
def signature credentials, datetime
|
48
|
+
k_secret = credentials.secret_access_key
|
45
49
|
k_date = hmac("AWS4" + k_secret, datetime[0,8])
|
46
50
|
k_region = hmac(k_date, region)
|
47
51
|
k_service = hmac(k_region, service)
|
@@ -124,10 +128,6 @@ module AWS
|
|
124
128
|
string.unpack('H*').first
|
125
129
|
end
|
126
130
|
|
127
|
-
def hmac key, string
|
128
|
-
OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha256'), key, string)
|
129
|
-
end
|
130
|
-
|
131
131
|
def hash string
|
132
132
|
Digest::SHA256.digest(string)
|
133
133
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Copyright 2011-2012 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
|
+
|
16
|
+
module AWS
|
17
|
+
module Core
|
18
|
+
|
19
|
+
# This module provides a {#sign} method that accepts a secret
|
20
|
+
# and a string to sign.
|
21
|
+
module Signer
|
22
|
+
|
23
|
+
# Signs a string using the credentials stored in memory.
|
24
|
+
# @param [String] secret Usually an AWS secret access key.
|
25
|
+
# @param [String] string_to_sign The string to sign.
|
26
|
+
# @param [String] digest_method The digest method to use when
|
27
|
+
# computing the HMAC digest.
|
28
|
+
# @return [String] Returns the computed signature.
|
29
|
+
def sign secret, string_to_sign, digest_method = 'sha256'
|
30
|
+
Base64.encode64(hmac(secret, string_to_sign, digest_method)).strip
|
31
|
+
end
|
32
|
+
module_function :sign
|
33
|
+
|
34
|
+
# Computes an HMAC digest of the passed string.
|
35
|
+
# @param [String] key
|
36
|
+
# @param [String] value
|
37
|
+
# @param [String] digest ('sha256')
|
38
|
+
# @return [String]
|
39
|
+
def hmac key, value, digest = 'sha256'
|
40
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new(digest), key, value)
|
41
|
+
end
|
42
|
+
module_function :hmac
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/aws/dynamo_db/client.rb
CHANGED
@@ -35,12 +35,13 @@ module AWS
|
|
35
35
|
|
36
36
|
super
|
37
37
|
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
|
42
|
-
|
43
|
-
@
|
38
|
+
# Replaces the current credential provider with a SessionProvider
|
39
|
+
# that provides refreshable STS session credentials. DynamoDB
|
40
|
+
# requires session credentials.
|
41
|
+
if credential_provider.session_token.nil?
|
42
|
+
long_term_credentials = credential_provider.credentials
|
43
|
+
@credential_provider = Core::CredentialProviders::SessionProvider.for(
|
44
|
+
long_term_credentials)
|
44
45
|
end
|
45
46
|
|
46
47
|
end
|
@@ -839,26 +840,17 @@ module AWS
|
|
839
840
|
end
|
840
841
|
|
841
842
|
def should_retry? response
|
842
|
-
if
|
843
|
-
true
|
844
|
-
elsif response.error.is_a?(Errors::ProvisionedThroughputExceededException)
|
843
|
+
if response.error.is_a?(Errors::ProvisionedThroughputExceededException)
|
845
844
|
config.dynamo_db_retry_throughput_errors?
|
846
845
|
else
|
847
846
|
super
|
848
847
|
end
|
849
848
|
end
|
850
849
|
|
851
|
-
def rebuild_http_request response
|
852
|
-
# called when a request is going to be retried, in case of
|
853
|
-
# expired credentials we should refresh the session
|
854
|
-
signer.refresh_session if possible_expired_credentials?(response)
|
855
|
-
super
|
856
|
-
end
|
857
|
-
|
858
850
|
def sleep_durations response
|
859
851
|
|
860
852
|
retry_count =
|
861
|
-
if
|
853
|
+
if expired_credentials?(response)
|
862
854
|
config.max_retries == 0 ? 0 : 1
|
863
855
|
else
|
864
856
|
config.max_retries { 10 }
|
@@ -876,13 +868,6 @@ module AWS
|
|
876
868
|
|
877
869
|
end
|
878
870
|
|
879
|
-
# Returns true if we get an access denied error from the service AND
|
880
|
-
# our signer is capible of getting new short-term credentials
|
881
|
-
def possible_expired_credentials? response
|
882
|
-
signer.respond_to?(:refresh_session) and
|
883
|
-
response.error.is_a?(Errors::ExpiredTokenException)
|
884
|
-
end
|
885
|
-
|
886
871
|
end
|
887
872
|
end
|
888
873
|
end
|
data/lib/aws/dynamo_db/table.rb
CHANGED
@@ -420,29 +420,6 @@ module AWS
|
|
420
420
|
#
|
421
421
|
# @return (see BatchWrite#process!)
|
422
422
|
#
|
423
|
-
def batch_put items
|
424
|
-
batch = BatchWrite.new(:config => config)
|
425
|
-
batch.put(self, options)
|
426
|
-
batch.process!
|
427
|
-
end
|
428
|
-
|
429
|
-
# Batch delets up to 25 items.
|
430
|
-
#
|
431
|
-
# table.batch_delete(%w(id1 id2 id3 id4))
|
432
|
-
#
|
433
|
-
# @param [Array<String>,Array<Array>] items A list of item keys to
|
434
|
-
# delete. For tables without a range key, items should be an array
|
435
|
-
# of hash key strings.
|
436
|
-
#
|
437
|
-
# batch.delete('table-name', ['hk1', 'hk2', 'hk3'])
|
438
|
-
#
|
439
|
-
# For tables with a range key, items should be an array of
|
440
|
-
# hash key and range key pairs.
|
441
|
-
#
|
442
|
-
# batch.delete('table-name', [['hk1', 'rk1'], ['hk1', 'rk2']])
|
443
|
-
#
|
444
|
-
# @return (see BatchWrite#process!)
|
445
|
-
#
|
446
423
|
def batch_put items
|
447
424
|
batch = BatchWrite.new(:config => config)
|
448
425
|
batch.put(self, items)
|
data/lib/aws/ec2/client.rb
CHANGED
@@ -17,7 +17,7 @@ module AWS
|
|
17
17
|
# Client class for Amazon Elastic Compute Cloud (EC2).
|
18
18
|
class Client < Core::Client
|
19
19
|
|
20
|
-
API_VERSION = '2012-
|
20
|
+
API_VERSION = '2012-06-01'
|
21
21
|
|
22
22
|
extend Core::Client::QueryXML
|
23
23
|
|
@@ -1883,6 +1883,9 @@ module AWS
|
|
1883
1883
|
# * +:association+ - (Hash)
|
1884
1884
|
# * +:public_ip+ - (String)
|
1885
1885
|
# * +:ip_owner_id+ - (String)
|
1886
|
+
# * +:iam_instance_profile+ - (Hash)
|
1887
|
+
# * +:arn+ - (String)
|
1888
|
+
# * +:id+ - (String)
|
1886
1889
|
#
|
1887
1890
|
# @return [Core::Response]
|
1888
1891
|
#
|
@@ -2471,6 +2474,9 @@ module AWS
|
|
2471
2474
|
# * +:private_ip_address+ - (String)
|
2472
2475
|
# * +:security_group_id+ - (Array<String>)
|
2473
2476
|
# * +:delete_on_termination+ - (Boolean)
|
2477
|
+
# * +:iam_instance_profile+ - (Hash)
|
2478
|
+
# * +:arn+ - (String)
|
2479
|
+
# * +:name+ - (String)
|
2474
2480
|
# * +:instance_id+ - (String)
|
2475
2481
|
# * +:create_time+ - (Time)
|
2476
2482
|
# * +:product_description+ - (String)
|
@@ -3612,6 +3618,9 @@ module AWS
|
|
3612
3618
|
# * +:private_ip_address+ - (String)
|
3613
3619
|
# * +:groups+ - (Array<String>)
|
3614
3620
|
# * +:delete_on_termination+ - (Boolean)
|
3621
|
+
# * +:iam_instance_profile+ - (Hash)
|
3622
|
+
# * +:arn+ - (String)
|
3623
|
+
# * +:name+ - (String)
|
3615
3624
|
#
|
3616
3625
|
# === Response Structure:
|
3617
3626
|
#
|
@@ -3659,6 +3668,9 @@ module AWS
|
|
3659
3668
|
# * +:private_ip_address+ - (String)
|
3660
3669
|
# * +:security_group_id+ - (Array<String>)
|
3661
3670
|
# * +:delete_on_termination+ - (Boolean)
|
3671
|
+
# * +:iam_instance_profile+ - (Hash)
|
3672
|
+
# * +:arn+ - (String)
|
3673
|
+
# * +:name+ - (String)
|
3662
3674
|
# * +:instance_id+ - (String)
|
3663
3675
|
# * +:create_time+ - (Time)
|
3664
3676
|
# * +:product_description+ - (String)
|
@@ -3929,6 +3941,9 @@ module AWS
|
|
3929
3941
|
# * +:private_ip_address+ - (String)
|
3930
3942
|
# * +:groups+ - (Array<String>)
|
3931
3943
|
# * +:delete_on_termination+ - (Boolean)
|
3944
|
+
# * +:iam_instance_profile+ - (Hash)
|
3945
|
+
# * +:arn+ - (String)
|
3946
|
+
# * +:name+ - (String)
|
3932
3947
|
#
|
3933
3948
|
# === Response Structure:
|
3934
3949
|
#
|
@@ -4016,6 +4031,9 @@ module AWS
|
|
4016
4031
|
# * +:association+ - (Hash)
|
4017
4032
|
# * +:public_ip+ - (String)
|
4018
4033
|
# * +:ip_owner_id+ - (String)
|
4034
|
+
# * +:iam_instance_profile+ - (Hash)
|
4035
|
+
# * +:arn+ - (String)
|
4036
|
+
# * +:id+ - (String)
|
4019
4037
|
#
|
4020
4038
|
# @return [Core::Response]
|
4021
4039
|
#
|
data/lib/aws/ec2/image.rb
CHANGED
@@ -146,15 +146,15 @@ module AWS
|
|
146
146
|
# @return [Hash] Returns a hash of block
|
147
147
|
# device mappings for the image. In each entry, the key is
|
148
148
|
# the device name (e.g. +"/dev/sda1"+) and the value is an
|
149
|
-
#
|
149
|
+
# hash with the following keys that return information
|
150
150
|
# about the block device:
|
151
151
|
#
|
152
|
-
# [snapshot_id] The ID of the snapshot that will be used to
|
152
|
+
# [:snapshot_id] The ID of the snapshot that will be used to
|
153
153
|
# create this device (may be nil).
|
154
154
|
#
|
155
|
-
# [volume_size] The size of the volume, in GiBs.
|
155
|
+
# [:volume_size] The size of the volume, in GiBs.
|
156
156
|
#
|
157
|
-
# [delete_on_termination] True if the Amazon EBS volume is
|
157
|
+
# [:delete_on_termination] True if the Amazon EBS volume is
|
158
158
|
# deleted on instance termination.
|
159
159
|
def block_device_mappings
|
160
160
|
(block_device_mapping || []).inject({}) do |h,mapping|
|
data/lib/aws/ec2/instance.rb
CHANGED
@@ -144,6 +144,10 @@ module AWS
|
|
144
144
|
# @attr_reader [String,nil] subnet_id Instances launched in a VPC have
|
145
145
|
# a subnet_id. Normal EC2 instances return nil.
|
146
146
|
#
|
147
|
+
# @attr_reader [String,nil] iam_instance_profile_id
|
148
|
+
#
|
149
|
+
# @attr_reader [String,nil] iam_instance_profile_arn
|
150
|
+
#
|
147
151
|
class Instance < Resource
|
148
152
|
|
149
153
|
include TaggedItem
|
@@ -260,6 +264,18 @@ module AWS
|
|
260
264
|
|
261
265
|
describe_call_attribute :subnet_id, :static => true
|
262
266
|
|
267
|
+
describe_call_attribute :iam_instance_profile_id,
|
268
|
+
:as => :iam_instance_profile,
|
269
|
+
:static => true do
|
270
|
+
translates_output{|profile| profile[:id] }
|
271
|
+
end
|
272
|
+
|
273
|
+
describe_call_attribute :iam_instance_profile_arn,
|
274
|
+
:as => :iam_instance_profile,
|
275
|
+
:static => true do
|
276
|
+
translates_output{|profile| profile[:arn] }
|
277
|
+
end
|
278
|
+
|
263
279
|
attribute :status do
|
264
280
|
translates_output{|state| state.name.tr("-","_").to_sym }
|
265
281
|
end
|
@@ -631,20 +647,17 @@ module AWS
|
|
631
647
|
instance_action :stop
|
632
648
|
end
|
633
649
|
|
634
|
-
# @private
|
635
650
|
protected
|
651
|
+
|
636
652
|
def find_in_response resp
|
637
653
|
resp.instance_index[id]
|
638
654
|
end
|
639
655
|
|
640
|
-
# @private
|
641
|
-
protected
|
642
656
|
def instance_action name
|
643
657
|
client.send("#{name}_instances", :instance_ids => [id])
|
644
658
|
nil
|
645
659
|
end
|
646
660
|
|
647
|
-
protected
|
648
661
|
def get_resource attribute
|
649
662
|
if self.class.mutable_describe_attributes.include?(attribute.name)
|
650
663
|
describe_attribute_call(attribute)
|
@@ -653,7 +666,6 @@ module AWS
|
|
653
666
|
end
|
654
667
|
end
|
655
668
|
|
656
|
-
protected
|
657
669
|
def attributes_from_response_object(obj)
|
658
670
|
if atts = super(obj)
|
659
671
|
if obj[:instance_state]
|
@@ -76,13 +76,17 @@ module AWS
|
|
76
76
|
# @param [Hash] options Options for new instance. +:image_id+ is
|
77
77
|
# the only required option.
|
78
78
|
#
|
79
|
-
# @option options :count How many instances to request. By
|
79
|
+
# @option options [Integer] :count How many instances to request. By
|
80
80
|
# default one instance is requested. You can specify this
|
81
81
|
# either as an integer or as a Range, to indicate the
|
82
82
|
# minimum and maximum number of instances to run. Note that
|
83
83
|
# for a new account you can request at most 20 instances at
|
84
84
|
# once.
|
85
85
|
#
|
86
|
+
# @option options [String] :iam_instance_profile The name or
|
87
|
+
# ARN of an IAM instance profile. This provides credentials
|
88
|
+
# to the EC2 instance(s) via the instance metadata service.
|
89
|
+
#
|
86
90
|
# @option options [Hash] :block_device_mappings This must be a
|
87
91
|
# hash; the keys are device names to map, and the value for
|
88
92
|
# each entry determines how that device is mapped. Valid
|
@@ -192,6 +196,17 @@ module AWS
|
|
192
196
|
#
|
193
197
|
def create options = {}
|
194
198
|
|
199
|
+
if profile = options.delete(:iam_instance_profile)
|
200
|
+
profile = case profile
|
201
|
+
when /^arn:aws:iam::/ then { :arn => profile }
|
202
|
+
when String then { :name => profile }
|
203
|
+
when Hash then profile
|
204
|
+
else
|
205
|
+
msg = "expected a name or ARN string for :iam_instance_profile"
|
206
|
+
end
|
207
|
+
options[:iam_instance_profile] = profile
|
208
|
+
end
|
209
|
+
|
195
210
|
if image = options.delete(:image)
|
196
211
|
options[:image_id] = image.id
|
197
212
|
end
|
data/lib/aws/errors.rb
CHANGED
@@ -118,5 +118,45 @@ module AWS
|
|
118
118
|
extend ExceptionMixinClassMethods
|
119
119
|
end
|
120
120
|
|
121
|
+
# Raised when AWS credentials could not be found.
|
122
|
+
class MissingCredentialsError < StandardError
|
123
|
+
|
124
|
+
def initialize msg = nil
|
125
|
+
msg ||= <<-MSG
|
126
|
+
|
127
|
+
Missing Credentials.
|
128
|
+
|
129
|
+
Unable to find AWS credentials. You can configure your AWS credentials
|
130
|
+
a few different ways:
|
131
|
+
|
132
|
+
* Call AWS.config with :access_key_id and :secret_access_key
|
133
|
+
|
134
|
+
* Export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to ENV
|
135
|
+
|
136
|
+
* On EC2 you can run instances with an IAM instance profile and credentials
|
137
|
+
will be auto loaded from the instance metadata service on those
|
138
|
+
instances.
|
139
|
+
|
140
|
+
* Call AWS.config with :credential_provider. A credential provider should
|
141
|
+
either include AWS::Core::CredentialProviders::Provider or respond to
|
142
|
+
the same public methods.
|
143
|
+
|
144
|
+
= Ruby on Rails
|
145
|
+
|
146
|
+
In a Ruby on Rails application you may also specify your credentials in
|
147
|
+
the following ways:
|
148
|
+
|
149
|
+
* Via a config initializer script using any of the methods mentioned above
|
150
|
+
(e.g. RAILS_ROOT/config/initializers/aws-sdk.rb).
|
151
|
+
|
152
|
+
* Via a yaml configuration file located at RAILS_ROOT/config/aws.yml.
|
153
|
+
This file should be formated like the default RAILS_ROOT/config/database.yml
|
154
|
+
file.
|
155
|
+
|
156
|
+
MSG
|
157
|
+
super(msg)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
121
161
|
end
|
122
162
|
end
|