joyent-cloud-pricing 1.0.9 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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