legion-settings 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: '09fab9f1b8877a7e4edd48838b81985de665106e'
4
+ data.tar.gz: 5f7fd30a767e066a87987ad0fdd04a3b605b1f87
5
+ SHA512:
6
+ metadata.gz: 1ccfdc0cee0c2983d381dca59260089b42141e600d97afaeaeaca94d093df0b35d88875526a5ed7528ec4416b29ae15ce753275e2574628f63b4c338ab285574
7
+ data.tar.gz: 45ed2014eb19bae521caad7cfd4cbe5baab5620d6adfb3138cc70a582f96e246ff9d1b872f67cb729d8b28cbc9f7cd7cbcc049e8c94c774fb5ca0c57043e57d1
@@ -0,0 +1,167 @@
1
+ version: 2 # use CircleCI 2.0
2
+ jobs:
3
+ "rubocop":
4
+ docker:
5
+ - image: circleci/ruby:2.4-node
6
+ steps:
7
+ - checkout
8
+ - run: gem install rubocop
9
+ - run:
10
+ name: Run Rubocop
11
+ command: rubocop
12
+ - store_test_results:
13
+ path: test_results
14
+ "ruby-2.0":
15
+ docker:
16
+ - image: circleci/ruby:2.0
17
+ steps:
18
+ - checkout
19
+ - run:
20
+ name: Bundle Install
21
+ command: bundle install
22
+ - run:
23
+ name: Run RSpec
24
+ command: bundle exec rspec --format progress --format RspecJunitFormatter -o test-results/rspec/results.xml
25
+ when: always
26
+ - store_test_results:
27
+ path: test-results
28
+ "ruby-2.1":
29
+ docker:
30
+ - image: circleci/ruby:2.1
31
+ steps:
32
+ - checkout
33
+ - run:
34
+ name: Bundle Install
35
+ command: bundle install
36
+ - run:
37
+ name: Run RSpec
38
+ command: bundle exec rspec --format progress --format RspecJunitFormatter -o test-results/rspec/results.xml
39
+ when: always
40
+ - store_test_results:
41
+ path: test-results
42
+ "ruby-2.2":
43
+ docker:
44
+ - image: circleci/ruby:2.2
45
+ steps:
46
+ - checkout
47
+ - run:
48
+ name: Bundle Install
49
+ command: bundle install
50
+ - run:
51
+ name: Run RSpec
52
+ command: bundle exec rspec --format progress --format RspecJunitFormatter -o test-results/rspec/results.xml
53
+ when: always
54
+ - store_test_results:
55
+ path: test-results
56
+
57
+ "ruby-2.3":
58
+ docker:
59
+ - image: circleci/ruby:2.3
60
+ steps:
61
+ - checkout
62
+ - run:
63
+ name: Bundle Install
64
+ command: bundle install
65
+ - run:
66
+ name: Run RSpec
67
+ command: bundle exec rspec --format progress --format RspecJunitFormatter -o test-results/rspec/results.xml
68
+ when: always
69
+ - store_test_results:
70
+ path: test-results
71
+
72
+ "ruby-2.4":
73
+ docker:
74
+ - image: circleci/ruby:2.4-node
75
+ steps:
76
+ - checkout
77
+ - run:
78
+ name: Bundle Install
79
+ command: bundle install
80
+ - run:
81
+ name: Run RSpec
82
+ command: bundle exec rspec --format progress --format RspecJunitFormatter -o test-results/rspec/results.xml
83
+ when: always
84
+ - store_test_results:
85
+ path: test-results
86
+ "ruby-2.5":
87
+ docker:
88
+ - image: circleci/ruby:2.5-node
89
+ steps:
90
+ - checkout
91
+ - run:
92
+ name: Bundle Install
93
+ command: bundle install
94
+ - run:
95
+ name: Run RSpec
96
+ command: bundle exec rspec --format progress --format RspecJunitFormatter -o test-results/rspec/results.xml
97
+ when: always
98
+ - store_test_results:
99
+ path: test-results
100
+ "ruby-2.6":
101
+ docker:
102
+ - image: circleci/ruby:2.6-node
103
+ steps:
104
+ - checkout
105
+ - run:
106
+ name: Bundle Install
107
+ command: bundle install
108
+ - run:
109
+ name: Run RSpec
110
+ command: bundle exec rspec --format progress --format RspecJunitFormatter -o test-results/rspec/results.xml
111
+ when: always
112
+ - store_test_results:
113
+ path: test-results
114
+ "jruby-9.2":
115
+ docker:
116
+ - image: circleci/jruby:9.2
117
+ steps:
118
+ - checkout
119
+ - run:
120
+ name: Bundle Install
121
+ command: bundle install
122
+ - run:
123
+ name: Run RSpec
124
+ command: bundle exec rspec --format progress --format RspecJunitFormatter -o test-results/rspec/results.xml
125
+ when: always
126
+ - store_test_results:
127
+ path: test-results
128
+
129
+ workflows:
130
+ version: 2
131
+ cop_rake_deploy:
132
+ jobs:
133
+ - rubocop
134
+ # - ruby-2.2:
135
+ # requires:
136
+ # - ruby-2.4
137
+ # filters:
138
+ # branches:
139
+ # only: /\bdevelop\b|\bmaster\b/
140
+ - ruby-2.3:
141
+ requires:
142
+ - ruby-2.4
143
+ filters:
144
+ branches:
145
+ only: /\bdevelop\b|\bmaster\b/
146
+ - ruby-2.4:
147
+ requires:
148
+ - rubocop
149
+ - ruby-2.5:
150
+ requires:
151
+ - ruby-2.4
152
+ filters:
153
+ branches:
154
+ only: /\bdevelop\b|\bmaster\b/
155
+ - ruby-2.6:
156
+ requires:
157
+ - ruby-2.4
158
+ filters:
159
+ branches:
160
+ only: /\bdevelop\b|\bmaster\b/
161
+ # - jruby-9.2:
162
+ # requires:
163
+ # - ruby-2.2
164
+ # - ruby-2.3
165
+ # - ruby-2.4
166
+ # - ruby-2.5
167
+ # - ruby-2.6
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /rspec/
11
+ /test-results/
12
+
13
+ # rspec failure tracking
14
+ .rspec_status
15
+
data/.rubocop.yml ADDED
@@ -0,0 +1,25 @@
1
+ Metrics/LineLength:
2
+ Max: 120
3
+ Metrics/MethodLength:
4
+ Max: 30
5
+ Metrics/ClassLength:
6
+ Max: 1500
7
+ Metrics/BlockLength:
8
+ Max: 50
9
+ Layout/SpaceAroundEqualsInParameterDefault:
10
+ EnforcedStyle: space
11
+ Style/SymbolArray:
12
+ Enabled: true
13
+ Layout/AlignHash:
14
+ EnforcedHashRocketStyle: table
15
+ EnforcedColonStyle: table
16
+ Style/HashSyntax:
17
+ EnforcedStyle: ruby19_no_mixed_keys
18
+ Style/Documentation:
19
+ Enabled: false
20
+ AllCops:
21
+ TargetRubyVersion: 2.4
22
+ Style/FrozenStringLiteralComment:
23
+ Enabled: false
24
+ Naming/FileName:
25
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in legion-settings.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Esity
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # Legion::Settings
2
+
3
+ Legion::Settings is part of the Legion Framework
4
+
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'legion-settings'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install legion-settings
21
+
22
+ ## Usage
23
+
24
+ This library is utilized by Legion to load config files
25
+
26
+ ## Gem
27
+
28
+ This gem can be viewed and download from [RubyGems - Legion-Settings](https://rubygems.org/gems/legion-settings)
29
+
30
+ ## Development
31
+
32
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
33
+
34
+ To install this gem onto your local machine, run `bundle exec install`.
35
+
36
+ ## Contributing
37
+
38
+ Bug reports and pull requests are welcome on GitHub at https://bitbucket.org/legion-io/legion-settings/issues This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
39
+
40
+ ## License
41
+
42
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'legion/settings'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,39 @@
1
+ image: ruby:2.4.0
2
+
3
+ pipelines:
4
+ branches:
5
+ master:
6
+ - step:
7
+ caches:
8
+ - bundler
9
+ script:
10
+ - gem install bundle rubocop
11
+ - bundle install
12
+ - rubocop
13
+ - rake
14
+ - step:
15
+ name: Deploy to test gem server
16
+ deployment: test
17
+ script:
18
+ - gem install bundle geminabox
19
+ - bundle install
20
+ - gem build legion-settings.gemspec
21
+ - gem inabox legion-settings*.gem -g https://gems.whonodes.org/ -o
22
+ - step:
23
+ name: Deploy to RubyGems
24
+ deployment: production
25
+ trigger: manual
26
+ script:
27
+ - gem build legion-settings.gemspec
28
+ default:
29
+ - step:
30
+ caches:
31
+ - bundler
32
+ script:
33
+ - gem install bundle rubocop
34
+ - bundle install
35
+ - rubocop
36
+ - rake
37
+ definitions:
38
+ caches:
39
+ bundler: vendor/bundle
@@ -0,0 +1,34 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'legion/settings/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'legion-settings'
7
+ spec.version = Legion::Settings::VERSION
8
+ spec.authors = ['Esity']
9
+ spec.email = ['matthewdiverson@gmail.com']
10
+
11
+ spec.summary = 'Used to load the json settings files'
12
+ spec.description = "Based on Sensu's implementation of settings"
13
+ spec.homepage = 'https://bitbucket.org/whonodes/legion-settings'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = 'exe'
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1'
24
+ spec.add_development_dependency 'codecov', '~> 0'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'rspec', '~> 3.0'
27
+ spec.add_development_dependency 'rspec_junit_formatter', '~> 0'
28
+ if RUBY_ENGINE == 'jruby'
29
+ spec.add_dependency('legion-json-jruby', '~> 0.1')
30
+ else
31
+ spec.add_dependency('legion-json', '~> 0.1')
32
+ end
33
+ spec.add_dependency 'legion-logging', '~> 0.1'
34
+ end
@@ -0,0 +1,40 @@
1
+ require 'legion/json'
2
+ require 'legion/settings/version'
3
+ require 'legion/json/parse_error'
4
+ require 'legion/settings/loader'
5
+
6
+ module Legion
7
+ # Base Legion::Settings module
8
+ module Settings
9
+ # Base settings, needs to be refactored
10
+ class << self
11
+ attr_accessor :loader
12
+ def load(options = {})
13
+ @loader = Legion::Settings::Loader.new
14
+ @loader.load_env
15
+ @loader.load_file(options[:config_file]) if options[:config_file]
16
+ @loader.load_directory(options[:config_dir]) if options[:config_dir]
17
+ options[:config_dirs]&.each do |directory|
18
+ @loader.load_directory(directory)
19
+ end
20
+ @loader
21
+ end
22
+
23
+ def get(options = {})
24
+ @loader || @loader = load(options)
25
+ end
26
+
27
+ def [](key)
28
+ Legion::Logging.warn('Legion::Settings was not loading, auto loading now!') if @loader.nil?
29
+ @loader = load if @loader.nil?
30
+ @loader[key]
31
+ end
32
+
33
+ def set_prop(key, value)
34
+ Legion::Logging.warn('Legion::Settings was not loading, auto loading now!') if @loader.nil?
35
+ @loader = load if @loader.nil?
36
+ @loader[key] = value
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,5 @@
1
+ module Legion
2
+ module Settings
3
+ CATEGORIES = [:interations].freeze
4
+ end
5
+ end
@@ -0,0 +1,282 @@
1
+ module Legion
2
+ module Settings
3
+ # This is the main settings class, needs refactor
4
+ class Loader
5
+ # This is the standard error
6
+ class Error < RuntimeError; end
7
+
8
+ attr_reader :warnings
9
+ attr_reader :errors
10
+ attr_reader :loaded_files
11
+
12
+ def initialize
13
+ @warnings = []
14
+ @errors = []
15
+ @settings = default_settings
16
+ @indifferent_access = false
17
+ @loaded_files = []
18
+ self.class.create_category_methods
19
+ end
20
+
21
+ def client_defaults
22
+ {
23
+ name: system_hostname,
24
+ address: system_address
25
+ }
26
+ end
27
+
28
+ def default_settings
29
+ default = {
30
+ client: {},
31
+ legion: {
32
+ spawn: {
33
+ limit: 12
34
+ }
35
+ },
36
+ transport: {
37
+ rabbitmq: {
38
+ user: 'guest',
39
+ password: 'guest',
40
+ host: '127.0.0.1'
41
+ }
42
+ },
43
+ data: {
44
+ mysql: {
45
+ user: 'legion',
46
+ password: 'legion',
47
+ max_connections: 20,
48
+ database: 'legion',
49
+ host: '127.0.0.1',
50
+ debug: false
51
+ }
52
+ }
53
+ }
54
+ default[:client] = client_defaults if %w[client rspec].include?(legion_service_name)
55
+ default
56
+ end
57
+
58
+ def self.create_category_methods
59
+ # CATEGORIES.each do |category|
60
+ # define_method(category) do
61
+ # setting_category(category)
62
+ # end
63
+ # method_name = category.to_s.chop + "_exists?"
64
+ # define_method(method_name.to_sym) do |name|
65
+ # definition_exists?(category, name)
66
+ # end
67
+ # end
68
+ end
69
+
70
+ def to_hash
71
+ unless @indifferent_access
72
+ indifferent_access!
73
+ @hexdigest = nil
74
+ end
75
+ @settings
76
+ end
77
+
78
+ def [](key)
79
+ to_hash[key]
80
+ end
81
+
82
+ def hexdigest
83
+ if @hexdigest && @indifferent_access
84
+ @hexdigest
85
+ else
86
+ hash = case legion_service_name
87
+ when 'client', 'rspec'
88
+ to_hash
89
+ else
90
+ to_hash.reject do |key, _value|
91
+ key.to_s == 'client'
92
+ end
93
+ end
94
+ @hexdigest = Digest::SHA256.hexdigest(hash.to_s)
95
+ end
96
+ end
97
+
98
+ def load_env
99
+ load_api_env
100
+ end
101
+
102
+ def load_file(file)
103
+ Legion::Logging.debug("Trying to load file #{file}")
104
+ if File.file?(file) && File.readable?(file)
105
+ begin
106
+ contents = read_config_file(file)
107
+ config = contents.empty? ? {} : Legion::JSON.load(contents)
108
+ merged = deep_merge(@settings, config)
109
+ deep_diff(@settings, merged) unless @loaded_files.empty?
110
+ @settings = merged
111
+ # @indifferent_access = false
112
+ @loaded_files << file
113
+ rescue Legion::JSON::ParseError => error
114
+ Legion::Logging.error('config file must be valid json')
115
+ Legion::Logging.debug("file:#{file}, error: #{error}")
116
+ end
117
+ else
118
+ Legion::Logging.warn("Config file does not exist or is not readable file:#{file}")
119
+ end
120
+ end
121
+
122
+ def load_directory(directory)
123
+ warning('loading config files from directory', directory: directory)
124
+ path = directory.gsub(/\\(?=\S)/, '/')
125
+ if File.readable?(path) && File.executable?(path)
126
+ Dir.glob(File.join(path, '**{,/*/**}/*.json')).uniq.each do |file|
127
+ load_file(file)
128
+ end
129
+ else
130
+ load_error('insufficient permissions for loading', directory: directory)
131
+ end
132
+ end
133
+
134
+ def load_client_overrides
135
+ @settings[:client][:subscriptions] ||= []
136
+ if @settings[:client][:subscriptions].is_a?(Array)
137
+ @settings[:client][:subscriptions] << "client:#{@settings[:client][:name]}"
138
+ @settings[:client][:subscriptions].uniq!
139
+ @indifferent_access = false
140
+ else
141
+ Legion::Logging.warn('unable to apply legion client overrides, reason: client subscriptions is not an array')
142
+ end
143
+ end
144
+
145
+ def load_overrides!
146
+ load_client_overrides if %w[client rspec].include?(legion_service_name)
147
+ end
148
+
149
+ def set_env!
150
+ ENV['LEGION_LOADED_TEMPFILE'] = create_loaded_tempfile!
151
+ end
152
+
153
+ def validate
154
+ validator = Validator.new
155
+ @errors += validator.run(@settings, legion_service_name)
156
+ end
157
+
158
+ private
159
+
160
+ def setting_category(category)
161
+ @settings[category].map do |name, details|
162
+ details.merge(name: name.to_s)
163
+ end
164
+ end
165
+
166
+ def definition_exists?(category, name)
167
+ @settings[category].key?(name.to_sym)
168
+ end
169
+
170
+ def indifferent_hash
171
+ Hash.new do |hash, key|
172
+ hash[key.to_sym] if key.is_a?(String)
173
+ end
174
+ end
175
+
176
+ def with_indifferent_access(hash)
177
+ hash = indifferent_hash.merge(hash)
178
+ hash.each do |key, value|
179
+ hash[key] = with_indifferent_access(value) if value.is_a?(Hash)
180
+ end
181
+ end
182
+
183
+ def indifferent_access!
184
+ @settings = with_indifferent_access(@settings)
185
+ @indifferent_access = true
186
+ end
187
+
188
+ def load_api_env
189
+ return unless ENV['LEGION_API_PORT']
190
+
191
+ @settings[:api] ||= {}
192
+ @settings[:api][:port] = ENV['LEGION_API_PORT'].to_i
193
+ Legion::Logging.warn("using api port environment variable, api: #{@settings[:api]}")
194
+ @indifferent_access = false
195
+ end
196
+
197
+ def read_config_file(file)
198
+ contents = IO.read(file)
199
+ if contents.respond_to?(:force_encoding)
200
+ encoding = ::Encoding::ASCII_8BIT
201
+ contents = contents.force_encoding(encoding)
202
+ contents.sub!("\xEF\xBB\xBF".force_encoding(encoding), '')
203
+ else
204
+ contents.sub!(/^\357\273\277/, '')
205
+ end
206
+ contents.strip
207
+ end
208
+
209
+ def deep_merge(hash_one, hash_two)
210
+ merged = hash_one.dup
211
+ hash_two.each do |key, value|
212
+ merged[key] = if hash_one[key].is_a?(Hash) && value.is_a?(Hash)
213
+ deep_merge(hash_one[key], value)
214
+ elsif hash_one[key].is_a?(Array) && value.is_a?(Array)
215
+ hash_one[key].concat(value).uniq
216
+ else
217
+ value
218
+ end
219
+ end
220
+ merged
221
+ end
222
+
223
+ # rubocop:disable Metrics/AbcSize
224
+ def deep_diff(hash_one, hash_two)
225
+ keys = hash_one.keys.concat(hash_two.keys).uniq
226
+ keys.each_with_object({}) do |key, diff|
227
+ next if hash_one[key] == hash_two[key]
228
+
229
+ diff[key] = if hash_one[key].is_a?(Hash) && hash_two[key].is_a?(Hash)
230
+ deep_diff(hash_one[key], hash_two[key])
231
+ else
232
+ [hash_one[key], hash_two[key]]
233
+ end
234
+ end
235
+ end
236
+ # rubocop:enable Metrics/AbcSize
237
+
238
+ def create_loaded_tempfile!
239
+ dir = ENV['LEGION_LOADED_TEMPFILE_DIR'] || Dir.tmpdir
240
+ file_name = "legion_#{legion_service_name}_loaded_files"
241
+ path = File.join(dir, file_name)
242
+ File.open(path, 'w') do |file|
243
+ file.write(@loaded_files.join(':'))
244
+ end
245
+ path
246
+ end
247
+
248
+ def legion_service_name
249
+ File.basename($PROGRAM_NAME).split('-').last
250
+ end
251
+
252
+ def system_hostname
253
+ Socket.gethostname
254
+ rescue StandardError
255
+ 'unknown'
256
+ end
257
+
258
+ def system_address
259
+ Socket.ip_address_list.find do |address|
260
+ address.ipv4? && !address.ipv4_loopback?
261
+ end.ip_address
262
+ rescue StandardError
263
+ 'unknown'
264
+ end
265
+
266
+ def warning(message, data = {})
267
+ @warnings << {
268
+ message: message
269
+ }.merge(data)
270
+ Legion::Logging.warn(message)
271
+ end
272
+
273
+ def load_error(message, data = {})
274
+ @errors << {
275
+ message: message
276
+ }.merge(data)
277
+ Legion::Logging.error(message)
278
+ raise(Error, message)
279
+ end
280
+ end
281
+ end
282
+ end
@@ -0,0 +1,170 @@
1
+ module Legion
2
+ module Settings
3
+ module Rules
4
+ # Check that a value is a hash.
5
+ #
6
+ # @param value [Object] to check.
7
+ # @return [TrueClass, FalseClass]
8
+ def must_be_a_hash(value)
9
+ value.is_a?(Hash)
10
+ end
11
+ alias is_a_hash? must_be_a_hash
12
+
13
+ # Check that a value is a hash, if set (not nil).
14
+ #
15
+ # @param value [Object] to check.
16
+ # @return [TrueClass, FalseClass]
17
+ def must_be_a_hash_if_set(value)
18
+ value.nil? ? true : must_be_a_hash(value)
19
+ end
20
+
21
+ # Check that a value is an array.
22
+ #
23
+ # @param value [Object] to check.
24
+ # @return [TrueClass, FalseClass]
25
+ def must_be_an_array(value)
26
+ value.is_a?(Array)
27
+ end
28
+ alias is_an_array? must_be_an_array
29
+
30
+ # Check that a value is an array, if set (not nil).
31
+ #
32
+ # @param value [Object] to check.
33
+ # @return [TrueClass, FalseClass]
34
+ def must_be_an_array_if_set(value)
35
+ value.nil? ? true : must_be_an_array(value)
36
+ end
37
+
38
+ # Check that a value is a string.
39
+ #
40
+ # @param value [Object] to check.
41
+ # @return [TrueClass, FalseClass]
42
+ def must_be_a_string(value)
43
+ value.is_a?(String)
44
+ end
45
+ alias is_a_string? must_be_a_string
46
+
47
+ # Check that a value is a string, if set (not nil).
48
+ #
49
+ # @param value [Object] to check.
50
+ # @return [TrueClass, FalseClass]
51
+ def must_be_a_string_if_set(value)
52
+ value.nil? ? true : must_be_a_string(value)
53
+ end
54
+
55
+ # Check that a value is an integer.
56
+ #
57
+ # @param value [Object] to check.
58
+ # @return [TrueClass, FalseClass]
59
+ def must_be_an_integer(value)
60
+ value.is_a?(Integer)
61
+ end
62
+ alias is_an_integer? must_be_an_integer
63
+
64
+ # Check that a value is an integer, if set (not nil).
65
+ #
66
+ # @param value [Object] to check.
67
+ # @return [TrueClass, FalseClass]
68
+ def must_be_an_integer_if_set(value)
69
+ value.nil? ? true : must_be_an_integer(value)
70
+ end
71
+
72
+ # Check that a value is numeric.
73
+ #
74
+ # @param value [Object] to check.
75
+ # @return [TrueClass, FalseClass]
76
+ def must_be_a_numeric(value)
77
+ value.is_a?(Numeric)
78
+ end
79
+
80
+ # Check that a value is numeric, if set (not nil).
81
+ #
82
+ # @param value [Object] to check.
83
+ # @return [TrueClass, FalseClass]
84
+ def must_be_a_numeric_if_set(value)
85
+ value.nil? ? true : must_be_a_numeric(value)
86
+ end
87
+
88
+ # Check that a value matches a regular expression.
89
+ #
90
+ # @param regex [Regexp] pattern to compare with value.
91
+ # @param value [Object] to check if matches pattern.
92
+ # @return [TrueClass, FalseClass]
93
+ def must_match_regex(regex, value)
94
+ (value =~ regex).zero?
95
+ end
96
+
97
+ # Check if a value is boolean.
98
+ #
99
+ # @param value [Object] to check.
100
+ # @return [TrueClass, FalseClass]
101
+ def must_be_boolean(value)
102
+ !value.nil?
103
+ end
104
+
105
+ # Check if a value is boolean, if set (no nil).
106
+ #
107
+ # @param value [Object] to check.
108
+ # @return [TrueClass, FalseClass]
109
+ def must_be_boolean_if_set(value)
110
+ value.nil? ? true : must_be_boolean(value)
111
+ end
112
+
113
+ # Check that value items are all strings and not empty.
114
+ #
115
+ # @param value [Array] with items to check.
116
+ # @param regex [Regexp] to validate string items with.
117
+ # @return [TrueClass, FalseClass]
118
+ def items_must_be_strings(value, regex = nil)
119
+ value.all? do |item|
120
+ item.is_a?(String) && !item.empty? &&
121
+ (regex.nil? || item =~ regex)
122
+ end
123
+ end
124
+
125
+ # Check if either of the values are set (not nil).
126
+ #
127
+ # @param values [Array<Object>] to check if not nil.
128
+ # @return [TrueClass, FalseClass]
129
+ def either_are_set?(*values)
130
+ values.any? do |value|
131
+ !value.nil?
132
+ end
133
+ end
134
+
135
+ # Check if values are valid times (can be parsed).
136
+ #
137
+ # @param values [Array<Object>] to check if valid time.
138
+ # @return [TrueClass, FalseClass]
139
+ def must_be_time(*values)
140
+ values.all? do |value|
141
+ begin
142
+ Time.parse(value)
143
+ rescue StandardError
144
+ false
145
+ end
146
+ end
147
+ end
148
+
149
+ # Check if values are allowed.
150
+ #
151
+ # @param allowed [Array<Object>] allowed values.
152
+ # @param values [Array<Object>] to check if allowed.
153
+ # @return [TrueClass, FalseClass]
154
+ def must_be_either(allowed, *values)
155
+ values.flatten.all? do |value|
156
+ allowed.include?(value)
157
+ end
158
+ end
159
+
160
+ # Check if values are allowed, if set (not nil).
161
+ #
162
+ # @param allowed [Array<Object>] allowed values.
163
+ # @param values [Array<Object>] to check if allowed.
164
+ # @return [TrueClass, FalseClass]
165
+ def must_be_either_if_set(allowed, *values)
166
+ values[0].nil? ? true : must_be_either(allowed, values)
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,80 @@
1
+ require 'legion/settings/rules'
2
+ require 'legion/settings/validators'
3
+ require 'legion/settings/constants'
4
+
5
+ module Legion
6
+ module Settings
7
+ class Validator
8
+ include Rules
9
+ include Validators
10
+
11
+ # @!attribute [r] failures
12
+ # @return [Array] validation failures.
13
+ attr_reader :failures
14
+
15
+ def initialize
16
+ @failures = []
17
+ end
18
+
19
+ # Run the validator.
20
+ #
21
+ # @param settings [Hash] legion settings to validate.
22
+ # @param service [String] legion service to validate for.
23
+ # @return [Array] validation failures.
24
+ def run(settings, service = nil)
25
+ validate_legion(settings[:legion])
26
+ validate_transport(settings[:transport])
27
+ validate_categories(settings)
28
+ case service
29
+ when 'client'
30
+ validate_client(settings[:client])
31
+ when 'api'
32
+ validate_api(settings[:api])
33
+ when 'rspec'
34
+ validate_client(settings[:client])
35
+ validate_api(settings[:api])
36
+ end
37
+ @failures
38
+ end
39
+
40
+ def reset!
41
+ failure_count = @failures.size
42
+ @failures = []
43
+ failure_count
44
+ end
45
+ alias reset reset!
46
+
47
+ private
48
+
49
+ # Validate setting categories: checks, filters, mutators, and
50
+ # handlers.
51
+ #
52
+ # @param settings [Hash] legion settings to validate.
53
+ def validate_categories(settings)
54
+ CATEGORIES.each do |category|
55
+ if is_a_hash?(settings[category])
56
+ validate_method = ('validate_' + category.to_s.chop).to_sym
57
+ settings[category].each do |name, details|
58
+ send(validate_method, details.merge(name: name.to_s))
59
+ end
60
+ else
61
+ invalid(settings[category], "#{category} must be a hash")
62
+ end
63
+ end
64
+ end
65
+
66
+ # Record an invalid object with a message.
67
+ #
68
+ # @param object [Object] invalid object.
69
+ # @param message [String] message explaining why the object is
70
+ # invalid.
71
+ # @return [Array] current validation failures.
72
+ def invalid(object, message)
73
+ @failures << {
74
+ object: object,
75
+ message: message
76
+ }
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,9 @@
1
+ require 'legion/settings/validators/legion'
2
+
3
+ module Legion
4
+ module Settings
5
+ module Validators
6
+ include Legion
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,37 @@
1
+ module Legion
2
+ module Settings
3
+ module Validators
4
+ module Legion
5
+ # Validate Legion spawn.
6
+ # Validates: limit
7
+ #
8
+ # @param legion [Hash] legion definition.
9
+ def validate_legion_spawn(legion)
10
+ spawn = legion[:spawn]
11
+ if is_a_hash?(spawn)
12
+ if is_an_integer?(spawn[:limit])
13
+ (spawn[:limit]).positive? ||
14
+ invalid(legion, 'legion spawn limit must be greater than 0')
15
+ else
16
+ invalid(legion, 'legion spawn limit must be an integer')
17
+ end
18
+ else
19
+ invalid(legion, 'legion spawn must be a hash')
20
+ end
21
+ end
22
+
23
+ # Validate a Legion definition.
24
+ # Validates: spawn
25
+ #
26
+ # @param legion [Hash] legion definition.
27
+ def validate_legion(legion)
28
+ if is_a_hash?(legion)
29
+ validate_legion_spawn(legion)
30
+ else
31
+ invalid(legion, 'legion must be a hash')
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,5 @@
1
+ module Legion
2
+ module Settings
3
+ VERSION = '0.1.0'.freeze
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: legion-settings
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Esity
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-12-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: codecov
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec_junit_formatter
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: legion-json
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.1'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: legion-logging
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.1'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.1'
111
+ description: Based on Sensu's implementation of settings
112
+ email:
113
+ - matthewdiverson@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".circleci/config.yml"
119
+ - ".gitignore"
120
+ - ".rubocop.yml"
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - bin/console
126
+ - bin/setup
127
+ - bitbucket-pipelines.yml
128
+ - legion-settings.gemspec
129
+ - lib/legion/settings.rb
130
+ - lib/legion/settings/constants.rb
131
+ - lib/legion/settings/loader.rb
132
+ - lib/legion/settings/rules.rb
133
+ - lib/legion/settings/validator.rb
134
+ - lib/legion/settings/validators.rb
135
+ - lib/legion/settings/validators/legion.rb
136
+ - lib/legion/settings/version.rb
137
+ homepage: https://bitbucket.org/whonodes/legion-settings
138
+ licenses:
139
+ - MIT
140
+ metadata: {}
141
+ post_install_message:
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 2.6.14
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: Used to load the json settings files
161
+ test_files: []