prefab-cloud-ruby 0.20.0 → 0.21.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/.envrc.sample +3 -0
- data/.github/workflows/ruby.yml +4 -0
- data/.gitmodules +3 -0
- data/Gemfile +12 -12
- data/Gemfile.lock +16 -14
- data/README.md +1 -1
- 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 +33 -24
- data/lib/prefab/config_client.rb +55 -66
- 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 +6 -5
- data/lib/prefab/local_config_parser.rb +110 -0
- data/lib/prefab/logger_client.rb +26 -31
- 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 +11 -9
- 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 +49 -43
- data/lib/prefab_services_pb.rb +0 -1
- data/prefab-cloud-ruby.gemspec +28 -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 +32 -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_logger.rb +47 -46
- data/test/test_weighted_value_resolver.rb +65 -0
- metadata +24 -27
- data/lib/prefab/config_helper.rb +0 -31
- data/run_test_harness_server.sh +0 -8
- data/test/harness_server.rb +0 -64
data/lib/prefab_pb.rb
CHANGED
@@ -17,12 +17,22 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
17
17
|
optional :bytes, :bytes, 3
|
18
18
|
optional :double, :double, 4
|
19
19
|
optional :bool, :bool, 5
|
20
|
-
optional :
|
20
|
+
optional :weighted_values, :message, 6, "prefab.WeightedValues"
|
21
21
|
optional :limit_definition, :message, 7, "prefab.LimitDefinition"
|
22
|
-
optional :segment, :message, 8, "prefab.Segment"
|
23
22
|
optional :log_level, :enum, 9, "prefab.LogLevel"
|
23
|
+
optional :string_list, :message, 10, "prefab.StringList"
|
24
24
|
end
|
25
25
|
end
|
26
|
+
add_message "prefab.StringList" do
|
27
|
+
repeated :values, :string, 1
|
28
|
+
end
|
29
|
+
add_message "prefab.WeightedValue" do
|
30
|
+
optional :weight, :int32, 1
|
31
|
+
optional :value, :message, 2, "prefab.ConfigValue"
|
32
|
+
end
|
33
|
+
add_message "prefab.WeightedValues" do
|
34
|
+
repeated :weighted_values, :message, 1, "prefab.WeightedValue"
|
35
|
+
end
|
26
36
|
add_message "prefab.Configs" do
|
27
37
|
repeated :configs, :message, 1, "prefab.Config"
|
28
38
|
optional :config_service_pointer, :message, 2, "prefab.ConfigServicePointer"
|
@@ -31,14 +41,24 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
31
41
|
optional :id, :int64, 1
|
32
42
|
optional :project_id, :int64, 2
|
33
43
|
optional :key, :string, 3
|
34
|
-
optional :changed_by, :
|
44
|
+
optional :changed_by, :message, 4, "prefab.ChangedBy"
|
35
45
|
repeated :rows, :message, 5, "prefab.ConfigRow"
|
36
|
-
repeated :
|
46
|
+
repeated :allowable_values, :message, 6, "prefab.ConfigValue"
|
47
|
+
optional :config_type, :enum, 7, "prefab.ConfigType"
|
48
|
+
proto3_optional :draftId, :int64, 8
|
49
|
+
end
|
50
|
+
add_message "prefab.ChangedBy" do
|
51
|
+
optional :user_id, :int64, 1
|
52
|
+
optional :email, :string, 2
|
37
53
|
end
|
38
54
|
add_message "prefab.ConfigRow" do
|
39
|
-
|
40
|
-
|
41
|
-
|
55
|
+
proto3_optional :project_env_id, :int64, 1
|
56
|
+
repeated :values, :message, 2, "prefab.ConditionalValue"
|
57
|
+
map :properties, :string, :message, 3, "prefab.ConfigValue"
|
58
|
+
end
|
59
|
+
add_message "prefab.ConditionalValue" do
|
60
|
+
repeated :criteria, :message, 1, "prefab.Criterion"
|
61
|
+
optional :value, :message, 2, "prefab.ConfigValue"
|
42
62
|
end
|
43
63
|
add_message "prefab.LimitResponse" do
|
44
64
|
optional :passed, :bool, 1
|
@@ -75,20 +95,12 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
75
95
|
value :MINIMUM, 1
|
76
96
|
value :MAXIMUM, 2
|
77
97
|
end
|
78
|
-
add_message "prefab.
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
proto3_optional :bool, :bool, 4
|
83
|
-
optional :name, :string, 5
|
84
|
-
optional :description, :string, 6
|
85
|
-
end
|
86
|
-
add_message "prefab.Criteria" do
|
87
|
-
optional :property, :string, 1
|
88
|
-
optional :operator, :enum, 2, "prefab.Criteria.CriteriaOperator"
|
89
|
-
repeated :values, :string, 3
|
98
|
+
add_message "prefab.Criterion" do
|
99
|
+
optional :property_name, :string, 1
|
100
|
+
optional :operator, :enum, 2, "prefab.Criterion.CriterionOperator"
|
101
|
+
optional :value_to_match, :message, 3, "prefab.ConfigValue"
|
90
102
|
end
|
91
|
-
add_enum "prefab.
|
103
|
+
add_enum "prefab.Criterion.CriterionOperator" do
|
92
104
|
value :NOT_SET, 0
|
93
105
|
value :LOOKUP_KEY_IN, 1
|
94
106
|
value :LOOKUP_KEY_NOT_IN, 2
|
@@ -99,22 +111,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
99
111
|
value :PROP_IS_NOT_ONE_OF, 7
|
100
112
|
value :PROP_ENDS_WITH_ONE_OF, 8
|
101
113
|
value :PROP_DOES_NOT_END_WITH_ONE_OF, 9
|
102
|
-
|
103
|
-
add_message "prefab.Rule" do
|
104
|
-
optional :criteria, :message, 1, "prefab.Criteria"
|
105
|
-
repeated :variant_weights, :message, 2, "prefab.VariantWeight"
|
106
|
-
end
|
107
|
-
add_message "prefab.Segment" do
|
108
|
-
repeated :criterion, :message, 1, "prefab.Criteria"
|
109
|
-
end
|
110
|
-
add_message "prefab.VariantWeight" do
|
111
|
-
optional :weight, :int32, 1
|
112
|
-
optional :variant_idx, :int32, 2
|
113
|
-
end
|
114
|
-
add_message "prefab.FeatureFlag" do
|
115
|
-
optional :active, :bool, 1
|
116
|
-
optional :inactive_variant_idx, :int32, 2
|
117
|
-
repeated :rules, :message, 5, "prefab.Rule"
|
114
|
+
value :HIERARCHICAL_MATCH, 10
|
118
115
|
end
|
119
116
|
add_message "prefab.Identity" do
|
120
117
|
proto3_optional :lookup, :string, 1
|
@@ -184,6 +181,14 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
184
181
|
optional :sequence_name, :string, 3
|
185
182
|
optional :size, :int64, 4
|
186
183
|
end
|
184
|
+
add_enum "prefab.ConfigType" do
|
185
|
+
value :NOT_SET_CONFIG_TYPE, 0
|
186
|
+
value :CONFIG, 1
|
187
|
+
value :FEATURE_FLAG, 2
|
188
|
+
value :LOG_LEVEL, 3
|
189
|
+
value :SEGMENT, 4
|
190
|
+
value :LIMIT_DEFINITION, 5
|
191
|
+
end
|
187
192
|
add_enum "prefab.LogLevel" do
|
188
193
|
value :NOT_SET_LOG_LEVEL, 0
|
189
194
|
value :TRACE, 1
|
@@ -205,20 +210,20 @@ end
|
|
205
210
|
module Prefab
|
206
211
|
ConfigServicePointer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigServicePointer").msgclass
|
207
212
|
ConfigValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigValue").msgclass
|
213
|
+
StringList = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.StringList").msgclass
|
214
|
+
WeightedValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.WeightedValue").msgclass
|
215
|
+
WeightedValues = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.WeightedValues").msgclass
|
208
216
|
Configs = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Configs").msgclass
|
209
217
|
Config = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Config").msgclass
|
218
|
+
ChangedBy = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ChangedBy").msgclass
|
210
219
|
ConfigRow = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigRow").msgclass
|
220
|
+
ConditionalValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConditionalValue").msgclass
|
211
221
|
LimitResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitResponse").msgclass
|
212
222
|
LimitResponse::LimitPolicyNames = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitResponse.LimitPolicyNames").enummodule
|
213
223
|
LimitRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitRequest").msgclass
|
214
224
|
LimitRequest::LimitCombiner = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitRequest.LimitCombiner").enummodule
|
215
|
-
|
216
|
-
|
217
|
-
Criteria::CriteriaOperator = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Criteria.CriteriaOperator").enummodule
|
218
|
-
Rule = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Rule").msgclass
|
219
|
-
Segment = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Segment").msgclass
|
220
|
-
VariantWeight = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.VariantWeight").msgclass
|
221
|
-
FeatureFlag = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.FeatureFlag").msgclass
|
225
|
+
Criterion = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Criterion").msgclass
|
226
|
+
Criterion::CriterionOperator = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Criterion.CriterionOperator").enummodule
|
222
227
|
Identity = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Identity").msgclass
|
223
228
|
ClientConfigValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ClientConfigValue").msgclass
|
224
229
|
ConfigEvaluations = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigEvaluations").msgclass
|
@@ -231,6 +236,7 @@ module Prefab
|
|
231
236
|
CreationResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.CreationResponse").msgclass
|
232
237
|
IdBlock = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.IdBlock").msgclass
|
233
238
|
IdBlockRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.IdBlockRequest").msgclass
|
239
|
+
ConfigType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigType").enummodule
|
234
240
|
LogLevel = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LogLevel").enummodule
|
235
241
|
OnFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.OnFailure").enummodule
|
236
242
|
end
|
data/lib/prefab_services_pb.rb
CHANGED
data/prefab-cloud-ruby.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: prefab-cloud-ruby 0.
|
5
|
+
# stub: prefab-cloud-ruby 0.21.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "prefab-cloud-ruby".freeze
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.21.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["Jeff Dwyer".freeze]
|
14
|
-
s.date = "
|
14
|
+
s.date = "2023-02-27"
|
15
15
|
s.description = "RateLimits & Config as a service".freeze
|
16
16
|
s.email = "jdwyer@prefab.cloud".freeze
|
17
17
|
s.extra_rdoc_files = [
|
@@ -20,7 +20,9 @@ Gem::Specification.new do |s|
|
|
20
20
|
]
|
21
21
|
s.files = [
|
22
22
|
".envrc",
|
23
|
+
".envrc.sample",
|
23
24
|
".github/workflows/ruby.yml",
|
25
|
+
".gitmodules",
|
24
26
|
".tool-versions",
|
25
27
|
"CODEOWNERS",
|
26
28
|
"Gemfile",
|
@@ -35,15 +37,17 @@ Gem::Specification.new do |s|
|
|
35
37
|
"lib/prefab/cancellable_interceptor.rb",
|
36
38
|
"lib/prefab/client.rb",
|
37
39
|
"lib/prefab/config_client.rb",
|
38
|
-
"lib/prefab/config_helper.rb",
|
39
40
|
"lib/prefab/config_loader.rb",
|
40
41
|
"lib/prefab/config_resolver.rb",
|
42
|
+
"lib/prefab/config_value_unwrapper.rb",
|
43
|
+
"lib/prefab/criteria_evaluator.rb",
|
41
44
|
"lib/prefab/error.rb",
|
42
45
|
"lib/prefab/errors/initialization_timeout_error.rb",
|
43
46
|
"lib/prefab/errors/invalid_api_key_error.rb",
|
44
47
|
"lib/prefab/errors/missing_default_error.rb",
|
45
48
|
"lib/prefab/feature_flag_client.rb",
|
46
49
|
"lib/prefab/internal_logger.rb",
|
50
|
+
"lib/prefab/local_config_parser.rb",
|
47
51
|
"lib/prefab/logger_client.rb",
|
48
52
|
"lib/prefab/murmer3.rb",
|
49
53
|
"lib/prefab/noop_cache.rb",
|
@@ -51,20 +55,27 @@ Gem::Specification.new do |s|
|
|
51
55
|
"lib/prefab/options.rb",
|
52
56
|
"lib/prefab/ratelimit_client.rb",
|
53
57
|
"lib/prefab/sse_logger.rb",
|
58
|
+
"lib/prefab/weighted_value_resolver.rb",
|
59
|
+
"lib/prefab/yaml_config_parser.rb",
|
54
60
|
"lib/prefab_pb.rb",
|
55
61
|
"lib/prefab_services_pb.rb",
|
56
62
|
"prefab-cloud-ruby.gemspec",
|
57
|
-
"run_test_harness_server.sh",
|
58
63
|
"test/.prefab.default.config.yaml",
|
59
64
|
"test/.prefab.unit_tests.config.yaml",
|
60
|
-
"test/
|
65
|
+
"test/integration_test.rb",
|
66
|
+
"test/integration_test_helpers.rb",
|
61
67
|
"test/test_client.rb",
|
62
68
|
"test/test_config_client.rb",
|
63
69
|
"test/test_config_loader.rb",
|
64
70
|
"test/test_config_resolver.rb",
|
71
|
+
"test/test_config_value_unwrapper.rb",
|
72
|
+
"test/test_criteria_evaluator.rb",
|
65
73
|
"test/test_feature_flag_client.rb",
|
66
74
|
"test/test_helper.rb",
|
67
|
-
"test/
|
75
|
+
"test/test_integration.rb",
|
76
|
+
"test/test_local_config_parser.rb",
|
77
|
+
"test/test_logger.rb",
|
78
|
+
"test/test_weighted_value_resolver.rb"
|
68
79
|
]
|
69
80
|
s.homepage = "http://github.com/prefab-cloud/prefab-cloud-ruby".freeze
|
70
81
|
s.licenses = ["MIT".freeze]
|
@@ -78,31 +89,29 @@ Gem::Specification.new do |s|
|
|
78
89
|
if s.respond_to? :add_runtime_dependency then
|
79
90
|
s.add_runtime_dependency(%q<concurrent-ruby>.freeze, ["~> 1.0", ">= 1.0.5"])
|
80
91
|
s.add_runtime_dependency(%q<faraday>.freeze, [">= 0"])
|
81
|
-
s.add_runtime_dependency(%q<ld-eventsource>.freeze, [">= 0"])
|
82
|
-
s.add_runtime_dependency(%q<grpc>.freeze, [">= 0"])
|
83
|
-
s.add_runtime_dependency(%q<google-protobuf>.freeze, [">= 0"])
|
84
92
|
s.add_runtime_dependency(%q<googleapis-common-protos-types>.freeze, [">= 0"])
|
93
|
+
s.add_runtime_dependency(%q<google-protobuf>.freeze, [">= 0"])
|
94
|
+
s.add_runtime_dependency(%q<grpc>.freeze, [">= 0"])
|
95
|
+
s.add_runtime_dependency(%q<ld-eventsource>.freeze, [">= 0"])
|
85
96
|
s.add_development_dependency(%q<benchmark-ips>.freeze, [">= 0"])
|
86
|
-
s.add_development_dependency(%q<grpc-tools>.freeze, [">= 0"])
|
87
|
-
s.add_development_dependency(%q<rdoc>.freeze, [">= 0"])
|
88
97
|
s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
|
98
|
+
s.add_development_dependency(%q<grpc-tools>.freeze, [">= 0"])
|
89
99
|
s.add_development_dependency(%q<juwelier>.freeze, ["~> 2.4.9"])
|
100
|
+
s.add_development_dependency(%q<rdoc>.freeze, [">= 0"])
|
90
101
|
s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
|
91
|
-
s.add_development_dependency(%q<thin>.freeze, [">= 0"])
|
92
102
|
else
|
93
103
|
s.add_dependency(%q<concurrent-ruby>.freeze, ["~> 1.0", ">= 1.0.5"])
|
94
104
|
s.add_dependency(%q<faraday>.freeze, [">= 0"])
|
95
|
-
s.add_dependency(%q<ld-eventsource>.freeze, [">= 0"])
|
96
|
-
s.add_dependency(%q<grpc>.freeze, [">= 0"])
|
97
|
-
s.add_dependency(%q<google-protobuf>.freeze, [">= 0"])
|
98
105
|
s.add_dependency(%q<googleapis-common-protos-types>.freeze, [">= 0"])
|
106
|
+
s.add_dependency(%q<google-protobuf>.freeze, [">= 0"])
|
107
|
+
s.add_dependency(%q<grpc>.freeze, [">= 0"])
|
108
|
+
s.add_dependency(%q<ld-eventsource>.freeze, [">= 0"])
|
99
109
|
s.add_dependency(%q<benchmark-ips>.freeze, [">= 0"])
|
100
|
-
s.add_dependency(%q<grpc-tools>.freeze, [">= 0"])
|
101
|
-
s.add_dependency(%q<rdoc>.freeze, [">= 0"])
|
102
110
|
s.add_dependency(%q<bundler>.freeze, [">= 0"])
|
111
|
+
s.add_dependency(%q<grpc-tools>.freeze, [">= 0"])
|
103
112
|
s.add_dependency(%q<juwelier>.freeze, ["~> 2.4.9"])
|
113
|
+
s.add_dependency(%q<rdoc>.freeze, [">= 0"])
|
104
114
|
s.add_dependency(%q<simplecov>.freeze, [">= 0"])
|
105
|
-
s.add_dependency(%q<thin>.freeze, [">= 0"])
|
106
115
|
end
|
107
116
|
end
|
108
117
|
|
@@ -9,8 +9,9 @@ sample: test sample value
|
|
9
9
|
enabled_flag: true
|
10
10
|
disabled_flag: false
|
11
11
|
flag_with_a_value: { "feature_flag": "true", value: "all-features" }
|
12
|
-
in_lookup_key: { "feature_flag": "true", value: true,
|
13
|
-
just_my_domain: { "feature_flag": "true", value: "new-version",
|
12
|
+
in_lookup_key: { "feature_flag": "true", value: true, criterion: { operator: LOOKUP_KEY_IN, values: [ "abc123", "xyz987" ] } }
|
13
|
+
just_my_domain: { "feature_flag": "true", value: "new-version", criterion: { operator: PROP_IS_ONE_OF, property: "domain", values: [ "prefab.cloud", "example.com" ] } }
|
14
|
+
|
14
15
|
nested:
|
15
16
|
values:
|
16
17
|
_: top level
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class IntegrationTest
|
4
|
+
attr_reader :func
|
5
|
+
attr_reader :input
|
6
|
+
attr_reader :expected
|
7
|
+
attr_reader :test_client
|
8
|
+
|
9
|
+
def initialize(test_data)
|
10
|
+
@client_overrides = parse_client_overrides(test_data['client_overrides'])
|
11
|
+
@func = parse_function(test_data['function'])
|
12
|
+
@input = parse_input(test_data['input'])
|
13
|
+
@expected = parse_expected(test_data['expected'])
|
14
|
+
test_client = :"#{test_data['client']}"
|
15
|
+
@test_client = base_client.send(test_client)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_type
|
19
|
+
if @expected[:status] == 'raise'
|
20
|
+
:raise
|
21
|
+
elsif @expected[:value].nil?
|
22
|
+
:nil
|
23
|
+
elsif @func == :feature_is_on_for?
|
24
|
+
:feature_flag
|
25
|
+
else
|
26
|
+
:simple_equality
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def parse_client_overrides(overrides)
|
33
|
+
Hash[
|
34
|
+
(overrides || {}).map do |(k, v)|
|
35
|
+
[k.to_sym, v]
|
36
|
+
end
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_function(function)
|
41
|
+
case function
|
42
|
+
when 'get_or_raise' then :get
|
43
|
+
when 'enabled' then :feature_is_on_for?
|
44
|
+
else :"#{function}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_input(input)
|
49
|
+
if input['key']
|
50
|
+
parse_config_input(input)
|
51
|
+
elsif input['flag']
|
52
|
+
parse_ff_input(input)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_config_input(input)
|
57
|
+
if !input['default'].nil?
|
58
|
+
[input['key'], input['default']]
|
59
|
+
else
|
60
|
+
[input['key']]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def parse_ff_input(input)
|
65
|
+
[input['flag'], input['lookup_key'], input['properties'] || {}]
|
66
|
+
end
|
67
|
+
|
68
|
+
def parse_expected(expected)
|
69
|
+
{
|
70
|
+
status: expected['status'],
|
71
|
+
error: parse_error_type(expected['error']),
|
72
|
+
message: expected['message'],
|
73
|
+
value: expected['value']
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def parse_error_type(error_type)
|
78
|
+
case error_type
|
79
|
+
when 'missing_default' then Prefab::Errors::MissingDefaultError
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def base_client
|
84
|
+
@_base_client ||= Prefab::Client.new(base_client_options)
|
85
|
+
end
|
86
|
+
|
87
|
+
def base_client_options
|
88
|
+
@_options ||= Prefab::Options.new(**{
|
89
|
+
prefab_config_override_dir: 'none',
|
90
|
+
prefab_config_classpath_dir: 'test',
|
91
|
+
prefab_envs: ['unit_tests'],
|
92
|
+
prefab_datasources: Prefab::Options::DATASOURCES::ALL,
|
93
|
+
api_key: ENV['PREFAB_INTEGRATION_TEST_API_KEY'],
|
94
|
+
prefab_api_url: 'https://api.staging-prefab.cloud',
|
95
|
+
prefab_grpc_url: 'grpc.staging-prefab.cloud:443'
|
96
|
+
}.merge(@client_overrides))
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IntegrationTestHelpers
|
4
|
+
SUBMODULE_PATH = 'test/prefab-cloud-integration-test-data'
|
5
|
+
RAISE_IF_NO_TESTS_FOUND = ENV['PREFAB_INTEGRATION_TEST_RAISE'] == 'true'
|
6
|
+
|
7
|
+
def self.find_integration_tests
|
8
|
+
version = find_integration_test_version
|
9
|
+
|
10
|
+
files = find_versioned_test_files(version)
|
11
|
+
|
12
|
+
if files.none?
|
13
|
+
message = "No integration tests found for version: #{version}"
|
14
|
+
raise message if RAISE_IF_NO_TESTS_FOUND
|
15
|
+
|
16
|
+
puts message
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
files
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.find_integration_test_version
|
24
|
+
File.read(File.join(SUBMODULE_PATH, 'version')).strip
|
25
|
+
rescue StandardError => e
|
26
|
+
puts "No version found for integration tests: #{e.message}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.find_versioned_test_files(version)
|
30
|
+
if version.nil?
|
31
|
+
[]
|
32
|
+
else
|
33
|
+
Dir[File.join(SUBMODULE_PATH, "tests/#{version}/**/*")]
|
34
|
+
.select { |file| file =~ /\.ya?ml$/ }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/test/test_client.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'test_helper'
|
3
4
|
|
4
5
|
class TestClient < Minitest::Test
|
@@ -7,25 +8,25 @@ class TestClient < Minitest::Test
|
|
7
8
|
end
|
8
9
|
|
9
10
|
def test_get
|
10
|
-
assert_equal
|
11
|
-
assert_equal 123, @client.get(
|
11
|
+
assert_equal 'test sample value', @client.get('sample')
|
12
|
+
assert_equal 123, @client.get('sample_int')
|
12
13
|
end
|
13
14
|
|
14
15
|
def test_get_with_default
|
15
16
|
# A `false` value is not replaced with the default
|
16
|
-
assert_equal false, @client.get(
|
17
|
+
assert_equal false, @client.get('false_value', 'red')
|
17
18
|
|
18
19
|
# A falsy value is not replaced with the default
|
19
|
-
assert_equal 0, @client.get(
|
20
|
+
assert_equal 0, @client.get('zero_value', 'red')
|
20
21
|
|
21
22
|
# A missing value returns the default
|
22
|
-
assert_equal
|
23
|
+
assert_equal 'buckets', @client.get('missing_value', 'buckets')
|
23
24
|
end
|
24
25
|
|
25
26
|
def test_get_with_missing_default
|
26
27
|
# it raises by default
|
27
28
|
err = assert_raises(Prefab::Errors::MissingDefaultError) do
|
28
|
-
assert_nil @client.get(
|
29
|
+
assert_nil @client.get('missing_value')
|
29
30
|
end
|
30
31
|
|
31
32
|
assert_match(/No value found for key/, err.message)
|
@@ -33,51 +34,51 @@ class TestClient < Minitest::Test
|
|
33
34
|
|
34
35
|
# you can opt-in to return `nil` instead
|
35
36
|
client = new_client(on_no_default: Prefab::Options::ON_NO_DEFAULT::RETURN_NIL)
|
36
|
-
assert_nil client.get(
|
37
|
+
assert_nil client.get('missing_value')
|
37
38
|
end
|
38
39
|
|
39
40
|
def test_enabled
|
40
|
-
assert_equal false, @client.enabled?(
|
41
|
-
assert_equal true, @client.enabled?(
|
42
|
-
assert_equal false, @client.enabled?(
|
43
|
-
assert_equal false, @client.enabled?(
|
41
|
+
assert_equal false, @client.enabled?('does_not_exist')
|
42
|
+
assert_equal true, @client.enabled?('enabled_flag')
|
43
|
+
assert_equal false, @client.enabled?('disabled_flag')
|
44
|
+
assert_equal false, @client.enabled?('flag_with_a_value')
|
44
45
|
end
|
45
46
|
|
46
47
|
def test_ff_enabled_with_lookup_key
|
47
|
-
assert_equal false, @client.enabled?(
|
48
|
-
assert_equal true, @client.enabled?(
|
49
|
-
assert_equal true, @client.enabled?(
|
48
|
+
assert_equal false, @client.enabled?('in_lookup_key', 'jimmy')
|
49
|
+
assert_equal true, @client.enabled?('in_lookup_key', 'abc123')
|
50
|
+
assert_equal true, @client.enabled?('in_lookup_key', 'xyz987')
|
50
51
|
end
|
51
52
|
|
52
53
|
def test_ff_get_with_lookup_key
|
53
|
-
assert_nil @client.get(
|
54
|
-
assert_equal
|
54
|
+
assert_nil @client.get('in_lookup_key', 'jimmy')
|
55
|
+
assert_equal 'DEFAULT', @client.get('in_lookup_key', 'jimmy', {}, 'DEFAULT')
|
55
56
|
|
56
|
-
assert_equal true, @client.get(
|
57
|
-
assert_equal true, @client.get(
|
57
|
+
assert_equal true, @client.get('in_lookup_key', 'abc123')
|
58
|
+
assert_equal true, @client.get('in_lookup_key', 'xyz987')
|
58
59
|
end
|
59
60
|
|
60
61
|
def test_ff_enabled_with_attributes
|
61
|
-
assert_equal false, @client.enabled?(
|
62
|
-
assert_equal false, @client.enabled?(
|
63
|
-
assert_equal false, @client.enabled?(
|
62
|
+
assert_equal false, @client.enabled?('just_my_domain', 'abc123', { domain: 'gmail.com' })
|
63
|
+
assert_equal false, @client.enabled?('just_my_domain', 'abc123', { domain: 'prefab.cloud' })
|
64
|
+
assert_equal false, @client.enabled?('just_my_domain', 'abc123', { domain: 'example.com' })
|
64
65
|
end
|
65
66
|
|
66
67
|
def test_ff_get_with_attributes
|
67
|
-
assert_nil @client.get(
|
68
|
-
assert_equal
|
68
|
+
assert_nil @client.get('just_my_domain', 'abc123', { domain: 'gmail.com' })
|
69
|
+
assert_equal 'DEFAULT', @client.get('just_my_domain', 'abc123', { domain: 'gmail.com' }, 'DEFAULT')
|
69
70
|
|
70
|
-
assert_equal
|
71
|
-
assert_equal
|
71
|
+
assert_equal 'new-version', @client.get('just_my_domain', 'abc123', { domain: 'prefab.cloud' })
|
72
|
+
assert_equal 'new-version', @client.get('just_my_domain', 'abc123', { domain: 'example.com' })
|
72
73
|
end
|
73
74
|
|
74
75
|
def test_getting_feature_flag_value
|
75
|
-
assert_equal false, @client.enabled?(
|
76
|
-
assert_equal
|
76
|
+
assert_equal false, @client.enabled?('flag_with_a_value')
|
77
|
+
assert_equal 'all-features', @client.get('flag_with_a_value')
|
77
78
|
end
|
78
79
|
|
79
80
|
def test_ssl_certs
|
80
|
-
certs = @client.send(:ssl_certs).split(
|
81
|
+
certs = @client.send(:ssl_certs).split('-----BEGIN CERTIFICATE-----')
|
81
82
|
|
82
83
|
# This is a smoke test to make sure multiple certs are loaded
|
83
84
|
assert certs.length > 1
|
@@ -87,9 +88,9 @@ class TestClient < Minitest::Test
|
|
87
88
|
|
88
89
|
def new_client(overrides = {})
|
89
90
|
options = Prefab::Options.new(**{
|
90
|
-
prefab_config_override_dir:
|
91
|
-
prefab_config_classpath_dir:
|
92
|
-
prefab_envs: [
|
91
|
+
prefab_config_override_dir: 'none',
|
92
|
+
prefab_config_classpath_dir: 'test',
|
93
|
+
prefab_envs: ['unit_tests'],
|
93
94
|
prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY
|
94
95
|
}.merge(overrides))
|
95
96
|
|
data/test/test_config_client.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'test_helper'
|
3
4
|
|
4
5
|
class TestConfigClient < Minitest::Test
|
5
6
|
def setup
|
6
7
|
options = Prefab::Options.new(
|
7
|
-
prefab_config_override_dir:
|
8
|
-
prefab_config_classpath_dir:
|
9
|
-
prefab_envs:
|
8
|
+
prefab_config_override_dir: 'none',
|
9
|
+
prefab_config_classpath_dir: 'test',
|
10
|
+
prefab_envs: 'unit_tests',
|
10
11
|
prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY
|
11
12
|
)
|
12
13
|
|
@@ -14,59 +15,59 @@ class TestConfigClient < Minitest::Test
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def test_load
|
17
|
-
assert_equal
|
18
|
-
assert_equal 123, @config_client.get(
|
19
|
-
assert_equal 12.12, @config_client.get(
|
20
|
-
assert_equal true, @config_client.get(
|
21
|
-
assert_equal :ERROR, @config_client.get(
|
18
|
+
assert_equal 'test sample value', @config_client.get('sample')
|
19
|
+
assert_equal 123, @config_client.get('sample_int')
|
20
|
+
assert_equal 12.12, @config_client.get('sample_double')
|
21
|
+
assert_equal true, @config_client.get('sample_bool')
|
22
|
+
assert_equal :ERROR, @config_client.get('log-level.app')
|
22
23
|
end
|
23
24
|
|
24
25
|
def test_initialization_timeout_error
|
25
26
|
options = Prefab::Options.new(
|
26
|
-
api_key:
|
27
|
+
api_key: '123-ENV-KEY-SDK',
|
27
28
|
initialization_timeout_sec: 0.01,
|
28
29
|
logdev: StringIO.new
|
29
30
|
)
|
30
31
|
|
31
32
|
err = assert_raises(Prefab::Errors::InitializationTimeoutError) do
|
32
|
-
Prefab::Client.new(options).config_client.get(
|
33
|
+
Prefab::Client.new(options).config_client.get('anything')
|
33
34
|
end
|
34
35
|
|
35
36
|
assert_match(/couldn't initialize in 0.01 second timeout/, err.message)
|
36
37
|
end
|
37
38
|
|
38
39
|
def test_prefab_envs_is_forgiving
|
39
|
-
assert_equal [
|
40
|
-
prefab_envs:
|
40
|
+
assert_equal ['my_env'], Prefab::Options.new(
|
41
|
+
prefab_envs: 'my_env'
|
41
42
|
).prefab_envs
|
42
43
|
|
43
|
-
assert_equal [
|
44
|
-
prefab_envs: [
|
44
|
+
assert_equal %w[my_env a_second_env], Prefab::Options.new(
|
45
|
+
prefab_envs: %w[my_env a_second_env]
|
45
46
|
).prefab_envs
|
46
47
|
end
|
47
48
|
|
48
49
|
def test_prefab_envs_env_var
|
49
|
-
ENV[
|
50
|
-
assert_equal [
|
50
|
+
ENV['PREFAB_ENVS'] = 'one,two'
|
51
|
+
assert_equal %w[one two], Prefab::Options.new.prefab_envs
|
51
52
|
end
|
52
53
|
|
53
54
|
def test_invalid_api_key_error
|
54
55
|
options = Prefab::Options.new(
|
55
|
-
api_key:
|
56
|
+
api_key: ''
|
56
57
|
)
|
57
58
|
|
58
59
|
err = assert_raises(Prefab::Errors::InvalidApiKeyError) do
|
59
|
-
Prefab::Client.new(options).config_client.get(
|
60
|
+
Prefab::Client.new(options).config_client.get('anything')
|
60
61
|
end
|
61
62
|
|
62
63
|
assert_match(/No API key/, err.message)
|
63
64
|
|
64
65
|
options = Prefab::Options.new(
|
65
|
-
api_key:
|
66
|
+
api_key: 'invalid'
|
66
67
|
)
|
67
68
|
|
68
69
|
err = assert_raises(Prefab::Errors::InvalidApiKeyError) do
|
69
|
-
Prefab::Client.new(options).config_client.get(
|
70
|
+
Prefab::Client.new(options).config_client.get('anything')
|
70
71
|
end
|
71
72
|
|
72
73
|
assert_match(/format is invalid/, err.message)
|