ff-ruby-server-sdk 1.0.6 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile +8 -2
- data/README.md +3 -2
- data/buildInContainer.sh +15 -0
- data/example/getting_started/getting_started.rb +2 -1
- data/example/tls_example/tls_example.rb +67 -0
- data/lib/ff/ruby/server/sdk/api/auth_service.rb +48 -40
- data/lib/ff/ruby/server/sdk/api/cf_client.rb +1 -1
- data/lib/ff/ruby/server/sdk/api/client_callback.rb +14 -9
- data/lib/ff/ruby/server/sdk/api/config.rb +4 -4
- data/lib/ff/ruby/server/sdk/api/config_builder.rb +5 -0
- data/lib/ff/ruby/server/sdk/api/evaluator.rb +30 -37
- data/lib/ff/ruby/server/sdk/api/inner_client.rb +19 -23
- data/lib/ff/ruby/server/sdk/api/inner_client_flag_evaluate_callback.rb +1 -1
- data/lib/ff/ruby/server/sdk/api/inner_client_updater.rb +1 -1
- data/lib/ff/ruby/server/sdk/api/metrics_event.rb +18 -6
- data/lib/ff/ruby/server/sdk/api/metrics_processor.rb +100 -173
- data/lib/ff/ruby/server/sdk/api/polling_processor.rb +10 -11
- data/lib/ff/ruby/server/sdk/api/update_processor.rb +1 -3
- data/lib/ff/ruby/server/sdk/common/sdk_codes.rb +102 -0
- data/lib/ff/ruby/server/sdk/connector/events.rb +60 -64
- data/lib/ff/ruby/server/sdk/connector/harness_connector.rb +50 -26
- data/lib/ff/ruby/server/sdk/version.rb +1 -1
- data/scripts/openapi.sh +2 -5
- data/scripts/sdk_specs.sh +1 -1
- metadata +18 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab04a74816651d46324faf27b7aac91d4d6ef5941c01eee61a674fb36cf54bd1
|
4
|
+
data.tar.gz: f52922e05d01426ba12f63e07b5f6e25fbfe477f83c44d13cba72038b35932dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d4038c666ffe22ce8170e17fd8bec516068c0e4fbb5034b706e5efafd3e612d06a4b9cd2b03e63d70bbb9b7b13f8e26360f5f5b26684bcb40904228afa449d7
|
7
|
+
data.tar.gz: 9164338df82c7c97cd2620d302e6d7b8f43299b2a5580988288ddf4ad6bf5b3469519d8ece420333b2c28ea908de27076d5e43905ebe8045b3c722f4909dbc69
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
# [1.1.0]
|
2
|
+
|
3
|
+
- [FFM-7285] - Remove Metrics queue and implement Map for better memory usage
|
4
|
+
- [FFM-7325] - Improve authentication retry logic
|
5
|
+
- [FFM-6926] - Add basic Ruby on Rails example
|
6
|
+
- [FFM-6965] - Fixes analytics_enabled(false) which didn't fully turn off metrics
|
7
|
+
- [FFM-7005] - Add TLS support custom CAs and remove sse-client
|
8
|
+
- [FFM-7292] - Add HTTP headers for diagnostics
|
9
|
+
|
1
10
|
# [1.0.6]
|
2
11
|
|
3
12
|
- [FFM-3715] - Updates open api dependency issue
|
data/Gemfile
CHANGED
@@ -16,10 +16,16 @@ gem "moneta"
|
|
16
16
|
|
17
17
|
# SSE support:
|
18
18
|
gem "rest-client"
|
19
|
-
gem "sse-client"
|
20
19
|
|
21
20
|
# Concurrency support:
|
22
|
-
gem "concurrent-ruby", require: "concurrent"
|
21
|
+
gem "concurrent-ruby", "1.1.10", require: "concurrent"
|
23
22
|
|
24
23
|
# Evaluator dependencies:
|
25
24
|
gem "murmurhash3"
|
25
|
+
|
26
|
+
gem "typhoeus"
|
27
|
+
|
28
|
+
group :test do
|
29
|
+
gem 'simplecov', '~> 0.21.2'
|
30
|
+
end
|
31
|
+
|
data/README.md
CHANGED
@@ -81,7 +81,7 @@ client.close
|
|
81
81
|
|
82
82
|
```bash
|
83
83
|
# Install the deps
|
84
|
-
gem install ff-ruby-server-sdk typhoeus
|
84
|
+
gem install ff-ruby-server-sdk typhoeus
|
85
85
|
|
86
86
|
# Set your API Key
|
87
87
|
export FF_API_KEY=<your key here>
|
@@ -96,7 +96,7 @@ use docker to quickly get started
|
|
96
96
|
|
97
97
|
```bash
|
98
98
|
# Install the package
|
99
|
-
docker run -v $(pwd):/app -w /app -e FF_API_KEY=$FF_API_KEY ruby:2.7-buster gem install --install-dir ./gems ff-ruby-server-sdk typhoeus
|
99
|
+
docker run -v $(pwd):/app -w /app -e FF_API_KEY=$FF_API_KEY ruby:2.7-buster gem install --install-dir ./gems ff-ruby-server-sdk typhoeus
|
100
100
|
|
101
101
|
# Run the script
|
102
102
|
docker run -v $(pwd):/app -w /app -e FF_API_KEY=$FF_API_KEY -e GEM_HOME=/app/gems ruby:2.7-buster ruby ./example/getting_started/getting_started.rb
|
@@ -108,6 +108,7 @@ Further examples and config options are in the further reading section:
|
|
108
108
|
|
109
109
|
[Further Reading](docs/further_reading.md)
|
110
110
|
|
111
|
+
[Ruby on Rails example](ruby_on_rails_example/README.md)
|
111
112
|
|
112
113
|
-------------------------
|
113
114
|
[Harness](https://www.harness.io/) is a feature management platform that helps teams to build better software and to
|
data/buildInContainer.sh
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
ruby -v
|
4
|
+
apt-get update
|
5
|
+
apt-get install -y npm
|
6
|
+
apt-get install -y maven
|
7
|
+
apt-get install -y jq
|
8
|
+
mvn --version
|
9
|
+
npm install @openapitools/openapi-generator-cli -g
|
10
|
+
npm install @openapitools/openapi-generator-cli -D
|
11
|
+
gem install minitest-junit
|
12
|
+
sh scripts/install.sh
|
13
|
+
gem env
|
14
|
+
gem install ff-ruby-server-sdk typhoeus
|
15
|
+
ruby test/ff/ruby/server/sdk/sdk_test.rb --junit
|
@@ -8,6 +8,7 @@ require "securerandom"
|
|
8
8
|
|
9
9
|
$stdout.sync = true
|
10
10
|
logger = Logger.new $stdout
|
11
|
+
logger.level = Logger::DEBUG
|
11
12
|
|
12
13
|
# API Key
|
13
14
|
apiKey = ENV['FF_API_KEY'] || 'changeme'
|
@@ -32,7 +33,7 @@ target = Target.new("RubySDK", identifier="rubysdk", attributes={"location": "em
|
|
32
33
|
# Loop forever reporting the state of the flag
|
33
34
|
loop do
|
34
35
|
result = client.bool_variation(flagName, target, false)
|
35
|
-
logger.info "Flag
|
36
|
+
logger.info "Flag #{flagName} is set to: #{result}"
|
36
37
|
sleep 10
|
37
38
|
end
|
38
39
|
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'ff/ruby/server/sdk/api/config'
|
2
|
+
require 'ff/ruby/server/sdk/dto/target'
|
3
|
+
require 'ff/ruby/server/sdk/api/cf_client'
|
4
|
+
require 'ff/ruby/server/sdk/api/config_builder'
|
5
|
+
|
6
|
+
require "logger"
|
7
|
+
require "securerandom"
|
8
|
+
|
9
|
+
$stdout.sync = true
|
10
|
+
logger = Logger.new $stdout
|
11
|
+
|
12
|
+
# API Key
|
13
|
+
apiKey = ENV['FF_API_KEY'] || 'changeme'
|
14
|
+
|
15
|
+
# Flag Name
|
16
|
+
flagName = ENV['FF_FLAG_NAME'] || 'harnessappdemodarkmode'
|
17
|
+
|
18
|
+
logger.info "Harness Ruby SDK TLS example"
|
19
|
+
|
20
|
+
=begin
|
21
|
+
For ff servers with a custom or private CAs, you can use 'tls_ca_cert' to pass in the CA bundle in ASCII PEM format.
|
22
|
+
You should also include any intermediate CAs so the full trust chain can be resolved. Typhoeus HTTP client uses libcurl
|
23
|
+
underneath, when developing you should enable debugging(true) to get more detailed error diagnostics logged, which
|
24
|
+
aren't reported through OpenAPI. Common errors include:
|
25
|
+
|
26
|
+
SSL peer certificate or SSH remote key was not OK - you have an invalid or missing CA for the server you're trying
|
27
|
+
to connect to. It can also mean the server hostname and request
|
28
|
+
hostname don't match.
|
29
|
+
SSL: no alternative certificate subject name - The hostname or IP used in your SDK URLs do not match the SANs
|
30
|
+
matches target host name ‘<host>' configured in the cert sent by the web server. You should either
|
31
|
+
fix your URLs or ensure the SANs in the X.509 cert are configured
|
32
|
+
correctly.
|
33
|
+
|
34
|
+
The example below assumes you have an ff-server (or proxy) configured with TLS for a server hosted on
|
35
|
+
'ffserver:8000' where the web server's cert has a SANs with DNS entry 'ffserver'. CA.crt tells the SDK you trust this
|
36
|
+
server.
|
37
|
+
|
38
|
+
Typhoeus/libcurl by default has its default CA bundle stored at /etc/ssl/cert.pem. You can append your CA here if
|
39
|
+
you choose not to use 'tls_ca_cert'.
|
40
|
+
|
41
|
+
=end
|
42
|
+
|
43
|
+
|
44
|
+
client = CfClient.instance
|
45
|
+
client.init(apiKey, ConfigBuilder.new.logger(logger)
|
46
|
+
.event_url("https://ffserver:8001/api/1.0")
|
47
|
+
.config_url("https://ffserver:8000/api/1.0")
|
48
|
+
.tls_ca_cert("/path/to/CA.crt")
|
49
|
+
.debugging(true)
|
50
|
+
.build)
|
51
|
+
|
52
|
+
client.wait_for_initialization
|
53
|
+
|
54
|
+
|
55
|
+
# Create a target (different targets can get different results based on rules. This include a custom attribute 'location')
|
56
|
+
target = Target.new("RubySDK", identifier="rubysdk", attributes={"location": "emea"})
|
57
|
+
|
58
|
+
# Loop forever reporting the state of the flag
|
59
|
+
loop do
|
60
|
+
result = client.bool_variation(flagName, target, false)
|
61
|
+
logger.info "#{flagName} flag variation: #{result}"
|
62
|
+
sleep 10
|
63
|
+
end
|
64
|
+
|
65
|
+
client.close
|
66
|
+
|
67
|
+
|
@@ -2,56 +2,47 @@ require_relative "../common/closeable"
|
|
2
2
|
|
3
3
|
class AuthService < Closeable
|
4
4
|
|
5
|
-
def initialize(connector
|
5
|
+
def initialize(connector, callback, logger, retry_delay_ms = 6000)
|
6
6
|
|
7
7
|
unless connector.kind_of?(Connector)
|
8
|
-
|
9
8
|
raise "The 'connector' parameter must be of '" + Connector.to_s + "' data type"
|
10
9
|
end
|
11
10
|
|
12
11
|
unless callback.kind_of?(ClientCallback)
|
13
|
-
|
14
12
|
raise "The 'callback' parameter must be of '" + ClientCallback.to_s + "' data type"
|
15
13
|
end
|
16
14
|
|
15
|
+
@logger = logger
|
17
16
|
@callback = callback
|
18
17
|
@connector = connector
|
19
|
-
@
|
20
|
-
|
21
|
-
if logger != nil
|
22
|
-
|
23
|
-
@logger = logger
|
24
|
-
else
|
25
|
-
|
26
|
-
@logger = Logger.new(STDOUT)
|
27
|
-
end
|
18
|
+
@retry_delay_ms = retry_delay_ms
|
19
|
+
@authenticated = false
|
28
20
|
end
|
29
21
|
|
30
22
|
def start_async
|
31
|
-
|
32
23
|
@logger.debug "Async starting: " + self.to_s
|
33
24
|
|
34
|
-
@
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@logger.debug "Async started: " + self.to_s
|
39
|
-
|
40
|
-
while @ready do
|
41
|
-
|
42
|
-
@logger.debug "Async auth iteration"
|
43
|
-
|
44
|
-
if @connector.authenticate
|
25
|
+
@thread = Thread.new :report_on_exception => true do
|
26
|
+
attempt = 1
|
27
|
+
until @authenticated do
|
28
|
+
http_code = @connector.authenticate
|
45
29
|
|
30
|
+
if http_code == 200
|
31
|
+
@authenticated = true
|
46
32
|
@callback.on_auth_success
|
47
33
|
stop_async
|
48
|
-
|
34
|
+
elsif should_retry_http_code http_code
|
35
|
+
delay_ms = @retry_delay_ms * [10, attempt].min
|
36
|
+
@logger.warn "Got HTTP code #{http_code} while authenticating on attempt #{attempt}, will retry in #{delay_ms} ms"
|
37
|
+
sleep(delay_ms/1000)
|
38
|
+
attempt += 1
|
39
|
+
SdkCodes::warn_auth_retying @logger, attempt
|
49
40
|
else
|
50
|
-
|
51
|
-
@
|
41
|
+
@logger.warn "Auth Service got HTTP code #{http_code} while authenticating, will not attempt to reconnect"
|
42
|
+
@callback.on_auth_failed
|
43
|
+
stop_async
|
44
|
+
next
|
52
45
|
end
|
53
|
-
|
54
|
-
sleep(@poll_interval_in_sec)
|
55
46
|
end
|
56
47
|
end
|
57
48
|
|
@@ -59,33 +50,50 @@ class AuthService < Closeable
|
|
59
50
|
end
|
60
51
|
|
61
52
|
def close
|
62
|
-
|
63
53
|
stop_async
|
64
54
|
end
|
65
55
|
|
66
|
-
|
56
|
+
protected
|
67
57
|
|
68
|
-
|
58
|
+
def on_auth_success
|
69
59
|
|
60
|
+
if @callback != nil
|
70
61
|
unless @callback.kind_of?(ClientCallback)
|
71
|
-
|
72
62
|
raise "Expected '" + ClientCallback.to_s + "' data type for the callback"
|
73
63
|
end
|
74
|
-
|
75
64
|
@callback.on_auth_success
|
76
65
|
end
|
77
66
|
end
|
78
67
|
|
79
|
-
protected
|
80
|
-
|
81
68
|
def stop_async
|
82
|
-
|
83
|
-
@ready = false
|
84
|
-
|
85
69
|
if @thread != nil
|
86
|
-
|
70
|
+
@logger.debug "Stopping Auth service, status=#{@thread.status}"
|
87
71
|
@thread.exit
|
88
72
|
@thread = nil
|
73
|
+
@logger.debug "Stopping Auth service done"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def is_authenticated
|
80
|
+
@authenticated
|
81
|
+
end
|
82
|
+
|
83
|
+
def should_retry_http_code(code)
|
84
|
+
# 408 request timeout
|
85
|
+
# 425 too early
|
86
|
+
# 429 too many requests
|
87
|
+
# 500 internal server error
|
88
|
+
# 502 bad gateway
|
89
|
+
# 503 service unavailable
|
90
|
+
# 504 gateway timeout
|
91
|
+
# -1 OpenAPI error (timeout etc)
|
92
|
+
case code
|
93
|
+
when 408,425,429,500,502,503,504,-1
|
94
|
+
return true
|
95
|
+
else
|
96
|
+
return false
|
89
97
|
end
|
90
98
|
end
|
91
99
|
end
|
@@ -2,44 +2,49 @@ require_relative "../common/closeable"
|
|
2
2
|
|
3
3
|
class ClientCallback < Closeable
|
4
4
|
|
5
|
+
TBI = RuntimeError.new("To be implemented")
|
6
|
+
|
5
7
|
def initialize
|
6
8
|
super
|
7
|
-
|
8
|
-
@tbi = "To be implemented"
|
9
9
|
end
|
10
10
|
|
11
11
|
def on_auth_success
|
12
12
|
|
13
|
-
raise
|
13
|
+
raise TBI
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_auth_failed
|
17
|
+
|
18
|
+
raise TBI
|
14
19
|
end
|
15
20
|
|
16
21
|
def on_authorized
|
17
22
|
|
18
|
-
raise
|
23
|
+
raise TBI
|
19
24
|
end
|
20
25
|
|
21
26
|
def is_closing
|
22
27
|
|
23
|
-
raise
|
28
|
+
raise TBI
|
24
29
|
end
|
25
30
|
|
26
31
|
def on_processor_ready(processor)
|
27
32
|
|
28
|
-
raise
|
33
|
+
raise TBI
|
29
34
|
end
|
30
35
|
|
31
36
|
def on_update_processor_ready
|
32
37
|
|
33
|
-
raise
|
38
|
+
raise TBI
|
34
39
|
end
|
35
40
|
|
36
41
|
def on_metrics_processor_ready
|
37
42
|
|
38
|
-
raise
|
43
|
+
raise TBI
|
39
44
|
end
|
40
45
|
|
41
46
|
def update(message, manual)
|
42
47
|
|
43
|
-
raise
|
48
|
+
raise TBI
|
44
49
|
end
|
45
50
|
end
|
@@ -7,7 +7,7 @@ class Config
|
|
7
7
|
attr_accessor :config_url, :event_url, :stream_enabled, :poll_interval_in_seconds, :analytics_enabled,
|
8
8
|
:frequency, :buffer_size, :all_attributes_private, :private_attributes, :connection_timeout,
|
9
9
|
:read_timeout, :write_timeout, :debugging, :metrics_service_acceptable_duration, :cache, :store,
|
10
|
-
:logger
|
10
|
+
:logger, :ssl_ca_cert
|
11
11
|
|
12
12
|
# Static:
|
13
13
|
class << self
|
@@ -35,7 +35,7 @@ class Config
|
|
35
35
|
|
36
36
|
@frequency = @@min_frequency
|
37
37
|
|
38
|
-
@buffer_size =
|
38
|
+
@buffer_size = 2048
|
39
39
|
|
40
40
|
@all_attributes_private = false
|
41
41
|
|
@@ -82,7 +82,7 @@ class Config
|
|
82
82
|
|
83
83
|
def verify_ssl
|
84
84
|
|
85
|
-
|
85
|
+
true
|
86
86
|
end
|
87
87
|
|
88
88
|
def cert_file
|
@@ -97,7 +97,7 @@ class Config
|
|
97
97
|
|
98
98
|
def ssl_ca_cert
|
99
99
|
|
100
|
-
|
100
|
+
@ssl_ca_cert
|
101
101
|
end
|
102
102
|
|
103
103
|
def client_side_validation
|
@@ -3,6 +3,7 @@ require "murmurhash3"
|
|
3
3
|
|
4
4
|
require_relative "evaluation"
|
5
5
|
require_relative "../common/repository"
|
6
|
+
require_relative "../common/sdk_codes"
|
6
7
|
|
7
8
|
class Evaluator < Evaluation
|
8
9
|
|
@@ -33,6 +34,7 @@ class Evaluator < Evaluation
|
|
33
34
|
return variation.value == "true"
|
34
35
|
end
|
35
36
|
|
37
|
+
SdkCodes::warn_default_variation_served @logger, identifier, target, default_value.to_s
|
36
38
|
default_value
|
37
39
|
end
|
38
40
|
|
@@ -45,6 +47,7 @@ class Evaluator < Evaluation
|
|
45
47
|
return variation.value
|
46
48
|
end
|
47
49
|
|
50
|
+
SdkCodes::warn_default_variation_served @logger, identifier, target, default_value.to_s
|
48
51
|
default_value
|
49
52
|
end
|
50
53
|
|
@@ -57,6 +60,7 @@ class Evaluator < Evaluation
|
|
57
60
|
return variation.value.to_i
|
58
61
|
end
|
59
62
|
|
63
|
+
SdkCodes::warn_default_variation_served @logger, identifier, target, default_value.to_s
|
60
64
|
default_value
|
61
65
|
end
|
62
66
|
|
@@ -68,6 +72,7 @@ class Evaluator < Evaluation
|
|
68
72
|
return variation.value.to_f
|
69
73
|
end
|
70
74
|
|
75
|
+
SdkCodes::warn_default_variation_served @logger, identifier, target, default_value.to_s
|
71
76
|
default_value
|
72
77
|
end
|
73
78
|
|
@@ -80,6 +85,7 @@ class Evaluator < Evaluation
|
|
80
85
|
return JSON.parse(variation.value)
|
81
86
|
end
|
82
87
|
|
88
|
+
SdkCodes::warn_default_variation_served @logger, identifier, target, default_value.to_s
|
83
89
|
default_value
|
84
90
|
end
|
85
91
|
|
@@ -219,13 +225,13 @@ class Evaluator < Evaluation
|
|
219
225
|
|
220
226
|
clauses.each do |clause|
|
221
227
|
|
222
|
-
|
228
|
+
if evaluate_clause(clause, target)
|
223
229
|
|
224
|
-
return
|
230
|
+
return true
|
225
231
|
end
|
226
232
|
end
|
227
233
|
|
228
|
-
|
234
|
+
false
|
229
235
|
end
|
230
236
|
|
231
237
|
def evaluate_clause(clause, target)
|
@@ -295,7 +301,7 @@ class Evaluator < Evaluation
|
|
295
301
|
|
296
302
|
if operator == "in"
|
297
303
|
|
298
|
-
return
|
304
|
+
return clause.values.include?(object)
|
299
305
|
end
|
300
306
|
|
301
307
|
if operator == "segmentMatch"
|
@@ -460,60 +466,47 @@ class Evaluator < Evaluation
|
|
460
466
|
prerequisites = parent_feature_config.prerequisites
|
461
467
|
|
462
468
|
if prerequisites != nil && !prerequisites.empty?
|
469
|
+
@logger.debug "Checking prerequisite #{prerequisites.to_s} of flag #{parent_feature_config.feature}"
|
463
470
|
|
464
|
-
|
465
|
-
|
466
|
-
prerequisites.each do |pqs|
|
467
|
-
|
468
|
-
pre_req_feature = pqs.feature
|
469
|
-
|
470
|
-
pre_req_feature_config = @repository.get_flag(pre_req_feature)
|
471
|
-
|
472
|
-
if pre_req_feature_config == nil
|
473
|
-
|
474
|
-
@logger.debug "Could not retrieve the pre requisite details of feature flag: " + pre_req_feature.to_s
|
471
|
+
prerequisites.each do |pre_req|
|
472
|
+
pre_req_flag = @repository.get_flag(pre_req.feature)
|
475
473
|
|
474
|
+
if pre_req_flag == nil
|
475
|
+
@logger.debug "Could not retrieve the pre requisite details of feature flag: #{pre_req.feature}"
|
476
476
|
return true
|
477
477
|
end
|
478
478
|
|
479
|
-
|
480
|
-
|
481
|
-
if pre_req_evaluated_variation == nil
|
482
|
-
|
483
|
-
@logger.debug "Could not evaluate the prerequisite details of feature flag: " + pre_req_feature.to_s
|
479
|
+
evaluated_pre_req = evaluate_flag(pre_req_flag, target)
|
484
480
|
|
481
|
+
if evaluated_pre_req == nil
|
482
|
+
@logger.debug "Could not evaluate the prerequisite details of feature flag: #{pre_req.feature}"
|
485
483
|
return true
|
486
484
|
end
|
487
485
|
|
488
|
-
@logger.debug "Pre requisite flag " + pre_req_feature_config.feature + " has variation " +
|
489
|
-
pre_req_evaluated_variation.to_s + " for target " + target.to_s
|
490
|
-
|
491
|
-
valid_pre_req_variations = pqs.variations
|
492
|
-
|
493
|
-
@logger.debug "Pre requisite flag " + pre_req_feature_config.to_s + " should have the variations " +
|
494
|
-
valid_pre_req_variations.to_s
|
495
|
-
|
496
486
|
none_match = true
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
if element.include?(pre_req_evaluated_variation.identifier)
|
501
|
-
|
487
|
+
pre_req.variations.each do |next_variation|
|
488
|
+
if next_variation.include?(evaluated_pre_req.identifier)
|
502
489
|
none_match = false
|
503
490
|
break
|
504
491
|
end
|
505
492
|
end
|
506
493
|
|
507
494
|
if none_match
|
508
|
-
|
495
|
+
@logger.debug "Prerequisite flag #{pre_req_flag.feature} has no matching variations for flag #{parent_feature_config.feature}"
|
509
496
|
return false
|
510
497
|
else
|
511
|
-
|
512
|
-
|
498
|
+
unless check_pre_requisite(pre_req_flag, target)
|
499
|
+
@logger.debug "Prerequisite flag #{pre_req_flag.feature} is switched off for flag #{parent_feature_config.feature}"
|
500
|
+
return false
|
501
|
+
end
|
513
502
|
end
|
514
|
-
end
|
503
|
+
end # prerequisites.each
|
504
|
+
|
505
|
+
@logger.debug "All prerequisite flags are switched on for flag #{parent_feature_config.feature}"
|
506
|
+
return true
|
515
507
|
end
|
516
508
|
|
509
|
+
@logger.debug "No prerequisite flags present for flag #{parent_feature_config.feature}, skipped"
|
517
510
|
true
|
518
511
|
end
|
519
512
|
|