mimi-config 0.1.1 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cca2e6a1670a7c4f5721347e52617840139f84c3
4
- data.tar.gz: 744fb11b98ed3ddbb7524a73a0a58b8156b0ddb7
3
+ metadata.gz: c11b17f051b8f15e08c1a3fbcfe0ba385949ff4a
4
+ data.tar.gz: 1c9eea0c84229415e795cfe45d107500f249250d
5
5
  SHA512:
6
- metadata.gz: 8c7b0f8d48b89bfa92f24aea94ab620a692d8b67bc170bc89f1f75f0b2264cf2cdcfd82d06732681cff6c9f4527373f1be51448de19164d5eb9977848bca2a97
7
- data.tar.gz: 4181ee303e70a2751fe026d89b639afc28ba6384e795f9f0f6c231dc855f4152b1ff63ea9cc023823bc855f51679fcabcfae35db82e4d29605acb229038fa5e9
6
+ metadata.gz: f6774639e0cd68abc8d81b44ede677827f42c933063bd93af2a811bce0dd17596fce9923c42bb235059ec24aaa022cd0f406edb5d98be27da98cc25797243fa2
7
+ data.tar.gz: 77b66fe00e50c047ed8314cf9c05cf713114368769b57d252ccd7f928bd243524359700ed2e607159f257b7b1f94083b5d34564c3a388b4399376980f5645a3d
data/Gemfile CHANGED
@@ -3,4 +3,5 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  # Comment out the following gem instructions, if you not using gem sources
6
- # gem 'mimi-core', path: '/mimi-core'
6
+ gem 'mimi-core', path: '../mimi-core'
7
+
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # mimi-config
2
2
 
3
- A simple ENV based configuration for microservice applications.
3
+ A simple ENV and manifest based configuration for microservice applications.
4
4
 
5
5
 
6
6
  ## Installation
@@ -23,64 +23,196 @@ Or install it yourself as:
23
23
 
24
24
  `Mimi::Config` allows you to define a set of configurable parameters and constants in a *manifest* file with a simple YAML format.
25
25
 
26
+ When instantiated, a `Mimi::Config` object reads and parses the manifest found in the specified file,
27
+ loads parameter values from ENV variables and processes them according to the manifest.
28
+
29
+ On success, `Mimi::Config` object makes configurable parameters available as Hash keys
30
+ or as methods:
31
+
32
+ ```yaml
33
+ # manifest.yml
34
+ param1:
35
+ default: "foobar"
36
+ ```
37
+
38
+ ```ruby
39
+ require 'mimi/config'
40
+
41
+ config = Mimi::Config.new('manifest.yml')
42
+ config.param1 # => "foobar", if ENV['param1'] is not set
43
+ ```
44
+
45
+
46
+ ## Manifest
47
+
48
+ A *manifest* is a formal declaration of accepted configurable parameters.
49
+ Only the parameters defined in the manifest may be set.
50
+
51
+ For each configurable parameter there may be declared:
52
+
53
+ * configurable parameter name
54
+ * human readable description of the parameter
55
+ * type of accepted values
56
+ * default value
57
+ * whether this parameter is constant or not
58
+
26
59
  ### Example manifest.yml
27
60
  ```yaml,name=manifest.yml
61
+ # This is a minimal definition of a configurable parameter.
62
+ # Its type is 'string', there is no human readable description and no default value:
63
+ min1:
64
+
65
+ # This parameter is optional as it has a default value.
28
66
  opt1:
29
67
  desc: This is an optional configurable parameter
30
- default: 123
68
+ default: "opt1.default"
31
69
 
70
+ # Having no defined default value makes the configurable parameter required
71
+ req1:
72
+ desc: This is a required configurable parameter
73
+
74
+ # An optional configurable parameter with a default value of 'nil':
32
75
  opt2:
33
- desc: This is an optional configurable parameter with the default value of nil
34
76
  default:
35
77
 
78
+ # A constant parameter of type 'string'.
79
+ # It must have a default value and it cannot be changed via ENV variable.
36
80
  const1:
37
- desc: This is a constant parameter, that cannot be changed via an ENV variable
38
- const: 456
81
+ desc: This is a constant parameter
82
+ default: "const1.default"
83
+ const: true
84
+ ```
85
+
86
+ ### Configurable parameter types
39
87
 
88
+ The type of configurable parameter defines which values/format it accepts from ENV,
89
+ and the type it converts the processed value to.
40
90
 
41
- req1: This is a required configurable parameter
91
+ ```yaml
92
+ # manifest_with_types.yml
42
93
 
43
- req2:
44
- desc: And so is this one
94
+ # 'string' accepts any value and converts to String
95
+ str1:
96
+ type: string
45
97
 
46
- # And so is this one with no description
47
- req3:
98
+ # 'integer' accepts any positive integer and converts to Integer
99
+ int1:
100
+ type: integer
101
+
102
+ # 'decimal' accepts a decimal number representation (integer or fractional) and converts to BigDecimal
103
+ dec1:
104
+ type: decimal
105
+
106
+ # 'boolean' accepts only String values 'true' and 'false',
107
+ # and converts to Ruby literals 'true' or 'false'.
108
+ bool1:
109
+ type: boolean
110
+
111
+ # 'json' accepts a valid JSON and converts to a decoded object (of any type)
112
+ json1:
113
+ type: json
114
+
115
+ # 'enum' is a special type that accepts only values from a provided set of string literals.
116
+ # Converts the value to String.
117
+ enum1:
118
+ type:
119
+ - debug
120
+ - info
121
+ - warn
122
+ - error
48
123
  ```
49
124
 
125
+ **Example:**
126
+
127
+ ```ruby
128
+ require 'mimi/config'
129
+
130
+ # Provided the ENV values are set as:
131
+ ENV['str1'] # => "foobar"
132
+ ENV['int1'] # => "123"
133
+ ENV['dec1'] # => "1.23"
134
+ ENV['bool1'] # => "true"
135
+ ENV['json1'] # => "[{\"a\":1},{\"b\":2}]"
136
+ ENV['enum1'] # => "info"
137
+
138
+ config = Mimi::Config.new('manifest_with_types.yml')
139
+
140
+ config.str1 # => "foobar" (String)
141
+ config.int1 # => 123 (Integer)
142
+ config.dec1 # => 1.23 (BigDecimal)
143
+ config.bool1 # => true (TrueClass)
144
+ config.json1 # => [{"a"=>1}, {"b"=>2}] (Array)
145
+ config.enum1 # => "info" (String)
146
+ ```
147
+
148
+
50
149
  ### How to load configuration from your app
51
150
 
52
151
  Providing you have placed your manifest into `config/manifest.yml`:
53
152
 
153
+ ```yaml
154
+ const1:
155
+ default: 456
156
+ const: true
157
+
158
+ req1:
159
+
160
+ opt1:
161
+ default: foobar
162
+
163
+ opt2:
164
+ type: integer
165
+ default: 0
166
+ ```
167
+
54
168
  ```ruby
55
169
  config = Mimi::Config.new('config/manifest.yml')
56
170
 
57
171
  config.const1 # => 456, from manifest.yml
58
- config.opt1 # value from ENV['opt1'] or default from manifest.yml
172
+ config.opt1 # value from ENV['opt1'] or default "foobar" from manifest.yml
59
173
  config.req2 # value from ENV['req2']
60
174
 
61
175
  # alternatively use [] syntax:
62
176
  config.opt2 #
63
- config[:opt2] # all three refer to the same configurable parameter
64
- config['opt2'] #
177
+ config[:opt2] # refers to the same configurable parameter
65
178
 
66
179
  # you cannot access parameters not defined in the manifest:
67
- config.req5 # => NoMethodError
68
- config['req5'] # => ArgumentError
180
+ config.foobar # => NoMethodError
181
+ config[:foobar] # => ArgumentError
182
+
183
+ # when using [] syntax, use Symbol as parameter name:
184
+ config.opt2 # => 0, if ENV['opt2'] is not set
185
+ config[:opt2] # => 0, if ENV['opt2'] is not set
186
+ config['opt2'] # => ArgumentError
69
187
 
70
188
  # check, if parameter is defined:
71
- config.include?('req5') # => false
189
+ config.include?(:foobar) # => false
72
190
  ```
73
191
 
74
- ## Development
192
+ ### Using with Dotenv
193
+
194
+ When a `Mimi::Config` object is instantiated, the `.env` file is loaded and processed,
195
+ the functionality provided by the `dotenv` gem.
196
+
197
+ You can choose to disable `dotenv` and `.env` file loading:
198
+
199
+ ```ruby
200
+ require 'mimi/config'
75
201
 
76
- 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.
202
+ config = Mimi::Config.new('manifest.yml', config_use_dotenv: false)
203
+ ```
77
204
 
78
- 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).
205
+ ### Using as Mimi component
79
206
 
80
- ## Contributing
207
+ It is possible to configure `Mimi::Config` as a Mimi module:
81
208
 
82
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/mimi-config. 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.
209
+ ```ruby
210
+ require 'mimi/config'
211
+
212
+ Mimi.use Mimi::Config, config_use_dotenv: false
213
+ ```
83
214
 
215
+ After that, any `Mimi::Config` object you instantiate will use provided options as default.
84
216
 
85
217
  ## License
86
218
 
@@ -1,5 +1,5 @@
1
1
  module Mimi
2
2
  class Config
3
- VERSION = '0.1.1'.freeze
3
+ VERSION = '1.0.0'.freeze
4
4
  end # class Config
5
5
  end # module Mimi
data/lib/mimi/config.rb CHANGED
@@ -22,10 +22,30 @@ module Mimi
22
22
  # Current set of values for configurable and const parameters
23
23
  attr_reader :params
24
24
 
25
- default_options(
26
- raise_on_missing_params: true,
27
- use_dotenv: true
28
- )
25
+ # Mimi::Config module manifest
26
+ #
27
+ def self.manifest
28
+ {
29
+ config_raise_on_missing_params: {
30
+ desc: 'Raise error on missing params',
31
+ default: true,
32
+ hidden: true
33
+ },
34
+ config_use_dotenv: {
35
+ desc: 'Use Dotenv and load .env file',
36
+ default: true,
37
+ hidden: true
38
+ }
39
+ }
40
+ end
41
+
42
+ # Returns the module path, for exported rake files
43
+ #
44
+ # @return [Pathname]
45
+ #
46
+ def self.module_path
47
+ Pathname.new(__dir__).join('..', '..').expand_path
48
+ end
29
49
 
30
50
  # Creates a Config object.
31
51
  #
@@ -37,7 +57,7 @@ module Mimi
37
57
  # @param manifest_filename [String,nil] path to the manifest.yml or nil to skip loading manifest
38
58
  #
39
59
  def initialize(manifest_filename = nil, opts = {})
40
- @manifest = Mimi::Config::Manifest.new
60
+ @manifest = Mimi::Core::Manifest.new({})
41
61
  @params = {}
42
62
  load(manifest_filename, opts) if manifest_filename
43
63
  end
@@ -46,11 +66,11 @@ module Mimi
46
66
  # from ENV.
47
67
  #
48
68
  def load(manifest_filename, opts = {})
49
- opts = self.class.module_options.deep_merge(opts)
69
+ opts = self.class.options.deep_merge(opts)
50
70
  manifest_filename = Pathname.new(manifest_filename).expand_path
51
- load_manifest(manifest_filename, opts)
71
+ @manifest.merge!(self.class.load_manifest(manifest_filename, opts))
52
72
  load_params(opts)
53
- if opts[:raise_on_missing_params] && !missing_params.empty?
73
+ if opts[:config_raise_on_missing_params] && !missing_params.empty?
54
74
  raise "Missing required configurable parameters: #{missing_params.join(', ')}"
55
75
  end
56
76
  self
@@ -63,23 +83,11 @@ module Mimi
63
83
  required_params - @params.keys
64
84
  end
65
85
 
66
- # Returns annotated manifest
86
+ # Returns the underlying manifest
67
87
  #
68
- def manifest
69
- @manifest.map do |k, v|
70
- {
71
- name: k,
72
- desc: v[:desc],
73
- required: !v.key?(:default),
74
- const: v[:const],
75
- default: v[:default]
76
- }
77
- end
78
- end
79
-
80
- # Returns raw manifest
88
+ # @return [Mimi::Core::Manifest]
81
89
  #
82
- def manifest_raw
90
+ def manifest
83
91
  @manifest
84
92
  end
85
93
 
@@ -89,26 +97,29 @@ module Mimi
89
97
  # via #[] and #<name> methods.
90
98
  #
91
99
  def include?(name)
92
- @manifest.key?(name.to_sym)
100
+ @manifest.to_h.key?(name.to_sym)
93
101
  end
94
102
 
95
103
  # Returns the parameter value
96
104
  #
97
- # @param key [String,Symbol] parameter name
105
+ # @param key [Symbol] parameter name
98
106
  #
99
107
  def [](key)
108
+ unless key.is_a?(Symbol)
109
+ raise ArgumentError, "Invalid key to #[], Symbol expected: '#{key.inspect}'"
110
+ end
100
111
  raise ArgumentError, "Undefined parameter '#{key}'" unless include?(key)
101
- @params[key.to_sym]
112
+ @params[key]
102
113
  end
103
114
 
104
115
  # Provides access to parameters as methods.
105
116
  #
106
117
  # Example:
107
- # config['foo'] # => 'bar'
118
+ # config[:foo] # => 'bar'
108
119
  # config.foo # => 'bar'
109
120
  #
110
121
  # # missing parameter
111
- # config['bar'] # => ArgumentError
122
+ # config[:bar] # => ArgumentError
112
123
  # config.bar # => NoMethodError
113
124
  #
114
125
  def method_missing(name, *)
@@ -126,46 +137,40 @@ module Mimi
126
137
  # @return [Hash]
127
138
  #
128
139
  def to_h
129
- @manifest.keys.map do |k|
140
+ @manifest.to_h.keys.map do |k|
130
141
  [k, self[k]]
131
142
  end.to_h
132
143
  end
133
144
 
134
145
  # Returns to_h.to_s
135
146
  #
147
+ # @return [String]
148
+ #
136
149
  def to_s
137
150
  to_h.to_s
138
151
  end
139
152
 
140
- private
141
-
142
- # Reads manifest file and merges it with the current manifest.
153
+ # Reads and parses the manifest file and constructs the Mimi::Core::Manifest object
154
+ #
155
+ # @param filename [Pathname]
156
+ # @param _opts
157
+ # @return [Mimi::Core::Manifest]
143
158
  #
144
- def load_manifest(filename, _opts = {})
145
- @manifest.load(filename)
159
+ def self.load_manifest(filename, _opts = {})
160
+ Mimi::Core::Manifest.from_yaml(File.read(filename))
161
+ rescue StandardError => e
162
+ raise "Failed to load config manifest from '#{filename}': #{e}"
146
163
  end
147
164
 
165
+ private
166
+
148
167
  # Reads parameters from the ENV according to the current manifest
149
168
  #
150
169
  def load_params(opts = {})
151
- Dotenv.load if opts[:use_dotenv]
152
- manifest.each do |p|
153
- env_name = p[:name].to_s
154
- if p[:const]
155
- # const
156
- @params[p[:name]] = p[:default]
157
- elsif p[:required]
158
- # required configurable
159
- @params[p[:name]] = ENV[env_name] if ENV.key?(env_name)
160
- else
161
- # optional configurable
162
- @params[p[:name]] = ENV.key?(env_name) ? ENV[env_name] : p[:default]
163
- end
164
- end
165
- @params
170
+ Dotenv.load if opts[:config_use_dotenv]
171
+ @params = @manifest.apply(ENV.to_h.symbolize_keys)
166
172
  end
167
173
  end # class Config
168
174
  end # module Mimi
169
175
 
170
176
  require_relative 'config/version'
171
- require_relative 'config/manifest'
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Returns the path to the manifest file
4
+ #
5
+ # @return [Pathname]
6
+ #
7
+ def rake_task_config_manifest_filename
8
+ Mimi.app_path_to('config', 'manifest.yml')
9
+ end
10
+
11
+ # Displays current manifest and configured values in .env format
12
+ #
13
+ # @param include_consts [true,false] include non-configurable parameters (consts)
14
+ #
15
+ def rake_task_config(include_consts = false)
16
+ manifest = Mimi::Config.load_manifest(rake_task_config_manifest_filename)
17
+ missing_params = manifest.keys.select { |k| manifest.required?(k) }.reject { |k| ENV.key?(k.to_s) }
18
+
19
+ manifest.to_h.each do |name, props|
20
+ next if props[:const] && !include_consts
21
+ annotation = []
22
+ if props[:const]
23
+ annotation << '[CONST]'
24
+ annotation << "(value: #{props[:default].inspect})"
25
+ elsif missing_params.include?(name)
26
+ annotation << "[MISSING] (#{props[:type]})"
27
+ else
28
+ annotation << "(#{props[:type]}, default: #{props[:default].inspect})"
29
+ end
30
+ annotation << props[:desc] if props.key?(:desc)
31
+ annotation.unshift(' #') unless annotation.empty?
32
+ puts "#{name}=#{ENV[name.to_s]}#{annotation.join(' ')}"
33
+ end
34
+ abort('# FIXME: configure missing parameters') unless missing_params.empty?
35
+ end
36
+
37
+ # Generates a new/updated config manifest
38
+ #
39
+ # @return [String] a config manifest in the YAML format
40
+ #
41
+ def rake_task_config_manifest_generate
42
+ manifest = Mimi::Core::Manifest.new({})
43
+
44
+ # merge loaded modules manifests
45
+ Mimi.loaded_modules.map(&:manifest).each do |manifest_hash|
46
+ manifest.merge!(manifest_hash)
47
+ end
48
+
49
+ # merge app's explicit manifest
50
+ app_manifest = Mimi::Config.load_manifest(rake_task_config_manifest_filename)
51
+ manifest.merge!(app_manifest)
52
+
53
+ manifest.to_yaml
54
+ end
55
+
56
+ desc 'Display config manifest and current config'
57
+ task :config do
58
+ rake_task_config(false)
59
+ end
60
+
61
+ namespace :config do
62
+ desc 'Display config manifest and current config, including consts'
63
+ task :all do
64
+ rake_task_config(true)
65
+ end
66
+
67
+ desc 'Generate and display a combined manifest for all loaded modules'
68
+ task :manifest do
69
+ puts rake_task_config_manifest_generate
70
+ end
71
+
72
+ namespace :manifest do
73
+ manifest_filename = Pathname.pwd.join('config', 'manifest.yml')
74
+ desc "Generate and write a combined manifest to: #{manifest_filename}"
75
+ task :create do
76
+ if File.exist?(manifest_filename)
77
+ puts "* Found an existing application manifest, loading: #{manifest_filename}"
78
+ end
79
+ puts '* Generating a combined manifest'
80
+ manifest_contents = rake_task_config_manifest_generate
81
+ config_path = Mimi.app_path_to('config')
82
+ puts "* Writing the combined manifest to: #{manifest_filename}"
83
+ sh "install -d #{config_path}" unless File.directory?(config_path)
84
+ File.open(rake_task_config_manifest_filename, 'w') do |f|
85
+ f.puts manifest_contents
86
+ end
87
+ end
88
+ end
89
+ end
data/mimi-config.gemspec CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ['lib']
29
29
 
30
- spec.add_dependency 'mimi-core', '~> 0.1'
30
+ spec.add_dependency 'mimi-core', '~> 1.0'
31
31
  spec.add_dependency 'dotenv', '~> 2.1'
32
32
 
33
33
  spec.add_development_dependency 'bundler', '~> 1.11'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mimi-config
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Kukushkin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-09 00:00:00.000000000 Z
11
+ date: 2019-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mimi-core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.1'
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.1'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: dotenv
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -112,8 +112,8 @@ files:
112
112
  - bin/console
113
113
  - bin/setup
114
114
  - lib/mimi/config.rb
115
- - lib/mimi/config/manifest.rb
116
115
  - lib/mimi/config/version.rb
116
+ - lib/tasks/config.rake
117
117
  - mimi-config.gemspec
118
118
  homepage: https://github.com/kukushkin/mimi-config
119
119
  licenses:
@@ -136,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
136
  version: '0'
137
137
  requirements: []
138
138
  rubyforge_project:
139
- rubygems_version: 2.4.5.1
139
+ rubygems_version: 2.6.14.4
140
140
  signing_key:
141
141
  specification_version: 4
142
142
  summary: Simple ENV based configuration for microservice apps
@@ -1,86 +0,0 @@
1
- module Mimi
2
- class Config
3
- class Manifest < Hash
4
- # Reads manifest file and merges it with the current manifest.
5
- #
6
- # @return [Mimi::Config::Manifest] current manifest merged with the new one
7
- #
8
- def load(filename_or_hash, _opts = {})
9
- new_manifest = nil
10
- if filename_or_hash.is_a?(String) || filename_or_hash.is_a?(Pathname)
11
- new_manifest = YAML.load(File.read(filename_or_hash))
12
- end
13
- new_manifest = filename_or_hash.dup if filename_or_hash.is_a?(Hash)
14
- return self unless new_manifest
15
- raise 'Invalid manifest file format' unless new_manifest.is_a?(Hash)
16
- new_manifest.each do |k, v|
17
- merge_key(k, v)
18
- end
19
- self
20
- rescue StandardError => e
21
- raise "Failed to load manifest file: #{e}"
22
- end
23
-
24
- # Returns YAML representation of the manifest
25
- #
26
- # @return [String]
27
- #
28
- def to_yaml
29
- out = []
30
- self.each do |k, v|
31
- if v.key?(:const)
32
- out << "#{k}:"
33
- out << " desc: #{value_to_yaml(v[:desc])}" if v.key?(:desc)
34
- if v[:const]
35
- out << " const: #{value_to_yaml(v[:default])}"
36
- elsif v.key?(:default)
37
- out << " default: #{value_to_yaml(v[:default])}"
38
- end
39
- elsif v.key?(:desc)
40
- out << "#{k}: #{value_to_yaml(v[:desc])}"
41
- else
42
- out << "#{k}:"
43
- end
44
- out << ''
45
- end
46
- out.join("\n")
47
- end
48
-
49
- private
50
-
51
- def value_to_yaml(v)
52
- v.nil? ? '# nil' : v.inspect
53
- end
54
-
55
- def merge_key(k, v)
56
- k = k.to_sym
57
- self[k] ||= {}
58
- if v.nil?
59
- # var:
60
- elsif v.is_a?(String)
61
- # var: A description
62
- self[k][:desc] = v
63
- elsif v.is_a?(Hash)
64
- merge_key_hash(k, v)
65
- end
66
- end
67
-
68
- def merge_key_hash(k, v)
69
- v = v.dup.stringify_keys
70
- self[k][:desc] = v['desc'] if v.key?('desc')
71
-
72
- if v.key?('const') && v.key?('default')
73
- raise "Invalid mix of 'const' and 'default' in parameter definition '#{k}'"
74
- end
75
-
76
- if v.key?('default')
77
- self[k][:const] = false
78
- self[k][:default] = v['default']
79
- elsif v.key?('const')
80
- self[k][:const] = true
81
- self[k][:default] = v['const']
82
- end
83
- end
84
- end # class Manifest
85
- end # class Config
86
- end # module Mimi