vault-tools 1.0.1 → 2.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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +15 -0
- data/Gemfile +3 -3
- data/Gemfile.lock +60 -66
- data/README.md +5 -14
- data/lib/vault-tools/app.rb +3 -3
- data/lib/vault-tools/config.rb +6 -24
- data/lib/vault-tools/log.rb +4 -4
- data/lib/vault-tools/pipeline.rb +2 -2
- 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 +10 -2
- data/lib/vault-tools.rb +1 -5
- data/test/config_test.rb +5 -34
- data/test/defaults_test.rb +4 -4
- data/test/helper.rb +12 -46
- data/test/log_test.rb +6 -5
- data/test/s3_test.rb +16 -16
- data/test/statement_store_test.rb +9 -12
- data/test/web_test.rb +1 -0
- data/vault-tools.gemspec +8 -7
- metadata +17 -47
- data/.travis.yml +0 -6
- data/lib/vault-tools/tracing/sidekiq_client.rb +0 -37
- data/lib/vault-tools/tracing/sidekiq_server.rb +0 -54
- data/lib/vault-tools/tracing.rb +0 -92
- data/test/tracing_test.rb +0 -86
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
@@ -53,7 +53,7 @@ module Vault
|
|
53
53
|
# protect! is used
|
54
54
|
%w{get put post delete head options path link unlink}.each do |meth|
|
55
55
|
define_method "#{meth}_unprotected".to_sym do |path, opts = {}, &block|
|
56
|
-
pattern = compile!(meth.upcase, path, block, opts).first
|
56
|
+
pattern = compile!(meth.upcase, path, block, **opts).first
|
57
57
|
set :unprotected_paths, settings.unprotected_paths + [pattern]
|
58
58
|
if meth.downcase == 'get'
|
59
59
|
conditions = @conditions.dup
|
@@ -100,11 +100,19 @@ module Vault
|
|
100
100
|
# Start timing the request.
|
101
101
|
before do
|
102
102
|
@start_request = Time.now
|
103
|
+
# if client sends content_type: application/json which no longer works
|
104
|
+
# https://github.com/puma/puma/compare/4.3.1...4.3.5#commitcomment-39478516
|
105
|
+
#
|
106
|
+
# fixing this here so that we do not break all client users at once
|
107
|
+
if request.env["CONTENT_TYPE"].nil? && request.env["HTTP_CONTENT_TYPE"]
|
108
|
+
request.env["CONTENT_TYPE"] = request.env["HTTP_CONTENT_TYPE"]
|
109
|
+
end
|
103
110
|
end
|
104
111
|
|
105
112
|
# Log details about the request including how long it took.
|
106
113
|
after do
|
107
|
-
|
114
|
+
@action ||= 'unknown'
|
115
|
+
Log.count_status(response.status, request_path: request.path_info)
|
108
116
|
Log.time("http.#{@action}", (Time.now - @start_request) * 1000)
|
109
117
|
end
|
110
118
|
|
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/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/log_test.rb
CHANGED
@@ -31,10 +31,11 @@ class LogTest < Vault::TestCase
|
|
31
31
|
|
32
32
|
# Vault::Log.count_status emits metrics to measure HTTP responses.
|
33
33
|
def test_count_status
|
34
|
-
Vault::Log.count_status(201)
|
35
|
-
assert_equal
|
36
|
-
assert_equal
|
37
|
-
assert_equal '
|
34
|
+
Vault::Log.count_status(201, request_path: '/some/request/path')
|
35
|
+
assert_equal 1, logdata['count#test-app.http.201']
|
36
|
+
assert_equal 1, logdata['count#test-app.http.2xx']
|
37
|
+
assert_equal '/some/request/path', logdata['request_path']
|
38
|
+
assert_equal 'test-deploy', logdata['source']
|
38
39
|
end
|
39
40
|
|
40
41
|
def test_measure
|
@@ -115,6 +116,6 @@ class LogTest < Vault::TestCase
|
|
115
116
|
assert_equal 'true', logged_data['A']
|
116
117
|
assert_equal 'true', logged_data['B']
|
117
118
|
assert_equal 'test-deploy', logged_data['source']
|
118
|
-
assert_match
|
119
|
+
assert_match(/\d/, logged_data['elapsed'])
|
119
120
|
end
|
120
121
|
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/test/web_test.rb
CHANGED
@@ -155,6 +155,7 @@ class WebTest < Vault::TestCase
|
|
155
155
|
head '/'
|
156
156
|
assert_equal '1', logged_data['count#test-app.http.200']
|
157
157
|
assert_equal '1', logged_data['count#test-app.http.2xx']
|
158
|
+
assert_equal '/', logged_data['request_path']
|
158
159
|
assert_equal(200, last_response.status)
|
159
160
|
end
|
160
161
|
|
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.7.1'
|
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'
|