joyent-cloud-pricing 1.0.6 → 1.0.7
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 +4 -4
- data/.coveralls.yml +1 -0
- data/.gitignore +1 -0
- data/README.md +29 -17
- data/joyent-cloud-pricing.gemspec +1 -0
- data/lib/pricing/analyzer.rb +13 -1
- data/lib/pricing/configuration.rb +2 -8
- data/lib/pricing/reporter.rb +14 -3
- data/lib/pricing/version.rb +1 -1
- data/spec/pricing/analyzer_spec.rb +49 -37
- data/spec/pricing/reporter_spec.rb +2 -0
- data/spec/spec_helper.rb +2 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6830b1d71aec26c98b251688edacd2a40448eac1
|
4
|
+
data.tar.gz: bfdeb0a822f1f8f6b15122402c4dbc491a061349
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c8bf089f0fe1f5e7361061ab4dcad2bc10845f64b2bdd92c40a20391910b59bdb8cc47540a5318eb9b656a0aef4552230c04bab1a6c8af5db9a3b40da0be958
|
7
|
+
data.tar.gz: cca584aaaecb758178cf1212a04400e1e8856a1c7c81b04a6b4e7ee6d6910ee137b2cc28da2f9d6e4f638e89fc6fc3f9242d67a4bb7e08a01f841236776267a8
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
[](http://badge.fury.io/rb/joyent-cloud-pricing)
|
2
2
|
[](http://travis-ci.org/kigster/joyent-cloud-pricing)
|
3
3
|
[](https://codeclimate.com/github/kigster/joyent-cloud-pricing)
|
4
|
+
[](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
|
68
|
-
|
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
|
-
|
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
|
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
|
136
|
-
|
137
|
-
|
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
|
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'
|
data/lib/pricing/analyzer.rb
CHANGED
@@ -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)
|
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
|
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
|
-
|
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)
|
data/lib/pricing/reporter.rb
CHANGED
@@ -20,7 +20,7 @@ module Joyent::Cloud::Pricing
|
|
20
20
|
end
|
21
21
|
|
22
22
|
@zones_in_use = zones_in_use
|
23
|
-
@analyzer
|
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.
|
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
|
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 -%>
|
data/lib/pricing/version.rb
CHANGED
@@ -2,41 +2,44 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe 'Joyent::Cloud::Pricing::Analyzer' do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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.
|
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-
|
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"
|