joyent-cloud-pricing 1.0.6 → 1.0.7

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: 9b380b01b5301c09ce4946aed2d0d55879ea978a
4
- data.tar.gz: 1eddbc97807b98e7e7ec1144226e47e61fef5414
3
+ metadata.gz: 6830b1d71aec26c98b251688edacd2a40448eac1
4
+ data.tar.gz: bfdeb0a822f1f8f6b15122402c4dbc491a061349
5
5
  SHA512:
6
- metadata.gz: bba5bd633fa5e1d02037487c549d130bb43cf8b473c33544e623aea153e3a71fdc17ec8f0a395c31fe2efcd79fc4f5e3ee6bb3db29dceba3169120d23c5f2c62
7
- data.tar.gz: 3ab4786f322d28b6077395eb2042a51ae079d78b88230ba5069745f0b43fe2314b49cda55208e0b58067c18cca224096201b1b05365d019c483d5f48705e8fd1
6
+ metadata.gz: 8c8bf089f0fe1f5e7361061ab4dcad2bc10845f64b2bdd92c40a20391910b59bdb8cc47540a5318eb9b656a0aef4552230c04bab1a6c8af5db9a3b40da0be958
7
+ data.tar.gz: cca584aaaecb758178cf1212a04400e1e8856a1c7c81b04a6b4e7ee6d6910ee137b2cc28da2f9d6e4f638e89fc6fc3f9242d67a4bb7e08a01f841236776267a8
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.gitignore CHANGED
@@ -16,3 +16,4 @@ test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
18
  .idea/**
19
+ **.DS_Store
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/joyent-cloud-pricing.png)](http://badge.fury.io/rb/joyent-cloud-pricing)
2
2
  [![Build status](https://secure.travis-ci.org/kigster/joyent-cloud-pricing.png)](http://travis-ci.org/kigster/joyent-cloud-pricing)
3
3
  [![Code Climate](https://codeclimate.com/github/kigster/joyent-cloud-pricing.png)](https://codeclimate.com/github/kigster/joyent-cloud-pricing)
4
+ [![Coverage Status](https://coveralls.io/repos/kigster/joyent-cloud-pricing/badge.png?branch=master)](https://coveralls.io/r/kigster/joyent-cloud-pricing?branch=master)
4
5
 
5
6
  # Joyent Cloud Pricing
6
7
 
@@ -64,14 +65,19 @@ rake joyent:pricing:update
64
65
  Full price is stored in the configuration instance.
65
66
 
66
67
  ```ruby
67
- Joyent::Cloud::Pricing::Configuration.instance["g3-standard-48-smartos"]
68
- # => 1.536
68
+ c = Joyent::Cloud::Pricing::Configuration.instance
69
+ f = c.flavor "g3-highmemory-34.25-kvm"
70
+ f.to_h
71
+ # => {:name=>"g3-highmemory-34.25-kvm", :os=>"Linux",
72
+ # :cost=>0.817, :cpus=>4.0, :disk=>843, :ram=>34.25}
73
+ f.name
74
+ # => "g3-highmemory-34.25-kvm"
69
75
  ```
70
76
 
71
77
  ## Analysis of Commit Pricing
72
78
 
73
- _DISCLAIMER_: please note that prices specified in this sample commit configuration
74
- are completely arbitrary and have no relationship to any actual discounts issued by Joyent, Inc.
79
+ > DISCLAIMER: please note that prices specified in this sample commit configuration
80
+ > are completely arbitrary and have no relationship to any actual discounts issued by Joyent, Inc.
75
81
 
76
82
  Reserve pricing is meant to be defined by a YAML file, outside of the gem folder,
77
83
  somewhere on the file system. File looks like this.
@@ -116,7 +122,7 @@ flavors = %w(
116
122
  commit = Joyent::Cloud::Pricing::Commit.from_yaml 'my_company/config/joyent-commit-pricing.yml'
117
123
  analyzer = Joyent::Cloud::Pricing::Analyzer.new(commit, flavors)
118
124
 
119
- analyzer.monthly_overages_price # => monthly $$ for instances in excess of reserve
125
+ analyzer.monthly_overages_price # => monthly $$ for instances in excess of reserve
120
126
  analyzer.over_reserved_zone_list # => list of zones in reserve, but not in reality
121
127
  ```
122
128
 
@@ -126,15 +132,11 @@ This module is used by ```knife joyent server price``` plugin to calculate prici
126
132
  reserve discounts.
127
133
 
128
134
  ```ruby
129
- current_zone_list = %w(
130
- g3-highcpu-8-smartos
131
- g3-highcpu-8-smartos
132
- # ....
133
- )
135
+ current_zone_list = %w(g3-highcpu-8-smartos g3-highcpu-8-smartos )
134
136
 
135
- reporter = Joyent::Cloud::Pricing::Reporter.new(
136
- 'config/reserve-commit.yml',
137
- current_zone_list)
137
+ reporter = Joyent::Cloud::Pricing::Reporter.new(
138
+ 'config/reserve-commit.yml',
139
+ current_zone_list)
138
140
 
139
141
  puts reporter.render
140
142
  ```
@@ -169,7 +171,7 @@ MONTHLY COSTS:
169
171
  YEARLY COSTS:
170
172
  On demand yearly $77,189.76
171
173
  Reserve prepay one time fee $98,600.00
172
- Reserve monthly fees $104,640.00
174
+ Reserve sum of all monthly fees $104,640.00
173
175
  ___________
174
176
  Total $280,429.76
175
177
 
@@ -179,6 +181,16 @@ YEARLY RESERVE SAVINGS:
179
181
  .................................................................
180
182
  ```
181
183
 
184
+ ## Usage with knife joyent
185
+
186
+ This gem is integrated with latest version of [knife-joyent](https://github.com/joyent/knife-joyent) gem.
187
+
188
+ Use it as follows:
189
+
190
+ ```
191
+ knife joyent server pricing -z -r config/my-reserve-config.yml
192
+ ```
193
+
182
194
  ## Contributing
183
195
 
184
196
  1. Fork it
@@ -189,9 +201,9 @@ YEARLY RESERVE SAVINGS:
189
201
 
190
202
  ## Disclaimer
191
203
 
192
- This gem is provided as a convenience tool in understanding and comparing cloud pricing. No warranties,
193
- explicit or implied, are made in relation to correctness or accuracy of the calculations provided by this
194
- library. Use at your own risk.
204
+ > This gem is provided as a convenience tool in understanding and comparing cloud pricing. No warranties,
205
+ > explicit or implied, are made in relation to correctness or accuracy of the calculations provided by this
206
+ > library. Use at your own risk.
195
207
 
196
208
  ## Author
197
209
 
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_development_dependency 'bundler', '~> 1.5'
26
26
  spec.add_development_dependency 'rake'
27
+ spec.add_development_dependency 'coveralls'
27
28
 
28
29
  spec.add_development_dependency 'rspec'
29
30
  spec.add_development_dependency 'rspec-mocks'
@@ -24,6 +24,17 @@ module Joyent::Cloud::Pricing
24
24
  h
25
25
  end
26
26
 
27
+ # Zones with flavor that's not recognized, and therefore unknown
28
+ def unknown_zone_counts
29
+ h = {}
30
+ zone_counts.each_pair { |flavor, count| h[flavor] = count if pricing.flavor(flavor).nil? }
31
+ h
32
+ end
33
+
34
+ def have_unknown_zones?
35
+ unknown_zone_counts.size > 0
36
+ end
37
+
27
38
  # Non-discounted full price
28
39
  def monthly_full_price
29
40
  monthly_full_price_for(zone_counts)
@@ -91,7 +102,8 @@ module Joyent::Cloud::Pricing
91
102
  def count_props(operation)
92
103
  results = [ zone_counts, excess_zone_counts, commit.flavor_counts ].map do |list|
93
104
  count_for_all list do |flavor|
94
- pricing.flavor(flavor).send(operation)
105
+ f = pricing.flavor(flavor)
106
+ f.respond_to?(operation.to_sym) ? f.send(operation) : 0
95
107
  end
96
108
  end
97
109
  { total: results[0], unreserved: results[1], reserved: results[2] }
@@ -4,7 +4,7 @@ require_relative 'flavor'
4
4
 
5
5
  module Joyent::Cloud::Pricing
6
6
  class Configuration
7
- @@lock = Mutex.new # just in case
7
+ @@lock = Mutex.new
8
8
 
9
9
  class << self
10
10
  def instance(reload = false)
@@ -54,13 +54,7 @@ module Joyent::Cloud::Pricing
54
54
 
55
55
  def monthly(flavor)
56
56
  f = self.cost(flavor)
57
- if f.nil?
58
- STDERR.puts "WARNING: can't find flavor #{flavor}, assuming 0"
59
- 0
60
- else
61
- monthly_from_hourly f
62
- end
63
-
57
+ f.nil? ? 0 : monthly_from_hourly(f)
64
58
  end
65
59
 
66
60
  def save_yaml(filename = PRICING_FILENAME)
@@ -20,7 +20,7 @@ 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
26
  end
@@ -44,7 +44,9 @@ module Joyent::Cloud::Pricing
44
44
  end
45
45
 
46
46
  def excess_zones
47
- zones = analyzer.excess_zone_counts.each_pair.map{|flavor, count| [ flavor, count, pricing.monthly(flavor) * count ]}.sort{|x,y| y[2] <=> x[2]}
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]}
48
50
  zones
49
51
  end
50
52
 
@@ -67,6 +69,15 @@ module Joyent::Cloud::Pricing
67
69
  PROPS_FORMAT= '%20d %20d %20d'
68
70
  REPORT_ASCII = <<ASCII
69
71
 
72
+ <%- if @r.analyzer.have_unknown_zones? -%>
73
+ <%= "WARNING!".red %>: flavor list has values which were not recognized, and
74
+ were excluded from calculations. Add them to legacy_prices.yml.
75
+
76
+ List of flavors with unknown properties:
77
+ <%= @r.analyzer.unknown_zone_counts.keys.map{|k| sprintf(" %20s", k) }.join("\n").red %>
78
+ <%= SEPARATOR %>
79
+
80
+ <%- end -%>
70
81
  ZONE COUNTS:
71
82
  Total # of zones <%= sprintf("%20d", @r.zones).cyan %>
72
83
  <%- if @r.reserve? -%>
@@ -100,7 +111,7 @@ YEARLY COSTS:
100
111
  <%- if @r.reserve? -%>
101
112
  On demand yearly <%= @f.format_price(@r.analyzer.yearly_overages_price, 20).yellow %>
102
113
  Reserve prepay one time fee <%= @f.format_price(@r.commit.upfront_price, 20).green %>
103
- Reserve monthly fees <%= @f.format_price(@r.commit.monthly_price * 12, 20).green %>
114
+ Reserve sum of all monthly fees <%= @f.format_price(@r.commit.monthly_price * 12, 20).green %>
104
115
  <%= "___________".cyan %>
105
116
  Total <%= @f.format_price(@r.analyzer.yearly_total, 20).cyan %>
106
117
  <%- else -%>
@@ -1,7 +1,7 @@
1
1
  module Joyent
2
2
  module Cloud
3
3
  module Pricing
4
- VERSION = '1.0.6'
4
+ VERSION = '1.0.7'
5
5
  end
6
6
  end
7
7
  end
@@ -2,41 +2,44 @@ require 'spec_helper'
2
2
 
3
3
  describe 'Joyent::Cloud::Pricing::Analyzer' do
4
4
 
5
- let(:flavors) { %w(
6
- g3-highcpu-16-smartos
7
- g3-highcpu-16-smartos
8
- g3-standard-30-smartos
9
- g3-highcpu-32-smartos-cc
10
- g3-highcpu-32-smartos-cc
11
- g3-highcpu-32-smartos-cc
12
- g3-highcpu-32-smartos-cc
13
- g3-highcpu-32-smartos-cc
14
- g3-highcpu-32-smartos-cc
15
- g3-highcpu-32-smartos-cc
16
- g3-highcpu-32-smartos-cc
17
- g3-highcpu-32-smartos-cc
18
- g3-highcpu-32-smartos-cc
19
- g3-highcpu-32-smartos-cc
20
- g3-highcpu-32-smartos-cc
21
- g3-highcpu-7-smartos
22
- g3-highcpu-7-smartos
23
- g3-highio-60.5-smartos
24
- g3-highio-60.5-smartos
25
- g3-highio-60.5-smartos
26
- g3-highio-60.5-smartos
27
- g3-highmemory-17.125-smartos
28
- g3-highmemory-17.125-smartos
29
- g3-highmemory-17.125-smartos
30
- g3-highmemory-17.125-smartos
31
- g3-highmemory-17.125-smartos
32
- g3-highmemory-17.125-smartos
33
- g3-highmemory-17.125-smartos
34
- g3-highmemory-17.125-smartos
35
- g3-highmemory-17.125-smartos
36
- g3-highmemory-17.125-smartos
37
- g3-highmemory-17.125-smartos
38
- g3-highmemory-17.125-smartos
39
- ) }
5
+ FLAVORS = %w(
6
+ g3-highcpu-16-smartos
7
+ g3-highcpu-16-smartos
8
+ g3-standard-30-smartos
9
+ g3-highcpu-32-smartos-cc
10
+ g3-highcpu-32-smartos-cc
11
+ g3-highcpu-32-smartos-cc
12
+ g3-highcpu-32-smartos-cc
13
+ g3-highcpu-32-smartos-cc
14
+ g3-highcpu-32-smartos-cc
15
+ g3-highcpu-32-smartos-cc
16
+ g3-highcpu-32-smartos-cc
17
+ g3-highcpu-32-smartos-cc
18
+ g3-highcpu-32-smartos-cc
19
+ g3-highcpu-32-smartos-cc
20
+ g3-highcpu-32-smartos-cc
21
+ g3-highcpu-7-smartos
22
+ g3-highcpu-7-smartos
23
+ g3-highio-60.5-smartos
24
+ g3-highio-60.5-smartos
25
+ g3-highio-60.5-smartos
26
+ g3-highio-60.5-smartos
27
+ g3-highmemory-17.125-smartos
28
+ g3-highmemory-17.125-smartos
29
+ g3-highmemory-17.125-smartos
30
+ g3-highmemory-17.125-smartos
31
+ g3-highmemory-17.125-smartos
32
+ g3-highmemory-17.125-smartos
33
+ g3-highmemory-17.125-smartos
34
+ g3-highmemory-17.125-smartos
35
+ g3-highmemory-17.125-smartos
36
+ g3-highmemory-17.125-smartos
37
+ g3-highmemory-17.125-smartos
38
+ g3-highmemory-17.125-smartos
39
+ some-unknown-flavor
40
+ )
41
+
42
+ let(:flavors) { FLAVORS }
40
43
  let(:commit) { Joyent::Cloud::Pricing::Commit.from_yaml 'spec/fixtures/commit.yml' }
41
44
  let(:analyzer) { Joyent::Cloud::Pricing::Analyzer.new(commit, flavors) }
42
45
 
@@ -53,7 +56,8 @@ describe 'Joyent::Cloud::Pricing::Analyzer' do
53
56
  :'g3-highcpu-7-smartos' => 2,
54
57
  :'g3-highio-60.5-smartos' => 4,
55
58
  :'g3-highmemory-17.125-smartos' => 12,
56
- :'g3-standard-30-smartos' => 1
59
+ :'g3-standard-30-smartos' => 1,
60
+ :'some-unknown-flavor' => 1
57
61
  })
58
62
  end
59
63
 
@@ -73,7 +77,8 @@ describe 'Joyent::Cloud::Pricing::Analyzer' do
73
77
  {:'g3-highcpu-16-smartos' => 2,
74
78
  :'g3-highcpu-32-smartos-cc' => 2,
75
79
  :'g3-highcpu-7-smartos' => 2,
76
- :'g3-standard-30-smartos' => 1
80
+ :'g3-standard-30-smartos' => 1,
81
+ :'some-unknown-flavor' => 1
77
82
  })
78
83
  end
79
84
 
@@ -95,4 +100,11 @@ describe 'Joyent::Cloud::Pricing::Analyzer' do
95
100
  expect(analyzer.disk).to eql({total: 28655.0, unreserved: 5807.0, reserved: 24300.0})
96
101
  end
97
102
  end
103
+
104
+ context 'for unknown instances' do
105
+ it 'should return some-unknown-flavor' do
106
+ expect(analyzer.unknown_zone_counts).to eql({ :'some-unknown-flavor' => 1 })
107
+ end
108
+ end
109
+
98
110
  end
@@ -36,6 +36,8 @@ describe 'Joyent::Cloud::Pricing::Reporter' do
36
36
  g3-highmemory-17.125-smartos
37
37
  g3-highmemory-17.125-smartos
38
38
  g3-highmemory-17.125-smartos
39
+ some-fake-flavor-without-pricing
40
+ some-fake-flavor-again
39
41
  ) }
40
42
  let(:commit) { Joyent::Cloud::Pricing::Commit.from_yaml 'spec/fixtures/commit.yml' }
41
43
  let(:reporter) { Joyent::Cloud::Pricing::Reporter.new(commit, flavors) }
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,8 @@ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
3
  require 'rubygems'
4
4
  require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
5
5
  require 'pricing'
6
+ require 'coveralls'
7
+ Coveralls.wear!
6
8
 
7
9
  # Dir['spec/support/**/*.rb'].each { |filename| require_relative "../#{filename}" }
8
10
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: joyent-cloud-pricing
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 1.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Gredeskoul
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-30 00:00:00.000000000 Z
11
+ date: 2014-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: coveralls
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rspec
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -102,6 +116,7 @@ executables: []
102
116
  extensions: []
103
117
  extra_rdoc_files: []
104
118
  files:
119
+ - ".coveralls.yml"
105
120
  - ".gitignore"
106
121
  - ".rspec"
107
122
  - ".travis.yml"