lita-spendo 0.2.0 → 0.3.0

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: 529456b3bdf3fc77c3beaa9b53fa8637414df145
4
- data.tar.gz: 43805a4f1e72389fb1cfd734200f98cb25611c77
3
+ metadata.gz: bc4b4aeb89372358c7c9cf749bb1100460133b65
4
+ data.tar.gz: f35e2fc01077fc05be824d154207c8bbe7bb710e
5
5
  SHA512:
6
- metadata.gz: 3541b6ba32df59527cdaa955216f298b50be57dadef8661169fb56e06be5de7aad2da7a2113a236b6588d63e2842c734d6d47f86168919f11ca80e74a5b51cfc
7
- data.tar.gz: a93c84f6d65caf9bab6815b953454f4900074d6792ae0685ee6946919f47b411b37c90eebd5bd5e7c49140e18e7e8b618da6a5842dfcc70aaf479003ef0e99d9
6
+ metadata.gz: a8f027a73e88ef7a89ae731e79e21c216e384c1c8d4ad51c93b6b63fdc74660afbe8a5f548e203531702392cf3d4d1642acb90f240bb75bb500194392bac5072
7
+ data.tar.gz: 7079d9d39d5486cf7715a4bf32e0846239259319aa6f8f03745bc56fa7bbf7025af0741e99e34d861e75ed9751074d15b1a10db349a55e27079cbc668c86c5b9
data/README.md CHANGED
@@ -12,17 +12,29 @@ gem "lita-spendo"
12
12
 
13
13
  ## Configuration
14
14
 
15
- Spendo relies on the aws-sdk gem. You must either specify the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables or, if you are running on EC2, rely on IAM instance roles. The account requires read access to the DynamoDB table holding your billing history.
15
+ Spendo relies on the aws-sdk gem so it requires an AWS account. The account requires read access to the DynamoDB table holding your billing history.
16
16
 
17
17
  ### Required attributes
18
18
 
19
- * `aws_account_id` (String) - Account number for your AWS account
20
19
  * `base_image_url` (String) - Base url for alert images. Images should be named 'n.jpg' where n is the alert level. We suggest increasingly-scary clown photos.
20
+ * `accounts` (Array) - Array of hashes containing account information. Each hash should look like this:
21
+
22
+ ``` ruby
23
+ {
24
+ nickname: 'foo',
25
+ aws_account_id: ENV['AWS_ACCOUNT_ID'],
26
+ aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
27
+ aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
28
+ aws_region: 'us-east-1',
29
+ room: 'shell', # or room JID or whatever
30
+ dynamodb_table: 'BillingHistory'
31
+ }
32
+ ```
21
33
 
22
34
  ### Optional attributes
23
35
 
24
- * `dynamodb_table` (String) - Name of the DynamoDB table containing billing history (defaults to 'BillingHistory')
36
+ * `time_between_polls` (Integer) - Spendo will wait this many seconds between polls to the BillingHistory table. Defaults to one hour (3600 seconds).
25
37
 
26
38
  ## Usage
27
39
 
28
- TODO: Describe the plugin's features and how to use them.
40
+ `lita spendo foo` - display current billing alert level for account foo.
@@ -7,12 +7,16 @@ module Lita
7
7
  attr_accessor :account, :table_name
8
8
 
9
9
  def initialize(params={})
10
+ @aws_access_key_id = params[:aws_access_key_id]
11
+ @aws_secret_access_key = params[:aws_secret_access_key]
12
+ @aws_region = params[:aws_region]
10
13
  @account = params[:aws_account_id]
11
14
  @table_name = params[:dynamodb_table]
12
15
  end
13
16
 
14
17
  def latest
15
- ddb = Aws::DynamoDB::Resource.new()
18
+ credentials = Aws::Credentials.new(@aws_access_key_id, @aws_secret_access_key)
19
+ ddb = Aws::DynamoDB::Resource.new(region: @aws_region, credentials: credentials)
16
20
  table = ddb.table(table_name)
17
21
  opts = {
18
22
  key_condition_expression: 'Account = :account',
@@ -26,69 +30,89 @@ module Lita
26
30
  end
27
31
 
28
32
  class Spendo < Handler
29
-
30
33
  LAST_RECORD_KEY = 'last_record'
31
34
 
32
- config :aws_account_id, type: String
33
- config :dynamodb_table, type: String, default: 'BillingHistory'
34
- config :base_image_url, type: String
35
- config :room, type: String
35
+ config :base_image_url, type: String
36
36
  config :time_between_polls, type: Integer, default: 60*60
37
37
 
38
- route(/^spendo$/, :show, command: true, help: {
39
- "spendo" => "show current billing level"
38
+ # array of hashes, each hash describing a different
39
+ # account to monitor.
40
+ # config.accounts = [
41
+ # {
42
+ # :aws_account_id = 'foo',
43
+ # :dynamodb_table = 'BillingHistory',
44
+ # :room = 'shell',
45
+ # :aws_access_key_id = 'foo',
46
+ # :aws_secret_access_key = 'foo',
47
+ # :nickname = 'foo'
48
+ # }
49
+ # ]
50
+ config :accounts, type: Array
51
+
52
+ route(/^spendo\s+(\S+)$/, :show, command: true, help: {
53
+ "spendo account_name" => "show current billing level for account_name"
40
54
  })
41
55
 
42
- on(:connected) do |payload|
43
- if config.room
44
- # join the alert room
45
- robot.join config.room
56
+ on(:connected) do
57
+ config.accounts.each do |account|
58
+ setup account
59
+ end
60
+ end
61
+
62
+ def setup(account)
63
+ if account[:room]
64
+ robot.join account[:room]
46
65
  end
47
66
 
48
- # set up a timer to poll DynamoDB
49
67
  every(config.time_between_polls) do |timer|
50
- check_for_alerts
68
+ check_for_alerts account
51
69
  end
52
70
  end
53
71
 
54
72
  def show(response)
55
- message, url = create_message
73
+ account_nick = response.match_data[1]
74
+ account = lookup_account account_nick
75
+ message, url = create_message account
56
76
 
57
77
  response.reply message
58
78
  response.reply url
59
79
  end
60
80
 
61
- attr_writer :billing_history
81
+ def create_client(account)
82
+ params = {
83
+ aws_account_id: account[:aws_account_id],
84
+ aws_region: account[:aws_region],
85
+ dynamodb_table: account[:dynamodb_table],
86
+ aws_access_key_id: account[:aws_access_key_id],
87
+ aws_secret_access_key: account[:aws_secret_access_key]
88
+ }
89
+
90
+ BillingHistory.new(params)
91
+ end
62
92
 
63
- def billing_history
64
- if @billing_history.nil?
65
- params = {
66
- aws_account_id: config.aws_account_id,
67
- dynamodb_table: config.dynamodb_table
68
- }
69
- @billing_history = BillingHistory.new(params)
70
- end
71
- @billing_history
93
+ def lookup_account(nickname)
94
+ config.accounts.select {|a| a[:nickname] == nickname }.first
72
95
  end
73
96
 
74
- def create_message
75
- data = billing_history.latest
97
+ def create_message(account)
98
+ client = create_client account
99
+ data = client.latest
76
100
 
77
- account = data['Account']
101
+ account_id = data['Account']
78
102
  current_fees = data['TotalFees'].to_f
79
103
  expected_fees = data['ExpectedFees'].to_f
80
104
  alert_level = data['AlertLevel'].to_i
81
105
  categorized_fees = data['FeesByCategory']
82
106
 
83
107
  message = "The current fees alert threshold has been reached.\n"
84
- message << "\nAccount: #{account}"
108
+ message << "\nAccount: #{account[:nickname]} #{account_id}"
85
109
  message << "\nCurrent fees: $#{current_fees}"
86
110
  message << "\nExpected monthly fees: $#{expected_fees}" # TODO
87
111
  message << "\nFee level is at #{alert_level * 25}% of expected"
88
112
  message << "\n\n Fee Category Breakdown\n\n"
89
113
 
90
- categorized_fees.each_pair do |k,v|
91
- value = v.to_f
114
+ categorized_fees.keys.sort.each do |k|
115
+ value = categorized_fees[k].to_f
92
116
  next if value == 0.0
93
117
  message << "#{k.ljust(20)}: $#{sprintf('%8.2f', value.round(2))}\n"
94
118
  end
@@ -98,16 +122,22 @@ module Lita
98
122
  return [message, url]
99
123
  end
100
124
 
125
+ def account_key(account)
126
+ account[:aws_account_id] + '_' + LAST_RECORD_KEY
127
+ end
128
+
101
129
  # write current data to redis
102
130
  # BigDecimals get saved as strings which fail to
103
131
  # deserialize as integers (but do deserialize as floats)
104
- def save_billing_data(data)
105
- redis.set LAST_RECORD_KEY, data.to_json
132
+ def save_billing_data(account, data)
133
+ key = account_key account
134
+ redis.set key, data.to_json
106
135
  end
107
136
 
108
137
  # read previous data from redis
109
- def load_billing_data
110
- data = redis.get LAST_RECORD_KEY
138
+ def load_billing_data(account)
139
+ key = account_key account
140
+ data = redis.get key
111
141
  return nil if data.nil?
112
142
 
113
143
  JSON.parse(data)
@@ -117,20 +147,21 @@ module Lita
117
147
  previous['AlertLevel'].to_f != current['AlertLevel'].to_f
118
148
  end
119
149
 
120
- def check_for_alerts
150
+ def check_for_alerts(account)
121
151
  log.debug "checking for alerts"
122
- current_data = billing_history.latest
123
- last_data = load_billing_data
152
+ client = create_client account
153
+ current_data = client.latest
154
+ last_data = load_billing_data(account)
124
155
 
125
156
  if last_data && alert_level_changed?(last_data, current_data)
126
- message, url = create_message
127
- target = Source.new(room: config.room)
157
+ message, url = create_message account
158
+ target = Source.new(room: account[:room])
128
159
  robot.send_messages(target, message, url)
129
160
  else
130
161
  log.debug "alert level unchanged"
131
162
  end
132
163
 
133
- save_billing_data current_data
164
+ save_billing_data account, current_data
134
165
  end
135
166
  end
136
167
 
data/lita-spendo.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "lita-spendo"
3
- spec.version = "0.2.0"
3
+ spec.version = "0.3.0"
4
4
  spec.authors = ["Chris Chalfant"]
5
5
  spec.email = ["cchalfant@leafsoftwaresolutions.com"]
6
6
  spec.description = "Lita handler for displaying AWS billing"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lita-spendo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Chalfant