stacked_config 0.1.0 → 0.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/.travis.yml +5 -0
- data/README.md +137 -5
- data/lib/stacked_config/layers/command_line_layer.rb +5 -1
- data/lib/stacked_config/layers/generic_layer.rb +0 -3
- data/lib/stacked_config/orchestrator.rb +30 -2
- data/lib/stacked_config/source_helper.rb +1 -1
- data/lib/stacked_config/version.rb +1 -1
- data/spec/command_line_layer_spec.rb +6 -6
- data/stacked_config.gemspec +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 396a51271ebfbb2aee0f6a8d3d03674f46b7a398
|
4
|
+
data.tar.gz: d4215b4890198baf73cb42ea690ff46b000e9ea3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35cc07767ab94e5891230097e9a83ecaac1202c4325af0d2e8e6fc82ff555d4b760e855bb8e41d8014e66135b52833608ff78e60a30df7e8750c67d48fb408e9
|
7
|
+
data.tar.gz: d114a476a6684535ffabc7a777fe4eff2175a11cd58cca4644ba9657b513e0fc4d3bad0850907425f12ce8c0074ad404d2c21c69da5f991cbc2c64410c5de3cd
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,10 +1,21 @@
|
|
1
1
|
# StackedConfig
|
2
|
+
[](https://travis-ci.org/lbriais/stacked_config)
|
3
|
+
[](http://badge.fury.io/rb/stacked_config)
|
2
4
|
|
3
|
-
|
5
|
+
The purpose of this gem is to provide a __simple__ way to handle the __inheritance__ of __config files__ for a ruby
|
6
|
+
script. By default, it will handle already few config layers:
|
4
7
|
|
5
|
-
|
8
|
+
* The __system layer__, which is a level common to all applications using this gem.
|
9
|
+
* The __global layer__, which is the level to declare options for all users that use the ruby script using this gem.
|
10
|
+
* The __user layer__, which is the level, where a user can set options for the ruby script using this gem.
|
11
|
+
* The __extra layer__, which provides the possibility to specify a config file from the command line.
|
12
|
+
* The __command-line layer__, which provides the ability to specify options from the command line.
|
13
|
+
* The __override layer__, which will contain all modifications done to the config at run time.
|
6
14
|
|
7
|
-
|
15
|
+
The different layers are evaluated by default in that order using the [super_stack gem][SS] (Please read for more
|
16
|
+
detail).
|
17
|
+
|
18
|
+
All the config files are following the [YAML] syntax.
|
8
19
|
|
9
20
|
## Installation
|
10
21
|
|
@@ -22,12 +33,133 @@ Or install it yourself as:
|
|
22
33
|
|
23
34
|
## Usage
|
24
35
|
|
25
|
-
|
36
|
+
### Basics
|
37
|
+
|
38
|
+
`stacked_config` is a very versatile configuration system for your scripts. The default behaviour may satisfy most of
|
39
|
+
the needs out of the box.
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
require 'stacked_config'
|
43
|
+
|
44
|
+
config = StackedConfig::Orchestrator.new
|
45
|
+
|
46
|
+
config[:runtime_property] = 'A runtime property'
|
47
|
+
|
48
|
+
# Displays all the internals of the config:
|
49
|
+
puts config.detailed_layers_info
|
50
|
+
|
51
|
+
# Normally you may probably only need to access some properties
|
52
|
+
if config[:help]
|
53
|
+
puts config.command_line_help
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
Try this little script and then create some config files to test how it is handled (see next section to know where to
|
58
|
+
create the config files).
|
59
|
+
|
60
|
+
|
61
|
+
### Where are my config files ?
|
62
|
+
|
63
|
+
`stacked_config` will look for config files in different places depending on the layer we are talking about. Have a look
|
64
|
+
at the source to understand where exactly your config files can be, but basically it is following the Unix way of
|
65
|
+
doing things...
|
66
|
+
|
67
|
+
* Sources for the [system layer][SystemLayer]
|
68
|
+
* Sources for the [global layer][GlobalLayer]
|
69
|
+
* Sources for the [user layer][UserLayer]
|
70
|
+
|
71
|
+
As you can see in the sources, paths are expressed using kind of 'templates', which meaning should be obvious
|
72
|
+
|
73
|
+
* `##SYSTEM_CONFIG_ROOT##` is where the system config is stored. On Unix systems, it should be `/etc`.
|
74
|
+
* `##PROGRAM_NAME##` is by default the name of the script you are running (with no extension). You can if you want
|
75
|
+
change this name at runtime. Changing it will trigger a re-search and reload of all the config files.
|
76
|
+
* `##USER_CONFIG_ROOT##` is where the user config is stored. On Unix systems, it should be your `$HOME` directory.
|
77
|
+
* `##EXTENSION##` is one of the following extensions : `conf CONF cfg CFG yml YML yaml YAML`.
|
78
|
+
|
79
|
+
The search of the config files is done according to the order defined in sources just above and then extensions
|
80
|
+
are tried according to the extensions just above in that exact order.
|
81
|
+
|
82
|
+
__The first file matching for a particular level is used !__ And there can be only one per level.
|
83
|
+
|
84
|
+
Thus according to the rules above, and assuming my script is named `my_script.rb` if the two following files exists at
|
85
|
+
user config level, only the first is taken in account:
|
86
|
+
|
87
|
+
* `~/.my_script.yml`
|
88
|
+
* `~/.config/my_script.conf`
|
89
|
+
|
90
|
+
|
91
|
+
### Script command line options
|
92
|
+
|
93
|
+
`stacked_config` uses internally the fantastic [Slop] gem to manage options coming from
|
94
|
+
the command line.
|
95
|
+
|
96
|
+
To define your options the command-line layer exposes a `slop_definition` method that enables
|
97
|
+
to directly configure slop.
|
98
|
+
|
99
|
+
For most usages you can use the higher level method `add_command_line_section` from the orchestrator.
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
require 'stacked_config'
|
103
|
+
|
104
|
+
config = StackedConfig::Orchestrator.new
|
105
|
+
config.add_command_line_section do |slop|
|
106
|
+
slop.on :u, :useless, 'Stupid option', :argument => false
|
107
|
+
slop.on :an_int, 'Stupid option with integer argument', :argument => true, :as => Integer
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
The `add_command_line_section` method supports a parameter to define the name of the section.
|
112
|
+
|
113
|
+
|
114
|
+
### Advanced usage
|
115
|
+
|
116
|
+
#### Re-ordering layers
|
117
|
+
|
118
|
+
The way layers are processed is done according to their priority. By default the existing layers have the following
|
119
|
+
priorities:
|
120
|
+
|
121
|
+
* The system layer has a priority of 10
|
122
|
+
* The global layer has a priority of 20
|
123
|
+
* The user layer has a priority of 30
|
124
|
+
* The extra layer has a priority of 40
|
125
|
+
* The command-line layer has a priority of 100
|
126
|
+
* The override layer has a priority of 1000
|
127
|
+
|
128
|
+
But imagine you want to say that no-one could override properties defined at the system and global layer even from the
|
129
|
+
command-line, then you just have to change the priorities of those 2 layers.
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
require 'stacked_config'
|
133
|
+
|
134
|
+
config = StackedConfig::Orchestrator.new
|
135
|
+
config.system_layer.priority = 1500
|
136
|
+
config.global_layer.priority = 1600
|
137
|
+
```
|
138
|
+
|
139
|
+
By doing such the system and global layers will be evaluated after the command line layer and therefore properties set
|
140
|
+
in those files cannot be overridden even at command line level.
|
141
|
+
|
142
|
+
|
143
|
+
#### Adding extra layers
|
144
|
+
|
145
|
+
Imagine you want to add a specific layer in your config, coming from let's say a web-service or a database, you may
|
146
|
+
create your own layers for this purpose. Have a look at [super_stack gem][SS] for further info about how to create
|
147
|
+
layers.
|
148
|
+
|
149
|
+
But basically just create your new layer, gives it a priority and add it to the orchestrator.
|
150
|
+
|
26
151
|
|
27
152
|
## Contributing
|
28
153
|
|
29
|
-
1. Fork it (
|
154
|
+
1. [Fork it] ( https://github.com/lbriais/stacked_config/fork )
|
30
155
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
31
156
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
32
157
|
4. Push to the branch (`git push origin my-new-feature`)
|
33
158
|
5. Create new Pull Request
|
159
|
+
|
160
|
+
[SS]: https://github.com/lbriais/super_stack "Super Stack gem"
|
161
|
+
[SystemLayer]: https://github.com/lbriais/stacked_config/blob/master/lib/stacked_config/layers/system_layer.rb "the system layer places where config files are searched"
|
162
|
+
[GlobalLayer]: https://github.com/lbriais/stacked_config/blob/master/lib/stacked_config/layers/global_layer.rb "the global layer places where config files are searched"
|
163
|
+
[UserLayer]: https://github.com/lbriais/stacked_config/blob/master/lib/stacked_config/layers/user_layer.rb "the user layer places where config files are searched"
|
164
|
+
[YAML]: http://www.yaml.org/ "The Yaml official site"
|
165
|
+
[Slop]: https://rubygems.org/gems/slop "The Slop gem"
|
@@ -14,7 +14,11 @@ module StackedConfig
|
|
14
14
|
slop_definition.parse
|
15
15
|
slop_definition.banner = build_banner
|
16
16
|
clear
|
17
|
-
merge! slop_definition.to_hash
|
17
|
+
merge! slop_definition.to_hash.delete_if {|k,v| v.nil?}
|
18
|
+
end
|
19
|
+
|
20
|
+
def possible_options
|
21
|
+
slop_definition.to_hash.keys.sort
|
18
22
|
end
|
19
23
|
|
20
24
|
def reload
|
@@ -10,14 +10,42 @@ module StackedConfig
|
|
10
10
|
super
|
11
11
|
self.merge_policy = SuperStack::MergePolicies::FullMergePolicy
|
12
12
|
setup_layers
|
13
|
-
default_name =
|
13
|
+
default_name = self.class.default_executable_name
|
14
14
|
describes_application executable_name: default_name, app_name: default_name
|
15
15
|
end
|
16
16
|
|
17
|
+
def detailed_layers_info
|
18
|
+
info, sep = [], '-' * 80
|
19
|
+
info << sep
|
20
|
+
layers.values.sort {|a, b| a.priority <=> b.priority}.each do |layer|
|
21
|
+
info << layer.name
|
22
|
+
if layer.file_name.nil?
|
23
|
+
info << 'There is no file attached to this level.'
|
24
|
+
else
|
25
|
+
info << "Using '#{layer.file_name}' as config file for this layer."
|
26
|
+
end
|
27
|
+
if layer.empty?
|
28
|
+
info << 'There is no data in this layer'
|
29
|
+
else
|
30
|
+
info << 'This layer contains the following data:'
|
31
|
+
info << layer.to_yaml
|
32
|
+
end
|
33
|
+
info << sep
|
34
|
+
end
|
35
|
+
info.join "\n"
|
36
|
+
end
|
37
|
+
|
38
|
+
def command_line_help
|
39
|
+
command_line_layer.help
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.default_executable_name
|
43
|
+
File.basename($PROGRAM_NAME).gsub /\.[^\.]+$/, ''
|
44
|
+
end
|
45
|
+
|
17
46
|
private
|
18
47
|
|
19
48
|
def setup_layers
|
20
|
-
|
21
49
|
# The command line level.
|
22
50
|
@command_line_layer = setup_layer StackedConfig::Layers::CommandLineLayer, 'Command line configuration level', 100
|
23
51
|
|
@@ -77,7 +77,7 @@ module StackedConfig
|
|
77
77
|
res.gsub! '##SYSTEM_CONFIG_ROOT##', system_config_root
|
78
78
|
res.gsub! '##USER_CONFIG_ROOT##', user_config_root
|
79
79
|
|
80
|
-
exec_name = manager.nil? ?
|
80
|
+
exec_name = manager.nil? ? StackedConfig::Orchestrator.default_executable_name : manager.executable_name
|
81
81
|
res.gsub! '##PROGRAM_NAME##', exec_name
|
82
82
|
res
|
83
83
|
end
|
@@ -4,24 +4,24 @@ require 'spec_helper'
|
|
4
4
|
describe StackedConfig::Layers::CommandLineLayer do
|
5
5
|
subject { StackedConfig::Layers::CommandLineLayer.new }
|
6
6
|
|
7
|
-
it 'should
|
8
|
-
expect(subject.length
|
7
|
+
it 'should expose an empty layer by default' do
|
8
|
+
expect(subject.length == 0).to be_truthy
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'should have a "help" command line options defined' do
|
12
|
-
expect(subject.
|
12
|
+
expect(subject.possible_options.include? :help).to be_truthy
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'should have a "auto" command line options defined' do
|
16
|
-
expect(subject.
|
16
|
+
expect(subject.possible_options.include? :auto).to be_truthy
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'should have a "simulate" command line options defined' do
|
20
|
-
expect(subject.
|
20
|
+
expect(subject.possible_options.include? :simulate).to be_truthy
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'should have a "verbose" command line options defined' do
|
24
|
-
expect(subject.
|
24
|
+
expect(subject.possible_options.include? :verbose).to be_truthy
|
25
25
|
end
|
26
26
|
|
27
27
|
|
data/stacked_config.gemspec
CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_development_dependency 'pry'
|
24
24
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
25
25
|
|
26
|
-
spec.add_dependency 'super_stack', '~> 0.2', '>= 0.2.
|
26
|
+
spec.add_dependency 'super_stack', '~> 0.2', '>= 0.2.5'
|
27
27
|
spec.add_dependency 'slop'
|
28
28
|
|
29
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stacked_config
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Laurent B.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -75,7 +75,7 @@ dependencies:
|
|
75
75
|
version: '0.2'
|
76
76
|
- - '>='
|
77
77
|
- !ruby/object:Gem::Version
|
78
|
-
version: 0.2.
|
78
|
+
version: 0.2.5
|
79
79
|
type: :runtime
|
80
80
|
prerelease: false
|
81
81
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -85,7 +85,7 @@ dependencies:
|
|
85
85
|
version: '0.2'
|
86
86
|
- - '>='
|
87
87
|
- !ruby/object:Gem::Version
|
88
|
-
version: 0.2.
|
88
|
+
version: 0.2.5
|
89
89
|
- !ruby/object:Gem::Dependency
|
90
90
|
name: slop
|
91
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,6 +109,7 @@ extra_rdoc_files: []
|
|
109
109
|
files:
|
110
110
|
- .gitignore
|
111
111
|
- .rspec
|
112
|
+
- .travis.yml
|
112
113
|
- Gemfile
|
113
114
|
- LICENSE.txt
|
114
115
|
- README.md
|