vault_client 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- module VaultClient
1
+ module VC
2
2
  class UnitGroupPresenter < BasePresenter
3
3
 
4
4
  attr_reader :unit_group
@@ -12,45 +12,33 @@ module VaultClient
12
12
  end
13
13
 
14
14
  def unit_presenters
15
- if defined?(@unit_presenters)
16
- @unit_presenters
17
- else
18
- @unit_presenters = @unit_group.units.map {|u| UnitPresenter.new(u)}
19
- end
20
- end
21
-
22
- def template
23
- if @unit_group.dyno_type?
24
- "line_item_types/dyno"
25
- elsif @unit_group.add_on_type?
26
- "line_item_types/add_on"
27
- elsif @unit_group.additional_type?
28
- "line_item_types/additional"
29
- end
30
- end
31
-
32
- def detail_template
33
- if @unit_group.run_type?
34
- "unit_group_types/flat"
35
- elsif @unit_group.dyno_type?
36
- "unit_group_types/metered"
37
- else
38
- "unit_group_types/brief"
39
- end
15
+ @unit_presenters ||= @unit_group.units.map {|u| UnitPresenter.new(u)}
40
16
  end
41
17
 
42
18
  def daily_report_url
43
- #TODO remove stub
19
+ #TODO remove chart stub
44
20
  #payments_uri("/billable_units/daily")
45
21
  "/billable_units/daily"
46
22
  end
47
23
 
48
24
  def compacted_reports
49
- #TODO remove stub
25
+ #TODO remove chart stub
50
26
  #BillableUnitReporter.compacted(@unit_group.units)
51
27
  []
52
28
  end
53
29
 
30
+ def total
31
+ money(@unit_group.total)
32
+ end
33
+
34
+ def qty
35
+ trunc_hours(@unit_group.qty)
36
+ end
37
+
38
+ def rate
39
+ @unit_group.rate
40
+ end
41
+
54
42
  def name
55
43
  @unit_group.name
56
44
  end
@@ -59,20 +47,17 @@ module VaultClient
59
47
  @unit_group.description
60
48
  end
61
49
 
62
- def qty
63
- trunc_hours(@unit_group.qty)
50
+ def product_name
51
+ @unit_group.product_name
64
52
  end
65
53
 
66
- def rate
54
+ def product_group
55
+ @unit_group.product_group
67
56
  end
68
57
 
69
58
  def unit_of_measure
70
- end
71
-
72
- def total
73
- money(@unit_group.total)
59
+ @unit_group.rate_period
74
60
  end
75
61
 
76
62
  end
77
63
  end
78
-
@@ -1,4 +1,4 @@
1
- module VaultClient
1
+ module VC
2
2
  class UnitPresenter < BasePresenter
3
3
 
4
4
  def initialize(unit)
@@ -6,7 +6,7 @@ module VaultClient
6
6
  end
7
7
 
8
8
  def total
9
- money(@unit.rate * @unit.qty)
9
+ money(@unit.total)
10
10
  end
11
11
 
12
12
  def rate
@@ -26,7 +26,7 @@ module VaultClient
26
26
  end
27
27
 
28
28
  def description
29
- @unit.subresource
29
+ @unit.product_name
30
30
  end
31
31
 
32
32
  end
@@ -1,4 +1,4 @@
1
- module VaultClient
1
+ module VC
2
2
  module LineItemBuilder
3
3
  extend self
4
4
 
@@ -1,88 +1,32 @@
1
- require 'rest-client'
2
1
  require 'yajl'
3
- require 'vault_helper'
4
- require 'resource_ownership_client'
5
- require 'billable_events_client'
6
- require 'usage_reports_client'
7
-
8
- module VaultClient
9
-
10
- AuthenticationError = Class.new(Exception)
11
- AuthorizationError = Class.new(Exception)
12
- ServiceDownError = Class.new(Exception)
13
- UnexpectedError = Class.new(Exception)
14
- SymanticError = Class.new(Exception)
15
-
16
- attr_accessor :url
2
+ require 'rest-client'
3
+ require 'helpers/http_helpers'
17
4
 
5
+ module VC
18
6
  extend self
19
-
20
- def resource_ownerships(action, args={})
21
- if ENV["VAULT_CLIENT_UNSAFE"] == "true"
22
- make_unsafe_request! {ResourceOwnershipClient.make_request(action, args)}
23
- else
24
- make_http_request {ResourceOwnershipClient.make_request(action, args)}
25
- end
26
- end
27
-
28
- def billable_events(action, args={})
29
- if ENV["VAULT_CLIENT_UNSAFE"] == "true"
30
- make_unsafe_request! {BillableEventsClient.make_request(action, args)}
31
- else
32
- make_http_request {BillableEventsClient.make_request(action, args)}
33
- end
34
- end
35
-
36
- def make_unsafe_request!
37
- begin
38
- resp = yield
39
- JSON.parse(resp.body)
40
- rescue RestClient => e
41
- return e.inspect
42
- end
43
- end
44
-
45
- def make_http_request(&block)
46
- block.call() do |resp, req, res|
47
- response_body = JSON.parse(resp.body)
48
- case resp.code
49
- when 200, 201
50
- response_body
51
- when 400, 401,
52
- raise(AuthenticationError, response_body)
53
- when 403
54
- raise(AuthorizationError, response_body)
55
- when 404
56
- raise(NotFound, response_body)
57
- when 422
58
- raise(SymanticError, response_body)
59
- when 500
60
- raise(UnexpectedError)
61
- when 503
62
- raise(ServiceDownError)
63
- end
64
- end
65
- end
66
-
67
- def url
68
- @url || ENV["VAULT_URL"]
69
- end
70
-
7
+ extend HttpHelpers
8
+
9
+ VCException = Class.new(Exception)
10
+ AuthenticationError = Class.new(VCException)
11
+ AuthorizationError = Class.new(VCException)
12
+ ServiceDownError = Class.new(VCException)
13
+ UnexpectedError = Class.new(VCException)
14
+ SymanticError = Class.new(VCException)
71
15
  end
72
16
 
73
- $:.unshift("lib")
74
17
 
75
- require 'models/usage_report'
18
+ require 'models/account'
76
19
  require 'models/billable_unit'
20
+ require 'models/report'
77
21
  require 'models/unit_group'
78
22
  require 'models/line_item'
23
+ require 'models/b_event'
24
+ require 'models/res_own'
79
25
 
80
26
  require 'services/line_item_builder'
81
- require 'services/report_builder'
82
-
83
- require 'dto/usage_report'
84
27
 
85
28
  require 'presenters/base_presenter'
86
- require 'presenters/report_presenter'
87
- require 'presenters/line_item_presenter'
88
29
  require 'presenters/unit_group_presenter'
30
+ require 'presenters/unit_presenter'
31
+ require 'presenters/line_item_presenter'
32
+ require 'presenters/report_presenter'
data/readme.md CHANGED
@@ -3,17 +3,15 @@
3
3
  ## Purpose
4
4
 
5
5
  This gem wraps the APIs defined [here](https://github.com/heroku/shushu/tree/master/doc).
6
+ The vault_client also provides a set of objects that help with the presentation
7
+ of an invoice.
6
8
 
7
- ## Usage
8
-
9
- ### Setup
9
+ ## Setup
10
10
 
11
11
  ```bash
12
12
  $ gem install vault_client
13
13
  ```
14
14
 
15
- ### Configure
16
-
17
15
  ```bash
18
16
  # Optional. When set, vault_client will ignore bad responses from The Vault's API.
19
17
  # Default: false
@@ -27,42 +25,208 @@ $VAULT_URL=https://vault-stg.heroku.com
27
25
  **Ruby configuration will take precedence over environment variables.**
28
26
 
29
27
  ```ruby
30
- VaultClient.url = "https://core:secret@vault-stg.heroku.com"
28
+ VC.url = "https://core:secret@vault-stg.heroku.com"
31
29
  ```
32
30
 
33
- ### Resource Ownership
31
+ ## Usage
32
+
33
+ ### PaymentMethods
34
+
35
+ This API deals primarily with credit cards. PaymentMethods can be created
36
+ indipendintly of Accounts. You will need a payment_method to generate an
37
+ invoice.
38
+
39
+ ```ruby
40
+ #TODO Build API
41
+ ```
42
+
43
+ ### Accounts
44
+
45
+ This API deals with accounts which is a primitive for grouping resources. You
46
+ will need an account to generate a usage report.
47
+
48
+ ```ruby
49
+ VC::Account.create
50
+ #=> {:id => "001"}
51
+ ```
52
+
53
+ ### AccountOwnerships
54
+
55
+ Use this API when you want to setup associations between Vault accounts and
56
+ Vault payment_methods.
57
+
58
+ For complete details on the semantics of this API, read the [AccountOwnerships
59
+ API docs.](https://github.com/heroku/shushu/blob/master/doc/account_ownership_api.md)
60
+
61
+ ```ruby
62
+ # To associate an account with a payment_method
63
+ VC::AcctOwn.act(
64
+ :account_id => vault_account_id,
65
+ :payment_method_id => payment_method_id,
66
+ :entity_id => entity_id,
67
+ :time => time
68
+ )
69
+ #=> {"payment_method_id"=>"123", "account_id"=>"1", "entity_id"=>"entity123"}
70
+
71
+ # Now we need to change the payment_method on an account
72
+ VC::AcctOwn.xfr(
73
+ :prev_payment_method_id => prev_payment_method_id,
74
+ :payment_method_id => new_payment_method_id,
75
+ :account_id => account_id,
76
+ :prev_entity_id => prev_entity_id,
77
+ :entity_id => entity_id,
78
+ :time => time
79
+ )
80
+ #=> {"payment_method_id"=>"456", "account_id"=>"1", "entity_id"=>"event124"}
81
+ ```
82
+
83
+ ### ResourceOwnerships
84
+
85
+ Use this API when dealing with resources and Vault accounts. For instance:
86
+ Heroku apps and Teams.
87
+
88
+ For complete details on the semantics of this API, read the [ResourceOwnerships
89
+ API docs.](https://github.com/heroku/shushu/blob/master/doc/resource_ownership_api.md)
34
90
 
35
91
  ```ruby
36
92
  # When a new app is created, activate a new resource_ownership record.
37
- VaultClient.resource_ownerships(:activate, hid, vault_account_id, time, event_id)
38
- #=> {"hid"=>"123", "account_id"=>"1", "event_id"=>"event123"}
93
+ VC::ResOwn.act(
94
+ :hid => hid,
95
+ :entity_id => entity_id,
96
+ :account_id => vault_account_id,
97
+ :time => time
98
+ )
99
+ #=> {"hid"=>"123", "account_id"=>"1", "entity_id"=>"event123"}
39
100
 
40
101
 
41
102
  # When an app is transfered to another vault account, transfer the resource_ownership record.
42
- VaultClient.resource_ownerships(:transfer, hid, prev_vault_account_id, new_vault_account_id, time, prev_event_id, event_id)
43
- #=> {"hid"=>"123", "account_id"=>"1", "event_id"=>"event123"}
103
+ VC::ResOwn.xfr(
104
+ :hid => hid,
105
+ :prev_entity_id => prev_entity_id,
106
+ :prev_vault_account_id => prev_vault_account_id,
107
+ :entity_id => entity_id,
108
+ :account_id => new_vault_account_id,
109
+ :time => time
110
+ )
111
+ #=> {"hid"=>"123", "account_id"=>"1", "entity_id"=>"event123"}
44
112
 
45
113
  # When an app is destroyed, deactivate the resource_ownership record.
46
- VaultClient.resource_ownerships(:deactivate, hid, new_vault_account_id, time, event_id)
47
- #=> {"hid"=>"123", "account_id"=>"1", "event_id"=>"event123"}
114
+ VC::ResOwn.deact(
115
+ :hid => hid,
116
+ :entity_id => entity_id,
117
+ :account_id => vault_account_id,
118
+ :time => time
119
+ )
120
+ #=> {"hid"=>"123", "account_id"=>"1", "entity_id"=>"event123"}
48
121
  ```
49
122
 
50
- ## Hacking
123
+ ### BillableEvents
51
124
 
52
- ### Supporting a vault endpoint
125
+ Use this API when you want to start billing for a resource. You can start
126
+ emitting events prior to setting up relationships between accounts and
127
+ payment_methods. (Although, usage reports and invoices will not be available
128
+ until account_ownerships and resource_ownerships have been established.)
53
129
 
54
- Define a method in the VaultClient module that looks like the name of the http
55
- resource. Have this method dispatch the call to another modle that implements
56
- the detail of the api. The aforementioned API client module should only return
57
- the data that is needed by rest-client to submit the request.
130
+ For complete details on the semantics of this API, read the [BillableEvents
131
+ API docs.](https://github.com/heroku/shushu/blob/master/doc/events_api.md)
58
132
 
59
- ### Running the tests
133
+ ```ruby
134
+ # Open an event when you would like to start billing.
135
+ VC::BEvent.open(
136
+ :entity_id => entity_id,
137
+ :hid => hid,
138
+ :time => time,
139
+ :rate_code => rate_code,
140
+ :product_name => product_name,
141
+ :qty => qty
142
+ )
143
+
144
+ # Don't forget to close it.
145
+ VC::BEvent.close(
146
+ :entity_id => entity_id,
147
+ :time => time
148
+ )
149
+ ```
60
150
 
61
- We only test that our API client modules return the http parameters and the body
62
- for the http request. We trust that when rest-client is used correctly it will
63
- work.
151
+ ### UsageReports
64
152
 
65
- ```bash
66
- $ bundle
67
- $ bundle turn test/
153
+ ```ruby
154
+ report = VC::UsageReport.new(account_id, from, to)
155
+ report.billable_units
156
+ ```
157
+
158
+
159
+ ### Invoices
160
+
161
+ ```ruby
162
+ invoice = VC::UsageReport.new(account_id, from, to)
163
+ invoice.billable_units
68
164
  ```
165
+
166
+
167
+ ### Report Generation
168
+
169
+ Invoices and UsageReports can be used for report generation. Basically, the
170
+ report generation code expects a collection of BillableUnits. BillableUnits are
171
+ returned from both the Invoice API and the UsageReport API. However, the details
172
+ of the billable_units may be different with respect to the type of the report.
173
+
174
+ #### Presenters
175
+
176
+ Clients of this library will want to generate some sort of view for the reports, the
177
+ presenter objects were created to aid with that effort. You should only need to
178
+ use the presenters while building views. Each view wraps a simple model object.
179
+ All of the models and presenters are derived from the billable_unit which is
180
+ retreived from the remote API.
181
+
182
+ Report --> LineItem --> UnitGroup --> Billable Unit
183
+
184
+
185
+ #### ReportPresenter
186
+
187
+ The report presenter is how you will kick off the process of generating a
188
+ report. You hand it a report object, either a UsageReport or and Invoice, and
189
+ using the reports billable_units, it will build the line_items and a set of
190
+ line_item_presenters for the line_items.
191
+
192
+ #### LineItemBuilder
193
+
194
+ The ReportPresenter will create a set of line_items based upon the
195
+ billable_units in the report. The default is to group things by HID. Thus there
196
+ will be a line_item for each distinct HID in the set of billable_units. The
197
+ builder will also give a collection of unit_groups to the line_item. By default,
198
+ the unit_groups will be partitioned by the product_group. (i.e. dyno, addon)
199
+
200
+ You can customize the LineItemBuilder by creating a new class that responds to
201
+ build and passing it to the ReportPresenter.
202
+
203
+ ```ruby
204
+ ReportPresenter.new(report, CustomLineItemBuilder)
205
+ ```
206
+
207
+ #### LineItemPresenter
208
+
209
+ The LineItemPresenter is responsible for handling the total and names of the
210
+ line_items. It also manages the set of unit_groups. Since the default
211
+ LineItemBuilder partitioned unit_groups based upon product_group, you can ask
212
+ the LineItemPresenter for infomation about subsets of unit_groups. For instance:
213
+
214
+ ```ruby
215
+ line_item_presenter.unit_group_presenters("dyno")
216
+ line_item_presenter.unit_group_total("dyno")
217
+ line_item_presenter.unit_group_qty("dyno")
218
+ ```
219
+
220
+
221
+ #### UnitGroupPresenter
222
+
223
+ UnitGroups are collections of billable_units that are partitioned by
224
+ product_name. So if there exists a set of billable_units that all have
225
+ product_group = "dyno" and product_name= "worker", then this presenter
226
+ will give you information about that group.
227
+
228
+
229
+ #### UnitPresenter
230
+
231
+ Finally, the UnitPresenter wraps a billable_unit and exposes methods to show
232
+ totals, quantities and other meta-data.