aws-rikanjo 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,113 @@
1
+ require 'optparse'
2
+ require 'aws/rikanjo/base'
3
+
4
+ module Aws
5
+ module RiKanjoo
6
+ class CLI
7
+
8
+ def initialize
9
+ @options = {}
10
+ @optparse = nil
11
+ @cost = nil
12
+ end
13
+
14
+ def start
15
+ parse
16
+ rikanjo
17
+ output
18
+ end
19
+
20
+ def parse
21
+ optparse = OptionParser.new do |opts|
22
+ opts.banner = 'Usage: rikanjo ec2/rds [options]'
23
+
24
+ # subcommand
25
+ mode = ARGV.shift
26
+ if mode == 'ec2'
27
+ elsif mode == 'rds'
28
+ opts.on('--multiaz', 'enable multi-az') do |value|
29
+ @options[:multiaz] = value
30
+ end
31
+ else
32
+ $stderr.puts "no such subcommand: #{mode}"
33
+ puts opts
34
+ exit 1
35
+ end
36
+ @options[:mode] = mode
37
+
38
+ region_values = %w(us-east-1 us-west-1 us-west-2 eu-west-1 ap-southeast-1 ap-northeast-1 ap-southeast-2 sa-east-1 )
39
+ opts.on('-r', '--region=VALUE', region_values, "specify aws-region (#{region_values.join('/')})") do |value|
40
+ @options[:region] = value
41
+ end
42
+
43
+ opts.on('-t', '--instance_type=VALUE', 'specify ec2-instance-type') do |value|
44
+ @options[:instance_type] = value
45
+ end
46
+
47
+ ri_util_values = %w(light medium heavy)
48
+ opts.on('-u', '--ri_util=VALUE', ri_util_values, "specify ri-util (#{ri_util_values.join('/')})") do |value|
49
+ @options[:ri_util] = value
50
+ end
51
+
52
+ opts.on('-j', '--output_json', "specify output_json flg") do |value|
53
+ @options[:output_json] = value
54
+ end
55
+
56
+ opts.on('-h', '--help') do
57
+ puts opts
58
+ exit
59
+ end
60
+ end
61
+
62
+ # validation
63
+ begin
64
+ optparse.parse!
65
+ require_args = [:region, :instance_type, :ri_util]
66
+ error_args = require_args.select { |param| @options[param].nil? }
67
+ unless error_args.empty?
68
+ puts "require arguments: #{error_args.join(', ')}"
69
+ puts
70
+ puts optparse
71
+ exit
72
+ end
73
+ rescue
74
+ puts $!.to_s
75
+ puts
76
+ puts optparse
77
+ exit
78
+ end
79
+ end
80
+
81
+ def rikanjo
82
+ # rikanjo
83
+ a = Aws::RiKanjoo::Base.new(
84
+ mode = @options[:mode],
85
+ region = @options[:region],
86
+ instance_type = @options[:instance_type],
87
+ ri_util = @options[:ri_util],
88
+ multiaz = @options[:multiaz],
89
+ )
90
+ @cost = a.total_cost_year
91
+ end
92
+
93
+ def output
94
+ if @options[:output_json]
95
+ output_json()
96
+ else
97
+ output_text()
98
+ end
99
+ end
100
+
101
+ def output_json
102
+ puts @cost.to_json
103
+ end
104
+
105
+ def output_text
106
+ @cost.keys.each do |key|
107
+ puts "#{key}: #{@cost[key]}"
108
+ end
109
+ end
110
+
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,117 @@
1
+ require 'yajl'
2
+
3
+ module Aws
4
+ module RiKanjoo
5
+ class Ec2
6
+ attr_reader :region, :instance_type, :ri_util
7
+
8
+ def initialize(region, instance_type, ri_util)
9
+ @region = region
10
+ @instance_type = instance_type
11
+ @ri_util = ri_util
12
+ @os = 'linux'
13
+ @current_price_url = 'http://a0.awsstatic.com/pricing/1/ec2'
14
+ @previous_price_url = 'http://a0.awsstatic.com/pricing/1/ec2/previous-generation'
15
+ end
16
+
17
+ def om_price_from_contents(contents)
18
+ region = convert_region(@region)
19
+
20
+ # parse
21
+ json = parse_contents(contents)
22
+
23
+ # select 'region' and 'instance_type'
24
+ json['config']['regions'].each do |r|
25
+ # r = {"region"=>"us-east", "instanceTypes"=>[{"type"=>"generalCurrentGen", ...
26
+ next unless r['region'] == region
27
+ r['instanceTypes'].each do |type|
28
+ # type = {"type"=>"generalCurrentGen", "sizes"=>[{"size"=>"m3.medium", "vCPU"=>"1" ...
29
+ type['sizes'].each do |i|
30
+ next unless i['size'] == @instance_type
31
+
32
+ return { hr_price: i['valueColumns'][0]['prices']['USD'] }
33
+ end
34
+ end
35
+ end
36
+
37
+ abort("[ec2][#{region}][#{@instance_type}] Not found om-price?")
38
+ end
39
+
40
+ def ri_price_from_contents(contents)
41
+ region = clean_region(@region)
42
+
43
+ # parse
44
+ json = parse_contents(contents)
45
+
46
+ ri_info = nil
47
+
48
+ json['config']['regions'].each do |r|
49
+ next unless r['region'] == region
50
+
51
+ r['instanceTypes'].each do |type|
52
+ type['sizes'].each do |i|
53
+ next unless i['size'] == @instance_type
54
+
55
+ ri_info = ri_info ||= {}
56
+ i['valueColumns'].each do |y|
57
+ case y['name']
58
+ when 'yrTerm1'
59
+ ri_info[@ri_util] = { upfront: y['prices']['USD'] }
60
+ when 'yrTerm1Hourly'
61
+ ri_info[@ri_util].store(:hr_price, y['prices']['USD'])
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ abort("[ec2][#{region}][#{@instance_type}] Not found ri-price?") unless ri_info
69
+
70
+ return ri_info
71
+ end
72
+
73
+ def price_url
74
+ return (self.previous_generation_type) ? @previous_price_url : @current_price_url
75
+ end
76
+
77
+ def om_price_file
78
+ return "#{@os}-od.min.js"
79
+ end
80
+
81
+ def ri_price_file
82
+ return (self.previous_generation_type) ? "#{@ri_util}_#{@os}.min.js" : "#{@os}-ri-#{@ri_util}.min.js"
83
+ end
84
+
85
+ def previous_generation_type
86
+ case @instance_type
87
+ when /^(c1|m2|cc2\.8xlarge|cr1\.8xlarge|hi1\.4xlarge|cg1\.4xlarge)/ then true
88
+ when /^m1/ then (@instance_type == 'm1.small') ? false : true
89
+ else false
90
+ end
91
+ end
92
+
93
+ def parse_contents(data)
94
+ data = data.gsub("/*\n * This file is intended for use only on aws.amazon.com. We do not guarantee its availability or accuracy.\n *\n * Copyright 2014 Amazon.com, Inc. or its affiliates. All rights reserved.\n */\ncallback({",'{').gsub("\);", '').gsub(/([a-zA-Z]+):/, '"\1":')
95
+ return Yajl::Parser.parse(data)
96
+ end
97
+
98
+ def convert_region(region)
99
+ # not same om region
100
+ case region
101
+ when 'us-east-1' then 'us-east'
102
+ when 'us-west-1' then 'us-west'
103
+ when 'us-west-2' then 'us-west-2'
104
+ when 'eu-west-1' then 'eu-ireland'
105
+ when 'ap-southeast-1' then 'apac-sin'
106
+ when 'ap-northeast-1' then 'apac-tokyo'
107
+ when 'ap-southeast-2' then 'apac-syd'
108
+ when 'sa-east-1' then 'sa-east-1'
109
+ end
110
+ end
111
+
112
+ def clean_region(region)
113
+ return region.gsub(/^us-east-1$/, 'us-east')
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,120 @@
1
+ module Aws
2
+ module RiKanjoo
3
+ class Rds
4
+ attr_reader :region, :instance_type, :ri_util
5
+
6
+ def initialize(region, instance_type, ri_util, multiaz)
7
+ @region = region
8
+ @instance_type = "db.#{instance_type}"
9
+ @ri_util = ri_util
10
+ @rdbms = 'mysql'
11
+ @current_price_url = "http://a0.awsstatic.com/pricing/1/rds/#{@rdbms}"
12
+ @previous_price_url = "http://a0.awsstatic.com/pricing/1/rds/#{@rdbms}/previous-generation"
13
+ @multiaz = multiaz
14
+ end
15
+
16
+ def om_price_from_contents(contents)
17
+ region = convert_region(@region)
18
+
19
+ # parse
20
+ json = parse_contents(contents)
21
+
22
+ # select 'region' and 'instance_type'
23
+ json['config']['regions'].each do |r|
24
+ # r = {"region"=>"us-east", "instanceTypes"=>[{"type"=>"generalCurrentGen", ...
25
+ next unless r['region'] == region
26
+ r['types'].each do |type|
27
+ # type = {"type"=>"generalCurrentGen", "sizes"=>[{"size"=>"m3.medium", "vCPU"=>"1" ...
28
+ type['tiers'].each do |i|
29
+ next unless i['name'] == @instance_type
30
+
31
+ return { hr_price: i['prices']['USD'] }
32
+ end
33
+ end
34
+ end
35
+
36
+ abort("[rds][#{region}][#{@instance_type}] Not found om-price?")
37
+ end
38
+
39
+ def ri_price_from_contents(contents)
40
+ region = convert_region(@region)
41
+ mtype = (@multiaz) ? 'Multi-AZ' : 'Single-AZ'
42
+
43
+ # parse
44
+ json = parse_contents(contents)
45
+
46
+ ri_info = nil
47
+
48
+ json['config']['regions'].each do |r|
49
+ next unless r['region'] == region
50
+
51
+ r['instanceTypes'].each do |type|
52
+ next unless type['type'] =~ /#{mtype}/
53
+
54
+ type['tiers'].each do |i|
55
+ next unless i['size'] == @instance_type
56
+
57
+ ri_info = ri_info ||= {}
58
+ i['valueColumns'].each do |y|
59
+ # beauty
60
+ y['name'].gsub!(/^year/, 'yr')
61
+ y['prices']['USD'].gsub!(/,/, '')
62
+
63
+ case y['name']
64
+ when 'yrTerm1'
65
+ ri_info[@ri_util] = { upfront: y['prices']['USD'] }
66
+ when 'yrTerm1Hourly'
67
+ ri_info[@ri_util].store(:hr_price, y['prices']['USD'])
68
+ end
69
+ end
70
+
71
+ end
72
+ end
73
+ end
74
+
75
+ abort("[rds][#{region}][#{@instance_type}] Not found ri-price?") unless ri_info
76
+
77
+ return ri_info
78
+ end
79
+
80
+ def price_url
81
+ return (self.previous_generation_type) ? @previous_price_url : @current_price_url
82
+ end
83
+
84
+ def om_price_file
85
+ return (@multiaz) ? "pricing-multiAZ-deployments.min.js" : "pricing-standard-deployments.min.js"
86
+ end
87
+
88
+ def ri_price_file
89
+ return "pricing-#{@ri_util}-utilization-reserved-instances.min.js"
90
+ end
91
+
92
+ def previous_generation_type
93
+ case @instance_type
94
+ when /^db.(c1|m2|cc2\.8xlarge|cr1\.8xlarge|hi1\.4xlarge|cg1\.4xlarge)/ then true
95
+ when /^db.m1/ then (@instance_type == 'db.m1.small') ? false : true
96
+ else false
97
+ end
98
+ end
99
+
100
+ def parse_contents(data)
101
+ data = data.gsub("/*\n * This file is intended for use only on aws.amazon.com. We do not guarantee its availability or accuracy.\n *\n * Copyright 2014 Amazon.com, Inc. or its affiliates. All rights reserved.\n */\ncallback({",'{').gsub("\);", '').gsub(/([a-zA-Z]+):/, '"\1":')
102
+ return Yajl::Parser.parse(data)
103
+ end
104
+
105
+ def convert_region(region)
106
+ # not same om region
107
+ case region
108
+ when 'us-east-1' then 'us-east'
109
+ when 'us-west-1' then 'us-west'
110
+ when 'us-west-2' then 'us-west-2'
111
+ when 'eu-west-1' then 'eu-ireland'
112
+ when 'ap-southeast-1' then 'apac-sin'
113
+ when 'ap-northeast-1' then 'apac-tokyo'
114
+ when 'ap-southeast-2' then 'apac-syd'
115
+ when 'sa-east-1' then 'sa-east-1'
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -1,5 +1,5 @@
1
1
  module Aws
2
2
  module Rikanjo
3
- VERSION = "0.0.8"
3
+ VERSION = "0.0.9"
4
4
  end
5
5
  end
@@ -1,14 +1,14 @@
1
1
  require "spec_helper"
2
- require "aws/rikanjo/mode/ec2"
2
+ require "aws/rikanjo/ec2"
3
3
 
4
4
  include RikanjoSpecHelper
5
5
 
6
- describe 'AWS::Rikanjo::Mode::Ec2' do
6
+ describe 'AWS::Rikanjo::Ec2' do
7
7
 
8
8
  describe 'previous type' do
9
9
  it "is previous instance type" do
10
10
  %w{ m1.medium c1.medium m2.xlarge cc2.8xlarge cr1.8xlarge hi1.4xlarge cg1.4xlarge }.each do |t|
11
- a = Aws::RiKanjoo::Mode::Ec2.new(
11
+ a = Aws::RiKanjoo::Ec2.new(
12
12
  region = 'ap-northeast-1',
13
13
  instance_type = t,
14
14
  ri_util = 'light',
@@ -19,7 +19,7 @@ describe 'AWS::Rikanjo::Mode::Ec2' do
19
19
 
20
20
  it "is current instance type" do
21
21
  %w{ t1.micro m1.small m3.medium c3.medium r3.xlarge i2.xlarge }.each do |t|
22
- a = Aws::RiKanjoo::Mode::Ec2.new(
22
+ a = Aws::RiKanjoo::Ec2.new(
23
23
  region = 'ap-northeast-1',
24
24
  instance_type = t,
25
25
  ri_util = 'light',
@@ -31,7 +31,7 @@ describe 'AWS::Rikanjo::Mode::Ec2' do
31
31
 
32
32
  describe 'url' do
33
33
  it "build previous price url" do
34
- a = Aws::RiKanjoo::Mode::Ec2.new(
34
+ a = Aws::RiKanjoo::Ec2.new(
35
35
  region = 'ap-northeast-1',
36
36
  instance_type = 'm1.medium',
37
37
  ri_util = 'light',
@@ -40,7 +40,7 @@ describe 'AWS::Rikanjo::Mode::Ec2' do
40
40
  end
41
41
 
42
42
  it "build current price url" do
43
- a = Aws::RiKanjoo::Mode::Ec2.new(
43
+ a = Aws::RiKanjoo::Ec2.new(
44
44
  region = 'ap-northeast-1',
45
45
  instance_type = 'm3.medium',
46
46
  ri_util = 'light',
@@ -49,7 +49,7 @@ describe 'AWS::Rikanjo::Mode::Ec2' do
49
49
  end
50
50
 
51
51
  it "build previous ri price file" do
52
- a = Aws::RiKanjoo::Mode::Ec2.new(
52
+ a = Aws::RiKanjoo::Ec2.new(
53
53
  region = 'ap-northeast-1',
54
54
  instance_type = 'm1.medium',
55
55
  ri_util = 'light',
@@ -58,7 +58,7 @@ describe 'AWS::Rikanjo::Mode::Ec2' do
58
58
  end
59
59
 
60
60
  it "build current ri price file" do
61
- a = Aws::RiKanjoo::Mode::Ec2.new(
61
+ a = Aws::RiKanjoo::Ec2.new(
62
62
  region = 'ap-northeast-1',
63
63
  instance_type = 'm3.medium',
64
64
  ri_util = 'heavy',
@@ -72,13 +72,13 @@ describe 'AWS::Rikanjo::Mode::Ec2' do
72
72
 
73
73
  before :all do
74
74
  # rikanjo (current)
75
- a1 = Aws::RiKanjoo::Mode::Ec2.new(
75
+ a1 = Aws::RiKanjoo::Ec2.new(
76
76
  region = 'ap-northeast-1',
77
77
  instance_type = 'm3.medium',
78
78
  ri_util = 'medium',
79
79
  )
80
80
  # rikanjo (previous)
81
- a2 = Aws::RiKanjoo::Mode::Ec2.new(
81
+ a2 = Aws::RiKanjoo::Ec2.new(
82
82
  region = 'ap-northeast-1',
83
83
  instance_type = 'm1.medium',
84
84
  ri_util = 'medium',
@@ -91,7 +91,7 @@ describe 'AWS::Rikanjo::Mode::Ec2' do
91
91
 
92
92
  it "is able to get the price" do
93
93
  regions.each do |region|
94
- a = Aws::RiKanjoo::Mode::Ec2.new(
94
+ a = Aws::RiKanjoo::Ec2.new(
95
95
  region = region,
96
96
  instance_type = 'm3.large',
97
97
  ri_util = 'medium',
@@ -108,7 +108,7 @@ describe 'AWS::Rikanjo::Mode::Ec2' do
108
108
 
109
109
  it "an exception is raised when there are no instance-type" do
110
110
  regions.each do |region|
111
- a = Aws::RiKanjoo::Mode::Ec2.new(
111
+ a = Aws::RiKanjoo::Ec2.new(
112
112
  region = region,
113
113
  instance_type = 'm3.large.not.exists',
114
114
  ri_util = 'medium',