chefspec 3.4.0 → 4.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 +4 -4
- data/.travis.yml +2 -19
- data/CHANGELOG.md +32 -1
- data/CONTRIBUTING.md +1 -1
- data/README.md +37 -9
- data/chefspec.gemspec +2 -3
- data/examples/render_file/spec/default_spec.rb +32 -17
- data/examples/server/recipes/render_with_cached.rb +3 -0
- data/examples/server/spec/client_spec.rb +1 -1
- data/examples/server/spec/data_bag_spec.rb +1 -1
- data/examples/server/spec/environment_spec.rb +1 -1
- data/examples/server/spec/node_spec.rb +1 -1
- data/examples/server/spec/render_with_cached_spec.rb +16 -0
- data/examples/server/spec/role_spec.rb +1 -1
- data/features/server.feature +10 -12
- data/features/support/executor.rb +2 -0
- data/gemfiles/{chef-11.0.0.gemfile → chef-11.12.0.gemfile} +1 -1
- data/gemfiles/chef-master.gemfile +1 -1
- data/lib/chefspec.rb +1 -0
- data/lib/chefspec/api/erl_call.rb +5 -5
- data/lib/chefspec/api/execute.rb +5 -5
- data/lib/chefspec/api/powershell_script.rb +5 -5
- data/lib/chefspec/api/ruby_block.rb +2 -2
- data/lib/chefspec/api/script.rb +13 -2
- data/lib/chefspec/cacher.rb +2 -1
- data/lib/chefspec/coverage.rb +10 -2
- data/lib/chefspec/expect_exception.rb +0 -2
- data/lib/chefspec/extensions/chef/lwrp_base.rb +5 -1
- data/lib/chefspec/extensions/chef/resource/freebsd_package.rb +19 -0
- data/lib/chefspec/librarian.rb +5 -2
- data/lib/chefspec/macros.rb +3 -3
- data/lib/chefspec/matchers/do_nothing_matcher.rb +4 -2
- data/lib/chefspec/matchers/include_recipe_matcher.rb +2 -2
- data/lib/chefspec/matchers/link_to_matcher.rb +11 -5
- data/lib/chefspec/matchers/notifications_matcher.rb +2 -2
- data/lib/chefspec/matchers/render_file_matcher.rb +9 -3
- data/lib/chefspec/matchers/resource_matcher.rb +2 -2
- data/lib/chefspec/matchers/state_attrs_matcher.rb +2 -2
- data/lib/chefspec/matchers/subscribes_matcher.rb +4 -4
- data/lib/chefspec/renderer.rb +1 -1
- data/lib/chefspec/rspec.rb +1 -0
- data/lib/chefspec/runner.rb +2 -1
- data/lib/chefspec/server.rb +90 -19
- data/lib/chefspec/version.rb +1 -1
- data/spec/unit/cacher_spec.rb +1 -1
- data/spec/unit/expect_exception_spec.rb +6 -6
- data/spec/unit/extensions/lwrp_base_spec.rb +9 -1
- data/spec/unit/macros_spec.rb +6 -6
- data/spec/unit/matchers/include_recipe_matcher_spec.rb +6 -6
- data/spec/unit/matchers/link_to_matcher_spec.rb +31 -15
- data/spec/unit/matchers/notifications_matcher_spec.rb +4 -4
- data/spec/unit/matchers/render_file_matcher_spec.rb +19 -10
- data/spec/unit/matchers/state_attrs_matcher_spec.rb +28 -24
- data/spec/unit/matchers/subscribes_matcher_spec.rb +7 -7
- data/spec/unit/renderer_spec.rb +7 -7
- data/spec/unit/runner_spec.rb +39 -9
- metadata +10 -25
- data/gemfiles/chef-11.2.0.gemfile +0 -5
- data/gemfiles/chef-11.4.4.gemfile +0 -5
- data/gemfiles/chef-11.6.0.gemfile +0 -5
- data/gemfiles/chef-11.8.0.gemfile +0 -5
@@ -15,19 +15,19 @@ module ChefSpec::API
|
|
15
15
|
# The Examples section demonstrates the different ways to test a
|
16
16
|
# +powershell_script+ resource with ChefSpec.
|
17
17
|
#
|
18
|
-
# @example Assert that a +powershell_script+ was
|
18
|
+
# @example Assert that a +powershell_script+ was run
|
19
19
|
# expect(chef_run).to run_powershell_script('/tmp')
|
20
20
|
#
|
21
|
-
# @example Assert that a +powershell_script+ was
|
21
|
+
# @example Assert that a +powershell_script+ was run with predicate matchers
|
22
22
|
# expect(chef_run).to run_powershell_script('/tmp').with_user('svargo')
|
23
23
|
#
|
24
|
-
# @example Assert that a +powershell_script+ was
|
24
|
+
# @example Assert that a +powershell_script+ was run with attributes
|
25
25
|
# expect(chef_run).to run_powershell_script('/tmp').with(user: 'svargo')
|
26
26
|
#
|
27
|
-
# @example Assert that a +powershell_script+ was
|
27
|
+
# @example Assert that a +powershell_script+ was run using a regex
|
28
28
|
# expect(chef_run).to run_powershell_script('/tmp').with(user: /sva(.+)/)
|
29
29
|
#
|
30
|
-
# @example Assert that a +powershell_script+ was _not_
|
30
|
+
# @example Assert that a +powershell_script+ was _not_ run
|
31
31
|
# expect(chef_run).to_not run_powershell_script('/tmp')
|
32
32
|
#
|
33
33
|
#
|
@@ -18,10 +18,10 @@ module ChefSpec::API
|
|
18
18
|
# The Examples section demonstrates the different ways to test a
|
19
19
|
# +ruby_block+ resource with ChefSpec.
|
20
20
|
#
|
21
|
-
# @example Assert that a +ruby_block+ was
|
21
|
+
# @example Assert that a +ruby_block+ was run
|
22
22
|
# expect(chef_run).to run_ruby_block('do_something')
|
23
23
|
#
|
24
|
-
# @example Assert that a +ruby_block+ was _not_
|
24
|
+
# @example Assert that a +ruby_block+ was _not_ run
|
25
25
|
# expect(chef_run).to_not run_ruby_block('do_something')
|
26
26
|
#
|
27
27
|
#
|
data/lib/chefspec/api/script.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module ChefSpec::API
|
2
2
|
# @since 1.0.0
|
3
3
|
module ScriptMatchers
|
4
|
-
ChefSpec::Runner.define_runner_method :script
|
5
|
-
|
6
4
|
#
|
7
5
|
# Assert that a +bash+ resource exists in the Chef run with the
|
8
6
|
# action +:run+. Given a Chef Recipe that runs "command" using
|
@@ -40,6 +38,8 @@ module ChefSpec::API
|
|
40
38
|
ChefSpec::Matchers::ResourceMatcher.new(:bash, :run, resource_name)
|
41
39
|
end
|
42
40
|
|
41
|
+
ChefSpec::Runner.define_runner_method :bash
|
42
|
+
|
43
43
|
#
|
44
44
|
# Assert that a +csh+ resource exists in the Chef run with the
|
45
45
|
# action +:run+. Given a Chef Recipe that runs "command" using
|
@@ -77,6 +77,8 @@ module ChefSpec::API
|
|
77
77
|
ChefSpec::Matchers::ResourceMatcher.new(:csh, :run, resource_name)
|
78
78
|
end
|
79
79
|
|
80
|
+
ChefSpec::Runner.define_runner_method :csh
|
81
|
+
|
80
82
|
#
|
81
83
|
# Assert that a +perl+ resource exists in the Chef run with the
|
82
84
|
# action +:run+. Given a Chef Recipe that runs "command" using
|
@@ -114,6 +116,8 @@ module ChefSpec::API
|
|
114
116
|
ChefSpec::Matchers::ResourceMatcher.new(:perl, :run, resource_name)
|
115
117
|
end
|
116
118
|
|
119
|
+
ChefSpec::Runner.define_runner_method :perl
|
120
|
+
|
117
121
|
#
|
118
122
|
# Assert that a +python+ resource exists in the Chef run with the
|
119
123
|
# action +:run+. Given a Chef Recipe that runs "command" using
|
@@ -151,6 +155,8 @@ module ChefSpec::API
|
|
151
155
|
ChefSpec::Matchers::ResourceMatcher.new(:python, :run, resource_name)
|
152
156
|
end
|
153
157
|
|
158
|
+
ChefSpec::Runner.define_runner_method :python
|
159
|
+
|
154
160
|
#
|
155
161
|
# Assert that a +ruby+ resource exists in the Chef run with the
|
156
162
|
# action +:run+. Given a Chef Recipe that runs "command" using
|
@@ -188,6 +194,8 @@ module ChefSpec::API
|
|
188
194
|
ChefSpec::Matchers::ResourceMatcher.new(:ruby, :run, resource_name)
|
189
195
|
end
|
190
196
|
|
197
|
+
ChefSpec::Runner.define_runner_method :ruby
|
198
|
+
|
191
199
|
#
|
192
200
|
# Assert that a +script+ resource exists in the Chef run with the
|
193
201
|
# action +:run+. Given a Chef Recipe that runs "command" using
|
@@ -224,5 +232,8 @@ module ChefSpec::API
|
|
224
232
|
def run_script(resource_name)
|
225
233
|
ChefSpec::Matchers::ResourceMatcher.new(:script, :run, resource_name)
|
226
234
|
end
|
235
|
+
|
236
|
+
|
237
|
+
ChefSpec::Runner.define_runner_method :script
|
227
238
|
end
|
228
239
|
end
|
data/lib/chefspec/cacher.rb
CHANGED
@@ -34,7 +34,8 @@ module ChefSpec
|
|
34
34
|
FINALIZER = lambda { |id| @@cache.delete(id) }
|
35
35
|
|
36
36
|
def cached(name, &block)
|
37
|
-
location
|
37
|
+
location = ancestors.first.metadata[:location]
|
38
|
+
location ||= ancestors.first.metadata[:parent_example_group][:location]
|
38
39
|
|
39
40
|
define_method(name) do
|
40
41
|
key = [location, name.to_s].join('.')
|
data/lib/chefspec/coverage.rb
CHANGED
@@ -161,11 +161,19 @@ module ChefSpec
|
|
161
161
|
end
|
162
162
|
|
163
163
|
def source_file
|
164
|
-
@source_file ||=
|
164
|
+
@source_file ||= if @resource.source_line
|
165
|
+
shortname(@resource.source_line.split(':').first)
|
166
|
+
else
|
167
|
+
'Unknown'
|
168
|
+
end
|
165
169
|
end
|
166
170
|
|
167
171
|
def source_line
|
168
|
-
@source_line ||= @resource.source_line
|
172
|
+
@source_line ||= if @resource.source_line
|
173
|
+
@resource.source_line.split(':', 2).last.to_i
|
174
|
+
else
|
175
|
+
'Unknown'
|
176
|
+
end
|
169
177
|
end
|
170
178
|
|
171
179
|
def touch!
|
@@ -39,7 +39,11 @@ class Chef
|
|
39
39
|
[self, superclass].each do |resource_holder|
|
40
40
|
look_in_parents = false
|
41
41
|
if resource_holder.const_defined?(class_name, look_in_parents)
|
42
|
-
resource_holder.send(:remove_const, class_name)
|
42
|
+
old_class = resource_holder.send(:remove_const, class_name)
|
43
|
+
|
44
|
+
if resource_holder.respond_to?(:resource_classes)
|
45
|
+
resource_holder.resource_classes.delete(old_class)
|
46
|
+
end
|
43
47
|
end
|
44
48
|
end
|
45
49
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'chef/resource/freebsd_package'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Resource
|
5
|
+
class FreebsdPackage < Chef::Resource::Package
|
6
|
+
#
|
7
|
+
# Chef decided it was a good idea to just shellout inside of a resource.
|
8
|
+
# Not only is that a horrible fucking idea, but I got flak when I asked
|
9
|
+
# to change it. So we are just going to monkey patch the fucking thing so
|
10
|
+
# it does not shell out.
|
11
|
+
#
|
12
|
+
# @return [false]
|
13
|
+
#
|
14
|
+
def supports_pkgng?
|
15
|
+
false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/chefspec/librarian.rb
CHANGED
@@ -25,7 +25,7 @@ module ChefSpec
|
|
25
25
|
#
|
26
26
|
def setup!
|
27
27
|
env = ::Librarian::Chef::Environment.new(project_path: Dir.pwd)
|
28
|
-
env.config_db.local['path'] = @tmpdir
|
28
|
+
@originalpath, env.config_db.local['path'] = env.config_db.local['path'], @tmpdir
|
29
29
|
::Librarian::Action::Resolve.new(env).run
|
30
30
|
::Librarian::Action::Install.new(env).run
|
31
31
|
|
@@ -33,9 +33,12 @@ module ChefSpec
|
|
33
33
|
end
|
34
34
|
|
35
35
|
#
|
36
|
-
# Remove the temporary directory.
|
36
|
+
# Remove the temporary directory and restore the librarian-chef cookbook path.
|
37
37
|
#
|
38
38
|
def teardown!
|
39
|
+
env = ::Librarian::Chef::Environment.new(project_path: Dir.pwd)
|
40
|
+
env.config_db.local['path'] = @originalpath
|
41
|
+
|
39
42
|
FileUtils.rm_rf(@tmpdir) if File.exists?(@tmpdir)
|
40
43
|
end
|
41
44
|
end
|
data/lib/chefspec/macros.rb
CHANGED
@@ -44,11 +44,11 @@ module ChefSpec
|
|
44
44
|
scope = self.is_a?(Class) ? self : self.class
|
45
45
|
|
46
46
|
metahash = scope.metadata
|
47
|
-
while metahash.has_key?(:
|
48
|
-
metahash = metahash[:
|
47
|
+
while metahash.has_key?(:parent_example_group)
|
48
|
+
metahash = metahash[:parent_example_group]
|
49
49
|
end
|
50
50
|
|
51
|
-
metahash[:
|
51
|
+
metahash[:description].to_s
|
52
52
|
end
|
53
53
|
|
54
54
|
#
|
@@ -4,6 +4,8 @@ module ChefSpec::Matchers
|
|
4
4
|
@resource = resource
|
5
5
|
|
6
6
|
if @resource
|
7
|
+
ChefSpec::Coverage.cover!(@resource)
|
8
|
+
|
7
9
|
actions = @resource.performed_actions
|
8
10
|
actions.empty? || actions == [:nothing]
|
9
11
|
else
|
@@ -15,7 +17,7 @@ module ChefSpec::Matchers
|
|
15
17
|
'do nothing'
|
16
18
|
end
|
17
19
|
|
18
|
-
def
|
20
|
+
def failure_message
|
19
21
|
if @resource
|
20
22
|
message = %|expected #{@resource} to do nothing, but the following |
|
21
23
|
message << %|actions were performed:|
|
@@ -35,7 +37,7 @@ module ChefSpec::Matchers
|
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
|
-
def
|
40
|
+
def failure_message_when_negated
|
39
41
|
if @resource
|
40
42
|
message = %|expected #{@resource} to do something, but no actions |
|
41
43
|
message << %|were performed.|
|
@@ -13,11 +13,11 @@ module ChefSpec::Matchers
|
|
13
13
|
%Q{include recipe "#{@recipe_name}"}
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
16
|
+
def failure_message
|
17
17
|
%Q{expected #{loaded_recipes.inspect} to include "#{@recipe_name}"}
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
20
|
+
def failure_message_when_negated
|
21
21
|
%Q{expected "#{@recipe_name}" to not be included}
|
22
22
|
end
|
23
23
|
|
@@ -7,16 +7,22 @@ module ChefSpec::Matchers
|
|
7
7
|
def matches?(link)
|
8
8
|
@link = link
|
9
9
|
|
10
|
-
@link
|
11
|
-
|
12
|
-
|
10
|
+
if @link
|
11
|
+
ChefSpec::Coverage.cover!(@link)
|
12
|
+
|
13
|
+
@link.is_a?(Chef::Resource::Link) &&
|
14
|
+
@link.performed_action?(:create) &&
|
15
|
+
@path === @link.to
|
16
|
+
else
|
17
|
+
false
|
18
|
+
end
|
13
19
|
end
|
14
20
|
|
15
21
|
def description
|
16
22
|
%Q{link to "#{@path}"}
|
17
23
|
end
|
18
24
|
|
19
|
-
def
|
25
|
+
def failure_message
|
20
26
|
if @link.nil?
|
21
27
|
%Q{expected "link[#{@path}]" with action :create to be in Chef run}
|
22
28
|
else
|
@@ -24,7 +30,7 @@ module ChefSpec::Matchers
|
|
24
30
|
end
|
25
31
|
end
|
26
32
|
|
27
|
-
def
|
33
|
+
def failure_message_when_negated
|
28
34
|
%Q{expected "#{@link}" to not link to "#{@path}"}
|
29
35
|
end
|
30
36
|
end
|
@@ -51,7 +51,7 @@ module ChefSpec::Matchers
|
|
51
51
|
message
|
52
52
|
end
|
53
53
|
|
54
|
-
def
|
54
|
+
def failure_message
|
55
55
|
if @resource
|
56
56
|
message = %Q{expected "#{@resource}" to notify "#{@expected_resource_type}[#{@expected_resource_name}]"}
|
57
57
|
message << " with action :#{@action}" if @action
|
@@ -77,7 +77,7 @@ module ChefSpec::Matchers
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
def
|
80
|
+
def failure_message_when_negated
|
81
81
|
if @resource
|
82
82
|
message = %Q{expected "#{@resource}" to not notify "#{@expected_resource_type}[#{@expected_resource_name}]"}
|
83
83
|
message << ", but it did."
|
@@ -6,7 +6,13 @@ module ChefSpec::Matchers
|
|
6
6
|
|
7
7
|
def matches?(runner)
|
8
8
|
@runner = runner
|
9
|
-
|
9
|
+
|
10
|
+
if resource
|
11
|
+
ChefSpec::Coverage.cover!(resource)
|
12
|
+
has_create_action? && matches_content?
|
13
|
+
else
|
14
|
+
false
|
15
|
+
end
|
10
16
|
end
|
11
17
|
|
12
18
|
def with_content(expected_content)
|
@@ -26,7 +32,7 @@ module ChefSpec::Matchers
|
|
26
32
|
message
|
27
33
|
end
|
28
34
|
|
29
|
-
def
|
35
|
+
def failure_message
|
30
36
|
message = %Q{expected Chef run to render "#{@path}"}
|
31
37
|
if @expected_content
|
32
38
|
message << " matching:"
|
@@ -41,7 +47,7 @@ module ChefSpec::Matchers
|
|
41
47
|
message
|
42
48
|
end
|
43
49
|
|
44
|
-
def
|
50
|
+
def failure_message_when_negated
|
45
51
|
message = %Q{expected file "#{@path}"}
|
46
52
|
if @expected_content
|
47
53
|
message << " matching:"
|
@@ -50,7 +50,7 @@ module ChefSpec::Matchers
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
def
|
53
|
+
def failure_message
|
54
54
|
if resource
|
55
55
|
if resource.performed_action?(@expected_action)
|
56
56
|
if unmatched_parameters.empty?
|
@@ -79,7 +79,7 @@ module ChefSpec::Matchers
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
-
def
|
82
|
+
def failure_message_when_negated
|
83
83
|
if resource
|
84
84
|
message = %Q{expected "#{resource.to_s}" actions #{resource.performed_actions.inspect} to not exist}
|
85
85
|
else
|
@@ -18,7 +18,7 @@ module ChefSpec::Matchers
|
|
18
18
|
%Q{have state attributes #{@expected_attrs.inspect}}
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def failure_message
|
22
22
|
if @resource
|
23
23
|
"expected #{state_attrs.inspect} to equal #{@expected_attrs.inspect}"
|
24
24
|
else
|
@@ -32,7 +32,7 @@ module ChefSpec::Matchers
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
35
|
+
def failure_message_when_negated
|
36
36
|
if @resource
|
37
37
|
"expected #{state_attrs.inspect} to not equal " \
|
38
38
|
"#{@expected_attrs.inspect}"
|
@@ -52,12 +52,12 @@ module ChefSpec::Matchers
|
|
52
52
|
@instance.description
|
53
53
|
end
|
54
54
|
|
55
|
-
def
|
56
|
-
@instance.
|
55
|
+
def failure_message
|
56
|
+
@instance.failure_message
|
57
57
|
end
|
58
58
|
|
59
|
-
def
|
60
|
-
@instance.
|
59
|
+
def failure_message_when_negated
|
60
|
+
@instance.failure_message_when_negated
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
data/lib/chefspec/renderer.rb
CHANGED
@@ -108,7 +108,7 @@ module ChefSpec
|
|
108
108
|
def content_from_cookbook_file(chef_run, cookbook_file)
|
109
109
|
cookbook_name = cookbook_file.cookbook || cookbook_file.cookbook_name
|
110
110
|
cookbook = cookbook_collection(chef_run.node)[cookbook_name]
|
111
|
-
File.read(cookbook.preferred_filename_on_disk_location(chef_run.node, :files, cookbook_file.source
|
111
|
+
File.read(cookbook.preferred_filename_on_disk_location(chef_run.node, :files, cookbook_file.source))
|
112
112
|
end
|
113
113
|
|
114
114
|
# The cookbook collection for the current Chef run context. Handles
|
data/lib/chefspec/rspec.rb
CHANGED
data/lib/chefspec/runner.rb
CHANGED
@@ -80,6 +80,7 @@ module ChefSpec
|
|
80
80
|
Chef::Config[:cache_type] = 'Memory'
|
81
81
|
Chef::Config[:client_key] = nil
|
82
82
|
Chef::Config[:cookbook_path] = Array(options[:cookbook_path])
|
83
|
+
Chef::Config[:no_lazy_load] = true
|
83
84
|
Chef::Config[:role_path] = Array(options[:role_path])
|
84
85
|
Chef::Config[:force_logger] = true
|
85
86
|
Chef::Config[:solo] = true
|
@@ -270,7 +271,7 @@ module ChefSpec
|
|
270
271
|
calling_spec = kaller.find { |line| line =~ /\/spec/ }
|
271
272
|
raise Error::CookbookPathNotFound if calling_spec.nil?
|
272
273
|
|
273
|
-
bits = calling_spec.split(
|
274
|
+
bits = calling_spec.split(/:[0-9]/, 2).first.split(File::SEPARATOR)
|
274
275
|
spec_dir = bits.index('spec') || 0
|
275
276
|
|
276
277
|
File.expand_path(File.join(bits.slice(0, spec_dir), '..'))
|
data/lib/chefspec/server.rb
CHANGED
@@ -61,6 +61,13 @@ module ChefSpec
|
|
61
61
|
instance.send(m, *args, &block)
|
62
62
|
end
|
63
63
|
|
64
|
+
#
|
65
|
+
# RSpec 3 checks +respond_to?+ for some odd reason.
|
66
|
+
#
|
67
|
+
def self.respond_to_missing?(m, include_private = false)
|
68
|
+
instance.respond_to?(m, include_private) || super
|
69
|
+
end
|
70
|
+
|
64
71
|
#
|
65
72
|
# @macro entity
|
66
73
|
# @method create_$1(name, data = {})
|
@@ -105,11 +112,11 @@ module ChefSpec
|
|
105
112
|
# Convert it to JSON
|
106
113
|
data = JSON.fast_generate(data)
|
107
114
|
|
108
|
-
|
115
|
+
load_data(name, '#{key}', data)
|
109
116
|
end
|
110
117
|
|
111
118
|
def #{method}(name)
|
112
|
-
data =
|
119
|
+
data = get('#{key}', name)
|
113
120
|
json = JSON.parse(data)
|
114
121
|
|
115
122
|
if #{klass}.respond_to?(:json_create)
|
@@ -122,37 +129,45 @@ module ChefSpec
|
|
122
129
|
end
|
123
130
|
|
124
131
|
def #{key}
|
125
|
-
|
132
|
+
get('#{key}')
|
126
133
|
end
|
127
134
|
|
128
135
|
def has_#{method}?(name)
|
129
|
-
|
136
|
+
!get('#{key}', name).nil?
|
130
137
|
rescue ChefZero::DataStore::DataNotFoundError
|
131
138
|
false
|
132
139
|
end
|
133
140
|
EOH
|
134
141
|
end
|
135
142
|
|
143
|
+
entity :client, Chef::Client, 'clients'
|
144
|
+
entity :data_bag, Chef::DataBag, 'data'
|
145
|
+
entity :environment, Chef::Environment, 'environments'
|
146
|
+
entity :node, Chef::Node, 'nodes'
|
147
|
+
entity :role, Chef::Role, 'roles'
|
148
|
+
|
136
149
|
include Singleton
|
137
150
|
|
138
151
|
attr_reader :server
|
139
152
|
|
140
153
|
#
|
141
154
|
# Create a new instance of the +ChefSpec::Server+ singleton. This method
|
142
|
-
# also starts the Chef Zero server in the background
|
155
|
+
# also starts the Chef Zero server in the background under the organization
|
156
|
+
# "chefspec".
|
143
157
|
#
|
144
158
|
def initialize
|
145
159
|
@server = ChefZero::Server.new(
|
160
|
+
# Set the log level from RSpec, defaulting to warn
|
146
161
|
log_level: RSpec.configuration.log_level || :warn,
|
162
|
+
|
163
|
+
# Set a random port so ChefSpec may be run in multiple jobs
|
164
|
+
port: port,
|
165
|
+
|
166
|
+
# Disable the "old" way - this is actually +multi_tenant: true+
|
167
|
+
single_org: false,
|
147
168
|
)
|
148
169
|
end
|
149
170
|
|
150
|
-
entity :client, Chef::Client, 'clients'
|
151
|
-
entity :data_bag, Chef::DataBag, 'data'
|
152
|
-
entity :environment, Chef::Environment, 'environments'
|
153
|
-
entity :node, Chef::Node, 'nodes'
|
154
|
-
entity :role, Chef::Role, 'roles'
|
155
|
-
|
156
171
|
#
|
157
172
|
# Create a new data_bag on the Chef Server. This overrides the method
|
158
173
|
# created by {entity}
|
@@ -163,7 +178,7 @@ module ChefSpec
|
|
163
178
|
# the data to load into the data bag
|
164
179
|
#
|
165
180
|
def create_data_bag(name, data = {})
|
166
|
-
|
181
|
+
load_data(name, 'data', data)
|
167
182
|
end
|
168
183
|
|
169
184
|
#
|
@@ -197,7 +212,7 @@ module ChefSpec
|
|
197
212
|
data = JSON.fast_generate(data)
|
198
213
|
end
|
199
214
|
|
200
|
-
|
215
|
+
load_data(name, 'nodes', data)
|
201
216
|
end
|
202
217
|
|
203
218
|
#
|
@@ -217,6 +232,15 @@ module ChefSpec
|
|
217
232
|
end
|
218
233
|
end
|
219
234
|
|
235
|
+
#
|
236
|
+
# The URL where ChefZero is listening (including the organization).
|
237
|
+
#
|
238
|
+
# @return [String]
|
239
|
+
#
|
240
|
+
def chef_server_url
|
241
|
+
@chef_server_url ||= File.join(@server.url, 'organizations', organization)
|
242
|
+
end
|
243
|
+
|
220
244
|
#
|
221
245
|
# Start the Chef Zero server in the background, updating the +Chef::Config+
|
222
246
|
# with the proper +chef_server_url+.
|
@@ -224,7 +248,7 @@ module ChefSpec
|
|
224
248
|
def start!
|
225
249
|
unless @server.running?
|
226
250
|
@server.start_background
|
227
|
-
Chef::Config[:chef_server_url] =
|
251
|
+
Chef::Config[:chef_server_url] = chef_server_url
|
228
252
|
end
|
229
253
|
end
|
230
254
|
|
@@ -233,6 +257,7 @@ module ChefSpec
|
|
233
257
|
#
|
234
258
|
def reset!
|
235
259
|
@server.clear_data
|
260
|
+
@server.data_store.create_dir(['organizations'], organization)
|
236
261
|
end
|
237
262
|
|
238
263
|
#
|
@@ -246,6 +271,15 @@ module ChefSpec
|
|
246
271
|
|
247
272
|
private
|
248
273
|
|
274
|
+
#
|
275
|
+
# The name of the Chef organization.
|
276
|
+
#
|
277
|
+
# @return [String]
|
278
|
+
#
|
279
|
+
def organization
|
280
|
+
RSpec.configuration.organization
|
281
|
+
end
|
282
|
+
|
249
283
|
#
|
250
284
|
# The directory where any cache information (such as private keys) should
|
251
285
|
# be stored. This cache is destroyed at the end of the run.
|
@@ -260,16 +294,52 @@ module ChefSpec
|
|
260
294
|
#
|
261
295
|
# Shortcut method for loading data into Chef Zero.
|
262
296
|
#
|
263
|
-
# @param [String, Symbol] key
|
264
|
-
# the key to load
|
265
297
|
# @param [String] name
|
266
298
|
# the name or id of the item to load
|
299
|
+
# @param [String, Symbol] key
|
300
|
+
# the key to load
|
267
301
|
# @param [Hash] data
|
268
302
|
# the data for the object, which will be converted to JSON and uploaded
|
269
303
|
# to the server
|
270
304
|
#
|
271
|
-
def load_data(
|
272
|
-
@server.load_data(key
|
305
|
+
def load_data(name, key, data = {})
|
306
|
+
@server.load_data({ key => { name => data } }, organization)
|
307
|
+
end
|
308
|
+
|
309
|
+
#
|
310
|
+
# Get the path to an item in the data store.
|
311
|
+
#
|
312
|
+
def get(*args)
|
313
|
+
if args.size == 1
|
314
|
+
@server.data_store.list(with_organization(*args))
|
315
|
+
else
|
316
|
+
@server.data_store.get(with_organization(*args))
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
#
|
321
|
+
# Prefix the given args with the organization. This is used by the data
|
322
|
+
# store to fetch elements.
|
323
|
+
#
|
324
|
+
# @return [Array<String>]
|
325
|
+
#
|
326
|
+
def with_organization(*args)
|
327
|
+
['organizations', organization, *args]
|
328
|
+
end
|
329
|
+
|
330
|
+
#
|
331
|
+
# A randomly assigned, open port for run the Chef Zero server.
|
332
|
+
#
|
333
|
+
# @return [Fixnum]
|
334
|
+
#
|
335
|
+
def port
|
336
|
+
return @port if @port
|
337
|
+
|
338
|
+
@server = TCPServer.new('127.0.0.1', 0)
|
339
|
+
@port = @server.addr[1].to_i
|
340
|
+
@server.close
|
341
|
+
|
342
|
+
return @port
|
273
343
|
end
|
274
344
|
end
|
275
345
|
end
|
@@ -277,7 +347,8 @@ end
|
|
277
347
|
ChefSpec::Server.start!
|
278
348
|
|
279
349
|
RSpec.configure do |config|
|
280
|
-
config.
|
350
|
+
config.before(:each) { ChefSpec::Server.reset! }
|
351
|
+
config.after(:each) { ChefSpec::Server.reset! }
|
281
352
|
end
|
282
353
|
|
283
354
|
at_exit { ChefSpec::Server.stop! }
|