chefspec 1.3.1 → 2.0.0
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/lib/chef/expect_exception.rb +34 -0
- data/lib/chef/formatters/chefspec.rb +46 -11
- data/lib/chefspec.rb +14 -0
- data/lib/chefspec/chef_runner.rb +16 -4
- data/lib/chefspec/helpers/describe.rb +5 -1
- data/lib/chefspec/matchers/execute.rb +1 -1
- data/lib/chefspec/matchers/file.rb +53 -54
- data/lib/chefspec/matchers/file_content.rb +17 -21
- data/lib/chefspec/matchers/package.rb +5 -6
- data/lib/chefspec/matchers/python.rb +7 -0
- data/lib/chefspec/matchers/ruby_block.rb +2 -2
- data/lib/chefspec/matchers/shared.rb +73 -27
- data/lib/chefspec/minitest.rb +4 -10
- data/lib/chefspec/monkey_patches/hash.rb +15 -8
- data/lib/chefspec/version.rb +1 -1
- metadata +33 -67
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 499bad18b2da5ab00aedf8c46c95c6045e95f81c
|
4
|
+
data.tar.gz: f4e98dc5b9a45a149174f0d0e20b3c22e3781b00
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cd4ac9f716914dfc745cfa45f9461d714d2f8e487fd33d28f00e886d54be9f234c18e71c6799b3e92f90581d60bd73acdac7ad35870ee1f3bfbef302faf1266e
|
7
|
+
data.tar.gz: 90ba125ef150adc1643f5dfabe85a893f5501b63cc7a8fce4e815012f78d7825d2743aef0d59c7238c3fbf9e863e26e094a294afc86a069b11782b92d58785e0
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Chef
|
2
|
+
module ExpectException
|
3
|
+
class << self
|
4
|
+
def expected?(chef_message, exception, *args)
|
5
|
+
@b.call(chef_message, exception)
|
6
|
+
end
|
7
|
+
|
8
|
+
def expect(klass, message)
|
9
|
+
expect_block do |chef_message, exception|
|
10
|
+
match?(exception, klass, message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def expect_block(&block)
|
15
|
+
@b = block
|
16
|
+
end
|
17
|
+
|
18
|
+
def clear
|
19
|
+
@b = lambda{|cm, e| false}
|
20
|
+
clear_seen
|
21
|
+
end
|
22
|
+
|
23
|
+
def clear_seen
|
24
|
+
@seen = []
|
25
|
+
end
|
26
|
+
|
27
|
+
def match?(exception, klass, message)
|
28
|
+
exception.class == klass and exception.message == message
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
clear
|
33
|
+
end
|
34
|
+
end
|
@@ -1,15 +1,10 @@
|
|
1
1
|
if defined?(Chef::Formatters::Base)
|
2
2
|
class Chef
|
3
3
|
module Formatters
|
4
|
-
|
5
|
-
# taken from Chef::Formatters:Min and all the output was then removed.
|
6
|
-
#
|
7
|
-
# @author Seth Vargo <sethvargo@gmail.com>
|
8
|
-
class ChefSpec < Formatters::Base
|
4
|
+
class ChefSpec < Base
|
9
5
|
cli_name(:chefspec)
|
10
6
|
|
11
|
-
attr_reader :updated_resources
|
12
|
-
attr_reader :updates_by_resource
|
7
|
+
attr_reader :updated_resources, :updates_by_resource
|
13
8
|
|
14
9
|
def initialize(out, err)
|
15
10
|
super
|
@@ -17,6 +12,10 @@ if defined?(Chef::Formatters::Base)
|
|
17
12
|
@updates_by_resource = Hash.new {|h, k| h[k] = []}
|
18
13
|
end
|
19
14
|
|
15
|
+
def error_expected?(message, exception, *args)
|
16
|
+
ExpectException.expected?(message, exception, *args)
|
17
|
+
end
|
18
|
+
|
20
19
|
# Called at the very start of a Chef Run
|
21
20
|
def run_start(version)
|
22
21
|
puts "Starting Chef Client, version #{version}"
|
@@ -28,6 +27,7 @@ if defined?(Chef::Formatters::Base)
|
|
28
27
|
|
29
28
|
# called at the end of a failed run
|
30
29
|
def run_failed(exception)
|
30
|
+
return if error_expected?(:run_failed, exception)
|
31
31
|
puts "chef client failed. #{@updated_resources.size} resources updated"
|
32
32
|
end
|
33
33
|
|
@@ -48,7 +48,7 @@ if defined?(Chef::Formatters::Base)
|
|
48
48
|
|
49
49
|
# Failed to register this client with the server.
|
50
50
|
def registration_failed(node_name, exception, config)
|
51
|
-
super
|
51
|
+
super unless error_expected?(:registration_failed, exception, config, node_name)
|
52
52
|
end
|
53
53
|
|
54
54
|
def node_load_start(node_name, config)
|
@@ -56,6 +56,11 @@ if defined?(Chef::Formatters::Base)
|
|
56
56
|
|
57
57
|
# Failed to load node data from the server
|
58
58
|
def node_load_failed(node_name, exception, config)
|
59
|
+
super unless error_expected?(:node_load_failed, exception)
|
60
|
+
end
|
61
|
+
|
62
|
+
def run_list_expand_failed(expanded_run_list, exception)
|
63
|
+
super unless error_expected?(:run_list_expand_failed, exception, expanded_run_list)
|
59
64
|
end
|
60
65
|
|
61
66
|
# Default and override attrs from roles have been computed, but not yet applied.
|
@@ -70,6 +75,11 @@ if defined?(Chef::Formatters::Base)
|
|
70
75
|
# Called when there is an error getting the cookbook collection from the
|
71
76
|
# server.
|
72
77
|
def cookbook_resolution_failed(expanded_run_list, exception)
|
78
|
+
super unless error_expected?(:cookbook_resolution_failed, exception, expanded_run_list)
|
79
|
+
end
|
80
|
+
|
81
|
+
def cookbook_sync_failed(cookbooks, exception)
|
82
|
+
super unless error_expected?(:cookbook_sync_failed, exception, cookbooks)
|
73
83
|
end
|
74
84
|
|
75
85
|
# Called when the cookbook collection is returned from the server.
|
@@ -116,8 +126,28 @@ if defined?(Chef::Formatters::Base)
|
|
116
126
|
def file_loaded(path)
|
117
127
|
end
|
118
128
|
|
119
|
-
def file_load_failed(path, exception)
|
120
|
-
super
|
129
|
+
def file_load_failed(path, exception, message = :file_load_failed, &block)
|
130
|
+
super(path, exception, &block) unless error_expected?(message, exception, path)
|
131
|
+
end
|
132
|
+
|
133
|
+
def library_file_load_failed(path, exception)
|
134
|
+
file_load_failed(path, exception, :library_file_load_failed)
|
135
|
+
end
|
136
|
+
|
137
|
+
def lwrp_file_load_failed(path, exception)
|
138
|
+
file_load_failed(path, exception, :lwrp_file_load_failed)
|
139
|
+
end
|
140
|
+
|
141
|
+
def attribute_file_load_failed(path, exception)
|
142
|
+
file_load_failed(path, exception, :attribute_file_load_failed)
|
143
|
+
end
|
144
|
+
|
145
|
+
def definition_file_load_failed(path, exception)
|
146
|
+
file_load_failed(path, exception, :definition_file_load_failed)
|
147
|
+
end
|
148
|
+
|
149
|
+
def recipe_file_load_failed(path, exception)
|
150
|
+
file_load_failed(path, exception, :recipe_file_load_failed)
|
121
151
|
end
|
122
152
|
|
123
153
|
# Called when recipes have been loaded.
|
@@ -138,10 +168,12 @@ if defined?(Chef::Formatters::Base)
|
|
138
168
|
|
139
169
|
# Called when a resource fails, but will retry.
|
140
170
|
def resource_failed_retriable(resource, action, retry_count, exception)
|
171
|
+
super unless error_expected?(:resource_failed_retriable, exception, retry_count, action, resource)
|
141
172
|
end
|
142
173
|
|
143
174
|
# Called when a resource fails and will not be retried.
|
144
175
|
def resource_failed(resource, action, exception)
|
176
|
+
super unless error_expected?(:resource, exception, exception, resource)
|
145
177
|
end
|
146
178
|
|
147
179
|
# Called when a resource action has been skipped b/c of a conditional
|
@@ -160,6 +192,10 @@ if defined?(Chef::Formatters::Base)
|
|
160
192
|
|
161
193
|
## TODO: callback for assertion fallback in why run
|
162
194
|
|
195
|
+
def recipe_not_found(exception)
|
196
|
+
super unless error_expected?(:recipe_not_found, exception)
|
197
|
+
end
|
198
|
+
|
163
199
|
# Called when a change has been made to a resource. May be called multiple
|
164
200
|
# times per resource, e.g., a file may have its content updated, and then
|
165
201
|
# its permissions updated.
|
@@ -191,7 +227,6 @@ if defined?(Chef::Formatters::Base)
|
|
191
227
|
# callback for it.
|
192
228
|
def msg(message)
|
193
229
|
end
|
194
|
-
|
195
230
|
end
|
196
231
|
end
|
197
232
|
end
|
data/lib/chefspec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'chef'
|
2
2
|
require 'chef/formatters/chefspec'
|
3
|
+
require 'chef/expect_exception'
|
3
4
|
require 'chefspec/chef_runner'
|
4
5
|
require 'chefspec/version'
|
5
6
|
|
@@ -20,6 +21,7 @@ if defined?(RSpec)
|
|
20
21
|
require 'chefspec/matchers/env'
|
21
22
|
require 'chefspec/matchers/include_recipe'
|
22
23
|
require 'chefspec/matchers/script'
|
24
|
+
require 'chefspec/matchers/python'
|
23
25
|
|
24
26
|
require 'chefspec/helpers/describe'
|
25
27
|
RSpec.configure do |c|
|
@@ -32,3 +34,15 @@ require 'chefspec/monkey_patches/conditional'
|
|
32
34
|
require 'chefspec/monkey_patches/hash'
|
33
35
|
require 'chefspec/monkey_patches/lwrp_base'
|
34
36
|
require 'chefspec/monkey_patches/provider'
|
37
|
+
|
38
|
+
module ChefSpec
|
39
|
+
class << self
|
40
|
+
def chef_11?
|
41
|
+
Gem::Requirement.new('~> 11.0').satisfied_by?(Gem::Version.new(Chef::VERSION))
|
42
|
+
end
|
43
|
+
|
44
|
+
def chef_10?
|
45
|
+
Gem::Requirement.new('~> 10.0').satisfied_by?(Gem::Version.new(Chef::VERSION))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/chefspec/chef_runner.rb
CHANGED
@@ -18,6 +18,20 @@ module ChefSpec
|
|
18
18
|
|
19
19
|
@resources = []
|
20
20
|
|
21
|
+
@needs_formatter_registered = Chef::Config.respond_to?(:add_formatter)
|
22
|
+
@nfr_mutex = Mutex.new
|
23
|
+
|
24
|
+
def self.register_formatter
|
25
|
+
return unless @needs_formatter_registered
|
26
|
+
@nfr_mutex.synchronize do
|
27
|
+
return unless @needs_formatter_registered
|
28
|
+
@needs_formatter_registered = false
|
29
|
+
# As of Chef 11, Chef uses custom formatters which munge the RSpec output.
|
30
|
+
# This uses a custom formatter which basically tells Chef to shut up.
|
31
|
+
Chef::Config.add_formatter('chefspec')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
21
35
|
attr_accessor :resources
|
22
36
|
attr_reader :step_into
|
23
37
|
attr_reader :run_context
|
@@ -126,9 +140,7 @@ module ChefSpec
|
|
126
140
|
@dummy_config = Tempfile.new 'chef-config'
|
127
141
|
Chef::Config[:config_file] = @dummy_config.path
|
128
142
|
|
129
|
-
|
130
|
-
# This uses a custom formatter which basically tells Chef to shut up.
|
131
|
-
Chef::Config.add_formatter('chefspec') if Chef::Config.respond_to?(:add_formatter)
|
143
|
+
self.class.register_formatter
|
132
144
|
|
133
145
|
Chef::Log.verbose = true if Chef::Log.respond_to?(:verbose)
|
134
146
|
Chef::Log.level(@options[:log_level])
|
@@ -188,7 +200,7 @@ module ChefSpec
|
|
188
200
|
end
|
189
201
|
|
190
202
|
FILE_RESOURCES = %w(directory cookbook_file file template link remote_directory remote_file)
|
191
|
-
PACKAGE_RESOURCES = %w(package apt_package dpkg_package easy_install_package freebsd_package macports_package portage_package rpm_package chef_gem solaris_package yum_package zypper_package)
|
203
|
+
PACKAGE_RESOURCES = %w(package apt_package dpkg_package easy_install_package freebsd_package macports_package portage_package rpm_package chef_gem solaris_package yum_package zypper_package python_pip)
|
192
204
|
SCRIPT_RESOURCES = %w(script powershell bash csh perl python ruby)
|
193
205
|
MISC_RESOURCES = %w(cron env user execute service log route ruby_block git subversion group mount ohai ifconfig deploy http_request)
|
194
206
|
|
@@ -2,7 +2,11 @@ module ChefSpec
|
|
2
2
|
module Helpers
|
3
3
|
module Describe
|
4
4
|
def described_recipe
|
5
|
-
self.class.metadata
|
5
|
+
metahash = self.class.metadata
|
6
|
+
while metahash.has_key? :example_group
|
7
|
+
metahash = metahash[:example_group]
|
8
|
+
end
|
9
|
+
metahash[:description_args].first
|
6
10
|
end
|
7
11
|
|
8
12
|
def described_cookbook
|
@@ -11,73 +11,72 @@ module ChefSpec
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
14
|
+
{:create_remote_file => [:create], :create_remote_file_if_missing => [:create_if_missing]}.each do |matcher, corr_action|
|
15
|
+
RSpec::Matchers.define matcher do |path|
|
16
|
+
match do |chef_run|
|
17
|
+
if @attributes
|
18
|
+
chef_run.resources.any? do |resource|
|
19
|
+
expected_remote_file?(resource,path,corr_action) &&
|
20
|
+
expected_attributes?(resource)
|
21
|
+
end
|
22
|
+
else
|
23
|
+
chef_run.resources.any? do |resource|
|
24
|
+
expected_remote_file?(resource,path,corr_action)
|
25
|
+
end
|
24
26
|
end
|
25
27
|
end
|
26
|
-
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
chain :with do |attributes|
|
30
|
+
@attributes = attributes
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
resource_type(resource) == 'remote_file' &&
|
38
|
-
resource.path == path &&
|
39
|
-
action.to_sym == :create
|
40
|
-
end
|
33
|
+
def expected_remote_file?(resource,path,corr_action)
|
34
|
+
resource_type(resource) == 'remote_file' &&
|
35
|
+
resource.path == path &&
|
36
|
+
!(corr_action & Array(resource.action).map(&:to_sym)).empty?
|
37
|
+
end
|
41
38
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
def expected_attributes?(resource)
|
40
|
+
@attributes.all? do |attribute,expected|
|
41
|
+
actual = resource.send(attribute)
|
42
|
+
attribute.to_sym == :source ? equal_source?(actual, expected) :
|
43
|
+
actual == expected
|
44
|
+
end
|
47
45
|
end
|
48
|
-
end
|
49
46
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
47
|
+
# Compare two remote_file source attributes for equality.
|
48
|
+
#
|
49
|
+
# @param actual [String, Array<String>] The actual source.
|
50
|
+
# @param expected [String, Array<String>] The expected source.
|
51
|
+
# @return [Boolean] true if they are equal or false if not.
|
52
|
+
def equal_source?(actual, expected)
|
53
|
+
# NOTE: Chef stores the source attribute internally as an array since
|
54
|
+
# version 11 in order to support mirrors.
|
55
|
+
# (see http://docs.opscode.com/breaking_changes_chef_11.html#remote-file-mirror-support-may-break-subclasses)
|
59
56
|
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
# Handle wrong formated expectation for Chef versions >= 11.
|
58
|
+
if actual.is_a?(Array) && expected.is_a?(String)
|
59
|
+
actual == [expected]
|
63
60
|
|
64
|
-
|
65
|
-
|
66
|
-
|
61
|
+
# Handle wrong formated expectation for Chef versions < 11.
|
62
|
+
elsif actual.is_a?(String) && expected.is_a?(Array)
|
63
|
+
[actual] == expected
|
67
64
|
|
68
|
-
|
69
|
-
|
70
|
-
|
65
|
+
# Else assume the actual matches the expected type (String or Array).
|
66
|
+
else
|
67
|
+
actual == expected
|
68
|
+
end
|
71
69
|
end
|
72
|
-
end
|
73
70
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
71
|
+
failure_message_for_should do |actual|
|
72
|
+
message = "No remote_file named '#{path}' for action #{corr_action} found"
|
73
|
+
message << " with:\n#{@attributes}" unless @attributes.nil?
|
74
|
+
message
|
75
|
+
end
|
78
76
|
|
79
|
-
|
80
|
-
|
77
|
+
failure_message_for_should_not do |actual|
|
78
|
+
"Found remote_file named '#{path}' that should not exist."
|
79
|
+
end
|
81
80
|
end
|
82
81
|
end
|
83
82
|
end
|
@@ -2,34 +2,30 @@ require 'chefspec/matchers/shared'
|
|
2
2
|
|
3
3
|
module ChefSpec
|
4
4
|
module Matchers
|
5
|
-
RSpec::Matchers.define :create_file_with_content do |path,
|
5
|
+
RSpec::Matchers.define :create_file_with_content do |path, expected|
|
6
6
|
match do |chef_run|
|
7
|
-
chef_run.resources.any? do |resource|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
cookbook_name = resource.cookbook || resource.cookbook_name
|
18
|
-
cookbook = chef_run.run_context.cookbook_collection[cookbook_name]
|
19
|
-
@actual_content = File.read(cookbook.preferred_filename_on_disk_location(chef_run.node, :files, resource.source, resource.path))
|
20
|
-
end
|
7
|
+
chef_run.resources.select { |resource| resource.name == path }.any? do |resource|
|
8
|
+
unless ([:create, :create_if_missing] & Array(resource.action).map(&:to_sym)).empty?
|
9
|
+
@actual_content = case resource_type(resource)
|
10
|
+
when 'template'
|
11
|
+
content_from_template(chef_run, resource)
|
12
|
+
when 'file'
|
13
|
+
content_from_file(chef_run, resource)
|
14
|
+
when 'cookbook_file'
|
15
|
+
content_from_cookbook_file(chef_run, resource)
|
16
|
+
end
|
21
17
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
18
|
+
if expected.is_a?(Regexp)
|
19
|
+
@actual_content.to_s =~ expected
|
20
|
+
else
|
21
|
+
@actual_content.to_s.include?(expected)
|
27
22
|
end
|
28
23
|
end
|
29
24
|
end
|
30
25
|
end
|
26
|
+
|
31
27
|
failure_message_for_should do |actual|
|
32
|
-
"File content:\n#{@actual_content} does not match expected:\n#{
|
28
|
+
"File content:\n#{@actual_content} does not match expected:\n#{expected}"
|
33
29
|
end
|
34
30
|
end
|
35
31
|
end
|
@@ -2,11 +2,7 @@ require 'chefspec/matchers/shared'
|
|
2
2
|
|
3
3
|
module ChefSpec
|
4
4
|
module Matchers
|
5
|
-
|
6
|
-
CHEF_GEM_SUPPORTED = defined?(::Chef::Resource::ChefGem)
|
7
|
-
PACKAGE_TYPES = [:package, :gem_package, :chef_gem, :yum_package]
|
8
|
-
PACKAGE_TYPES << :chef_gem if CHEF_GEM_SUPPORTED
|
9
|
-
define_resource_matchers([:install, :remove, :upgrade, :purge], PACKAGE_TYPES, :package_name)
|
5
|
+
define_resource_matchers([:install, :remove, :upgrade, :purge], [:package, :gem_package, :chef_gem, :yum_package], :package_name)
|
10
6
|
|
11
7
|
RSpec::Matchers.define :install_package_at_version do |package_name, version|
|
12
8
|
match do |chef_run|
|
@@ -15,6 +11,7 @@ module ChefSpec
|
|
15
11
|
end
|
16
12
|
end
|
17
13
|
end
|
14
|
+
|
18
15
|
RSpec::Matchers.define :install_yum_package_at_version do |package_name, version|
|
19
16
|
match do |chef_run|
|
20
17
|
chef_run.resources.any? do |resource|
|
@@ -22,6 +19,7 @@ module ChefSpec
|
|
22
19
|
end
|
23
20
|
end
|
24
21
|
end
|
22
|
+
|
25
23
|
RSpec::Matchers.define :install_gem_package_at_version do |package_name, version|
|
26
24
|
match do |chef_run|
|
27
25
|
chef_run.resources.any? do |resource|
|
@@ -29,12 +27,13 @@ module ChefSpec
|
|
29
27
|
end
|
30
28
|
end
|
31
29
|
end
|
30
|
+
|
32
31
|
RSpec::Matchers.define :install_chef_gem_at_version do |package_name, version|
|
33
32
|
match do |chef_run|
|
34
33
|
chef_run.resources.any? do |resource|
|
35
34
|
resource_type(resource) == 'chef_gem' and resource.package_name == package_name and resource.action.to_s.include? 'install' and resource.version == version
|
36
35
|
end
|
37
36
|
end
|
38
|
-
end
|
37
|
+
end
|
39
38
|
end
|
40
39
|
end
|
@@ -5,9 +5,9 @@ module ChefSpec
|
|
5
5
|
RSpec::Matchers.define :execute_ruby_block do |block_name|
|
6
6
|
match do |chef_run|
|
7
7
|
chef_run.resources.any? do |resource|
|
8
|
-
resource_type(resource) == 'ruby_block' and resource.name
|
8
|
+
resource_type(resource) == 'ruby_block' and block_name === resource.name
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
13
|
-
end
|
13
|
+
end
|
@@ -3,6 +3,7 @@ begin
|
|
3
3
|
require 'chef/provider/template_finder'
|
4
4
|
rescue LoadError
|
5
5
|
end
|
6
|
+
|
6
7
|
# Given a resource return the unqualified type it is
|
7
8
|
#
|
8
9
|
# @param [String] resource A Chef Resource
|
@@ -29,10 +30,11 @@ def define_resource_matchers(actions, resource_types, name_attribute)
|
|
29
30
|
RSpec::Matchers.define "#{action}_#{resource_type}".to_sym do |name|
|
30
31
|
match do |chef_run|
|
31
32
|
accepted_types = [resource_type.to_s]
|
32
|
-
accepted_types
|
33
|
+
accepted_types += ['template', 'cookbook_file'] if action.to_s == 'create' and resource_type.to_s == 'file'
|
33
34
|
chef_run.resources.any? do |resource|
|
34
|
-
accepted_types.include? resource_type(resource) and
|
35
|
-
|
35
|
+
(accepted_types.include? resource_type(resource) and
|
36
|
+
name === resource.send(name_attribute) and
|
37
|
+
resource_actions(resource).include? action.to_s)
|
36
38
|
end
|
37
39
|
end
|
38
40
|
failure_message_for_should do |actual|
|
@@ -45,39 +47,83 @@ def define_resource_matchers(actions, resource_types, name_attribute)
|
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
|
-
#
|
50
|
+
# Compute the contents of a template using Chef's templating logic.
|
51
|
+
#
|
52
|
+
# @param [Chef::RunContext] chef_run
|
53
|
+
# the run context for the node
|
54
|
+
# @param [Chef::Provider::Template] template
|
55
|
+
# the template resource
|
49
56
|
#
|
50
|
-
# @
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
# @return [String]
|
58
|
+
def content_from_template(chef_run, template)
|
59
|
+
cookbook_name = template.cookbook || template.cookbook_name
|
60
|
+
template_location = cookbook_collection(chef_run.node)[cookbook_name].preferred_filename_on_disk_location(chef_run.node, :templates, template.source)
|
61
|
+
|
62
|
+
if Chef::Mixin::Template.const_defined?(:TemplateContext) # Chef 11+
|
63
|
+
template_context = Chef::Mixin::Template::TemplateContext.new([])
|
64
|
+
template_context.update({
|
65
|
+
:node => chef_run.node,
|
66
|
+
:template_finder => template_finder(chef_run, cookbook_name),
|
67
|
+
}.merge(template.variables))
|
68
|
+
template_context.render_template(template_location)
|
69
|
+
else
|
70
|
+
template.provider.new(template, chef_run.run_context).send(:render_with_context, template_location) do |file|
|
71
|
+
File.read(file.path)
|
72
|
+
end
|
61
73
|
end
|
62
|
-
Erubis::Eruby.new(IO.read(template_path(template, node))).evaluate(context)
|
63
74
|
end
|
64
75
|
|
65
|
-
#
|
76
|
+
# Get the contents of a file resource.
|
66
77
|
#
|
67
|
-
# @param [Chef::
|
68
|
-
#
|
69
|
-
|
70
|
-
|
78
|
+
# @param [Chef::RunContext] chef_run
|
79
|
+
# the run context for the node
|
80
|
+
# @param [Chef::Provider::File] file
|
81
|
+
# the file resource
|
82
|
+
#
|
83
|
+
# @return [String]
|
84
|
+
def content_from_file(chef_run, file)
|
85
|
+
file.content
|
86
|
+
end
|
87
|
+
|
88
|
+
# Get the contents of a cookbook file using Chef.
|
89
|
+
#
|
90
|
+
# @param [Chef::RunContext] chef_run
|
91
|
+
# the run context for the node
|
92
|
+
# @param [Chef::Provider::CookbookFile] cookbook_file
|
93
|
+
# the file resource
|
94
|
+
def content_from_cookbook_file(chef_run, cookbook_file)
|
95
|
+
cookbook_name = cookbook_file.cookbook || cookbook_file.cookbook_name
|
96
|
+
cookbook = chef_run.run_context.cookbook_collection[cookbook_name]
|
97
|
+
File.read(cookbook.preferred_filename_on_disk_location(chef_run.node, :files, cookbook_file.source, cookbook_file.path))
|
98
|
+
end
|
99
|
+
|
100
|
+
# The cookbook collection for the current Chef run context. Handles
|
101
|
+
# the differing cases between Chef 10 and Chef 11.
|
102
|
+
#
|
103
|
+
# @param [Chef::Node] node
|
104
|
+
# the Chef node to get the cookbook collection from
|
105
|
+
#
|
106
|
+
# @return [Array<Chef::Cookbook>]
|
107
|
+
def cookbook_collection(node)
|
71
108
|
if node.respond_to?(:run_context)
|
72
|
-
|
109
|
+
node.run_context.cookbook_collection # Chef 11+
|
73
110
|
else
|
74
|
-
|
111
|
+
node.cookbook_collection # Chef 10
|
75
112
|
end
|
76
|
-
cookbook.preferred_filename_on_disk_location(node, :templates, template.source)
|
77
113
|
end
|
78
114
|
|
79
|
-
|
80
|
-
|
81
|
-
|
115
|
+
# Return a new instance of the TemplateFinder if we are running on Chef 11.
|
116
|
+
#
|
117
|
+
# @param [Chef::RunContext] chef_run
|
118
|
+
# the run context for the noe
|
119
|
+
# @param [String] cookbook_name
|
120
|
+
# the name of the cookbook
|
121
|
+
#
|
122
|
+
# @return [Chef::Provider::TemplateFinder, nil]
|
123
|
+
def template_finder(chef_run, cookbook_name)
|
124
|
+
if Chef::Provider.const_defined?(:TemplateFinder) # Chef 11+
|
125
|
+
Chef::Provider::TemplateFinder.new(chef_run.run_context, cookbook_name, chef_run.node)
|
126
|
+
else
|
127
|
+
nil
|
82
128
|
end
|
83
129
|
end
|
data/lib/chefspec/minitest.rb
CHANGED
@@ -134,13 +134,6 @@ module ChefSpec
|
|
134
134
|
resources.select{|r| r.resource_name == type}
|
135
135
|
end
|
136
136
|
|
137
|
-
def cookbook_file_content(file_resource)
|
138
|
-
file = cookbook_files(file_resource.cookbook_name).find do |f|
|
139
|
-
Pathname.new(f).basename.to_s == file_resource.path
|
140
|
-
end
|
141
|
-
File.read(file)
|
142
|
-
end
|
143
|
-
|
144
137
|
def cookbook_files(cookbook)
|
145
138
|
run_context.cookbook_collection[cookbook].file_filenames
|
146
139
|
end
|
@@ -150,11 +143,11 @@ module ChefSpec
|
|
150
143
|
f.path == file.path &&
|
151
144
|
case f.resource_name
|
152
145
|
when :cookbook_file
|
153
|
-
|
146
|
+
content_from_cookbook_file(chef_run, f)
|
154
147
|
when :file
|
155
|
-
f
|
148
|
+
content_from_file(chef_run, f)
|
156
149
|
when :template
|
157
|
-
|
150
|
+
content_from_template(chef_run, f)
|
158
151
|
else raise NotImplementedError,
|
159
152
|
":#{f.resource_name} not supported for comparison"
|
160
153
|
end.include?(content)
|
@@ -179,6 +172,7 @@ module ChefSpec
|
|
179
172
|
:cookbook_path => default_cookbook_path).converge recipe_for_module(spec_mod)
|
180
173
|
override_minitest_resources(chef_run.run_context, spec_mod)
|
181
174
|
override_minitest_assertions(chef_run)
|
175
|
+
share_object(spec_mod, :chef_run, chef_run)
|
182
176
|
share_object(spec_mod, :node, chef_run.node)
|
183
177
|
share_object(spec_mod, :resources, chef_run.resources)
|
184
178
|
share_object(spec_mod, :run_context, chef_run.run_context)
|
@@ -1,14 +1,21 @@
|
|
1
1
|
# Ruby stdlib Hash class
|
2
2
|
class Hash
|
3
|
-
|
4
3
|
# Monkey-patch to stdlib Hash to give us Mash style lookup
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
self[
|
10
|
-
|
11
|
-
|
4
|
+
def method_missing(m, *args, &block)
|
5
|
+
if has_key?(m.to_sym)
|
6
|
+
self[m.to_sym]
|
7
|
+
elsif has_key?(m.to_s)
|
8
|
+
self[m.to_s]
|
9
|
+
else
|
10
|
+
super
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Monkey-patch to stdlib Hash to correspond to Mash-style lookup
|
15
|
+
# @see {Hash#respond_to?}
|
16
|
+
def respond_to?(m)
|
17
|
+
if has_key?(m.to_sym) || has_key?(m.to_s)
|
18
|
+
true
|
12
19
|
else
|
13
20
|
super
|
14
21
|
end
|
data/lib/chefspec/version.rb
CHANGED
metadata
CHANGED
@@ -1,90 +1,74 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chefspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 2.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Andrew Crump
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-08-22 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: chef
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '10.0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '10.0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: erubis
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: fauxhai
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: 0.1.1
|
54
|
-
- - <
|
45
|
+
- - ~>
|
55
46
|
- !ruby/object:Gem::Version
|
56
|
-
version: '
|
47
|
+
version: '1.1'
|
57
48
|
type: :runtime
|
58
49
|
prerelease: false
|
59
50
|
version_requirements: !ruby/object:Gem::Requirement
|
60
|
-
none: false
|
61
51
|
requirements:
|
62
|
-
- -
|
63
|
-
- !ruby/object:Gem::Version
|
64
|
-
version: 0.1.1
|
65
|
-
- - <
|
52
|
+
- - ~>
|
66
53
|
- !ruby/object:Gem::Version
|
67
|
-
version: '
|
54
|
+
version: '1.1'
|
68
55
|
- !ruby/object:Gem::Dependency
|
69
56
|
name: minitest-chef-handler
|
70
57
|
requirement: !ruby/object:Gem::Requirement
|
71
|
-
none: false
|
72
58
|
requirements:
|
73
|
-
- -
|
59
|
+
- - '>='
|
74
60
|
- !ruby/object:Gem::Version
|
75
61
|
version: 0.6.0
|
76
62
|
type: :runtime
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
none: false
|
80
65
|
requirements:
|
81
|
-
- -
|
66
|
+
- - '>='
|
82
67
|
- !ruby/object:Gem::Version
|
83
68
|
version: 0.6.0
|
84
69
|
- !ruby/object:Gem::Dependency
|
85
70
|
name: rspec
|
86
71
|
requirement: !ruby/object:Gem::Requirement
|
87
|
-
none: false
|
88
72
|
requirements:
|
89
73
|
- - ~>
|
90
74
|
- !ruby/object:Gem::Version
|
@@ -92,7 +76,6 @@ dependencies:
|
|
92
76
|
type: :runtime
|
93
77
|
prerelease: false
|
94
78
|
version_requirements: !ruby/object:Gem::Requirement
|
95
|
-
none: false
|
96
79
|
requirements:
|
97
80
|
- - ~>
|
98
81
|
- !ruby/object:Gem::Version
|
@@ -100,105 +83,94 @@ dependencies:
|
|
100
83
|
- !ruby/object:Gem::Dependency
|
101
84
|
name: rake
|
102
85
|
requirement: !ruby/object:Gem::Requirement
|
103
|
-
none: false
|
104
86
|
requirements:
|
105
|
-
- -
|
87
|
+
- - '>='
|
106
88
|
- !ruby/object:Gem::Version
|
107
89
|
version: '0'
|
108
90
|
type: :development
|
109
91
|
prerelease: false
|
110
92
|
version_requirements: !ruby/object:Gem::Requirement
|
111
|
-
none: false
|
112
93
|
requirements:
|
113
|
-
- -
|
94
|
+
- - '>='
|
114
95
|
- !ruby/object:Gem::Version
|
115
96
|
version: '0'
|
116
97
|
- !ruby/object:Gem::Dependency
|
117
98
|
name: yard
|
118
99
|
requirement: !ruby/object:Gem::Requirement
|
119
|
-
none: false
|
120
100
|
requirements:
|
121
101
|
- - ~>
|
122
102
|
- !ruby/object:Gem::Version
|
123
|
-
version: 0.8
|
103
|
+
version: '0.8'
|
124
104
|
type: :development
|
125
105
|
prerelease: false
|
126
106
|
version_requirements: !ruby/object:Gem::Requirement
|
127
|
-
none: false
|
128
107
|
requirements:
|
129
108
|
- - ~>
|
130
109
|
- !ruby/object:Gem::Version
|
131
|
-
version: 0.8
|
110
|
+
version: '0.8'
|
132
111
|
- !ruby/object:Gem::Dependency
|
133
112
|
name: aruba
|
134
113
|
requirement: !ruby/object:Gem::Requirement
|
135
|
-
none: false
|
136
114
|
requirements:
|
137
115
|
- - ~>
|
138
116
|
- !ruby/object:Gem::Version
|
139
|
-
version: 0.
|
117
|
+
version: '0.5'
|
140
118
|
type: :development
|
141
119
|
prerelease: false
|
142
120
|
version_requirements: !ruby/object:Gem::Requirement
|
143
|
-
none: false
|
144
121
|
requirements:
|
145
122
|
- - ~>
|
146
123
|
- !ruby/object:Gem::Version
|
147
|
-
version: 0.
|
124
|
+
version: '0.5'
|
148
125
|
- !ruby/object:Gem::Dependency
|
149
126
|
name: cucumber
|
150
127
|
requirement: !ruby/object:Gem::Requirement
|
151
|
-
none: false
|
152
128
|
requirements:
|
153
129
|
- - ~>
|
154
130
|
- !ruby/object:Gem::Version
|
155
|
-
version: 1.
|
131
|
+
version: '1.3'
|
156
132
|
type: :development
|
157
133
|
prerelease: false
|
158
134
|
version_requirements: !ruby/object:Gem::Requirement
|
159
|
-
none: false
|
160
135
|
requirements:
|
161
136
|
- - ~>
|
162
137
|
- !ruby/object:Gem::Version
|
163
|
-
version: 1.
|
138
|
+
version: '1.3'
|
164
139
|
- !ruby/object:Gem::Dependency
|
165
140
|
name: i18n
|
166
141
|
requirement: !ruby/object:Gem::Requirement
|
167
|
-
none: false
|
168
142
|
requirements:
|
169
143
|
- - ~>
|
170
144
|
- !ruby/object:Gem::Version
|
171
|
-
version: 0.6
|
145
|
+
version: '0.6'
|
172
146
|
type: :development
|
173
147
|
prerelease: false
|
174
148
|
version_requirements: !ruby/object:Gem::Requirement
|
175
|
-
none: false
|
176
149
|
requirements:
|
177
150
|
- - ~>
|
178
151
|
- !ruby/object:Gem::Version
|
179
|
-
version: 0.6
|
152
|
+
version: '0.6'
|
180
153
|
- !ruby/object:Gem::Dependency
|
181
154
|
name: simplecov
|
182
155
|
requirement: !ruby/object:Gem::Requirement
|
183
|
-
none: false
|
184
156
|
requirements:
|
185
157
|
- - ~>
|
186
158
|
- !ruby/object:Gem::Version
|
187
|
-
version: 0.7
|
159
|
+
version: '0.7'
|
188
160
|
type: :development
|
189
161
|
prerelease: false
|
190
162
|
version_requirements: !ruby/object:Gem::Requirement
|
191
|
-
none: false
|
192
163
|
requirements:
|
193
164
|
- - ~>
|
194
165
|
- !ruby/object:Gem::Version
|
195
|
-
version: 0.7
|
166
|
+
version: '0.7'
|
196
167
|
description: Write RSpec examples for Opscode Chef recipes
|
197
168
|
email:
|
198
169
|
executables: []
|
199
170
|
extensions: []
|
200
171
|
extra_rdoc_files: []
|
201
172
|
files:
|
173
|
+
- lib/chef/expect_exception.rb
|
202
174
|
- lib/chef/formatters/chefspec.rb
|
203
175
|
- lib/chef/knife/cookbook_create_specs.rb
|
204
176
|
- lib/chefspec/chef_runner.rb
|
@@ -214,6 +186,7 @@ files:
|
|
214
186
|
- lib/chefspec/matchers/log.rb
|
215
187
|
- lib/chefspec/matchers/notifications.rb
|
216
188
|
- lib/chefspec/matchers/package.rb
|
189
|
+
- lib/chefspec/matchers/python.rb
|
217
190
|
- lib/chefspec/matchers/ruby_block.rb
|
218
191
|
- lib/chefspec/matchers/script.rb
|
219
192
|
- lib/chefspec/matchers/service.rb
|
@@ -229,33 +202,26 @@ files:
|
|
229
202
|
homepage: http://acrmp.github.com/chefspec
|
230
203
|
licenses:
|
231
204
|
- MIT
|
205
|
+
metadata: {}
|
232
206
|
post_install_message:
|
233
207
|
rdoc_options: []
|
234
208
|
require_paths:
|
235
209
|
- lib
|
236
210
|
required_ruby_version: !ruby/object:Gem::Requirement
|
237
|
-
none: false
|
238
211
|
requirements:
|
239
|
-
- -
|
212
|
+
- - '>='
|
240
213
|
- !ruby/object:Gem::Version
|
241
|
-
version: '
|
242
|
-
segments:
|
243
|
-
- 0
|
244
|
-
hash: 1265930440020953415
|
214
|
+
version: '1.9'
|
245
215
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
246
|
-
none: false
|
247
216
|
requirements:
|
248
|
-
- -
|
217
|
+
- - '>='
|
249
218
|
- !ruby/object:Gem::Version
|
250
219
|
version: '0'
|
251
|
-
segments:
|
252
|
-
- 0
|
253
|
-
hash: 1265930440020953415
|
254
220
|
requirements: []
|
255
221
|
rubyforge_project:
|
256
|
-
rubygems_version:
|
222
|
+
rubygems_version: 2.0.3
|
257
223
|
signing_key:
|
258
|
-
specification_version:
|
259
|
-
summary: chefspec-
|
224
|
+
specification_version: 4
|
225
|
+
summary: chefspec-2.0.0
|
260
226
|
test_files: []
|
261
227
|
has_rdoc:
|