geemus-fog 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +6 -0
- data/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +94 -0
- data/VERSION +1 -0
- data/benchs/fog_vs.rb +76 -0
- data/benchs/headers_split_vs_match.rb +18 -0
- data/benchs/params.rb +43 -0
- data/benchs/parse_vs_push.rb +60 -0
- data/benchs/stripping.rb +26 -0
- data/lib/fog/aws/ec2.rb +159 -0
- data/lib/fog/aws/parsers/ec2/allocate_address.rb +19 -0
- data/lib/fog/aws/parsers/ec2/attach_volume.rb +22 -0
- data/lib/fog/aws/parsers/ec2/basic.rb +25 -0
- data/lib/fog/aws/parsers/ec2/create_key_pair.rb +20 -0
- data/lib/fog/aws/parsers/ec2/create_snapshot.rb +22 -0
- data/lib/fog/aws/parsers/ec2/create_volume.rb +24 -0
- data/lib/fog/aws/parsers/ec2/describe_addresses.rb +30 -0
- data/lib/fog/aws/parsers/ec2/describe_availability_zones.rb +30 -0
- data/lib/fog/aws/parsers/ec2/describe_images.rb +49 -0
- data/lib/fog/aws/parsers/ec2/describe_instances.rb +73 -0
- data/lib/fog/aws/parsers/ec2/describe_key_pairs.rb +30 -0
- data/lib/fog/aws/parsers/ec2/describe_regions.rb +30 -0
- data/lib/fog/aws/parsers/ec2/describe_security_groups.rb +75 -0
- data/lib/fog/aws/parsers/ec2/describe_snapshots.rb +30 -0
- data/lib/fog/aws/parsers/ec2/describe_volumes.rb +57 -0
- data/lib/fog/aws/parsers/ec2/detach_volume.rb +22 -0
- data/lib/fog/aws/parsers/ec2/get_console_output.rb +28 -0
- data/lib/fog/aws/parsers/ec2/run_instances.rb +65 -0
- data/lib/fog/aws/parsers/ec2/terminate_instances.rb +55 -0
- data/lib/fog/aws/parsers/s3/copy_object.rb +22 -0
- data/lib/fog/aws/parsers/s3/get_bucket.rb +46 -0
- data/lib/fog/aws/parsers/s3/get_bucket_location.rb +20 -0
- data/lib/fog/aws/parsers/s3/get_request_payment.rb +20 -0
- data/lib/fog/aws/parsers/s3/get_service.rb +32 -0
- data/lib/fog/aws/parsers/simpledb/basic.rb +31 -0
- data/lib/fog/aws/parsers/simpledb/domain_metadata.rb +30 -0
- data/lib/fog/aws/parsers/simpledb/get_attributes.rb +34 -0
- data/lib/fog/aws/parsers/simpledb/list_domains.rb +28 -0
- data/lib/fog/aws/parsers/simpledb/select.rb +39 -0
- data/lib/fog/aws/requests/ec2/allocate_address.rb +50 -0
- data/lib/fog/aws/requests/ec2/associate_address.rb +26 -0
- data/lib/fog/aws/requests/ec2/attach_volume.rb +32 -0
- data/lib/fog/aws/requests/ec2/authorize_security_group_ingress.rb +32 -0
- data/lib/fog/aws/requests/ec2/create_key_pair.rb +60 -0
- data/lib/fog/aws/requests/ec2/create_security_group.rb +61 -0
- data/lib/fog/aws/requests/ec2/create_snapshot.rb +28 -0
- data/lib/fog/aws/requests/ec2/create_volume.rb +66 -0
- data/lib/fog/aws/requests/ec2/delete_key_pair.rb +49 -0
- data/lib/fog/aws/requests/ec2/delete_security_group.rb +52 -0
- data/lib/fog/aws/requests/ec2/delete_snapshot.rb +24 -0
- data/lib/fog/aws/requests/ec2/delete_volume.rb +55 -0
- data/lib/fog/aws/requests/ec2/describe_addresses.rb +61 -0
- data/lib/fog/aws/requests/ec2/describe_availability_zones.rb +27 -0
- data/lib/fog/aws/requests/ec2/describe_images.rb +41 -0
- data/lib/fog/aws/requests/ec2/describe_instances.rb +48 -0
- data/lib/fog/aws/requests/ec2/describe_key_pairs.rb +63 -0
- data/lib/fog/aws/requests/ec2/describe_regions.rb +26 -0
- data/lib/fog/aws/requests/ec2/describe_security_groups.rb +71 -0
- data/lib/fog/aws/requests/ec2/describe_snapshots.rb +29 -0
- data/lib/fog/aws/requests/ec2/describe_volumes.rb +85 -0
- data/lib/fog/aws/requests/ec2/detach_volume.rb +32 -0
- data/lib/fog/aws/requests/ec2/disassociate_address.rb +24 -0
- data/lib/fog/aws/requests/ec2/get_console_output.rb +26 -0
- data/lib/fog/aws/requests/ec2/reboot_instances.rb +24 -0
- data/lib/fog/aws/requests/ec2/release_address.rb +50 -0
- data/lib/fog/aws/requests/ec2/revoke_security_group_ingress.rb +32 -0
- data/lib/fog/aws/requests/ec2/run_instances.rb +74 -0
- data/lib/fog/aws/requests/ec2/terminate_instances.rb +31 -0
- data/lib/fog/aws/requests/s3/copy_object.rb +80 -0
- data/lib/fog/aws/requests/s3/delete_bucket.rb +49 -0
- data/lib/fog/aws/requests/s3/delete_object.rb +52 -0
- data/lib/fog/aws/requests/s3/get_bucket.rb +92 -0
- data/lib/fog/aws/requests/s3/get_bucket_location.rb +53 -0
- data/lib/fog/aws/requests/s3/get_object.rb +81 -0
- data/lib/fog/aws/requests/s3/get_request_payment.rb +53 -0
- data/lib/fog/aws/requests/s3/get_service.rb +58 -0
- data/lib/fog/aws/requests/s3/head_object.rb +61 -0
- data/lib/fog/aws/requests/s3/put_bucket.rb +69 -0
- data/lib/fog/aws/requests/s3/put_object.rb +75 -0
- data/lib/fog/aws/requests/s3/put_request_payment.rb +56 -0
- data/lib/fog/aws/requests/simpledb/batch_put_attributes.rb +31 -0
- data/lib/fog/aws/requests/simpledb/create_domain.rb +25 -0
- data/lib/fog/aws/requests/simpledb/delete_attributes.rb +34 -0
- data/lib/fog/aws/requests/simpledb/delete_domain.rb +25 -0
- data/lib/fog/aws/requests/simpledb/domain_metadata.rb +30 -0
- data/lib/fog/aws/requests/simpledb/get_attributes.rb +35 -0
- data/lib/fog/aws/requests/simpledb/list_domains.rb +30 -0
- data/lib/fog/aws/requests/simpledb/put_attributes.rb +29 -0
- data/lib/fog/aws/requests/simpledb/select.rb +29 -0
- data/lib/fog/aws/s3.rb +143 -0
- data/lib/fog/aws/simpledb.rb +157 -0
- data/lib/fog/aws.rb +127 -0
- data/lib/fog/connection.rb +122 -0
- data/lib/fog/errors.rb +131 -0
- data/lib/fog/parser.rb +30 -0
- data/lib/fog/response.rb +12 -0
- data/lib/fog.rb +22 -0
- data/spec/aws/ec2/allocate_address_spec.rb +20 -0
- data/spec/aws/ec2/associate_address_spec.rb +22 -0
- data/spec/aws/ec2/attach_volume_spec.rb +33 -0
- data/spec/aws/ec2/authorize_security_group_ingress_spec.rb +25 -0
- data/spec/aws/ec2/create_key_pair_spec.rb +27 -0
- data/spec/aws/ec2/create_security_group_spec.rb +25 -0
- data/spec/aws/ec2/create_snapshot_spec.rb +27 -0
- data/spec/aws/ec2/create_volume_spec.rb +25 -0
- data/spec/aws/ec2/delete_key_pair_spec.rb +20 -0
- data/spec/aws/ec2/delete_security_group_spec.rb +22 -0
- data/spec/aws/ec2/delete_snapshot_spec.rb +25 -0
- data/spec/aws/ec2/delete_volume_spec.rb +22 -0
- data/spec/aws/ec2/describe_addresses_spec.rb +34 -0
- data/spec/aws/ec2/describe_availability_zones_spec.rb +25 -0
- data/spec/aws/ec2/describe_images_spec.rb +41 -0
- data/spec/aws/ec2/describe_instances_spec.rb +76 -0
- data/spec/aws/ec2/describe_key_pairs_spec.rb +38 -0
- data/spec/aws/ec2/describe_regions_spec.rb +23 -0
- data/spec/aws/ec2/describe_security_groups_spec.rb +47 -0
- data/spec/aws/ec2/describe_snapshot_spec.rb +44 -0
- data/spec/aws/ec2/describe_volumes_spec.rb +46 -0
- data/spec/aws/ec2/detach_volume_spec.rb +33 -0
- data/spec/aws/ec2/disassociate_address_spec.rb +23 -0
- data/spec/aws/ec2/get_console_output_spec.rb +22 -0
- data/spec/aws/ec2/reboot_instances_spec.rb +20 -0
- data/spec/aws/ec2/release_address_spec.rb +22 -0
- data/spec/aws/ec2/revoke_security_group_ingress_spec.rb +31 -0
- data/spec/aws/ec2/run_instances_spec.rb +43 -0
- data/spec/aws/ec2/terminate_instances_spec.rb +25 -0
- data/spec/aws/s3/copy_object_spec.rb +57 -0
- data/spec/aws/s3/delete_bucket_spec.rb +21 -0
- data/spec/aws/s3/delete_object_spec.rb +31 -0
- data/spec/aws/s3/get_bucket_location_spec.rb +30 -0
- data/spec/aws/s3/get_bucket_spec.rb +42 -0
- data/spec/aws/s3/get_object_spec.rb +40 -0
- data/spec/aws/s3/get_request_payment_spec.rb +26 -0
- data/spec/aws/s3/get_service_spec.rb +32 -0
- data/spec/aws/s3/head_object_spec.rb +27 -0
- data/spec/aws/s3/put_bucket_spec.rb +22 -0
- data/spec/aws/s3/put_object_spec.rb +34 -0
- data/spec/aws/s3/put_request_payment_spec.rb +25 -0
- data/spec/aws/simpledb/batch_put_attributes_spec.rb +21 -0
- data/spec/aws/simpledb/create_domain_spec.rb +20 -0
- data/spec/aws/simpledb/delete_attributes_spec.rb +21 -0
- data/spec/aws/simpledb/delete_domain_spec.rb +20 -0
- data/spec/aws/simpledb/domain_metadata_spec.rb +42 -0
- data/spec/aws/simpledb/get_attributes_spec.rb +30 -0
- data/spec/aws/simpledb/list_domains_spec.rb +29 -0
- data/spec/aws/simpledb/put_attributes_spec.rb +21 -0
- data/spec/aws/simpledb/select_spec.rb +7 -0
- data/spec/lorem.txt +1 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +74 -0
- metadata +256 -0
data/lib/fog/aws/s3.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
module Fog
|
2
|
+
module AWS
|
3
|
+
class S3
|
4
|
+
|
5
|
+
def self.reload
|
6
|
+
current_directory = File.dirname(__FILE__)
|
7
|
+
load "#{current_directory}/../connection.rb"
|
8
|
+
load "#{current_directory}/../parser.rb"
|
9
|
+
load "#{current_directory}/../response.rb"
|
10
|
+
|
11
|
+
parsers_directory = "#{current_directory}/parsers/s3"
|
12
|
+
load "#{parsers_directory}/copy_object.rb"
|
13
|
+
load "#{parsers_directory}/get_bucket.rb"
|
14
|
+
load "#{parsers_directory}/get_bucket_location.rb"
|
15
|
+
load "#{parsers_directory}/get_request_payment.rb"
|
16
|
+
load "#{parsers_directory}/get_service.rb"
|
17
|
+
|
18
|
+
requests_directory = "#{current_directory}/requests/s3"
|
19
|
+
load "#{requests_directory}/copy_object.rb"
|
20
|
+
load "#{requests_directory}/delete_bucket.rb"
|
21
|
+
load "#{requests_directory}/delete_object.rb"
|
22
|
+
load "#{requests_directory}/get_bucket.rb"
|
23
|
+
load "#{requests_directory}/get_bucket_location.rb"
|
24
|
+
load "#{requests_directory}/get_object.rb"
|
25
|
+
load "#{requests_directory}/get_request_payment.rb"
|
26
|
+
load "#{requests_directory}/get_service.rb"
|
27
|
+
load "#{requests_directory}/head_object.rb"
|
28
|
+
load "#{requests_directory}/put_bucket.rb"
|
29
|
+
load "#{requests_directory}/put_object.rb"
|
30
|
+
load "#{requests_directory}/put_request_payment.rb"
|
31
|
+
end
|
32
|
+
|
33
|
+
if Fog.mocking?
|
34
|
+
attr_accessor :data
|
35
|
+
end
|
36
|
+
|
37
|
+
# Initialize connection to S3
|
38
|
+
#
|
39
|
+
# ==== Notes
|
40
|
+
# options parameter must include values for :aws_access_key_id and
|
41
|
+
# :aws_secret_access_key in order to create a connection
|
42
|
+
#
|
43
|
+
# ==== Examples
|
44
|
+
# sdb = S3.new(
|
45
|
+
# :aws_access_key_id => your_aws_access_key_id,
|
46
|
+
# :aws_secret_access_key => your_aws_secret_access_key
|
47
|
+
# )
|
48
|
+
#
|
49
|
+
# ==== Parameters
|
50
|
+
# * options<~Hash> - config arguments for connection. Defaults to {}.
|
51
|
+
#
|
52
|
+
# ==== Returns
|
53
|
+
# * S3 object with connection to aws.
|
54
|
+
def initialize(options={})
|
55
|
+
@aws_access_key_id = options[:aws_access_key_id]
|
56
|
+
@aws_secret_access_key = options[:aws_secret_access_key]
|
57
|
+
@hmac = HMAC::SHA1.new(@aws_secret_access_key)
|
58
|
+
@host = options[:host] || 's3.amazonaws.com'
|
59
|
+
@port = options[:port] || 443
|
60
|
+
@scheme = options[:scheme] || 'https'
|
61
|
+
@connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}")
|
62
|
+
|
63
|
+
if Fog.mocking?
|
64
|
+
@data = { :buckets => {} }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def parse_file(file)
|
71
|
+
metadata = {
|
72
|
+
:body => nil,
|
73
|
+
:headers => {}
|
74
|
+
}
|
75
|
+
|
76
|
+
filename = File.basename(file.path)
|
77
|
+
unless (mime_types = MIME::Types.of(filename)).empty?
|
78
|
+
metadata[:headers]['Content-Type'] = mime_types.first.content_type
|
79
|
+
end
|
80
|
+
|
81
|
+
metadata[:body] = file.read
|
82
|
+
metadata[:headers]['Content-Length'] = metadata[:body].size.to_s
|
83
|
+
metadata[:headers]['Content-MD5'] = Base64.encode64(Digest::MD5.digest(metadata[:body])).strip
|
84
|
+
metadata
|
85
|
+
end
|
86
|
+
|
87
|
+
def request(params)
|
88
|
+
params[:headers]['Date'] = Time.now.utc.strftime("%a, %d %b %Y %H:%M:%S +0000")
|
89
|
+
|
90
|
+
string_to_sign =
|
91
|
+
<<-DATA
|
92
|
+
#{params[:method]}
|
93
|
+
#{params[:headers]['Content-MD5']}
|
94
|
+
#{params[:headers]['Content-Type']}
|
95
|
+
#{params[:headers]['Date']}
|
96
|
+
DATA
|
97
|
+
|
98
|
+
amz_headers, canonical_amz_headers = {}, ''
|
99
|
+
for key, value in params[:headers]
|
100
|
+
if key[0..5] == 'x-amz-'
|
101
|
+
amz_headers[key] = value
|
102
|
+
end
|
103
|
+
end
|
104
|
+
amz_headers = amz_headers.sort {|x, y| x[0] <=> y[0]}
|
105
|
+
for pair in amz_headers
|
106
|
+
canonical_amz_headers << "#{pair[0]}:#{pair[1]}\n"
|
107
|
+
end
|
108
|
+
string_to_sign << "#{canonical_amz_headers}"
|
109
|
+
|
110
|
+
canonical_resource = "/"
|
111
|
+
subdomain = params[:host].split(".#{@host}").first
|
112
|
+
unless subdomain == @host
|
113
|
+
canonical_resource << "#{subdomain}/"
|
114
|
+
end
|
115
|
+
canonical_resource << "#{params[:path]}"
|
116
|
+
if params[:query] && !params[:query].empty?
|
117
|
+
canonical_resource << "?#{params[:query]}"
|
118
|
+
end
|
119
|
+
string_to_sign << "#{canonical_resource}"
|
120
|
+
|
121
|
+
hmac = @hmac.update(string_to_sign)
|
122
|
+
signature = Base64.encode64(hmac.digest).chomp!
|
123
|
+
params[:headers]['Authorization'] = "AWS #{@aws_access_key_id}:#{signature}"
|
124
|
+
|
125
|
+
response = @connection.request({
|
126
|
+
:body => params[:body],
|
127
|
+
:expects => params[:expects],
|
128
|
+
:headers => params[:headers],
|
129
|
+
:host => params[:host],
|
130
|
+
:method => params[:method],
|
131
|
+
:parser => params[:parser],
|
132
|
+
:path => params[:path],
|
133
|
+
:query => params[:query]
|
134
|
+
})
|
135
|
+
|
136
|
+
response
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
Fog::AWS::S3.reload
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module Fog
|
2
|
+
module AWS
|
3
|
+
class SimpleDB
|
4
|
+
|
5
|
+
def self.reload
|
6
|
+
current_directory = File.dirname(__FILE__)
|
7
|
+
load "#{current_directory}/../connection.rb"
|
8
|
+
load "#{current_directory}/../parser.rb"
|
9
|
+
load "#{current_directory}/../response.rb"
|
10
|
+
|
11
|
+
parsers_directory = "#{current_directory}/parsers/simpledb"
|
12
|
+
load "#{parsers_directory}/basic.rb"
|
13
|
+
load "#{parsers_directory}/domain_metadata.rb"
|
14
|
+
load "#{parsers_directory}/get_attributes.rb"
|
15
|
+
load "#{parsers_directory}/list_domains.rb"
|
16
|
+
load "#{parsers_directory}/select.rb"
|
17
|
+
|
18
|
+
requests_directory = "#{current_directory}/requests/simpledb"
|
19
|
+
load "#{requests_directory}/batch_put_attributes.rb"
|
20
|
+
load "#{requests_directory}/create_domain.rb"
|
21
|
+
load "#{requests_directory}/delete_attributes.rb"
|
22
|
+
load "#{requests_directory}/delete_domain.rb"
|
23
|
+
load "#{requests_directory}/domain_metadata.rb"
|
24
|
+
load "#{requests_directory}/get_attributes.rb"
|
25
|
+
load "#{requests_directory}/list_domains.rb"
|
26
|
+
load "#{requests_directory}/put_attributes.rb"
|
27
|
+
load "#{requests_directory}/select.rb"
|
28
|
+
end
|
29
|
+
|
30
|
+
# Initialize connection to SimpleDB
|
31
|
+
#
|
32
|
+
# ==== Notes
|
33
|
+
# options parameter must include values for :aws_access_key_id and
|
34
|
+
# :aws_secret_access_key in order to create a connection
|
35
|
+
#
|
36
|
+
# ==== Examples
|
37
|
+
# sdb = SimpleDB.new(
|
38
|
+
# :aws_access_key_id => your_aws_access_key_id,
|
39
|
+
# :aws_secret_access_key => your_aws_secret_access_key
|
40
|
+
# )
|
41
|
+
#
|
42
|
+
# ==== Parameters
|
43
|
+
# * options<~Hash> - config arguments for connection. Defaults to {}.
|
44
|
+
#
|
45
|
+
# ==== Returns
|
46
|
+
# * SimpleDB object with connection to aws.
|
47
|
+
def initialize(options={})
|
48
|
+
@aws_access_key_id = options[:aws_access_key_id]
|
49
|
+
@aws_secret_access_key = options[:aws_secret_access_key]
|
50
|
+
@hmac = HMAC::SHA256.new(@aws_secret_access_key)
|
51
|
+
@host = options[:host] || 'sdb.amazonaws.com'
|
52
|
+
@nil_string = options[:nil_string]|| 'nil'
|
53
|
+
@port = options[:port] || 443
|
54
|
+
@scheme = options[:scheme] || 'https'
|
55
|
+
@connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}")
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def encode_attributes(attributes, replace_attributes = [])
|
61
|
+
encoded_attributes = {}
|
62
|
+
if attributes
|
63
|
+
index = 0
|
64
|
+
for key in attributes.keys
|
65
|
+
for value in Array(attributes[key])
|
66
|
+
encoded_attributes["Attribute.#{index}.Name"] = key.to_s
|
67
|
+
if replace_attributes.include?(key)
|
68
|
+
encoded_attributes["Attribute.#{index}.Replace"] = 'true'
|
69
|
+
end
|
70
|
+
encoded_attributes["Attribute.#{index}.Value"] = sdb_encode(value)
|
71
|
+
index += 1
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
encoded_attributes
|
76
|
+
end
|
77
|
+
|
78
|
+
def encode_attribute_names(attributes)
|
79
|
+
encoded_attribute_names = {}
|
80
|
+
if attributes
|
81
|
+
index = 0
|
82
|
+
for attribute in attributes
|
83
|
+
encoded_attribute_names["AttributeName.#{index}"] = attribute.to_s
|
84
|
+
index += 1
|
85
|
+
end
|
86
|
+
end
|
87
|
+
encoded_attribute_names
|
88
|
+
end
|
89
|
+
|
90
|
+
def encode_batch_attributes(items, replace_attributes = Hash.new([]))
|
91
|
+
encoded_attributes = {}
|
92
|
+
if items
|
93
|
+
item_index = 0
|
94
|
+
for item_key in items.keys
|
95
|
+
encoded_attributes["Item.#{item_index}.ItemName"] = item_key.to_s
|
96
|
+
for attribute_key in items[item_key].keys
|
97
|
+
attribute_index = 0
|
98
|
+
for value in Array(items[item_key][attribute_key])
|
99
|
+
encoded_attributes["Item.#{item_index}.Attribute.#{attribute_index}.Name"] = attribute_key.to_s
|
100
|
+
if replace_attributes[item_key].include?(attribute_key)
|
101
|
+
encoded_attributes["Item.#{item_index}.Attribute.#{attribute_index}.Replace"] = 'true'
|
102
|
+
end
|
103
|
+
encoded_attributes["Item.#{item_index}.Attribute.#{attribute_index}.Value"] = sdb_encode(value)
|
104
|
+
attribute_index += 1
|
105
|
+
end
|
106
|
+
item_index += 1
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
encoded_attributes
|
111
|
+
end
|
112
|
+
|
113
|
+
def request(params, parser)
|
114
|
+
params.merge!({
|
115
|
+
'AWSAccessKeyId' => @aws_access_key_id,
|
116
|
+
'SignatureMethod' => 'HmacSHA256',
|
117
|
+
'SignatureVersion' => '2',
|
118
|
+
'Timestamp' => Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
119
|
+
'Version' => '2007-11-07'
|
120
|
+
})
|
121
|
+
|
122
|
+
body = ''
|
123
|
+
for key in params.keys.sort
|
124
|
+
unless (value = params[key]).nil?
|
125
|
+
body << "#{key}=#{CGI.escape(value.to_s).gsub(/\+/, '%20')}&"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
string_to_sign = "POST\n#{@host}\n/\n" << body.chop
|
130
|
+
hmac = @hmac.update(string_to_sign)
|
131
|
+
body << "Signature=#{CGI.escape(Base64.encode64(hmac.digest).chomp!).gsub(/\+/, '%20')}"
|
132
|
+
|
133
|
+
response = @connection.request({
|
134
|
+
:body => body,
|
135
|
+
:expects => 200,
|
136
|
+
:headers => { 'Content-Type' => 'application/x-www-form-urlencoded' },
|
137
|
+
:host => @host,
|
138
|
+
:method => 'POST',
|
139
|
+
:parser => parser
|
140
|
+
})
|
141
|
+
|
142
|
+
response
|
143
|
+
end
|
144
|
+
|
145
|
+
def sdb_encode(value)
|
146
|
+
if value.nil?
|
147
|
+
@nil_string
|
148
|
+
else
|
149
|
+
value.to_s
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
Fog::AWS::SimpleDB.reload
|
data/lib/fog/aws.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'base64'
|
3
|
+
require 'cgi'
|
4
|
+
require 'digest/md5'
|
5
|
+
require 'hmac-sha1'
|
6
|
+
require 'hmac-sha2'
|
7
|
+
require 'mime/types'
|
8
|
+
|
9
|
+
module Fog
|
10
|
+
module AWS
|
11
|
+
|
12
|
+
def self.reload
|
13
|
+
current_directory = File.dirname(__FILE__)
|
14
|
+
load "#{current_directory}/aws/ec2.rb"
|
15
|
+
Fog::AWS::EC2.reload
|
16
|
+
load "#{current_directory}/aws/simpledb.rb"
|
17
|
+
Fog::AWS::SimpleDB.reload
|
18
|
+
load "#{current_directory}/aws/s3.rb"
|
19
|
+
Fog::AWS::S3.reload
|
20
|
+
end
|
21
|
+
|
22
|
+
if Fog.mocking?
|
23
|
+
srand(Time.now.to_i)
|
24
|
+
|
25
|
+
class Mock
|
26
|
+
|
27
|
+
def self.etag
|
28
|
+
hex(32)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.key_fingerprint
|
32
|
+
fingerprint = []
|
33
|
+
20.times do
|
34
|
+
fingerprint << hex(2)
|
35
|
+
end
|
36
|
+
fingerprint.join(':')
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.instance_id
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.ip_address
|
43
|
+
ip = []
|
44
|
+
4.times do
|
45
|
+
ip << numbers(rand(3) + 1).to_i.to_s # remove leading 0
|
46
|
+
end
|
47
|
+
ip.join('.')
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.key_material
|
51
|
+
key_material = ['-----BEGIN RSA PRIVATE KEY-----']
|
52
|
+
20.times do
|
53
|
+
key_material << base64(76)
|
54
|
+
end
|
55
|
+
key_material << base64(67) + '='
|
56
|
+
key_material << '-----END RSA PRIVATE KEY-----'
|
57
|
+
key_material.join("\n")
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.owner_id
|
61
|
+
numbers(12)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.request_id
|
65
|
+
request_id = []
|
66
|
+
request_id << hex(8)
|
67
|
+
3.times do
|
68
|
+
request_id << hex(4)
|
69
|
+
end
|
70
|
+
request_id << hex(12)
|
71
|
+
request_id.join('-')
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.snapshot_id
|
75
|
+
"snap-#{hex(8)}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.volume_id
|
79
|
+
"vol-#{hex(8)}"
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def self.random_selection(characters, length)
|
85
|
+
selection = ''
|
86
|
+
length.times do
|
87
|
+
position = rand(characters.length)
|
88
|
+
selection << characters[position..position]
|
89
|
+
end
|
90
|
+
selection
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.letters(length)
|
94
|
+
random_selection(
|
95
|
+
'abcdefghijklmnopqrstuvwxyz',
|
96
|
+
length
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.numbers(length)
|
101
|
+
random_selection(
|
102
|
+
'0123456789',
|
103
|
+
length
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.hex(length)
|
108
|
+
random_selection(
|
109
|
+
'0123456789abcdef',
|
110
|
+
length
|
111
|
+
)
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.base64(length)
|
115
|
+
random_selection(
|
116
|
+
"ABCDEFGHIJKLMNOP QRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
|
117
|
+
length
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
Fog::AWS.reload
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'openssl'
|
3
|
+
require 'socket'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
require "#{File.dirname(__FILE__)}/errors"
|
7
|
+
require "#{File.dirname(__FILE__)}/response"
|
8
|
+
|
9
|
+
unless Fog.mocking?
|
10
|
+
|
11
|
+
module Fog
|
12
|
+
class Connection
|
13
|
+
|
14
|
+
def initialize(url)
|
15
|
+
@uri = URI.parse(url)
|
16
|
+
@connection = TCPSocket.open(@uri.host, @uri.port)
|
17
|
+
if @uri.scheme == 'https'
|
18
|
+
@ssl_context = OpenSSL::SSL::SSLContext.new
|
19
|
+
@ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
20
|
+
@connection = OpenSSL::SSL::SSLSocket.new(@connection, @ssl_context)
|
21
|
+
@connection.sync_close = true
|
22
|
+
@connection.connect
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def request(params)
|
27
|
+
params[:path] ||= ''
|
28
|
+
unless params[:path][0] == '/'
|
29
|
+
params[:path] = '/' + params[:path].to_s
|
30
|
+
end
|
31
|
+
if params[:query] && !params[:query].empty?
|
32
|
+
params[:path] << "?#{params[:query]}"
|
33
|
+
end
|
34
|
+
request = "#{params[:method]} #{params[:path]} HTTP/1.1\r\n"
|
35
|
+
params[:headers] ||= {}
|
36
|
+
params[:headers]['Host'] = params[:host]
|
37
|
+
if params[:body]
|
38
|
+
params[:headers]['Content-Length'] = params[:body].length
|
39
|
+
end
|
40
|
+
for key, value in params[:headers]
|
41
|
+
request << "#{key}: #{value}\r\n"
|
42
|
+
end
|
43
|
+
request << "\r\n#{params[:body]}"
|
44
|
+
@connection.write(request)
|
45
|
+
|
46
|
+
response = Fog::Response.new
|
47
|
+
response.request = params
|
48
|
+
response.status = @connection.readline[9..11].to_i
|
49
|
+
while true
|
50
|
+
data = @connection.readline.chomp!
|
51
|
+
if data == ""
|
52
|
+
break
|
53
|
+
end
|
54
|
+
header = data.split(': ')
|
55
|
+
response.headers[capitalize(header[0])] = header[1]
|
56
|
+
end
|
57
|
+
|
58
|
+
if params[:parser]
|
59
|
+
body = Nokogiri::XML::SAX::PushParser.new(params[:parser])
|
60
|
+
else
|
61
|
+
body = ''
|
62
|
+
end
|
63
|
+
|
64
|
+
unless params[:method] == 'HEAD'
|
65
|
+
if response.headers['Content-Length']
|
66
|
+
body << @connection.read(response.headers['Content-Length'].to_i)
|
67
|
+
elsif response.headers['Transfer-Encoding'] == 'chunked'
|
68
|
+
while true
|
69
|
+
# 2 == "/r/n".length
|
70
|
+
chunk_size = @connection.readline.chomp!.to_i(16) + 2
|
71
|
+
chunk = @connection.read(chunk_size)
|
72
|
+
body << chunk[0...-2]
|
73
|
+
if chunk_size == 2
|
74
|
+
break
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
if params[:parser]
|
81
|
+
body.finish
|
82
|
+
response.body = params[:parser].response
|
83
|
+
else
|
84
|
+
response.body = body
|
85
|
+
end
|
86
|
+
|
87
|
+
if params[:expects] && params[:expects] != response.status
|
88
|
+
raise(Fog::Errors.status_error(params[:expects], response.status, response))
|
89
|
+
else
|
90
|
+
response
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def capitalize(header)
|
97
|
+
words = header.split('-')
|
98
|
+
header = ''
|
99
|
+
for word in words
|
100
|
+
header << word[0..0].upcase << word[1..-1] << '-'
|
101
|
+
end
|
102
|
+
header.chop!
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
else
|
109
|
+
|
110
|
+
module Fog
|
111
|
+
class Connection
|
112
|
+
|
113
|
+
def initialize(url)
|
114
|
+
end
|
115
|
+
|
116
|
+
def request(params)
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
data/lib/fog/errors.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
module Fog
|
2
|
+
module Errors
|
3
|
+
class Continue < StandardError; end # 100
|
4
|
+
class SwitchingProtocols < StandardError; end # 101
|
5
|
+
class OK < StandardError; end # 200
|
6
|
+
class Created < StandardError; end # 201
|
7
|
+
class Accepted < StandardError; end # 202
|
8
|
+
class NonAuthoritativeInformation < StandardError; end # 203
|
9
|
+
class NoContent < StandardError; end # 204
|
10
|
+
class ResetContent < StandardError; end # 205
|
11
|
+
class PartialContent < StandardError; end # 206
|
12
|
+
class MultipleChoices < StandardError; end # 300
|
13
|
+
class MovedPermanently < StandardError; end # 301
|
14
|
+
class Found < StandardError; end # 302
|
15
|
+
class SeeOther < StandardError; end # 303
|
16
|
+
class NotModified < StandardError; end # 304
|
17
|
+
class UseProxy < StandardError; end # 305
|
18
|
+
class TemporaryRedirect < StandardError; end # 307
|
19
|
+
class BadRequest < StandardError; end # 400
|
20
|
+
class Unauthorized < StandardError; end # 401
|
21
|
+
class PaymentRequired < StandardError; end # 402
|
22
|
+
class Forbidden < StandardError; end # 403
|
23
|
+
class NotFound < StandardError; end # 404
|
24
|
+
class MethodNotAllowed < StandardError; end # 405
|
25
|
+
class NotAcceptable < StandardError; end #406
|
26
|
+
class ProxyAuthenticationRequired < StandardError; end #407
|
27
|
+
class RequestTimeout < StandardError; end # 408
|
28
|
+
class Conflict < StandardError; end # 409
|
29
|
+
class Gone < StandardError; end # 410
|
30
|
+
class LengthRequired < StandardError; end # 411
|
31
|
+
class PreconditionFailed < StandardError; end # 412
|
32
|
+
class RequestEntityTooLarge < StandardError; end # 412
|
33
|
+
class RequestURITooLong < StandardError; end # 414
|
34
|
+
class UnsupportedMediaType < StandardError; end # 415
|
35
|
+
class RequestedRangeNotSatisfiable < StandardError; end # 416
|
36
|
+
class ExpectationFailed < StandardError; end # 417
|
37
|
+
class InternalServerError < StandardError; end # 500
|
38
|
+
class NotImplemented < StandardError; end # 501
|
39
|
+
class BadGateway < StandardError; end # 502
|
40
|
+
class ServiceUnavailable < StandardError; end # 503
|
41
|
+
class GatewayTimeout < StandardError; end # 504
|
42
|
+
|
43
|
+
# Messages for nicer exceptions, from rfc2616
|
44
|
+
def self.status_error(expected, actual, response)
|
45
|
+
@errors ||= {
|
46
|
+
100 => Fog::Errors::Continue,
|
47
|
+
101 => Fog::Errors::SwitchingProtocols,
|
48
|
+
200 => Fog::Errors::OK,
|
49
|
+
201 => Fog::Errors::Created,
|
50
|
+
202 => Fog::Errors::Accepted,
|
51
|
+
203 => Fog::Errors::NonAuthoritativeInformation,
|
52
|
+
204 => Fog::Errors::NoContent,
|
53
|
+
205 => Fog::Errors::ResetContent,
|
54
|
+
206 => Fog::Errors::PartialContent,
|
55
|
+
300 => Fog::Errors::MultipleChoices,
|
56
|
+
301 => Fog::Errors::MovedPermanently,
|
57
|
+
302 => Fog::Errors::Found,
|
58
|
+
303 => Fog::Errors::SeeOther,
|
59
|
+
304 => Fog::Errors::NotModified,
|
60
|
+
305 => Fog::Errors::UseProxy,
|
61
|
+
307 => Fog::Errors::TemporaryRedirect,
|
62
|
+
400 => Fog::Errors::BadRequest,
|
63
|
+
401 => Fog::Errors::Unauthorized,
|
64
|
+
402 => Fog::Errors::PaymentRequired,
|
65
|
+
403 => Fog::Errors::Forbidden,
|
66
|
+
404 => Fog::Errors::NotFound,
|
67
|
+
405 => Fog::Errors::MethodNotAllowed,
|
68
|
+
406 => Fog::Errors::NotAcceptable,
|
69
|
+
407 => Fog::Errors::ProxyAuthenticationRequired,
|
70
|
+
408 => Fog::Errors::RequestTimeout,
|
71
|
+
409 => Fog::Errors::Conflict,
|
72
|
+
410 => Fog::Errors::Gone,
|
73
|
+
411 => Fog::Errors::LengthRequired,
|
74
|
+
412 => Fog::Errors::PreconditionFailed,
|
75
|
+
413 => Fog::Errors::RequestEntityTooLarge,
|
76
|
+
414 => Fog::Errors::RequestURITooLong,
|
77
|
+
415 => Fog::Errors::UnsupportedMediaType,
|
78
|
+
416 => Fog::Errors::RequestedRangeNotSatisfiable,
|
79
|
+
417 => Fog::Errors::ExpectationFailed,
|
80
|
+
500 => Fog::Errors::InternalServerError,
|
81
|
+
501 => Fog::Errors::NotImplemented,
|
82
|
+
502 => Fog::Errors::BadGateway,
|
83
|
+
503 => Fog::Errors::ServiceUnavailable,
|
84
|
+
504 => Fog::Errors::GatewayTimeout
|
85
|
+
}
|
86
|
+
@messages ||= {
|
87
|
+
100 => 'Continue',
|
88
|
+
101 => 'Switching Protocols',
|
89
|
+
200 => 'OK',
|
90
|
+
201 =>'Created',
|
91
|
+
202 => 'Accepted',
|
92
|
+
203 => 'Non-Authoritative Information',
|
93
|
+
204 => 'No Content',
|
94
|
+
205 => 'Reset Content',
|
95
|
+
206 => 'Partial Content',
|
96
|
+
300 => 'Multiple Choices',
|
97
|
+
301 => 'Moved Permanently',
|
98
|
+
302 => 'Found',
|
99
|
+
303 => 'See Other',
|
100
|
+
304 => 'Not Modified',
|
101
|
+
305 => 'Use Proxy',
|
102
|
+
307 => 'Temporary Redirect',
|
103
|
+
400 => 'Bad Request',
|
104
|
+
401 => 'Unauthorized',
|
105
|
+
402 => 'Payment Required',
|
106
|
+
403 => 'Forbidden',
|
107
|
+
404 => 'Not Found',
|
108
|
+
405 => 'Method Not Allowed',
|
109
|
+
406 => 'Not Acceptable',
|
110
|
+
407 => 'Proxy Authentication Required',
|
111
|
+
408 => 'Request Timeout',
|
112
|
+
409 => 'Conflict',
|
113
|
+
410 => 'Gone',
|
114
|
+
411 => 'Length Required',
|
115
|
+
412 => 'Precondition Failed',
|
116
|
+
413 => 'Request Entity Too Large',
|
117
|
+
414 => 'Request-URI Too Long',
|
118
|
+
415 => 'Unsupported Media Type',
|
119
|
+
416 => 'Requested Range Not Satisfiable',
|
120
|
+
417 => 'Expectation Failed',
|
121
|
+
500 => 'Internal Server Error',
|
122
|
+
501 => 'Not Implemented',
|
123
|
+
502 => 'Bad Gateway',
|
124
|
+
503 => 'Service Unavailable',
|
125
|
+
504 => 'Gateway Timeout'
|
126
|
+
}
|
127
|
+
@errors[actual].new("Expected(#{expected} #{@messages[expected]}) <=> Actual(#{actual} #{@messages[actual]}) #{response.inspect}")
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|