diff options
author | John Keiser <jkeiser@opscode.com> | 2013-12-03 00:42:25 -0800 |
---|---|---|
committer | John Keiser <jkeiser@opscode.com> | 2013-12-03 00:42:25 -0800 |
commit | ed46272e4dcf47a2600d28aee83b72f4ea656f0a (patch) | |
tree | 29c177831164e3847ebd72d99ba2124d6478bb35 | |
parent | 24eb243b25d75f8cbd1bf2955509bad6dfe3af5b (diff) | |
download | mixlib-config-ed46272e4dcf47a2600d28aee83b72f4ea656f0a.tar.gz |
Add ability to reopen config_context, add setter for config_context
-rw-r--r-- | lib/mixlib/config.rb | 51 | ||||
-rw-r--r-- | lib/mixlib/config/configurable.rb | 33 | ||||
-rw-r--r-- | lib/mixlib/config/reopened_config_context_with_configurable_error.rb | 24 | ||||
-rw-r--r-- | lib/mixlib/config/reopened_configurable_with_config_context_error.rb | 24 | ||||
-rw-r--r-- | spec/mixlib/config_spec.rb | 67 |
5 files changed, 166 insertions, 33 deletions
diff --git a/lib/mixlib/config.rb b/lib/mixlib/config.rb index 7b96fe0..7e48393 100644 --- a/lib/mixlib/config.rb +++ b/lib/mixlib/config.rb @@ -21,6 +21,8 @@ require 'mixlib/config/version' require 'mixlib/config/configurable' require 'mixlib/config/unknown_config_option_error' +require 'mixlib/config/reopened_config_context_with_configurable_error' +require 'mixlib/config/reopened_configurable_with_config_context_error' module Mixlib module Config @@ -152,9 +154,17 @@ module Mixlib # def save(include_defaults = false) result = self.configuration.dup - (self.configurables.keys - result.keys).each do |missing_default| - # Ask any configurables to save themselves into the result array - self.configurables[missing_default].save(self.configuration, result, include_defaults) + if include_defaults + (self.configurables.keys - result.keys).each do |missing_default| + # Ask any configurables to save themselves into the result array + if self.configurables[missing_default].has_default + result[missing_default] = self.configurables[missing_default].default + end + end + end + self.config_contexts.each_pair do |key, context| + context_result = context.save(include_defaults) + result[key] = context_result if context_result.size != 0 || include_defaults end result end @@ -184,7 +194,7 @@ module Mixlib hash.each do |key, value| if self.config_contexts.has_key?(key) # Grab the config context and let internal_get cache it if so desired - internal_get(key).restore(value) + self.config_contexts[key].restore(value) else self.configuration[key] = value end @@ -262,6 +272,9 @@ module Mixlib # The value of the config option. def configurable(symbol, &block) unless configurables[symbol] + if config_contexts.has_key?(symbol) + raise ReopenedConfigContextWithConfigurableError, "Cannot redefine config_context #{symbol} as a configurable value" + end configurables[symbol] = Configurable.new(symbol) define_attr_accessor_methods(symbol) end @@ -274,6 +287,8 @@ module Mixlib # Allows you to create a new config context where you can define new # options with default values. # + # This method allows you to open up the configurable more than once. + # # For example: # # config_context :server_info do @@ -285,16 +300,25 @@ module Mixlib # block<Block>: a block that will be run in the context of this new config # class. def config_context(symbol, &block) - context = Class.new - context.extend(::Mixlib::Config) - context.config_parent = self - config_contexts[symbol] = context + if configurables.has_key?(symbol) + raise ReopenedConfigurableWithConfigContextError, "Cannot redefine config value #{symbol} with a config context" + end + + if config_contexts.has_key?(symbol) + context = config_contexts[symbol] + else + context = Class.new + context.extend(::Mixlib::Config) + context.config_parent = self + config_contexts[symbol] = context + define_attr_accessor_methods(symbol) + end + if block context.instance_eval(&block) end - configurable(symbol).defaults_to(context).writes_value do |value| - raise "config context #{symbol} cannot be modified" - end + + context end NOT_PASSED = Object.new @@ -373,6 +397,7 @@ module Mixlib private # Internal dispatch setter for config values. + # # === Parameters # symbol<Symbol>:: Name of the method (variable setter) # value<Object>:: Value to be set in config hash @@ -380,6 +405,8 @@ module Mixlib def internal_set(symbol,value) if configurables.has_key?(symbol) configurables[symbol].set(self.configuration, value) + elsif config_contexts.has_key?(symbol) + config_contexts[symbol].restore(value) else if config_strict_mode == :warn Chef::Log.warn("Setting unsupported config value #{method_name}..") @@ -393,6 +420,8 @@ module Mixlib def internal_get(symbol) if configurables.has_key?(symbol) configurables[symbol].get(self.configuration) + elsif config_contexts.has_key?(symbol) + config_contexts[symbol] else if config_strict_mode == :warn Chef::Log.warn("Reading unsupported config value #{symbol}.") diff --git a/lib/mixlib/config/configurable.rb b/lib/mixlib/config/configurable.rb index 02081df..4a1bd46 100644 --- a/lib/mixlib/config/configurable.rb +++ b/lib/mixlib/config/configurable.rb @@ -21,15 +21,17 @@ module Mixlib class Configurable def initialize(symbol) @symbol = symbol - @default = nil + @default_block = nil @has_default = false @default_value = nil @writes_value = nil end + attr_reader :has_default + def defaults_to(default_value = nil, &block) @has_default = true - @default = block + @default_block = block @default_value = default_value self end @@ -42,11 +44,8 @@ module Mixlib def get(config) if config.has_key?(@symbol) config[@symbol] - elsif @default - @default.call - elsif @default_value.is_a?(::Mixlib::Config) - # Don't dup config_contexts - @default_value + elsif @default_block + @default_block.call else begin # Some things cannot be dup'd, and you won't know this till after the fact @@ -62,21 +61,11 @@ module Mixlib config[@symbol] = @writes_value ? @writes_value.call(value) : value end - # Sets the saved value into the result hash. Don't bother stashing defaults away or duping them. - def save(config, result, include_defaults) - if config.has_key?(@symbol) - result[@symbol] = config[@symbol] - elsif @default_value.is_a?(::Mixlib::Config) - saved_context = @default_value.save(include_defaults) - if saved_context != {} || include_defaults - result[@symbol] = saved_context - end - elsif include_defaults && @has_default - if @default - result[@symbol] = @default.call - else - result[@symbol] = @default_value - end + def default + if @default_block + @default_block.call + else + @default_value end end end diff --git a/lib/mixlib/config/reopened_config_context_with_configurable_error.rb b/lib/mixlib/config/reopened_config_context_with_configurable_error.rb new file mode 100644 index 0000000..3f3351f --- /dev/null +++ b/lib/mixlib/config/reopened_config_context_with_configurable_error.rb @@ -0,0 +1,24 @@ +# +# Author:: John Keiser (<jkeiser@opscode.com>) +# Copyright:: Copyright (c) 2013 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module Mixlib + module Config + class ReopenedConfigContextWithConfigurableError < StandardError + end + end +end diff --git a/lib/mixlib/config/reopened_configurable_with_config_context_error.rb b/lib/mixlib/config/reopened_configurable_with_config_context_error.rb new file mode 100644 index 0000000..47ffb70 --- /dev/null +++ b/lib/mixlib/config/reopened_configurable_with_config_context_error.rb @@ -0,0 +1,24 @@ +# +# Author:: John Keiser (<jkeiser@opscode.com>) +# Copyright:: Copyright (c) 2013 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module Mixlib + module Config + class ReopenedConfigurableWithConfigContextError < StandardError + end + end +end diff --git a/spec/mixlib/config_spec.rb b/spec/mixlib/config_spec.rb index b58dc97..b5c753b 100644 --- a/spec/mixlib/config_spec.rb +++ b/spec/mixlib/config_spec.rb @@ -734,6 +734,26 @@ describe Mixlib::Config do @klass.blah.x.should == 5 end + it "setting the entire context to a hash with default value overridden sets the value" do + @klass.blah = { :x => 10 } + @klass.blah.x.should == 10 + end + + it "setting the entire context to a hash sets non-default values" do + @klass.blah = { :y => 10 } + @klass.blah.x.should == 5 + @klass.blah.y.should == 10 + end + + it "setting the entire context to a hash deletes any non-default values and resets default values" do + @klass.blah.x = 10 + @klass.blah.y = 10 + @klass.blah = { :z => 10 } + @klass.blah.x.should == 5 + @klass.blah.y.should == nil + @klass.blah.z.should == 10 + end + it "after reset of the parent class, children are reset" do @klass.blah.x = 10 @klass.blah.x.should == 10 @@ -887,4 +907,51 @@ describe Mixlib::Config do lambda { StrictClass3.y = 10 }.should raise_error(Mixlib::Config::UnknownConfigOptionError) end end + + describe "When a config_context is opened twice" do + before :each do + @klass = Class.new + @klass.extend(::Mixlib::Config) + @klass.class_eval do + config_context(:blah) do + default :x, 10 + end + config_context(:blah) do + default :y, 20 + end + end + end + + it "Both config_context blocks are honored" do + @klass.blah.x == 10 + @klass.blah.y == 20 + end + end + + it "When a config_context is opened in place of a regular configurable, an error is raised" do + klass = Class.new + klass.extend(::Mixlib::Config) + lambda do + klass.class_eval do + default :blah, 10 + config_context(:blah) do + default :y, 20 + end + end + end.should raise_error(Mixlib::Config::ReopenedConfigurableWithConfigContextError) + end + + it "When a config_context is opened in place of a regular configurable, an error is raised" do + klass = Class.new + klass.extend(::Mixlib::Config) + lambda do + klass.class_eval do + config_context(:blah) do + default :y, 20 + end + default :blah, 10 + end + end.should raise_error(Mixlib::Config::ReopenedConfigContextWithConfigurableError) + end + end |