vault_client 0.0.3 → 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.
@@ -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.