cucloud 0.7.5 → 0.7.6

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: 34988a759221260aa910c03f3063f5dc833f5422
4
- data.tar.gz: b002d383d5a5766231643a6d9ec214e0c376396c
3
+ metadata.gz: b9c097b02b7b8ee93f6adb3be2c80ea3e859b767
4
+ data.tar.gz: 7e35d979d839416122e5b42a7805de6481afb2f5
5
5
  SHA512:
6
- metadata.gz: 359e34085a6474d24686dc2874ac878cea7856be6549afe3d542b35aeb7a8108ecdb2cd5d335f52ef8efbd945385ae1f601e36bd9cb49aa0030c4a2578ab88d9
7
- data.tar.gz: 9a9d44ee28bfe4572f0351afe87aea8f2868f013386e6832ec9e454a110ba1b0b84548ecc7235aa533d33ed24a4b38bd9a660dca899ce1df89f032bae539e506
6
+ metadata.gz: d2be8ee2db184cf7b875764c83ee0fc01820710741fe981ffb73c95d93cb4a42c0f29d4459d8f4a255127df4448de5b8321ad46a8d1fdd142a5522a2cccca49b
7
+ data.tar.gz: 5d91d37eaa27392c7420458bb97d43caffa9502667701b366606ba6c1431c1582428b6dce2317ecfa5fb5724b5ca3e2d8906b73fd79eda2f33e8a9a69101a4fc
data/cucloud.gemspec CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.add_dependency 'aws-sdk', '~> 2'
28
28
  spec.add_dependency 'uuid', '~> 2.3'
29
+ spec.add_dependency 'descriptive_statistics', '~> 2.5'
29
30
 
30
31
  spec.add_development_dependency 'bundler', '~> 1.11'
31
32
  spec.add_development_dependency 'coveralls'
data/lib/cucloud.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'aws-sdk'
2
+ require 'descriptive_statistics'
2
3
 
3
4
  # Main Cucloud Module namespace and defaults
4
5
  module Cucloud
@@ -15,6 +16,7 @@ module Cucloud
15
16
  require 'cucloud/rds_utils'
16
17
  require 'cucloud/lambda_utils'
17
18
  require 'cucloud/cfn_utils'
19
+ require 'cucloud/utilities'
18
20
 
19
21
  # This is the default region API calls are made against
20
22
  DEFAULT_REGION = 'us-east-1'.freeze
@@ -11,6 +11,10 @@ module Cucloud
11
11
  WAITER_MAX_ATTEMPS = 240
12
12
  # Delay between calls used by waiter to check status
13
13
  WAITER_DELAY = 15
14
+ # Two weeks in hours
15
+ TWO_WEEKS = 336
16
+ # Default OS to use
17
+ DEFAULT_OS = 'Linux/UNIX'.freeze
14
18
 
15
19
  def initialize(ec2_client = Aws::EC2::Client.new, ssm_utils = Cucloud::SSMUtils.new)
16
20
  @ec2 = ec2_client
@@ -195,7 +199,7 @@ module Cucloud
195
199
  next if volumes_backed_up_recently[volume.volume_id.to_s]
196
200
  instance_name = get_instance_name(volume.attachments[0].instance_id)
197
201
  tags = additional_snapshot_tags.dup
198
- unless tags.any? { |tagitem| tagitem[:key] == 'Instance Name' }
202
+ unless instance_name.nil? || tags.any? { |tagitem| tagitem[:key] == 'Instance Name' }
199
203
  tags << { key: 'Instance Name', value: instance_name }
200
204
  end
201
205
  volume.tags.each do |tag|
@@ -253,5 +257,64 @@ module Cucloud
253
257
  end
254
258
  found_snapshots
255
259
  end
260
+
261
+ # Get a recommendation for a spot bid request. Given an instance type and
262
+ # OS we will grab data from a period specified, default is from two weeks to now,
263
+ # and calculate recommendations for the AZs in the current region
264
+ # @param instance_type [String] Insrance type to get bid for
265
+ # @param os [String] OS you whish to run, default linux
266
+ # @param num_hours [Integer] How many hours to look back, default two weeks
267
+ # @return [Hash] Reccomendations by region, empty if no viable recommendations
268
+ def best_spot_bid_price(instance_type, os = DEFAULT_OS, num_hours = TWO_WEEKS)
269
+ price_history_by_az = {}
270
+ recommendations = {}
271
+
272
+ options = {
273
+ end_time: Time.now.utc,
274
+ instance_types: [
275
+ instance_type
276
+ ],
277
+ product_descriptions: [
278
+ os
279
+ ],
280
+ start_time: (Time.now - num_hours * 60).utc
281
+ }
282
+
283
+ loop do
284
+ price_history = @ec2.describe_spot_price_history(options)
285
+ price_history.spot_price_history.each do |price|
286
+ price_history_by_az[price.availability_zone] = [] unless price_history_by_az[price.availability_zone]
287
+ price_history_by_az[price.availability_zone].push(price.spot_price.to_f)
288
+ end
289
+
290
+ break if price_history.next_token.nil? || price_history.next_token.empty?
291
+ options[:next_token] = price_history.next_token
292
+ end
293
+
294
+ price_history_by_az.each do |key, data|
295
+ stats = data.descriptive_statistics
296
+ next unless stats[:number] > 30
297
+ confidence_interval = Cucloud::Utilities.confidence_interval_99(
298
+ stats[:mean],
299
+ stats[:standard_deviation],
300
+ stats[:number]
301
+ )
302
+ recommendations[key] = confidence_interval[1]
303
+ end
304
+
305
+ recommendations
306
+ end
307
+
308
+ # Make spot instance request
309
+ # @param options [Hash] Options to provide to the API
310
+ # see http://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/Client.html#request_spot_instances-instance_method
311
+ # @return [Hash] Description of the spot request
312
+ def make_spot_instance_request(options)
313
+ spot_requests = @ec2.request_spot_instances(options)
314
+ request_ids = [spot_requests.spot_instance_requests[0].spot_instance_request_id]
315
+
316
+ @ec2.wait_until(:spot_instance_request_fulfilled, spot_instance_request_ids: request_ids)
317
+ @ec2.describe_spot_instance_requests(spot_instance_request_ids: request_ids)
318
+ end
256
319
  end
257
320
  end
@@ -0,0 +1,39 @@
1
+ module Cucloud
2
+ # Utilities class - for basice shared utilities
3
+ class Utilities
4
+ # Z Score to calculate 99% confidence interval
5
+ Z_SCORE_99 = 2.576
6
+ # Z Score to calculate 99% confidence interval
7
+ Z_SCORE_96 = 1.96
8
+
9
+ # Calculate 99% confidence interval
10
+ # @param mean [Float] sample mean
11
+ # @param stdev [Float] sample standard deviation
12
+ # @param sample_size [Integer] sample size
13
+ # @return [Array] Two element array representing the computed confidence interval
14
+ def self.confidence_interval_99(mean, stdev, sample_size)
15
+ confidence_interval(mean, stdev, sample_size, Z_SCORE_99)
16
+ end
17
+
18
+ # Calculate 95% confidence interval
19
+ # @param mean [Float] sample mean
20
+ # @param stdev [Float] sample standard deviation
21
+ # @param sample_size [Integer] sample size
22
+ # @return [Array] Two element array representing the computed confidence interval
23
+ def self.confidence_interval_95(mean, stdev, sample_size)
24
+ confidence_interval(mean, stdev, sample_size, Z_SCORE_96)
25
+ end
26
+
27
+ private_class_method
28
+
29
+ # Calculate confidence interval for given zscore
30
+ # @param mean [Float] sample mean
31
+ # @param stdev [Float] sample standard deviation
32
+ # @param sample_size [Integer] sample size
33
+ # @return [Array] Two element array representing the computed confidence interval
34
+ def self.confidence_interval(mean, stdev, sample_size, zscore)
35
+ delta = zscore * stdev / Math.sqrt(sample_size - 1)
36
+ [mean - delta, mean + delta]
37
+ end
38
+ end
39
+ end
@@ -1,5 +1,5 @@
1
1
  module Cucloud
2
2
  # Disable mutable constant warning - freezing this oddly breaks bundler
3
3
  # rubocop:disable Style/MutableConstant
4
- VERSION = '0.7.5'
4
+ VERSION = '0.7.6'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cucloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.5
4
+ version: 0.7.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - sbower
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2017-03-14 00:00:00.000000000 Z
13
+ date: 2017-04-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: aws-sdk
@@ -40,6 +40,20 @@ dependencies:
40
40
  - - "~>"
41
41
  - !ruby/object:Gem::Version
42
42
  version: '2.3'
43
+ - !ruby/object:Gem::Dependency
44
+ name: descriptive_statistics
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '2.5'
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '2.5'
43
57
  - !ruby/object:Gem::Dependency
44
58
  name: bundler
45
59
  requirement: !ruby/object:Gem::Requirement
@@ -159,6 +173,7 @@ files:
159
173
  - lib/cucloud/lambda_utils.rb
160
174
  - lib/cucloud/rds_utils.rb
161
175
  - lib/cucloud/ssm_utils.rb
176
+ - lib/cucloud/utilities.rb
162
177
  - lib/cucloud/version.rb
163
178
  - lib/cucloud/vpc_utils.rb
164
179
  homepage: https://github.com/CU-CloudCollab/cucloud_ruby