ruboty-kanjo 0.1.0 → 1.0.0

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: 94f52aa724a6748935c8a8864eee93b941c1c03d
4
- data.tar.gz: b12af63a2675dec4f218b269ba97ef0d48039cec
3
+ metadata.gz: 5599f410097e6f482e82e73e5f37d29631e0810f
4
+ data.tar.gz: 8802c5c4153d3144f92559ba1fbf5f4549a19ff8
5
5
  SHA512:
6
- metadata.gz: 23ed9e548c954598e1a399e8153a547d913a66d64f1a6bc4f741a2423b179be867709f3bc715b2e4f08951718c47766c25176854c87caee2214d7409d3158bd7
7
- data.tar.gz: 68ae94550d2a88965525303939970f8e52f88c5950881e56cd2f4f9a2f5fdde3e1b58e65f9dd6e3e5bf7584627b91d5a513b1d6d608d5396e73dddcfe03be039
6
+ metadata.gz: 88551c8c9e2f167e58eab58f9fdc9e248d11190673790202c374dc367bf1a3bc6413df24d964349cf7622d168b54d7bfc1e705f9a64350af5c4619e315e9947d
7
+ data.tar.gz: cb2136b734b54bd18a08bfea0a6a15b60539a5fb8e1bd938fa863adf9f40e3a74729022038f680f0680e4bca8f431437d803ff1a1b12d6477a2cc69c7b52c6d0
data/README.md CHANGED
@@ -17,7 +17,8 @@ And then execute:
17
17
  ## Usage
18
18
 
19
19
  ```
20
- ruboty kanjo aws - fetch pricing by AWS
20
+ ruboty /kanjo aws billing\z/ - fetch aws billing
21
+ ruboty /kanjo aws spot (?<availability_zone>[a-z0-9-]+) (?<instances>[a-z0-9.]+(?:\s*,\s*[a-z0-9.]+)*)\z/ - fetch aws spot instacne prices
21
22
  ```
22
23
 
23
24
  ## Development
@@ -3,10 +3,17 @@ require 'ruboty/kanjo/actions/aws'
3
3
 
4
4
  module Ruboty::Handlers
5
5
  class Kanjo < Ruboty::Handlers::Base
6
- on /kanjo aws\z/, name: :aws, description: 'fetch aws billing'
6
+ on /kanjo aws billing\z/,
7
+ name: :aws_billing, description: 'fetch aws billing'
8
+ on /kanjo aws spot (?<availability_zone>[a-z0-9-]+) (?<instances>[a-z0-9.]+(?:\s*,\s*[a-z0-9.]+)*)\z/,
9
+ name: :aws_spot_instance, description: 'fetch aws spot instacne prices'
7
10
 
8
- def aws(message)
9
- Ruboty::Kanjo::Actions::AWS.new(message).call
11
+ def aws_billing(message)
12
+ Ruboty::Kanjo::Actions::AWS.new(message).billing
13
+ end
14
+
15
+ def aws_spot_instance(message)
16
+ Ruboty::Kanjo::Actions::AWS.new(message).spot_instance
10
17
  end
11
18
  end
12
19
  end
@@ -2,29 +2,84 @@ require 'aws-sdk'
2
2
 
3
3
  module Ruboty::Kanjo::Actions
4
4
  class AWS < Ruboty::Actions::Base
5
- ONE_HOUR = 60 * 60
6
-
7
- def call
5
+ ONE_HOUR = 60 * 60 * 6
6
+
7
+ INSTANCE_TYPES = %w(
8
+ t1.micro t2.nano t2.micro t2.small t2.medium t2.large
9
+ m1.small m1.medium m1.large m1.xlarge
10
+ m3.medium m3.large m3.xlarge m3.2xlarge
11
+ m4.large m4.xlarge m4.2xlarge m4.4xlarge m4.10xlarge m4.16xlarge
12
+ m2.xlarge m2.2xlarge m2.4xlarge
13
+ cr1.8xlarge
14
+ r3.large r3.xlarge r3.2xlarge r3.4xlarge r3.8xlarge
15
+ x1.16xlarge x1.32xlarge
16
+ i2.xlarge i2.2xlarge i2.4xlarge i2.8xlarge
17
+ hi1.4xlarge
18
+ hs1.8xlarge
19
+ c1.medium c1.xlarge
20
+ c3.large c3.xlarge c3.2xlarge c3.4xlarge c3.8xlarge
21
+ c4.large c4.xlarge c4.2xlarge c4.4xlarge c4.8xlarge
22
+ cc1.4xlarge cc2.8xlarge
23
+ g2.2xlarge g2.8xlarge
24
+ cg1.4xlarge
25
+ p2.xlarge p2.8xlarge p2.16xlarge
26
+ d2.xlarge d2.2xlarge d2.4xlarge d2.8xlarge
27
+ )
28
+
29
+ def billing
8
30
  services = list_services
9
31
 
10
- col = (services + ['Total']).map(&:size).max
11
-
12
- total_price = get_price
13
- msg = ["#{'Total'.ljust(col)} : #{total_price} USD"]
32
+ prices = {}
33
+ prices['Total'] = get_price
14
34
 
15
35
  services.each do |service|
16
- msg.push("#{service.ljust(col)} : #{get_price(service)} USD")
36
+ prices[service] = get_price(service)
37
+ end
38
+
39
+ message.reply(table(prices), code: true)
40
+ end
41
+
42
+ def spot_instance
43
+ az = message[:availability_zone]
44
+ types = message[:instances].split(/\s*,\s*/)
45
+
46
+ types = types.keep_if { |type| INSTANCE_TYPES.include?(type) }
47
+
48
+ if types.empty?
49
+ message.reply('Not available instance types')
50
+ return
51
+ end
52
+
53
+ unless availability_zones.include?(az)
54
+ message.reply('Availability zone is invalid')
55
+ return
56
+ end
57
+
58
+ res = ec2.describe_spot_price_history({
59
+ dry_run: false,
60
+ start_time: Time.now,
61
+ end_time: Time.now,
62
+ instance_types: types,
63
+ availability_zone: az,
64
+ max_results: 5,
65
+ })
66
+
67
+ prices = {}
68
+ res.spot_price_history.sort_by(&:instance_type).each do |history|
69
+ prices[history.instance_type + ' '+ history.product_description] = "#{history.spot_price} USD"
17
70
  end
18
71
 
19
- message.reply(msg.join("\n"))
72
+ message.reply(table(prices), code: true)
20
73
  end
21
74
 
22
75
  def list_services
23
- resp = cloudwatch.list_metrics(namespace: 'AWS/Billing',
24
- metric_name: 'EstimatedCharges',
25
- dimensions: [
26
- { name: 'Currency', value: 'USD' }
27
- ])
76
+ resp = cloudwatch.list_metrics(
77
+ namespace: 'AWS/Billing',
78
+ metric_name: 'EstimatedCharges',
79
+ dimensions: [
80
+ { name: 'Currency', value: 'USD' }
81
+ ]
82
+ )
28
83
 
29
84
  services = []
30
85
  resp.metrics.each do |metric|
@@ -56,7 +111,7 @@ module Ruboty::Kanjo::Actions
56
111
  unit: 'None'
57
112
  )
58
113
 
59
- resp.datapoints.last.maximum
114
+ resp.datapoints.last&.maximum
60
115
  end
61
116
 
62
117
  private
@@ -64,5 +119,24 @@ module Ruboty::Kanjo::Actions
64
119
  def cloudwatch
65
120
  @cloudwatch ||= Aws::CloudWatch::Client.new(region: 'us-east-1')
66
121
  end
122
+
123
+ def ec2
124
+ @ec2 ||= Aws::EC2::Client.new()
125
+ end
126
+
127
+ def availability_zones
128
+ ec2.describe_availability_zones.availability_zones.map(&:zone_name)
129
+ end
130
+
131
+ def table(data)
132
+ col = data.keys.map(&:size).max
133
+
134
+ lines = []
135
+ data.each_pair do |key, val|
136
+ lines.push("#{key.ljust(col)} : #{val}")
137
+ end
138
+
139
+ lines.join("\n")
140
+ end
67
141
  end
68
142
  end
@@ -1,5 +1,5 @@
1
1
  module Ruboty
2
2
  module Kanjo
3
- VERSION = '0.1.0'.freeze
3
+ VERSION = '1.0.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruboty-kanjo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sho Kusano