joyent-cloud-pricing 1.0.9 → 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 53bb4dcbcc11ef172f4dee489d822a8321376c14
4
- data.tar.gz: 1e5f59d10f6e583c0d169e306d62cec68c590841
3
+ metadata.gz: ffe763f26373c4c9dd19d269cabb8d34be18204b
4
+ data.tar.gz: e1454babed191bb8e3ddd4f3a6d0f768396a5c76
5
5
  SHA512:
6
- metadata.gz: 6acc5a126679a3cb3188b274ebed7b1569b51a62191a48f40e5e65e253f26284768dbcb95f8dd2c2d2862e2b234ffec9f04e7b02681a1bb46388d29cebd0edd1
7
- data.tar.gz: 143cbf0c084214bf76d67cac0f4377f590607c597e5eb908d3cbb13e6e1633ac2a106351b658288ab22f82f53c08a5801de70a674cdd3d2fcc4f79fcfe1b8c27
6
+ metadata.gz: 8ee3d92c075e5bd7bd352b59b6e16bf1e6fcd57b5312888b9ae8d802d63bd206138ae8c36c8a95226c56546bae3fd4125fbab1e75d16d53c3a13a207ef0007fb
7
+ data.tar.gz: a37d969d4682497eb6380875b9fa7380190145b1d6b3946de4b15d1885f638e2b416c3f51647a47c4a6480058d4d692d223c40cbaac4ca088e56182fdf3859fe
data/README.md CHANGED
@@ -54,15 +54,16 @@ Or install it yourself as:
54
54
 
55
55
  Most recent pricing structure is stored in the YAML file under ```config/joyent_pricing.yml```.
56
56
 
57
- To update this file, run provided rake task:
57
+ To update this file using prices published on Joyent's website, run the provided rake
58
+ task, and if YAML file changed, please feel free to submit a pull request.
58
59
 
59
60
  ```ruby
60
61
  rake joyent:pricing:update
61
62
  ```
62
63
 
63
- ## Full Pricing
64
+ ### Full Pricing
64
65
 
65
- Full price is stored in the configuration instance.
66
+ Full price is stored in the configuration instance and is read from YAML file.
66
67
 
67
68
  ```ruby
68
69
  c = Joyent::Cloud::Pricing::Configuration.instance
@@ -74,7 +75,7 @@ f.name
74
75
  # => "g3-highmemory-34.25-kvm"
75
76
  ```
76
77
 
77
- ## Analysis of Commit Pricing
78
+ ### Analysis of Commit Pricing
78
79
 
79
80
  > DISCLAIMER: please note that prices specified in this sample commit configuration
80
81
  > are completely arbitrary and have no relationship to any actual discounts issued by Joyent, Inc.
@@ -126,7 +127,30 @@ analyzer.monthly_overages_price # => monthly $$ for instances in excess of res
126
127
  analyzer.over_reserved_zone_list # => list of zones in reserve, but not in reality
127
128
  ```
128
129
 
129
- ## Reporter
130
+ ### Custom Pricing
131
+
132
+ If you have some zones with flavors that are either old, or created specifically for you,
133
+ they may not be known to this library. If they are known to you, you can use the reserve
134
+ pricing YAML file, and add a 'custom' section to it to define prices (and other attributes)
135
+ for any of the custom flavors, as follows (note that the 'reserved' section is not required).
136
+
137
+ ```yaml
138
+ defaults: &defaults
139
+ years: 1
140
+
141
+ custom:
142
+ :flavor-just-for-me:
143
+ :cost: 1.22
144
+ :disk: 800
145
+ :ram: 96
146
+ :cpus: 32
147
+
148
+ ```
149
+
150
+ The structure is the same as in the main file ```joyent_pricing.yml```, and the contents will
151
+ simply be merged on top of Joyent's standard pricing, so you can even overwrite existing flavors.
152
+
153
+ ### Reporter
130
154
 
131
155
  This module is used by ```knife joyent server price``` plugin to calculate pricing with and without
132
156
  reserve discounts.
@@ -144,23 +168,28 @@ puts reporter.render
144
168
  Example output with commit pricing used:
145
169
 
146
170
  ```
171
+ Joyent Pricing Calculator: https://github.com/kigster/joyent-cloud-pricing
172
+ .................................................................
147
173
  ZONE COUNTS:
148
174
  Total # of zones 33
149
175
  Total # of reserved zones 27
150
- Total # of reserved but absent zones 1
176
+ Total # of reserved but absent flavors 6
177
+ 4 x g3-highmemory-68.375-smartos
178
+ 2 x g3-highcpu-7-smartos
179
+ .................................................................
151
180
 
152
181
  Resources in use: Reserved On-Demand Total
153
182
  CPUs 384 118 494
154
183
  RAM 828G 140G 907G
155
184
  DISK 23T 5T 27T
156
- .................................................................
157
185
 
158
186
  MONTHLY COSTS:
159
187
  List of on-demand flavors by price (in excess of reserve)
160
- 2 x g3-highcpu-32-smartos-cc $3,339.36
161
- 2 x g3-highcpu-16-smartos $1,670.40
162
- 2 x g3-highcpu-7-smartos $731.52
163
- 1 x g3-standard-30-smartos $691.20
188
+
189
+ 2 x g3-highcpu-32-smartos-cc $3,339.36
190
+ 2 x g3-highcpu-16-smartos $1,670.40
191
+ 2 x g3-highcpu-7-smartos $731.52
192
+ 1 x g3-standard-30-smartos $691.20
164
193
  ___________
165
194
  On demand monthly $6,432.48
166
195
  Zones under reserve pricing $8,720.00
@@ -181,14 +210,18 @@ YEARLY RESERVE SAVINGS:
181
210
  .................................................................
182
211
  ```
183
212
 
184
- ## Usage with knife joyent
213
+ ### Color
214
+
215
+ You can turn off color output by setting ```NO_COLOR``` environment variable.
216
+
217
+ ### Usage with knife joyent
185
218
 
186
- This gem is integrated with latest version of [knife-joyent](https://github.com/joyent/knife-joyent) gem.
219
+ This gem is integrated into [knife-joyent](https://github.com/joyent/knife-joyent) gem.
187
220
 
188
- Use it as follows:
221
+ Use it with ```knife joyent``` as follows:
189
222
 
190
223
  ```
191
- knife joyent server pricing -z -r config/my-reserve-config.yml
224
+ knife joyent server pricing -z -r config/my-reserve-config.yml [ --no-color ]
192
225
  ```
193
226
 
194
227
  ## Contributing
@@ -12,3 +12,9 @@ reserved:
12
12
  prepay: 800.00
13
13
  monthly: 60
14
14
  number: 12
15
+
16
+ custom:
17
+ :my-special-custom-flavor-pricing-hourly:
18
+ :cost: 2.451
19
+ :another-flavor-just-for-me:
20
+ :cost: 1.22
@@ -1,8 +1,19 @@
1
1
  :g3-standard-8-smartos:
2
2
  :cost: 0.26
3
+ :ram: 8.0
4
+ :cpus: 4.0
5
+ :disk: 738
3
6
  :g3-highcpu-8-smartos:
4
7
  :cost: 0.58
8
+ :ram: 8.0
9
+ :cpus: 8.0
10
+ :disk: 738
5
11
  :g3-standard-0.5-smartos:
6
12
  :cost: 0.016
13
+ :ram: 0.5
14
+ :cpus: 0.5
7
15
  :g3-highmemory-96-smartos:
8
16
  :cost: 2.451
17
+ :ram: 7.5
18
+ :cpus: 32.0
19
+ :disk: 3100
@@ -6,7 +6,7 @@ module Joyent
6
6
  module Pricing
7
7
 
8
8
  PRICING_FILENAME = File.expand_path('../../config/joyent_pricing.yml', __FILE__)
9
- LEGACY_FILENAME = File.expand_path('../../config/legacy_prices.yml', __FILE__)
9
+ LEGACY_FILENAME = File.expand_path('../../config/joyent_pricing_unpublished.yml', __FILE__)
10
10
  COMMIT_FILENAME = 'config/commit_pricing.yml'
11
11
  JOYENT_URL = 'http://www.joyent.com/products/compute-service/pricing'
12
12
  HOURS_PER_MONTH = 720
@@ -31,10 +31,20 @@ module Joyent::Cloud::Pricing
31
31
  h
32
32
  end
33
33
 
34
+ def unknown_zone_total
35
+ count_for_all(unknown_zone_counts) do |flavor|
36
+ 1
37
+ end.to_i
38
+ end
39
+
34
40
  def have_unknown_zones?
35
41
  unknown_zone_counts.size > 0
36
42
  end
37
43
 
44
+ def have_excess_zones?
45
+ excess_zone_counts.size > 0
46
+ end
47
+
38
48
  def have_over_reserved_zones?
39
49
  over_reserved_zone_counts.size > 0
40
50
  end
@@ -5,19 +5,23 @@ module Joyent::Cloud::Pricing
5
5
  class Commit
6
6
  class << self
7
7
  def from_yaml(filename = COMMIT_FILENAME)
8
- new(YAML.load(File.read(filename))['reserved'])
8
+ hash = YAML.load(File.read(filename))
9
+ new(hash['reserved'] || {}, hash['custom'])
9
10
  end
10
11
  end
11
12
 
12
13
  # map of image names to prices
13
- attr_accessor :reserves
14
+ attr_accessor :reserves, :custom
14
15
 
15
- def initialize(hash = {})
16
+ def initialize(hash = {}, custom = nil)
16
17
  @config = hash.symbolize_keys
17
18
  self.reserves = {}
18
19
  @config.each_pair do |flavor, config|
19
20
  self.reserves[flavor] = Reserve.new(flavor, config)
20
21
  end
22
+ if custom
23
+ Joyent::Cloud::Pricing::Configuration.instance.merge(custom)
24
+ end
21
25
  end
22
26
 
23
27
  def reserve_for flavor
@@ -64,6 +64,10 @@ module Joyent::Cloud::Pricing
64
64
  end
65
65
  end
66
66
 
67
+ def merge(additional_pricing)
68
+ config.merge!(additional_pricing)
69
+ end
70
+
67
71
  end
68
72
  end
69
73
 
@@ -0,0 +1,66 @@
1
+ <%- separator = ('.' * 65).cyan -%>
2
+ Joyent Pricing Calculator: https://github.com/kigster/joyent-cloud-pricing
3
+ <%= separator %>
4
+ <%- if have_unknown_zones? -%>
5
+ <%= "WARNING!".red %>: Some 'flavors' in your list were not recognized, and
6
+ were excluded from calculations. You could add them to the "custom"
7
+ section of your reserve pricing file, and specify their cost.
8
+
9
+ Total # of zones with unknown flavors: <%= sprintf("%20d", unknown_zone_total).red %>
10
+ List of unknown flavors below:
11
+
12
+ <%= unknown_zones_for_print.red %>
13
+ <%= separator %>
14
+
15
+ <%- end -%>
16
+ ZONE COUNTS:
17
+ Total # of zones <%= sprintf("%20d", zones_in_use.size).cyan %>
18
+ <%- if have_commit_pricing? -%>
19
+ Total # of reserved zones <%= sprintf("%20d", commit.total_zones).green %>
20
+ <%- if have_over_reserved_zones? -%>
21
+ Total # of reserved but absent flavors <%= value = sprintf("%20d", over_reserved_zone_counts.size || 0); value == "0" ? value.blue : value.red %>
22
+ <%= over_reserved_zones_for_print.magenta %>
23
+ <%- end -%>
24
+ <%- end -%>
25
+ <%= separator %>
26
+
27
+ Resources in use:<%= sprintf('%14s %15s %15s', 'Reserved', 'On-Demand', 'Total') %>
28
+ CPUs <%= props = zone_props_to_string(:cpus, 16); props[0].green + props[1].yellow + props[2].cyan %>
29
+ RAM <%= props = zone_props_to_string(:ram, 15, 'G'); props[0].green + props[1].yellow + props[2].cyan %>
30
+ DISK <%= props = zone_props_to_string(:disk, 15, 'T', 1024); props[0].green + props[1].yellow + props[2].cyan %>
31
+ <%= separator %>
32
+
33
+ MONTHLY COSTS:
34
+ <%- if print_zone_list -%>
35
+ List of on-demand flavors by price <%= have_commit_pricing? ? "(in excess of reserve)" : "" %>
36
+
37
+ <%= excess_zones_for_print %>
38
+ <%= "___________".yellow %>
39
+ <%- end -%>
40
+ On demand monthly <%= format_price(monthly_overages_price, 20).yellow %>
41
+ <%- if have_commit_pricing? -%>
42
+ Zones under reserve pricing <%= format_price(commit.monthly_price, 20).green %>
43
+ <%- end -%>
44
+ <%- if have_commit_pricing? -%>
45
+ <%= "___________".cyan %>
46
+ Total <%= format_price(monthly_total_price, 20).cyan %>
47
+ <%- end -%>
48
+ <%= separator %>
49
+
50
+ YEARLY COSTS:
51
+ <%- if have_commit_pricing? -%>
52
+ On demand yearly <%= format_price(yearly_overages_price, 20).yellow %>
53
+ Reserve prepay one time fee <%= format_price(commit.upfront_price, 20).green %>
54
+ Reserve sum of all monthly fees <%= format_price(commit.monthly_price * 12, 20).green %>
55
+ <%= "___________".cyan %>
56
+ Total <%= format_price(yearly_total, 20).cyan %>
57
+ <%- else -%>
58
+ On demand yearly <%= format_price(yearly_full_price, 20).cyan %>
59
+ <%- end -%>
60
+ <%- if have_commit_pricing? -%>
61
+
62
+ YEARLY RESERVE SAVINGS:
63
+ Savings due to reserved pricing <%= format_price(yearly_savings, 20).green %>
64
+ Savings % <%= sprintf("%19d", yearly_savings_percent).green + '%'.green %>
65
+ <%- end -%>
66
+ <%= separator %>
@@ -5,7 +5,7 @@ require 'colored'
5
5
  module Joyent::Cloud::Pricing
6
6
  class Reporter
7
7
 
8
- attr_accessor :commit, :zones_in_use, :analyzer, :formatter, :print_zone_list
8
+ attr_accessor :commit, :zones_in_use, :analyzer, :formatter, :print_zone_list, :template
9
9
 
10
10
  def initialize(commit = COMMIT, zones_in_use = [])
11
11
  @commit = case commit
@@ -20,130 +20,100 @@ module Joyent::Cloud::Pricing
20
20
  end
21
21
 
22
22
  @zones_in_use = zones_in_use
23
- @analyzer = Joyent::Cloud::Pricing::Analyzer.new(@commit, @zones_in_use)
23
+ @analyzer = Joyent::Cloud::Pricing::Analyzer.new(@commit, @zones_in_use)
24
24
  @formatter = Joyent::Cloud::Pricing::Formatter.new(pricing.config)
25
25
  @print_zone_list = true
26
+ @template = File.read(File.expand_path('../report.txt.erb', __FILE__))
26
27
  end
27
28
 
28
- def render
29
+ def render(options = {})
30
+ disable_color if (options && options[:disable_color]) || ENV['NO_COLOR']
29
31
  @r = self
30
- @f = formatter
31
- ERB.new(REPORT_ASCII, 0, '-').result(binding)
32
+ ERB.new(template, 0, '-').result(binding)
32
33
  end
33
34
 
34
- def reserve?
35
- commit.reserves.size > 0
35
+ def pricing
36
+ Joyent::Cloud::Pricing::Configuration.instance
36
37
  end
37
38
 
38
- def zones
39
- zones_in_use.size
39
+ # Various formatting helpers follow below
40
+ # Note that we delegate to analyzer for majority of calls.
41
+ # Sorry about that method_missing :(
42
+
43
+ def method_missing(method, *args, &block)
44
+ if @analyzer.respond_to?(method)
45
+ @analyzer.send(method, *args, &block)
46
+ else
47
+ super
48
+ end
40
49
  end
41
50
 
42
- def pricing
43
- Joyent::Cloud::Pricing::Configuration.instance
51
+ def format_price *args
52
+ @formatter.format_price *args
44
53
  end
45
54
 
46
- def excess_zones
47
- zones = analyzer.excess_zone_counts.each_pair.
48
- map{|flavor, count| [ flavor, count, pricing.monthly(flavor) * count ]}.
49
- sort{|x,y| y[2] <=> x[2]}
50
- zones
55
+ def have_commit_pricing?
56
+ commit.reserves.size > 0
51
57
  end
52
58
 
53
- def excess_zone_list
54
- excess_zones.map do |tuple|
55
- flavor, count, monthly = tuple
56
- sprintf(" %2d x %-36s %20s",
57
- count, flavor, formatter.format_price(monthly, 20).yellow)
58
- end.join("\n")
59
+ def excess_zones_for_print
60
+ zones_for_print(zone_counts_to_list(analyzer.excess_zone_counts), :yellow)
59
61
  end
60
62
 
61
- def zone_props_to_string(prop_type, width, suffix = '', divide_by = 1)
62
- props = analyzer.send(prop_type)
63
- [ props[:reserved], props[:unreserved], props[:total] ].map do |value|
64
- sprintf("%#{width}d#{suffix}", value / divide_by)
65
- end
63
+ def over_reserved_zones_for_print
64
+ zones_for_print(analyzer.over_reserved_zone_counts)
66
65
  end
67
66
 
68
- def unknown_flavor_zone_list
69
- analyzer.unknown_zone_counts.keys
67
+ def unknown_zones_for_print
68
+ zone_list_for_print(analyzer.unknown_zone_counts.keys)
70
69
  end
71
70
 
72
- def over_reserved_zone_list
73
- analyzer.over_reserved_zone_counts.keys
71
+ def zones_for_print(zone_list, color = nil)
72
+ zone_list.map do |tuple|
73
+ flavor, count, monthly = tuple
74
+ price = formatter.format_price(monthly, 16)
75
+ price = price.send(color) if color
76
+ sprintf(" %2d x %-36s %16s", count, flavor, price)
77
+ end.join("\n")
74
78
  end
75
79
 
76
80
  def zone_list_for_print(list, format = ' %-40s')
77
- list.map{|k| sprintf(format, k) }.join("\n")
81
+ list.map { |k| sprintf(format, k) }.join("\n")
78
82
  end
79
83
 
80
- SEPARATOR = ('.' * 65).cyan
81
- PROPS_FORMAT= '%20d %20d %20d'
82
- REPORT_ASCII = <<ASCII
83
-
84
- <%- if @r.analyzer.have_unknown_zones? -%>
85
- <%= "WARNING!".red %>: flavor list has values which were not recognized, and
86
- were excluded from calculations. Add them to legacy_prices.yml.
87
-
88
- List of flavors with unknown properties:
89
- Total # of unrecognized flavor zones <%= sprintf("%20d", @r.analyzer.unknown_zone_counts.keys.size).red %>
90
- <%= @r.zone_list_for_print(@r.unknown_flavor_zone_list).red %>
91
- <%= SEPARATOR %>
92
-
93
- <%- end -%>
94
- ZONE COUNTS:
95
- Total # of zones <%= sprintf("%20d", @r.zones).cyan %>
96
- <%- if @r.reserve? -%>
97
- Total # of reserved zones <%= sprintf("%20d", @r.commit.total_zones).green %>
98
- <%- if @r.analyzer.have_over_reserved_zones? -%>
99
- Total # of reserved but absent zones <%= value = sprintf("%20d", @r.analyzer.over_reserved_zone_counts.size || 0); value == "0" ? value.blue : value.red %>
100
- <%= @r.zone_list_for_print(@r.over_reserved_zone_list).red %>
101
- <%- end -%>
102
- <%- end -%>
103
- <%= SEPARATOR %>
104
-
105
- Resources in use:<%= sprintf('%14s %15s %15s', 'Reserved', 'On-Demand', 'Total') %>
106
- CPUs <%= props = @r.zone_props_to_string(:cpus, 16); props[0].green + props[1].yellow + props[2].cyan %>
107
- RAM <%= props = @r.zone_props_to_string(:ram, 15, 'G'); props[0].green + props[1].yellow + props[2].cyan %>
108
- DISK <%= props = @r.zone_props_to_string(:disk, 15, 'T', 1024); props[0].green + props[1].yellow + props[2].cyan %>
109
- <%= SEPARATOR %>
110
-
111
- MONTHLY COSTS:
112
- <%- if @r.print_zone_list -%>
113
- List of on-demand flavors by price <%= @r.reserve? ? "(in excess of reserve)" : "" %>
114
- <%= @r.excess_zone_list %>
115
- <%= "___________".yellow %>
116
- <%- end -%>
117
- On demand monthly <%= @f.format_price(@r.analyzer.monthly_overages_price, 20).yellow %>
118
- <%- if @r.reserve? -%>
119
- Zones under reserve pricing <%= @f.format_price(@r.commit.monthly_price, 20).green %>
120
- <%- end -%>
121
- <%- if @r.reserve? -%>
122
- <%= "___________".cyan %>
123
- Total <%= @f.format_price(@r.analyzer.monthly_total_price, 20).cyan %>
124
- <%- end -%>
125
- <%= SEPARATOR %>
126
-
127
- YEARLY COSTS:
128
- <%- if @r.reserve? -%>
129
- On demand yearly <%= @f.format_price(@r.analyzer.yearly_overages_price, 20).yellow %>
130
- Reserve prepay one time fee <%= @f.format_price(@r.commit.upfront_price, 20).green %>
131
- Reserve sum of all monthly fees <%= @f.format_price(@r.commit.monthly_price * 12, 20).green %>
132
- <%= "___________".cyan %>
133
- Total <%= @f.format_price(@r.analyzer.yearly_total, 20).cyan %>
134
- <%- else -%>
135
- On demand yearly <%= @f.format_price(@r.analyzer.yearly_full_price, 20).cyan %>
136
- <%- end -%>
137
- <%- if @r.reserve? -%>
138
-
139
- YEARLY RESERVE SAVINGS:
140
- Savings due to reserved pricing <%= @f.format_price(@r.analyzer.yearly_savings, 20).green %>
141
- Savings % <%= sprintf("%19d", @r.analyzer.yearly_savings_percent).green + '%'.green %>
142
- <%- end -%>
143
- <%= SEPARATOR %>
144
-
145
- ASCII
84
+ def zone_counts_to_list zone_count_hash
85
+ zones = zone_count_hash.each_pair.
86
+ map { |flavor, count| [flavor, count, pricing.monthly(flavor) * count] }.
87
+ sort { |x, y| y[2] <=> x[2] }
88
+ zones
89
+ end
146
90
 
147
- end
91
+ def zone_props_to_string(prop_type, width, suffix = '', divide_by = 1)
92
+ props = analyzer.send(prop_type)
93
+ [props[:reserved], props[:unreserved], props[:total]].map do |value|
94
+ sprintf("%#{width}d#{suffix}", value / divide_by)
95
+ end
96
+ end
148
97
 
98
+ private
99
+
100
+ def disable_color
101
+ String.instance_eval do
102
+ %w(
103
+ black
104
+ red
105
+ green
106
+ yellow
107
+ blue
108
+ magenta
109
+ cyan
110
+ white
111
+ ).each do |color|
112
+ define_method(color) do
113
+ self
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
149
119
  end
@@ -1,7 +1,7 @@
1
1
  module Joyent
2
2
  module Cloud
3
3
  module Pricing
4
- VERSION = '1.0.9'
4
+ VERSION = '1.0.10'
5
5
  end
6
6
  end
7
7
  end
@@ -17,3 +17,7 @@ reserved:
17
17
  prepay: 1800.00
18
18
  monthly: 600
19
19
  quantity: 5
20
+
21
+ custom:
22
+ :some-instance:
23
+ :cost: 2.451
@@ -0,0 +1,6 @@
1
+ defaults: &defaults
2
+ years: 1
3
+
4
+ custom:
5
+ :some-fake-flavor-again:
6
+ :cost: 5.1
@@ -37,6 +37,8 @@ describe 'Joyent::Cloud::Pricing::Analyzer' do
37
37
  g3-highmemory-17.125-smartos
38
38
  g3-highmemory-17.125-smartos
39
39
  some-unknown-flavor
40
+ some-other-unknown-flavor
41
+ some-other-unknown-flavor
40
42
  )
41
43
 
42
44
  let(:flavors) { FLAVORS }
@@ -57,7 +59,8 @@ describe 'Joyent::Cloud::Pricing::Analyzer' do
57
59
  :'g3-highio-60.5-smartos' => 4,
58
60
  :'g3-highmemory-17.125-smartos' => 12,
59
61
  :'g3-standard-30-smartos' => 1,
60
- :'some-unknown-flavor' => 1
62
+ :'some-unknown-flavor' => 1,
63
+ :'some-other-unknown-flavor' => 2
61
64
  })
62
65
  end
63
66
 
@@ -78,7 +81,8 @@ describe 'Joyent::Cloud::Pricing::Analyzer' do
78
81
  :'g3-highcpu-32-smartos-cc' => 2,
79
82
  :'g3-highcpu-7-smartos' => 2,
80
83
  :'g3-standard-30-smartos' => 1,
81
- :'some-unknown-flavor' => 1
84
+ :'some-unknown-flavor' => 1,
85
+ :'some-other-unknown-flavor' => 2
82
86
  })
83
87
  end
84
88
 
@@ -103,7 +107,9 @@ describe 'Joyent::Cloud::Pricing::Analyzer' do
103
107
 
104
108
  context 'for unknown instances' do
105
109
  it 'should return some-unknown-flavor' do
106
- expect(analyzer.unknown_zone_counts).to eql({ :'some-unknown-flavor' => 1 })
110
+ expect(analyzer.unknown_zone_counts).to eql({ :'some-unknown-flavor' => 1,
111
+ :'some-other-unknown-flavor' => 2 })
112
+ expect(analyzer.unknown_zone_total).to eql(3)
107
113
  end
108
114
  end
109
115
 
@@ -1,22 +1,43 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'Joyent::Cloud::Pricing::Commit' do
4
- let(:commit) { Joyent::Cloud::Pricing::Commit.from_yaml 'spec/fixtures/commit.yml' }
5
4
 
6
- let(:expected_commit) { {
7
- 'g3-highcpu-32-smartos-cc' => {prepay: 8000.0, monthly: 500.0, years: 1, quantity: 10},
8
- 'g3-highmemory-17.125-smartos' => {prepay: 800.0, monthly: 60.0, years: 1, quantity: 12},
9
- 'g3-highio-60.5-smartos' => {prepay: 1800.0, monthly: 600.0, years: 1, quantity: 5}
10
- } }
5
+ context 'when some reserve pricing is defined' do
6
+ let(:commit) { Joyent::Cloud::Pricing::Commit.from_yaml 'spec/fixtures/commit.yml' }
7
+ let(:config) { Joyent::Cloud::Pricing::Configuration.instance }
11
8
 
12
- it 'should correctly load commit from the file' do
13
- expected_commit.keys.each do |flavor|
14
- expect(expected_commit[flavor]).to eql(commit.reserve_for(flavor).to_hash)
9
+ let(:expected_commit) { {
10
+ 'g3-highcpu-32-smartos-cc' => {prepay: 8000.0, monthly: 500.0, years: 1, quantity: 10},
11
+ 'g3-highmemory-17.125-smartos' => {prepay: 800.0, monthly: 60.0, years: 1, quantity: 12},
12
+ 'g3-highio-60.5-smartos' => {prepay: 1800.0, monthly: 600.0, years: 1, quantity: 5}
13
+ } }
14
+
15
+ it 'should correctly load commit from the file' do
16
+ expected_commit.keys.each do |flavor|
17
+ expect(expected_commit[flavor]).to eql(commit.reserve_for(flavor).to_hash)
18
+ end
19
+ end
20
+
21
+ it '#monthly_price' do
22
+ expect(commit.monthly_price).to eql(8720.0)
23
+ end
24
+
25
+ it 'should have different custom pricing' do
26
+ expect(commit.reserves.keys.size).to eql(3)
27
+ expect(config.config[:'some-instance'][:cost]).to eql(2.451)
15
28
  end
16
29
  end
17
30
 
18
- it '#monthly_price' do
19
- expect(commit.monthly_price).to eql(8720.0)
31
+ context 'when no reserve but custom pricing is available' do
32
+ let(:commit) { Joyent::Cloud::Pricing::Commit.from_yaml 'spec/fixtures/commit_noreserve.yml' }
33
+ let(:config) { Joyent::Cloud::Pricing::Configuration.instance }
34
+ let(:custom_flavor) { :'some-fake-flavor-again' }
35
+ it 'should load properly and add custom to config' do
36
+
37
+ expect(commit.reserves).to be_empty
38
+ expect(config.config[custom_flavor.to_sym][:cost]).to eql(5.1)
39
+ config.config.delete(custom_flavor.to_sym)
40
+ end
20
41
  end
21
42
 
22
43
  end
@@ -55,17 +55,25 @@ describe 'Joyent::Cloud::Pricing::Reporter' do
55
55
  end
56
56
 
57
57
  context '#render' do
58
- it 'should propertly render an ERB template' do
59
- output = reporter.render
60
- expect(output).to_not be_nil
58
+ context 'with existing commit pricing' do
59
+ it 'should propertly render an ERB template' do
60
+ output = reporter.render
61
+ STDOUT.puts output if ENV['DEBUG_REPORTER']
62
+ expect(output).to_not be_nil
63
+ expect(output).to include('MONTHLY COSTS')
64
+ expect(output).to include('YEARLY RESERVE SAVINGS')
65
+ end
61
66
  end
62
67
 
63
- context 'blank commit configuration' do
68
+ context 'without any commit configuration' do
64
69
  let(:commit) { Joyent::Cloud::Pricing::Commit.new }
65
70
  it 'should still properly render an ERB template' do
66
71
  expect(commit.reserves.size).to eql(0)
67
72
  output = reporter.render
73
+ STDOUT.puts output if ENV['DEBUG_REPORTER']
68
74
  expect(output).to_not be_nil
75
+ expect(output).to_not include('YEARLY RESERVE SAVINGS')
76
+ expect(output).to include('some-fake-flavor-without-pricing')
69
77
  end
70
78
  end
71
79
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: joyent-cloud-pricing
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Gredeskoul
@@ -126,7 +126,7 @@ files:
126
126
  - Rakefile
127
127
  - config/commit_pricing.yml.example
128
128
  - config/joyent_pricing.yml
129
- - config/legacy_prices.yml
129
+ - config/joyent_pricing_unpublished.yml
130
130
  - joyent-cloud-pricing.gemspec
131
131
  - lib/pricing.rb
132
132
  - lib/pricing/analyzer.rb
@@ -135,6 +135,7 @@ files:
135
135
  - lib/pricing/flavor.rb
136
136
  - lib/pricing/formatter.rb
137
137
  - lib/pricing/helpers.rb
138
+ - lib/pricing/report.txt.erb
138
139
  - lib/pricing/reporter.rb
139
140
  - lib/pricing/reserve.rb
140
141
  - lib/pricing/scraper.rb
@@ -142,6 +143,7 @@ files:
142
143
  - lib/pricing/version.rb
143
144
  - lib/tasks/update.rake
144
145
  - spec/fixtures/commit.yml
146
+ - spec/fixtures/commit_noreserve.yml
145
147
  - spec/fixtures/pricing.yml
146
148
  - spec/pricing/analyzer_spec.rb
147
149
  - spec/pricing/commit_spec.rb
@@ -178,6 +180,7 @@ summary: Tools for calculating monthly and yearly price of infrastructure hosted
178
180
  Joyent Public Cloud.
179
181
  test_files:
180
182
  - spec/fixtures/commit.yml
183
+ - spec/fixtures/commit_noreserve.yml
181
184
  - spec/fixtures/pricing.yml
182
185
  - spec/pricing/analyzer_spec.rb
183
186
  - spec/pricing/commit_spec.rb