summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaire McQuin <mcquin@users.noreply.github.com>2014-11-21 14:58:16 -0800
committerClaire McQuin <mcquin@users.noreply.github.com>2014-11-21 14:58:16 -0800
commitcae8e657151485bb427c01ad8e0d37625ae64c84 (patch)
treeb0a0ee41acfd84222b48092f485d026d828b07cd
parentcaad34bc0ff6297d04210075d8a67b52e97d42f2 (diff)
parentedbf71e853762915901526215dd0e11c47fe6882 (diff)
downloadchef-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.rb1
-rw-r--r--lib/chef/dsl.rb1
-rw-r--r--spec/data/cookbooks/audit/metadata.rb2
-rw-r--r--spec/data/cookbooks/audit/recipes/default.rb3
-rw-r--r--spec/data/cookbooks/audit/recipes/defined_outside_block.rb6
-rw-r--r--spec/data/cookbooks/audit/recipes/multiple_controls.rb11
-rw-r--r--spec/data/cookbooks/audit/recipes/serverspec_helpers.rb9
-rw-r--r--spec/data/cookbooks/audit/recipes/single_controls.rb5
-rw-r--r--spec/integration/solo/solo_spec.rb2
-rw-r--r--spec/unit/audit/duplication_spec.rb107
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