-
Notifications
You must be signed in to change notification settings - Fork 130
External Parameters #170
Description
Problems
The current configuration system could use some attention. These are the arguments for changing its behavior:
- Using
binding.evalto set constants is an unsafe Ruby practice. - Because the above method was chosen, there are potential variable, method or constant name collisions possible (you could name your configuration keys too similar to library methods or existing constants).
- There is no way to address the configuration as a whole, perhaps to implement environments, or turn all configuration keys into
Parameterdefaults. - The
-Doption is a powerful override for a specific key-value pair from the invocation, but right now it's interpreted as raw Ruby, and this should be guarded against.
Proposal
Implement an ExternalParameters configuration class. Move all of the logic of reading configuration files into this class, and remove the binding implementation. An instance of this class would be created for every time CloudFormation is invoked, and assigned to an easily recognizable method name. ExternalParameters would have all of the normal associated behavior of a regular Ruby hash. -D options on the command line turn into key-value entries in the configuration hash. Lastly, keep the old behavior around for a few releases with the option to disable/deprecate. In this case, the class would also assign the constants in the old way, to not break existing implementations.
Benefits
- Clarified and standardized approach to configuration. All configuration behavior and logic is clean, and implemented in one dedicated class.
- Access configuration as an entity, or separately as keys and values. Powerful and flexible.
- Since the behavior is encapsulated, end users can extend the behavior to implement additional functionality, namely environments.
- Configuration behaves as a
Hash, with all of the benefits and expectations associated. - A single class is more easily testable.
Example
Some examples of how this would work (for discussion points, not a final implementation):
Keep existing behavior
Given a yaml file config.yaml:
---
FOO: foo
BAR: barInvoking cfndsl template.rb -y config.yaml
# template.rb
# Both behaviors
CloudFormation do
ExternalParameters[:FOO] #=> 'foo'
FOO #=> 'foo'
endMore flexible access
Given a yaml file config.yaml:
---
# Allow users to use lowercase config entries, something previously difficult to do
foo: foo
bar: barInvoking cfndsl template.rb -y config.yaml
# template.rb
CloudFormation do
ExternalParameters[:foo] #=> 'foo'
# We could easily implement indifferent access if desired
ExternalParameters['foo'] #=> 'foo'
# You can also address all configuration at the same time
ExternalParameters.each_pair do |key, val|
# ...
end
endImplementing environments
Given a yaml file config.yaml:
---
production:
...
development:
...Invoking cfndsl template.rb -y config.yaml -D environment=production
# template.rb
CloudFormation do
environment = ExternalParameters[:environment]
config = ExternalParameters.fetch environment
# use only production config
# ...
end