stacked_config 0.4.2 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|