awscosts 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -4
- data/awscosts.gemspec +1 -0
- data/fixtures/vcr_cassettes/AWSCosts_EBS.yml +17 -496
- data/fixtures/vcr_cassettes/AWSCosts_EC2OnDemand/EC2_type_of_linux.yml +63 -4583
- data/fixtures/vcr_cassettes/AWSCosts_EC2OnDemand/EC2_type_of_rhel.yml +63 -4585
- data/fixtures/vcr_cassettes/AWSCosts_EC2OnDemand/EC2_type_of_sles.yml +63 -4585
- data/fixtures/vcr_cassettes/AWSCosts_EC2OnDemand/EC2_type_of_windows.yml +63 -4583
- data/fixtures/vcr_cassettes/AWSCosts_EC2OnDemand/EC2_type_of_windows_with_sql.yml +63 -3535
- data/fixtures/vcr_cassettes/AWSCosts_EC2OnDemand/EC2_type_of_windows_with_sql_web.yml +63 -4060
- data/fixtures/vcr_cassettes/AWSCosts_EC2ReservedInstances/Reserved_instances/in_the_us-east-1_region/EC2_type_of_linux.yml +16 -5970
- data/fixtures/vcr_cassettes/AWSCosts_EC2ReservedInstances/Reserved_instances/in_the_us-east-1_region/EC2_type_of_rhel.yml +16 -5970
- data/fixtures/vcr_cassettes/AWSCosts_EC2ReservedInstances/Reserved_instances/in_the_us-east-1_region/EC2_type_of_sles.yml +16 -5970
- data/fixtures/vcr_cassettes/AWSCosts_EC2ReservedInstances/Reserved_instances/in_the_us-east-1_region/EC2_type_of_windows.yml +16 -5970
- data/fixtures/vcr_cassettes/AWSCosts_EC2ReservedInstances/Reserved_instances/in_the_us-east-1_region/EC2_type_of_windows_with_sql.yml +16 -5970
- data/fixtures/vcr_cassettes/AWSCosts_EC2ReservedInstances/Reserved_instances/in_the_us-east-1_region/EC2_type_of_windows_with_sql_web.yml +16 -5970
- data/fixtures/vcr_cassettes/AWSCosts_ELB.yml +17 -283
- data/fixtures/vcr_cassettes/AWSCosts_EMR.yml +12 -12
- data/fixtures/vcr_cassettes/AWSCosts_ElasticIPs.yml +17 -445
- data/fixtures/vcr_cassettes/AWSCosts_S3DataTransfer.yml +19 -925
- data/fixtures/vcr_cassettes/AWSCosts_S3Requests.yml +19 -454
- data/fixtures/vcr_cassettes/AWSCosts_S3Storage.yml +19 -1396
- data/lib/awscosts/cache.rb +26 -4
- data/lib/awscosts/ec2.rb +26 -5
- data/lib/awscosts/ec2_ebs.rb +3 -14
- data/lib/awscosts/ec2_ebs_optimized.rb +31 -0
- data/lib/awscosts/ec2_elastic_ips.rb +4 -4
- data/lib/awscosts/ec2_elb.rb +4 -4
- data/lib/awscosts/ec2_on_demand.rb +24 -19
- data/lib/awscosts/ec2_reserved_instances.rb +7 -8
- data/lib/awscosts/emr.rb +1 -2
- data/lib/awscosts/region.rb +12 -10
- data/lib/awscosts/s3.rb +4 -3
- data/lib/awscosts/s3_data_transfer.rb +7 -7
- data/lib/awscosts/s3_requests.rb +5 -6
- data/lib/awscosts/s3_storage.rb +7 -7
- data/lib/awscosts/version.rb +1 -1
- data/spec/awscosts/ec2_ebs_spec.rb +17 -33
- data/spec/awscosts/ec2_elastic_ips_spec.rb +2 -0
- data/spec/awscosts/ec2_reserved_instances_spec.rb +3 -0
- metadata +17 -2
data/lib/awscosts/cache.rb
CHANGED
@@ -1,15 +1,28 @@
|
|
1
1
|
require 'httparty'
|
2
|
-
require '
|
2
|
+
require 'oj'
|
3
3
|
|
4
4
|
module AWSCosts::Cache
|
5
5
|
extend self
|
6
6
|
|
7
7
|
BASE_URI = "http://aws.amazon.com"
|
8
|
+
BASE_JSONP_URI = "http://a0.awsstatic.com"
|
8
9
|
|
9
10
|
def get uri, base_uri = BASE_URI, &block
|
10
|
-
cache[uri] ||=
|
11
|
-
|
12
|
-
|
11
|
+
cache["#{base_uri}#{uri}"] ||= Oj::load(HTTParty.get("#{base_uri}#{uri}").body)
|
12
|
+
yield cache["#{base_uri}#{uri}"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_jsonp uri, base_uri = BASE_JSONP_URI, &block
|
16
|
+
attempts = 0
|
17
|
+
cache["#{base_uri}#{uri}"] ||= begin
|
18
|
+
extract_json_from_callback(HTTParty.get("#{base_uri}#{uri}").body)
|
19
|
+
rescue NoMethodError
|
20
|
+
attempts += 1
|
21
|
+
retry if attempts < 5
|
22
|
+
raise "Failed to retrieve or parse data for #{base_uri}#{uri}"
|
23
|
+
end
|
24
|
+
|
25
|
+
yield cache["#{base_uri}#{uri}"]
|
13
26
|
end
|
14
27
|
|
15
28
|
private
|
@@ -17,6 +30,15 @@ module AWSCosts::Cache
|
|
17
30
|
@cache ||= {}
|
18
31
|
end
|
19
32
|
|
33
|
+
def extract_json_from_callback body
|
34
|
+
body.match /^.*callback\((\{.*\})\);$/
|
35
|
+
body = $1
|
36
|
+
|
37
|
+
# Handle "json" with keys that are not quoted
|
38
|
+
# When we get {foo: "1"} instead of {"foo": "1"}
|
39
|
+
# http://stackoverflow.com/questions/2060356/parsing-json-without-quoted-keys
|
40
|
+
Oj::load(body.gsub(/(\w+)\s*:/, '"\1":'))
|
41
|
+
end
|
20
42
|
end
|
21
43
|
|
22
44
|
|
data/lib/awscosts/ec2.rb
CHANGED
@@ -2,6 +2,7 @@ require 'awscosts/ec2_on_demand'
|
|
2
2
|
require 'awscosts/ec2_reserved_instances'
|
3
3
|
require 'awscosts/ec2_elb'
|
4
4
|
require 'awscosts/ec2_ebs'
|
5
|
+
require 'awscosts/ec2_ebs_optimized'
|
5
6
|
require 'awscosts/ec2_elastic_ips'
|
6
7
|
|
7
8
|
class AWSCosts::EC2
|
@@ -11,28 +12,48 @@ class AWSCosts::EC2
|
|
11
12
|
TYPES = { windows: 'mswin', linux: 'linux', windows_with_sql: 'mswinSQL',
|
12
13
|
windows_with_sql_web: 'mswinSQLWeb', rhel: 'rhel', sles: 'sles' }
|
13
14
|
|
15
|
+
REGION_MAPPING = {
|
16
|
+
'us-east-1' => "us-east",
|
17
|
+
'us-west-1' => "us-west",
|
18
|
+
'us-west-2' => "us-west-2",
|
19
|
+
'eu-west-1' => "eu-ireland",
|
20
|
+
'eu-central-1' => "eu-central-1",
|
21
|
+
'ap-southeast-1' => "apac-sin",
|
22
|
+
'ap-southeast-2' =>"apac-syd",
|
23
|
+
'ap-northeast-1' =>"apac-tokyo",
|
24
|
+
'sa-east-1' => "sa-east-1"
|
25
|
+
}
|
26
|
+
|
14
27
|
def initialize region
|
15
28
|
@region = region
|
16
29
|
end
|
17
30
|
|
18
31
|
def on_demand(type)
|
32
|
+
raise ArgumentError.new("Unknown platform: #{type}") if TYPES[type].nil?
|
19
33
|
AWSCosts::EC2OnDemand.fetch(TYPES[type], self.region.name)
|
20
34
|
end
|
21
35
|
|
22
|
-
def reserved(type, utilisation= :light)
|
23
|
-
|
36
|
+
def reserved(type, utilisation = :light)
|
37
|
+
r = self.region.name
|
38
|
+
r = 'us-east' if r == 'us-east-1'
|
39
|
+
raise ArgumentError.new("Unknown platform: #{type}") if TYPES[type].nil?
|
40
|
+
AWSCosts::EC2ReservedInstances.fetch(TYPES[type], utilisation, r)
|
24
41
|
end
|
25
42
|
|
26
43
|
def elb
|
27
|
-
AWSCosts::ELB.fetch(self.region.
|
44
|
+
AWSCosts::ELB.fetch(REGION_MAPPING[self.region.name])
|
28
45
|
end
|
29
46
|
|
30
47
|
def ebs
|
31
|
-
AWSCosts::EBS.fetch(self.region.
|
48
|
+
AWSCosts::EBS.fetch(REGION_MAPPING[self.region.name])
|
49
|
+
end
|
50
|
+
|
51
|
+
def ebs_optimized
|
52
|
+
AWSCosts::EBSOptimized.fetch(REGION_MAPPING[self.region.name])
|
32
53
|
end
|
33
54
|
|
34
55
|
def elastic_ips
|
35
|
-
AWSCosts::ElasticIPs.fetch(self.region.
|
56
|
+
AWSCosts::ElasticIPs.fetch(REGION_MAPPING[self.region.name])
|
36
57
|
end
|
37
58
|
end
|
38
59
|
|
data/lib/awscosts/ec2_ebs.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
require 'httparty'
|
2
|
-
require 'json'
|
3
2
|
|
4
3
|
class AWSCosts::EBS
|
5
4
|
|
6
|
-
TYPES = { 'ebsVols' => :standard, 'ebsPIOPSVols' => :provisioned_iops,
|
7
|
-
'ebsSnapsToS3' => :snapshots_to_s3 }
|
8
|
-
|
9
5
|
def initialize data
|
10
6
|
@data= data
|
11
7
|
end
|
@@ -15,17 +11,10 @@ class AWSCosts::EBS
|
|
15
11
|
end
|
16
12
|
|
17
13
|
def self.fetch region
|
18
|
-
transformed= AWSCosts::Cache.
|
14
|
+
transformed = AWSCosts::Cache.get_jsonp('/pricing/1/ebs/pricing-ebs.min.js') do |data|
|
19
15
|
result = {}
|
20
|
-
data['config']['regions'].each do |
|
21
|
-
|
22
|
-
region['types'].each do |type|
|
23
|
-
container[TYPES[type['name']]] = {}
|
24
|
-
type['values'].each do |value|
|
25
|
-
container[TYPES[type['name']]][value['rate']] = value['prices']['USD'].to_f
|
26
|
-
end
|
27
|
-
end
|
28
|
-
result[region['region']] = container
|
16
|
+
data['config']['regions'].each do |r|
|
17
|
+
result[r['region']] = r['types']
|
29
18
|
end
|
30
19
|
result
|
31
20
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
class AWSCosts::EBSOptimized
|
4
|
+
|
5
|
+
def initialize data
|
6
|
+
@data = data
|
7
|
+
end
|
8
|
+
|
9
|
+
def price type = nil
|
10
|
+
type.nil? ? @data : @data[type]
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.fetch region
|
14
|
+
transformed = AWSCosts::Cache.get_jsonp('/pricing/1/ec2/pricing-ebs-optimized-instances.min.js') do |data|
|
15
|
+
result = {}
|
16
|
+
data['config']['regions'].each do |r|
|
17
|
+
container = {}
|
18
|
+
r['instanceTypes'].each do |type|
|
19
|
+
type['sizes'].each do |size|
|
20
|
+
container[size['size']] = size['valueColumns'].select{|v| v['name'] == 'ebsOptimized'}.first['prices']['USD'].to_f
|
21
|
+
end
|
22
|
+
end
|
23
|
+
result[r['region']] = container
|
24
|
+
end
|
25
|
+
result
|
26
|
+
end
|
27
|
+
self.new(transformed[region])
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
@@ -25,16 +25,16 @@ class AWSCosts::ElasticIPs
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def self.fetch region
|
28
|
-
transformed= AWSCosts::Cache.
|
28
|
+
transformed = AWSCosts::Cache.get_jsonp('/pricing/1/ec2/pricing-elastic-ips.min.js') do |data|
|
29
29
|
result = {}
|
30
|
-
data['config']['regions'].each do |
|
30
|
+
data['config']['regions'].each do |r|
|
31
31
|
container = {}
|
32
|
-
|
32
|
+
r['types'].each do |type|
|
33
33
|
type['values'].each do |value|
|
34
34
|
container[value['rate']] = value['prices']['USD'].to_f
|
35
35
|
end
|
36
36
|
end
|
37
|
-
result[
|
37
|
+
result[r['region']] = container
|
38
38
|
end
|
39
39
|
result
|
40
40
|
end
|
data/lib/awscosts/ec2_elb.rb
CHANGED
@@ -13,16 +13,16 @@ class AWSCosts::ELB
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.fetch region
|
16
|
-
transformed= AWSCosts::Cache.
|
16
|
+
transformed = AWSCosts::Cache.get_jsonp('/pricing/1/ec2/pricing-elb.min.js') do |data|
|
17
17
|
result = {}
|
18
|
-
data['config']['regions'].each do |
|
18
|
+
data['config']['regions'].each do |r|
|
19
19
|
container = {}
|
20
|
-
|
20
|
+
r['types'].each do |type|
|
21
21
|
type['values'].each do |value|
|
22
22
|
container[value['rate']] = value['prices']['USD'].to_f
|
23
23
|
end
|
24
24
|
end
|
25
|
-
result[
|
25
|
+
result[r['region']] = container
|
26
26
|
end
|
27
27
|
result
|
28
28
|
end
|
@@ -22,7 +22,7 @@ class AWSCosts::EC2OnDemand
|
|
22
22
|
'hiIoODI.xxxxl' => 'hi1.4xlarge' }
|
23
23
|
|
24
24
|
def initialize data
|
25
|
-
@data= data
|
25
|
+
@data = data
|
26
26
|
end
|
27
27
|
|
28
28
|
def price size=nil
|
@@ -30,30 +30,35 @@ class AWSCosts::EC2OnDemand
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def self.fetch type, region
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
platform_cost
|
43
|
-
|
33
|
+
result = {}
|
34
|
+
['/pricing/1/ec2/%s-od.min.js', '/pricing/1/ec2/previous-generation/%s-od.min.js'].each do |uri|
|
35
|
+
AWSCosts::Cache.get_jsonp(uri % type) do |data|
|
36
|
+
data['config']['regions'].each do |r|
|
37
|
+
result[r['region']] ||= {}
|
38
|
+
platforms = result[r['region']]
|
39
|
+
r['instanceTypes'].each do |instance_type|
|
40
|
+
instance_type['sizes'].each do |instance_size|
|
41
|
+
size = instance_size['size']
|
42
|
+
platform_cost = Hash.new({})
|
43
|
+
instance_size['valueColumns'].each do |value|
|
44
|
+
# Don't return 0.0 for "N/A" since that is misleading
|
45
|
+
platform_cost[value['name']] = value['prices']['USD'] == 'N/A' ? nil : value['prices']['USD'].to_f
|
46
|
+
end
|
44
47
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
+
platform_cost.each_pair do |p,v|
|
49
|
+
platforms[p] = {} unless platforms.key?(p)
|
50
|
+
platforms[p][size] = v
|
51
|
+
end
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
51
|
-
result[region['region']] = platforms
|
52
55
|
end
|
53
|
-
result
|
54
56
|
end
|
55
|
-
|
56
|
-
|
57
|
+
|
58
|
+
raise "No result for region #{region} while fetching EC2 OnDemand Pricing" if result[region].nil?
|
59
|
+
raise "No result for #{type} in region #{region} while fetching EC2 OnDemand Pricing" if result[region][type].nil?
|
60
|
+
|
61
|
+
self.new(result[region][type])
|
57
62
|
end
|
58
63
|
|
59
64
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'httparty'
|
2
|
-
require 'json'
|
3
2
|
class AWSCosts::EC2ReservedInstances
|
4
3
|
|
5
4
|
TERMS = { one_year: 'yrTerm1', three_year: 'yrTerm3' }
|
@@ -42,19 +41,19 @@ class AWSCosts::EC2ReservedInstances
|
|
42
41
|
end
|
43
42
|
end
|
44
43
|
|
45
|
-
|
46
44
|
def self.fetch type, utilisation, region
|
47
|
-
transformed= AWSCosts::Cache.
|
45
|
+
transformed = AWSCosts::Cache.get_jsonp("/pricing/1/ec2/#{type}-ri-#{utilisation}.min.js") do |data|
|
48
46
|
result = {}
|
49
|
-
data['config']['regions'].each do |
|
47
|
+
data['config']['regions'].each do |r|
|
50
48
|
platforms = {}
|
51
|
-
|
49
|
+
r['instanceTypes'].each do |instance_type|
|
52
50
|
instance_type['sizes'].each do |instance_size|
|
53
51
|
size = instance_size['size']
|
54
52
|
platform_cost = Hash.new({})
|
55
53
|
|
56
54
|
instance_size['valueColumns'].each do |value|
|
57
|
-
|
55
|
+
# Don't return 0.0 for "N/A" since that is misleading
|
56
|
+
platform_cost[value['name']] = value['prices']['USD'] == 'N/A' ? nil : value['prices']['USD'].to_f
|
58
57
|
end
|
59
58
|
|
60
59
|
platform_cost.each_pair do |p,v|
|
@@ -63,11 +62,11 @@ class AWSCosts::EC2ReservedInstances
|
|
63
62
|
end
|
64
63
|
end
|
65
64
|
end
|
66
|
-
result[
|
65
|
+
result[r['region']] = platforms
|
67
66
|
end
|
68
67
|
result
|
69
68
|
end
|
70
|
-
|
69
|
+
self.new(transformed[region])
|
71
70
|
end
|
72
71
|
|
73
72
|
end
|
data/lib/awscosts/emr.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'httparty'
|
2
|
-
require 'json'
|
3
2
|
|
4
3
|
class AWSCosts::EMR
|
5
4
|
|
@@ -45,7 +44,7 @@ class AWSCosts::EMR
|
|
45
44
|
end
|
46
45
|
platform_cost.each_pair do |p,v|
|
47
46
|
platforms[p] = {} unless platforms.key?(p)
|
48
|
-
platforms[p][
|
47
|
+
platforms[p][size] = v
|
49
48
|
end
|
50
49
|
end
|
51
50
|
end
|
data/lib/awscosts/region.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
|
2
2
|
class AWSCosts::Region
|
3
3
|
|
4
|
-
attr_reader :name, :full_name, :price_mapping
|
4
|
+
attr_reader :name, :full_name, :price_mapping, :emr_mapping
|
5
5
|
|
6
6
|
SUPPORTED = {
|
7
|
-
'us-east-1' => { :full_name => 'US (Northern Virginia)', :price_mapping => 'us-east' },
|
8
|
-
'us-west-1' => { :full_name => 'US (Northern California)', :price_mapping => 'us-west' },
|
9
|
-
'us-west-2' => { :full_name => 'US (Oregon)', :price_mapping => 'us-west-2' },
|
10
|
-
'eu-west-1' => { :full_name => 'EU (Ireland)', :price_mapping => 'eu-ireland' },
|
11
|
-
'
|
12
|
-
'ap-southeast-
|
13
|
-
'ap-
|
14
|
-
'
|
7
|
+
'us-east-1' => { :full_name => 'US (Northern Virginia)', :price_mapping => 'us-east-1', :emr_mapping => 'us-east' },
|
8
|
+
'us-west-1' => { :full_name => 'US (Northern California)', :price_mapping => 'us-west-1', :emr_mapping => 'us-west' },
|
9
|
+
'us-west-2' => { :full_name => 'US (Oregon)', :price_mapping => 'us-west-2', :emr_mapping => 'us-west-2' },
|
10
|
+
'eu-west-1' => { :full_name => 'EU (Ireland)', :price_mapping => 'eu-west-1', :emr_mapping => 'eu-ireland' },
|
11
|
+
'eu-central-1' => { :full_name => 'EU (Frankfurt)' },
|
12
|
+
'ap-southeast-1' => { :full_name => 'Asia Pacific (Singapore)', :price_mapping => 'ap-southeast-1', :emr_mapping => 'apac-sin' },
|
13
|
+
'ap-southeast-2' => { :full_name => 'Asia Pacific (Sydney)', :price_mapping => 'ap-southeast-2', :emr_mapping => 'apac-syd' },
|
14
|
+
'ap-northeast-1' => { :full_name => 'Asia Pacific (Tokyo)', :price_mapping => 'ap-northeast-1', :emr_mapping => 'apac-tokyo' },
|
15
|
+
'sa-east-1' => { :full_name => 'South America (Sao Paulo)', :price_mapping => 'sa-east-1', :emr_mapping => 'sa-east-1' }
|
15
16
|
}
|
16
17
|
|
17
18
|
def self.find name
|
@@ -24,7 +25,7 @@ class AWSCosts::Region
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def emr
|
27
|
-
AWSCosts::EMR.fetch(self.
|
28
|
+
AWSCosts::EMR.fetch(self.emr_mapping)
|
28
29
|
end
|
29
30
|
|
30
31
|
def s3
|
@@ -36,6 +37,7 @@ class AWSCosts::Region
|
|
36
37
|
@name = name
|
37
38
|
@full_name = SUPPORTED[name][:full_name]
|
38
39
|
@price_mapping = SUPPORTED[name][:price_mapping]
|
40
|
+
@emr_mapping = SUPPORTED[name][:emr_mapping]
|
39
41
|
end
|
40
42
|
|
41
43
|
end
|
data/lib/awscosts/s3.rb
CHANGED
@@ -11,6 +11,7 @@ class AWSCosts::S3
|
|
11
11
|
'us-west-1' => "us-west-1",
|
12
12
|
'us-west-2' => "us-west-2",
|
13
13
|
'eu-west-1' => "eu-west-1",
|
14
|
+
'eu-central-1' => "eu-central-1",
|
14
15
|
'ap-southeast-1' => "ap-southeast-1",
|
15
16
|
'ap-southeast-2' =>"ap-southeast-2",
|
16
17
|
'ap-northeast-1' =>"ap-northeast-1",
|
@@ -22,15 +23,15 @@ class AWSCosts::S3
|
|
22
23
|
end
|
23
24
|
|
24
25
|
def storage
|
25
|
-
AWSCosts::S3Storage.fetch(
|
26
|
+
AWSCosts::S3Storage.fetch(@region)
|
26
27
|
end
|
27
28
|
|
28
29
|
def data_transfer
|
29
|
-
AWSCosts::S3DataTransfer.fetch(
|
30
|
+
AWSCosts::S3DataTransfer.fetch(@region)
|
30
31
|
end
|
31
32
|
|
32
33
|
def requests
|
33
|
-
AWSCosts::S3Requests.fetch(
|
34
|
+
AWSCosts::S3Requests.fetch(@region)
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
@@ -1,12 +1,11 @@
|
|
1
1
|
require 'httparty'
|
2
|
-
require 'json'
|
3
2
|
|
4
3
|
class AWSCosts::S3DataTransfer
|
5
4
|
|
6
5
|
TYPES = %w{dataXferInS3, dataXferOutS3CrossRegion, dataXferOutS3}
|
7
6
|
|
8
7
|
def initialize data
|
9
|
-
@data= data
|
8
|
+
@data = data
|
10
9
|
end
|
11
10
|
|
12
11
|
def price type = nil
|
@@ -14,17 +13,18 @@ class AWSCosts::S3DataTransfer
|
|
14
13
|
end
|
15
14
|
|
16
15
|
def self.fetch region
|
17
|
-
transformed= AWSCosts::Cache.
|
16
|
+
transformed = AWSCosts::Cache.get_jsonp("/pricing/1/s3/pricing-data-transfer-s3.min.js") do |data|
|
18
17
|
result = {}
|
19
|
-
data['config']['regions'].each do |
|
18
|
+
data['config']['regions'].each do |r|
|
20
19
|
types = {}
|
21
|
-
|
20
|
+
r['types'].each do |type|
|
22
21
|
types[type['name']] = {}
|
23
22
|
type['tiers'].each do |tier|
|
24
|
-
|
23
|
+
# Don't return 0.0 for "contactus" since that is misleading
|
24
|
+
types[type['name']][tier['name']] = tier['prices']['USD'] == 'contactus' ? nil : tier['prices']['USD'].to_f
|
25
25
|
end
|
26
26
|
end
|
27
|
-
result[
|
27
|
+
result[r['region']] = types
|
28
28
|
end
|
29
29
|
result
|
30
30
|
end
|