ff-ruby-server-sdk 1.0.6 → 1.1.1
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 +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
|
|