diff options
author | Claire McQuin <mcquin@users.noreply.github.com> | 2014-11-21 14:58:16 -0800 |
---|---|---|
committer | Claire McQuin <mcquin@users.noreply.github.com> | 2014-11-21 14:58:16 -0800 |
commit | cae8e657151485bb427c01ad8e0d37625ae64c84 (patch) | |
tree | b0a0ee41acfd84222b48092f485d026d828b07cd | |
parent | caad34bc0ff6297d04210075d8a67b52e97d42f2 (diff) | |
parent | edbf71e853762915901526215dd0e11c47fe6882 (diff) | |
download | chef-mcquin/controls_group_object.tar.gz |
Merge pull request #2436 from opscode/tball/audit-duplication-testmcquin/controls_group_object
Audit tests for `package` DSL duplication
-rw-r--r-- | lib/chef/audit/audit_event_proxy.rb | 1 | ||||
-rw-r--r-- | lib/chef/dsl.rb | 1 | ||||
-rw-r--r-- | spec/data/cookbooks/audit/metadata.rb | 2 | ||||
-rw-r--r-- | spec/data/cookbooks/audit/recipes/default.rb | 3 | ||||
-rw-r--r-- | spec/data/cookbooks/audit/recipes/defined_outside_block.rb | 6 | ||||
-rw-r--r-- | spec/data/cookbooks/audit/recipes/multiple_controls.rb | 11 | ||||
-rw-r--r-- | spec/data/cookbooks/audit/recipes/serverspec_helpers.rb | 9 | ||||
-rw-r--r-- | spec/data/cookbooks/audit/recipes/single_controls.rb | 5 | ||||
-rw-r--r-- | spec/integration/solo/solo_spec.rb | 2 | ||||
-rw-r--r-- | spec/unit/audit/duplication_spec.rb | 107 |
10 files changed, 146 insertions, 1 deletions
diff --git a/lib/chef/audit/audit_event_proxy.rb b/lib/chef/audit/audit_event_proxy.rb index 71d1e2aa50..6b66b70b6c 100644 --- a/lib/chef/audit/audit_event_proxy.rb +++ b/lib/chef/audit/audit_event_proxy.rb @@ -1,3 +1,4 @@ +require 'rspec' RSpec::Support.require_rspec_core "formatters/base_text_formatter" class Chef diff --git a/lib/chef/dsl.rb b/lib/chef/dsl.rb index 7717d99113..7ff605e466 100644 --- a/lib/chef/dsl.rb +++ b/lib/chef/dsl.rb @@ -4,3 +4,4 @@ require 'chef/dsl/data_query' require 'chef/dsl/include_recipe' require 'chef/dsl/include_attribute' require 'chef/dsl/registry_helper' +require 'chef/dsl/audit' diff --git a/spec/data/cookbooks/audit/metadata.rb b/spec/data/cookbooks/audit/metadata.rb new file mode 100644 index 0000000000..763c6f6675 --- /dev/null +++ b/spec/data/cookbooks/audit/metadata.rb @@ -0,0 +1,2 @@ +name "audit" +version "1.0.0" diff --git a/spec/data/cookbooks/audit/recipes/default.rb b/spec/data/cookbooks/audit/recipes/default.rb new file mode 100644 index 0000000000..66a6341d5f --- /dev/null +++ b/spec/data/cookbooks/audit/recipes/default.rb @@ -0,0 +1,3 @@ +# Inside a recipe self refers to a Recipe object, so it calls the correct #method_missing chain to find the +# package resource +package "foo1" diff --git a/spec/data/cookbooks/audit/recipes/defined_outside_block.rb b/spec/data/cookbooks/audit/recipes/defined_outside_block.rb new file mode 100644 index 0000000000..2f4245c8ee --- /dev/null +++ b/spec/data/cookbooks/audit/recipes/defined_outside_block.rb @@ -0,0 +1,6 @@ +controls "some more controls" do + control "foo5" +end + +# Even after seeing a `controls` block `control` should not work outside the block - even when running in rspec +control("foo4") diff --git a/spec/data/cookbooks/audit/recipes/multiple_controls.rb b/spec/data/cookbooks/audit/recipes/multiple_controls.rb new file mode 100644 index 0000000000..14538d9f65 --- /dev/null +++ b/spec/data/cookbooks/audit/recipes/multiple_controls.rb @@ -0,0 +1,11 @@ +controls "some controls" do + package "foo3" +end + +package "bar" + +controls "some more controls" do + package "baz" +end + +package "bang" diff --git a/spec/data/cookbooks/audit/recipes/serverspec_helpers.rb b/spec/data/cookbooks/audit/recipes/serverspec_helpers.rb new file mode 100644 index 0000000000..c82411eb9d --- /dev/null +++ b/spec/data/cookbooks/audit/recipes/serverspec_helpers.rb @@ -0,0 +1,9 @@ +# Serverspec helper `cgroup` should only be defined in controls block, not Chef::Recipe + +controls "cgroup controls" do + describe cgroup('group1') do + true + end +end + +cgroup('group2') diff --git a/spec/data/cookbooks/audit/recipes/single_controls.rb b/spec/data/cookbooks/audit/recipes/single_controls.rb new file mode 100644 index 0000000000..5bd8600326 --- /dev/null +++ b/spec/data/cookbooks/audit/recipes/single_controls.rb @@ -0,0 +1,5 @@ +# Inside a `controls` block, self refers to a subclass of RSpec::ExampleGroups so `package` calls the correct +# serverspec helper +controls "some controls" do + package "foo2" +end diff --git a/spec/integration/solo/solo_spec.rb b/spec/integration/solo/solo_spec.rb index 9500e7a1ca..cc9ba1abb2 100644 --- a/spec/integration/solo/solo_spec.rb +++ b/spec/integration/solo/solo_spec.rb @@ -92,7 +92,7 @@ EOM # We have a timeout protection here so that if due to some bug # run_lock gets stuck we can discover it. expect { - Timeout.timeout(1200) do + Timeout.timeout(120) do chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..") # Instantiate the first chef-solo run diff --git a/spec/unit/audit/duplication_spec.rb b/spec/unit/audit/duplication_spec.rb new file mode 100644 index 0000000000..78027a6bf7 --- /dev/null +++ b/spec/unit/audit/duplication_spec.rb @@ -0,0 +1,107 @@ +# +# Author:: Tyler Ball (<tball@getchef.com>) +# Copyright:: Copyright (c) 2014 Chef, 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. +# + +require 'spec_helper' +require 'chef/recipe' +require 'chef/audit/runner' + +describe "Duplicated `package` DSL in Chef and Serverspec" do + + # TODO (?) disable rspec global DSL - but do we want it enabled for OUR rspecs? No, because we always have a runner? + # TODO (?) disable serverspec global DSL + + let(:cookbook_repo) { File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "data", "cookbooks")) } + let(:audit_recipes) { File.join(cookbook_repo, "audit", "recipes") } + + let(:cookbook_loader) do + loader = Chef::CookbookLoader.new(cookbook_repo) + loader.load_cookbooks + loader + end + + let(:cookbook_collection) { Chef::CookbookCollection.new(cookbook_loader) } + + let(:node) do + Chef::Node.new.tap {|n| n.normal[:tags] = [] } + end + + let(:events) do + Chef::EventDispatch::Dispatcher.new + end + + let(:run_context) do + Chef::RunContext.new(node, cookbook_collection, events) + end + + let(:auditor) do + auditor = Chef::Audit::Runner.new(run_context) + allow(auditor).to receive(:configure_rspec).and_return(true) + allow(auditor).to receive(:do_run).and_return(true) + auditor + end + + it "Should call the Chef Recipe DSL in a Chef Recipe" do + # Chef::DSL::Recipe#method_missing calls #resource_for_node twice when looking up the Resource instance - once in + # #have_resource_class_for? and once in #declare_resource. Chef::DSL::Recipe#resource_class_for calls + # Chef::Resource#resource_for_node + expect(Chef::Resource).to receive(:resource_for_node).with(:package, instance_of(Chef::Node)).exactly(2).times.and_return(Chef::Resource::Package) + expect(Chef::Resource::Package).to receive(:new).with("foo1", run_context).and_call_original + + Chef::Recipe.new("audit", "default", run_context).from_file(File.join(audit_recipes, "default.rb")) + end + + it "Should call the Serverspec DSL in a `controls` block" do + expect(Chef::Resource).to_not receive(:resource_for_node) + # Waiting until here to require this because otherwise it complains that it hasn't been configured yet + # and configuration takes place in the `controls` method + require 'serverspec' + + Chef::Recipe.new("audit", "single_controls", run_context).from_file(File.join(audit_recipes, "single_controls.rb")) + end + + it "Should still use the recipe DSL outside of a controls block after a controls block has ran" do + expect(Serverspec::Type::Package).to receive(:new).with("foo3") + expect(Serverspec::Type::Package).to receive(:new).with("baz") + expect(Chef::Resource).to receive(:resource_for_node).with(:package, instance_of(Chef::Node)).exactly(4).times.and_return(Chef::Resource::Package) + expect(Chef::Resource::Package).to receive(:new).with("bar", run_context).and_call_original + expect(Chef::Resource::Package).to receive(:new).with("bang", run_context).and_call_original + + Chef::Recipe.new("audit", "multiple_controls", run_context).from_file(File.join(audit_recipes, "multiple_controls.rb")) + # Have to run the auditor because we have logic inside a `controls` block to test - that doesn't get evaluated + # until the auditor is ran + auditor.run + end + + it "Should not allow `control` or `__controls__` to be defined outside of a `controls` block" do + expect_any_instance_of(Chef::Recipe).to receive(:controls).with("some more controls").and_call_original + expect_any_instance_of(Chef::Recipe).to receive(:control).with("foo4").and_call_original + + expect { + Chef::Recipe.new("audit", "defined_outside_block", run_context).from_file(File.join(audit_recipes, "defined_outside_block.rb")) + }.to raise_error(NoMethodError, /No resource or method named `control'/) + end + + it "Should include serverspec specific matchers only inside `controls` block" do + # cgroup is a rspec matcher I'm assuming we won't define elsewhere + expect(Serverspec::Type::Cgroup).to receive(:new).with("group1").and_call_original + expect { + Chef::Recipe.new("audit", "serverspec_helpers", run_context).from_file(File.join(audit_recipes, "serverspec_helpers.rb")) + }.to raise_error(NoMethodError, /No resource or method named `cgroup' for `Chef::Recipe/) + auditor.run + end +end |