chefspec-chef 9.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +30 -0
  3. data/LICENSE +22 -0
  4. data/Rakefile +85 -0
  5. data/chefspec-chef.gemspec +30 -0
  6. data/lib/chefspec/api/core.rb +217 -0
  7. data/lib/chefspec/api/described.rb +53 -0
  8. data/lib/chefspec/api/do_nothing.rb +26 -0
  9. data/lib/chefspec/api/include_any_recipe.rb +24 -0
  10. data/lib/chefspec/api/include_recipe.rb +28 -0
  11. data/lib/chefspec/api/link.rb +28 -0
  12. data/lib/chefspec/api/notifications.rb +40 -0
  13. data/lib/chefspec/api/reboot.rb +14 -0
  14. data/lib/chefspec/api/render_file.rb +37 -0
  15. data/lib/chefspec/api/state_attrs.rb +30 -0
  16. data/lib/chefspec/api/stubs.rb +183 -0
  17. data/lib/chefspec/api/stubs_for.rb +139 -0
  18. data/lib/chefspec/api/subscriptions.rb +37 -0
  19. data/lib/chefspec/api/user.rb +230 -0
  20. data/lib/chefspec/api.rb +39 -0
  21. data/lib/chefspec/berkshelf.rb +63 -0
  22. data/lib/chefspec/cacher.rb +64 -0
  23. data/lib/chefspec/coverage/filters.rb +82 -0
  24. data/lib/chefspec/coverage.rb +247 -0
  25. data/lib/chefspec/deprecations.rb +46 -0
  26. data/lib/chefspec/errors.rb +48 -0
  27. data/lib/chefspec/expect_exception.rb +51 -0
  28. data/lib/chefspec/extensions/chef/client.rb +21 -0
  29. data/lib/chefspec/extensions/chef/conditional.rb +16 -0
  30. data/lib/chefspec/extensions/chef/cookbook/gem_installer.rb +33 -0
  31. data/lib/chefspec/extensions/chef/cookbook_loader.rb +14 -0
  32. data/lib/chefspec/extensions/chef/cookbook_uploader.rb +12 -0
  33. data/lib/chefspec/extensions/chef/data_query.rb +49 -0
  34. data/lib/chefspec/extensions/chef/lwrp_base.rb +29 -0
  35. data/lib/chefspec/extensions/chef/provider.rb +39 -0
  36. data/lib/chefspec/extensions/chef/resource/freebsd_package.rb +17 -0
  37. data/lib/chefspec/extensions/chef/resource.rb +188 -0
  38. data/lib/chefspec/extensions/chef/run_context/cookbook_compiler.rb +84 -0
  39. data/lib/chefspec/extensions/chef/securable.rb +19 -0
  40. data/lib/chefspec/extensions/ohai/system.rb +11 -0
  41. data/lib/chefspec/extensions.rb +21 -0
  42. data/lib/chefspec/file_cache_path_proxy.rb +15 -0
  43. data/lib/chefspec/formatter.rb +282 -0
  44. data/lib/chefspec/librarian.rb +51 -0
  45. data/lib/chefspec/matchers/do_nothing_matcher.rb +52 -0
  46. data/lib/chefspec/matchers/include_any_recipe_matcher.rb +51 -0
  47. data/lib/chefspec/matchers/include_recipe_matcher.rb +46 -0
  48. data/lib/chefspec/matchers/link_to_matcher.rb +37 -0
  49. data/lib/chefspec/matchers/notifications_matcher.rb +143 -0
  50. data/lib/chefspec/matchers/render_file_matcher.rb +140 -0
  51. data/lib/chefspec/matchers/resource_matcher.rb +175 -0
  52. data/lib/chefspec/matchers/state_attrs_matcher.rb +71 -0
  53. data/lib/chefspec/matchers/subscribes_matcher.rb +72 -0
  54. data/lib/chefspec/matchers.rb +13 -0
  55. data/lib/chefspec/mixins/normalize.rb +22 -0
  56. data/lib/chefspec/policyfile.rb +69 -0
  57. data/lib/chefspec/renderer.rb +145 -0
  58. data/lib/chefspec/rspec.rb +21 -0
  59. data/lib/chefspec/runner.rb +8 -0
  60. data/lib/chefspec/server.rb +4 -0
  61. data/lib/chefspec/server_methods.rb +173 -0
  62. data/lib/chefspec/server_runner.rb +76 -0
  63. data/lib/chefspec/solo_runner.rb +516 -0
  64. data/lib/chefspec/stubs/command_registry.rb +11 -0
  65. data/lib/chefspec/stubs/command_stub.rb +37 -0
  66. data/lib/chefspec/stubs/data_bag_item_registry.rb +13 -0
  67. data/lib/chefspec/stubs/data_bag_item_stub.rb +25 -0
  68. data/lib/chefspec/stubs/data_bag_registry.rb +13 -0
  69. data/lib/chefspec/stubs/data_bag_stub.rb +23 -0
  70. data/lib/chefspec/stubs/registry.rb +32 -0
  71. data/lib/chefspec/stubs/search_registry.rb +13 -0
  72. data/lib/chefspec/stubs/search_stub.rb +25 -0
  73. data/lib/chefspec/stubs/stub.rb +38 -0
  74. data/lib/chefspec/util.rb +58 -0
  75. data/lib/chefspec/version.rb +3 -0
  76. data/lib/chefspec/zero_server.rb +142 -0
  77. data/lib/chefspec.rb +75 -0
  78. data/spec/spec_helper.rb +12 -0
  79. data/spec/support/hash.rb +35 -0
  80. data/spec/unit/cacher_spec.rb +70 -0
  81. data/spec/unit/coverage/filters_spec.rb +60 -0
  82. data/spec/unit/deprecations_spec.rb +52 -0
  83. data/spec/unit/errors_spec.rb +57 -0
  84. data/spec/unit/expect_exception_spec.rb +32 -0
  85. data/spec/unit/macros_spec.rb +119 -0
  86. data/spec/unit/matchers/do_nothing_matcher.rb +5 -0
  87. data/spec/unit/matchers/include_any_recipe_matcher_spec.rb +52 -0
  88. data/spec/unit/matchers/include_recipe_matcher_spec.rb +38 -0
  89. data/spec/unit/matchers/link_to_matcher_spec.rb +55 -0
  90. data/spec/unit/matchers/notifications_matcher_spec.rb +39 -0
  91. data/spec/unit/matchers/render_file_matcher_spec.rb +68 -0
  92. data/spec/unit/matchers/resource_matcher_spec.rb +5 -0
  93. data/spec/unit/matchers/state_attrs_matcher_spec.rb +68 -0
  94. data/spec/unit/matchers/subscribes_matcher_spec.rb +63 -0
  95. data/spec/unit/renderer_spec.rb +69 -0
  96. data/spec/unit/server_runner_spec.rb +28 -0
  97. data/spec/unit/solo_runner_spec.rb +171 -0
  98. data/spec/unit/stubs/command_registry_spec.rb +27 -0
  99. data/spec/unit/stubs/command_stub_spec.rb +61 -0
  100. data/spec/unit/stubs/data_bag_item_registry_spec.rb +39 -0
  101. data/spec/unit/stubs/data_bag_item_stub_spec.rb +36 -0
  102. data/spec/unit/stubs/data_bag_registry_spec.rb +39 -0
  103. data/spec/unit/stubs/data_bag_stub_spec.rb +35 -0
  104. data/spec/unit/stubs/registry_spec.rb +29 -0
  105. data/spec/unit/stubs/search_registry_spec.rb +39 -0
  106. data/spec/unit/stubs/search_stub_spec.rb +36 -0
  107. data/spec/unit/stubs/stub_spec.rb +64 -0
  108. data/templates/coverage/human.erb +22 -0
  109. data/templates/coverage/json.erb +8 -0
  110. data/templates/coverage/table.erb +14 -0
  111. data/templates/errors/cookbook_path_not_found.erb +3 -0
  112. data/templates/errors/erb_template_parse_error.erb +5 -0
  113. data/templates/errors/gem_load_error.erb +7 -0
  114. data/templates/errors/invalid_berkshelf_options.erb +4 -0
  115. data/templates/errors/may_need_to_specify_platform.erb +25 -0
  116. data/templates/errors/no_conversion_error.erb +1 -0
  117. data/templates/errors/not_stubbed.erb +7 -0
  118. data/templates/errors/shell_out_not_stubbed.erb +10 -0
  119. data/templates/errors/template_not_found.erb +9 -0
  120. 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