joyent-cloud-pricing 1.0.3 → 1.0.4
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/README.md +19 -3
- data/config/joyent_pricing.yml +309 -45
- data/config/legacy_prices.yml +6 -3
- data/joyent-cloud-pricing.gemspec +6 -6
- data/lib/pricing.rb +10 -9
- data/lib/pricing/analyzer.rb +32 -10
- data/lib/pricing/commit.rb +6 -0
- data/lib/pricing/configuration.rb +13 -4
- data/lib/pricing/flavor.rb +25 -0
- data/lib/pricing/formatter.rb +1 -1
- data/lib/pricing/reporter.rb +36 -21
- data/lib/pricing/scraper.rb +13 -8
- data/lib/pricing/version.rb +1 -1
- data/spec/fixtures/pricing.yml +10 -4
- data/spec/pricing/analyzer_spec.rb +98 -0
- data/spec/pricing/configuration_spec.rb +22 -11
- data/spec/pricing/formatter_spec.rb +20 -19
- data/spec/pricing/reporter_spec.rb +6 -6
- data/spec/pricing/scraper_spec.rb +14 -6
- metadata +4 -3
- data/spec/pricing/analyze_spec.rb +0 -82
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af9e7e7a7f24831b00088ee284035a3ab1c5d385
|
|
4
|
+
data.tar.gz: f7de3d3f2c71529d6a5a9a8fc64fa2ac2f6a0e03
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: de8614e7801059dd5ee1f9886a05c4a1ae750857c26215197a5a7ea3da276556037762415ede75f9cf7652bc8d822eb53b7816217bade8a1b3320a70eac2b786
|
|
7
|
+
data.tar.gz: ee977c931ab860210802396ef2f920169e7610808b9bde394c0eb6d13c724c17716eb99faef8287488c753689c51590d3646b90c21bebd5266f3855e7eb5e9b0
|
data/README.md
CHANGED
|
@@ -70,8 +70,11 @@ Joyent::Cloud::Pricing::Configuration.instance["g3-standard-48-smartos"]
|
|
|
70
70
|
|
|
71
71
|
## Analysis of Commit Pricing
|
|
72
72
|
|
|
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.
|
|
75
|
+
|
|
73
76
|
Reserve pricing is meant to be defined by a YAML file, outside of the gem folder,
|
|
74
|
-
somewhere on the file system. File looks like this
|
|
77
|
+
somewhere on the file system. File looks like this.
|
|
75
78
|
|
|
76
79
|
```yaml
|
|
77
80
|
defaults: &defaults
|
|
@@ -123,8 +126,15 @@ This module is used by ```knife joyent server price``` plugin to calculate prici
|
|
|
123
126
|
reserve discounts.
|
|
124
127
|
|
|
125
128
|
```ruby
|
|
126
|
-
current_zone_list = %w(
|
|
127
|
-
|
|
129
|
+
current_zone_list = %w(
|
|
130
|
+
g3-highcpu-8-smartos
|
|
131
|
+
g3-highcpu-8-smartos
|
|
132
|
+
# ....
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
reporter = Joyent::Cloud::Pricing::Reporter.new(
|
|
136
|
+
'config/reserve-commit.yml',
|
|
137
|
+
current_zone_list)
|
|
128
138
|
|
|
129
139
|
puts reporter.render
|
|
130
140
|
```
|
|
@@ -175,6 +185,12 @@ YEARLY COSTS:
|
|
|
175
185
|
4. Push to the branch (`git push origin my-new-feature`)
|
|
176
186
|
5. Create new Pull Request
|
|
177
187
|
|
|
188
|
+
## Disclaimer
|
|
189
|
+
|
|
190
|
+
This gem is provided as a convenience tool in understanding and comparing cloud pricing. No warranties,
|
|
191
|
+
explicit or implied, are made in relation to correctness or accuracy of the calculations provided by this
|
|
192
|
+
library. Use at your own risk.
|
|
193
|
+
|
|
178
194
|
## Author
|
|
179
195
|
|
|
180
196
|
Konstantin Gredeskoul, [@kig on twitter](http://twitter.com/kig), [@kigster on github](http://github.com/kigster)
|
data/config/joyent_pricing.yml
CHANGED
|
@@ -1,47 +1,311 @@
|
|
|
1
1
|
---
|
|
2
|
-
:date: '2014-03-
|
|
2
|
+
:date: '2014-03-30 00:02:20 -0700'
|
|
3
3
|
:pricing:
|
|
4
|
-
:g3-standard-0.625-smartos:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
:g3-standard-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
:g3-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
:g3-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
:g3-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
:g3-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
:g3-
|
|
47
|
-
|
|
4
|
+
:g3-standard-0.625-smartos:
|
|
5
|
+
:name: g3-standard-0.625-smartos
|
|
6
|
+
:os: SmartOS
|
|
7
|
+
:cost: 0.02
|
|
8
|
+
:cpus: 0.15
|
|
9
|
+
:disk: 20
|
|
10
|
+
:ram: 0.625
|
|
11
|
+
:g3-standard-1.75-smartos:
|
|
12
|
+
:name: g3-standard-1.75-smartos
|
|
13
|
+
:os: SmartOS
|
|
14
|
+
:cost: 0.056
|
|
15
|
+
:cpus: 1.0
|
|
16
|
+
:disk: 56
|
|
17
|
+
:ram: 1.75
|
|
18
|
+
:g3-standard-3.75-smartos:
|
|
19
|
+
:name: g3-standard-3.75-smartos
|
|
20
|
+
:os: SmartOS
|
|
21
|
+
:cost: 0.12
|
|
22
|
+
:cpus: 1.0
|
|
23
|
+
:disk: 123
|
|
24
|
+
:ram: 3.75
|
|
25
|
+
:g3-standard-7.5-smartos:
|
|
26
|
+
:name: g3-standard-7.5-smartos
|
|
27
|
+
:os: SmartOS
|
|
28
|
+
:cost: 0.24
|
|
29
|
+
:cpus: 2.0
|
|
30
|
+
:disk: 738
|
|
31
|
+
:ram: 7.5
|
|
32
|
+
:g3-standard-15-smartos:
|
|
33
|
+
:name: g3-standard-15-smartos
|
|
34
|
+
:os: SmartOS
|
|
35
|
+
:cost: 0.48
|
|
36
|
+
:cpus: 4.0
|
|
37
|
+
:disk: 1467
|
|
38
|
+
:ram: 15.0
|
|
39
|
+
:g3-standard-30-smartos:
|
|
40
|
+
:name: g3-standard-30-smartos
|
|
41
|
+
:os: SmartOS
|
|
42
|
+
:cost: 0.96
|
|
43
|
+
:cpus: 8.0
|
|
44
|
+
:disk: 1683
|
|
45
|
+
:ram: 30.0
|
|
46
|
+
:g3-standard-48-smartos:
|
|
47
|
+
:name: g3-standard-48-smartos
|
|
48
|
+
:os: SmartOS
|
|
49
|
+
:cost: 1.536
|
|
50
|
+
:cpus: 12.0
|
|
51
|
+
:disk: 1683
|
|
52
|
+
:ram: 48.0
|
|
53
|
+
:g3-standard-64-smartos:
|
|
54
|
+
:name: g3-standard-64-smartos
|
|
55
|
+
:os: SmartOS
|
|
56
|
+
:cost: 2.048
|
|
57
|
+
:cpus: 16.0
|
|
58
|
+
:disk: 2100
|
|
59
|
+
:ram: 64.0
|
|
60
|
+
:g3-standard-80-smartos:
|
|
61
|
+
:name: g3-standard-80-smartos
|
|
62
|
+
:os: SmartOS
|
|
63
|
+
:cost: 2.56
|
|
64
|
+
:cpus: 20.0
|
|
65
|
+
:disk: 2625
|
|
66
|
+
:ram: 80.0
|
|
67
|
+
:g3-standard-96-smartos:
|
|
68
|
+
:name: g3-standard-96-smartos
|
|
69
|
+
:os: SmartOS
|
|
70
|
+
:cost: 3.072
|
|
71
|
+
:cpus: 24.0
|
|
72
|
+
:disk: 3150
|
|
73
|
+
:ram: 96.0
|
|
74
|
+
:g3-standard-128-smartos-cc:
|
|
75
|
+
:name: g3-standard-128-smartos-cc
|
|
76
|
+
:os: SmartOS
|
|
77
|
+
:cost: 4.096
|
|
78
|
+
:cpus: 32.0
|
|
79
|
+
:disk: 4200
|
|
80
|
+
:ram: 128.0
|
|
81
|
+
:g3-highmemory-17.125-smartos:
|
|
82
|
+
:name: g3-highmemory-17.125-smartos
|
|
83
|
+
:os: SmartOS
|
|
84
|
+
:cost: 0.409
|
|
85
|
+
:cpus: 2.0
|
|
86
|
+
:disk: 420
|
|
87
|
+
:ram: 17.125
|
|
88
|
+
:g3-highmemory-34.25-smartos:
|
|
89
|
+
:name: g3-highmemory-34.25-smartos
|
|
90
|
+
:os: SmartOS
|
|
91
|
+
:cost: 0.817
|
|
92
|
+
:cpus: 4.0
|
|
93
|
+
:disk: 843
|
|
94
|
+
:ram: 34.25
|
|
95
|
+
:g3-highmemory-68.375-smartos:
|
|
96
|
+
:name: g3-highmemory-68.375-smartos
|
|
97
|
+
:os: SmartOS
|
|
98
|
+
:cost: 1.63
|
|
99
|
+
:cpus: 8.0
|
|
100
|
+
:disk: 1122
|
|
101
|
+
:ram: 68.375
|
|
102
|
+
:g3-highmemory-144-smartos:
|
|
103
|
+
:name: g3-highmemory-144-smartos
|
|
104
|
+
:os: SmartOS
|
|
105
|
+
:cost: 3.433
|
|
106
|
+
:cpus: 18.0
|
|
107
|
+
:disk: 2363
|
|
108
|
+
:ram: 144.0
|
|
109
|
+
:g3-highmemory-256-smartos-cc:
|
|
110
|
+
:name: g3-highmemory-256-smartos-cc
|
|
111
|
+
:os: SmartOS
|
|
112
|
+
:cost: 6.102
|
|
113
|
+
:cpus: 32.0
|
|
114
|
+
:disk: 4200
|
|
115
|
+
:ram: 256.0
|
|
116
|
+
:g3-highcpu-1.75-smartos:
|
|
117
|
+
:name: g3-highcpu-1.75-smartos
|
|
118
|
+
:os: SmartOS
|
|
119
|
+
:cost: 0.127
|
|
120
|
+
:cpus: 2.0
|
|
121
|
+
:disk: 75
|
|
122
|
+
:ram: 1.75
|
|
123
|
+
:g3-highcpu-7-smartos:
|
|
124
|
+
:name: g3-highcpu-7-smartos
|
|
125
|
+
:os: SmartOS
|
|
126
|
+
:cost: 0.508
|
|
127
|
+
:cpus: 7.0
|
|
128
|
+
:disk: 262
|
|
129
|
+
:ram: 7.0
|
|
130
|
+
:g3-highcpu-16-smartos:
|
|
131
|
+
:name: g3-highcpu-16-smartos
|
|
132
|
+
:os: SmartOS
|
|
133
|
+
:cost: 1.16
|
|
134
|
+
:cpus: 16.0
|
|
135
|
+
:disk: 600
|
|
136
|
+
:ram: 16.0
|
|
137
|
+
:g3-highcpu-24-smartos:
|
|
138
|
+
:name: g3-highcpu-24-smartos
|
|
139
|
+
:os: SmartOS
|
|
140
|
+
:cost: 1.739
|
|
141
|
+
:cpus: 24.0
|
|
142
|
+
:disk: 900
|
|
143
|
+
:ram: 24.0
|
|
144
|
+
:g3-highcpu-32-smartos-cc:
|
|
145
|
+
:name: g3-highcpu-32-smartos-cc
|
|
146
|
+
:os: SmartOS
|
|
147
|
+
:cost: 2.319
|
|
148
|
+
:cpus: 32.0
|
|
149
|
+
:disk: 1200
|
|
150
|
+
:ram: 32.0
|
|
151
|
+
:g3-highio-15-smartos:
|
|
152
|
+
:name: g3-highio-15-smartos
|
|
153
|
+
:os: SmartOS
|
|
154
|
+
:cost: 0.76
|
|
155
|
+
:cpus: 2.0
|
|
156
|
+
:disk: 360
|
|
157
|
+
:ram: 15.0
|
|
158
|
+
:g3-highio-30-smartos:
|
|
159
|
+
:name: g3-highio-30-smartos
|
|
160
|
+
:os: SmartOS
|
|
161
|
+
:cost: 1.52
|
|
162
|
+
:cpus: 4.0
|
|
163
|
+
:disk: 725
|
|
164
|
+
:ram: 30.0
|
|
165
|
+
:g3-highio-60.5-smartos:
|
|
166
|
+
:name: g3-highio-60.5-smartos
|
|
167
|
+
:os: SmartOS
|
|
168
|
+
:cost: 3.067
|
|
169
|
+
:cpus: 8.0
|
|
170
|
+
:disk: 1452
|
|
171
|
+
:ram: 60.5
|
|
172
|
+
:g3-highio-128-smartos:
|
|
173
|
+
:name: g3-highio-128-smartos
|
|
174
|
+
:os: SmartOS
|
|
175
|
+
:cost: 6.488
|
|
176
|
+
:cpus: 16.0
|
|
177
|
+
:disk: 3072
|
|
178
|
+
:ram: 128.0
|
|
179
|
+
:g3-highio-256-smartos-cc:
|
|
180
|
+
:name: g3-highio-256-smartos-cc
|
|
181
|
+
:os: SmartOS
|
|
182
|
+
:cost: 12.976
|
|
183
|
+
:cpus: 32.0
|
|
184
|
+
:disk: 6144
|
|
185
|
+
:ram: 256.0
|
|
186
|
+
:g3-highstorage-32-smartos:
|
|
187
|
+
:name: g3-highstorage-32-smartos
|
|
188
|
+
:os: SmartOS
|
|
189
|
+
:cost: 0.863
|
|
190
|
+
:cpus: 8.0
|
|
191
|
+
:disk: 7680
|
|
192
|
+
:ram: 32.0
|
|
193
|
+
:g3-highstorage-64-smartos:
|
|
194
|
+
:name: g3-highstorage-64-smartos
|
|
195
|
+
:os: SmartOS
|
|
196
|
+
:cost: 1.726
|
|
197
|
+
:cpus: 16.0
|
|
198
|
+
:disk: 15360
|
|
199
|
+
:ram: 64.0
|
|
200
|
+
:g3-highstorage-128-smartos-cc:
|
|
201
|
+
:name: g3-highstorage-128-smartos-cc
|
|
202
|
+
:os: SmartOS
|
|
203
|
+
:cost: 3.451
|
|
204
|
+
:cpus: 32.0
|
|
205
|
+
:disk: 30720
|
|
206
|
+
:ram: 128.0
|
|
207
|
+
:g3-standard-0.625-kvm:
|
|
208
|
+
:name: g3-standard-0.625-kvm
|
|
209
|
+
:os: Linux
|
|
210
|
+
:cost: 0.02
|
|
211
|
+
:cpus: 0.15
|
|
212
|
+
:disk: 20
|
|
213
|
+
:ram: 0.625
|
|
214
|
+
:g3-standard-1.75-kvm:
|
|
215
|
+
:name: g3-standard-1.75-kvm
|
|
216
|
+
:os: Linux
|
|
217
|
+
:cost: 0.056
|
|
218
|
+
:cpus: 1.0
|
|
219
|
+
:disk: 56
|
|
220
|
+
:ram: 1.75
|
|
221
|
+
:g3-standard-3.75-kvm:
|
|
222
|
+
:name: g3-standard-3.75-kvm
|
|
223
|
+
:os: Linux
|
|
224
|
+
:cost: 0.12
|
|
225
|
+
:cpus: 1.0
|
|
226
|
+
:disk: 123
|
|
227
|
+
:ram: 3.75
|
|
228
|
+
:g3-standard-7.5-kvm:
|
|
229
|
+
:name: g3-standard-7.5-kvm
|
|
230
|
+
:os: Linux
|
|
231
|
+
:cost: 0.24
|
|
232
|
+
:cpus: 2.0
|
|
233
|
+
:disk: 738
|
|
234
|
+
:ram: 7.5
|
|
235
|
+
:g3-standard-15-kvm:
|
|
236
|
+
:name: g3-standard-15-kvm
|
|
237
|
+
:os: Linux
|
|
238
|
+
:cost: 0.48
|
|
239
|
+
:cpus: 4.0
|
|
240
|
+
:disk: 1467
|
|
241
|
+
:ram: 15.0
|
|
242
|
+
:g3-standard-30-kvm:
|
|
243
|
+
:name: g3-standard-30-kvm
|
|
244
|
+
:os: Linux
|
|
245
|
+
:cost: 0.96
|
|
246
|
+
:cpus: 8.0
|
|
247
|
+
:disk: 1683
|
|
248
|
+
:ram: 30.0
|
|
249
|
+
:g3-highmemory-17.125-kvm:
|
|
250
|
+
:name: g3-highmemory-17.125-kvm
|
|
251
|
+
:os: Linux
|
|
252
|
+
:cost: 0.409
|
|
253
|
+
:cpus: 2.0
|
|
254
|
+
:disk: 420
|
|
255
|
+
:ram: 17.125
|
|
256
|
+
:g3-highmemory-34.25-kvm:
|
|
257
|
+
:name: g3-highmemory-34.25-kvm
|
|
258
|
+
:os: Linux
|
|
259
|
+
:cost: 0.817
|
|
260
|
+
:cpus: 4.0
|
|
261
|
+
:disk: 843
|
|
262
|
+
:ram: 34.25
|
|
263
|
+
:g3-highmemory-68.375-kvm:
|
|
264
|
+
:name: g3-highmemory-68.375-kvm
|
|
265
|
+
:os: Linux
|
|
266
|
+
:cost: 1.63
|
|
267
|
+
:cpus: 8.0
|
|
268
|
+
:disk: 1122
|
|
269
|
+
:ram: 68.375
|
|
270
|
+
:g3-highcpu-1.75-kvm:
|
|
271
|
+
:name: g3-highcpu-1.75-kvm
|
|
272
|
+
:os: Linux
|
|
273
|
+
:cost: 0.127
|
|
274
|
+
:cpus: 2.0
|
|
275
|
+
:disk: 75
|
|
276
|
+
:ram: 1.75
|
|
277
|
+
:g3-highcpu-7-kvm:
|
|
278
|
+
:name: g3-highcpu-7-kvm
|
|
279
|
+
:os: Linux
|
|
280
|
+
:cost: 0.508
|
|
281
|
+
:cpus: 7.0
|
|
282
|
+
:disk: 262
|
|
283
|
+
:ram: 7.0
|
|
284
|
+
:g3-highio-15-kvm:
|
|
285
|
+
:name: g3-highio-15-kvm
|
|
286
|
+
:os: Linux
|
|
287
|
+
:cost: 0.76
|
|
288
|
+
:cpus: 2.0
|
|
289
|
+
:disk: 360
|
|
290
|
+
:ram: 15.0
|
|
291
|
+
:g3-highio-30-kvm:
|
|
292
|
+
:name: g3-highio-30-kvm
|
|
293
|
+
:os: Linux
|
|
294
|
+
:cost: 1.52
|
|
295
|
+
:cpus: 4.0
|
|
296
|
+
:disk: 725
|
|
297
|
+
:ram: 30.0
|
|
298
|
+
:g3-highio-60.5-kvm:
|
|
299
|
+
:name: g3-highio-60.5-kvm
|
|
300
|
+
:os: Linux
|
|
301
|
+
:cost: 3.067
|
|
302
|
+
:cpus: 8.0
|
|
303
|
+
:disk: 1452
|
|
304
|
+
:ram: 60.5
|
|
305
|
+
:g3-highstorage-32-kvm:
|
|
306
|
+
:name: g3-highstorage-32-kvm
|
|
307
|
+
:os: Linux
|
|
308
|
+
:cost: 0.863
|
|
309
|
+
:cpus: 8.0
|
|
310
|
+
:disk: 7680
|
|
311
|
+
:ram: 32.0
|
data/config/legacy_prices.yml
CHANGED
|
@@ -4,20 +4,20 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
4
4
|
require 'pricing/version'
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name =
|
|
7
|
+
spec.name = 'joyent-cloud-pricing'
|
|
8
8
|
spec.version = Joyent::Cloud::Pricing::VERSION
|
|
9
|
-
spec.authors = [
|
|
10
|
-
spec.email = [
|
|
9
|
+
spec.authors = ['Konstantin Gredeskoul']
|
|
10
|
+
spec.email = ['kigster@gmail.com']
|
|
11
11
|
spec.summary = %q{Tools for calculating monthly and yearly price of infrastructure hosted on Joyent Public Cloud.}
|
|
12
12
|
spec.description = %q{Various set of tools and helpers to calculate infrastructure footprint and cost on Joyent Cloud. Supports commit discounts.}
|
|
13
|
-
spec.homepage =
|
|
14
|
-
spec.license =
|
|
13
|
+
spec.homepage = 'https://github.com/kigster/joyent-cloud-pricing'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
15
|
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
19
|
|
|
20
|
-
spec.require_paths = [
|
|
20
|
+
spec.require_paths = ['lib']
|
|
21
21
|
|
|
22
22
|
spec.add_dependency 'nokogiri'
|
|
23
23
|
spec.add_dependency 'colored'
|
data/lib/pricing.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require 'pricing/version'
|
|
2
|
+
require 'pricing/symbolize_keys'
|
|
3
3
|
|
|
4
4
|
module Joyent
|
|
5
5
|
module Cloud
|
|
@@ -15,10 +15,11 @@ module Joyent
|
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
require
|
|
19
|
-
require
|
|
20
|
-
require
|
|
21
|
-
require
|
|
22
|
-
require
|
|
23
|
-
require
|
|
24
|
-
require
|
|
18
|
+
require 'pricing/flavor'
|
|
19
|
+
require 'pricing/helpers'
|
|
20
|
+
require 'pricing/configuration'
|
|
21
|
+
require 'pricing/scraper'
|
|
22
|
+
require 'pricing/formatter'
|
|
23
|
+
require 'pricing/commit'
|
|
24
|
+
require 'pricing/analyzer'
|
|
25
|
+
require 'pricing/reporter'
|
data/lib/pricing/analyzer.rb
CHANGED
|
@@ -3,35 +3,35 @@ require_relative 'commit'
|
|
|
3
3
|
module Joyent::Cloud::Pricing
|
|
4
4
|
class Analyzer
|
|
5
5
|
|
|
6
|
-
attr_accessor :commit, :
|
|
6
|
+
attr_accessor :commit, :zone_counts
|
|
7
7
|
|
|
8
8
|
def initialize(commit, flavors = [])
|
|
9
9
|
@commit = commit
|
|
10
|
-
@
|
|
10
|
+
@zone_counts = count_dupes(flavors).symbolize_keys
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
# Zones that are not on commit
|
|
14
|
-
def
|
|
14
|
+
def excess_zone_counts
|
|
15
15
|
h = {}
|
|
16
|
-
|
|
16
|
+
zone_counts.each_pair { |flavor, count| diff = count - quantity_for(flavor); h[flavor] = diff if diff > 0 }
|
|
17
17
|
h
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
# Zones that are committed, but do not exist
|
|
21
|
-
def
|
|
21
|
+
def over_reserved_zone_counts
|
|
22
22
|
h = {}
|
|
23
|
-
|
|
23
|
+
zone_counts.each_pair { |flavor, count| diff = count - quantity_for(flavor); h[flavor] = -diff if diff < 0 }
|
|
24
24
|
h
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
# Non-discounted full price
|
|
28
28
|
def monthly_full_price
|
|
29
|
-
monthly_full_price_for(
|
|
29
|
+
monthly_full_price_for(zone_counts)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
# Excess zones cost this much
|
|
33
33
|
def monthly_overages_price
|
|
34
|
-
monthly_full_price_for(
|
|
34
|
+
monthly_full_price_for(excess_zone_counts)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
# Monthly for all of the commits
|
|
@@ -49,7 +49,7 @@ module Joyent::Cloud::Pricing
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def monthly_full_price_for zones
|
|
52
|
-
|
|
52
|
+
count_for_all zones do |flavor|
|
|
53
53
|
pricing.monthly(flavor)
|
|
54
54
|
end
|
|
55
55
|
end
|
|
@@ -74,9 +74,31 @@ module Joyent::Cloud::Pricing
|
|
|
74
74
|
100 * (yearly_full_price - yearly_total) / yearly_full_price
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
+
def cpus
|
|
78
|
+
count_props(:cpus)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def ram
|
|
82
|
+
count_props(:ram)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def disk
|
|
86
|
+
count_props(:disk)
|
|
87
|
+
end
|
|
88
|
+
|
|
77
89
|
private
|
|
78
90
|
|
|
79
|
-
def
|
|
91
|
+
def count_props(operation)
|
|
92
|
+
results = [ zone_counts, excess_zone_counts, commit.flavor_counts ].map do |list|
|
|
93
|
+
count_for_all list do |flavor|
|
|
94
|
+
pricing.flavor(flavor).send(operation)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
{ total: results[0], unreserved: results[1], reserved: results[2] }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def count_for_all zones, &block
|
|
80
102
|
zones.keys.inject(0) do |sum, flavor|
|
|
81
103
|
sum += zones[flavor] * yield(flavor); sum
|
|
82
104
|
end.round(2)
|
data/lib/pricing/commit.rb
CHANGED
|
@@ -44,6 +44,12 @@ module Joyent::Cloud::Pricing
|
|
|
44
44
|
reserves.empty? ? 0 : reserves.values.first.years
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
def flavor_counts
|
|
48
|
+
zone_list = {}
|
|
49
|
+
reserves.keys.each{|zone| zone_list[zone] = reserves[zone].quantity}
|
|
50
|
+
zone_list
|
|
51
|
+
end
|
|
52
|
+
|
|
47
53
|
private
|
|
48
54
|
|
|
49
55
|
def sum_of
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'yaml'
|
|
2
2
|
require_relative 'helpers'
|
|
3
|
+
require_relative 'flavor'
|
|
3
4
|
|
|
4
5
|
module Joyent::Cloud::Pricing
|
|
5
6
|
class Configuration
|
|
@@ -39,12 +40,20 @@ module Joyent::Cloud::Pricing
|
|
|
39
40
|
@config = hash.symbolize_keys
|
|
40
41
|
end
|
|
41
42
|
|
|
42
|
-
def
|
|
43
|
-
|
|
43
|
+
def cost(flavor)
|
|
44
|
+
f = config[flavor.to_sym]
|
|
45
|
+
f.nil? ? nil : f[:cost]
|
|
44
46
|
end
|
|
45
47
|
|
|
46
|
-
def
|
|
47
|
-
f =
|
|
48
|
+
def flavor(flavor)
|
|
49
|
+
f = config[flavor.to_sym]
|
|
50
|
+
return nil if f.nil?
|
|
51
|
+
f.delete(:name) # name is saved in YAML, but it's not in Flavor class hash attributes
|
|
52
|
+
Flavor.new(flavor, f)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def monthly(flavor)
|
|
56
|
+
f = self.cost(flavor)
|
|
48
57
|
if f.nil?
|
|
49
58
|
STDERR.puts "WARNING: can't find flavor #{flavor}, assuming 0"
|
|
50
59
|
0
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Joyent::Cloud::Pricing
|
|
2
|
+
class Flavor
|
|
3
|
+
attr_accessor :name, :os, :cost, :ram, :cpus, :disk
|
|
4
|
+
|
|
5
|
+
def initialize(name, os: os, cost: cost, ram: ram, cpus: cpus, disk: disk)
|
|
6
|
+
@name = name
|
|
7
|
+
@os = os
|
|
8
|
+
@cost = (cost == 'N/A') ? nil : cost.to_f
|
|
9
|
+
@cpus = cpus.to_f
|
|
10
|
+
@disk = disk.to_i
|
|
11
|
+
@ram = ram.to_f
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_h
|
|
15
|
+
{
|
|
16
|
+
name: name,
|
|
17
|
+
os: os,
|
|
18
|
+
cost: cost,
|
|
19
|
+
cpus: cpus,
|
|
20
|
+
disk: disk,
|
|
21
|
+
ram: ram
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/pricing/formatter.rb
CHANGED
data/lib/pricing/reporter.rb
CHANGED
|
@@ -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
|
|
8
|
+
attr_accessor :commit, :zones_in_use, :analyzer, :formatter, :print_zone_list
|
|
9
9
|
|
|
10
10
|
def initialize(commit = COMMIT, zones_in_use = [])
|
|
11
11
|
@commit = case commit
|
|
@@ -20,8 +20,9 @@ module Joyent::Cloud::Pricing
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
@zones_in_use = zones_in_use
|
|
23
|
-
@analyzer = Analyzer.new(@commit, @zones_in_use)
|
|
24
|
-
@formatter = Formatter.new(pricing.config)
|
|
23
|
+
@analyzer = Joyent::Cloud::Pricing::Analyzer.new(@commit, @zones_in_use)
|
|
24
|
+
@formatter = Joyent::Cloud::Pricing::Formatter.new(pricing.config)
|
|
25
|
+
@print_zone_list = true
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
def render
|
|
@@ -39,11 +40,11 @@ module Joyent::Cloud::Pricing
|
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
def pricing
|
|
42
|
-
Configuration.instance
|
|
43
|
+
Joyent::Cloud::Pricing::Configuration.instance
|
|
43
44
|
end
|
|
44
45
|
|
|
45
46
|
def excess_zones
|
|
46
|
-
zones = analyzer.
|
|
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
48
|
zones
|
|
48
49
|
end
|
|
49
50
|
|
|
@@ -55,30 +56,39 @@ module Joyent::Cloud::Pricing
|
|
|
55
56
|
end.join("\n")
|
|
56
57
|
end
|
|
57
58
|
|
|
59
|
+
def zone_props_to_string(prop_type, width, suffix = '', divide_by = 1)
|
|
60
|
+
props = analyzer.send(prop_type)
|
|
61
|
+
[ props[:reserved], props[:unreserved], props[:total] ].map do |value|
|
|
62
|
+
sprintf("%#{width}d#{suffix}", value / divide_by)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
58
66
|
SEPARATOR = ('.' * 65).cyan
|
|
67
|
+
PROPS_FORMAT= '%20d %20d %20d'
|
|
59
68
|
REPORT_ASCII = <<ASCII
|
|
60
69
|
|
|
61
70
|
ZONE COUNTS:
|
|
62
71
|
Total # of zones <%= sprintf("%20d", @r.zones).cyan %>
|
|
63
72
|
<%- if @r.reserve? -%>
|
|
64
73
|
Total # of reserved zones <%= sprintf("%20d", @r.commit.total_zones).green %>
|
|
65
|
-
Total # of reserved but absent zones <%= value = sprintf("%20d", @r.analyzer.
|
|
66
|
-
Reserve Pricing Term/Duration (years) <%= sprintf("%20d", @r.commit.years || 0).blue %>
|
|
67
|
-
<%= SEPARATOR %>
|
|
68
|
-
|
|
69
|
-
RESERVE UPFRONT COST:
|
|
70
|
-
Reserve Pricing Upfront Payments <%= @f.format_price(@r.commit.upfront_price, 20).green %>
|
|
74
|
+
Total # of reserved but absent zones <%= value = sprintf("%20d", @r.analyzer.over_reserved_zone_counts.size || 0); value == "0" ? value.blue : value.red %>
|
|
71
75
|
<%- end -%>
|
|
76
|
+
|
|
77
|
+
Resources in use:<%= sprintf('%14s %15s %15s', 'Reserved', 'On-Demand', 'Total') %>
|
|
78
|
+
CPUs <%= props = @r.zone_props_to_string(:cpus, 16); props[0].green + props[1].yellow + props[2].cyan %>
|
|
79
|
+
RAM <%= props = @r.zone_props_to_string(:ram, 15, 'G'); props[0].green + props[1].yellow + props[2].cyan %>
|
|
80
|
+
DISK <%= props = @r.zone_props_to_string(:disk, 15, 'T', 1024); props[0].green + props[1].yellow + props[2].cyan %>
|
|
72
81
|
<%= SEPARATOR %>
|
|
73
82
|
|
|
74
83
|
MONTHLY COSTS:
|
|
75
|
-
|
|
84
|
+
<%- if @r.print_zone_list -%>
|
|
85
|
+
List of on-demand flavors by price <%= @r.reserve? ? "(in excess of reserve)" : "" %>
|
|
76
86
|
<%= @r.excess_zone_list %>
|
|
77
87
|
<%= "___________".yellow %>
|
|
78
|
-
|
|
79
|
-
|
|
88
|
+
<%- end -%>
|
|
89
|
+
On demand monthly <%= @f.format_price(@r.analyzer.monthly_overages_price, 20).yellow %>
|
|
80
90
|
<%- if @r.reserve? -%>
|
|
81
|
-
Zones
|
|
91
|
+
Zones under reserve pricing <%= @f.format_price(@r.commit.monthly_price, 20).green %>
|
|
82
92
|
<%- end -%>
|
|
83
93
|
<%- if @r.reserve? -%>
|
|
84
94
|
<%= "___________".cyan %>
|
|
@@ -88,16 +98,21 @@ MONTHLY COSTS:
|
|
|
88
98
|
|
|
89
99
|
YEARLY COSTS:
|
|
90
100
|
<%- if @r.reserve? -%>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
Reserve Yearly <%= @f.format_price(@r.commit.yearly_price, 20).green %>
|
|
95
|
-
On Demand Yearly <%= @f.format_price(@r.analyzer.yearly_overages_price, 20).yellow %>
|
|
101
|
+
On demand yearly <%= @f.format_price(@r.analyzer.yearly_overages_price, 20).yellow %>
|
|
102
|
+
Commit prepay one time fee <%= @f.format_price(@r.commit.upfront_price, 20).green %>
|
|
103
|
+
Reserve yearly <%= @f.format_price(@r.commit.yearly_price, 20).green %>
|
|
96
104
|
<%= "___________".cyan %>
|
|
97
105
|
Total <%= @f.format_price(@r.analyzer.yearly_total, 20).cyan %>
|
|
98
106
|
<%- else -%>
|
|
99
|
-
On
|
|
107
|
+
On demand yearly <%= @f.format_price(@r.analyzer.yearly_full_price, 20).cyan %>
|
|
100
108
|
<%- end -%>
|
|
109
|
+
<%- if @r.reserve? -%>
|
|
110
|
+
|
|
111
|
+
YEARLY RESERVE SAVINGS:
|
|
112
|
+
Savings due to reserved pricing <%= @f.format_price(@r.analyzer.yearly_savings, 20).green %>
|
|
113
|
+
Savings % <%= sprintf("%19d", @r.analyzer.yearly_savings_percent).green + '%'.green %>
|
|
114
|
+
<%- end -%>
|
|
115
|
+
<%= SEPARATOR %>
|
|
101
116
|
|
|
102
117
|
ASCII
|
|
103
118
|
|
data/lib/pricing/scraper.rb
CHANGED
|
@@ -12,15 +12,14 @@ module Joyent::Cloud::Pricing
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
class Parser < Struct.new(:doc)
|
|
15
|
-
class PriceTuple < Struct.new(:os, :cost, :flavor); end
|
|
16
15
|
|
|
17
16
|
def result
|
|
18
17
|
config = Hash.new
|
|
19
|
-
self.doc.css(
|
|
20
|
-
|
|
21
|
-
next if
|
|
22
|
-
next if
|
|
23
|
-
config[
|
|
18
|
+
self.doc.css('ul.full-specs').each do |ul|
|
|
19
|
+
flavor = extract_price(ul)
|
|
20
|
+
next if flavor.cost.nil?
|
|
21
|
+
next if flavor.name =~ /kvm/ && flavor.os !~ /linux/i
|
|
22
|
+
config[flavor.name]= flavor.to_h
|
|
24
23
|
end
|
|
25
24
|
config
|
|
26
25
|
end
|
|
@@ -30,8 +29,14 @@ module Joyent::Cloud::Pricing
|
|
|
30
29
|
def extract_price(ul)
|
|
31
30
|
lis = ul.css("span").map(&:content)
|
|
32
31
|
# grab last two <li> elements in each <ul class="full-spec"> block
|
|
33
|
-
#
|
|
34
|
-
|
|
32
|
+
# and first few for cpu/ram/disk
|
|
33
|
+
# note: this obviously depends on Joyent website markup and is subject to break.
|
|
34
|
+
Flavor.new(lis[-1], # flavor
|
|
35
|
+
os: lis[-3],
|
|
36
|
+
cost: lis[-2].gsub(/^\$/, ''),
|
|
37
|
+
ram: lis[0],
|
|
38
|
+
cpus: lis[1],
|
|
39
|
+
disk: lis[2])
|
|
35
40
|
end
|
|
36
41
|
end
|
|
37
42
|
end
|
data/lib/pricing/version.rb
CHANGED
data/spec/fixtures/pricing.yml
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
:date: '2014-03-23 21:51:04 -0700'
|
|
3
3
|
:pricing:
|
|
4
|
-
g3-standard-0.625-smartos:
|
|
5
|
-
|
|
6
|
-
g3-standard-
|
|
7
|
-
|
|
4
|
+
g3-standard-0.625-smartos:
|
|
5
|
+
:cost: 0.02
|
|
6
|
+
g3-standard-30-kvm:
|
|
7
|
+
:cost: 0.96
|
|
8
|
+
g3-standard-48-smartos:
|
|
9
|
+
:cost: 1.536
|
|
10
|
+
:ram: 12
|
|
11
|
+
:cpus: 16.0
|
|
12
|
+
g3-standard-64-smartos:
|
|
13
|
+
:cost: 2.048
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe 'Joyent::Cloud::Pricing::Analyzer' do
|
|
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
|
+
) }
|
|
40
|
+
let(:commit) { Joyent::Cloud::Pricing::Commit.from_yaml 'spec/fixtures/commit.yml' }
|
|
41
|
+
let(:analyzer) { Joyent::Cloud::Pricing::Analyzer.new(commit, flavors) }
|
|
42
|
+
|
|
43
|
+
# need to have pricing so that it reloads from real price TODO: fix this
|
|
44
|
+
before do
|
|
45
|
+
Joyent::Cloud::Pricing::Configuration.from_yaml
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it '#initialize' do
|
|
49
|
+
expect(analyzer.zone_counts).to_not be_empty
|
|
50
|
+
expect(analyzer.zone_counts).to eql (
|
|
51
|
+
{:'g3-highcpu-16-smartos' => 2,
|
|
52
|
+
:'g3-highcpu-32-smartos-cc' => 12,
|
|
53
|
+
:'g3-highcpu-7-smartos' => 2,
|
|
54
|
+
:'g3-highio-60.5-smartos' => 4,
|
|
55
|
+
:'g3-highmemory-17.125-smartos' => 12,
|
|
56
|
+
:'g3-standard-30-smartos' => 1
|
|
57
|
+
})
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context 'monthly prices' do
|
|
61
|
+
it '#monthly_full_price' do
|
|
62
|
+
expect(analyzer.monthly_full_price).to eql(35496.0)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it '#monthly_overages_price' do
|
|
66
|
+
expect(analyzer.monthly_overages_price).to eql(6432.48)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'zone frequency counts' do
|
|
71
|
+
it '#excess_zone_counts' do
|
|
72
|
+
expect(analyzer.excess_zone_counts).to eql(
|
|
73
|
+
{:'g3-highcpu-16-smartos' => 2,
|
|
74
|
+
:'g3-highcpu-32-smartos-cc' => 2,
|
|
75
|
+
:'g3-highcpu-7-smartos' => 2,
|
|
76
|
+
:'g3-standard-30-smartos' => 1
|
|
77
|
+
})
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it '#over_reserved_zone_counts' do
|
|
81
|
+
expect(analyzer.over_reserved_zone_counts).to eql({:'g3-highio-60.5-smartos' => 1})
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context 'reserved and unreserved totals for flavor properties' do
|
|
86
|
+
it '#cpus' do
|
|
87
|
+
expect(analyzer.cpus).to eql({total: 494.0, reserved: 384.0, unreserved: 118.0})
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it '#ram' do
|
|
91
|
+
expect(analyzer.ram).to eql({total: 907.5, unreserved: 140.0, reserved: 828.0})
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it '#disk' do
|
|
95
|
+
expect(analyzer.disk).to eql({total: 28655.0, unreserved: 5807.0, reserved: 24300.0})
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -2,28 +2,28 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
describe 'Joyent::Cloud::Pricing::Configuration' do
|
|
4
4
|
expected_prices = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
'g3-standard-48-smartos' => 1.536,
|
|
6
|
+
'g3-standard-0.625-smartos' => 0.02,
|
|
7
|
+
'g3-standard-30-kvm' => 0.960,
|
|
8
|
+
'g3-standard-8-smartos' => 0.26,
|
|
9
|
+
'g3-highcpu-8-smartos' => 0.58,
|
|
10
|
+
'g3-standard-0.5-smartos' => 0.016
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
let(:config) {
|
|
14
14
|
Joyent::Cloud::Pricing::Configuration.from_yaml 'spec/fixtures/pricing.yml'
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
context
|
|
17
|
+
context '#from_yaml' do
|
|
18
18
|
expected_prices.keys.each do |flavor|
|
|
19
19
|
it "should load pricing for #{flavor}" do
|
|
20
|
-
expect(config
|
|
20
|
+
expect(config.cost(flavor)).to eql(expected_prices[flavor])
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
context
|
|
26
|
-
it
|
|
25
|
+
context '#instance' do
|
|
26
|
+
it 'should be able to create new instance, but remember the last once' do
|
|
27
27
|
c1 = Joyent::Cloud::Pricing::Configuration.from_yaml 'spec/fixtures/pricing.yml'
|
|
28
28
|
c2 = Joyent::Cloud::Pricing::Configuration.from_yaml 'spec/fixtures/pricing.yml'
|
|
29
29
|
|
|
@@ -31,8 +31,19 @@ describe 'Joyent::Cloud::Pricing::Configuration' do
|
|
|
31
31
|
expect(Joyent::Cloud::Pricing::Configuration.instance).not_to eql(c1)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
it
|
|
34
|
+
it 'should have instance set' do
|
|
35
35
|
expect(Joyent::Cloud::Pricing::Configuration.instance).not_to be_nil
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
|
+
|
|
39
|
+
context '#flavor' do
|
|
40
|
+
it 'should properly instantiate Flavor instance from hash' do
|
|
41
|
+
flavor = config.flavor 'g3-standard-48-smartos'
|
|
42
|
+
expect(flavor.class).to eql(Joyent::Cloud::Pricing::Flavor)
|
|
43
|
+
|
|
44
|
+
expect(flavor.ram).to eql(12.0)
|
|
45
|
+
expect(flavor.cpus).to eql(16.0)
|
|
46
|
+
expect(flavor.cost).to eql(1.536)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
38
49
|
end
|
|
@@ -2,34 +2,35 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
describe' Joyent::Cloud::Pricing::Formatter' do
|
|
4
4
|
|
|
5
|
-
let(:config) {
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
let(:config) { Joyent::Cloud::Pricing::Configuration.new(
|
|
6
|
+
{'g3-standard-48-smartos' => {cost: 1.536},
|
|
7
|
+
'g3-standard-0.625-smartos' => {cost: 0.02},
|
|
8
|
+
'g3-standard-30-kvm' => {cost: 0.960} }) }
|
|
8
9
|
|
|
9
10
|
let(:formatter) { Joyent::Cloud::Pricing::Formatter.new(config) }
|
|
10
11
|
|
|
11
|
-
context
|
|
12
|
-
it
|
|
13
|
-
expect(formatter.format_monthly_price
|
|
14
|
-
expect(formatter.format_monthly_price
|
|
12
|
+
context '#format_monthly_price' do
|
|
13
|
+
it 'should return properly formatted monthly price' do
|
|
14
|
+
expect(formatter.format_monthly_price 'g3-standard-0.625-smartos').to eql('$14.40')
|
|
15
|
+
expect(formatter.format_monthly_price 'g3-standard-30-kvm').to eql('$691.20')
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
|
-
context
|
|
18
|
-
it
|
|
19
|
-
expect(formatter.format_monthly_price
|
|
18
|
+
context '#monthly_formatted_price_for_flavor' do
|
|
19
|
+
it 'should return properly formatted monthly price' do
|
|
20
|
+
expect(formatter.format_monthly_price 'g3-standard-48-smartos', 10).to eql(' $1,105.92')
|
|
20
21
|
end
|
|
21
|
-
it
|
|
22
|
-
expect(formatter.format_monthly_price
|
|
22
|
+
it 'should return blank when no match was found' do
|
|
23
|
+
expect(formatter.format_monthly_price 'asdfkasdfasdlfkjasl;dkjf').to eql('')
|
|
23
24
|
end
|
|
24
25
|
end
|
|
25
|
-
context
|
|
26
|
-
it
|
|
27
|
-
expect(formatter.format_price 24566.34, 10).to eql(
|
|
28
|
-
expect(formatter.format_price 4566.34, 10).to eql(
|
|
26
|
+
context '#format_price' do
|
|
27
|
+
it 'should return properly formatted price' do
|
|
28
|
+
expect(formatter.format_price 24566.34, 10).to eql('$24,566.34')
|
|
29
|
+
expect(formatter.format_price 4566.34, 10).to eql(' $4,566.34')
|
|
29
30
|
end
|
|
30
|
-
it
|
|
31
|
-
expect(formatter.format_price 0, 10).to eql(
|
|
32
|
-
expect(formatter.format_price nil, 10).to eql(
|
|
31
|
+
it 'should return blank string of given width for 0 or nil' do
|
|
32
|
+
expect(formatter.format_price 0, 10).to eql(' ')
|
|
33
|
+
expect(formatter.format_price nil, 10).to eql(' ')
|
|
33
34
|
end
|
|
34
35
|
end
|
|
35
36
|
end
|
|
@@ -44,23 +44,23 @@ describe 'Joyent::Cloud::Pricing::Reporter' do
|
|
|
44
44
|
Joyent::Cloud::Pricing::Configuration.instance(true)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
context
|
|
48
|
-
it
|
|
47
|
+
context '#initialize' do
|
|
48
|
+
it 'should not be empty when created' do
|
|
49
49
|
expect(reporter).to_not be_nil
|
|
50
50
|
expect(reporter.analyzer).to_not be_nil
|
|
51
51
|
expect(reporter.zones_in_use.size).to eql(flavors.size)
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
context
|
|
56
|
-
it
|
|
55
|
+
context '#render' do
|
|
56
|
+
it 'should propertly render an ERB template' do
|
|
57
57
|
output = reporter.render
|
|
58
58
|
expect(output).to_not be_nil
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
context
|
|
61
|
+
context 'blank commit configuration' do
|
|
62
62
|
let(:commit) { Joyent::Cloud::Pricing::Commit.new }
|
|
63
|
-
it
|
|
63
|
+
it 'should still properly render an ERB template' do
|
|
64
64
|
expect(commit.reserves.size).to eql(0)
|
|
65
65
|
output = reporter.render
|
|
66
66
|
expect(output).to_not be_nil
|
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe 'Joyent::Cloud::Pricing::Scraper' do
|
|
4
|
-
context
|
|
4
|
+
context 'scraping from URL'
|
|
5
5
|
let(:scraper) { Joyent::Cloud::Pricing::Scraper.new }
|
|
6
6
|
|
|
7
|
-
let(:prices) { {
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
let(:prices) { {'g3-standard-48-smartos' => 1.536,
|
|
8
|
+
'g3-standard-0.625-smartos' => 0.02,
|
|
9
|
+
'g3-standard-30-kvm' => 0.960
|
|
10
|
+
} }
|
|
11
|
+
|
|
12
|
+
let(:cpus) { {'g3-standard-48-smartos' => 12.0,
|
|
13
|
+
'g3-standard-0.625-smartos' => 0.15,
|
|
14
|
+
'g3-standard-30-kvm' => 8.0
|
|
10
15
|
} }
|
|
11
16
|
|
|
12
17
|
before do
|
|
13
18
|
@config = scraper.scrape
|
|
14
19
|
end
|
|
15
20
|
|
|
16
|
-
it
|
|
21
|
+
it 'should load pricing configuration hash from Joyent Website' do
|
|
17
22
|
prices.keys.each do |flavor|
|
|
18
|
-
expect(@config[flavor]).to eql(prices[flavor])
|
|
23
|
+
expect(@config[flavor][:cost]).to eql(prices[flavor])
|
|
24
|
+
end
|
|
25
|
+
cpus.keys.each do |flavor|
|
|
26
|
+
expect(@config[flavor][:cpus]).to eql(cpus[flavor])
|
|
19
27
|
end
|
|
20
28
|
end
|
|
21
29
|
end
|
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.
|
|
4
|
+
version: 1.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Konstantin Gredeskoul
|
|
@@ -117,6 +117,7 @@ files:
|
|
|
117
117
|
- lib/pricing/analyzer.rb
|
|
118
118
|
- lib/pricing/commit.rb
|
|
119
119
|
- lib/pricing/configuration.rb
|
|
120
|
+
- lib/pricing/flavor.rb
|
|
120
121
|
- lib/pricing/formatter.rb
|
|
121
122
|
- lib/pricing/helpers.rb
|
|
122
123
|
- lib/pricing/reporter.rb
|
|
@@ -127,7 +128,7 @@ files:
|
|
|
127
128
|
- lib/tasks/update.rake
|
|
128
129
|
- spec/fixtures/commit.yml
|
|
129
130
|
- spec/fixtures/pricing.yml
|
|
130
|
-
- spec/pricing/
|
|
131
|
+
- spec/pricing/analyzer_spec.rb
|
|
131
132
|
- spec/pricing/commit_spec.rb
|
|
132
133
|
- spec/pricing/configuration_spec.rb
|
|
133
134
|
- spec/pricing/formatter_spec.rb
|
|
@@ -163,7 +164,7 @@ summary: Tools for calculating monthly and yearly price of infrastructure hosted
|
|
|
163
164
|
test_files:
|
|
164
165
|
- spec/fixtures/commit.yml
|
|
165
166
|
- spec/fixtures/pricing.yml
|
|
166
|
-
- spec/pricing/
|
|
167
|
+
- spec/pricing/analyzer_spec.rb
|
|
167
168
|
- spec/pricing/commit_spec.rb
|
|
168
169
|
- spec/pricing/configuration_spec.rb
|
|
169
170
|
- spec/pricing/formatter_spec.rb
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe 'Joyent::Cloud::Pricing::Analyze' do
|
|
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
|
-
) }
|
|
40
|
-
let(:commit) { Joyent::Cloud::Pricing::Commit.from_yaml 'spec/fixtures/commit.yml' }
|
|
41
|
-
let(:analyzer) { Joyent::Cloud::Pricing::Analyzer.new(commit, flavors) }
|
|
42
|
-
|
|
43
|
-
# need to have pricing so that it reloads from real price TODO: fix this
|
|
44
|
-
before do
|
|
45
|
-
Joyent::Cloud::Pricing::Configuration.from_yaml
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
it '#initialize' do
|
|
49
|
-
expect(analyzer.zone_list).to_not be_empty
|
|
50
|
-
expect(analyzer.zone_list).to eql (
|
|
51
|
-
{:"g3-highcpu-16-smartos" => 2,
|
|
52
|
-
:"g3-highcpu-32-smartos-cc" => 12,
|
|
53
|
-
:"g3-highcpu-7-smartos" => 2,
|
|
54
|
-
:"g3-highio-60.5-smartos" => 4,
|
|
55
|
-
:"g3-highmemory-17.125-smartos" => 12,
|
|
56
|
-
:"g3-standard-30-smartos" => 1
|
|
57
|
-
})
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
it '#monthly_full_price' do
|
|
61
|
-
expect(analyzer.monthly_full_price).to eql(35496.0)
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
it '#excess_zone_list' do
|
|
65
|
-
expect(analyzer.excess_zone_list).to eql(
|
|
66
|
-
{:"g3-highcpu-16-smartos" => 2,
|
|
67
|
-
:"g3-highcpu-32-smartos-cc" => 2,
|
|
68
|
-
:"g3-highcpu-7-smartos" => 2,
|
|
69
|
-
:"g3-standard-30-smartos" => 1
|
|
70
|
-
})
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
it '#monthly_overages_price' do
|
|
74
|
-
expect(analyzer.monthly_overages_price).to eql( 6432.48 )
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
it '#over_reserved_zone_list' do
|
|
78
|
-
expect(analyzer.over_reserved_zone_list).to eql( {:"g3-highio-60.5-smartos" => 1 })
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
end
|