stacked_config 0.4.2 → 1.0.2
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/README.md +44 -31
- data/lib/stacked_config/layers/command_line_layer.rb +4 -1
- data/lib/stacked_config/layers/executable_gem_layer.rb +45 -0
- data/lib/stacked_config/layers/gem_layer.rb +37 -6
- data/lib/stacked_config/layers/generic_layer.rb +43 -0
- data/lib/stacked_config/layers/global_layer.rb +13 -1
- data/lib/stacked_config/layers/system_layer.rb +22 -0
- data/lib/stacked_config/layers/user_layer.rb +20 -0
- data/lib/stacked_config/orchestrator.rb +16 -7
- data/lib/stacked_config/program_description_helper.rb +10 -0
- data/lib/stacked_config/source_helper.rb +15 -74
- data/lib/stacked_config/version.rb +1 -1
- data/lib/stacked_config.rb +1 -0
- data/spec/env_layer_spec.rb +10 -1
- data/spec/executable_gem_layer_spec.rb +23 -0
- data/spec/gem_layer_spec.rb +6 -2
- data/spec/global_layer_spec.rb +6 -2
- data/spec/orchestrator_spec.rb +29 -6
- data/spec/source_helper_spec.rb +4 -14
- data/spec/system_layer_spec.rb +8 -2
- data/spec/user_layer_spec.rb +6 -2
- data/stacked_config.gemspec +1 -1
- data/test/tstgem/config/rspec.yml +1 -1
- data/test/tstgem/config/tstgem.yml +7 -0
- data/test/tstgem/spec/global_spec.rb +2 -2
- metadata +8 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b40875c352b97a4a48b2265e2952978785af039
|
4
|
+
data.tar.gz: 88c153c71f5795df1d1342f03e19a1d9adf45be0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8ef28bf029e4b335bbf6a024ff61939c7dca489cb7602b53dbc48d57b4f7668233d2dd625e1d8cdfda734a6bf6519625f160326498c0d7a2d042cc3aacbdfe92
|
7
|
+
data.tar.gz: e6360ba692bb4beb230a87bc067afff6063882a5448b917a6697c20b20d210e2582b28eaa34dc658b3ad45c7a6fcb6e3379cd4377bfe6e7a36d85fdafc5dc4b4
|
data/README.md
CHANGED
@@ -10,13 +10,17 @@ The purpose of this gem is to provide a __simple__ way to handle the __inheritan
|
|
10
10
|
script. By default, it will handle already few config layers:
|
11
11
|
|
12
12
|
* The __system layer__, which is a layer common to all applications using this gem.
|
13
|
-
* The
|
14
|
-
as the layer where you will set the default values for your
|
13
|
+
* The __executable gem layer__, which is the layer that will enable a script provided by a gem to embed its own default
|
14
|
+
config. __You may consider this level as the layer where you will set the default values for the properties of your
|
15
|
+
executable__. This layer will get the config from the Gem that hosts the current __executable__ running.
|
16
|
+
* The __gem layer__, which is the layer that will enable a gem to embed its own default config. Nevertheless as it is
|
17
|
+
not really possible to guess automatically the name of the gem, it has to be created manually.
|
15
18
|
* The __global layer__, which is the layer to declare options for all users that use the ruby script using this gem.
|
16
19
|
* The __user layer__, which is the layer, where a user can set options for the ruby script using this gem.
|
17
20
|
* The __extra layer__, which provides the possibility to specify another config file from the config itself.
|
18
21
|
* The __enviroment variables layer__, which provides the possibility to include in the config variables coming from
|
19
|
-
the shell variables. See [below](#environment-variables) for more info.
|
22
|
+
the shell variables. See [below](#environment-variables) for more info. This level is optional and not created by
|
23
|
+
default.
|
20
24
|
* The __command-line layer__, which provides the ability to specify options from the command line.
|
21
25
|
* The __override layer__, which will contain all modifications done to the config at run time.
|
22
26
|
|
@@ -28,6 +32,8 @@ All the config files are following the [YAML] syntax.
|
|
28
32
|
__If you're looking for a complete solution for your command line scripts, including some logging features, then you
|
29
33
|
are probably looking for the [easy_app_helper Gem][EAH], which is itself internally relying on [stacked_config][SC].__
|
30
34
|
|
35
|
+
Version 1.x introduces some minor non compatibilities with previous versions. Check [below]() for more info.
|
36
|
+
|
31
37
|
## Installation
|
32
38
|
|
33
39
|
Add this line to your application's Gemfile:
|
@@ -79,7 +85,7 @@ clears the override layer.
|
|
79
85
|
Every layer is accessible through the following orchestrator properties:
|
80
86
|
|
81
87
|
* `system_layer`
|
82
|
-
* `
|
88
|
+
* `executable_gem_layer`
|
83
89
|
* `global_layer`
|
84
90
|
* `user_layer`
|
85
91
|
* `provided_config_file_layer`
|
@@ -87,31 +93,25 @@ Every layer is accessible through the following orchestrator properties:
|
|
87
93
|
* `command_line_layer`
|
88
94
|
* `write_layer`
|
89
95
|
|
96
|
+
The 'gem_layer' has no direct accessor as there could be more than one.
|
97
|
+
|
98
|
+
|
90
99
|
### Where are my config files ?
|
91
100
|
|
92
101
|
`stacked_config` will look for config files in different places depending on the layer we are talking about. Have a look
|
93
102
|
at the source to understand where exactly your config files can be, but basically it is following the Unix way of
|
94
103
|
doing things...
|
95
104
|
|
105
|
+
All file based layers are inheriting from `StackedConfig::Layers::GenericLayer`
|
106
|
+
|
96
107
|
* Sources for the [system layer][SystemLayer]
|
108
|
+
* Sources for the [executable gem layer][ExecutableGemLayer]
|
97
109
|
* Sources for the [gem layer][GemLayer]
|
98
110
|
* Sources for the [global layer][GlobalLayer]
|
99
111
|
* Sources for the [user layer][UserLayer]
|
100
112
|
|
101
|
-
|
102
|
-
|
103
|
-
* `##SYSTEM_CONFIG_ROOT##` is where the system config is stored. On Unix systems, it should be `/etc`.
|
104
|
-
* `##USER_CONFIG_ROOT##` is where the user config is stored. On Unix systems, it should be your `$HOME` directory.
|
105
|
-
* `##GEM_CONFIG_ROOT##` is the path to the "current" Gem root. The current gem being the one containing the
|
106
|
-
currently executing script.
|
107
|
-
* `##PROGRAM_NAME##` is by default the name of the script you are running (with no extension). You can if you want
|
108
|
-
change this name at runtime. __Changing it (using the `config_file_base_name` orchestrator property ) will trigger a
|
109
|
-
re-search and reload of all the config files__. `config_file_base_name` defines the base name to search for config
|
110
|
-
files accross the system. by default the name of the gem will be used.
|
111
|
-
* `##EXTENSION##` is one of the following extensions : `conf CONF cfg CFG yml YML yaml YAML`.
|
112
|
-
|
113
|
-
The search of the config files for a layer is done according to the order defined in sources just above and then
|
114
|
-
extensions are tried according to the extensions just above in that exact order.
|
113
|
+
The search of the config files for a layer is done according to the order defined in `possible_sources` just above
|
114
|
+
and then extensions are tried according to the extensions just above in that exact order.
|
115
115
|
|
116
116
|
__The first file matching for a particular level is used ! And there can be only one per level.__
|
117
117
|
|
@@ -121,6 +121,10 @@ user config level, only the first is taken in account:
|
|
121
121
|
* `~/.my_script.yml`
|
122
122
|
* `~/.config/my_script.conf`
|
123
123
|
|
124
|
+
you can get information about all files that are checked by the layers inheriting from
|
125
|
+
`StackedConfig::Layers::GenericLayer` by using the orchestrator convenience method `detailed_config_files_info` that
|
126
|
+
returns a hash which keys are the file names and values are hashes of information stating if the file is valid or used.
|
127
|
+
|
124
128
|
|
125
129
|
### Environment variables
|
126
130
|
|
@@ -298,10 +302,11 @@ The way layers are processed is done according to their priority. By default the
|
|
298
302
|
priorities:
|
299
303
|
|
300
304
|
* The system layer has a priority of __10__
|
301
|
-
* The gem layer has a priority of __20__
|
302
|
-
* The
|
303
|
-
* The
|
304
|
-
* The
|
305
|
+
* The executable gem layer has a priority of __20__
|
306
|
+
* The gem layer has a priority of __30__ (if exists)
|
307
|
+
* The global layer has a priority of __40__
|
308
|
+
* The user layer has a priority of __50__
|
309
|
+
* The extra layer has a priority of __60__
|
305
310
|
* The command-line layer has a priority of __100__
|
306
311
|
* The override layer has a priority of __1000__
|
307
312
|
|
@@ -485,6 +490,13 @@ This layer contains the following data:
|
|
485
490
|
## Bye...
|
486
491
|
```
|
487
492
|
|
493
|
+
|
494
|
+
## Non nackward compatible changes
|
495
|
+
|
496
|
+
### Between version 0.x and 1.x
|
497
|
+
|
498
|
+
TODO
|
499
|
+
|
488
500
|
## Contributing
|
489
501
|
|
490
502
|
1. [Fork it] ( https://github.com/lbriais/stacked_config/fork ), clone your fork.
|
@@ -493,12 +505,13 @@ This layer contains the following data:
|
|
493
505
|
4. Push to the branch (`git push origin my-new-feature`).
|
494
506
|
5. Create a Pull Request.
|
495
507
|
|
496
|
-
[SS]:
|
497
|
-
[SC]:
|
498
|
-
[SystemLayer]:
|
499
|
-
[
|
500
|
-
[
|
501
|
-
[
|
502
|
-
[
|
503
|
-
[
|
504
|
-
[
|
508
|
+
[SS]: https://github.com/lbriais/super_stack "Super Stack gem"
|
509
|
+
[SC]: https://github.com/lbriais/stacked_config "The stacked_config Gem"
|
510
|
+
[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"
|
511
|
+
[ExecutableGemLayer]: https://github.com/lbriais/stacked_config/blob/master/lib/stacked_config/layers/executable_gem_layer.rb "the executable gem layer places where config files are searched"
|
512
|
+
[GemLayer]: https://github.com/lbriais/stacked_config/blob/master/lib/stacked_config/layers/gem_layer.rb "the gem layer places where config files are searched"
|
513
|
+
[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"
|
514
|
+
[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"
|
515
|
+
[YAML]: http://www.yaml.org/ "The Yaml official site"
|
516
|
+
[Slop]: https://rubygems.org/gems/slop "The Slop gem"
|
517
|
+
[EAH]: https://github.com/lbriais/easy_app_helper "The EasyAppHelper gem"
|
@@ -13,7 +13,10 @@ module StackedConfig
|
|
13
13
|
def load(*args)
|
14
14
|
slop_definition.parse
|
15
15
|
slop_definition.banner = build_banner
|
16
|
-
|
16
|
+
h = slop_definition.to_hash.delete_if {|k,v| v.nil?}
|
17
|
+
res = {}
|
18
|
+
h.each{|k,v| res[k.to_s] = v }
|
19
|
+
h
|
17
20
|
end
|
18
21
|
|
19
22
|
def possible_options
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module StackedConfig
|
2
|
+
module Layers
|
3
|
+
|
4
|
+
class ExecutableGemLayer < StackedConfig::Layers::GenericLayer
|
5
|
+
|
6
|
+
|
7
|
+
def self.executable_gem_config_root
|
8
|
+
return nil unless $PROGRAM_NAME
|
9
|
+
|
10
|
+
Gem.loaded_specs.each_pair do |name, spec|
|
11
|
+
executable_basename = File.basename($PROGRAM_NAME)
|
12
|
+
return spec.full_gem_path if spec.executables.include? executable_basename
|
13
|
+
end
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def executable_gem_config_root
|
18
|
+
self.class.executable_gem_config_root
|
19
|
+
end
|
20
|
+
|
21
|
+
def possible_sources
|
22
|
+
[
|
23
|
+
%w(##EXECUTABLE_GEM_CONFIG_ROOT## etc ##PROGRAM_NAME##.##EXTENSION##),
|
24
|
+
%w(##EXECUTABLE_GEM_CONFIG_ROOT## etc ##PROGRAM_NAME## config.##EXTENSION##),
|
25
|
+
%w(##EXECUTABLE_GEM_CONFIG_ROOT## etc ##PROGRAM_NAME## ##PROGRAM_NAME##.##EXTENSION##),
|
26
|
+
%w(##EXECUTABLE_GEM_CONFIG_ROOT## config ##PROGRAM_NAME##.##EXTENSION##),
|
27
|
+
%w(##EXECUTABLE_GEM_CONFIG_ROOT## config ##PROGRAM_NAME## config.##EXTENSION##),
|
28
|
+
%w(##EXECUTABLE_GEM_CONFIG_ROOT## config ##PROGRAM_NAME## ##PROGRAM_NAME##.##EXTENSION##)
|
29
|
+
]
|
30
|
+
end
|
31
|
+
|
32
|
+
def perform_substitutions path_part
|
33
|
+
return nil unless executable_gem_config_root
|
34
|
+
res = path_part.dup
|
35
|
+
res.gsub! '##EXECUTABLE_GEM_CONFIG_ROOT##', executable_gem_config_root
|
36
|
+
exec_name = manager.nil? ? StackedConfig::Orchestrator.default_config_file_base_name : manager.config_file_base_name
|
37
|
+
res.gsub! '##PROGRAM_NAME##', exec_name
|
38
|
+
res
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -2,17 +2,48 @@ module StackedConfig
|
|
2
2
|
module Layers
|
3
3
|
|
4
4
|
class GemLayer < StackedConfig::Layers::GenericLayer
|
5
|
+
|
6
|
+
attr_reader :gem_name
|
7
|
+
|
8
|
+
def self.gem_config_root(gem_name)
|
9
|
+
return nil unless gem_name
|
10
|
+
Gem.loaded_specs.each_pair do |name, spec|
|
11
|
+
return spec.full_gem_path if name == gem_name
|
12
|
+
end
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def gem_config_root
|
17
|
+
self.class.gem_config_root gem_name
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def gem_name=(gem_name)
|
22
|
+
@gem_name = gem_name.to_s
|
23
|
+
rescan
|
24
|
+
reload
|
25
|
+
end
|
26
|
+
|
5
27
|
def possible_sources
|
6
28
|
[
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
29
|
+
%w(##GEM_CONFIG_ROOT## etc ##GEM_NAME##.##EXTENSION##),
|
30
|
+
%w(##GEM_CONFIG_ROOT## etc ##GEM_NAME## config.##EXTENSION##),
|
31
|
+
%w(##GEM_CONFIG_ROOT## etc ##GEM_NAME## ##GEM_NAME##.##EXTENSION##),
|
32
|
+
%w(##GEM_CONFIG_ROOT## config ##GEM_NAME##.##EXTENSION##),
|
33
|
+
%w(##GEM_CONFIG_ROOT## config ##GEM_NAME## config.##EXTENSION##),
|
34
|
+
%w(##GEM_CONFIG_ROOT## config ##GEM_NAME## ##GEM_NAME##.##EXTENSION##)
|
13
35
|
]
|
14
36
|
end
|
15
37
|
|
38
|
+
def perform_substitutions path_part
|
39
|
+
return nil unless gem_config_root
|
40
|
+
res = path_part.dup
|
41
|
+
res.gsub! '##GEM_CONFIG_ROOT##', gem_config_root
|
42
|
+
res.gsub! '##GEM_NAME##', gem_name if self.respond_to? :gem_name
|
43
|
+
res
|
44
|
+
end
|
45
|
+
|
46
|
+
|
16
47
|
end
|
17
48
|
|
18
49
|
end
|
@@ -13,6 +13,49 @@ module StackedConfig
|
|
13
13
|
rescan
|
14
14
|
end
|
15
15
|
|
16
|
+
def possible_config_files(places=possible_sources)
|
17
|
+
result = {}
|
18
|
+
already_found = false
|
19
|
+
browse_files(places) do |file|
|
20
|
+
exists = File.readable?(file)
|
21
|
+
used = false
|
22
|
+
already_found = used = true if exists and not already_found
|
23
|
+
result[file] = {
|
24
|
+
exists: exists,
|
25
|
+
used: used,
|
26
|
+
layer: [name]
|
27
|
+
}
|
28
|
+
end
|
29
|
+
result
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def set_config_file(places)
|
35
|
+
@file_name = nil
|
36
|
+
browse_files(places) do |file|
|
37
|
+
if File.readable? file
|
38
|
+
@file_name = file
|
39
|
+
return @file_name
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def browse_files(places, &block)
|
45
|
+
places.each do |path_array|
|
46
|
+
begin
|
47
|
+
potential_config_file = File.join(path_array.map { |path_part| perform_substitutions path_part })
|
48
|
+
rescue
|
49
|
+
# do nothing
|
50
|
+
end
|
51
|
+
return unless potential_config_file
|
52
|
+
EXTENSIONS.each do |extension|
|
53
|
+
file = potential_config_file.gsub '##EXTENSION##', extension
|
54
|
+
yield file
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
16
59
|
end
|
17
60
|
|
18
61
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module StackedConfig
|
2
2
|
module Layers
|
3
3
|
|
4
|
-
class GlobalLayer < StackedConfig::Layers::
|
4
|
+
class GlobalLayer < StackedConfig::Layers::SystemLayer
|
5
5
|
def possible_sources
|
6
6
|
[
|
7
7
|
['##SYSTEM_CONFIG_ROOT##', '##PROGRAM_NAME##.##EXTENSION##' ],
|
@@ -10,7 +10,19 @@ module StackedConfig
|
|
10
10
|
]
|
11
11
|
end
|
12
12
|
|
13
|
+
def perform_substitutions(path_part)
|
14
|
+
res = path_part.dup
|
15
|
+
res.gsub! '##SYSTEM_CONFIG_ROOT##', system_config_root
|
16
|
+
|
17
|
+
exec_name = manager.nil? ? StackedConfig::Orchestrator.default_config_file_base_name : manager.config_file_base_name
|
18
|
+
res.gsub! '##PROGRAM_NAME##', exec_name
|
19
|
+
|
20
|
+
res
|
21
|
+
end
|
22
|
+
|
13
23
|
end
|
14
24
|
|
25
|
+
|
26
|
+
|
15
27
|
end
|
16
28
|
end
|
@@ -2,6 +2,21 @@ module StackedConfig
|
|
2
2
|
module Layers
|
3
3
|
|
4
4
|
class SystemLayer < StackedConfig::Layers::GenericLayer
|
5
|
+
|
6
|
+
SYSTEM_CONFIG_ROOT = {
|
7
|
+
windows: [File.join(ENV['systemRoot'] || '', 'Config')],
|
8
|
+
unix: '/etc'
|
9
|
+
}
|
10
|
+
|
11
|
+
def self.system_config_root
|
12
|
+
SYSTEM_CONFIG_ROOT[os_flavour]
|
13
|
+
end
|
14
|
+
|
15
|
+
def system_config_root
|
16
|
+
self.class.system_config_root
|
17
|
+
end
|
18
|
+
|
19
|
+
|
5
20
|
def possible_sources
|
6
21
|
[
|
7
22
|
['##SYSTEM_CONFIG_ROOT##', 'stacked_config.##EXTENSION##' ],
|
@@ -9,6 +24,13 @@ module StackedConfig
|
|
9
24
|
]
|
10
25
|
end
|
11
26
|
|
27
|
+
def perform_substitutions path_part
|
28
|
+
res = path_part.dup
|
29
|
+
res.gsub! '##SYSTEM_CONFIG_ROOT##', system_config_root
|
30
|
+
res
|
31
|
+
end
|
32
|
+
|
33
|
+
|
12
34
|
end
|
13
35
|
|
14
36
|
end
|
@@ -3,6 +3,16 @@ module StackedConfig
|
|
3
3
|
|
4
4
|
class UserLayer < StackedConfig::Layers::GenericLayer
|
5
5
|
|
6
|
+
|
7
|
+
def self.user_config_root
|
8
|
+
Dir.home
|
9
|
+
end
|
10
|
+
|
11
|
+
def user_config_root
|
12
|
+
self.class.user_config_root
|
13
|
+
end
|
14
|
+
|
15
|
+
|
6
16
|
def possible_sources
|
7
17
|
[
|
8
18
|
['##USER_CONFIG_ROOT##', '.##PROGRAM_NAME##.##EXTENSION##' ],
|
@@ -14,6 +24,16 @@ module StackedConfig
|
|
14
24
|
]
|
15
25
|
end
|
16
26
|
|
27
|
+
def perform_substitutions path_part
|
28
|
+
res = path_part.dup
|
29
|
+
res.gsub! '##USER_CONFIG_ROOT##', user_config_root
|
30
|
+
|
31
|
+
exec_name = manager.nil? ? StackedConfig::Orchestrator.default_config_file_base_name : manager.config_file_base_name
|
32
|
+
res.gsub! '##PROGRAM_NAME##', exec_name
|
33
|
+
|
34
|
+
res
|
35
|
+
end
|
36
|
+
|
17
37
|
end
|
18
38
|
|
19
39
|
end
|
@@ -3,7 +3,7 @@ module StackedConfig
|
|
3
3
|
|
4
4
|
include StackedConfig::ProgramDescriptionHelper
|
5
5
|
|
6
|
-
attr_reader :system_layer, :global_layer, :
|
6
|
+
attr_reader :system_layer, :global_layer, :executable_gem_layer, :user_layer, :env_layer,
|
7
7
|
:command_line_layer, :provided_config_file_layer
|
8
8
|
|
9
9
|
def initialize
|
@@ -19,13 +19,22 @@ module StackedConfig
|
|
19
19
|
File.basename($PROGRAM_NAME).gsub /\.[^\.]+$/, ''
|
20
20
|
end
|
21
21
|
|
22
|
-
def include_env_layer(filter = nil, priority =
|
22
|
+
def include_env_layer(filter = nil, priority = 70)
|
23
23
|
@env_layer = StackedConfig::Layers::EnvLayer.new filter
|
24
24
|
env_layer.name = 'Environment variables level'
|
25
25
|
env_layer.priority = priority
|
26
26
|
self << env_layer
|
27
27
|
end
|
28
28
|
|
29
|
+
def include_gem_layer_for(gem_name, priority = 30)
|
30
|
+
gem_layer = StackedConfig::Layers::GemLayer.new
|
31
|
+
gem_layer.gem_name = gem_name
|
32
|
+
raise "No config found in gem #{gem_name}" if gem_layer.file_name.nil?
|
33
|
+
gem_layer.name = "#{gem_name} Gem configuration level"
|
34
|
+
gem_layer.priority = priority
|
35
|
+
self << gem_layer
|
36
|
+
end
|
37
|
+
|
29
38
|
private
|
30
39
|
|
31
40
|
def setup_layers
|
@@ -35,17 +44,17 @@ module StackedConfig
|
|
35
44
|
# The system level
|
36
45
|
@system_layer = setup_layer StackedConfig::Layers::SystemLayer, 'System-wide configuration level', 10
|
37
46
|
|
38
|
-
# The gem level
|
39
|
-
@
|
47
|
+
# The executable gem level
|
48
|
+
@executable_gem_layer = setup_layer StackedConfig::Layers::ExecutableGemLayer, 'Gem associated to the executable running configuration level', 20
|
40
49
|
|
41
50
|
# The global level
|
42
|
-
@global_layer = setup_layer StackedConfig::Layers::GlobalLayer, 'Global configuration level',
|
51
|
+
@global_layer = setup_layer StackedConfig::Layers::GlobalLayer, 'Global configuration level', 40
|
43
52
|
|
44
53
|
# The user level
|
45
|
-
@user_layer = setup_layer StackedConfig::Layers::UserLayer, 'User configuration level',
|
54
|
+
@user_layer = setup_layer StackedConfig::Layers::UserLayer, 'User configuration level', 50
|
46
55
|
|
47
56
|
# The specifically provided config file level
|
48
|
-
@provided_config_file_layer = setup_layer StackedConfig::Layers::ProvidedConfigFileLayer, 'Specific config file configuration level',
|
57
|
+
@provided_config_file_layer = setup_layer StackedConfig::Layers::ProvidedConfigFileLayer, 'Specific config file configuration level', 60
|
49
58
|
|
50
59
|
# The layer to write something
|
51
60
|
override_layer = setup_layer SuperStack::Layer, 'Overridden configuration level', 1000
|
@@ -64,6 +64,16 @@ module StackedConfig
|
|
64
64
|
info.join "\n"
|
65
65
|
end
|
66
66
|
|
67
|
+
def detailed_config_files_info
|
68
|
+
merger = SuperStack::Manager.new
|
69
|
+
merger.merge_policy = SuperStack::MergePolicies::FullMergePolicy
|
70
|
+
layers.values.each do |layer|
|
71
|
+
merger << layer.possible_config_files if layer.respond_to? :possible_config_files
|
72
|
+
end
|
73
|
+
merger[]
|
74
|
+
end
|
75
|
+
|
76
|
+
|
67
77
|
def command_line_help
|
68
78
|
command_line_layer.help
|
69
79
|
end
|
@@ -7,97 +7,38 @@ module StackedConfig
|
|
7
7
|
}
|
8
8
|
DEFAULT_OS_FLAVOUR = :unix
|
9
9
|
|
10
|
-
SYSTEM_CONFIG_ROOT = {
|
11
|
-
windows: [File.join(ENV['systemRoot'] || '', 'Config')],
|
12
|
-
unix: '/etc'
|
13
|
-
}
|
14
10
|
|
15
11
|
EXTENSIONS = %w(conf CONF cfg CFG yml YML yaml YAML)
|
16
12
|
|
17
|
-
def self.
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.supported_oses
|
22
|
-
OS_FLAVOURS.values.sort.uniq
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.system_config_root
|
26
|
-
SYSTEM_CONFIG_ROOT[os_flavour]
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.user_config_root
|
30
|
-
Dir.home
|
13
|
+
def self.included(base)
|
14
|
+
base.extend ClassMethods
|
31
15
|
end
|
32
16
|
|
33
|
-
|
34
|
-
|
17
|
+
module ClassMethods
|
18
|
+
def os_flavour
|
19
|
+
StackedConfig::SourceHelper.os_flavour
|
20
|
+
end
|
35
21
|
|
36
|
-
|
37
|
-
|
38
|
-
return spec.full_gem_path if spec.executables.include? executable_basename
|
22
|
+
def supported_oses
|
23
|
+
StackedConfig::SourceHelper.supported_oses
|
39
24
|
end
|
40
|
-
nil
|
41
25
|
end
|
42
26
|
|
43
|
-
def
|
44
|
-
|
27
|
+
def self.os_flavour
|
28
|
+
OS_FLAVOURS[RbConfig::CONFIG['target_os'].to_sym] || DEFAULT_OS_FLAVOUR
|
45
29
|
end
|
46
30
|
|
47
|
-
def supported_oses
|
48
|
-
|
31
|
+
def self.supported_oses
|
32
|
+
OS_FLAVOURS.values.sort.uniq
|
49
33
|
end
|
50
34
|
|
51
35
|
def os_flavour
|
52
|
-
@os_flavour ||=
|
53
|
-
end
|
54
|
-
|
55
|
-
def system_config_root
|
56
|
-
StackedConfig::SourceHelper.system_config_root
|
57
|
-
end
|
58
|
-
|
59
|
-
def user_config_root
|
60
|
-
StackedConfig::SourceHelper.user_config_root
|
61
|
-
end
|
62
|
-
|
63
|
-
def set_config_file(places)
|
64
|
-
@file_name = nil
|
65
|
-
places.each do |path_array|
|
66
|
-
# Perform path substitutions
|
67
|
-
begin
|
68
|
-
potential_config_file = File.join(path_array.map { |path_part| perform_substitutions path_part })
|
69
|
-
rescue
|
70
|
-
#do nothing
|
71
|
-
end
|
72
|
-
return unless potential_config_file
|
73
|
-
# Try to find config file with extension
|
74
|
-
EXTENSIONS.each do |extension|
|
75
|
-
file = potential_config_file.gsub '##EXTENSION##', extension
|
76
|
-
if File.readable? file
|
77
|
-
@file_name = file
|
78
|
-
return @file_name
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
36
|
+
@os_flavour ||= self.class.os_flavour
|
82
37
|
end
|
83
38
|
|
84
|
-
|
85
|
-
|
86
|
-
def perform_substitutions path_part
|
87
|
-
res = path_part.dup
|
88
|
-
res.gsub! '##SYSTEM_CONFIG_ROOT##', system_config_root
|
89
|
-
res.gsub! '##USER_CONFIG_ROOT##', user_config_root
|
90
|
-
|
91
|
-
exec_name = manager.nil? ? StackedConfig::Orchestrator.default_config_file_base_name : manager.config_file_base_name
|
92
|
-
res.gsub! '##PROGRAM_NAME##', exec_name
|
93
|
-
if res =~ /##GEM_CONFIG_ROOT##/
|
94
|
-
return nil unless gem_config_root
|
95
|
-
res.gsub! '##GEM_CONFIG_ROOT##', gem_config_root
|
96
|
-
end
|
97
|
-
|
98
|
-
res
|
39
|
+
def supported_oses
|
40
|
+
self.class.supported_oses
|
99
41
|
end
|
100
42
|
|
101
|
-
|
102
43
|
end
|
103
44
|
end
|
data/lib/stacked_config.rb
CHANGED
@@ -6,6 +6,7 @@ require 'stacked_config/source_helper'
|
|
6
6
|
require 'stacked_config/program_description_helper'
|
7
7
|
require 'stacked_config/layers/generic_layer'
|
8
8
|
require 'stacked_config/layers/system_layer'
|
9
|
+
require 'stacked_config/layers/executable_gem_layer'
|
9
10
|
require 'stacked_config/layers/gem_layer'
|
10
11
|
require 'stacked_config/layers/global_layer'
|
11
12
|
require 'stacked_config/layers/user_layer'
|
data/spec/env_layer_spec.rb
CHANGED
@@ -46,6 +46,15 @@ describe StackedConfig::Layers::EnvLayer do
|
|
46
46
|
expect(layer.keys.length == 1).to be_truthy
|
47
47
|
end
|
48
48
|
|
49
|
+
[NIL_FILTER, STRING_FILTER, ARRAY_FILTER, REGEXP_FILTER].each do |filter|
|
50
|
+
it "should be the same to provide a #{filter.class} filter to the constructor or afterwards" do
|
51
|
+
layer1 = StackedConfig::Layers::EnvLayer.new(filter)
|
52
|
+
layer2 = StackedConfig::Layers::EnvLayer.new
|
53
|
+
layer2.filter = filter
|
54
|
+
expect(layer1).to eq layer2
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
49
58
|
end
|
50
59
|
|
51
|
-
end
|
60
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe StackedConfig::Layers::ExecutableGemLayer do
|
5
|
+
# subject is a modified ExecutableGemLayer to redirect executable_gem_config_root to the test directory
|
6
|
+
subject {
|
7
|
+
s = StackedConfig::Layers::ExecutableGemLayer.new
|
8
|
+
gem_path = File.expand_path '../..', __FILE__
|
9
|
+
allow(s).to receive(:executable_gem_config_root) {File.join(gem_path, 'test', 'tstgem') }
|
10
|
+
s.rescan
|
11
|
+
s
|
12
|
+
}
|
13
|
+
|
14
|
+
it 'should provide an executable gem config root' do
|
15
|
+
expect(subject.executable_gem_config_root).to_not be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should return the path of the first matching config file it found' do
|
19
|
+
expect(subject.file_name).not_to be_nil
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
end
|
data/spec/gem_layer_spec.rb
CHANGED
@@ -2,15 +2,19 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
|
4
4
|
describe StackedConfig::Layers::GemLayer do
|
5
|
-
# subject is a modified
|
5
|
+
# subject is a modified GemLayer to redirect gem_config_root to the test directory
|
6
6
|
subject {
|
7
7
|
s = StackedConfig::Layers::GemLayer.new
|
8
8
|
gem_path = File.expand_path '../..', __FILE__
|
9
9
|
allow(s).to receive(:gem_config_root) {File.join(gem_path, 'test', 'tstgem') }
|
10
|
-
s.
|
10
|
+
s.gem_name = 'tstgem'
|
11
11
|
s
|
12
12
|
}
|
13
13
|
|
14
|
+
it 'should provide a gem config root' do
|
15
|
+
expect(subject.gem_config_root).to_not be_nil
|
16
|
+
end
|
17
|
+
|
14
18
|
it 'should return the path of the first matching config file it found' do
|
15
19
|
expect(subject.file_name).not_to be_nil
|
16
20
|
end
|
data/spec/global_layer_spec.rb
CHANGED
@@ -14,6 +14,10 @@ describe StackedConfig::Layers::GlobalLayer do
|
|
14
14
|
s
|
15
15
|
}
|
16
16
|
|
17
|
+
it 'should provide a system config root' do
|
18
|
+
expect(subject.system_config_root).to_not be_nil
|
19
|
+
end
|
20
|
+
|
17
21
|
it 'should return the path of the first matching config file it found' do
|
18
22
|
expect(subject.file_name).not_to be_nil
|
19
23
|
end
|
@@ -25,9 +29,9 @@ describe StackedConfig::Layers::GlobalLayer do
|
|
25
29
|
end
|
26
30
|
|
27
31
|
it 'should enable to load the file' do
|
28
|
-
expect(subject[
|
32
|
+
expect(subject['an_array']).to be_nil
|
29
33
|
subject.load
|
30
|
-
expect(subject[
|
34
|
+
expect(subject['an_array']).to be_an Array
|
31
35
|
end
|
32
36
|
|
33
37
|
|
data/spec/orchestrator_spec.rb
CHANGED
@@ -7,13 +7,13 @@ describe StackedConfig::Orchestrator do
|
|
7
7
|
# Patching SourceHelper to find test config files in this gem test directory instead of from the system.
|
8
8
|
os = StackedConfig::SourceHelper.os_flavour
|
9
9
|
gem_path = File.expand_path '../..', __FILE__
|
10
|
-
altered_sys_conf_root = File.join gem_path, 'test', os.to_s, StackedConfig::
|
10
|
+
altered_sys_conf_root = File.join gem_path, 'test', os.to_s, StackedConfig::Layers::SystemLayer::SYSTEM_CONFIG_ROOT[os]
|
11
11
|
altered_user_conf_root = File.join gem_path, 'test', 'user'
|
12
12
|
altered_gem_conf_root = File.join(gem_path, 'test', 'tstgem')
|
13
13
|
|
14
|
-
allow(StackedConfig::
|
15
|
-
allow(StackedConfig::
|
16
|
-
allow(StackedConfig::
|
14
|
+
allow(StackedConfig::Layers::SystemLayer).to receive(:system_config_root) { altered_sys_conf_root }
|
15
|
+
allow(StackedConfig::Layers::UserLayer).to receive(:user_config_root) { altered_user_conf_root }
|
16
|
+
allow(StackedConfig::Layers::ExecutableGemLayer).to receive(:executable_gem_config_root) { altered_gem_conf_root }
|
17
17
|
|
18
18
|
StackedConfig::Orchestrator.new
|
19
19
|
}
|
@@ -53,8 +53,8 @@ describe StackedConfig::Orchestrator do
|
|
53
53
|
expect(subject.system_layer).to be subject.to_a.first
|
54
54
|
end
|
55
55
|
|
56
|
-
it 'should have the gem layer evaluated in second' do
|
57
|
-
expect(subject.
|
56
|
+
it 'should have the executable gem layer evaluated in second' do
|
57
|
+
expect(subject.executable_gem_layer).to be subject.to_a[1]
|
58
58
|
end
|
59
59
|
|
60
60
|
it 'should have the global layer evaluated in third' do
|
@@ -130,5 +130,28 @@ describe StackedConfig::Orchestrator do
|
|
130
130
|
|
131
131
|
end
|
132
132
|
|
133
|
+
context 'when adding a gem config in the config' do
|
134
|
+
|
135
|
+
it 'should insert the new layer with a default priority of 30' do
|
136
|
+
gem_path = File.expand_path '../..', __FILE__
|
137
|
+
allow(StackedConfig::Layers::GemLayer).to receive(:gem_config_root) do |gem_name|
|
138
|
+
File.join(gem_path, 'test', gem_name.to_s)
|
139
|
+
end
|
140
|
+
expect {subject.include_gem_layer_for :tstgem}.not_to raise_error
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should give info about where files are searched' do
|
146
|
+
info = subject.detailed_config_files_info
|
147
|
+
expect(info).to be_a Hash
|
148
|
+
found_files = info.keys.map { |file| File.readable?(file) ? file : nil}.compact
|
149
|
+
expect(found_files.length).to be 4
|
150
|
+
found_files.each do |file|
|
151
|
+
expect(info[file][:exists]).to be_truthy
|
152
|
+
expect(info[file][:used]).to be_truthy
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
133
156
|
|
134
157
|
end
|
data/spec/source_helper_spec.rb
CHANGED
@@ -3,24 +3,14 @@ require 'spec_helper'
|
|
3
3
|
|
4
4
|
describe StackedConfig::SourceHelper do
|
5
5
|
|
6
|
-
subject {
|
7
|
-
s = Object.new
|
8
|
-
s.extend StackedConfig::SourceHelper
|
9
|
-
s
|
10
|
-
}
|
6
|
+
subject {StackedConfig::SourceHelper }
|
11
7
|
|
12
8
|
it 'should provide an OS flavour' do
|
13
9
|
expect(subject.os_flavour).to_not be_nil
|
10
|
+
# s = Object.new
|
11
|
+
# s.extend subject
|
12
|
+
# expect(s.os_flavour).to_not be_nil
|
14
13
|
end
|
15
14
|
|
16
|
-
it 'should provide a system config root' do
|
17
|
-
expect(subject.system_config_root).to_not be_nil
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'should provide a user config root' do
|
21
|
-
expect(subject.user_config_root).to_not be_nil
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
15
|
end
|
26
16
|
|
data/spec/system_layer_spec.rb
CHANGED
@@ -14,6 +14,11 @@ describe StackedConfig::Layers::SystemLayer do
|
|
14
14
|
s
|
15
15
|
}
|
16
16
|
|
17
|
+
it 'should provide a system config root' do
|
18
|
+
expect(subject.system_config_root).to_not be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
|
17
22
|
it 'should return the path of the first matching config file it found' do
|
18
23
|
expect(subject.file_name).not_to be_nil
|
19
24
|
end
|
@@ -25,11 +30,12 @@ describe StackedConfig::Layers::SystemLayer do
|
|
25
30
|
end
|
26
31
|
|
27
32
|
it 'should enable to load the file' do
|
28
|
-
expect(subject[
|
33
|
+
expect(subject['stacked_config_copyright']).to be_nil
|
29
34
|
subject.load
|
30
|
-
expect(subject[
|
35
|
+
expect(subject['stacked_config_copyright']).not_to be_nil
|
31
36
|
end
|
32
37
|
|
33
38
|
|
34
39
|
|
40
|
+
|
35
41
|
end
|
data/spec/user_layer_spec.rb
CHANGED
@@ -13,6 +13,10 @@ describe StackedConfig::Layers::UserLayer do
|
|
13
13
|
s
|
14
14
|
}
|
15
15
|
|
16
|
+
it 'should provide a user config root' do
|
17
|
+
expect(subject.user_config_root).to_not be_nil
|
18
|
+
end
|
19
|
+
|
16
20
|
it 'should return the path of the first matching config file it found' do
|
17
21
|
expect(subject.file_name).not_to be_nil
|
18
22
|
end
|
@@ -24,9 +28,9 @@ describe StackedConfig::Layers::UserLayer do
|
|
24
28
|
end
|
25
29
|
|
26
30
|
it 'should enable to load the file' do
|
27
|
-
expect(subject[
|
31
|
+
expect(subject['an_array']).to be_nil
|
28
32
|
subject.load
|
29
|
-
expect(subject[
|
33
|
+
expect(subject['an_array']).to be_an Array
|
30
34
|
end
|
31
35
|
|
32
36
|
|
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.
|
26
|
+
spec.add_dependency 'super_stack', '~> 0.4'
|
27
27
|
spec.add_dependency 'slop', '~> 3.0'
|
28
28
|
|
29
29
|
end
|
@@ -4,8 +4,8 @@ require 'spec_helper'
|
|
4
4
|
describe 'Using stacked_config within a gem' do
|
5
5
|
|
6
6
|
it 'should detect we are in a gem' do
|
7
|
-
expect(StackedConfig::SourceHelper.
|
8
|
-
expect(StackedConfig::SourceHelper.
|
7
|
+
expect(StackedConfig::SourceHelper.executable_gem_config_root).to_not be_nil
|
8
|
+
expect(StackedConfig::SourceHelper.executable_gem_config_root =~ /rspec-core/).to be_truthy
|
9
9
|
end
|
10
10
|
|
11
11
|
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.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Laurent B.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -71,12 +71,6 @@ dependencies:
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ~>
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0.2'
|
76
|
-
- - '>='
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
version: 0.2.5
|
79
|
-
- - <
|
80
74
|
- !ruby/object:Gem::Version
|
81
75
|
version: '0.4'
|
82
76
|
type: :runtime
|
@@ -84,12 +78,6 @@ dependencies:
|
|
84
78
|
version_requirements: !ruby/object:Gem::Requirement
|
85
79
|
requirements:
|
86
80
|
- - ~>
|
87
|
-
- !ruby/object:Gem::Version
|
88
|
-
version: '0.2'
|
89
|
-
- - '>='
|
90
|
-
- !ruby/object:Gem::Version
|
91
|
-
version: 0.2.5
|
92
|
-
- - <
|
93
81
|
- !ruby/object:Gem::Version
|
94
82
|
version: '0.4'
|
95
83
|
- !ruby/object:Gem::Dependency
|
@@ -123,6 +111,7 @@ files:
|
|
123
111
|
- lib/stacked_config.rb
|
124
112
|
- lib/stacked_config/layers/command_line_layer.rb
|
125
113
|
- lib/stacked_config/layers/env_layer.rb
|
114
|
+
- lib/stacked_config/layers/executable_gem_layer.rb
|
126
115
|
- lib/stacked_config/layers/gem_layer.rb
|
127
116
|
- lib/stacked_config/layers/generic_layer.rb
|
128
117
|
- lib/stacked_config/layers/global_layer.rb
|
@@ -135,6 +124,7 @@ files:
|
|
135
124
|
- lib/stacked_config/version.rb
|
136
125
|
- spec/command_line_layer_spec.rb
|
137
126
|
- spec/env_layer_spec.rb
|
127
|
+
- spec/executable_gem_layer_spec.rb
|
138
128
|
- spec/gem_layer_spec.rb
|
139
129
|
- spec/global_layer_spec.rb
|
140
130
|
- spec/orchestrator_spec.rb
|
@@ -151,6 +141,7 @@ files:
|
|
151
141
|
- test/tstgem/README.md
|
152
142
|
- test/tstgem/Rakefile
|
153
143
|
- test/tstgem/config/rspec.yml
|
144
|
+
- test/tstgem/config/tstgem.yml
|
154
145
|
- test/tstgem/lib/tstgem.rb
|
155
146
|
- test/tstgem/lib/tstgem/version.rb
|
156
147
|
- test/tstgem/spec/global_spec.rb
|
@@ -180,13 +171,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
171
|
version: '0'
|
181
172
|
requirements: []
|
182
173
|
rubyforge_project:
|
183
|
-
rubygems_version: 2.0.
|
174
|
+
rubygems_version: 2.0.0
|
184
175
|
signing_key:
|
185
176
|
specification_version: 4
|
186
177
|
summary: Manages config files according to standard policy.
|
187
178
|
test_files:
|
188
179
|
- spec/command_line_layer_spec.rb
|
189
180
|
- spec/env_layer_spec.rb
|
181
|
+
- spec/executable_gem_layer_spec.rb
|
190
182
|
- spec/gem_layer_spec.rb
|
191
183
|
- spec/global_layer_spec.rb
|
192
184
|
- spec/orchestrator_spec.rb
|
@@ -202,6 +194,7 @@ test_files:
|
|
202
194
|
- test/tstgem/README.md
|
203
195
|
- test/tstgem/Rakefile
|
204
196
|
- test/tstgem/config/rspec.yml
|
197
|
+
- test/tstgem/config/tstgem.yml
|
205
198
|
- test/tstgem/lib/tstgem.rb
|
206
199
|
- test/tstgem/lib/tstgem/version.rb
|
207
200
|
- test/tstgem/spec/global_spec.rb
|