chefspec-chef 9.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +30 -0
- data/LICENSE +22 -0
- data/Rakefile +85 -0
- data/chefspec-chef.gemspec +30 -0
- data/lib/chefspec/api/core.rb +217 -0
- data/lib/chefspec/api/described.rb +53 -0
- data/lib/chefspec/api/do_nothing.rb +26 -0
- data/lib/chefspec/api/include_any_recipe.rb +24 -0
- data/lib/chefspec/api/include_recipe.rb +28 -0
- data/lib/chefspec/api/link.rb +28 -0
- data/lib/chefspec/api/notifications.rb +40 -0
- data/lib/chefspec/api/reboot.rb +14 -0
- data/lib/chefspec/api/render_file.rb +37 -0
- data/lib/chefspec/api/state_attrs.rb +30 -0
- data/lib/chefspec/api/stubs.rb +183 -0
- data/lib/chefspec/api/stubs_for.rb +139 -0
- data/lib/chefspec/api/subscriptions.rb +37 -0
- data/lib/chefspec/api/user.rb +230 -0
- data/lib/chefspec/api.rb +39 -0
- data/lib/chefspec/berkshelf.rb +63 -0
- data/lib/chefspec/cacher.rb +64 -0
- data/lib/chefspec/coverage/filters.rb +82 -0
- data/lib/chefspec/coverage.rb +247 -0
- data/lib/chefspec/deprecations.rb +46 -0
- data/lib/chefspec/errors.rb +48 -0
- data/lib/chefspec/expect_exception.rb +51 -0
- data/lib/chefspec/extensions/chef/client.rb +21 -0
- data/lib/chefspec/extensions/chef/conditional.rb +16 -0
- data/lib/chefspec/extensions/chef/cookbook/gem_installer.rb +33 -0
- data/lib/chefspec/extensions/chef/cookbook_loader.rb +14 -0
- data/lib/chefspec/extensions/chef/cookbook_uploader.rb +12 -0
- data/lib/chefspec/extensions/chef/data_query.rb +49 -0
- data/lib/chefspec/extensions/chef/lwrp_base.rb +29 -0
- data/lib/chefspec/extensions/chef/provider.rb +39 -0
- data/lib/chefspec/extensions/chef/resource/freebsd_package.rb +17 -0
- data/lib/chefspec/extensions/chef/resource.rb +188 -0
- data/lib/chefspec/extensions/chef/run_context/cookbook_compiler.rb +84 -0
- data/lib/chefspec/extensions/chef/securable.rb +19 -0
- data/lib/chefspec/extensions/ohai/system.rb +11 -0
- data/lib/chefspec/extensions.rb +21 -0
- data/lib/chefspec/file_cache_path_proxy.rb +15 -0
- data/lib/chefspec/formatter.rb +282 -0
- data/lib/chefspec/librarian.rb +51 -0
- data/lib/chefspec/matchers/do_nothing_matcher.rb +52 -0
- data/lib/chefspec/matchers/include_any_recipe_matcher.rb +51 -0
- data/lib/chefspec/matchers/include_recipe_matcher.rb +46 -0
- data/lib/chefspec/matchers/link_to_matcher.rb +37 -0
- data/lib/chefspec/matchers/notifications_matcher.rb +143 -0
- data/lib/chefspec/matchers/render_file_matcher.rb +140 -0
- data/lib/chefspec/matchers/resource_matcher.rb +175 -0
- data/lib/chefspec/matchers/state_attrs_matcher.rb +71 -0
- data/lib/chefspec/matchers/subscribes_matcher.rb +72 -0
- data/lib/chefspec/matchers.rb +13 -0
- data/lib/chefspec/mixins/normalize.rb +22 -0
- data/lib/chefspec/policyfile.rb +69 -0
- data/lib/chefspec/renderer.rb +145 -0
- data/lib/chefspec/rspec.rb +21 -0
- data/lib/chefspec/runner.rb +8 -0
- data/lib/chefspec/server.rb +4 -0
- data/lib/chefspec/server_methods.rb +173 -0
- data/lib/chefspec/server_runner.rb +76 -0
- data/lib/chefspec/solo_runner.rb +516 -0
- data/lib/chefspec/stubs/command_registry.rb +11 -0
- data/lib/chefspec/stubs/command_stub.rb +37 -0
- data/lib/chefspec/stubs/data_bag_item_registry.rb +13 -0
- data/lib/chefspec/stubs/data_bag_item_stub.rb +25 -0
- data/lib/chefspec/stubs/data_bag_registry.rb +13 -0
- data/lib/chefspec/stubs/data_bag_stub.rb +23 -0
- data/lib/chefspec/stubs/registry.rb +32 -0
- data/lib/chefspec/stubs/search_registry.rb +13 -0
- data/lib/chefspec/stubs/search_stub.rb +25 -0
- data/lib/chefspec/stubs/stub.rb +38 -0
- data/lib/chefspec/util.rb +58 -0
- data/lib/chefspec/version.rb +3 -0
- data/lib/chefspec/zero_server.rb +142 -0
- data/lib/chefspec.rb +75 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/hash.rb +35 -0
- data/spec/unit/cacher_spec.rb +70 -0
- data/spec/unit/coverage/filters_spec.rb +60 -0
- data/spec/unit/deprecations_spec.rb +52 -0
- data/spec/unit/errors_spec.rb +57 -0
- data/spec/unit/expect_exception_spec.rb +32 -0
- data/spec/unit/macros_spec.rb +119 -0
- data/spec/unit/matchers/do_nothing_matcher.rb +5 -0
- data/spec/unit/matchers/include_any_recipe_matcher_spec.rb +52 -0
- data/spec/unit/matchers/include_recipe_matcher_spec.rb +38 -0
- data/spec/unit/matchers/link_to_matcher_spec.rb +55 -0
- data/spec/unit/matchers/notifications_matcher_spec.rb +39 -0
- data/spec/unit/matchers/render_file_matcher_spec.rb +68 -0
- data/spec/unit/matchers/resource_matcher_spec.rb +5 -0
- data/spec/unit/matchers/state_attrs_matcher_spec.rb +68 -0
- data/spec/unit/matchers/subscribes_matcher_spec.rb +63 -0
- data/spec/unit/renderer_spec.rb +69 -0
- data/spec/unit/server_runner_spec.rb +28 -0
- data/spec/unit/solo_runner_spec.rb +171 -0
- data/spec/unit/stubs/command_registry_spec.rb +27 -0
- data/spec/unit/stubs/command_stub_spec.rb +61 -0
- data/spec/unit/stubs/data_bag_item_registry_spec.rb +39 -0
- data/spec/unit/stubs/data_bag_item_stub_spec.rb +36 -0
- data/spec/unit/stubs/data_bag_registry_spec.rb +39 -0
- data/spec/unit/stubs/data_bag_stub_spec.rb +35 -0
- data/spec/unit/stubs/registry_spec.rb +29 -0
- data/spec/unit/stubs/search_registry_spec.rb +39 -0
- data/spec/unit/stubs/search_stub_spec.rb +36 -0
- data/spec/unit/stubs/stub_spec.rb +64 -0
- data/templates/coverage/human.erb +22 -0
- data/templates/coverage/json.erb +8 -0
- data/templates/coverage/table.erb +14 -0
- data/templates/errors/cookbook_path_not_found.erb +3 -0
- data/templates/errors/erb_template_parse_error.erb +5 -0
- data/templates/errors/gem_load_error.erb +7 -0
- data/templates/errors/invalid_berkshelf_options.erb +4 -0
- data/templates/errors/may_need_to_specify_platform.erb +25 -0
- data/templates/errors/no_conversion_error.erb +1 -0
- data/templates/errors/not_stubbed.erb +7 -0
- data/templates/errors/shell_out_not_stubbed.erb +10 -0
- data/templates/errors/template_not_found.erb +9 -0
- metadata +221 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: ff591aba0dfcbf3e5260ac9a313dcb6d4712e242399a1141d8b5a4826a38510e
|
|
4
|
+
data.tar.gz: 76c87147defb9b4e50aac7d3f21e7c8b7e8ec37366cdb008841df885547269b1
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 843e62a9f07eca7637e0a319624b889a400ccf618dfc5c94080068ee3291207ca2284291c33f34253f8ce61854438a5a8a380863ffb3c0d8dff889230e347fbd
|
|
7
|
+
data.tar.gz: 8af007117d07d1024cded0ce067168567d0907595fc0c0a62db5648c66b2d23a203e67e39141c5b493092f4b744a5210397ed9bde11c8ffafd1bdbc831f69c46
|
data/Gemfile
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
|
|
3
|
+
gemspec
|
|
4
|
+
|
|
5
|
+
group :development do
|
|
6
|
+
gem "rake"
|
|
7
|
+
gem "redcarpet"
|
|
8
|
+
gem "yard"
|
|
9
|
+
gem "pry"
|
|
10
|
+
gem "pry-byebug"
|
|
11
|
+
gem "chefstyle"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
if ENV["GEMFILE_MOD"]
|
|
15
|
+
puts "GEMFILE_MOD: #{ENV["GEMFILE_MOD"]}"
|
|
16
|
+
instance_eval(ENV["GEMFILE_MOD"])
|
|
17
|
+
else
|
|
18
|
+
gem "chef", git: "https://github.com/chef/chef"
|
|
19
|
+
gem "ohai", git: "https://github.com/chef/ohai"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# TODO: remove when we drop ruby 2.5
|
|
23
|
+
if Gem.ruby_version < Gem::Version.new("2.6")
|
|
24
|
+
# 16.7.23 required ruby 2.6+
|
|
25
|
+
gem "chef-utils", "< 16.7.23"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# If you want to load debugging tools into the bundle exec sandbox,
|
|
29
|
+
# add these additional dependencies into Gemfile.local
|
|
30
|
+
eval_gemfile(__FILE__ + ".local") if File.exist?(__FILE__ + ".local")
|
data/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (C) 2011 by Andrew Crump
|
|
4
|
+
Copyright (C) 2013 by Seth Vargo
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in
|
|
14
|
+
all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
22
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
2
|
+
require "rspec/core"
|
|
3
|
+
require "rspec/core/rake_task"
|
|
4
|
+
require "yard/rake/yardoc_task"
|
|
5
|
+
require "tmpdir"
|
|
6
|
+
require "rspec"
|
|
7
|
+
require "chefspec"
|
|
8
|
+
require "chefstyle"
|
|
9
|
+
|
|
10
|
+
require "chef/version"
|
|
11
|
+
|
|
12
|
+
require "rubocop/rake_task"
|
|
13
|
+
RuboCop::RakeTask.new(:style) do |task|
|
|
14
|
+
task.options << "--display-cop-names"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
YARD::Rake::YardocTask.new
|
|
18
|
+
|
|
19
|
+
RSpec::Core::RakeTask.new(:unit) do |t|
|
|
20
|
+
t.rspec_opts = [].tap do |a|
|
|
21
|
+
a.push("--color")
|
|
22
|
+
a.push("--format progress")
|
|
23
|
+
end.join(" ")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
failed = []
|
|
27
|
+
start_time = nil
|
|
28
|
+
|
|
29
|
+
namespace :acceptance do |ns|
|
|
30
|
+
|
|
31
|
+
Dir.foreach("examples") do |dir|
|
|
32
|
+
next if %w{. .. .DS_Store}.include?(dir)
|
|
33
|
+
|
|
34
|
+
desc "#{dir} acceptance tests"
|
|
35
|
+
task dir.to_sym do
|
|
36
|
+
start_time ||= Time.now
|
|
37
|
+
Dir.mktmpdir do |tmp|
|
|
38
|
+
FileUtils.cp_r("examples/#{dir}", tmp)
|
|
39
|
+
|
|
40
|
+
pwd = Dir.pwd
|
|
41
|
+
|
|
42
|
+
Dir.chdir "#{tmp}/#{dir}" do
|
|
43
|
+
puts "rspec examples/#{dir}"
|
|
44
|
+
|
|
45
|
+
#
|
|
46
|
+
# This bit of mildly awful magic below is to load each file into an in-memory
|
|
47
|
+
# RSpec runner while keeping a persistent ChefZero server alive.
|
|
48
|
+
#
|
|
49
|
+
load "#{pwd}/lib/chefspec/rspec.rb"
|
|
50
|
+
|
|
51
|
+
RSpec.configure do |config|
|
|
52
|
+
config.full_backtrace = true
|
|
53
|
+
config.color = true
|
|
54
|
+
config.run_all_when_everything_filtered = true
|
|
55
|
+
config.filter_run(:focus)
|
|
56
|
+
config.before(:suite) do
|
|
57
|
+
ChefSpec::ZeroServer.setup!
|
|
58
|
+
end
|
|
59
|
+
config.after(:each) do
|
|
60
|
+
ChefSpec::ZeroServer.reset!
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
RSpec.clear_examples
|
|
65
|
+
exitstatus = RSpec::Core::Runner.run(["spec"])
|
|
66
|
+
RSpec.reset
|
|
67
|
+
failed << dir unless exitstatus == 0
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
rescue Errno::ENOENT # examples dir is probably missing
|
|
73
|
+
puts "The rake acceptance tests require a full git checkout of chefspec including all examples files!"
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
task acceptance: Rake.application.tasks.select { |t| t.name.start_with?("acceptance:") } do
|
|
78
|
+
puts "Acceptance tests took #{Time.now - start_time} seconds"
|
|
79
|
+
raise "some tests failed: #{failed.join(", ")}" unless failed.empty?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
desc "Run all tests"
|
|
83
|
+
task test: %i{unit acceptance}
|
|
84
|
+
|
|
85
|
+
task default: [:test]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
|
2
|
+
$:.unshift lib unless $:.include?(lib)
|
|
3
|
+
require "chefspec/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "chefspec-chef"
|
|
7
|
+
s.version = ChefSpec::VERSION
|
|
8
|
+
s.authors = ["Andrew Crump", "Seth Vargo"]
|
|
9
|
+
s.email = ["andrew.crump@ieee.org", "sethvargo@gmail.com"]
|
|
10
|
+
s.summary = "Write RSpec examples and generate coverage reports for " \
|
|
11
|
+
"Chef recipes!"
|
|
12
|
+
s.description = "ChefSpec is a unit testing and resource coverage " \
|
|
13
|
+
"(code coverage) framework for testing Chef cookbooks " \
|
|
14
|
+
"ChefSpec makes it easy to write examples and get fast " \
|
|
15
|
+
"feedback on cookbook changes without the need for " \
|
|
16
|
+
"virtual machines or cloud servers."
|
|
17
|
+
s.homepage = "https://github.com/chef/chefspec"
|
|
18
|
+
s.license = "MIT"
|
|
19
|
+
|
|
20
|
+
# Packaging
|
|
21
|
+
s.files = %w{LICENSE Rakefile Gemfile chefspec-chef.gemspec} + Dir.glob("{lib,templates,spec}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
|
|
22
|
+
s.require_paths = ["lib"]
|
|
23
|
+
|
|
24
|
+
s.required_ruby_version = ">= 2.5"
|
|
25
|
+
|
|
26
|
+
s.add_dependency "chef", ">= 15"
|
|
27
|
+
s.add_dependency "chef-cli"
|
|
28
|
+
s.add_dependency "fauxhai-chef", ">= 9.3"
|
|
29
|
+
s.add_dependency "rspec", "~> 3.0"
|
|
30
|
+
end
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
module ChefSpec
|
|
2
|
+
module API
|
|
3
|
+
# Module containing the core RSpec API for ChefSpec.
|
|
4
|
+
module Core
|
|
5
|
+
# Pull in the needed machinery to use `around` and `let` in here.
|
|
6
|
+
extend RSpec::SharedContext
|
|
7
|
+
|
|
8
|
+
# Activate all of the various ChefSpec stubs for the duraction of this
|
|
9
|
+
# example block.
|
|
10
|
+
around do |ex|
|
|
11
|
+
old_chefspec_mode = $CHEFSPEC_MODE
|
|
12
|
+
$CHEFSPEC_MODE = true
|
|
13
|
+
begin
|
|
14
|
+
# Only run the preload if a platform is configured via the new system
|
|
15
|
+
# since otherwise it will spam warnings about the platform not being
|
|
16
|
+
# set.
|
|
17
|
+
chef_runner_instance.preload! if chefspec_platform
|
|
18
|
+
ex.run
|
|
19
|
+
ensure
|
|
20
|
+
$CHEFSPEC_MODE = old_chefspec_mode
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Let variables to set data in a scoped way. Used below by
|
|
25
|
+
# {ClassMethods#platform}.
|
|
26
|
+
let(:chefspec_default_attributes) { chefspec_attributes(:default_attributes) }
|
|
27
|
+
let(:chefspec_normal_attributes) { chefspec_attributes(:normal_attributes) }
|
|
28
|
+
let(:chefspec_override_attributes) { chefspec_attributes(:override_attributes) }
|
|
29
|
+
let(:chefspec_automatic_attributes) { chefspec_attributes(:automatic_attributes) }
|
|
30
|
+
let(:chefspec_platform) { nil }
|
|
31
|
+
let(:chefspec_platform_version) { nil }
|
|
32
|
+
|
|
33
|
+
# Compute the options for the runner.
|
|
34
|
+
#
|
|
35
|
+
# @abstract
|
|
36
|
+
# @return [Hash<Symbol, Object>]
|
|
37
|
+
def chef_runner_options
|
|
38
|
+
options = {
|
|
39
|
+
step_into: chefspec_ancestor_gather([], :step_into) { |memo, val| memo | val },
|
|
40
|
+
default_attributes: chefspec_default_attributes,
|
|
41
|
+
normal_attributes: chefspec_normal_attributes,
|
|
42
|
+
override_attributes: chefspec_override_attributes,
|
|
43
|
+
automatic_attributes: chefspec_automatic_attributes,
|
|
44
|
+
spec_declaration_locations: self.class.declaration_locations.last[0],
|
|
45
|
+
}
|
|
46
|
+
# Only specify these if set in the example so we don't override the
|
|
47
|
+
# global settings.
|
|
48
|
+
options[:platform] = chefspec_platform if chefspec_platform
|
|
49
|
+
options[:version] = chefspec_platform_version if chefspec_platform_version
|
|
50
|
+
# Merge in any final overrides.
|
|
51
|
+
options.update(chefspec_attributes(:chefspec_options).symbolize_keys)
|
|
52
|
+
options
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Class of runner to use.
|
|
56
|
+
#
|
|
57
|
+
# @abstract
|
|
58
|
+
# @return [Class]
|
|
59
|
+
def chef_runner_class
|
|
60
|
+
ChefSpec::SoloRunner
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Create an instance of the runner.
|
|
64
|
+
#
|
|
65
|
+
# This should only be used in cases where the `let()` cache would be a problem.
|
|
66
|
+
#
|
|
67
|
+
# @return [ChefSpec::SoloRunner]
|
|
68
|
+
def chef_runner_instance
|
|
69
|
+
chef_runner_class.new(chef_runner_options)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Set up the runner object but don't actually run anything yet.
|
|
73
|
+
let(:chef_runner) { chef_runner_instance }
|
|
74
|
+
|
|
75
|
+
# By default, run the recipe in the base `describe` block.
|
|
76
|
+
let(:chef_run) { chef_runner.converge(described_recipe) }
|
|
77
|
+
|
|
78
|
+
# Helper method for some of the nestable test value methods like
|
|
79
|
+
# {ClassMethods#default_attributes} and {ClassMethods#step_into}.
|
|
80
|
+
#
|
|
81
|
+
# @api private
|
|
82
|
+
# @param start [Object] Initial value for the reducer.
|
|
83
|
+
# @param method [Symbol] Name of the group-level method to call on each
|
|
84
|
+
# ancestor.
|
|
85
|
+
# @param block [Proc] Reducer callable.
|
|
86
|
+
# @return [Object]
|
|
87
|
+
def chefspec_ancestor_gather(start, method, &block)
|
|
88
|
+
candidate_ancestors = self.class.ancestors.select { |cls| cls.respond_to?(method) && cls != ChefSpec::API::Core }
|
|
89
|
+
candidate_ancestors.reverse.inject(start) do |memo, cls|
|
|
90
|
+
block.call(memo, cls.send(method))
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Special case of {#chefspec_ancestor_gather} because we do it four times.
|
|
95
|
+
#
|
|
96
|
+
# @api private
|
|
97
|
+
# @param method [Symbol] Name of the group-level method to call on each
|
|
98
|
+
# ancestor.
|
|
99
|
+
# @return [Mash]
|
|
100
|
+
def chefspec_attributes(method)
|
|
101
|
+
chefspec_ancestor_gather(Mash.new, method) do |memo, val|
|
|
102
|
+
Chef::Mixin::DeepMerge.merge(memo, val)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Methods that will end up as group-level.
|
|
107
|
+
#
|
|
108
|
+
# @api private
|
|
109
|
+
module ClassMethods
|
|
110
|
+
# Set the Fauxhai platform to use for this example group.
|
|
111
|
+
#
|
|
112
|
+
# @example
|
|
113
|
+
# describe 'myrecipe' do
|
|
114
|
+
# platform 'ubuntu', '18.04'
|
|
115
|
+
# @param name [String] Platform name to set.
|
|
116
|
+
# @param version [String, nil] Platform version to set.
|
|
117
|
+
# @return [void]
|
|
118
|
+
def platform(name, version = nil)
|
|
119
|
+
let(:chefspec_platform) { name }
|
|
120
|
+
let(:chefspec_platform_version) { version }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Use an in-line block of recipe code for this example group rather
|
|
124
|
+
# than a recipe from a cookbook.
|
|
125
|
+
#
|
|
126
|
+
# @example
|
|
127
|
+
# describe 'my_resource' do
|
|
128
|
+
# recipe do
|
|
129
|
+
# my_resource 'helloworld'
|
|
130
|
+
# end
|
|
131
|
+
# @param block [Proc] A block of Chef recipe code.
|
|
132
|
+
# @return [void]
|
|
133
|
+
def recipe(&block)
|
|
134
|
+
let(:chef_run) do
|
|
135
|
+
chef_runner.converge_block(&block)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Set default-level node attributes to use for this example group.
|
|
140
|
+
#
|
|
141
|
+
# @example
|
|
142
|
+
# describe 'myapp::install' do
|
|
143
|
+
# default_attributes['myapp']['version'] = '1.0'
|
|
144
|
+
# @return [Chef::Node::VividMash]
|
|
145
|
+
def default_attributes
|
|
146
|
+
@chefspec_default_attributes ||= Chef::Node::VividMash.new
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Set normal-level node attributes to use for this example group.
|
|
150
|
+
#
|
|
151
|
+
# @example
|
|
152
|
+
# describe 'myapp::install' do
|
|
153
|
+
# normal_attributes['myapp']['version'] = '1.0'
|
|
154
|
+
# @return [Chef::Node::VividMash]
|
|
155
|
+
def normal_attributes
|
|
156
|
+
@chefspec_normal_attributes ||= Chef::Node::VividMash.new
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Set override-level node attributes to use for this example group.
|
|
160
|
+
#
|
|
161
|
+
# @example
|
|
162
|
+
# describe 'myapp::install' do
|
|
163
|
+
# override_attributes['myapp']['version'] = '1.0'
|
|
164
|
+
# @return [Chef::Node::VividMash]
|
|
165
|
+
def override_attributes
|
|
166
|
+
@chefspec_override_attributes ||= Chef::Node::VividMash.new
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Set automatic-level node attributes to use for this example group.
|
|
170
|
+
#
|
|
171
|
+
# @example
|
|
172
|
+
# describe 'myapp::install' do
|
|
173
|
+
# automatic_attributes['kernel']['machine'] = 'ppc64'
|
|
174
|
+
# @return [Chef::Node::VividMash]
|
|
175
|
+
def automatic_attributes
|
|
176
|
+
@chefspec_automatic_attributes ||= Chef::Node::VividMash.new
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Set additional ChefSpec runner options to use for this example group.
|
|
180
|
+
#
|
|
181
|
+
# @example
|
|
182
|
+
# describe 'myapp::install' do
|
|
183
|
+
# chefspec_options[:log_level] = :debug
|
|
184
|
+
# @return [Chef::Node::VividMash]
|
|
185
|
+
def chefspec_options
|
|
186
|
+
@chefspec_options ||= Chef::Node::VividMash.new
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Add resources to the step_into list for this example group.
|
|
190
|
+
#
|
|
191
|
+
# @example
|
|
192
|
+
# describe 'myapp::install' do
|
|
193
|
+
# step_into :my_resource
|
|
194
|
+
# @return [Array]
|
|
195
|
+
def step_into(*resources)
|
|
196
|
+
@chefspec_step_into ||= []
|
|
197
|
+
@chefspec_step_into |= resources.flatten.map(&:to_s)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# @api private
|
|
201
|
+
def included(klass)
|
|
202
|
+
super
|
|
203
|
+
# Inject classmethods into the group.
|
|
204
|
+
klass.extend(ClassMethods)
|
|
205
|
+
# If the describe block is aimed at string or resource/provider class
|
|
206
|
+
# then set the default subject to be the Chef run.
|
|
207
|
+
if klass.described_class.nil? || klass.described_class.is_a?(Class) && (klass.described_class < Chef::Resource || klass.described_class < Chef::Provider)
|
|
208
|
+
klass.subject { chef_run }
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
extend ClassMethods
|
|
214
|
+
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module ChefSpec
|
|
2
|
+
module API
|
|
3
|
+
module Described
|
|
4
|
+
#
|
|
5
|
+
# The name of the currently running cookbook spec. Given the top-level
|
|
6
|
+
# +describe+ block is of the format:
|
|
7
|
+
#
|
|
8
|
+
# describe 'my_cookbook::my_recipe' do
|
|
9
|
+
# # ...
|
|
10
|
+
# end
|
|
11
|
+
#
|
|
12
|
+
# The value of +described_cookbook+ is "my_cookbook".
|
|
13
|
+
#
|
|
14
|
+
# @example Using +described_cookbook+ in a context block
|
|
15
|
+
# context "#{described_recipe} installs foo" do
|
|
16
|
+
# # ...
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
#
|
|
20
|
+
# @return [String]
|
|
21
|
+
#
|
|
22
|
+
def described_cookbook
|
|
23
|
+
described_recipe.split("::").first
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
#
|
|
27
|
+
# The name of the currently running recipe spec. Given the top-level
|
|
28
|
+
# +describe+ block is of the format:
|
|
29
|
+
#
|
|
30
|
+
# describe 'my_cookbook::my_recipe' do
|
|
31
|
+
# # ...
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# The value of +described_recipe+ is "my_cookbook::my_recipe".
|
|
35
|
+
#
|
|
36
|
+
# @example Using +described_recipe+ in the +ChefSpec::SoloRunner+
|
|
37
|
+
# let(:chef_run) { ChefSpec::SoloRunner.new.converge(described_recipe) }
|
|
38
|
+
#
|
|
39
|
+
#
|
|
40
|
+
# @return [String]
|
|
41
|
+
#
|
|
42
|
+
def described_recipe
|
|
43
|
+
scope = is_a?(Class) ? self : self.class
|
|
44
|
+
|
|
45
|
+
metahash = scope.metadata
|
|
46
|
+
metahash = metahash[:parent_example_group] while metahash.key?(:parent_example_group)
|
|
47
|
+
|
|
48
|
+
metahash[:description].to_s
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module ChefSpec
|
|
2
|
+
module API
|
|
3
|
+
module DoNothing
|
|
4
|
+
#
|
|
5
|
+
# Assert that a resource in the Chef run does not perform any actions. Given
|
|
6
|
+
# a resource with +action :nothing+:
|
|
7
|
+
#
|
|
8
|
+
# package 'apache2' do
|
|
9
|
+
# action :nothing
|
|
10
|
+
# end
|
|
11
|
+
#
|
|
12
|
+
# The Examples section demonstrates the different ways to test that no
|
|
13
|
+
# actions were performed on a resource in a Chef run.
|
|
14
|
+
#
|
|
15
|
+
# @example Assert the +package+ does not perform any actions
|
|
16
|
+
# expect(chef_run.package('apache2')).to do_nothing
|
|
17
|
+
#
|
|
18
|
+
# @return [ChefSpec::Matchers::DoNothingMatcher]
|
|
19
|
+
#
|
|
20
|
+
def do_nothing
|
|
21
|
+
ChefSpec::Matchers::DoNothingMatcher.new
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module ChefSpec
|
|
2
|
+
module API
|
|
3
|
+
module IncludeAnyRecipe
|
|
4
|
+
#
|
|
5
|
+
# Assert that a Chef run includes any recipe.
|
|
6
|
+
#
|
|
7
|
+
# include_recipe 'apache2::default'
|
|
8
|
+
#
|
|
9
|
+
# The Examples section demonstrates the different ways to test an
|
|
10
|
+
# +include_any_recipe+ directive with ChefSpec.
|
|
11
|
+
#
|
|
12
|
+
# @example Assert the Chef run did not include any recipes
|
|
13
|
+
# expect(chef_run).not_to include_any_recipe
|
|
14
|
+
#
|
|
15
|
+
#
|
|
16
|
+
# @return [ChefSpec::Matchers::IncludeAnyRecipeMatcher]
|
|
17
|
+
#
|
|
18
|
+
def include_any_recipe
|
|
19
|
+
ChefSpec::Matchers::IncludeAnyRecipeMatcher.new
|
|
20
|
+
end
|
|
21
|
+
alias_method :include_any_recipes, :include_any_recipe
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module ChefSpec
|
|
2
|
+
module API
|
|
3
|
+
module IncludeRecipe
|
|
4
|
+
#
|
|
5
|
+
# Assert that a Chef run includes a certain recipe. Given a Chef Recipe
|
|
6
|
+
# that calls +include_recipe+:
|
|
7
|
+
#
|
|
8
|
+
# include_recipe 'apache2::default'
|
|
9
|
+
#
|
|
10
|
+
# The Examples section demonstrates the different ways to test an
|
|
11
|
+
# +include_recipe+ directive with ChefSpec.
|
|
12
|
+
#
|
|
13
|
+
# @example Assert the +apache2::default+ recipe is included in the Chef run
|
|
14
|
+
# expect(chef_run).to include_recipe('apache2::default')
|
|
15
|
+
#
|
|
16
|
+
#
|
|
17
|
+
# @param [String] recipe_name
|
|
18
|
+
# the name of the recipe to be included
|
|
19
|
+
#
|
|
20
|
+
# @return [ChefSpec::Matchers::IncludeRecipeMatcher]
|
|
21
|
+
#
|
|
22
|
+
def include_recipe(recipe_name)
|
|
23
|
+
ChefSpec::Matchers::IncludeRecipeMatcher.new(recipe_name)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module ChefSpec
|
|
2
|
+
module API
|
|
3
|
+
module Link
|
|
4
|
+
#
|
|
5
|
+
# Assert that a symlink links to a specific path. This is really
|
|
6
|
+
# syntactic sugar for the following:
|
|
7
|
+
#
|
|
8
|
+
# expect(chef_run).to create_link('/tmp/thing').with(to: '/tmp/other_thing')
|
|
9
|
+
#
|
|
10
|
+
# @example Using +link_to+ with a String path
|
|
11
|
+
# link = chef_run.link('/tmp/thing')
|
|
12
|
+
# expect(link).to link_to('/tmp/other_thing')
|
|
13
|
+
#
|
|
14
|
+
# @example Using +link_to+ with a regular expression
|
|
15
|
+
# expect(link).to link_to(/\/tmp/(.+)/)
|
|
16
|
+
#
|
|
17
|
+
# @param [String, Regex] path
|
|
18
|
+
# the path to link to
|
|
19
|
+
#
|
|
20
|
+
# @return [ChefSpec::Matchers::LinkToMatcher]
|
|
21
|
+
#
|
|
22
|
+
def link_to(path)
|
|
23
|
+
ChefSpec::Matchers::LinkToMatcher.new(path)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module ChefSpec
|
|
2
|
+
module API
|
|
3
|
+
module Notifications
|
|
4
|
+
#
|
|
5
|
+
# Assert that a resource notifies another. Given a Chef Recipe that
|
|
6
|
+
# notifies a template resource to restart apache:
|
|
7
|
+
#
|
|
8
|
+
# template '/etc/apache2/config' do
|
|
9
|
+
# notifies :restart, 'service[apache2]'
|
|
10
|
+
# end
|
|
11
|
+
#
|
|
12
|
+
# The Examples section demonstrates the different ways to test an
|
|
13
|
+
# notifications on a resource with ChefSpec.
|
|
14
|
+
#
|
|
15
|
+
# @example Assert the template notifies apache of something
|
|
16
|
+
# template = chef_run.template('/etc/apache2.conf')
|
|
17
|
+
# expect(template).to notify('service[apache2]')
|
|
18
|
+
#
|
|
19
|
+
# @example Assert the template notifies apache to restart
|
|
20
|
+
# expect(template).to notify('service[apache2]').to(:restart)
|
|
21
|
+
#
|
|
22
|
+
# @example Assert the template notifies apache to restart immediately
|
|
23
|
+
# expect(template).to notify('service[apache2]').to(:restart).immediately
|
|
24
|
+
#
|
|
25
|
+
# @example Assert the template notifies apache to restart delayed
|
|
26
|
+
# expect(template).to notify('service[apache2]').to(:restart).delayed
|
|
27
|
+
#
|
|
28
|
+
#
|
|
29
|
+
# @param [String] signature
|
|
30
|
+
# the signature of the notification to match
|
|
31
|
+
#
|
|
32
|
+
# @return [ChefSpec::Matchers::NotificationsMatcher]
|
|
33
|
+
#
|
|
34
|
+
def notify(signature)
|
|
35
|
+
ChefSpec::Matchers::NotificationsMatcher.new(signature)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module ChefSpec
|
|
2
|
+
module API
|
|
3
|
+
module Reboot
|
|
4
|
+
def now_reboot(resource_name)
|
|
5
|
+
ChefSpec::Matchers::ResourceMatcher.new(:reboot, :reboot_now, resource_name)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def request_reboot(resource_name)
|
|
9
|
+
ChefSpec::Matchers::ResourceMatcher.new(:reboot, :request_reboot, resource_name)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module ChefSpec
|
|
2
|
+
module API
|
|
3
|
+
module RenderFile
|
|
4
|
+
#
|
|
5
|
+
# Assert that a file is rendered by the Chef run. This matcher works for
|
|
6
|
+
# +template+, +file+, and +cookbook_file+ resources. The content from the
|
|
7
|
+
# resource must be convertable to a string; verifying the content of a
|
|
8
|
+
# binary file is not permissible at this time.
|
|
9
|
+
#
|
|
10
|
+
# @example Assert a template is rendered
|
|
11
|
+
# expect(chef_run).to render_file('/etc/foo')
|
|
12
|
+
#
|
|
13
|
+
# @example Assert a template is rendered with certain content
|
|
14
|
+
# expect(template).to render_file('/etc/foo').with_content('This is a file')
|
|
15
|
+
#
|
|
16
|
+
# @example Assert a template is rendered with matching content
|
|
17
|
+
# expect(template).to render_file('/etc/foo').with_content(/^This(.+)$/)
|
|
18
|
+
#
|
|
19
|
+
# @example Assert a template is rendered with content matching any RSpec matcher
|
|
20
|
+
# expect(template).to render_file('/etc/foo').with_content(starts_with('This'))
|
|
21
|
+
#
|
|
22
|
+
# @example Assert a partial path to a template is rendered with matching content
|
|
23
|
+
# expect(template).to render_file(/\/etc\/foo-(\d+)$/).with_content(/^This(.+)$/)
|
|
24
|
+
#
|
|
25
|
+
#
|
|
26
|
+
# @param [String] path
|
|
27
|
+
# the path of the file to render
|
|
28
|
+
#
|
|
29
|
+
# @return [ChefSpec::Matchers::RenderFileMatcher]
|
|
30
|
+
#
|
|
31
|
+
def render_file(path)
|
|
32
|
+
ChefSpec::Matchers::RenderFileMatcher.new(path)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module ChefSpec
|
|
2
|
+
module API
|
|
3
|
+
module StateAttrs
|
|
4
|
+
#
|
|
5
|
+
# Assert that a Chef resource has certain state attributes (since Chef
|
|
6
|
+
# 11.8.0):
|
|
7
|
+
#
|
|
8
|
+
# state_attrs :time, :temperature
|
|
9
|
+
#
|
|
10
|
+
# @see https://github.com/opscode/chef/blob/e43d7ebda/lib/chef/resource/file.rb#L32-L37
|
|
11
|
+
#
|
|
12
|
+
# The Examples section demonstrates the different ways to test a
|
|
13
|
+
# resource's +state_attrs+ with ChefSpec.
|
|
14
|
+
#
|
|
15
|
+
# @example Assert the +lwrp+ resource has two state attributes
|
|
16
|
+
# expect(lwrp).to have_state_attrs(:time, :temperature)
|
|
17
|
+
#
|
|
18
|
+
#
|
|
19
|
+
# @param [Array] state_attrs
|
|
20
|
+
# the list of state attributes to assert
|
|
21
|
+
#
|
|
22
|
+
# @return [ChefSpec::Matchers::StateAttrsMatcher]
|
|
23
|
+
#
|
|
24
|
+
def have_state_attrs(*state_attrs)
|
|
25
|
+
ChefSpec::Matchers::StateAttrsMatcher.new(state_attrs)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|