prefab-cloud-ruby 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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'],
|