unleash 0.1.6 → 3.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 99d6b4f0efb9cf53a2f86930e2e26594d2de8c72aee68ee20e1374f6ac1826cc
4
- data.tar.gz: ac9905dee38bb80b0f94595907e74856be1842149bfbfc54ee0ff8390bd9dcda
3
+ metadata.gz: 70d64956aa703576336ee95064ef909655a664159b571be5417ebf073f0de224
4
+ data.tar.gz: 36cff93bb8203971721e3eeace2d24d9db4075926d2c2609e5c6acd01179c2fd
5
5
  SHA512:
6
- metadata.gz: b0ce261b43d7325d3aac1ed62a60d7fdec14543d92e5da63f3e1e699ab6a79d5a529c9080f51dfaf641ce72e18518a61ac1f14395987b3e515503865ed1ef5bf
7
- data.tar.gz: 3b4cf6548b3c19be261f3794370a80868f0c07cec0988423aa1388f5a75349f880ef1b824652a2bd582814149c985f82e7e1b01772470e41fd119406272f3b42
6
+ metadata.gz: 7b8c366cc799582a672646c796858381189e9286149929bb5e37afc2404cce9ac140b0c004ba8a3a7f774b0d83c705c2c714932656121054ab920f58afa55b34
7
+ data.tar.gz: 6a4f8aa92aa80e17eb2477cc77a534dcbe44b2b63b3ff7c05867392252e808ec76750094adaf476c739c2641db1ef0f8a7c3729001fd7efe8ab209a255ebe968
data/.gitignore CHANGED
@@ -7,9 +7,10 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ /vendor
10
11
 
11
12
  # rspec failure tracking
12
13
  .rspec_status
13
14
 
14
15
  # Clone of the client-specification
15
- /client-specification/
16
+ /client-specification/
data/.rubocop.yml CHANGED
@@ -1,16 +1,70 @@
1
+ # inherit_from: .rubocop_todo.yml
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 2.5
5
+
1
6
  Naming/PredicateName:
2
- NameWhitelist:
7
+ AllowedMethods:
3
8
  - is_enabled?
4
9
 
5
- Metrics/LineLength:
10
+ Metrics/ClassLength:
6
11
  Max: 120
12
+ Layout/LineLength:
13
+ Max: 140
14
+ Metrics/MethodLength:
15
+ Max: 20
16
+ Metrics/BlockLength:
17
+ Max: 100
18
+ Exclude:
19
+ - 'spec/unleash/client_spec.rb'
20
+ - 'spec/unleash/feature_toggle_spec.rb'
7
21
 
8
- Style/RedundantSelf:
9
- Enabled: false
10
- Style/PreferredHashMethods:
22
+ Metrics/AbcSize:
23
+ Max: 25
24
+ Metrics/CyclomaticComplexity:
25
+ Max: 9
26
+ Metrics/PerceivedComplexity:
27
+ Max: 9
28
+
29
+ Style/Documentation:
11
30
  Enabled: false
31
+
12
32
  Style/StringLiterals:
13
33
  Enabled: false
34
+ Style/RedundantSelf:
35
+ Enabled: false
36
+
37
+ Style/SymbolArray:
38
+ EnforcedStyle: brackets
39
+ Style/WordArray:
40
+ EnforcedStyle: brackets
41
+ Style/PreferredHashMethods:
42
+ EnforcedStyle: verbose
43
+ Style/FrozenStringLiteralComment:
44
+ EnforcedStyle: never
45
+ Style/GuardClause:
46
+ MinBodyLength: 8
47
+
48
+ Style/HashEachMethods:
49
+ Enabled: true
50
+ Style/HashTransformKeys:
51
+ Enabled: true
52
+ Style/HashTransformValues:
53
+ Enabled: true
54
+
55
+ Style/IfInsideElse:
56
+ Exclude:
57
+ - 'bin/unleash-client'
58
+
59
+ Style/Next:
60
+ Exclude:
61
+ - 'lib/unleash/scheduled_executor.rb'
62
+
63
+ Layout/MultilineMethodCallIndentation:
64
+ EnforcedStyle: indented
14
65
 
15
66
  Layout/SpaceBeforeBlockBraces:
16
- Enabled: false
67
+ EnforcedStyle: no_space
68
+ Exclude:
69
+ - 'unleash-client.gemspec'
70
+ - 'spec/**/*.rb'
data/.travis.yml CHANGED
@@ -1,12 +1,15 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.3
5
- - 2.4
6
- - 2.5
7
- - 2.6
8
- - jruby
4
+ - jruby
5
+ - 3.0
6
+ - 2.7
7
+ - 2.6
8
+ - 2.5
9
9
  before_install:
10
- - gem install bundler -v 2.0.2
11
- # install client spec from official repository:
12
- - git clone --depth 5 https://github.com/Unleash/client-specification.git client-specification
10
+ - gem install bundler -v 2.1.4
11
+ - git clone --depth 5 --branch v3.3.0 https://github.com/Unleash/client-specification.git client-specification
12
+
13
+ notifications:
14
+ slack:
15
+ secure: x593zOjdl2yVB8uP54v8CmuCOat8GFHnK99NPvPHKvif5U7PGe0YOgYh4DC1+Jc9vfjn1ke+0++m+Gif4quowpeOaA/t45xpB494lyziXsBulYml245jRp9yzoUmIIt7KxHhv4rlo3Q1ztMJgh6a5yDCornKHW2bKTkLsvqVTwxBRatLOrt6K9O8FivO/NaqgcoXl7Rw0fOx/bsZtx2IAFueTCH19NoqW1mk9KFEZ96YqJSvuqmfDC0AO7siq03WKlB++nPlKe1QcrlPalCrcsSzrYNhYJ3akBTt/ZbE1v6YJv2L+zUqRnAPTY2H+qp8WejFQtdhIjfeJ/SWox0iWv/Wy/mTFfj+EhFO9Aq+xhMjJ1OOLtNAPoYJyatEVgJkILb6M26igTFcuI60xBbGNmh5ZYeyRdn5/xFb7G2zyJ2Swc3PvN1uLzMHfTF0R7WzGq4CRNGIOjrHTGncyB3IGAONOdJdM3iT9XKY6cdlRK0VkQjEsEMe0eNv2fxxLVSGna4sdJoTND6LhJ6qCfuS9DEDXwoRdLxAXxefycCh9VNp7gloMJx8IbHYxOW0BFZqc3hxNU9X2SwOj6j72DZMrdYDg2aPAW69HG0iMontQ37Di87JEW2F2Cpgb49+4twByrQNIx+st+DGNce1vpc0DN+KuJVdIcmha654lT7Ffe8=
data/README.md CHANGED
@@ -10,10 +10,10 @@ Leverage the [Unleash Server](https://github.com/Unleash/unleash) for powerful f
10
10
 
11
11
  ## Supported Ruby Interpreters
12
12
 
13
- * MRI 2.3
14
- * MRI 2.4
15
- * MRI 2.5
13
+ * MRI 3.0
14
+ * MRI 2.7
16
15
  * MRI 2.6
16
+ * MRI 2.5
17
17
  * jruby
18
18
 
19
19
  ## Installation
@@ -21,7 +21,7 @@ Leverage the [Unleash Server](https://github.com/Unleash/unleash) for powerful f
21
21
  Add this line to your application's Gemfile:
22
22
 
23
23
  ```ruby
24
- gem 'unleash', '~> 0.1.6'
24
+ gem 'unleash', '~> 3.2.3'
25
25
  ```
26
26
 
27
27
  And then execute:
@@ -66,7 +66,7 @@ Argument | Description | Required? | Type | Default Value|
66
66
  `disable_metrics` | Disables sending metrics to Unleash server. | N | Boolean | `false` |
67
67
  `custom_http_headers` | Custom headers to send to Unleash. | N | Hash | {} |
68
68
  `timeout` | How long to wait for the connection to be established or wait in reading state (open_timeout/read_timeout) | N | Integer | 30 |
69
- `retry_limit` | How many consecutive failures in connecting to the Unleash server are allowed before giving up. | N | Integer | 1 |
69
+ `retry_limit` | How many consecutive failures in connecting to the Unleash server are allowed before giving up. Use `Float::INFINITY` if you would like it to never give up. | N | Numeric | 5 |
70
70
  `backup_file` | Filename to store the last known state from the Unleash server. Best to not change this from the default. | N | String | `Dir.tmpdir + "/unleash-#{app_name}-repo.json` |
71
71
  `logger` | Specify a custom `Logger` class to handle logs for the Unleash client. | N | Class | `Logger.new(STDOUT)` |
72
72
  `log_level` | Change the log level for the `Logger` class. Constant from `Logger::Severity`. | N | Constant | `Logger::ERROR` |
@@ -242,8 +242,6 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
242
242
 
243
243
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
244
244
 
245
- See [TODO.md](TODO.md) for known limitations, and feature roadmap.
246
-
247
245
 
248
246
  ## Contributing
249
247
 
data/Rakefile CHANGED
@@ -3,4 +3,4 @@ require "rspec/core/rake_task"
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
data/bin/unleash-client CHANGED
@@ -12,7 +12,7 @@ options = {
12
12
  url: 'http://localhost:4242',
13
13
  demo: false,
14
14
  disable_metrics: true,
15
- sleep: 0.1,
15
+ sleep: 0.1
16
16
  }
17
17
 
18
18
  OptionParser.new do |opts|
@@ -57,17 +57,26 @@ raise 'feature_name is required. see --help for usage.' unless feature_name
57
57
 
58
58
  options[:verbose] = false if options[:quiet]
59
59
 
60
+ log_level = \
61
+ if options[:quiet]
62
+ Logger::ERROR
63
+ elsif options[:verbose]
64
+ Logger::DEBUG
65
+ else
66
+ Logger::WARN
67
+ end
68
+
60
69
  @unleash = Unleash::Client.new(
61
70
  url: options[:url],
62
71
  app_name: 'unleash-client-ruby-cli',
63
72
  disable_metrics: options[:metrics],
64
- log_level: log_level = options[:quiet] ? Logger::ERROR : (options[:verbose] ? Logger::DEBUG : Logger::WARN),
73
+ log_level: log_level
65
74
  )
66
75
 
67
- context_params = ARGV.map{ |e| e.split("=") }.map{ |k,v| [k.to_sym, v] }.to_h
68
- context_properties = context_params.reject{ |k,v| [:user_id, :session_id, :remote_address].include? k }
69
- context_params.select!{ |k,v| [:user_id, :session_id, :remote_address].include? k }
70
- context_params.merge!( properties: context_properties ) unless context_properties.nil?
76
+ context_params = ARGV.map{ |e| e.split("=") }.map{ |k, v| [k.to_sym, v] }.to_h
77
+ context_properties = context_params.reject{ |k, _v| [:user_id, :session_id, :remote_address].include? k }
78
+ context_params.select!{ |k, _v| [:user_id, :session_id, :remote_address].include? k }
79
+ context_params.merge!(properties: context_properties) unless context_properties.nil?
71
80
  unleash_context = Unleash::Context.new(context_params)
72
81
 
73
82
  if options[:verbose]
@@ -80,26 +89,21 @@ if options[:verbose]
80
89
  puts ""
81
90
  end
82
91
 
83
-
84
-
85
92
  if options[:demo]
86
93
  loop do
87
94
  enabled = @unleash.is_enabled?(feature_name, unleash_context)
88
95
  print enabled ? '.' : '|'
89
96
  sleep options[:sleep]
90
97
  end
98
+ elsif options[:variant]
99
+ variant = @unleash.get_variant(feature_name, unleash_context)
100
+ puts " For feature \'#{feature_name}\' got variant \'#{variant}\'"
91
101
  else
92
- if options[:variant]
93
- variant = @unleash.get_variant(feature_name, unleash_context)
94
- puts " For feature \'#{feature_name}\' got variant \'#{variant}\'"
102
+ if @unleash.is_enabled?(feature_name, unleash_context)
103
+ puts " \'#{feature_name}\' is enabled according to unleash"
95
104
  else
96
- if @unleash.is_enabled?(feature_name, unleash_context)
97
- puts " \'#{feature_name}\' is enabled according to unleash"
98
- else
99
- puts " \'#{feature_name}\' is disabled according to unleash"
100
- end
105
+ puts " \'#{feature_name}\' is disabled according to unleash"
101
106
  end
102
107
  end
103
108
 
104
-
105
109
  @unleash.shutdown
data/examples/simple.rb CHANGED
@@ -16,12 +16,14 @@ puts ">> START simple.rb"
16
16
 
17
17
  # or:
18
18
 
19
- @unleash = Unleash::Client.new( url: 'http://unleash.herokuapp.com/api', app_name: 'simple-test',
19
+ @unleash = Unleash::Client.new(
20
+ url: 'https://app.unleash-hosted.com/demo/api',
21
+ app_name: 'simple-test',
20
22
  instance_id: 'local-test-cli',
21
23
  refresh_interval: 2,
22
24
  metrics_interval: 2,
23
25
  retry_limit: 2,
24
- log_level: Logger::DEBUG,
26
+ custom_http_headers: {'Authorization': '943ca9171e2c884c545c5d82417a655fb77cec970cc3b78a8ff87f4406b495d0'},
25
27
  )
26
28
 
27
29
  # feature_name = "AwesomeFeature"
@@ -55,5 +57,3 @@ puts "> shutting down client..."
55
57
  @unleash.shutdown
56
58
 
57
59
  puts ">> END simple.rb"
58
-
59
-
@@ -1,16 +1,29 @@
1
1
  module Unleash
2
2
  class ActivationStrategy
3
- attr_accessor :name, :params
3
+ attr_accessor :name, :params, :constraints
4
4
 
5
- def initialize(name, params)
5
+ def initialize(name, params, constraints = [])
6
6
  self.name = name
7
7
 
8
8
  if params.is_a?(Hash)
9
9
  self.params = params
10
+ elsif params.nil?
11
+ self.params = {}
10
12
  else
11
- Unleash.logger.warn "Invalid params provided for ActivationStrategy #{params}"
13
+ Unleash.logger.warn "Invalid params provided for ActivationStrategy (params:#{params})"
12
14
  self.params = {}
13
15
  end
16
+
17
+ if constraints.is_a?(Array) && constraints.each{ |c| c.is_a?(Constraint) }
18
+ self.constraints = constraints
19
+ else
20
+ Unleash.logger.warn "Invalid constraints provided for ActivationStrategy (contraints: #{constraints})"
21
+ self.constraints = []
22
+ end
23
+ end
24
+
25
+ def matches_context?(context)
26
+ self.constraints.any?{ |c| c.matches_context? context }
14
27
  end
15
28
  end
16
29
  end
@@ -3,11 +3,11 @@ require 'unleash/toggle_fetcher'
3
3
  require 'unleash/metrics_reporter'
4
4
  require 'unleash/scheduled_executor'
5
5
  require 'unleash/feature_toggle'
6
+ require 'unleash/util/http'
6
7
  require 'logger'
7
8
  require 'time'
8
9
 
9
10
  module Unleash
10
-
11
11
  class Client
12
12
  attr_accessor :fetcher_scheduled_executor, :metrics_scheduled_executor
13
13
 
@@ -18,71 +18,56 @@ module Unleash
18
18
  Unleash.logger = Unleash.configuration.logger.clone
19
19
  Unleash.logger.level = Unleash.configuration.log_level
20
20
 
21
- unless Unleash.configuration.disable_client
22
- Unleash.toggle_fetcher = Unleash::ToggleFetcher.new
23
-
24
- register
25
-
26
- self.fetcher_scheduled_executor = Unleash::ScheduledExecutor.new('ToggleFetcher', Unleash.configuration.refresh_interval)
27
- self.fetcher_scheduled_executor.run do
28
- Unleash.toggle_fetcher.fetch
29
- end
30
-
31
- unless Unleash.configuration.disable_metrics
32
- Unleash.toggle_metrics = Unleash::Metrics.new
33
- Unleash.reporter = Unleash::MetricsReporter.new
34
- self.metrics_scheduled_executor = Unleash::ScheduledExecutor.new('MetricsReporter', Unleash.configuration.metrics_interval)
35
- self.metrics_scheduled_executor.run do
36
- Unleash.reporter.send
37
- end
38
- end
39
- else
21
+ if Unleash.configuration.disable_client
40
22
  Unleash.logger.warn "Unleash::Client is disabled! Will only return default results!"
23
+ return
41
24
  end
25
+
26
+ register
27
+ start_toggle_fetcher
28
+ start_metrics unless Unleash.configuration.disable_metrics
42
29
  end
43
30
 
44
31
  def is_enabled?(feature, context = nil, default_value = false)
45
- Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} with context #{context}"
32
+ Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} with context #{context}"
46
33
 
47
- if Unleash.configuration.disable_client
48
- Unleash.logger.warn "unleash_client is disabled! Always returning #{default_value} for feature #{feature}!"
49
- return default_value
50
- end
34
+ if Unleash.configuration.disable_client
35
+ Unleash.logger.warn "unleash_client is disabled! Always returning #{default_value} for feature #{feature}!"
36
+ return default_value
37
+ end
51
38
 
52
- toggle_as_hash = Unleash.toggles.select{ |toggle| toggle['name'] == feature }.first if Unleash.toggles
39
+ toggle_as_hash = Unleash&.toggles&.select{ |toggle| toggle['name'] == feature }&.first
53
40
 
54
- if toggle_as_hash.nil?
55
- Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} not found"
56
- return default_value
57
- end
41
+ if toggle_as_hash.nil?
42
+ Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} not found"
43
+ return default_value
44
+ end
58
45
 
59
- toggle = Unleash::FeatureToggle.new(toggle_as_hash)
60
- toggle_result = toggle.is_enabled?(context, default_value)
46
+ toggle = Unleash::FeatureToggle.new(toggle_as_hash)
61
47
 
62
- return toggle_result
48
+ toggle.is_enabled?(context, default_value)
63
49
  end
64
50
 
65
51
  # enabled? is a more ruby idiomatic method name than is_enabled?
66
- alias_method :enabled?, :is_enabled?
52
+ alias enabled? is_enabled?
67
53
 
68
54
  # execute a code block (passed as a parameter), if is_enabled? is true.
69
55
  def if_enabled(feature, context = nil, default_value = false, &blk)
70
- yield if is_enabled?(feature, context, default_value)
56
+ yield(blk) if is_enabled?(feature, context, default_value)
71
57
  end
72
58
 
73
-
74
- def get_variant(feature, context = nil, fallback_variant = false)
59
+ def get_variant(feature, context = nil, fallback_variant = nil)
75
60
  Unleash.logger.debug "Unleash::Client.get_variant for feature: #{feature} with context #{context}"
76
61
 
77
62
  if Unleash.configuration.disable_client
78
- Unleash.logger.warn "unleash_client is disabled! Always returning #{default_variant} for feature #{feature}!"
63
+ Unleash.logger.debug "unleash_client is disabled! Always returning #{default_variant} for feature #{feature}!"
79
64
  return fallback_variant || Unleash::FeatureToggle.disabled_variant
80
65
  end
81
66
 
82
- toggle_as_hash = Unleash.toggles.select{ |toggle| toggle['name'] == feature }.first if Unleash.toggles
67
+ toggle_as_hash = Unleash&.toggles&.select{ |toggle| toggle['name'] == feature }&.first
83
68
 
84
69
  if toggle_as_hash.nil?
85
- Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} not found"
70
+ Unleash.logger.debug "Unleash::Client.get_variant feature: #{feature} not found"
86
71
  return fallback_variant || Unleash::FeatureToggle.disabled_variant
87
72
  end
88
73
 
@@ -96,7 +81,7 @@ module Unleash
96
81
 
97
82
  # TODO: Add to README: name, payload, enabled (bool)
98
83
 
99
- return variant
84
+ variant
100
85
  end
101
86
 
102
87
  # safe shutdown: also flush metrics to server and toggles to disk
@@ -117,9 +102,10 @@ module Unleash
117
102
  end
118
103
 
119
104
  private
105
+
120
106
  def info
121
- return {
122
- 'appName': Unleash.configuration.app_name,
107
+ {
108
+ 'appName': Unleash.configuration.app_name,
123
109
  'instanceId': Unleash.configuration.instance_id,
124
110
  'sdkVersion': "unleash-client-ruby:" + Unleash::VERSION,
125
111
  'strategies': Unleash::STRATEGIES.keys,
@@ -128,28 +114,42 @@ module Unleash
128
114
  }
129
115
  end
130
116
 
131
- def register
132
- Unleash.logger.debug "register()"
133
-
134
- uri = URI(Unleash.configuration.client_register_url)
135
- http = Net::HTTP.new(uri.host, uri.port)
136
- http.use_ssl = true if uri.scheme == 'https'
137
- http.open_timeout = Unleash.configuration.timeout # in seconds
138
- http.read_timeout = Unleash.configuration.timeout # in seconds
117
+ def start_toggle_fetcher
118
+ Unleash.toggle_fetcher = Unleash::ToggleFetcher.new
119
+ self.fetcher_scheduled_executor = Unleash::ScheduledExecutor.new(
120
+ 'ToggleFetcher',
121
+ Unleash.configuration.refresh_interval,
122
+ Unleash.configuration.retry_limit
123
+ )
124
+ self.fetcher_scheduled_executor.run do
125
+ Unleash.toggle_fetcher.fetch
126
+ end
127
+ end
139
128
 
140
- headers = (Unleash.configuration.get_http_headers || {}).dup
141
- headers['Content-Type'] = 'application/json'
129
+ def start_metrics
130
+ Unleash.toggle_metrics = Unleash::Metrics.new
131
+ Unleash.reporter = Unleash::MetricsReporter.new
132
+ self.metrics_scheduled_executor = Unleash::ScheduledExecutor.new(
133
+ 'MetricsReporter',
134
+ Unleash.configuration.metrics_interval,
135
+ Unleash.configuration.retry_limit
136
+ )
137
+ self.metrics_scheduled_executor.run do
138
+ Unleash.reporter.send
139
+ end
140
+ end
142
141
 
143
- request = Net::HTTP::Post.new(uri.request_uri, headers)
144
- request.body = info.to_json
142
+ def register
143
+ Unleash.logger.debug "register()"
145
144
 
146
145
  # Send the request, if possible
147
146
  begin
148
- response = http.request(request)
149
- rescue Exception => e
147
+ response = Unleash::Util::Http.post(Unleash.configuration.client_register_url, info.to_json)
148
+ rescue StandardError => e
150
149
  Unleash.logger.error "unable to register client with unleash server due to exception #{e.class}:'#{e}'."
151
150
  Unleash.logger.error "stacktrace: #{e.backtrace}"
152
151
  end
152
+ Unleash.logger.debug "client registered: #{response}"
153
153
  end
154
154
  end
155
155
  end