prefab-cloud-ruby 0.20.0 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.envrc.sample +3 -0
- data/.github/workflows/ruby.yml +5 -1
- data/.gitmodules +3 -0
- data/Gemfile +14 -12
- data/Gemfile.lock +24 -14
- data/README.md +12 -10
- data/Rakefile +13 -14
- data/VERSION +1 -1
- data/lib/prefab/auth_interceptor.rb +2 -1
- data/lib/prefab/cancellable_interceptor.rb +8 -7
- data/lib/prefab/client.rb +52 -27
- data/lib/prefab/config_client.rb +59 -70
- data/lib/prefab/config_loader.rb +7 -114
- data/lib/prefab/config_resolver.rb +27 -57
- data/lib/prefab/config_value_unwrapper.rb +23 -0
- data/lib/prefab/criteria_evaluator.rb +96 -0
- data/lib/prefab/errors/invalid_api_key_error.rb +1 -1
- data/lib/prefab/feature_flag_client.rb +13 -145
- data/lib/prefab/internal_logger.rb +7 -6
- data/lib/prefab/local_config_parser.rb +110 -0
- data/lib/prefab/log_path_collector.rb +98 -0
- data/lib/prefab/logger_client.rb +46 -44
- data/lib/prefab/murmer3.rb +3 -4
- data/lib/prefab/noop_cache.rb +5 -7
- data/lib/prefab/noop_stats.rb +2 -3
- data/lib/prefab/options.rb +32 -11
- data/lib/prefab/ratelimit_client.rb +11 -13
- data/lib/prefab/sse_logger.rb +3 -2
- data/lib/prefab/weighted_value_resolver.rb +42 -0
- data/lib/prefab/yaml_config_parser.rb +32 -0
- data/lib/prefab-cloud-ruby.rb +7 -2
- data/lib/prefab_pb.rb +70 -43
- data/lib/prefab_services_pb.rb +14 -1
- data/prefab-cloud-ruby.gemspec +33 -19
- data/test/.prefab.unit_tests.config.yaml +3 -2
- data/test/integration_test.rb +98 -0
- data/test/integration_test_helpers.rb +37 -0
- data/test/test_client.rb +56 -31
- data/test/test_config_client.rb +21 -20
- data/test/test_config_loader.rb +48 -37
- data/test/test_config_resolver.rb +312 -135
- data/test/test_config_value_unwrapper.rb +83 -0
- data/test/test_criteria_evaluator.rb +533 -0
- data/test/test_feature_flag_client.rb +35 -347
- data/test/test_helper.rb +18 -14
- data/test/test_integration.rb +33 -0
- data/test/test_local_config_parser.rb +78 -0
- data/test/test_log_path_collector.rb +56 -0
- data/test/test_logger.rb +52 -51
- data/test/test_options.rb +32 -0
- data/test/test_weighted_value_resolver.rb +65 -0
- metadata +30 -16
- data/lib/prefab/config_helper.rb +0 -31
- data/run_test_harness_server.sh +0 -8
- data/test/harness_server.rb +0 -64
data/test/test_logger.rb
CHANGED
@@ -11,19 +11,19 @@ class TestCLogger < Minitest::Test
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_get_path
|
14
|
-
assert_equal
|
15
|
-
@logger.get_path(
|
16
|
-
|
17
|
-
|
18
|
-
assert_equal
|
19
|
-
@logger.get_path(
|
20
|
-
|
21
|
-
assert_equal
|
14
|
+
assert_equal 'test_l.foo_warn',
|
15
|
+
@logger.get_path('/Users/jdwyah/Documents/workspace/RateLimitInc/prefab-cloud-ruby/lib/test_l.rb',
|
16
|
+
'foo_warn')
|
17
|
+
|
18
|
+
assert_equal 'active_support.log_subscriber.info',
|
19
|
+
@logger.get_path('/Users/jdwyah/.rvm/gems/ruby-2.3.3@forcerank/gems/activesupport-4.1.16/lib/active_support/log_subscriber.rb',
|
20
|
+
'info')
|
21
|
+
assert_equal 'active_support.log_subscriber.info',
|
22
22
|
@logger.get_path("/Users/jeffdwyer/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.4/lib/active_support/log_subscriber.rb:130:in `info'",
|
23
|
-
|
24
|
-
assert_equal
|
23
|
+
'info')
|
24
|
+
assert_equal 'unknown.info',
|
25
25
|
@logger.get_path(nil,
|
26
|
-
|
26
|
+
'info')
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_loc_resolution
|
@@ -34,80 +34,81 @@ class TestCLogger < Minitest::Test
|
|
34
34
|
end # https://ruby-doc.org/core-3.0.0/Thread/Backtrace/Location.html
|
35
35
|
|
36
36
|
# verify that even if the Thread::Backtrace::Location does not have an absolute_location, we do our best
|
37
|
-
assert_equal
|
37
|
+
assert_equal 'active_support.log_subscriber.info',
|
38
38
|
@logger.get_loc_path(backtrace_location.new(nil,
|
39
|
-
|
39
|
+
'info',
|
40
40
|
"/Users/jeffdwyer/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.4/lib/active_support/log_subscriber.rb:130:in `info'"))
|
41
|
-
assert_equal
|
42
|
-
@logger.get_loc_path(backtrace_location.new(
|
43
|
-
|
41
|
+
assert_equal 'test_l.info',
|
42
|
+
@logger.get_loc_path(backtrace_location.new('/Users/jdwyah/Documents/workspace/RateLimitInc/prefab-cloud-ruby/lib/test_l.rb',
|
43
|
+
'info',
|
44
44
|
"/Users/jeffdwyer/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.4/lib/active_support/log_subscriber.rb:130:in `info'"))
|
45
45
|
end
|
46
46
|
|
47
47
|
def test_level_of
|
48
|
-
with_env(
|
48
|
+
with_env('PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL', 'info') do
|
49
49
|
# env var overrides the default level
|
50
|
-
assert_equal Logger::INFO,
|
51
|
-
@logger.level_of(
|
50
|
+
assert_equal ::Logger::INFO,
|
51
|
+
@logger.level_of('app.models.user'), 'PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL is info'
|
52
52
|
|
53
53
|
@logger.set_config_client(MockConfigClient.new({}))
|
54
|
-
assert_equal Logger::WARN,
|
55
|
-
@logger.level_of(
|
54
|
+
assert_equal ::Logger::WARN,
|
55
|
+
@logger.level_of('app.models.user'), 'default is warn'
|
56
56
|
|
57
|
-
@logger.set_config_client(MockConfigClient.new(
|
58
|
-
assert_equal Logger::INFO,
|
59
|
-
@logger.level_of(
|
57
|
+
@logger.set_config_client(MockConfigClient.new('log-level.app' => :INFO))
|
58
|
+
assert_equal ::Logger::INFO,
|
59
|
+
@logger.level_of('app.models.user')
|
60
60
|
|
61
|
-
@logger.set_config_client(MockConfigClient.new(
|
62
|
-
assert_equal Logger::DEBUG,
|
63
|
-
@logger.level_of(
|
61
|
+
@logger.set_config_client(MockConfigClient.new('log-level.app' => :DEBUG))
|
62
|
+
assert_equal ::Logger::DEBUG,
|
63
|
+
@logger.level_of('app.models.user')
|
64
64
|
|
65
|
-
@logger.set_config_client(MockConfigClient.new(
|
66
|
-
|
67
|
-
assert_equal Logger::ERROR,
|
68
|
-
@logger.level_of(
|
65
|
+
@logger.set_config_client(MockConfigClient.new('log-level.app' => :DEBUG,
|
66
|
+
'log-level.app.models' => :ERROR))
|
67
|
+
assert_equal ::Logger::ERROR,
|
68
|
+
@logger.level_of('app.models.user'), 'test leveling'
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
72
|
def test_log_internal
|
73
73
|
logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- cloud.prefab.client.test.path: : test message/)
|
74
|
-
logger.log_internal(
|
74
|
+
logger.log_internal('test message', 'test.path', '', ::Logger::WARN)
|
75
75
|
mock_logdev.verify
|
76
76
|
end
|
77
77
|
|
78
78
|
def test_log_internal_unknown
|
79
79
|
logger, mock_logdev = mock_logger_expecting(/A, \[.*\] ANY -- cloud.prefab.client.test.path: : test message/)
|
80
|
-
logger.log_internal(
|
80
|
+
logger.log_internal('test message', 'test.path', '', ::Logger::UNKNOWN)
|
81
81
|
mock_logdev.verify
|
82
82
|
end
|
83
83
|
|
84
84
|
def test_log_internal_silencing
|
85
|
-
logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- cloud.prefab.client.test.path: : should log/,
|
85
|
+
logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- cloud.prefab.client.test.path: : should log/,
|
86
|
+
calls: 2)
|
86
87
|
logger.silence do
|
87
|
-
logger.log_internal(
|
88
|
+
logger.log_internal('should not log', 'test.path', '', ::Logger::WARN)
|
88
89
|
end
|
89
|
-
logger.log_internal(
|
90
|
+
logger.log_internal('should log', 'test.path', '', ::Logger::WARN)
|
90
91
|
mock_logdev.verify
|
91
92
|
end
|
92
93
|
|
93
94
|
def test_log
|
94
95
|
logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- test.path: : test message/)
|
95
|
-
logger.log(
|
96
|
+
logger.log('test message', 'test.path', '', ::Logger::WARN)
|
96
97
|
mock_logdev.verify
|
97
98
|
end
|
98
99
|
|
99
100
|
def test_log_unknown
|
100
101
|
logger, mock_logdev = mock_logger_expecting(/A, \[.*\] ANY -- test.path: : test message/)
|
101
|
-
logger.log(
|
102
|
+
logger.log('test message', 'test.path', '', ::Logger::UNKNOWN)
|
102
103
|
mock_logdev.verify
|
103
104
|
end
|
104
105
|
|
105
106
|
def test_log_silencing
|
106
107
|
logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- test.path: : should log/, calls: 2)
|
107
108
|
logger.silence do
|
108
|
-
logger.log(
|
109
|
+
logger.log('should not log', 'test.path', '', ::Logger::WARN)
|
109
110
|
end
|
110
|
-
logger.log(
|
111
|
+
logger.log('should log', 'test.path', '', ::Logger::WARN)
|
111
112
|
mock_logdev.verify
|
112
113
|
end
|
113
114
|
|
@@ -125,11 +126,11 @@ class TestCLogger < Minitest::Test
|
|
125
126
|
|
126
127
|
def test_logging_without_a_progname
|
127
128
|
prefab, io = captured_logger
|
128
|
-
message =
|
129
|
+
message = 'MY MESSAGE'
|
129
130
|
|
130
131
|
prefab.log.error message
|
131
132
|
|
132
|
-
assert_logged io, 'ERROR',
|
133
|
+
assert_logged io, 'ERROR', 'test.test_logger.test_logging_without_a_progname', message
|
133
134
|
end
|
134
135
|
|
135
136
|
def test_logging_without_a_progname_or_message
|
@@ -137,35 +138,35 @@ class TestCLogger < Minitest::Test
|
|
137
138
|
|
138
139
|
prefab.log.error
|
139
140
|
|
140
|
-
assert_logged io, 'ERROR',
|
141
|
+
assert_logged io, 'ERROR', 'test.test_logger.test_logging_without_a_progname_or_message', ''
|
141
142
|
end
|
142
143
|
|
143
144
|
def test_logging_with_a_progname
|
144
145
|
prefab, io = captured_logger
|
145
|
-
message =
|
146
|
+
message = 'MY MESSAGE'
|
146
147
|
|
147
|
-
prefab.log.progname =
|
148
|
+
prefab.log.progname = 'MY_PROGNAME'
|
148
149
|
prefab.log.error message
|
149
150
|
|
150
|
-
assert_logged io, 'ERROR',
|
151
|
+
assert_logged io, 'ERROR', 'MY_PROGNAME test.test_logger.test_logging_with_a_progname', message
|
151
152
|
end
|
152
153
|
|
153
154
|
def test_logging_with_a_progname_and_no_message
|
154
155
|
prefab, io = captured_logger
|
155
156
|
|
156
|
-
prefab.log.progname =
|
157
|
+
prefab.log.progname = 'MY_PROGNAME'
|
157
158
|
prefab.log.error
|
158
159
|
|
159
|
-
assert_logged io, 'ERROR',
|
160
|
+
assert_logged io, 'ERROR', 'MY_PROGNAME test.test_logger.test_logging_with_a_progname_and_no_message', 'MY_PROGNAME'
|
160
161
|
end
|
161
162
|
|
162
163
|
private
|
163
164
|
|
164
165
|
def assert_logged(logged_io, level, path, message)
|
165
|
-
assert_match(/#{level} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [
|
166
|
+
assert_match(/#{level} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]?\d+: #{path}: #{message}\n/, logged_io.string)
|
166
167
|
end
|
167
168
|
|
168
|
-
def mock_logger_expecting
|
169
|
+
def mock_logger_expecting(pattern, configs = {}, calls: 1)
|
169
170
|
mock_logdev = Minitest::Mock.new
|
170
171
|
mock_logdev.expect :write, nil do |arg|
|
171
172
|
pattern.match(arg)
|
@@ -189,6 +190,6 @@ class TestCLogger < Minitest::Test
|
|
189
190
|
))
|
190
191
|
prefab = Prefab::Client.new(options)
|
191
192
|
|
192
|
-
|
193
|
+
[prefab, io]
|
193
194
|
end
|
194
195
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class TestOptions < Minitest::Test
|
6
|
+
API_KEY = 'abcdefg'
|
7
|
+
|
8
|
+
def test_works_with_named_arguments
|
9
|
+
assert_equal API_KEY, Prefab::Options.new(api_key: API_KEY).api_key
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_works_with_hash
|
13
|
+
assert_equal API_KEY, Prefab::Options.new({ api_key: API_KEY }).api_key
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_collect_max_paths
|
17
|
+
assert_equal 1000, Prefab::Options.new.collect_max_paths
|
18
|
+
assert_equal 100, Prefab::Options.new(collect_max_paths: 100).collect_max_paths
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_collect_max_paths_with_local_only
|
22
|
+
options = Prefab::Options.new(collect_max_paths: 100,
|
23
|
+
prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY)
|
24
|
+
assert_equal 0, options.collect_max_paths
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_collect_max_paths_with_collect_logs_false
|
28
|
+
options = Prefab::Options.new(collect_max_paths: 100,
|
29
|
+
collect_logs: false)
|
30
|
+
assert_equal 0, options.collect_max_paths
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class TestWeightedValueResolver < Minitest::Test
|
6
|
+
KEY = 'config_key'
|
7
|
+
|
8
|
+
def test_resolving_single_value
|
9
|
+
values = weighted_values([['abc', 1]])
|
10
|
+
resolver = Prefab::WeightedValueResolver.new(values, KEY, nil)
|
11
|
+
assert_equal 'abc', resolver.resolve.value.string
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_resolving_multiple_values_evenly_distributed
|
15
|
+
values = weighted_values([['abc', 1], ['def', 1]])
|
16
|
+
|
17
|
+
resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:001')
|
18
|
+
assert_equal 'abc', resolver.resolve.value.string
|
19
|
+
|
20
|
+
resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:456')
|
21
|
+
assert_equal 'def', resolver.resolve.value.string
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_resolving_multiple_values_unevenly_distributed
|
25
|
+
values = weighted_values([['abc', 1], ['def', 98], ['ghi', 1]])
|
26
|
+
|
27
|
+
resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:456')
|
28
|
+
assert_equal 'def', resolver.resolve.value.string
|
29
|
+
|
30
|
+
resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:103')
|
31
|
+
assert_equal 'ghi', resolver.resolve.value.string
|
32
|
+
|
33
|
+
resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:119')
|
34
|
+
assert_equal 'abc', resolver.resolve.value.string
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_resolving_multiple_values_with_simulation
|
38
|
+
values = weighted_values([['abc', 1], ['def', 98], ['ghi', 1]])
|
39
|
+
results = {}
|
40
|
+
|
41
|
+
10_000.times do |i|
|
42
|
+
result = Prefab::WeightedValueResolver.new(values, KEY, "user:#{i}").resolve.value.string
|
43
|
+
results[result] ||= 0
|
44
|
+
results[result] += 1
|
45
|
+
end
|
46
|
+
|
47
|
+
assert_in_delta 100, results['abc'], 20
|
48
|
+
assert_in_delta 9800, results['def'], 50
|
49
|
+
assert_in_delta 100, results['ghi'], 20
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def weighted_values(values_and_weights)
|
55
|
+
values_and_weights.map do |value, weight|
|
56
|
+
weighted_value(value, weight)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def weighted_value(string, weight)
|
61
|
+
Prefab::WeightedValue.new(
|
62
|
+
value: Prefab::ConfigValue.new(string: string), weight: weight
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prefab-cloud-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Dwyer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -45,7 +45,7 @@ dependencies:
|
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '0'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
48
|
+
name: googleapis-common-protos-types
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
51
|
- - ">="
|
@@ -59,7 +59,7 @@ dependencies:
|
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '0'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
62
|
+
name: google-protobuf
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - ">="
|
@@ -73,7 +73,7 @@ dependencies:
|
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '0'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
|
-
name:
|
76
|
+
name: grpc
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
79
|
- - ">="
|
@@ -87,7 +87,7 @@ dependencies:
|
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '0'
|
89
89
|
- !ruby/object:Gem::Dependency
|
90
|
-
name:
|
90
|
+
name: ld-eventsource
|
91
91
|
requirement: !ruby/object:Gem::Requirement
|
92
92
|
requirements:
|
93
93
|
- - ">="
|
@@ -101,13 +101,13 @@ dependencies:
|
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '0'
|
103
103
|
- !ruby/object:Gem::Dependency
|
104
|
-
name:
|
104
|
+
name: uuid
|
105
105
|
requirement: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
107
|
- - ">="
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: '0'
|
110
|
-
type: :
|
110
|
+
type: :runtime
|
111
111
|
prerelease: false
|
112
112
|
version_requirements: !ruby/object:Gem::Requirement
|
113
113
|
requirements:
|
@@ -115,7 +115,7 @@ dependencies:
|
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: '0'
|
117
117
|
- !ruby/object:Gem::Dependency
|
118
|
-
name:
|
118
|
+
name: benchmark-ips
|
119
119
|
requirement: !ruby/object:Gem::Requirement
|
120
120
|
requirements:
|
121
121
|
- - ">="
|
@@ -129,7 +129,7 @@ dependencies:
|
|
129
129
|
- !ruby/object:Gem::Version
|
130
130
|
version: '0'
|
131
131
|
- !ruby/object:Gem::Dependency
|
132
|
-
name:
|
132
|
+
name: bundler
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
134
134
|
requirements:
|
135
135
|
- - ">="
|
@@ -143,7 +143,7 @@ dependencies:
|
|
143
143
|
- !ruby/object:Gem::Version
|
144
144
|
version: '0'
|
145
145
|
- !ruby/object:Gem::Dependency
|
146
|
-
name:
|
146
|
+
name: grpc-tools
|
147
147
|
requirement: !ruby/object:Gem::Requirement
|
148
148
|
requirements:
|
149
149
|
- - ">="
|
@@ -171,7 +171,7 @@ dependencies:
|
|
171
171
|
- !ruby/object:Gem::Version
|
172
172
|
version: 2.4.9
|
173
173
|
- !ruby/object:Gem::Dependency
|
174
|
-
name:
|
174
|
+
name: rdoc
|
175
175
|
requirement: !ruby/object:Gem::Requirement
|
176
176
|
requirements:
|
177
177
|
- - ">="
|
@@ -185,7 +185,7 @@ dependencies:
|
|
185
185
|
- !ruby/object:Gem::Version
|
186
186
|
version: '0'
|
187
187
|
- !ruby/object:Gem::Dependency
|
188
|
-
name:
|
188
|
+
name: simplecov
|
189
189
|
requirement: !ruby/object:Gem::Requirement
|
190
190
|
requirements:
|
191
191
|
- - ">="
|
@@ -207,7 +207,9 @@ extra_rdoc_files:
|
|
207
207
|
- README.md
|
208
208
|
files:
|
209
209
|
- ".envrc"
|
210
|
+
- ".envrc.sample"
|
210
211
|
- ".github/workflows/ruby.yml"
|
212
|
+
- ".gitmodules"
|
211
213
|
- ".tool-versions"
|
212
214
|
- CODEOWNERS
|
213
215
|
- Gemfile
|
@@ -222,15 +224,18 @@ files:
|
|
222
224
|
- lib/prefab/cancellable_interceptor.rb
|
223
225
|
- lib/prefab/client.rb
|
224
226
|
- lib/prefab/config_client.rb
|
225
|
-
- lib/prefab/config_helper.rb
|
226
227
|
- lib/prefab/config_loader.rb
|
227
228
|
- lib/prefab/config_resolver.rb
|
229
|
+
- lib/prefab/config_value_unwrapper.rb
|
230
|
+
- lib/prefab/criteria_evaluator.rb
|
228
231
|
- lib/prefab/error.rb
|
229
232
|
- lib/prefab/errors/initialization_timeout_error.rb
|
230
233
|
- lib/prefab/errors/invalid_api_key_error.rb
|
231
234
|
- lib/prefab/errors/missing_default_error.rb
|
232
235
|
- lib/prefab/feature_flag_client.rb
|
233
236
|
- lib/prefab/internal_logger.rb
|
237
|
+
- lib/prefab/local_config_parser.rb
|
238
|
+
- lib/prefab/log_path_collector.rb
|
234
239
|
- lib/prefab/logger_client.rb
|
235
240
|
- lib/prefab/murmer3.rb
|
236
241
|
- lib/prefab/noop_cache.rb
|
@@ -238,20 +243,29 @@ files:
|
|
238
243
|
- lib/prefab/options.rb
|
239
244
|
- lib/prefab/ratelimit_client.rb
|
240
245
|
- lib/prefab/sse_logger.rb
|
246
|
+
- lib/prefab/weighted_value_resolver.rb
|
247
|
+
- lib/prefab/yaml_config_parser.rb
|
241
248
|
- lib/prefab_pb.rb
|
242
249
|
- lib/prefab_services_pb.rb
|
243
250
|
- prefab-cloud-ruby.gemspec
|
244
|
-
- run_test_harness_server.sh
|
245
251
|
- test/.prefab.default.config.yaml
|
246
252
|
- test/.prefab.unit_tests.config.yaml
|
247
|
-
- test/
|
253
|
+
- test/integration_test.rb
|
254
|
+
- test/integration_test_helpers.rb
|
248
255
|
- test/test_client.rb
|
249
256
|
- test/test_config_client.rb
|
250
257
|
- test/test_config_loader.rb
|
251
258
|
- test/test_config_resolver.rb
|
259
|
+
- test/test_config_value_unwrapper.rb
|
260
|
+
- test/test_criteria_evaluator.rb
|
252
261
|
- test/test_feature_flag_client.rb
|
253
262
|
- test/test_helper.rb
|
263
|
+
- test/test_integration.rb
|
264
|
+
- test/test_local_config_parser.rb
|
265
|
+
- test/test_log_path_collector.rb
|
254
266
|
- test/test_logger.rb
|
267
|
+
- test/test_options.rb
|
268
|
+
- test/test_weighted_value_resolver.rb
|
255
269
|
homepage: http://github.com/prefab-cloud/prefab-cloud-ruby
|
256
270
|
licenses:
|
257
271
|
- MIT
|
data/lib/prefab/config_helper.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Prefab
|
3
|
-
module ConfigHelper
|
4
|
-
def value_of(config_value)
|
5
|
-
case config_value.type
|
6
|
-
when :string
|
7
|
-
config_value.string
|
8
|
-
when :int
|
9
|
-
config_value.int
|
10
|
-
when :double
|
11
|
-
config_value.double
|
12
|
-
when :bool
|
13
|
-
config_value.bool
|
14
|
-
when :feature_flag
|
15
|
-
config_value.feature_flag
|
16
|
-
when :segment
|
17
|
-
config_value.segment
|
18
|
-
when :log_level
|
19
|
-
config_value.log_level
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def value_of_variant(feature_flag_variant)
|
24
|
-
return feature_flag_variant.string if feature_flag_variant.has_string?
|
25
|
-
return feature_flag_variant.int if feature_flag_variant.has_int?
|
26
|
-
return feature_flag_variant.double if feature_flag_variant.has_double?
|
27
|
-
return feature_flag_variant.bool if feature_flag_variant.has_bool?
|
28
|
-
return nil
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/run_test_harness_server.sh
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
#! /usr/bin/env bash
|
2
|
-
|
3
|
-
PREFAB_CDN_URL="https://api-prefab-cloud.global.ssl.fastly.net" \
|
4
|
-
PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL=debug \
|
5
|
-
PREFAB_CLOUD_HTTP=true \
|
6
|
-
PREFAB_API_KEY="1|local_development_api_key" \
|
7
|
-
PREFAB_GRPC_URL="localhost:50051" \
|
8
|
-
ruby -Ilib test/harness_server.rb
|
data/test/harness_server.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'prefab-cloud-ruby'
|
3
|
-
require 'rack'
|
4
|
-
require 'base64'
|
5
|
-
require 'json'
|
6
|
-
|
7
|
-
handler = Rack::Handler::Thin
|
8
|
-
|
9
|
-
#
|
10
|
-
# This is a very lightweight server that allows the compliance harness to excercise the prefab client
|
11
|
-
#
|
12
|
-
class RackApp
|
13
|
-
def call(env)
|
14
|
-
props = CGI::parse(env["QUERY_STRING"])
|
15
|
-
props = JSON.parse(Base64.decode64(props["props"][0]))
|
16
|
-
|
17
|
-
key = props["key"]
|
18
|
-
namespace = props["namespace"]
|
19
|
-
api_key = props["api_key"]
|
20
|
-
user_key = props["user_key"]
|
21
|
-
is_feature_flag = !props["feature_flag"].nil?
|
22
|
-
attributes = props["attributes"]
|
23
|
-
puts props
|
24
|
-
|
25
|
-
options = Prefab::Options.new(
|
26
|
-
api_key: api_key,
|
27
|
-
namespace: namespace,
|
28
|
-
initialization_timeout_sec: 1,
|
29
|
-
# We want to `return` rather than raise so we'll use the initial payload if we can't connect to the SSE server
|
30
|
-
on_init_failure: Prefab::Options::ON_INITIALIZATION_FAILURE::RETURN,
|
31
|
-
# Want to return `nil` rather than raise so we can verify empty values
|
32
|
-
on_no_default: Prefab::Options::ON_NO_DEFAULT::RETURN_NIL
|
33
|
-
)
|
34
|
-
|
35
|
-
client = Prefab::Client.new(options)
|
36
|
-
|
37
|
-
puts "Key #{key}"
|
38
|
-
puts "User #{user_key}"
|
39
|
-
puts "api_key #{api_key}"
|
40
|
-
puts "Namespace #{namespace}"
|
41
|
-
puts "Props! #{props}"
|
42
|
-
puts "is_feature_flag! #{is_feature_flag}"
|
43
|
-
|
44
|
-
puts client.config_client.to_s
|
45
|
-
|
46
|
-
if is_feature_flag
|
47
|
-
puts "EVALFF #{key} #{user_key}"
|
48
|
-
rtn = client.feature_flag_client.get(key, user_key, attributes).to_s
|
49
|
-
else
|
50
|
-
rtn = client.config_client.get(key).to_s
|
51
|
-
end
|
52
|
-
|
53
|
-
puts "return #{rtn}"
|
54
|
-
|
55
|
-
[200, { "Content-Type" => "text/plain" }, rtn]
|
56
|
-
|
57
|
-
rescue Exception => e
|
58
|
-
puts "ERROR #{e.message}"
|
59
|
-
puts e.backtrace
|
60
|
-
[500, { "Content-Type" => "text/plain" }, e.message]
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
handler.run RackApp.new
|