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 +4 -4
- data/README.md +16 -4
- data/lib/lita/handlers/spendo.rb +72 -41
- data/lita-spendo.gemspec +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc4b4aeb89372358c7c9cf749bb1100460133b65
|
4
|
+
data.tar.gz: f35e2fc01077fc05be824d154207c8bbe7bb710e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
* `
|
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
|
-
|
40
|
+
`lita spendo foo` - display current billing alert level for account foo.
|
data/lib/lita/handlers/spendo.rb
CHANGED
@@ -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
|
-
|
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 :
|
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
|
-
|
39
|
-
|
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
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
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
|
-
|
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
|
64
|
-
|
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
|
-
|
97
|
+
def create_message(account)
|
98
|
+
client = create_client account
|
99
|
+
data = client.latest
|
76
100
|
|
77
|
-
|
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.
|
91
|
-
value =
|
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
|
-
|
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
|
-
|
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
|
-
|
123
|
-
|
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:
|
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