-
Notifications
You must be signed in to change notification settings - Fork 102
Revamping the Configuration System
davetron5000 edited this page Mar 28, 2013
·
2 revisions
The configuration system is pretty janky at the moment:
The implementation is pretty hacky and inflexible. This is for me to noodle about what to do about it.
- Design so it can be tested outside of an aruba test - these tests are hard to set up and make exploring edge cases difficult.
- Make
initconfig
much fancier - possibly even allowing it to read/write particular options - Differentiate configuration name from all flags that set an option, e.g. standardize on the longest string for the given option (obviously, we should accept any flag name in the config, but only write one)
There's four main components to consider:
-
command - the command(s) that deal with the config (currently, the command
initconfig
) - location - where is the config file?
- runtime access - how do we get configured values?
- manipulation - how do we read/write the config file
If each of these were just classes, they could be tested much more simply (although overwriting the contents of global_options
and options
with configured values is tricky to test right now)
initconfig
made more sense in the world of single command apps, but even then it was a bit degenerate. I think the way forward is as follows:
-
initconfig
stays the same semantically, but gains more flexibility in where the config file can be located and stops writing duplicate values. Effectively, we make this useable, but deprecate it - A new command hierarchy, rooted at
config
(name changeable for backwards-compatibility):-
app config
- print the location of the config file to use -
app config init flag1=value1 flag2=value2
- init the config file with the given global values, much likeinitconfig
today. Main difference would be to not put app defaults into the config file and to specify only one key/value pair per flag. -
app config set flag=value
- set the config value for a global flag or switch -
app config set command flag=value
- set the config value for a command-specific flag -
app config set command subcommand flag=value
- you see where this is going -
app config delete flag=value
- remove value from config - New global option,
--config
that allows explicitly stating where the config file is
-
- Beef up the
config_file
option, or simply replace it with aconfiguration
concept:
# Set up a config file named .my_app.conf, and locate it first in the current directory
# where the app is being run - if it's not found, look in parent directories until we find one, if
# we don't, look in the user's home directory, finally looking in /etc/. Also add the
# --config-file global flag
config '.my_app.conf', :locate => [:cwd,:parents,:home,'/etc/'], :flag => true
# Set up a config file named .my_app.conf, which must be in the user's home directory.
# Do NOT set up the --config-file global flag - this is how config_file more or less works
config '.my_app.conf', :locate => :home, :flag => false
All of this should be "hookable" by the developer so that I can void things like "merged configs" or other oddities that some find useful. More pseudo code:
config '.my_app.conf',
:locate => [:cwd,:parents,'/etc/'],
:flag => "config-location",
:on_locate => lambda { |current_config,located_config|
# current_config is a possible-empty configuration object
# located_config is a parsed configuration object of whatever config file we just found
if located_config.path =~ /^\/etc/
false
else
current_config.merge(located_config)
true
end
},
:on_parse => lambda { |config_file_path
# config_file_path is the path to a located config file
# Return a Config created however you like - here we
# imagine using JSON
Config.from_hash(JSON.parse(config_file_path))
}