cloud_cost_tracker 0.1.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.
- data/.gitignore +16 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/Guardfile +10 -0
- data/LICENSE.TXT +10 -0
- data/README.md +123 -0
- data/Rakefile +15 -0
- data/billing issues.md +4 -0
- data/bin/cloud_cost_tracker +94 -0
- data/cloud_cost_tracker.gemspec +36 -0
- data/config/accounts.example.yml +45 -0
- data/config/billing/compute-aws-servers/us-east-on_demand.yml +44 -0
- data/config/billing/compute-aws-snapshots.yml +5 -0
- data/config/billing/compute-aws-volumes.yml +5 -0
- data/config/billing/elasticache-aws.yml +15 -0
- data/config/billing/rds-aws-servers/us-east-on_demand-mysql.yml +26 -0
- data/config/billing/rds-aws-servers/us-east-on_demand-storage.yml +10 -0
- data/config/billing/storage-aws-directories.yml +5 -0
- data/config/database.example.yml +18 -0
- data/db/migrate/20120118000000_create_billing_records.rb +22 -0
- data/db/migrate/20120119000000_create_billing_codes.rb +20 -0
- data/lib/cloud_cost_tracker/billing/account_billing_policy.rb +106 -0
- data/lib/cloud_cost_tracker/billing/compute/aws/servers.rb +30 -0
- data/lib/cloud_cost_tracker/billing/compute/aws/snapshots.rb +43 -0
- data/lib/cloud_cost_tracker/billing/compute/aws/volumes.rb +30 -0
- data/lib/cloud_cost_tracker/billing/elasticache/clusters.rb +33 -0
- data/lib/cloud_cost_tracker/billing/rds/server_storage.rb +30 -0
- data/lib/cloud_cost_tracker/billing/rds/servers.rb +31 -0
- data/lib/cloud_cost_tracker/billing/resource_billing_policy.rb +119 -0
- data/lib/cloud_cost_tracker/billing/storage/aws/directories.rb +47 -0
- data/lib/cloud_cost_tracker/coding/account_coding_policy.rb +73 -0
- data/lib/cloud_cost_tracker/coding/compute/aws/account_coding_policy.rb +38 -0
- data/lib/cloud_cost_tracker/coding/compute/aws/servers.rb +26 -0
- data/lib/cloud_cost_tracker/coding/compute/aws/volumes.rb +26 -0
- data/lib/cloud_cost_tracker/coding/rds/account_coding_policy.rb +25 -0
- data/lib/cloud_cost_tracker/coding/rds/servers.rb +59 -0
- data/lib/cloud_cost_tracker/coding/resource_coding_policy.rb +25 -0
- data/lib/cloud_cost_tracker/extensions/fog_model.rb +41 -0
- data/lib/cloud_cost_tracker/models/billing_code.rb +14 -0
- data/lib/cloud_cost_tracker/models/billing_record.rb +88 -0
- data/lib/cloud_cost_tracker/tasks.rb +3 -0
- data/lib/cloud_cost_tracker/tracker.rb +86 -0
- data/lib/cloud_cost_tracker/util/module_instrospection.rb +13 -0
- data/lib/cloud_cost_tracker/version.rb +3 -0
- data/lib/cloud_cost_tracker.rb +113 -0
- data/lib/tasks/database.rake +25 -0
- data/lib/tasks/rspec.rake +6 -0
- data/lib/tasks/track.rake +19 -0
- data/spec/lib/cloud_cost_tracker/billing/account_billing_policy_spec.rb +33 -0
- data/spec/lib/cloud_cost_tracker/billing/resource_billing_policy_spec.rb +102 -0
- data/spec/lib/cloud_cost_tracker/cloud_cost_tracker_spec.rb +57 -0
- data/spec/lib/cloud_cost_tracker/coding/account_coding_policy_spec.rb +32 -0
- data/spec/lib/cloud_cost_tracker/coding/resource_coding_policy_spec.rb +23 -0
- data/spec/lib/cloud_cost_tracker/models/billing_code_spec.rb +35 -0
- data/spec/lib/cloud_cost_tracker/models/billing_record_spec.rb +206 -0
- data/spec/lib/cloud_cost_tracker/tracker_spec.rb +37 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/support/_configure_logging.rb +6 -0
- data/writing-billing-policies.md +8 -0
- data/writing-coding-policies.md +7 -0
- metadata +224 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
module CloudCostTracker
|
2
|
+
module Billing
|
3
|
+
describe BillingCode do
|
4
|
+
before(:each) do
|
5
|
+
@existing_code = BillingCode.create!(
|
6
|
+
:key => 'fake key', :value => 'fake value'
|
7
|
+
)
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:each) do
|
11
|
+
@existing_code.destroy
|
12
|
+
end
|
13
|
+
|
14
|
+
it "is valid with valid attributes" do
|
15
|
+
@existing_code.should be_valid
|
16
|
+
end
|
17
|
+
|
18
|
+
it "is not valid without a key" do
|
19
|
+
@existing_code.key = nil
|
20
|
+
@existing_code.should_not be_valid
|
21
|
+
end
|
22
|
+
it "is valid without a value" do
|
23
|
+
@existing_code.value = nil
|
24
|
+
@existing_code.should be_valid
|
25
|
+
end
|
26
|
+
|
27
|
+
#it "is not valid if an identical code is already saved" do
|
28
|
+
# BillingCode.new(
|
29
|
+
# :key => 'fake key', :value => 'fake value'
|
30
|
+
# ).should_not be_valid
|
31
|
+
#end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
module CloudCostTracker
|
2
|
+
module Billing
|
3
|
+
describe BillingRecord do
|
4
|
+
|
5
|
+
# some constants for a generic BillingRecord
|
6
|
+
@stop_time = Time.now
|
7
|
+
@start_time = Time.now - FogTracker::DEFAULT_POLLING_TIME
|
8
|
+
@hourly_rate = 5.0
|
9
|
+
RECORD_PARAMETERS = {
|
10
|
+
:provider => "fake_provider_name",
|
11
|
+
:service => "fake_service_name",
|
12
|
+
:account => "fake_account_ID",
|
13
|
+
:resource_id => "fake_resource_ID",
|
14
|
+
:resource_type => "fake_resource_type",
|
15
|
+
:billing_type => "fake_billing_type",
|
16
|
+
:start_time => @start_time,
|
17
|
+
:stop_time => @stop_time,
|
18
|
+
:cost_per_hour => @hourly_rate,
|
19
|
+
:total_cost => ((@stop_time - @start_time) * @hourly_rate) / 3600,
|
20
|
+
}
|
21
|
+
# A day in the distant future
|
22
|
+
NEW_YEARS_DAY_3000 = Time.gm(3000, 1, 1, 0, 0, 0)
|
23
|
+
|
24
|
+
before(:each) do
|
25
|
+
BillingRecord.delete_all ; BillingCode.delete_all # clean database
|
26
|
+
# Make a "current" billing record
|
27
|
+
@existing_bill = BillingRecord.create!(RECORD_PARAMETERS)
|
28
|
+
# Make a billing record that follows the existing one in time
|
29
|
+
@next_bill = BillingRecord.new(RECORD_PARAMETERS.merge(
|
30
|
+
:start_time => RECORD_PARAMETERS[:stop_time],
|
31
|
+
:stop_time => RECORD_PARAMETERS[:stop_time] + 3600
|
32
|
+
))
|
33
|
+
end
|
34
|
+
|
35
|
+
after(:each) do
|
36
|
+
BillingRecord.delete_all ; BillingCode.delete_all # clean database
|
37
|
+
end
|
38
|
+
|
39
|
+
it "is valid with valid attributes" do
|
40
|
+
@existing_bill.should be_valid
|
41
|
+
end
|
42
|
+
|
43
|
+
it "is not valid without a provider name" do
|
44
|
+
@existing_bill.provider = nil
|
45
|
+
@existing_bill.should_not be_valid
|
46
|
+
end
|
47
|
+
it "is not valid without a service name" do
|
48
|
+
@existing_bill.service = nil
|
49
|
+
@existing_bill.should_not be_valid
|
50
|
+
end
|
51
|
+
it "is not valid without an account name" do
|
52
|
+
@existing_bill.account = nil
|
53
|
+
@existing_bill.should_not be_valid
|
54
|
+
end
|
55
|
+
it "is not valid without a resource ID" do
|
56
|
+
@existing_bill.resource_id = nil
|
57
|
+
@existing_bill.should_not be_valid
|
58
|
+
end
|
59
|
+
it "is not valid without a resource type" do
|
60
|
+
@existing_bill.resource_type = nil
|
61
|
+
@existing_bill.should_not be_valid
|
62
|
+
end
|
63
|
+
it "is not valid without a billing type" do
|
64
|
+
@existing_bill.billing_type = nil
|
65
|
+
@existing_bill.should_not be_valid
|
66
|
+
end
|
67
|
+
it "is not valid without a start time" do
|
68
|
+
@existing_bill.start_time = nil
|
69
|
+
@existing_bill.should_not be_valid
|
70
|
+
end
|
71
|
+
it "is not valid without a stop time" do
|
72
|
+
@existing_bill.stop_time = nil
|
73
|
+
@existing_bill.should_not be_valid
|
74
|
+
end
|
75
|
+
it "is not valid without an hourly cost" do
|
76
|
+
@existing_bill.cost_per_hour = nil
|
77
|
+
@existing_bill.should_not be_valid
|
78
|
+
end
|
79
|
+
it "is not valid without a total cost" do
|
80
|
+
@existing_bill.total_cost = nil
|
81
|
+
@existing_bill.should_not be_valid
|
82
|
+
end
|
83
|
+
it "validates its associated billing codes" do
|
84
|
+
new_record = BillingRecord.new(RECORD_PARAMETERS)
|
85
|
+
new_record.billing_codes = [BillingCode.new]
|
86
|
+
new_record.should_not be_valid
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#most_recent_like' do
|
90
|
+
context "when invoked with a BillingRecord" do
|
91
|
+
context "and a record for the same resource / billing type exists" do
|
92
|
+
it 'returns the most recent BillingRecord for the same resource' do
|
93
|
+
BillingRecord.most_recent_like(@next_bill).should == @existing_bill
|
94
|
+
end
|
95
|
+
end
|
96
|
+
context "and no record for the same resource / billing type exists" do
|
97
|
+
it 'returns nil' do
|
98
|
+
BillingRecord.delete_all
|
99
|
+
BillingRecord.most_recent_like(@next_bill).should == nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '#overlaps_with' do
|
106
|
+
context "when invoked with a BillingRecord far away in time" do
|
107
|
+
it "returns false" do
|
108
|
+
@next_bill.start_time = NEW_YEARS_DAY_3000
|
109
|
+
@next_bill.stop_time = NEW_YEARS_DAY_3000 + 3600
|
110
|
+
@existing_bill.overlaps_with(@next_bill).should == false
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
context "when invoked with a BillingRecord adjacent in time" do
|
115
|
+
it "returns true" do
|
116
|
+
@existing_bill.overlaps_with(@next_bill).should == true
|
117
|
+
end
|
118
|
+
end
|
119
|
+
context "when invoked with a BillingRecord overlapping in time" do
|
120
|
+
it "returns true" do
|
121
|
+
@next_bill.start_time = RECORD_PARAMETERS[:stop_time] - 1
|
122
|
+
@next_bill.stop_time = RECORD_PARAMETERS[:stop_time] + 3600
|
123
|
+
@existing_bill.overlaps_with(@next_bill).should == true
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '#merge_with with an existing BillingRecord' do
|
129
|
+
it "copies the stop time of the current record onto the existing record" do
|
130
|
+
@next_bill.stop_time = NEW_YEARS_DAY_3000
|
131
|
+
@existing_bill.merge_with @next_bill
|
132
|
+
@existing_bill.stop_time.should == NEW_YEARS_DAY_3000
|
133
|
+
end
|
134
|
+
it "updates the total for the existing record" do
|
135
|
+
# Run an update that causes the @existing_bill's total to double
|
136
|
+
duration = (@existing_bill.stop_time - @existing_bill.start_time)
|
137
|
+
@next_bill.stop_time = @existing_bill.stop_time + duration
|
138
|
+
@existing_bill.merge_with @next_bill
|
139
|
+
@existing_bill.total_cost.should == 2 * RECORD_PARAMETERS[:total_cost]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '#set_codes' do
|
144
|
+
context 'when invoked on a saved (existing) BillingRecord' do
|
145
|
+
before(:each) {@existing_code = BillingCode.create!(:key=>'k', :value=>'v')}
|
146
|
+
context "with a key, value pair that matches an existing BillingCode" do
|
147
|
+
it "associates with the existing BillingCode" do
|
148
|
+
@existing_bill.set_codes [['k', 'v']]
|
149
|
+
@existing_bill.billing_codes.should == [@existing_code]
|
150
|
+
@existing_bill.should be_valid
|
151
|
+
end
|
152
|
+
end
|
153
|
+
context "with a key, value pair that matches no existing BillingCode" do
|
154
|
+
it "creates a new BillingCode and associates with it" do
|
155
|
+
@existing_bill.billing_codes.should == Array.new
|
156
|
+
@existing_bill.set_codes [['k', 'v']]
|
157
|
+
@existing_bill.billing_codes.should == [@existing_code]
|
158
|
+
@existing_bill.should be_valid
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
context 'when invoked on a new, unsaved BillingRecord' do
|
163
|
+
before(:each) { @new_bill = BillingRecord.new(RECORD_PARAMETERS) }
|
164
|
+
context "with a key, value pair that matches an existing BillingCode" do
|
165
|
+
it "associates with the existing BillingCode" do
|
166
|
+
BillingCode.all.should == Array.new
|
167
|
+
existing_code = BillingCode.create!(:key => 'k', :value => 'v')
|
168
|
+
@new_bill.set_codes [['k', 'v']]
|
169
|
+
@new_bill.billing_codes.should == [existing_code]
|
170
|
+
@new_bill.should be_valid
|
171
|
+
end
|
172
|
+
end
|
173
|
+
context "with a key, value pair that matches no existing BillingCode" do
|
174
|
+
it "creates a new BillingCode and associates with it" do
|
175
|
+
BillingCode.all.should == Array.new
|
176
|
+
@new_bill.billing_codes.should == Array.new
|
177
|
+
@new_bill.set_codes [['k', 'v']]
|
178
|
+
@new_bill.billing_codes.size.should == 1
|
179
|
+
@new_bill.billing_codes.first.key.should == 'k'
|
180
|
+
@new_bill.billing_codes.first.value.should == 'v'
|
181
|
+
@new_bill.should be_valid
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe '#to_hash' do
|
188
|
+
it "returns a Hash of the record's attributes" do
|
189
|
+
@existing_bill.billing_codes = [
|
190
|
+
BillingCode.new(:key => 'key1', :value => 'val1'),
|
191
|
+
BillingCode.new(:key => 'key2', :value => 'val2'),
|
192
|
+
]
|
193
|
+
@existing_bill.to_hash['provider'].should == "fake_provider_name"
|
194
|
+
@existing_bill.to_hash['service'].should == "fake_service_name"
|
195
|
+
@existing_bill.to_hash['account'].should == "fake_account_ID"
|
196
|
+
@existing_bill.to_hash['resource_id'].should == "fake_resource_ID"
|
197
|
+
@existing_bill.to_hash['resource_type'].should == "fake_resource_type"
|
198
|
+
@existing_bill.to_hash['billing_type'].should == "fake_billing_type"
|
199
|
+
@existing_bill.to_hash['billing_codes'].should ==
|
200
|
+
[['key1', 'val1'], ['key2', 'val2']]
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module CloudCostTracker
|
2
|
+
describe Tracker do
|
3
|
+
|
4
|
+
before(:each) do
|
5
|
+
@tracker = Tracker.new(FAKE_ACCOUNTS)
|
6
|
+
Billing::BillingRecord.delete_all
|
7
|
+
end
|
8
|
+
|
9
|
+
after(:each) do
|
10
|
+
Billing::BillingRecord.delete_all
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#update' do
|
14
|
+
before(:each) do
|
15
|
+
@resource = FAKE_AWS.servers.new
|
16
|
+
@resource.stub(:tracker_account).and_return(FAKE_ACCOUNT)
|
17
|
+
@resource.stub(:identity).and_return "fake server ID"
|
18
|
+
@resource.stub(:status).and_return "running"
|
19
|
+
FogTracker::AccountTracker.any_instance.stub(:all_resources).
|
20
|
+
and_return([ @resource ])
|
21
|
+
end
|
22
|
+
|
23
|
+
it "Generates BillingRecords for all Resources in its accounts" do
|
24
|
+
@tracker.update
|
25
|
+
Billing::BillingRecord.all.count.should == 1
|
26
|
+
end
|
27
|
+
|
28
|
+
it "Generates billing codes for all Resources in its accounts" do
|
29
|
+
@resource.stub(:tags).and_return('environment' => 'sandbox')
|
30
|
+
@tracker.update
|
31
|
+
@tracker['*::Compute::AWS::servers'].first.billing_codes.should ==
|
32
|
+
[['environment', 'sandbox']]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
ENV['RACK_ENV'] ||= 'test'
|
2
|
+
Bundler.require # Load all gems and libs
|
3
|
+
|
4
|
+
Fog.mock! # Don't try to connect to the network
|
5
|
+
|
6
|
+
FAKE_ACCOUNT_NAME = 'Fake EC2 Account'
|
7
|
+
FAKE_ACCOUNT = {
|
8
|
+
:name => FAKE_ACCOUNT_NAME,
|
9
|
+
:provider => 'AWS',
|
10
|
+
:service => 'Compute',
|
11
|
+
:delay => 10,
|
12
|
+
:credentials => {
|
13
|
+
:aws_access_key_id => "fake user",
|
14
|
+
:aws_secret_access_key => 'fake password'
|
15
|
+
},
|
16
|
+
:exclude_resources => [
|
17
|
+
:spot_requests, # No Fog mocks for this resource
|
18
|
+
],
|
19
|
+
}
|
20
|
+
FAKE_ACCOUNTS = {FAKE_ACCOUNT_NAME => FAKE_ACCOUNT}
|
21
|
+
FAKE_AWS = Fog::Compute.new(
|
22
|
+
:provider => 'AWS',
|
23
|
+
:aws_access_key_id => 'XXXXXXXXXXXXXXXXXXXX',
|
24
|
+
:aws_secret_access_key => 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
|
25
|
+
)
|
26
|
+
FAKE_RDS = Fog::AWS::RDS.new(
|
27
|
+
:aws_access_key_id => 'XXXXXXXXXXXXXXXXXXXX',
|
28
|
+
:aws_secret_access_key => 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
|
29
|
+
)
|
30
|
+
|
31
|
+
## Establish ActiveRecord connection and Migrate database
|
32
|
+
# The following db config files are used, in order of preference:
|
33
|
+
# 1. ENV['DB_CONFIG_FILE']
|
34
|
+
# 2. ./config/database.yml
|
35
|
+
# 3. ./config/database.example.yml
|
36
|
+
db_conf_file = './config/database.example.yml'
|
37
|
+
db_conf_file = './config/database.yml' if File.exists? './config/database.yml'
|
38
|
+
if ENV['DB_CONFIG_FILE']
|
39
|
+
db_conf_file = ENV['DB_CONFIG_FILE']
|
40
|
+
else
|
41
|
+
ENV['DB_CONFIG_FILE'] = db_conf_file
|
42
|
+
end
|
43
|
+
puts "Reading DB config file #{db_conf_file}..."
|
44
|
+
db_config = YAML::load(File.open(db_conf_file))[CloudCostTracker.env]
|
45
|
+
puts "Using DB #{db_config['database']}..."
|
46
|
+
ActiveRecord::Base.establish_connection(db_config)
|
47
|
+
migration_dir = File.expand_path('../../db/migrate', __FILE__)
|
48
|
+
ActiveRecord::Migrator.migrate migration_dir
|
49
|
+
|
50
|
+
# Require RSpec support files. Logging is configured there
|
51
|
+
support_files = Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")]
|
52
|
+
support_files.sort.each {|f| require f}
|
53
|
+
|
54
|
+
# RSpec configuration block
|
55
|
+
RSpec.configure do |config|
|
56
|
+
config.mock_with :rspec # == Mock Framework
|
57
|
+
#config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
58
|
+
end
|
metadata
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cloud_cost_tracker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Benton Roberts
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: fog_tracker
|
16
|
+
requirement: &70113161132220 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.3.9
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70113161132220
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activerecord
|
27
|
+
requirement: &70113161130840 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70113161130840
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &70113161098660 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70113161098660
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
requirement: &70113161096820 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70113161096820
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: yard
|
60
|
+
requirement: &70113161095120 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70113161095120
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard
|
71
|
+
requirement: &70113161094320 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70113161094320
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: guard-rspec
|
82
|
+
requirement: &70113161092700 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70113161092700
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: ruby_gntp
|
93
|
+
requirement: &70113160454700 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70113160454700
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: sqlite3
|
104
|
+
requirement: &70113160454200 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *70113160454200
|
113
|
+
description: Periodically polls one or more cloud computing accounts using the fog
|
114
|
+
gem, and generates ActiveRecord rows representing BillingRecords for each discovered
|
115
|
+
resource.
|
116
|
+
email:
|
117
|
+
- benton@bentonroberts.com
|
118
|
+
executables:
|
119
|
+
- cloud_cost_tracker
|
120
|
+
extensions: []
|
121
|
+
extra_rdoc_files: []
|
122
|
+
files:
|
123
|
+
- .gitignore
|
124
|
+
- .yardopts
|
125
|
+
- Gemfile
|
126
|
+
- Guardfile
|
127
|
+
- LICENSE.TXT
|
128
|
+
- README.md
|
129
|
+
- Rakefile
|
130
|
+
- billing issues.md
|
131
|
+
- bin/cloud_cost_tracker
|
132
|
+
- cloud_cost_tracker.gemspec
|
133
|
+
- config/accounts.example.yml
|
134
|
+
- config/billing/compute-aws-servers/us-east-on_demand.yml
|
135
|
+
- config/billing/compute-aws-snapshots.yml
|
136
|
+
- config/billing/compute-aws-volumes.yml
|
137
|
+
- config/billing/elasticache-aws.yml
|
138
|
+
- config/billing/rds-aws-servers/us-east-on_demand-mysql.yml
|
139
|
+
- config/billing/rds-aws-servers/us-east-on_demand-storage.yml
|
140
|
+
- config/billing/storage-aws-directories.yml
|
141
|
+
- config/database.example.yml
|
142
|
+
- db/migrate/20120118000000_create_billing_records.rb
|
143
|
+
- db/migrate/20120119000000_create_billing_codes.rb
|
144
|
+
- lib/cloud_cost_tracker.rb
|
145
|
+
- lib/cloud_cost_tracker/billing/account_billing_policy.rb
|
146
|
+
- lib/cloud_cost_tracker/billing/compute/aws/servers.rb
|
147
|
+
- lib/cloud_cost_tracker/billing/compute/aws/snapshots.rb
|
148
|
+
- lib/cloud_cost_tracker/billing/compute/aws/volumes.rb
|
149
|
+
- lib/cloud_cost_tracker/billing/elasticache/clusters.rb
|
150
|
+
- lib/cloud_cost_tracker/billing/rds/server_storage.rb
|
151
|
+
- lib/cloud_cost_tracker/billing/rds/servers.rb
|
152
|
+
- lib/cloud_cost_tracker/billing/resource_billing_policy.rb
|
153
|
+
- lib/cloud_cost_tracker/billing/storage/aws/directories.rb
|
154
|
+
- lib/cloud_cost_tracker/coding/account_coding_policy.rb
|
155
|
+
- lib/cloud_cost_tracker/coding/compute/aws/account_coding_policy.rb
|
156
|
+
- lib/cloud_cost_tracker/coding/compute/aws/servers.rb
|
157
|
+
- lib/cloud_cost_tracker/coding/compute/aws/volumes.rb
|
158
|
+
- lib/cloud_cost_tracker/coding/rds/account_coding_policy.rb
|
159
|
+
- lib/cloud_cost_tracker/coding/rds/servers.rb
|
160
|
+
- lib/cloud_cost_tracker/coding/resource_coding_policy.rb
|
161
|
+
- lib/cloud_cost_tracker/extensions/fog_model.rb
|
162
|
+
- lib/cloud_cost_tracker/models/billing_code.rb
|
163
|
+
- lib/cloud_cost_tracker/models/billing_record.rb
|
164
|
+
- lib/cloud_cost_tracker/tasks.rb
|
165
|
+
- lib/cloud_cost_tracker/tracker.rb
|
166
|
+
- lib/cloud_cost_tracker/util/module_instrospection.rb
|
167
|
+
- lib/cloud_cost_tracker/version.rb
|
168
|
+
- lib/tasks/database.rake
|
169
|
+
- lib/tasks/rspec.rake
|
170
|
+
- lib/tasks/track.rake
|
171
|
+
- spec/lib/cloud_cost_tracker/billing/account_billing_policy_spec.rb
|
172
|
+
- spec/lib/cloud_cost_tracker/billing/resource_billing_policy_spec.rb
|
173
|
+
- spec/lib/cloud_cost_tracker/cloud_cost_tracker_spec.rb
|
174
|
+
- spec/lib/cloud_cost_tracker/coding/account_coding_policy_spec.rb
|
175
|
+
- spec/lib/cloud_cost_tracker/coding/resource_coding_policy_spec.rb
|
176
|
+
- spec/lib/cloud_cost_tracker/models/billing_code_spec.rb
|
177
|
+
- spec/lib/cloud_cost_tracker/models/billing_record_spec.rb
|
178
|
+
- spec/lib/cloud_cost_tracker/tracker_spec.rb
|
179
|
+
- spec/spec_helper.rb
|
180
|
+
- spec/support/_configure_logging.rb
|
181
|
+
- writing-billing-policies.md
|
182
|
+
- writing-coding-policies.md
|
183
|
+
homepage: http://github.com/benton/cloud_cost_tracker
|
184
|
+
licenses: []
|
185
|
+
post_install_message:
|
186
|
+
rdoc_options: []
|
187
|
+
require_paths:
|
188
|
+
- lib
|
189
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
190
|
+
none: false
|
191
|
+
requirements:
|
192
|
+
- - ! '>='
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
segments:
|
196
|
+
- 0
|
197
|
+
hash: 2940390420287301713
|
198
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
199
|
+
none: false
|
200
|
+
requirements:
|
201
|
+
- - ! '>='
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '0'
|
204
|
+
segments:
|
205
|
+
- 0
|
206
|
+
hash: 2940390420287301713
|
207
|
+
requirements: []
|
208
|
+
rubyforge_project: cloud_cost_tracker
|
209
|
+
rubygems_version: 1.8.15
|
210
|
+
signing_key:
|
211
|
+
specification_version: 3
|
212
|
+
summary: Records expenses for cloud computing resources in an ActiveRecord database
|
213
|
+
test_files:
|
214
|
+
- spec/lib/cloud_cost_tracker/billing/account_billing_policy_spec.rb
|
215
|
+
- spec/lib/cloud_cost_tracker/billing/resource_billing_policy_spec.rb
|
216
|
+
- spec/lib/cloud_cost_tracker/cloud_cost_tracker_spec.rb
|
217
|
+
- spec/lib/cloud_cost_tracker/coding/account_coding_policy_spec.rb
|
218
|
+
- spec/lib/cloud_cost_tracker/coding/resource_coding_policy_spec.rb
|
219
|
+
- spec/lib/cloud_cost_tracker/models/billing_code_spec.rb
|
220
|
+
- spec/lib/cloud_cost_tracker/models/billing_record_spec.rb
|
221
|
+
- spec/lib/cloud_cost_tracker/tracker_spec.rb
|
222
|
+
- spec/spec_helper.rb
|
223
|
+
- spec/support/_configure_logging.rb
|
224
|
+
has_rdoc:
|