vault-tools 1.0.1 → 2.0.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/.travis.yml +4 -3
- data/Gemfile +3 -2
- data/Gemfile.lock +37 -43
- data/README.md +0 -13
- data/lib/vault-tools.rb +1 -5
- data/lib/vault-tools/app.rb +3 -3
- data/lib/vault-tools/config.rb +6 -24
- data/lib/vault-tools/log.rb +2 -2
- data/lib/vault-tools/pipeline.rb +1 -1
- data/lib/vault-tools/s3.rb +9 -9
- data/lib/vault-tools/statement_store.rb +15 -9
- data/lib/vault-tools/time.rb +1 -1
- data/lib/vault-tools/user.rb +3 -3
- data/lib/vault-tools/version.rb +1 -1
- data/lib/vault-tools/web.rb +1 -0
- data/test/config_test.rb +5 -34
- data/test/defaults_test.rb +4 -4
- data/test/helper.rb +12 -46
- data/test/s3_test.rb +16 -16
- data/test/statement_store_test.rb +9 -12
- data/vault-tools.gemspec +8 -7
- metadata +12 -41
- data/lib/vault-tools/tracing.rb +0 -92
- data/lib/vault-tools/tracing/sidekiq_client.rb +0 -37
- data/lib/vault-tools/tracing/sidekiq_server.rb +0 -54
- data/test/tracing_test.rb +0 -86
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9265591e92a631fd1b996644985ee742c622ac3259412dc5b7ca2e6ff3c7aebe
|
|
4
|
+
data.tar.gz: b01e51fe465c1a001685bd909fcbfec83757005cad808b34918328af0fca4906
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3910495873e72ce2299d303118e790fa42f22ec6acd0fe440d2d1ca595a394e50afc30e58751a352db9b5ed87f6448aa88db042ab8059bee6b9b58da53376df7
|
|
7
|
+
data.tar.gz: 4dd78be8dec844bb89a2729309ffe80f8084736c9535e0d74ecf8a352cffde2fa9f548cc303443732aa0e750ae5c0074257adeae54e28f38c72548c804dab6d8
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
|
@@ -4,12 +4,13 @@ source 'https://rubygems.org'
|
|
|
4
4
|
gemspec
|
|
5
5
|
|
|
6
6
|
group :development do
|
|
7
|
-
gem 'rake', '~>
|
|
7
|
+
gem 'rake', '~> 12.3'
|
|
8
8
|
gem 'shotgun', '~> 0.9.2'
|
|
9
9
|
gem 'yard-sinatra'
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
group :test do
|
|
13
13
|
gem 'guard-minitest'
|
|
14
|
-
gem '
|
|
14
|
+
gem 'minitest-around'
|
|
15
|
+
gem 'vault-test-tools', '~> 1.0.0'
|
|
15
16
|
end
|
data/Gemfile.lock
CHANGED
|
@@ -1,84 +1,82 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
vault-tools (
|
|
5
|
-
aws-sdk (~> 1.0)
|
|
4
|
+
vault-tools (2.0.0)
|
|
5
|
+
aws-sdk-s3 (~> 1.0)
|
|
6
6
|
coderay
|
|
7
7
|
excon
|
|
8
|
-
fernet (= 2.0
|
|
9
|
-
heroku-api
|
|
8
|
+
fernet (= 2.0)
|
|
10
9
|
rack (~> 2.0)
|
|
11
10
|
rack-ssl-enforcer
|
|
12
|
-
rollbar (~> 2.
|
|
11
|
+
rollbar (~> 2.18.2)
|
|
13
12
|
scrolls (~> 0.9)
|
|
14
13
|
sinatra (~> 2.0.4)
|
|
15
14
|
uuidtools
|
|
16
|
-
zipkin-tracer (~> 0.27)
|
|
17
15
|
|
|
18
16
|
GEM
|
|
19
17
|
remote: https://rubygems.org/
|
|
20
18
|
specs:
|
|
21
|
-
aws-
|
|
22
|
-
|
|
23
|
-
aws-sdk-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
aws-eventstream (1.0.1)
|
|
20
|
+
aws-partitions (1.127.0)
|
|
21
|
+
aws-sdk-core (3.44.1)
|
|
22
|
+
aws-eventstream (~> 1.0)
|
|
23
|
+
aws-partitions (~> 1.0)
|
|
24
|
+
aws-sigv4 (~> 1.0)
|
|
25
|
+
jmespath (~> 1.0)
|
|
26
|
+
aws-sdk-kms (1.13.0)
|
|
27
|
+
aws-sdk-core (~> 3, >= 3.39.0)
|
|
28
|
+
aws-sigv4 (~> 1.0)
|
|
29
|
+
aws-sdk-s3 (1.30.0)
|
|
30
|
+
aws-sdk-core (~> 3, >= 3.39.0)
|
|
31
|
+
aws-sdk-kms (~> 1)
|
|
32
|
+
aws-sigv4 (~> 1.0)
|
|
33
|
+
aws-sigv4 (1.0.3)
|
|
26
34
|
coderay (1.1.2)
|
|
27
|
-
concurrent-ruby (1.1.3)
|
|
28
35
|
dotenv (2.5.0)
|
|
29
36
|
excon (0.62.0)
|
|
30
|
-
|
|
31
|
-
multipart-post (>= 1.2, < 3)
|
|
32
|
-
fernet (2.0.rc2)
|
|
37
|
+
fernet (2.0)
|
|
33
38
|
valcro (= 0.1)
|
|
34
|
-
finagle-thrift (1.4.2)
|
|
35
|
-
thrift (~> 0.9.3)
|
|
36
39
|
guard-compat (1.2.1)
|
|
37
40
|
guard-minitest (2.4.6)
|
|
38
41
|
guard-compat (~> 1.2)
|
|
39
42
|
minitest (>= 3.0)
|
|
40
|
-
|
|
41
|
-
excon (~> 0.45)
|
|
42
|
-
multi_json (~> 1.8)
|
|
43
|
-
json (1.8.6)
|
|
43
|
+
jmespath (1.4.0)
|
|
44
44
|
logfmt (0.0.8)
|
|
45
45
|
method_source (0.9.2)
|
|
46
|
-
mini_portile2 (2.
|
|
46
|
+
mini_portile2 (2.4.0)
|
|
47
47
|
minitest (5.11.3)
|
|
48
|
+
minitest-around (0.5.0)
|
|
49
|
+
minitest (~> 5.0)
|
|
48
50
|
multi_json (1.13.1)
|
|
49
|
-
multipart-post (2.0.0)
|
|
50
51
|
mustermann (1.0.3)
|
|
51
|
-
nokogiri (1.
|
|
52
|
-
mini_portile2 (~> 2.
|
|
52
|
+
nokogiri (1.10.1)
|
|
53
|
+
mini_portile2 (~> 2.4.0)
|
|
53
54
|
pry (0.12.2)
|
|
54
55
|
coderay (~> 1.1.0)
|
|
55
56
|
method_source (~> 0.9.0)
|
|
56
57
|
rack (2.0.6)
|
|
57
|
-
rack-protection (2.0.
|
|
58
|
+
rack-protection (2.0.5)
|
|
58
59
|
rack
|
|
59
60
|
rack-ssl-enforcer (0.2.9)
|
|
60
61
|
rack-test (1.1.0)
|
|
61
62
|
rack (>= 1.0, < 3)
|
|
62
|
-
rake (
|
|
63
|
-
rdoc (6.
|
|
64
|
-
rollbar (2.
|
|
63
|
+
rake (12.3.2)
|
|
64
|
+
rdoc (6.1.1)
|
|
65
|
+
rollbar (2.18.2)
|
|
65
66
|
multi_json
|
|
66
67
|
rr (1.2.1)
|
|
67
68
|
scrolls (0.9.0)
|
|
68
69
|
shotgun (0.9.2)
|
|
69
70
|
rack (>= 1.0)
|
|
70
|
-
sinatra (2.0.
|
|
71
|
+
sinatra (2.0.5)
|
|
71
72
|
mustermann (~> 1.0)
|
|
72
73
|
rack (~> 2.0)
|
|
73
|
-
rack-protection (= 2.0.
|
|
74
|
+
rack-protection (= 2.0.5)
|
|
74
75
|
tilt (~> 2.0)
|
|
75
|
-
|
|
76
|
-
concurrent-ruby (~> 1.0)
|
|
77
|
-
thrift (0.9.3.0)
|
|
78
|
-
tilt (2.0.8)
|
|
76
|
+
tilt (2.0.9)
|
|
79
77
|
uuidtools (2.1.5)
|
|
80
78
|
valcro (0.1)
|
|
81
|
-
vault-test-tools (0.
|
|
79
|
+
vault-test-tools (1.0.0)
|
|
82
80
|
logfmt
|
|
83
81
|
minitest (~> 5.11)
|
|
84
82
|
nokogiri
|
|
@@ -88,11 +86,6 @@ GEM
|
|
|
88
86
|
yard (0.9.16)
|
|
89
87
|
yard-sinatra (1.0.0)
|
|
90
88
|
yard (~> 0.7)
|
|
91
|
-
zipkin-tracer (0.29.1)
|
|
92
|
-
faraday (~> 0.8)
|
|
93
|
-
finagle-thrift (~> 1.4.2)
|
|
94
|
-
rack (>= 1.0)
|
|
95
|
-
sucker_punch (~> 2.0)
|
|
96
89
|
|
|
97
90
|
PLATFORMS
|
|
98
91
|
ruby
|
|
@@ -100,11 +93,12 @@ PLATFORMS
|
|
|
100
93
|
DEPENDENCIES
|
|
101
94
|
dotenv
|
|
102
95
|
guard-minitest
|
|
96
|
+
minitest-around
|
|
103
97
|
pry
|
|
104
|
-
rake (~>
|
|
98
|
+
rake (~> 12.3)
|
|
105
99
|
rdoc
|
|
106
100
|
shotgun (~> 0.9.2)
|
|
107
|
-
vault-test-tools (~> 0.
|
|
101
|
+
vault-test-tools (~> 1.0.0)
|
|
108
102
|
vault-tools!
|
|
109
103
|
yard
|
|
110
104
|
yard-sinatra
|
data/README.md
CHANGED
|
@@ -26,9 +26,6 @@ calling `Vault.setup` will:
|
|
|
26
26
|
- if the `CONFIG_APP` environment variable is defined and this is
|
|
27
27
|
the production environment, it will attempt to use the Heroku API
|
|
28
28
|
to load the config vars from another app into `Vault::Config`
|
|
29
|
-
- enable distributed tracing via Zipkin, if the [required config
|
|
30
|
-
vars](#configs-for-tracing) are set
|
|
31
|
-
|
|
32
29
|
|
|
33
30
|
### `Vault::Config`
|
|
34
31
|
|
|
@@ -93,16 +90,6 @@ Generate the API documentation:
|
|
|
93
90
|
|
|
94
91
|
vendor/bin/d
|
|
95
92
|
|
|
96
|
-
## Configs for tracing
|
|
97
|
-
|
|
98
|
-
The following are config vars to be set in the consumer app for tracing with
|
|
99
|
-
Zipkin:
|
|
100
|
-
* `APP_NAME` (required) what the trace will show up as in the Zipkin interface.
|
|
101
|
-
* `ZIPKIN_ENABLED` (required) must be set to `true` to start tracing.
|
|
102
|
-
* `ZIPKIN_API_HOST` (required) where to post traces to. URL must contain the
|
|
103
|
-
basic auth creds from the Tools team.
|
|
104
|
-
* `ZIPKIN_SAMPLE_RATE` defaults to `0.1`.
|
|
105
|
-
|
|
106
93
|
## Releasing
|
|
107
94
|
|
|
108
95
|
> bundle exec rake release
|
data/lib/vault-tools.rb
CHANGED
|
@@ -3,8 +3,8 @@ require "vault-tools/version"
|
|
|
3
3
|
require 'sinatra/base'
|
|
4
4
|
require 'scrolls'
|
|
5
5
|
require 'rack/ssl-enforcer'
|
|
6
|
-
require 'heroku-api'
|
|
7
6
|
require 'rollbar'
|
|
7
|
+
require 'excon'
|
|
8
8
|
|
|
9
9
|
# Yes, there's a lot of stuff on STDERR. But its on
|
|
10
10
|
# stderr and not stdout so you can pipe to /dev/null if
|
|
@@ -72,7 +72,6 @@ module Vault
|
|
|
72
72
|
self.override_global_config
|
|
73
73
|
self.load_shared_config
|
|
74
74
|
self.init_scrolls
|
|
75
|
-
Tracing.configure
|
|
76
75
|
end
|
|
77
76
|
end
|
|
78
77
|
|
|
@@ -90,9 +89,6 @@ require 'vault-tools/time'
|
|
|
90
89
|
require 'vault-tools/s3'
|
|
91
90
|
require 'vault-tools/statement_store'
|
|
92
91
|
require 'vault-tools/rollbar_helper'
|
|
93
|
-
require 'vault-tools/tracing/sidekiq_client'
|
|
94
|
-
require 'vault-tools/tracing/sidekiq_server'
|
|
95
|
-
require 'vault-tools/tracing'
|
|
96
92
|
|
|
97
93
|
Rollbar.configure do |config|
|
|
98
94
|
config.environment = ENV['RACK_ENV'] || ENV['RAILS_ENV'] || ENV['APP_ENV'] || ENV['ROLLBAR_ENV'] || 'unassigned'
|
data/lib/vault-tools/app.rb
CHANGED
|
@@ -5,7 +5,7 @@ module Vault
|
|
|
5
5
|
ID_CAPTURE = /\Aapp(\d+)\@[\w\.]+com\z/
|
|
6
6
|
# Convert a core app ID into a Heroku app ID.
|
|
7
7
|
#
|
|
8
|
-
# @param app_id [
|
|
8
|
+
# @param app_id [Integer] A core app ID.
|
|
9
9
|
# @return [String] A Heroku ID that uniquely represents the app.
|
|
10
10
|
def self.id_to_hid(app_id)
|
|
11
11
|
"app#{app_id}@heroku.com"
|
|
@@ -13,7 +13,7 @@ module Vault
|
|
|
13
13
|
|
|
14
14
|
# Convert a core app ID into a v5 UUID.
|
|
15
15
|
#
|
|
16
|
-
# @param app_id [
|
|
16
|
+
# @param app_id [Integer] An app ID.
|
|
17
17
|
# @return [String] A v5 UUID that uniquely represents the app.
|
|
18
18
|
def self.id_to_uuid(app_id)
|
|
19
19
|
url = "https://vault.heroku.com/apps/#{app_id}"
|
|
@@ -24,7 +24,7 @@ module Vault
|
|
|
24
24
|
#
|
|
25
25
|
# @param heroku_id [String] A Heroku app ID, such as `app1234@heroku.com`.
|
|
26
26
|
# @raise [ArgumentError] Raised if a malformed Heroku ID is provided.
|
|
27
|
-
# @return [
|
|
27
|
+
# @return [Integer] The core app ID that uniquely represents the app.
|
|
28
28
|
def self.hid_to_id(heroku_id)
|
|
29
29
|
if app_id = heroku_id.slice(ID_CAPTURE, 1)
|
|
30
30
|
app_id.to_i
|
data/lib/vault-tools/config.rb
CHANGED
|
@@ -32,30 +32,12 @@ module Vault
|
|
|
32
32
|
ENV[var_name] || @@shared[var_name] || @@defaults[default_name]
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
# Loads config from another app.
|
|
36
|
-
def self.load_shared!(app = nil)
|
|
37
|
-
heroku = Heroku::API.new
|
|
38
|
-
@@shared = heroku.get_config_vars(app).body
|
|
39
|
-
end
|
|
40
|
-
|
|
41
35
|
# Reset defaults and shared values
|
|
42
36
|
def self.reset!
|
|
43
37
|
@@defaults = {}
|
|
44
38
|
@@shared = {}
|
|
45
39
|
end
|
|
46
40
|
|
|
47
|
-
# An environment variable from another app.
|
|
48
|
-
#
|
|
49
|
-
# @param app [String] The name of the app to get the value from.
|
|
50
|
-
# @param name [String] The name of the environment variable to fetch a
|
|
51
|
-
# value for.
|
|
52
|
-
# @return [String] The value of an environment variable from another
|
|
53
|
-
# Heroku app or nil if no match is available.
|
|
54
|
-
def self.remote_env(app, name)
|
|
55
|
-
heroku = Heroku::API.new
|
|
56
|
-
heroku.get_config_vars(app).body[name]
|
|
57
|
-
end
|
|
58
|
-
|
|
59
41
|
# An environment variable.
|
|
60
42
|
#
|
|
61
43
|
# @param name [String] The name of the environment variable to fetch a
|
|
@@ -126,7 +108,7 @@ module Vault
|
|
|
126
108
|
|
|
127
109
|
# The port to listen on for web requests.
|
|
128
110
|
#
|
|
129
|
-
# @return [
|
|
111
|
+
# @return [Integer] The port to listen on for web requests.
|
|
130
112
|
def self.port
|
|
131
113
|
env!("PORT").to_i
|
|
132
114
|
end
|
|
@@ -148,12 +130,12 @@ module Vault
|
|
|
148
130
|
!bool?('VAULT_TOOLS_DISABLE_SSL')
|
|
149
131
|
end
|
|
150
132
|
|
|
151
|
-
# An environment variable converted to a
|
|
133
|
+
# An environment variable converted to a Integer.
|
|
152
134
|
#
|
|
153
135
|
# @param name [String] The name of the environment variable to fetch a
|
|
154
|
-
#
|
|
155
|
-
# @return [
|
|
156
|
-
#
|
|
136
|
+
# Integer for.
|
|
137
|
+
# @return [Integer] The number or nil if the value couldn't be coerced to a
|
|
138
|
+
# Integer.
|
|
157
139
|
def self.int(name)
|
|
158
140
|
self[name] && self[name].to_i
|
|
159
141
|
end
|
|
@@ -194,7 +176,7 @@ module Vault
|
|
|
194
176
|
|
|
195
177
|
# The number of threads to use in Sidekiq workers.
|
|
196
178
|
#
|
|
197
|
-
# @return [
|
|
179
|
+
# @return [Integer] The number of threads from the `SIDEKIQ_CONCURRENCY`
|
|
198
180
|
# environment variable or 25 if no variable is defined.
|
|
199
181
|
def self.sidekiq_concurrency
|
|
200
182
|
int('SIDEKIQ_CONCURRENCY') || 25
|
data/lib/vault-tools/log.rb
CHANGED
|
@@ -19,7 +19,7 @@ module Vault
|
|
|
19
19
|
# This makes it possible to easily measure individual HTTP status codes as
|
|
20
20
|
# well as classes of HTTP status codes.
|
|
21
21
|
#
|
|
22
|
-
# @param status [
|
|
22
|
+
# @param status [Integer] The HTTP status code to record.
|
|
23
23
|
def self.count_status(status)
|
|
24
24
|
count("http.#{status}")
|
|
25
25
|
if status_prefix = status.to_s.match(/\d/)[0]
|
|
@@ -39,7 +39,7 @@ module Vault
|
|
|
39
39
|
# Log a timing metric.
|
|
40
40
|
#
|
|
41
41
|
# @param name [String] A Sinatra-formatted route URL.
|
|
42
|
-
# @param duration [
|
|
42
|
+
# @param duration [Integer] The duration to record, in milliseconds.
|
|
43
43
|
def self.time(name, duration)
|
|
44
44
|
if name
|
|
45
45
|
name.gsub(/\/:\w+/, ''). # Remove param names from path.
|
data/lib/vault-tools/pipeline.rb
CHANGED
data/lib/vault-tools/s3.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require 'aws-sdk'
|
|
1
|
+
require 'aws-sdk-s3'
|
|
2
2
|
|
|
3
3
|
module S3
|
|
4
4
|
extend self
|
|
@@ -10,7 +10,7 @@ module S3
|
|
|
10
10
|
# @param value [String]
|
|
11
11
|
def write(bucket, key, value)
|
|
12
12
|
Vault::Log.log(:fn => __method__, :key => key) do
|
|
13
|
-
s3.
|
|
13
|
+
s3.put_object({bucket: bucket, key: key, body: value})
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -20,17 +20,17 @@ module S3
|
|
|
20
20
|
# @param key [String]
|
|
21
21
|
def read(bucket, key)
|
|
22
22
|
Vault::Log.log(:fn => __method__, :key => key) do
|
|
23
|
-
s3.
|
|
23
|
+
s3.get_object({bucket: bucket, key: key}).body.read
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
# Get the underlying AWS::S3 instance, creating it using environment
|
|
28
|
-
# if necessary.
|
|
27
|
+
# Get the underlying AWS::S3::Client instance, creating it using environment
|
|
28
|
+
# vars if necessary.
|
|
29
29
|
def s3
|
|
30
|
-
@s3 ||=
|
|
31
|
-
:
|
|
32
|
-
|
|
33
|
-
:
|
|
30
|
+
@s3 ||= Aws::S3::Client.new(
|
|
31
|
+
credentials: Aws::Credentials.new(Config.env('AWS_ACCESS_KEY_ID'),
|
|
32
|
+
Config.env('AWS_SECRET_ACCESS_KEY')),
|
|
33
|
+
region: Config.env('AWS_REGION')
|
|
34
34
|
)
|
|
35
35
|
end
|
|
36
36
|
|
|
@@ -2,8 +2,9 @@ module Vault
|
|
|
2
2
|
# The StatementStore knows how to save and retrieve invoices from S3
|
|
3
3
|
class StatementStore
|
|
4
4
|
def initialize(opts = {})
|
|
5
|
-
@
|
|
6
|
-
|
|
5
|
+
@credentials = Aws::Credentials.new(opts.fetch(:key_id, Config[:aws_access_key_id]),
|
|
6
|
+
opts.fetch(:key, Config[:aws_secret_access_key]))
|
|
7
|
+
@region = opts.fetch(:region, Config[:aws_region])
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
# Retrieve invoice JSON from S3
|
|
@@ -34,20 +35,24 @@ module Vault
|
|
|
34
35
|
|
|
35
36
|
# Retrieve the contents in a given format of a given file from S3
|
|
36
37
|
def retrieve(format, opts)
|
|
37
|
-
s3.
|
|
38
|
+
s3.get_object({
|
|
39
|
+
bucket: bucket_for(format, opts),
|
|
40
|
+
key: path_for(opts)
|
|
41
|
+
}).body.read
|
|
38
42
|
end
|
|
39
43
|
|
|
40
44
|
# Write the contents in the given format to S3
|
|
41
45
|
def write(format, opts)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
s3.put_object({
|
|
47
|
+
bucket: bucket_for(format, opts),
|
|
48
|
+
key: path_for(opts),
|
|
49
|
+
body: opts[:contents]
|
|
50
|
+
})
|
|
45
51
|
end
|
|
46
52
|
|
|
47
53
|
# Get an instance of the S3 client to work with
|
|
48
54
|
def s3
|
|
49
|
-
@s3 ||=
|
|
50
|
-
use_ssl: true)
|
|
55
|
+
@s3 ||= Aws::S3::Client.new(credentials: @credentials, region: @region)
|
|
51
56
|
end
|
|
52
57
|
|
|
53
58
|
# Determine which bucket an invoice should live in
|
|
@@ -73,10 +78,11 @@ module Vault
|
|
|
73
78
|
private
|
|
74
79
|
|
|
75
80
|
def validate_path_opts(opts)
|
|
81
|
+
user = opts[:user_hid] || opts[:user_id]
|
|
82
|
+
|
|
76
83
|
fail(ArgumentError, 'start_time required!') unless opts[:start_time]
|
|
77
84
|
fail(ArgumentError, 'stop_time required!') unless opts[:stop_time]
|
|
78
85
|
fail(ArgumentError, 'version required!') unless opts[:version]
|
|
79
|
-
user = opts[:user_hid] || opts[:user_id]
|
|
80
86
|
fail(ArgumentError, 'user_hid or or user_id required!') unless user
|
|
81
87
|
end
|
|
82
88
|
end
|
data/lib/vault-tools/time.rb
CHANGED
data/lib/vault-tools/user.rb
CHANGED
|
@@ -5,7 +5,7 @@ module Vault
|
|
|
5
5
|
ID_CAPTURE = /^user(\d+)\@[\w\.]+com$/
|
|
6
6
|
# Convert a user ID into a Heroku user ID.
|
|
7
7
|
#
|
|
8
|
-
# @param user_id [
|
|
8
|
+
# @param user_id [Integer] A user ID.
|
|
9
9
|
# @return [String] A Heroku ID that uniquely represents the user.
|
|
10
10
|
def self.id_to_hid(user_id)
|
|
11
11
|
"user#{user_id}@heroku.com"
|
|
@@ -13,7 +13,7 @@ module Vault
|
|
|
13
13
|
|
|
14
14
|
# Convert a user ID into a v5 UUID.
|
|
15
15
|
#
|
|
16
|
-
# @param user_id [
|
|
16
|
+
# @param user_id [Integer] A user ID.
|
|
17
17
|
# @return [String] A v5 UUID that uniquely represents the user.
|
|
18
18
|
def self.id_to_uuid(user_id)
|
|
19
19
|
url = "https://vault.heroku.com/users/#{user_id}"
|
|
@@ -25,7 +25,7 @@ module Vault
|
|
|
25
25
|
# @param heroku_id [String] A Heroku user ID, such as
|
|
26
26
|
# `user1234@heroku.com`.
|
|
27
27
|
# @raise [ArgumentError] Raised if a malformed Heroku ID is provided.
|
|
28
|
-
# @return [
|
|
28
|
+
# @return [Integer] The core user ID that uniquely represents the user.
|
|
29
29
|
def self.hid_to_id(heroku_id)
|
|
30
30
|
if user_id = heroku_id.slice(ID_CAPTURE, 1)
|
|
31
31
|
user_id.to_i
|
data/lib/vault-tools/version.rb
CHANGED
data/lib/vault-tools/web.rb
CHANGED
data/test/config_test.rb
CHANGED
|
@@ -9,35 +9,6 @@ class ConfigTest < Vault::TestCase
|
|
|
9
9
|
Config.reset!
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
# Config.remote_env uses the Heroku API to read config vars from
|
|
13
|
-
# other apps.
|
|
14
|
-
def test_remote_env
|
|
15
|
-
api_mock = MiniTest::Mock.new
|
|
16
|
-
api_response = OpenStruct.new(body: {'DATABASE_URL' => 'postgres:///foo'})
|
|
17
|
-
Heroku::API.stub(:new, api_mock) do
|
|
18
|
-
api_mock.expect(:get_config_vars, api_response, ['app'])
|
|
19
|
-
assert_equal('postgres:///foo',
|
|
20
|
-
Config.remote_env('app', 'DATABASE_URL'))
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Config.remote_env uses the Heroku API to read config vars from
|
|
25
|
-
# other apps.
|
|
26
|
-
def test_shared_config_loads_shared_with_correct_precedence
|
|
27
|
-
set_env('CONFIG_APP', 'vault-config')
|
|
28
|
-
api_mock = MiniTest::Mock.new
|
|
29
|
-
api_response = OpenStruct.new(body: {'HELLO' => 'world'})
|
|
30
|
-
Heroku::API.stub(:new, api_mock) do
|
|
31
|
-
api_mock.expect(:get_config_vars, api_response, ['vault-config'])
|
|
32
|
-
assert_equal(nil, Config[:hello])
|
|
33
|
-
Config.default(:hello, 'foo')
|
|
34
|
-
assert_equal('foo', Config[:hello])
|
|
35
|
-
# this is how we'll call it in the code
|
|
36
|
-
Config.load_shared!(Config[:config_app])
|
|
37
|
-
assert_equal('world', Config[:hello])
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
12
|
# Config.env returns the value matching the specified environment
|
|
42
13
|
# variable name.
|
|
43
14
|
def test_env
|
|
@@ -55,7 +26,7 @@ class ConfigTest < Vault::TestCase
|
|
|
55
26
|
# Config.env return nil if an unknown environment variable is
|
|
56
27
|
# requested.
|
|
57
28
|
def test_env_with_unknown_name
|
|
58
|
-
|
|
29
|
+
assert_nil(Config.env('UNKNOWN'))
|
|
59
30
|
end
|
|
60
31
|
|
|
61
32
|
# Config.env! returns the value matching the specified environment
|
|
@@ -132,7 +103,7 @@ class ConfigTest < Vault::TestCase
|
|
|
132
103
|
end
|
|
133
104
|
end
|
|
134
105
|
|
|
135
|
-
# Config.port converts the value from the environment to a
|
|
106
|
+
# Config.port converts the value from the environment to a Integer
|
|
136
107
|
def test_port_convert_to_int
|
|
137
108
|
set_env 'PORT', "3000"
|
|
138
109
|
assert_equal(3000, Config.port)
|
|
@@ -150,14 +121,14 @@ class ConfigTest < Vault::TestCase
|
|
|
150
121
|
|
|
151
122
|
# Config.int(VAR) returns nil or VAR as integer.
|
|
152
123
|
def test_int
|
|
153
|
-
|
|
124
|
+
assert_nil Config.int('FOO')
|
|
154
125
|
set_env 'FOO', "3000"
|
|
155
126
|
assert_equal(3000, Config.int('FOO'))
|
|
156
127
|
end
|
|
157
128
|
|
|
158
129
|
# Config.time returns nil or VAR as time
|
|
159
130
|
def test_time
|
|
160
|
-
|
|
131
|
+
assert_nil(Config.time('T'))
|
|
161
132
|
set_env 'T', '2000'
|
|
162
133
|
assert_equal(Time.utc(2000), Config.time(:t))
|
|
163
134
|
set_env 'T', '2000-2'
|
|
@@ -170,7 +141,7 @@ class ConfigTest < Vault::TestCase
|
|
|
170
141
|
|
|
171
142
|
# Config.time returns nil or VAR as URI
|
|
172
143
|
def test_uri
|
|
173
|
-
|
|
144
|
+
assert_nil(Config.uri('URL'))
|
|
174
145
|
set_env 'URL', 'http://user:password@the-web.com/path/to/greatness?foo=bar'
|
|
175
146
|
uri = Config.uri('URL')
|
|
176
147
|
assert_equal('http', uri.scheme)
|
data/test/defaults_test.rb
CHANGED
|
@@ -8,13 +8,13 @@ class DefaultsTest < Vault::TestCase
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def test_default_when_no_value
|
|
11
|
-
|
|
11
|
+
assert_nil(Config[:max_connections])
|
|
12
12
|
Config.default(:max_connections, 10)
|
|
13
13
|
assert_equal(Config[:max_connections], 10)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def test_default_with_int
|
|
17
|
-
|
|
17
|
+
assert_nil(Config[:max_connections])
|
|
18
18
|
Config.default(:max_connections, '10')
|
|
19
19
|
assert_equal('10', Config[:max_connections])
|
|
20
20
|
assert_equal(10, Config.int(:max_connections))
|
|
@@ -23,7 +23,7 @@ class DefaultsTest < Vault::TestCase
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def test_default_with_time
|
|
26
|
-
|
|
26
|
+
assert_nil(Config[:date])
|
|
27
27
|
Config.default(:date, '2013-01-01')
|
|
28
28
|
assert_equal('2013-01-01', Config[:date])
|
|
29
29
|
assert_equal(Time.utc(2013), Config.time(:date))
|
|
@@ -33,7 +33,7 @@ class DefaultsTest < Vault::TestCase
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def test_default_with_array
|
|
36
|
-
|
|
36
|
+
assert_nil(Config[:array])
|
|
37
37
|
Config.default(:array, '10')
|
|
38
38
|
assert_equal('10', Config[:array])
|
|
39
39
|
assert_equal(['10'], Config.array(:array))
|
data/test/helper.rb
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
require 'vault-test-tools'
|
|
2
2
|
require 'vault-tools'
|
|
3
3
|
require 'rr'
|
|
4
|
+
require 'minitest/around/unit'
|
|
5
|
+
require 'pry'
|
|
4
6
|
|
|
5
7
|
ENV['RACK_ENV'] = 'test'
|
|
8
|
+
ENV['AWS_REGION'] = 'us-east-1'
|
|
6
9
|
|
|
7
10
|
module LoggedDataHelper
|
|
8
11
|
def logged_data
|
|
@@ -39,69 +42,32 @@ class Vault::TestCase
|
|
|
39
42
|
end
|
|
40
43
|
|
|
41
44
|
module StubbedS3
|
|
42
|
-
class FakeFile
|
|
43
|
-
def initialize(contents=nil)
|
|
44
|
-
@contents = contents
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def write(contents)
|
|
48
|
-
@contents = contents
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def read
|
|
52
|
-
@contents
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
class FakeBucket
|
|
57
|
-
def initialize
|
|
58
|
-
@files = {}
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def [](file_name)
|
|
62
|
-
@files[file_name] ||= FakeFile.new
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def write(file_name, contents)
|
|
66
|
-
@files[file_name].write(contents)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def objects
|
|
70
|
-
self
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
45
|
class FakeClient
|
|
75
46
|
def initialize
|
|
76
|
-
@
|
|
47
|
+
@files = {}
|
|
77
48
|
end
|
|
78
49
|
|
|
79
|
-
def
|
|
80
|
-
@
|
|
50
|
+
def put_object(opts)
|
|
51
|
+
@files["#{opts[:bucket]}::#{opts[:key]}"] = opts[:body]
|
|
81
52
|
end
|
|
82
53
|
|
|
83
|
-
def
|
|
84
|
-
|
|
54
|
+
def get_object(opts)
|
|
55
|
+
val = @files["#{opts[:bucket]}::#{opts[:key]}"]
|
|
56
|
+
OpenStruct.new(body: OpenStruct.new(read: val))
|
|
85
57
|
end
|
|
86
58
|
end
|
|
87
59
|
|
|
88
60
|
class << self
|
|
89
61
|
def seed(bucket, file, contents)
|
|
90
|
-
fake_client.
|
|
62
|
+
fake_client.put_object({bucket: bucket, key: file, body: contents})
|
|
91
63
|
end
|
|
92
64
|
|
|
93
65
|
def fake_client
|
|
94
66
|
@client ||= FakeClient.new
|
|
95
67
|
end
|
|
96
68
|
|
|
97
|
-
def enable!(
|
|
98
|
-
|
|
99
|
-
expected_aws_args = {
|
|
100
|
-
access_key_id: opts.fetch(:access_key_id, 'FAKE_ID'),
|
|
101
|
-
secret_access_key: opts.fetch(:secret_access_key, 'FAKE_KEY'),
|
|
102
|
-
use_ssl: opts.fetch(:use_ssl, true)
|
|
103
|
-
}
|
|
104
|
-
env.stub(AWS::S3).new(expected_aws_args) { fake_client }
|
|
69
|
+
def enable!(opts={}, &block)
|
|
70
|
+
Aws::S3::Client.stub(:new, fake_client) { yield }
|
|
105
71
|
end
|
|
106
72
|
end
|
|
107
73
|
end
|
data/test/s3_test.rb
CHANGED
|
@@ -7,13 +7,14 @@ end
|
|
|
7
7
|
class S3Test < Vault::TestCase
|
|
8
8
|
include LoggedDataHelper
|
|
9
9
|
|
|
10
|
-
def
|
|
11
|
-
super
|
|
10
|
+
def around
|
|
12
11
|
set_env 'APP_DEPLOY', 'test'
|
|
13
12
|
set_env 'AWS_ACCESS_KEY_ID', 'fake access key id'
|
|
14
13
|
set_env 'AWS_SECRET_ACCESS_KEY', 'fake secret access key'
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
StubbedS3.enable! do
|
|
15
|
+
@consumer = SomeS3Consumer.new
|
|
16
|
+
yield
|
|
17
|
+
end
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def log_output
|
|
@@ -23,33 +24,32 @@ class S3Test < Vault::TestCase
|
|
|
23
24
|
# S3 writes should be logged.
|
|
24
25
|
def test_write_logs
|
|
25
26
|
@consumer.write('fake bucket', 'fake key', 'fake value')
|
|
26
|
-
assert_match
|
|
27
|
+
assert_match(/fake key/, log_output)
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
# S3 reads should be logged.
|
|
30
31
|
def test_read_logs
|
|
31
32
|
@consumer.read('fake bucket', 'fake key')
|
|
32
|
-
assert_match
|
|
33
|
+
assert_match(/fake key/, log_output)
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
# Should use S3 to write to bucket
|
|
36
37
|
def test_writes_to_s3_bucket
|
|
37
|
-
mock(@consumer).s3.mock!.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
mock(@consumer).s3.mock!.put_object({
|
|
39
|
+
bucket: 'fake bucket',
|
|
40
|
+
key: 'fake key',
|
|
41
|
+
body: 'fake value'
|
|
42
|
+
})
|
|
42
43
|
@consumer.write('fake bucket', 'fake key', 'fake value')
|
|
43
44
|
end
|
|
44
45
|
|
|
45
46
|
# Should use S3 to read from bucket
|
|
46
47
|
def test_reads_from_s3_bucket
|
|
47
48
|
#s3.buckets[bucket].objects[key].read
|
|
48
|
-
mock(@consumer).s3.mock!.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
mock!.read
|
|
49
|
+
mock(@consumer).s3.mock!.get_object({
|
|
50
|
+
bucket: 'fake bucket',
|
|
51
|
+
key: 'fake key'
|
|
52
|
+
}).mock!.body.mock!.read
|
|
53
53
|
@consumer.read('fake bucket', 'fake key')
|
|
54
54
|
end
|
|
55
55
|
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
require 'helper'
|
|
2
2
|
|
|
3
3
|
class StatementStoreTest < Vault::TestCase
|
|
4
|
-
def
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
def around(&block)
|
|
5
|
+
StubbedS3.enable! do
|
|
6
|
+
StubbedS3.seed('vault-v2-json-invoice-test',
|
|
7
|
+
'2014-10-01/2014-11-01/user8@heroku.com_v2', '{"foo": 1}')
|
|
8
|
+
yield
|
|
9
|
+
end
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def test_invoice_path_with_user_id
|
|
@@ -36,15 +36,12 @@ class StatementStoreTest < Vault::TestCase
|
|
|
36
36
|
# Nothing Before Write
|
|
37
37
|
doc = inv.get_json(start_time: '2014-10-01', stop_time: '2014-11-01',
|
|
38
38
|
user_hid: 'user9@heroku.com', version: 2)
|
|
39
|
-
|
|
40
|
-
assert_equal expected, doc
|
|
39
|
+
assert_nil doc
|
|
41
40
|
|
|
42
41
|
# Write to S3 updating expectation
|
|
43
42
|
expected = {"bar" => 3}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
contents: expected)
|
|
47
|
-
assert obj.is_a? StubbedS3::FakeFile
|
|
43
|
+
inv.write_json(start_time: '2014-10-01', stop_time: '2014-11-01',
|
|
44
|
+
user_hid: 'user9@heroku.com', version: 2, contents: expected)
|
|
48
45
|
|
|
49
46
|
# There after write
|
|
50
47
|
doc = inv.get_json(start_time: '2014-10-01', stop_time: '2014-11-01',
|
data/vault-tools.gemspec
CHANGED
|
@@ -7,11 +7,14 @@ require 'vault-tools/version'
|
|
|
7
7
|
Gem::Specification.new do |gem|
|
|
8
8
|
gem.name = "vault-tools"
|
|
9
9
|
gem.version = Vault::Tools::VERSION
|
|
10
|
-
gem.authors = ["Chris Continanza", "Jamu Kakar"]
|
|
11
|
-
gem.email = ["
|
|
10
|
+
gem.authors = ["Chris Continanza", "Jamu Kakar", "Kenny Parnell"]
|
|
11
|
+
gem.email = ["csquared@heroku.com", "christopher.continanza@gmail.com",
|
|
12
|
+
"jkakar@heroku.com","jkakar@kakar.ca",
|
|
13
|
+
"kennyp@heroku.com", "k.parnell@gmail.com"]
|
|
12
14
|
gem.description = "Basic tools for Heroku Vault's Ruby projects"
|
|
13
15
|
gem.summary = "Test classes, base web classes, and helpers - oh my!"
|
|
14
16
|
gem.homepage = ""
|
|
17
|
+
gem.required_ruby_version = '>= 2.5.3'
|
|
15
18
|
|
|
16
19
|
gem.files = `git ls-files`.split($/)
|
|
17
20
|
gem.test_files = gem.files.grep('^(test|spec|features)/')
|
|
@@ -21,14 +24,12 @@ Gem::Specification.new do |gem|
|
|
|
21
24
|
gem.add_dependency 'sinatra', '~> 2.0.4'
|
|
22
25
|
gem.add_dependency 'uuidtools'
|
|
23
26
|
gem.add_dependency 'rack-ssl-enforcer'
|
|
24
|
-
gem.add_dependency '
|
|
25
|
-
gem.add_dependency '
|
|
26
|
-
gem.add_dependency '
|
|
27
|
-
gem.add_dependency 'aws-sdk', '~> 1.0'
|
|
27
|
+
gem.add_dependency 'fernet', '2.0'
|
|
28
|
+
gem.add_dependency 'rollbar', '~> 2.18.2'
|
|
29
|
+
gem.add_dependency 'aws-sdk-s3', '~> 1.0'
|
|
28
30
|
gem.add_dependency 'excon'
|
|
29
31
|
gem.add_dependency 'rack', '~> 2.0'
|
|
30
32
|
gem.add_dependency 'coderay'
|
|
31
|
-
gem.add_dependency 'zipkin-tracer', '~> 0.27'
|
|
32
33
|
|
|
33
34
|
gem.add_development_dependency 'dotenv'
|
|
34
35
|
gem.add_development_dependency 'pry'
|
metadata
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: vault-tools
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris Continanza
|
|
8
8
|
- Jamu Kakar
|
|
9
|
+
- Kenny Parnell
|
|
9
10
|
autorequire:
|
|
10
11
|
bindir: bin
|
|
11
12
|
cert_chain: []
|
|
12
|
-
date:
|
|
13
|
+
date: 2019-01-14 00:00:00.000000000 Z
|
|
13
14
|
dependencies:
|
|
14
15
|
- !ruby/object:Gem::Dependency
|
|
15
16
|
name: scrolls
|
|
@@ -67,50 +68,36 @@ dependencies:
|
|
|
67
68
|
- - ">="
|
|
68
69
|
- !ruby/object:Gem::Version
|
|
69
70
|
version: '0'
|
|
70
|
-
- !ruby/object:Gem::Dependency
|
|
71
|
-
name: heroku-api
|
|
72
|
-
requirement: !ruby/object:Gem::Requirement
|
|
73
|
-
requirements:
|
|
74
|
-
- - ">="
|
|
75
|
-
- !ruby/object:Gem::Version
|
|
76
|
-
version: '0'
|
|
77
|
-
type: :runtime
|
|
78
|
-
prerelease: false
|
|
79
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
80
|
-
requirements:
|
|
81
|
-
- - ">="
|
|
82
|
-
- !ruby/object:Gem::Version
|
|
83
|
-
version: '0'
|
|
84
71
|
- !ruby/object:Gem::Dependency
|
|
85
72
|
name: fernet
|
|
86
73
|
requirement: !ruby/object:Gem::Requirement
|
|
87
74
|
requirements:
|
|
88
75
|
- - '='
|
|
89
76
|
- !ruby/object:Gem::Version
|
|
90
|
-
version: 2.0
|
|
77
|
+
version: '2.0'
|
|
91
78
|
type: :runtime
|
|
92
79
|
prerelease: false
|
|
93
80
|
version_requirements: !ruby/object:Gem::Requirement
|
|
94
81
|
requirements:
|
|
95
82
|
- - '='
|
|
96
83
|
- !ruby/object:Gem::Version
|
|
97
|
-
version: 2.0
|
|
84
|
+
version: '2.0'
|
|
98
85
|
- !ruby/object:Gem::Dependency
|
|
99
86
|
name: rollbar
|
|
100
87
|
requirement: !ruby/object:Gem::Requirement
|
|
101
88
|
requirements:
|
|
102
89
|
- - "~>"
|
|
103
90
|
- !ruby/object:Gem::Version
|
|
104
|
-
version: 2.
|
|
91
|
+
version: 2.18.2
|
|
105
92
|
type: :runtime
|
|
106
93
|
prerelease: false
|
|
107
94
|
version_requirements: !ruby/object:Gem::Requirement
|
|
108
95
|
requirements:
|
|
109
96
|
- - "~>"
|
|
110
97
|
- !ruby/object:Gem::Version
|
|
111
|
-
version: 2.
|
|
98
|
+
version: 2.18.2
|
|
112
99
|
- !ruby/object:Gem::Dependency
|
|
113
|
-
name: aws-sdk
|
|
100
|
+
name: aws-sdk-s3
|
|
114
101
|
requirement: !ruby/object:Gem::Requirement
|
|
115
102
|
requirements:
|
|
116
103
|
- - "~>"
|
|
@@ -165,20 +152,6 @@ dependencies:
|
|
|
165
152
|
- - ">="
|
|
166
153
|
- !ruby/object:Gem::Version
|
|
167
154
|
version: '0'
|
|
168
|
-
- !ruby/object:Gem::Dependency
|
|
169
|
-
name: zipkin-tracer
|
|
170
|
-
requirement: !ruby/object:Gem::Requirement
|
|
171
|
-
requirements:
|
|
172
|
-
- - "~>"
|
|
173
|
-
- !ruby/object:Gem::Version
|
|
174
|
-
version: '0.27'
|
|
175
|
-
type: :runtime
|
|
176
|
-
prerelease: false
|
|
177
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
178
|
-
requirements:
|
|
179
|
-
- - "~>"
|
|
180
|
-
- !ruby/object:Gem::Version
|
|
181
|
-
version: '0.27'
|
|
182
155
|
- !ruby/object:Gem::Dependency
|
|
183
156
|
name: dotenv
|
|
184
157
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -237,10 +210,12 @@ dependencies:
|
|
|
237
210
|
version: '0'
|
|
238
211
|
description: Basic tools for Heroku Vault's Ruby projects
|
|
239
212
|
email:
|
|
240
|
-
- christopher.continanza@gmail.com
|
|
241
213
|
- csquared@heroku.com
|
|
214
|
+
- christopher.continanza@gmail.com
|
|
242
215
|
- jkakar@heroku.com
|
|
243
216
|
- jkakar@kakar.ca
|
|
217
|
+
- kennyp@heroku.com
|
|
218
|
+
- k.parnell@gmail.com
|
|
244
219
|
executables: []
|
|
245
220
|
extensions: []
|
|
246
221
|
extra_rdoc_files: []
|
|
@@ -272,9 +247,6 @@ files:
|
|
|
272
247
|
- lib/vault-tools/tasks.rb
|
|
273
248
|
- lib/vault-tools/text_processor.rb
|
|
274
249
|
- lib/vault-tools/time.rb
|
|
275
|
-
- lib/vault-tools/tracing.rb
|
|
276
|
-
- lib/vault-tools/tracing/sidekiq_client.rb
|
|
277
|
-
- lib/vault-tools/tracing/sidekiq_server.rb
|
|
278
250
|
- lib/vault-tools/usage_db_tasks.rb
|
|
279
251
|
- lib/vault-tools/user.rb
|
|
280
252
|
- lib/vault-tools/vault_db_tasks.rb
|
|
@@ -292,7 +264,6 @@ files:
|
|
|
292
264
|
- test/statement_store_test.rb
|
|
293
265
|
- test/text_processor_test.rb
|
|
294
266
|
- test/time_test.rb
|
|
295
|
-
- test/tracing_test.rb
|
|
296
267
|
- test/user_test.rb
|
|
297
268
|
- test/web_test.rb
|
|
298
269
|
- vault-tools.gemspec
|
|
@@ -307,7 +278,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
307
278
|
requirements:
|
|
308
279
|
- - ">="
|
|
309
280
|
- !ruby/object:Gem::Version
|
|
310
|
-
version:
|
|
281
|
+
version: 2.5.3
|
|
311
282
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
312
283
|
requirements:
|
|
313
284
|
- - ">="
|
data/lib/vault-tools/tracing.rb
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
require 'zipkin-tracer'
|
|
2
|
-
|
|
3
|
-
module Vault
|
|
4
|
-
module Tracing
|
|
5
|
-
ZIPKIN_API_HOST_STAGING = 'https://zipkin-staging.heroku.tools'.freeze
|
|
6
|
-
|
|
7
|
-
# Injects the zipkin middleware into the Web class, add Zipkin middleware to
|
|
8
|
-
# Excon.
|
|
9
|
-
#
|
|
10
|
-
# @example
|
|
11
|
-
# Vault::Tracing.configure
|
|
12
|
-
#
|
|
13
|
-
# @return nil
|
|
14
|
-
def self.configure
|
|
15
|
-
return unless Vault::Tracing.enabled?
|
|
16
|
-
|
|
17
|
-
Vault::Web.instance_eval { require 'zipkin-tracer' }
|
|
18
|
-
Vault::Web.use ZipkinTracer::RackHandler, config
|
|
19
|
-
setup_excon
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Traces a local component. Useful to track down long running implementation
|
|
23
|
-
# methods within an app, instead of only tracing external calls.
|
|
24
|
-
#
|
|
25
|
-
# @param name [String] the name of the span to record in Zipkin.
|
|
26
|
-
# @param tracer [Constant] the const that should respond to :local_component_span
|
|
27
|
-
# @param options [Hash] the options to create a message with.
|
|
28
|
-
#
|
|
29
|
-
# @example
|
|
30
|
-
# Vault::Tracing.trace_local 'cashier_middleware_x', internal: true do
|
|
31
|
-
# # some expensive task
|
|
32
|
-
# end
|
|
33
|
-
#
|
|
34
|
-
# @yield [the_block_passed_in]
|
|
35
|
-
def self.trace_local(name, tracer = ZipkinTracer::TraceClient, **options)
|
|
36
|
-
return yield unless Vault::Tracing.enabled?
|
|
37
|
-
|
|
38
|
-
tracer.local_component_span(name) do |span|
|
|
39
|
-
span.name = name
|
|
40
|
-
span.record_tag('options', options.to_s) unless options.empty?
|
|
41
|
-
yield
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Configuration options for the Zipkin RackHandler.
|
|
46
|
-
#
|
|
47
|
-
# @return [Hash] config options for Zipkin tracer
|
|
48
|
-
def self.config
|
|
49
|
-
{
|
|
50
|
-
service_name: "#{Config.app_name}.herokuapp.com",
|
|
51
|
-
service_port: 443,
|
|
52
|
-
json_api_host: Config[:zipkin_api_host],
|
|
53
|
-
sample_rate: (Config[:zipkin_sample_rate] || 0.1).to_f,
|
|
54
|
-
sampled_as_boolean: false
|
|
55
|
-
}
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# A helper to guard against injecting Zipkin when not desired.
|
|
59
|
-
#
|
|
60
|
-
# @return [true] if so
|
|
61
|
-
def self.enabled?
|
|
62
|
-
Config.app_name &&
|
|
63
|
-
Config[:zipkin_enabled] == 'true' &&
|
|
64
|
-
Config[:zipkin_api_host]
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Adds ZipkinTracer::ExconHandler to Excon's default middlewares if Excon is
|
|
68
|
-
# defined
|
|
69
|
-
#
|
|
70
|
-
# @private
|
|
71
|
-
#
|
|
72
|
-
# @return nil
|
|
73
|
-
def self.setup_excon
|
|
74
|
-
if add_to_excon_middlewares?
|
|
75
|
-
Excon.defaults[:middlewares].push(ZipkinTracer::ExconHandler)
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
private_class_method :setup_excon
|
|
79
|
-
|
|
80
|
-
# Checks to see if Excon is defined and if the Zipkin middleware has already
|
|
81
|
-
# been inserted.
|
|
82
|
-
#
|
|
83
|
-
# @private
|
|
84
|
-
#
|
|
85
|
-
# @return [true] if Excon is defined and the middleware is not already
|
|
86
|
-
# inserted
|
|
87
|
-
def self.add_to_excon_middlewares?
|
|
88
|
-
defined?(Excon) && !Excon.defaults[:middlewares].include?(ZipkinTracer::ExconHandler)
|
|
89
|
-
end
|
|
90
|
-
private_class_method :add_to_excon_middlewares?
|
|
91
|
-
end
|
|
92
|
-
end
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
module Vault
|
|
2
|
-
module Tracing
|
|
3
|
-
# Tracing info for sidekiq, adding them as params
|
|
4
|
-
# This was lifted straight out of heroku/coal_car
|
|
5
|
-
class SidekiqClient
|
|
6
|
-
def trace_information(trace_id)
|
|
7
|
-
{
|
|
8
|
-
"trace_id" => trace_id.trace_id,
|
|
9
|
-
"parent_id" => trace_id.parent_id,
|
|
10
|
-
"span_id" => trace_id.span_id,
|
|
11
|
-
"sampled" => trace_id.sampled,
|
|
12
|
-
"flags" => trace_id.flags
|
|
13
|
-
}
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def call(worker_class, job, _queue, _redis_pool)
|
|
17
|
-
trace_id = ::ZipkinTracer::TraceGenerator.new.next_trace_id
|
|
18
|
-
::ZipkinTracer::TraceContainer.with_trace_id(trace_id) do
|
|
19
|
-
job["zipkin_trace_information"] = trace_information(trace_id)
|
|
20
|
-
if trace_id.sampled?
|
|
21
|
-
::Trace.tracer.with_new_span(trace_id, "sidekiq") do |span|
|
|
22
|
-
local_endpoint = Trace.default_endpoint
|
|
23
|
-
klass = job["wrapped".freeze] || worker_class
|
|
24
|
-
span.record_tag("job_class",
|
|
25
|
-
klass,
|
|
26
|
-
::Trace::BinaryAnnotation::Type::STRING,
|
|
27
|
-
local_endpoint)
|
|
28
|
-
yield
|
|
29
|
-
end
|
|
30
|
-
else
|
|
31
|
-
yield
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
module Vault
|
|
2
|
-
module Tracing
|
|
3
|
-
# Tracing info for sidekiq
|
|
4
|
-
# This was lifted straight out of heroku/coal_car
|
|
5
|
-
class SidekiqServer
|
|
6
|
-
def initialize(config = nil)
|
|
7
|
-
@config = ZipkinTracer::Config.new(nil, config).freeze
|
|
8
|
-
@tracer = ZipkinTracer::TracerFactory.new.tracer(@config)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def call(worker, job, _queue)
|
|
12
|
-
result = nil
|
|
13
|
-
id = trace_id(job)
|
|
14
|
-
klass = job["wrapped".freeze] || worker.class.to_s
|
|
15
|
-
::ZipkinTracer::TraceContainer.with_trace_id(id) do
|
|
16
|
-
if id.sampled?
|
|
17
|
-
@tracer.with_new_span(id, klass) do |span|
|
|
18
|
-
span.record("sidekiq.start")
|
|
19
|
-
result = yield
|
|
20
|
-
span.record("sidekiq.end")
|
|
21
|
-
end
|
|
22
|
-
else
|
|
23
|
-
yield
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
::Trace.tracer.flush! if ::Trace.tracer.respond_to?(:flush!)
|
|
27
|
-
result
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
def trace_id(job)
|
|
33
|
-
info = job["zipkin_trace_information"]
|
|
34
|
-
if info
|
|
35
|
-
trace_id = info["trace_id"]
|
|
36
|
-
span_id = info["span_id"]
|
|
37
|
-
parent_span_id = info["parent_id"]
|
|
38
|
-
sampled = info["sampled"]
|
|
39
|
-
flags = info["flags"].to_i
|
|
40
|
-
else
|
|
41
|
-
trace_id = span_id = ::Trace.generate_id
|
|
42
|
-
parent_span_id = nil
|
|
43
|
-
sampled = sample?
|
|
44
|
-
flags = ::Trace::Flags::EMPTY
|
|
45
|
-
end
|
|
46
|
-
::Trace::TraceId.new(trace_id, parent_span_id, span_id, sampled, flags)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def sample?
|
|
50
|
-
rand < @config.sample_rate
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
data/test/tracing_test.rb
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
require 'helper'
|
|
2
|
-
|
|
3
|
-
class TracingTest < Vault::TestCase
|
|
4
|
-
# Anonymous Web Frontend
|
|
5
|
-
def app
|
|
6
|
-
@app ||= Class.new(Vault::Web)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
# Middleware is attached at load time, so we have to delete the Vault::Web
|
|
10
|
-
# class and reload it to simulate being loaded with different environment
|
|
11
|
-
# variables.
|
|
12
|
-
def reload_web!
|
|
13
|
-
# remove the constant to force a clean reload
|
|
14
|
-
Vault.send(:remove_const, 'Web')
|
|
15
|
-
load 'lib/vault-tools/web.rb'
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# Always reload the web class to eliminate test leakage
|
|
19
|
-
def setup
|
|
20
|
-
super
|
|
21
|
-
reload_web!
|
|
22
|
-
enable
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def teardown
|
|
26
|
-
super
|
|
27
|
-
@app = nil
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def enable
|
|
31
|
-
set_env('APP_NAME', 'test_app')
|
|
32
|
-
set_env('ZIPKIN_ENABLED', 'true')
|
|
33
|
-
set_env('ZIPKIN_API_HOST', 'http://localhost')
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def disable
|
|
37
|
-
set_env('ZIPKIN_ENABLED', nil)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def test_service_name_gets_herokuapp
|
|
41
|
-
assert_equal 'test_app.herokuapp.com', Vault::Tracing.config[:service_name]
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def test_configure_enabled
|
|
45
|
-
Vault::Tracing.configure
|
|
46
|
-
middleware_constants = app.middleware.map(&:first)
|
|
47
|
-
assert middleware_constants.include?(ZipkinTracer::RackHandler),
|
|
48
|
-
"expected ZipkinTracer::RackHandler to be in the middleware stack, got #{middleware_constants}"
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def test_configure_not_enabled
|
|
52
|
-
disable
|
|
53
|
-
refute Vault::Tracing.configure,
|
|
54
|
-
'Vault::Tracing.configure should return nil when not enabled'
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def test_excon
|
|
58
|
-
Vault::Tracing.configure
|
|
59
|
-
assert Excon.defaults[:middlewares].include?(ZipkinTracer::ExconHandler),
|
|
60
|
-
"Vault::Tracing.setup_excon should add ZipkinTracer::ExconHandler to excon's middleware"
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def test_enabled_true
|
|
64
|
-
assert Vault::Tracing.enabled?,
|
|
65
|
-
'Vault::Tracing.enabled? should return true when enabled'
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def test_enabled_false
|
|
69
|
-
disable
|
|
70
|
-
refute Vault::Tracing.enabled?,
|
|
71
|
-
'Vault::Tracing.enabled? should return false when not enabled'
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def test_trace_local_yield
|
|
75
|
-
result = Vault::Tracing.trace_local('testing', opt: 'foo') { 1 + 1 }
|
|
76
|
-
assert_equal 2, result, 'trace_local should yield the result of the block given'
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def test_trace_local_calls_tracer
|
|
80
|
-
tracer_mock = Minitest::Mock.new
|
|
81
|
-
tracer_mock.expect :local_component_span, true, ['testing']
|
|
82
|
-
Vault::Tracing.trace_local('testing', tracer_mock, opt: 'foo') { 1 + 1 }
|
|
83
|
-
assert tracer_mock.verify,
|
|
84
|
-
'trace_local should call :local_component_span on the tracer'
|
|
85
|
-
end
|
|
86
|
-
end
|