diff options
author | danielsdeleo <dan@opscode.com> | 2013-01-29 18:10:28 -0800 |
---|---|---|
committer | danielsdeleo <dan@opscode.com> | 2013-01-29 18:10:28 -0800 |
commit | afd031b09c90e373da3f64365b6406c3d0d48c2c (patch) | |
tree | 71cf184908b864caba51ea1214430d489917c560 | |
parent | 1f03cb4604b1944d20afd0faf292686fcb0f012b (diff) | |
parent | b4fbb9bd3a6aeae9d3ff218f877da1ade1bba101 (diff) | |
download | chef-afd031b09c90e373da3f64365b6406c3d0d48c2c.tar.gz |
Merge branch 'set-unless-fix'
-rw-r--r-- | lib/chef/node.rb | 5 | ||||
-rw-r--r-- | lib/chef/node/attribute.rb | 29 | ||||
-rw-r--r-- | spec/unit/node/attribute_spec.rb | 31 | ||||
-rw-r--r-- | spec/unit/node_spec.rb | 45 |
4 files changed, 110 insertions, 0 deletions
diff --git a/lib/chef/node.rb b/lib/chef/node.rb index 0caf6602fe..b301045b28 100644 --- a/lib/chef/node.rb +++ b/lib/chef/node.rb @@ -123,6 +123,7 @@ class Chef # Set a normal attribute of this node, but auto-vivify any Mashes that # might be missing def normal + attributes.set_unless_value_present = false attributes.normal end @@ -139,12 +140,14 @@ class Chef # Set a default of this node, but auto-vivify any Mashes that might # be missing def default + attributes.set_unless_value_present = false attributes.default end # Set a force default attribute. Intermediate mashes will be created by # auto-vivify if necessary. def default! + attributes.set_unless_value_present = false attributes.default! end @@ -158,12 +161,14 @@ class Chef # Set an override attribute of this node, but auto-vivify any Mashes that # might be missing def override + attributes.set_unless_value_present = false attributes.override end # Set a force override attribute. Intermediate mashes will be created by # auto-vivify if needed. def override! + attributes.set_unless_value_present = false attributes.override! end diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb index eb6a0372d5..a417406721 100644 --- a/lib/chef/node/attribute.rb +++ b/lib/chef/node/attribute.rb @@ -209,6 +209,34 @@ class Chef @combined_default = nil end + # Debug what's going on with an attribute. +args+ is a path spec to the + # attribute you're interested in. For example, to debug where the value + # of `node[:network][:default_interface]` is coming from, use: + # debug_value(:network, :default_interface). + # The return value is an Array of Arrays. The first element is + # `["set_unless_enabled?", Boolean]`, which describes whether the + # attribute collection is in "set_unless" mode. The rest of the Arrays + # are pairs of `["precedence_level", value]`, where precedence level is + # the component, such as role default, normal, etc. and value is the + # attribute value set at that precedence level. If there is no value at + # that precedence level, +value+ will be the symbol +:not_present+. + def debug_value(*args) + components = COMPONENTS.map do |component| + ivar = instance_variable_get(component) + value = args.inject(ivar) do |so_far, key| + if so_far == :not_present + :not_present + elsif so_far.has_key?(key) + so_far[key] + else + :not_present + end + end + [component.to_s.sub(/^@/,""), value] + end + [["set_unless_enabled?", @set_unless_present]] + components + end + # Enables or disables `||=`-like attribute setting. See, e.g., Node#set_unless def set_unless_value_present=(setting) @set_unless_present = setting @@ -220,6 +248,7 @@ class Chef @merged_attributes = nil @combined_default = nil @combined_override = nil + @set_unless_present = false end alias :reset :reset_cache diff --git a/spec/unit/node/attribute_spec.rb b/spec/unit/node/attribute_spec.rb index 435dc3230c..5aa563aedf 100644 --- a/spec/unit/node/attribute_spec.rb +++ b/spec/unit/node/attribute_spec.rb @@ -247,6 +247,37 @@ describe Chef::Node::Attribute do end + describe "when debugging attributes" do + before do + @attributes.default[:foo][:bar] = "default" + @attributes.env_default[:foo][:bar] = "env_default" + @attributes.role_default[:foo][:bar] = "role_default" + @attributes.force_default[:foo][:bar] = "force_default" + @attributes.normal[:foo][:bar] = "normal" + @attributes.override[:foo][:bar] = "override" + @attributes.role_override[:foo][:bar] = "role_override" + @attributes.env_override[:foo][:bar] = "env_override" + @attributes.force_override[:foo][:bar] = "force_override" + @attributes.automatic[:foo][:bar] = "automatic" + end + + it "gives the value at each level of precedence for a path spec" do + expected = [["set_unless_enabled?", false], + ["default", "default"], + ["env_default", "env_default"], + ["role_default", "role_default"], + ["force_default", "force_default"], + ["normal", "normal"], + ["override", "override"], + ["role_override", "role_override"], + ["env_override", "env_override"], + ["force_override", "force_override"], + ["automatic", "automatic"] + ] + @attributes.debug_value(:foo, :bar).should == expected + end + end + describe "when fetching values based on precedence" do before do @attributes.default["default"] = "cookbook default" diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb index d785f84c73..3d32902b94 100644 --- a/spec/unit/node_spec.rb +++ b/spec/unit/node_spec.rb @@ -177,6 +177,21 @@ describe Chef::Node do node[:snoopy][:is_a_puppy].should == true end + it "should allow you to set a value after a set_unless" do + # this tests for set_unless_present state bleeding between statements CHEF-3806 + node.set_unless[:snoopy][:is_a_puppy] = false + node.set[:snoopy][:is_a_puppy] = true + node[:snoopy][:is_a_puppy].should == true + end + + it "should let you set a value after a 'dangling' set_unless" do + # this tests for set_unless_present state bleeding between statements CHEF-3806 + node.set[:snoopy][:is_a_puppy] = "what" + node.set_unless[:snoopy][:is_a_puppy] + node.set[:snoopy][:is_a_puppy] = true + node[:snoopy][:is_a_puppy].should == true + end + it "auto-vivifies attributes created via method syntax" do node.set.fuu.bahrr.baz = "qux" node.fuu.bahrr.baz.should == "qux" @@ -201,6 +216,21 @@ describe Chef::Node do node[:snoopy][:is_a_puppy].should == true end + it "should allow you to set a value after a default_unless" do + # this tests for set_unless_present state bleeding between statements CHEF-3806 + node.default_unless[:snoopy][:is_a_puppy] = false + node.default[:snoopy][:is_a_puppy] = true + node[:snoopy][:is_a_puppy].should == true + end + + it "should allow you to set a value after a 'dangling' default_unless" do + # this tests for set_unless_present state bleeding between statements CHEF-3806 + node.default[:snoopy][:is_a_puppy] = "what" + node.default_unless[:snoopy][:is_a_puppy] + node.default[:snoopy][:is_a_puppy] = true + node[:snoopy][:is_a_puppy].should == true + end + it "auto-vivifies attributes created via method syntax" do node.default.fuu.bahrr.baz = "qux" node.fuu.bahrr.baz.should == "qux" @@ -231,6 +261,21 @@ describe Chef::Node do node[:snoopy][:is_a_puppy].should == true end + it "should allow you to set a value after an override_unless" do + # this tests for set_unless_present state bleeding between statements CHEF-3806 + node.override_unless[:snoopy][:is_a_puppy] = false + node.override[:snoopy][:is_a_puppy] = true + node[:snoopy][:is_a_puppy].should == true + end + + it "should allow you to set a value after a 'dangling' override_unless" do + # this tests for set_unless_present state bleeding between statements CHEF-3806 + node.override_unless[:snoopy][:is_a_puppy] = "what" + node.override_unless[:snoopy][:is_a_puppy] + node.override[:snoopy][:is_a_puppy] = true + node[:snoopy][:is_a_puppy].should == true + end + it "auto-vivifies attributes created via method syntax" do node.override.fuu.bahrr.baz = "qux" node.fuu.bahrr.baz.should == "qux" |