prefab-cloud-ruby 1.2.0 → 1.3.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/CHANGELOG.md +12 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +21 -0
- data/LICENSE.txt +1 -1
- data/VERSION +1 -1
- data/lib/prefab/client.rb +4 -0
- data/lib/prefab/config_client.rb +20 -1
- data/lib/prefab/config_loader.rb +2 -0
- data/lib/prefab/config_value_unwrapper.rb +93 -15
- data/lib/prefab/config_value_wrapper.rb +6 -6
- data/lib/prefab/criteria_evaluator.rb +4 -3
- data/lib/prefab/encryption.rb +65 -0
- data/lib/prefab/errors/env_var_parse_error.rb +11 -0
- data/lib/prefab/evaluation.rb +8 -4
- data/lib/prefab/internal_logger.rb +6 -23
- data/lib/prefab/local_config_parser.rb +58 -2
- data/lib/prefab/log_subscribers/action_controller_subscriber.rb +54 -0
- data/lib/prefab/logger_client.rb +0 -7
- data/lib/prefab/options.rb +11 -1
- data/lib/prefab/resolved_config_presenter.rb +2 -2
- data/lib/prefab/sse_logger.rb +4 -20
- data/lib/prefab/static_logger.rb +29 -0
- data/lib/prefab-cloud-ruby.rb +6 -0
- data/lib/prefab_pb.rb +5 -1
- data/prefab-cloud-ruby.gemspec +11 -3
- data/test/test_action_controller.rb +52 -0
- data/test/test_config_value_unwrapper.rb +167 -20
- data/test/test_context_shape.rb +3 -4
- data/test/test_encryption.rb +16 -0
- data/test/test_local_config_parser.rb +73 -2
- data/test/test_logger.rb +5 -5
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55134a75669f459bbb12d50cfa6e221937a5c00f53ca365e609f0cb436b24aff
|
4
|
+
data.tar.gz: f3507032152e1dfe7b48156e5b8795d3bfd9262e077fab18923fef7cbeb78e34
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 839db6777d5e6c3a76d34b7812787e8241779b2ede48d4ffddbf5e96bb493494e8d30e980582a5d06518e8f64f789287417ac5e6abc66c7789e17082992c83fb
|
7
|
+
data.tar.gz: fd26b0d5ceb02a17724ede1a3329bda2a1ca7ee1c8d49e0776c61498bfe7e1b41ca81158e395192c4c73c35970824e5eb2d319b241a9489e0e215febe9ea2bb6
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## Unreleased
|
4
|
+
|
5
|
+
## 1.3.0 - 2023-11-13
|
6
|
+
- Less logging when wifi is off and we load from cache (#157)
|
7
|
+
- Alpha: Add Provided & Secret Support (#152)
|
8
|
+
- Alpha: x_datafile (#156)
|
9
|
+
- Add single line action-controller output under rails.controller (#158)
|
10
|
+
|
11
|
+
## 1.2.1 - 2023-11-01
|
12
|
+
- Update protobuf definitions (#154)
|
13
|
+
|
14
|
+
|
3
15
|
## 1.2.0 - 2023-10-30
|
4
16
|
- Add `Prefab.get('key')` style usage after a `Prefab.init()` call (#151)
|
5
17
|
- Add `add_context_keys` and `with_context_keys` method for LoggerClient (#145)
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,17 +1,32 @@
|
|
1
1
|
GEM
|
2
2
|
remote: https://rubygems.org/
|
3
3
|
specs:
|
4
|
+
activesupport (7.1.2)
|
5
|
+
base64
|
6
|
+
bigdecimal
|
7
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
8
|
+
connection_pool (>= 2.2.5)
|
9
|
+
drb
|
10
|
+
i18n (>= 1.6, < 2)
|
11
|
+
minitest (>= 5.1)
|
12
|
+
mutex_m
|
13
|
+
tzinfo (~> 2.0)
|
4
14
|
addressable (2.8.0)
|
5
15
|
public_suffix (>= 2.0.2, < 5.0)
|
6
16
|
ansi (1.5.0)
|
17
|
+
base64 (0.2.0)
|
7
18
|
benchmark-ips (2.10.0)
|
19
|
+
bigdecimal (3.1.4)
|
8
20
|
builder (3.2.4)
|
9
21
|
concurrent-ruby (1.1.10)
|
22
|
+
connection_pool (2.4.1)
|
10
23
|
descendants_tracker (0.0.4)
|
11
24
|
thread_safe (~> 0.3, >= 0.3.1)
|
12
25
|
docile (1.3.5)
|
13
26
|
domain_name (0.5.20190701)
|
14
27
|
unf (>= 0.0.5, < 1.0.0)
|
28
|
+
drb (2.2.0)
|
29
|
+
ruby2_keywords
|
15
30
|
faraday (1.3.0)
|
16
31
|
faraday-net_http (~> 1.0)
|
17
32
|
multipart-post (>= 1.2, < 3)
|
@@ -43,6 +58,8 @@ GEM
|
|
43
58
|
http-cookie (1.0.4)
|
44
59
|
domain_name (~> 0.5)
|
45
60
|
http-form_data (2.3.0)
|
61
|
+
i18n (1.14.1)
|
62
|
+
concurrent-ruby (~> 1.0)
|
46
63
|
juwelier (2.4.9)
|
47
64
|
builder
|
48
65
|
bundler
|
@@ -78,6 +95,7 @@ GEM
|
|
78
95
|
multi_json (1.15.0)
|
79
96
|
multi_xml (0.6.0)
|
80
97
|
multipart-post (2.1.1)
|
98
|
+
mutex_m (0.2.0)
|
81
99
|
nokogiri (1.15.2)
|
82
100
|
mini_portile2 (~> 2.8.2)
|
83
101
|
racc (~> 1.4)
|
@@ -104,6 +122,8 @@ GEM
|
|
104
122
|
systemu (2.6.5)
|
105
123
|
thread_safe (0.3.6)
|
106
124
|
timecop (0.9.4)
|
125
|
+
tzinfo (2.0.6)
|
126
|
+
concurrent-ruby (~> 1.0)
|
107
127
|
unf (0.1.4)
|
108
128
|
unf_ext
|
109
129
|
unf_ext (0.0.8)
|
@@ -114,6 +134,7 @@ PLATFORMS
|
|
114
134
|
ruby
|
115
135
|
|
116
136
|
DEPENDENCIES
|
137
|
+
activesupport (>= 4)
|
117
138
|
benchmark-ips
|
118
139
|
bundler
|
119
140
|
concurrent-ruby (~> 1.0, >= 1.0.5)
|
data/LICENSE.txt
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.3.0
|
data/lib/prefab/client.rb
CHANGED
@@ -22,6 +22,8 @@ module Prefab
|
|
22
22
|
|
23
23
|
if @options.local_only?
|
24
24
|
LOG.debug 'Prefab Running in Local Mode'
|
25
|
+
elsif @options.datafile?
|
26
|
+
LOG.debug 'Prefab Running in DataFile Mode'
|
25
27
|
else
|
26
28
|
@api_key = @options.api_key
|
27
29
|
raise Prefab::Errors::InvalidApiKeyError, @api_key if @api_key.nil? || @api_key.empty? || api_key.count('-') < 1
|
@@ -96,6 +98,8 @@ module Prefab
|
|
96
98
|
ActiveJob::Base.logger = log if defined?(ActiveJob)
|
97
99
|
ActiveRecord::Base.logger = log
|
98
100
|
ActiveStorage.logger = log if defined?(ActiveStorage)
|
101
|
+
|
102
|
+
LogSubscribers::ActionControllerSubscriber.attach_to :action_controller unless @options.disable_action_controller_logging
|
99
103
|
end
|
100
104
|
|
101
105
|
def on_update(&block)
|
data/lib/prefab/config_client.rb
CHANGED
@@ -31,6 +31,8 @@ module Prefab
|
|
31
31
|
|
32
32
|
if @options.local_only?
|
33
33
|
finish_init!(:local_only, nil)
|
34
|
+
elsif @options.datafile?
|
35
|
+
load_json_file(@options.datafile)
|
34
36
|
else
|
35
37
|
load_checkpoint
|
36
38
|
start_checkpointing_thread
|
@@ -141,8 +143,16 @@ module Prefab
|
|
141
143
|
LOG.info "Checkpoint #{source} failed to load. Response #{resp.status}"
|
142
144
|
false
|
143
145
|
end
|
146
|
+
rescue Faraday::ConnectionFailed => e
|
147
|
+
if @initialization_lock.write_locked?
|
148
|
+
LOG.warn "Connection Fail loading #{source} checkpoint."
|
149
|
+
else
|
150
|
+
LOG.debug "Connection Fail loading #{source} checkpoint."
|
151
|
+
end
|
152
|
+
false
|
144
153
|
rescue StandardError => e
|
145
154
|
LOG.warn "Unexpected #{source} problem loading checkpoint #{e} #{conn}"
|
155
|
+
LOG.debug e.backtrace
|
146
156
|
false
|
147
157
|
end
|
148
158
|
|
@@ -156,7 +166,7 @@ module Prefab
|
|
156
166
|
[
|
157
167
|
context.type,
|
158
168
|
context.values.keys.map do |k|
|
159
|
-
[k, Prefab::ConfigValueUnwrapper.new(context.values[k]).unwrap]
|
169
|
+
[k, Prefab::ConfigValueUnwrapper.new(context.values[k], @config_resolver).unwrap]
|
160
170
|
end.to_h
|
161
171
|
]
|
162
172
|
end.to_h
|
@@ -210,12 +220,21 @@ module Prefab
|
|
210
220
|
if hours_old > STALE_CACHE_WARN_HOURS
|
211
221
|
LOG.info "Stale Cache Load: #{hours_old} hours old"
|
212
222
|
end
|
223
|
+
true
|
213
224
|
end
|
214
225
|
rescue => e
|
215
226
|
LOG.debug "Failed to read cached configs at #{cache_path}. #{e}"
|
216
227
|
false
|
217
228
|
end
|
218
229
|
|
230
|
+
def load_json_file(file)
|
231
|
+
File.open(file) do |f|
|
232
|
+
f.flock(File::LOCK_SH)
|
233
|
+
configs = PrefabProto::Configs.decode_json(f.read)
|
234
|
+
load_configs(configs, :datafile)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
219
238
|
# A thread that checks for a checkpoint
|
220
239
|
def start_checkpointing_thread
|
221
240
|
Thread.new do
|
data/lib/prefab/config_loader.rb
CHANGED
@@ -54,6 +54,7 @@ module Prefab
|
|
54
54
|
private
|
55
55
|
|
56
56
|
def load_classpath_config
|
57
|
+
return {} if @prefab_options.datafile?
|
57
58
|
classpath_dir = @prefab_options.prefab_config_classpath_dir
|
58
59
|
rtn = load_glob(File.join(classpath_dir, '.prefab.default.config.yaml'))
|
59
60
|
@prefab_options.prefab_envs.each do |env|
|
@@ -63,6 +64,7 @@ module Prefab
|
|
63
64
|
end
|
64
65
|
|
65
66
|
def load_local_overrides
|
67
|
+
return {} if @prefab_options.datafile?
|
66
68
|
override_dir = @prefab_options.prefab_config_override_dir
|
67
69
|
rtn = load_glob(File.join(override_dir, '.prefab.default.config.yaml'))
|
68
70
|
@prefab_options.prefab_envs.each do |env|
|
@@ -3,37 +3,115 @@
|
|
3
3
|
module Prefab
|
4
4
|
class ConfigValueUnwrapper
|
5
5
|
LOG = Prefab::InternalLogger.new(ConfigValueUnwrapper)
|
6
|
-
|
6
|
+
CONFIDENTIAL_PREFIX = "*****"
|
7
|
+
attr_reader :weighted_value_index
|
7
8
|
|
8
|
-
def initialize(
|
9
|
-
@
|
9
|
+
def initialize(config_value, resolver, weighted_value_index = nil)
|
10
|
+
@config_value = config_value
|
11
|
+
@resolver = resolver
|
10
12
|
@weighted_value_index = weighted_value_index
|
11
13
|
end
|
12
14
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
when :string_list
|
18
|
-
value.string_list.values
|
15
|
+
def reportable_wrapped_value
|
16
|
+
if @config_value.confidential
|
17
|
+
# Unique hash for differentiation
|
18
|
+
Prefab::ConfigValueWrapper.wrap("#{CONFIDENTIAL_PREFIX}#{Digest::MD5.hexdigest(unwrap)[0,5]}")
|
19
19
|
else
|
20
|
-
|
21
|
-
|
20
|
+
@config_value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def reportable_value
|
25
|
+
Prefab::ConfigValueUnwrapper.new(reportable_wrapped_value, @resolver, @weighted_value_index).unwrap
|
26
|
+
end
|
27
|
+
|
28
|
+
def raw_config_value
|
29
|
+
@config_value
|
30
|
+
end
|
31
|
+
|
32
|
+
# this will return the actual value of confidential, use reportable_value unless you need it
|
33
|
+
def unwrap
|
34
|
+
raw = case @config_value.type
|
35
|
+
when :int, :string, :double, :bool, :log_level
|
36
|
+
@config_value.public_send(@config_value.type)
|
37
|
+
when :string_list
|
38
|
+
@config_value.string_list.values
|
39
|
+
else
|
40
|
+
LOG.error "Unknown type: #{@config_value.type}"
|
41
|
+
raise "Unknown type: #{@config_value.type}"
|
42
|
+
end
|
43
|
+
if @config_value.has_decrypt_with?
|
44
|
+
decryption_key = @resolver.get(@config_value.decrypt_with)&.unwrapped_value
|
45
|
+
if decryption_key.nil?
|
46
|
+
LOG.warn "No value for decryption key #{@config_value.decrypt_with} found."
|
47
|
+
return ""
|
48
|
+
else
|
49
|
+
unencrypted = Prefab::Encryption.new(decryption_key).decrypt(raw)
|
50
|
+
return unencrypted
|
51
|
+
end
|
22
52
|
end
|
53
|
+
|
54
|
+
raw
|
55
|
+
|
23
56
|
end
|
24
57
|
|
25
|
-
def self.deepest_value(config_value,
|
58
|
+
def self.deepest_value(config_value, config, context, resolver)
|
26
59
|
if config_value&.type == :weighted_values
|
27
60
|
value, index = Prefab::WeightedValueResolver.new(
|
28
61
|
config_value.weighted_values.weighted_values,
|
29
|
-
|
62
|
+
config.key,
|
30
63
|
context.get(config_value.weighted_values.hash_by_property_name)
|
31
64
|
).resolve
|
32
65
|
|
33
|
-
new(deepest_value(value.value,
|
66
|
+
new(deepest_value(value.value, config, context, resolver).raw_config_value, resolver, index)
|
67
|
+
|
68
|
+
elsif config_value&.type == :provided
|
69
|
+
if :ENV_VAR == config_value.provided.source
|
70
|
+
raw = ENV[config_value.provided.lookup]
|
71
|
+
if raw.nil?
|
72
|
+
LOG.warn "ENV Variable #{config_value.provided.lookup} not found. Using empty string."
|
73
|
+
new(Prefab::ConfigValueWrapper.wrap(""), resolver)
|
74
|
+
else
|
75
|
+
coerced = coerce_into_type(raw, config, config_value.provided.lookup)
|
76
|
+
new(Prefab::ConfigValueWrapper.wrap(coerced, confidential: config_value.confidential), resolver)
|
77
|
+
end
|
78
|
+
else
|
79
|
+
raise "Unknown Provided Source #{config_value.provided.source}"
|
80
|
+
end
|
81
|
+
else
|
82
|
+
new(config_value, resolver)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Don't allow env vars to resolve to a value_type other than the config's value_type
|
87
|
+
def self.coerce_into_type(value_string, config, env_var_name)
|
88
|
+
case config.value_type
|
89
|
+
when :INT then Integer(value_string)
|
90
|
+
when :DOUBLE then Float(value_string)
|
91
|
+
when :STRING then String(value_string)
|
92
|
+
when :STRING_LIST then
|
93
|
+
maybe_string_list = YAML.load(value_string)
|
94
|
+
case maybe_string_list
|
95
|
+
when Array
|
96
|
+
maybe_string_list
|
97
|
+
else
|
98
|
+
raise raise Prefab::Errors::EnvVarParseError.new(value_string, config, env_var_name)
|
99
|
+
end
|
100
|
+
when :BOOL then
|
101
|
+
maybe_bool = YAML.load(value_string)
|
102
|
+
case maybe_bool
|
103
|
+
when TrueClass,FalseClass
|
104
|
+
maybe_bool
|
105
|
+
else
|
106
|
+
raise Prefab::Errors::EnvVarParseError.new(value_string, config, env_var_name)
|
107
|
+
end
|
108
|
+
when :NOT_SET_VALUE_TYPE
|
109
|
+
YAML.load(value_string)
|
34
110
|
else
|
35
|
-
new(
|
111
|
+
raise Prefab::Errors::EnvVarParseError.new(value_string, config, env_var_name)
|
36
112
|
end
|
113
|
+
rescue ArgumentError
|
114
|
+
raise Prefab::Errors::EnvVarParseError.new(value_string, config, env_var_name)
|
37
115
|
end
|
38
116
|
end
|
39
117
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
module Prefab
|
2
2
|
class ConfigValueWrapper
|
3
|
-
def self.wrap(value)
|
3
|
+
def self.wrap(value, confidential: nil)
|
4
4
|
case value
|
5
5
|
when Integer
|
6
|
-
PrefabProto::ConfigValue.new(int: value)
|
6
|
+
PrefabProto::ConfigValue.new(int: value, confidential: confidential)
|
7
7
|
when Float
|
8
|
-
PrefabProto::ConfigValue.new(double: value)
|
8
|
+
PrefabProto::ConfigValue.new(double: value, confidential: confidential)
|
9
9
|
when TrueClass, FalseClass
|
10
|
-
PrefabProto::ConfigValue.new(bool: value)
|
10
|
+
PrefabProto::ConfigValue.new(bool: value, confidential: confidential)
|
11
11
|
when Array
|
12
|
-
PrefabProto::ConfigValue.new(string_list: PrefabProto::StringList.new(values: value.map(&:to_s)))
|
12
|
+
PrefabProto::ConfigValue.new(string_list: PrefabProto::StringList.new(values: value.map(&:to_s)), confidential: confidential)
|
13
13
|
else
|
14
|
-
PrefabProto::ConfigValue.new(string: value.to_s)
|
14
|
+
PrefabProto::ConfigValue.new(string: value.to_s, confidential: confidential)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -22,7 +22,7 @@ module Prefab
|
|
22
22
|
def evaluate(properties)
|
23
23
|
rtn = evaluate_for_env(@project_env_id, properties) ||
|
24
24
|
evaluate_for_env(0, properties)
|
25
|
-
LOG.debug "Eval Key #{@config.key} Result #{rtn&.
|
25
|
+
LOG.debug "Eval Key #{@config.key} Result #{rtn&.reportable_value} with #{properties.to_h}" unless @config.config_type == :LOG_LEVEL
|
26
26
|
rtn
|
27
27
|
end
|
28
28
|
|
@@ -93,7 +93,8 @@ module Prefab
|
|
93
93
|
value: conditional_value.value,
|
94
94
|
value_index: value_index,
|
95
95
|
config_row_index: index,
|
96
|
-
context: properties
|
96
|
+
context: properties,
|
97
|
+
resolver: @resolver
|
97
98
|
)
|
98
99
|
end
|
99
100
|
end
|
@@ -111,7 +112,7 @@ module Prefab
|
|
111
112
|
|
112
113
|
def matches?(criterion, value, properties)
|
113
114
|
criterion_value_or_values = Prefab::ConfigValueUnwrapper.deepest_value(criterion.value_to_match, @config.key,
|
114
|
-
properties).unwrap
|
115
|
+
properties, @resolver).unwrap
|
115
116
|
|
116
117
|
case criterion_value_or_values
|
117
118
|
when Google::Protobuf::RepeatedField
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Prefab
|
4
|
+
class Encryption
|
5
|
+
CIPHER_TYPE = "aes-256-gcm" # 32/12
|
6
|
+
SEPARATOR = "--"
|
7
|
+
|
8
|
+
# Hexadecimal format ensures that generated keys are representable with
|
9
|
+
# plain text
|
10
|
+
#
|
11
|
+
# To convert back to the original string with the desired length:
|
12
|
+
# [ value ].pack("H*")
|
13
|
+
def self.generate_new_hex_key
|
14
|
+
generate_random_key.unpack("H*")[0]
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(key_string_hex)
|
18
|
+
@key = [key_string_hex].pack("H*")
|
19
|
+
end
|
20
|
+
|
21
|
+
def encrypt(clear_text)
|
22
|
+
cipher = OpenSSL::Cipher.new(CIPHER_TYPE)
|
23
|
+
cipher.encrypt
|
24
|
+
iv = cipher.random_iv
|
25
|
+
|
26
|
+
# load them into the cipher
|
27
|
+
cipher.key = @key
|
28
|
+
cipher.iv = iv
|
29
|
+
cipher.auth_data = ""
|
30
|
+
|
31
|
+
# encrypt the message
|
32
|
+
encrypted = cipher.update(clear_text)
|
33
|
+
encrypted << cipher.final
|
34
|
+
tag = cipher.auth_tag
|
35
|
+
|
36
|
+
# pack and join
|
37
|
+
[encrypted, iv, tag].map { |p| p.unpack("H*")[0] }.join(SEPARATOR)
|
38
|
+
end
|
39
|
+
|
40
|
+
def decrypt(encrypted_string)
|
41
|
+
unpacked_parts = encrypted_string.split(SEPARATOR).map { |p| [p].pack("H*") }
|
42
|
+
|
43
|
+
cipher = OpenSSL::Cipher.new(CIPHER_TYPE)
|
44
|
+
cipher.decrypt
|
45
|
+
cipher.key = @key
|
46
|
+
cipher.iv = unpacked_parts[1]
|
47
|
+
cipher.auth_tag = unpacked_parts[2]
|
48
|
+
|
49
|
+
# and decrypt it
|
50
|
+
decrypted = cipher.update(unpacked_parts[0])
|
51
|
+
decrypted << cipher.final
|
52
|
+
decrypted
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def self.generate_random_key
|
58
|
+
SecureRandom.random_bytes(key_length)
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.key_length
|
62
|
+
OpenSSL::Cipher.new(CIPHER_TYPE).key_len
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Prefab
|
4
|
+
module Errors
|
5
|
+
class EnvVarParseError < Prefab::Error
|
6
|
+
def initialize(env_var, config, env_var_name)
|
7
|
+
super("Evaluating #{config.key} couldn't coerce #{env_var_name} of #{env_var} to #{config.value_type}")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/prefab/evaluation.rb
CHANGED
@@ -5,18 +5,23 @@ module Prefab
|
|
5
5
|
class Evaluation
|
6
6
|
attr_reader :value
|
7
7
|
|
8
|
-
def initialize(config:, value:, value_index:, config_row_index:, context:)
|
8
|
+
def initialize(config:, value:, value_index:, config_row_index:, context:, resolver:)
|
9
9
|
@config = config
|
10
10
|
@value = value
|
11
11
|
@value_index = value_index
|
12
12
|
@config_row_index = config_row_index
|
13
13
|
@context = context
|
14
|
+
@resolver = resolver
|
14
15
|
end
|
15
16
|
|
16
17
|
def unwrapped_value
|
17
18
|
deepest_value.unwrap
|
18
19
|
end
|
19
20
|
|
21
|
+
def reportable_value
|
22
|
+
deepest_value.reportable_value
|
23
|
+
end
|
24
|
+
|
20
25
|
def report_and_return(evaluation_summary_aggregator)
|
21
26
|
report(evaluation_summary_aggregator)
|
22
27
|
|
@@ -27,7 +32,6 @@ module Prefab
|
|
27
32
|
|
28
33
|
def report(evaluation_summary_aggregator)
|
29
34
|
return if @config.config_type == :LOG_LEVEL
|
30
|
-
|
31
35
|
evaluation_summary_aggregator&.record(
|
32
36
|
config_key: @config.key,
|
33
37
|
config_type: @config.config_type,
|
@@ -35,14 +39,14 @@ module Prefab
|
|
35
39
|
config_id: @config.id,
|
36
40
|
config_row_index: @config_row_index,
|
37
41
|
conditional_value_index: @value_index,
|
38
|
-
selected_value: deepest_value.
|
42
|
+
selected_value: deepest_value.reportable_wrapped_value,
|
39
43
|
weighted_value_index: deepest_value.weighted_value_index,
|
40
44
|
selected_index: nil # TODO
|
41
45
|
})
|
42
46
|
end
|
43
47
|
|
44
48
|
def deepest_value
|
45
|
-
@deepest_value ||= Prefab::ConfigValueUnwrapper.deepest_value(@value, @config
|
49
|
+
@deepest_value ||= Prefab::ConfigValueUnwrapper.deepest_value(@value, @config, @context, @resolver)
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
@@ -1,33 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Prefab
|
4
|
-
class InternalLogger <
|
4
|
+
class InternalLogger < StaticLogger
|
5
|
+
INTERNAL_PREFIX = 'cloud.prefab.client'
|
6
|
+
|
5
7
|
def initialize(path)
|
6
8
|
if path.is_a?(Class)
|
7
|
-
|
9
|
+
path_string = path.name.split('::').last.downcase
|
8
10
|
else
|
9
|
-
|
11
|
+
path_string = path
|
10
12
|
end
|
11
|
-
|
12
|
-
|
13
|
-
def debug msg
|
14
|
-
Prefab::LoggerClient.instance.log_internal ::Logger::DEBUG, msg, @path
|
15
|
-
end
|
16
|
-
|
17
|
-
def info msg
|
18
|
-
Prefab::LoggerClient.instance.log_internal ::Logger::INFO, msg, @path
|
19
|
-
end
|
20
|
-
|
21
|
-
def warn msg
|
22
|
-
Prefab::LoggerClient.instance.log_internal ::Logger::WARN, msg, @path
|
23
|
-
end
|
24
|
-
|
25
|
-
def error msg
|
26
|
-
Prefab::LoggerClient.instance.log_internal ::Logger::ERROR, msg, @path
|
27
|
-
end
|
28
|
-
|
29
|
-
def fatal msg
|
30
|
-
Prefab::LoggerClient.instance.log_internal ::Logger::FATAL, msg, @path
|
13
|
+
super("#{INTERNAL_PREFIX}.#{path_string}")
|
31
14
|
end
|
32
15
|
end
|
33
16
|
end
|
@@ -7,6 +7,10 @@ module Prefab
|
|
7
7
|
if value.instance_of?(Hash)
|
8
8
|
if value['feature_flag']
|
9
9
|
config[key] = feature_flag_config(file, key, value)
|
10
|
+
elsif value['type'] == 'provided'
|
11
|
+
config[key] = provided_config(file, key, value)
|
12
|
+
elsif value['decrypt_with'] || value['confidential']
|
13
|
+
config[key] = complex_string(file, key, value)
|
10
14
|
else
|
11
15
|
value.each do |nest_key, nest_value|
|
12
16
|
nested_key = "#{key}.#{nest_key}"
|
@@ -23,8 +27,8 @@ module Prefab
|
|
23
27
|
key: key,
|
24
28
|
rows: [
|
25
29
|
PrefabProto::ConfigRow.new(values: [
|
26
|
-
|
27
|
-
|
30
|
+
PrefabProto::ConditionalValue.new(value: value_from(key, value))
|
31
|
+
])
|
28
32
|
]
|
29
33
|
)
|
30
34
|
}
|
@@ -79,6 +83,58 @@ module Prefab
|
|
79
83
|
}
|
80
84
|
end
|
81
85
|
|
86
|
+
def provided_config(file, key, value_hash)
|
87
|
+
value = PrefabProto::ConfigValue.new(provided: PrefabProto::Provided.new(
|
88
|
+
source: :ENV_VAR,
|
89
|
+
lookup: value_hash["lookup"],
|
90
|
+
),
|
91
|
+
confidential: value_hash["confidential"],
|
92
|
+
)
|
93
|
+
|
94
|
+
row = PrefabProto::ConfigRow.new(
|
95
|
+
values: [
|
96
|
+
PrefabProto::ConditionalValue.new(
|
97
|
+
value: value
|
98
|
+
)
|
99
|
+
]
|
100
|
+
)
|
101
|
+
|
102
|
+
{
|
103
|
+
source: file,
|
104
|
+
match: value.provided.lookup,
|
105
|
+
config: PrefabProto::Config.new(
|
106
|
+
config_type: :CONFIG,
|
107
|
+
key: key,
|
108
|
+
rows: [row]
|
109
|
+
)
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
def complex_string(file, key, value_hash)
|
114
|
+
value = PrefabProto::ConfigValue.new(
|
115
|
+
string: value_hash["value"],
|
116
|
+
confidential: value_hash["confidential"],
|
117
|
+
decrypt_with: value_hash["decrypt_with"],
|
118
|
+
)
|
119
|
+
|
120
|
+
row = PrefabProto::ConfigRow.new(
|
121
|
+
values: [
|
122
|
+
PrefabProto::ConditionalValue.new(
|
123
|
+
value: value
|
124
|
+
)
|
125
|
+
]
|
126
|
+
)
|
127
|
+
|
128
|
+
{
|
129
|
+
source: file,
|
130
|
+
config: PrefabProto::Config.new(
|
131
|
+
config_type: :CONFIG,
|
132
|
+
key: key,
|
133
|
+
rows: [row]
|
134
|
+
)
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
82
138
|
def parse_criterion(criterion)
|
83
139
|
PrefabProto::Criterion.new(operator: criterion['operator'],
|
84
140
|
property_name: criterion['property'],
|