chefspec 5.4.0 → 6.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 +6 -2
- data/CHANGELOG.md +12 -1
- data/README.md +17 -3
- data/chefspec.gemspec +2 -3
- data/examples/apt_package/spec/install_spec.rb +1 -1
- data/examples/apt_package/spec/purge_spec.rb +1 -1
- data/examples/apt_package/spec/reconfig_spec.rb +1 -1
- data/examples/apt_package/spec/remove_spec.rb +1 -1
- data/examples/apt_package/spec/upgrade_spec.rb +1 -1
- data/examples/apt_repository/spec/add_spec.rb +1 -1
- data/examples/apt_repository/spec/remove_spec.rb +1 -1
- data/examples/apt_update/spec/periodic_spec.rb +1 -1
- data/examples/apt_update/spec/update_spec.rb +1 -1
- data/examples/batch/spec/run_spec.rb +1 -1
- data/examples/cab_package/recipes/install.rb +13 -0
- data/examples/cab_package/recipes/remove.rb +13 -0
- data/examples/cab_package/spec/install_spec.rb +26 -0
- data/examples/cab_package/spec/remove_spec.rb +22 -0
- data/examples/chocolatey_package/spec/install_spec.rb +1 -1
- data/examples/chocolatey_package/spec/remove_spec.rb +1 -1
- data/examples/chocolatey_package/spec/upgrade_spec.rb +1 -1
- data/examples/dnf_package/recipes/install.rb +13 -0
- data/examples/dnf_package/recipes/purge.rb +13 -0
- data/examples/dnf_package/recipes/remove.rb +13 -0
- data/examples/dnf_package/recipes/upgrade.rb +13 -0
- data/examples/dnf_package/spec/install_spec.rb +26 -0
- data/examples/dnf_package/spec/purge_spec.rb +22 -0
- data/examples/dnf_package/spec/remove_spec.rb +22 -0
- data/examples/dnf_package/spec/upgrade_spec.rb +22 -0
- data/examples/dpkg_package/spec/install_spec.rb +1 -1
- data/examples/dpkg_package/spec/purge_spec.rb +1 -1
- data/examples/dpkg_package/spec/remove_spec.rb +1 -1
- data/examples/dsc_resource/spec/run_spec.rb +4 -4
- data/examples/dsc_script/spec/run_spec.rb +1 -1
- data/examples/env/spec/create_spec.rb +1 -1
- data/examples/env/spec/delete_spec.rb +1 -1
- data/examples/env/spec/modify_spec.rb +1 -1
- data/examples/freebsd_package/spec/install_spec.rb +1 -1
- data/examples/freebsd_package/spec/remove_spec.rb +1 -1
- data/examples/ips_package/spec/install_spec.rb +1 -1
- data/examples/ips_package/spec/remove_spec.rb +1 -1
- data/examples/ips_package/spec/upgrade_spec.rb +1 -1
- data/examples/msu_package/recipes/install.rb +13 -0
- data/examples/msu_package/recipes/remove.rb +13 -0
- data/examples/msu_package/spec/install_spec.rb +26 -0
- data/examples/msu_package/spec/remove_spec.rb +22 -0
- data/examples/pacman_package/spec/install_spec.rb +1 -1
- data/examples/pacman_package/spec/purge_spec.rb +1 -1
- data/examples/pacman_package/spec/remove_spec.rb +1 -1
- data/examples/pacman_package/spec/upgrade_spec.rb +1 -1
- data/examples/portage_package/spec/install_spec.rb +1 -1
- data/examples/portage_package/spec/purge_spec.rb +1 -1
- data/examples/portage_package/spec/remove_spec.rb +1 -1
- data/examples/portage_package/spec/upgrade_spec.rb +1 -1
- data/examples/powershell_script/spec/run_spec.rb +1 -1
- data/examples/registry_key/spec/create_if_missing_spec.rb +1 -1
- data/examples/registry_key/spec/create_spec.rb +1 -1
- data/examples/registry_key/spec/delete_key_spec.rb +1 -1
- data/examples/registry_key/spec/delete_spec.rb +1 -1
- data/examples/roles/roles/role.rb +2 -2
- data/examples/rpm_package/spec/install_spec.rb +1 -1
- data/examples/rpm_package/spec/remove_spec.rb +1 -1
- data/examples/rpm_package/spec/upgrade_spec.rb +1 -1
- data/examples/server/spec/data_bag_spec.rb +9 -11
- data/examples/smartos_package/spec/install_spec.rb +1 -1
- data/examples/smartos_package/spec/remove_spec.rb +1 -1
- data/examples/smartos_package/spec/upgrade_spec.rb +1 -1
- data/examples/solaris_package/spec/install_spec.rb +1 -1
- data/examples/solaris_package/spec/remove_spec.rb +1 -1
- data/examples/step_into/spec/default_spec.rb +2 -2
- data/examples/use_inline_resources/spec/default_spec.rb +1 -1
- data/examples/windows_package/spec/install_spec.rb +1 -1
- data/examples/windows_package/spec/remove_spec.rb +1 -1
- data/examples/windows_service/spec/configure_startup_spec.rb +1 -1
- data/examples/windows_service/spec/disable_spec.rb +1 -1
- data/examples/windows_service/spec/enable_spec.rb +1 -1
- data/examples/windows_service/spec/reload_spec.rb +1 -1
- data/examples/windows_service/spec/restart_spec.rb +1 -1
- data/examples/windows_service/spec/start_spec.rb +1 -1
- data/examples/windows_service/spec/stop_spec.rb +1 -1
- data/examples/yum_package/spec/install_spec.rb +1 -1
- data/examples/yum_package/spec/purge_spec.rb +1 -1
- data/examples/yum_package/spec/remove_spec.rb +1 -1
- data/examples/yum_package/spec/upgrade_spec.rb +1 -1
- data/examples/yum_repository/spec/add_spec.rb +1 -1
- data/examples/yum_repository/spec/create_spec.rb +1 -1
- data/examples/yum_repository/spec/delete_spec.rb +1 -1
- data/examples/yum_repository/spec/makecache_spec.rb +1 -1
- data/examples/yum_repository/spec/remove_spec.rb +1 -1
- data/features/cab_package.feature +21 -0
- data/features/dnf_package.feature +26 -0
- data/features/msu_package.feature +23 -0
- data/features/support/env.rb +8 -0
- data/lib/chefspec.rb +0 -1
- data/lib/chefspec/api.rb +3 -0
- data/lib/chefspec/api/cab_package.rb +80 -0
- data/lib/chefspec/api/dnf_package.rb +154 -0
- data/lib/chefspec/api/msu_package.rb +81 -0
- data/lib/chefspec/rspec.rb +1 -0
- data/lib/chefspec/server_methods.rb +4 -35
- data/lib/chefspec/server_runner.rb +2 -42
- data/lib/chefspec/version.rb +1 -1
- data/lib/chefspec/zero_server.rb +139 -0
- metadata +31 -6
- data/lib/chefspec/chef_backwards_compat.rb +0 -79
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
module ChefSpec::API
|
|
2
|
+
# @since 6.0.0
|
|
3
|
+
module DnfPackageMatchers
|
|
4
|
+
ChefSpec.define_matcher :dnf_package
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# Assert that a +dnf_package+ resource exists in the Chef run with the
|
|
8
|
+
# action +:install+. Given a Chef Recipe that installs "apache2" as a
|
|
9
|
+
# +dnf_package+:
|
|
10
|
+
#
|
|
11
|
+
# dnf_package 'apache2' do
|
|
12
|
+
# action :install
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# The Examples section demonstrates the different ways to test a
|
|
16
|
+
# +dnf_package+ resource with ChefSpec.
|
|
17
|
+
#
|
|
18
|
+
# @example Assert that a +dnf_package+ was installed
|
|
19
|
+
# expect(chef_run).to install_dnf_package('apache2')
|
|
20
|
+
#
|
|
21
|
+
# @example Assert that a +dnf_package+ was installed with predicate matchers
|
|
22
|
+
# expect(chef_run).to install_dnf_package('apache2').with_version('1.2.3')
|
|
23
|
+
#
|
|
24
|
+
# @example Assert that a +dnf_package+ was installed with attributes
|
|
25
|
+
# expect(chef_run).to install_dnf_package('apache2').with(version: '1.2.3')
|
|
26
|
+
#
|
|
27
|
+
# @example Assert that a +dnf_package+ was installed using a regex
|
|
28
|
+
# expect(chef_run).to install_dnf_package('apache2').with(version: /(\d+\.){2}\.\d+/)
|
|
29
|
+
#
|
|
30
|
+
# @example Assert that a +dnf_package+ was _not_ installed
|
|
31
|
+
# expect(chef_run).to_not install_dnf_package('apache2')
|
|
32
|
+
#
|
|
33
|
+
#
|
|
34
|
+
# @param [String, Regex] resource_name
|
|
35
|
+
# the name of the resource to match
|
|
36
|
+
#
|
|
37
|
+
# @return [ChefSpec::Matchers::ResourceMatcher]
|
|
38
|
+
#
|
|
39
|
+
def install_dnf_package(resource_name)
|
|
40
|
+
ChefSpec::Matchers::ResourceMatcher.new(:dnf_package, :install, resource_name)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# Assert that a +dnf_package+ resource exists in the Chef run with the
|
|
45
|
+
# action +:purge+. Given a Chef Recipe that purges "apache2" as a
|
|
46
|
+
# +dnf_package+:
|
|
47
|
+
#
|
|
48
|
+
# dnf_package 'apache2' do
|
|
49
|
+
# action :purge
|
|
50
|
+
# end
|
|
51
|
+
#
|
|
52
|
+
# The Examples section demonstrates the different ways to test a
|
|
53
|
+
# +dnf_package+ resource with ChefSpec.
|
|
54
|
+
#
|
|
55
|
+
# @example Assert that a +dnf_package+ was purged
|
|
56
|
+
# expect(chef_run).to purge_dnf_package('apache2')
|
|
57
|
+
#
|
|
58
|
+
# @example Assert that a +dnf_package+ was purged with predicate matchers
|
|
59
|
+
# expect(chef_run).to purge_dnf_package('apache2').with_version('1.2.3')
|
|
60
|
+
#
|
|
61
|
+
# @example Assert that a +dnf_package+ was purged with attributes
|
|
62
|
+
# expect(chef_run).to purge_dnf_package('apache2').with(version: '1.2.3')
|
|
63
|
+
#
|
|
64
|
+
# @example Assert that a +dnf_package+ was purged using a regex
|
|
65
|
+
# expect(chef_run).to purge_dnf_package('apache2').with(version: /(\d+\.){2}\.\d+/)
|
|
66
|
+
#
|
|
67
|
+
# @example Assert that a +dnf_package+ was _not_ purged
|
|
68
|
+
# expect(chef_run).to_not purge_dnf_package('apache2')
|
|
69
|
+
#
|
|
70
|
+
#
|
|
71
|
+
# @param [String, Regex] resource_name
|
|
72
|
+
# the name of the resource to match
|
|
73
|
+
#
|
|
74
|
+
# @return [ChefSpec::Matchers::ResourceMatcher]
|
|
75
|
+
#
|
|
76
|
+
def purge_dnf_package(resource_name)
|
|
77
|
+
ChefSpec::Matchers::ResourceMatcher.new(:dnf_package, :purge, resource_name)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
#
|
|
81
|
+
# Assert that a +dnf_package+ resource exists in the Chef run with the
|
|
82
|
+
# action +:remove+. Given a Chef Recipe that removes "apache2" as a
|
|
83
|
+
# +dnf_package+:
|
|
84
|
+
#
|
|
85
|
+
# dnf_package 'apache2' do
|
|
86
|
+
# action :remove
|
|
87
|
+
# end
|
|
88
|
+
#
|
|
89
|
+
# The Examples section demonstrates the different ways to test a
|
|
90
|
+
# +dnf_package+ resource with ChefSpec.
|
|
91
|
+
#
|
|
92
|
+
# @example Assert that a +dnf_package+ was removed
|
|
93
|
+
# expect(chef_run).to remove_dnf_package('apache2')
|
|
94
|
+
#
|
|
95
|
+
# @example Assert that a +dnf_package+ was removed with predicate matchers
|
|
96
|
+
# expect(chef_run).to remove_dnf_package('apache2').with_version('1.2.3')
|
|
97
|
+
#
|
|
98
|
+
# @example Assert that a +dnf_package+ was removed with attributes
|
|
99
|
+
# expect(chef_run).to remove_dnf_package('apache2').with(version: '1.2.3')
|
|
100
|
+
#
|
|
101
|
+
# @example Assert that a +dnf_package+ was removed using a regex
|
|
102
|
+
# expect(chef_run).to remove_dnf_package('apache2').with(version: /(\d+\.){2}\.\d+/)
|
|
103
|
+
#
|
|
104
|
+
# @example Assert that a +dnf_package+ was _not_ removed
|
|
105
|
+
# expect(chef_run).to_not remove_dnf_package('apache2')
|
|
106
|
+
#
|
|
107
|
+
#
|
|
108
|
+
# @param [String, Regex] resource_name
|
|
109
|
+
# the name of the resource to match
|
|
110
|
+
#
|
|
111
|
+
# @return [ChefSpec::Matchers::ResourceMatcher]
|
|
112
|
+
#
|
|
113
|
+
def remove_dnf_package(resource_name)
|
|
114
|
+
ChefSpec::Matchers::ResourceMatcher.new(:dnf_package, :remove, resource_name)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
#
|
|
118
|
+
# Assert that a +dnf_package+ resource exists in the Chef run with the
|
|
119
|
+
# action +:upgrade+. Given a Chef Recipe that upgrades "apache2" as a
|
|
120
|
+
# +dnf_package+:
|
|
121
|
+
#
|
|
122
|
+
# dnf_package 'apache2' do
|
|
123
|
+
# action :upgrade
|
|
124
|
+
# end
|
|
125
|
+
#
|
|
126
|
+
# The Examples section demonstrates the different ways to test a
|
|
127
|
+
# +dnf_package+ resource with ChefSpec.
|
|
128
|
+
#
|
|
129
|
+
# @example Assert that a +dnf_package+ was upgraded
|
|
130
|
+
# expect(chef_run).to upgrade_dnf_package('apache2')
|
|
131
|
+
#
|
|
132
|
+
# @example Assert that a +dnf_package+ was upgraded with predicate matchers
|
|
133
|
+
# expect(chef_run).to upgrade_dnf_package('apache2').with_version('1.2.3')
|
|
134
|
+
#
|
|
135
|
+
# @example Assert that a +dnf_package+ was upgraded with attributes
|
|
136
|
+
# expect(chef_run).to upgrade_dnf_package('apache2').with(version: '1.2.3')
|
|
137
|
+
#
|
|
138
|
+
# @example Assert that a +dnf_package+ was upgraded using a regex
|
|
139
|
+
# expect(chef_run).to upgrade_dnf_package('apache2').with(version: /(\d+\.){2}\.\d+/)
|
|
140
|
+
#
|
|
141
|
+
# @example Assert that a +dnf_package+ was _not_ upgraded
|
|
142
|
+
# expect(chef_run).to_not upgrade_dnf_package('apache2')
|
|
143
|
+
#
|
|
144
|
+
#
|
|
145
|
+
# @param [String, Regex] resource_name
|
|
146
|
+
# the name of the resource to match
|
|
147
|
+
#
|
|
148
|
+
# @return [ChefSpec::Matchers::ResourceMatcher]
|
|
149
|
+
#
|
|
150
|
+
def upgrade_dnf_package(resource_name)
|
|
151
|
+
ChefSpec::Matchers::ResourceMatcher.new(:dnf_package, :upgrade, resource_name)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module ChefSpec::API
|
|
2
|
+
# @since 6.0.0
|
|
3
|
+
module MsuPackageMatchers
|
|
4
|
+
ChefSpec.define_matcher :msu_package
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# Assert that a +msu_package+ resource exists in the Chef run with the
|
|
8
|
+
# action +:install+. Given a Chef Recipe that installs "KB2959977" as a
|
|
9
|
+
# +msu_package+:
|
|
10
|
+
#
|
|
11
|
+
# msu_package 'KB2959977' do
|
|
12
|
+
# source 'C:\Windows8.1-KB2959977-x64.msu'
|
|
13
|
+
# action :install
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# The Examples section demonstrates the different ways to test a
|
|
17
|
+
# +msu_package+ resource with ChefSpec.
|
|
18
|
+
#
|
|
19
|
+
# @example Assert that a +msu_package+ was installed
|
|
20
|
+
# expect(chef_run).to install_msu_package('KB2959977')
|
|
21
|
+
#
|
|
22
|
+
# @example Assert that a +msu_package+ was installed with predicate matchers
|
|
23
|
+
# expect(chef_run).to install_msu_package('KB2959977').with_source('C:\Windows8.1-KB2959977-x64.msu')
|
|
24
|
+
#
|
|
25
|
+
# @example Assert that a +msu_package+ was installed with attributes
|
|
26
|
+
# expect(chef_run).to install_msu_package('KB2959977').with(source: 'C:\Windows8.1-KB2959977-x64.msu')
|
|
27
|
+
#
|
|
28
|
+
# @example Assert that a +msu_package+ was installed using a regex
|
|
29
|
+
# expect(chef_run).to install_msu_package('KB2959977').with(source: /.*KB2959977.*/)
|
|
30
|
+
#
|
|
31
|
+
# @example Assert that a +msu_package+ was _not_ installed
|
|
32
|
+
# expect(chef_run).to_not install_msu_package('KB2959977')
|
|
33
|
+
#
|
|
34
|
+
#
|
|
35
|
+
# @param [String, Regex] resource_name
|
|
36
|
+
# the name of the resource to match
|
|
37
|
+
#
|
|
38
|
+
# @return [ChefSpec::Matchers::ResourceMatcher]
|
|
39
|
+
#
|
|
40
|
+
def install_msu_package(resource_name)
|
|
41
|
+
ChefSpec::Matchers::ResourceMatcher.new(:msu_package, :install, resource_name)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
#
|
|
45
|
+
# Assert that a +msu_package+ resource exists in the Chef run with the
|
|
46
|
+
# action +:remove+. Given a Chef Recipe that removes "KB2959977" as a
|
|
47
|
+
# +msu_package+:
|
|
48
|
+
#
|
|
49
|
+
# msu_package 'KB2959977' do
|
|
50
|
+
# action :remove
|
|
51
|
+
# end
|
|
52
|
+
#
|
|
53
|
+
# The Examples section demonstrates the different ways to test a
|
|
54
|
+
# +msu_package+ resource with ChefSpec.
|
|
55
|
+
#
|
|
56
|
+
# @example Assert that a +msu_package+ was removed
|
|
57
|
+
# expect(chef_run).to remove_msu_package('KB2959977')
|
|
58
|
+
#
|
|
59
|
+
# @example Assert that a +msu_package+ was removed with predicate matchers
|
|
60
|
+
# expect(chef_run).to remove_msu_package('KB2959977').with_source('C:\Windows8.1-KB2959977-x64.msu')
|
|
61
|
+
#
|
|
62
|
+
# @example Assert that a +msu_package+ was removed with attributes
|
|
63
|
+
# expect(chef_run).to remove_msu_package('KB2959977').with(source: 'C:\Windows8.1-KB2959977-x64.msu')
|
|
64
|
+
#
|
|
65
|
+
# @example Assert that a +msu_package+ was removed using a regex
|
|
66
|
+
# expect(chef_run).to remove_msu_package('KB2959977').with(source: /.*KB2959977.*/)
|
|
67
|
+
#
|
|
68
|
+
# @example Assert that a +msu_package+ was _not_ removed
|
|
69
|
+
# expect(chef_run).to_not remove_msu_package('KB2959977')
|
|
70
|
+
#
|
|
71
|
+
#
|
|
72
|
+
# @param [String, Regex] resource_name
|
|
73
|
+
# the name of the resource to match
|
|
74
|
+
#
|
|
75
|
+
# @return [ChefSpec::Matchers::ResourceMatcher]
|
|
76
|
+
#
|
|
77
|
+
def remove_msu_package(resource_name)
|
|
78
|
+
ChefSpec::Matchers::ResourceMatcher.new(:msu_package, :remove, resource_name)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
data/lib/chefspec/rspec.rb
CHANGED
|
@@ -10,16 +10,7 @@ module ChefSpec
|
|
|
10
10
|
# @return [ChefZero::Server]
|
|
11
11
|
#
|
|
12
12
|
def server
|
|
13
|
-
|
|
14
|
-
# Set the log level from RSpec, defaulting to warn
|
|
15
|
-
log_level: RSpec.configuration.log_level || :warn,
|
|
16
|
-
|
|
17
|
-
# Set a random port so ChefSpec may be run in multiple contexts
|
|
18
|
-
port: port,
|
|
19
|
-
|
|
20
|
-
# Set the data store
|
|
21
|
-
data_store: data_store(RSpec.configuration.server_runner_data_store),
|
|
22
|
-
)
|
|
13
|
+
ChefSpec::ZeroServer.server
|
|
23
14
|
end
|
|
24
15
|
|
|
25
16
|
#
|
|
@@ -160,7 +151,7 @@ module ChefSpec
|
|
|
160
151
|
# to the server
|
|
161
152
|
#
|
|
162
153
|
def load_data(name, key, data = {})
|
|
163
|
-
|
|
154
|
+
ChefSpec::ZeroServer.load_data(name, key, data)
|
|
164
155
|
end
|
|
165
156
|
|
|
166
157
|
#
|
|
@@ -170,32 +161,10 @@ module ChefSpec
|
|
|
170
161
|
args.unshift('organizations', 'chef')
|
|
171
162
|
|
|
172
163
|
if args.size == 3
|
|
173
|
-
|
|
164
|
+
server.data_store.list(args)
|
|
174
165
|
else
|
|
175
|
-
|
|
166
|
+
server.data_store.get(args)
|
|
176
167
|
end
|
|
177
168
|
end
|
|
178
|
-
|
|
179
|
-
#
|
|
180
|
-
# Generate the DataStore object to be passed in to the ChefZero::Server object
|
|
181
|
-
#
|
|
182
|
-
def data_store(option)
|
|
183
|
-
require "chef_zero/data_store/default_facade"
|
|
184
|
-
|
|
185
|
-
store = case option
|
|
186
|
-
when :in_memory
|
|
187
|
-
require "chef_zero/data_store/memory_store_v2"
|
|
188
|
-
ChefZero::DataStore::MemoryStoreV2.new
|
|
189
|
-
when :on_disk
|
|
190
|
-
require "tmpdir"
|
|
191
|
-
require "chef_zero/data_store/raw_file_store"
|
|
192
|
-
tmpdir = Dir.mktmpdir
|
|
193
|
-
ChefZero::DataStore::RawFileStore.new(Dir.mktmpdir)
|
|
194
|
-
else
|
|
195
|
-
raise ArgumentError, ":#{option} is not a valid server_runner_data_store option. Please use either :in_memory or :on_disk."
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
ChefZero::DataStore::DefaultFacade.new(store, "chef", true)
|
|
199
|
-
end
|
|
200
169
|
end
|
|
201
170
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
require 'chef_zero/server'
|
|
2
1
|
require 'chef/cookbook_loader'
|
|
3
2
|
require 'chef/cookbook_uploader'
|
|
4
3
|
|
|
4
|
+
require_relative 'zero_server'
|
|
5
5
|
require_relative 'file_cache_path_proxy'
|
|
6
6
|
require_relative 'server_methods'
|
|
7
7
|
require_relative 'solo_runner'
|
|
@@ -32,39 +32,14 @@ module ChefSpec
|
|
|
32
32
|
Chef::Config[:chef_server_url] = server.url
|
|
33
33
|
Chef::Config[:http_retry_count] = 0
|
|
34
34
|
|
|
35
|
-
# Start the Chef Zero instance in the background
|
|
36
|
-
server.start_background
|
|
37
|
-
at_exit { server.stop if server.running? }
|
|
38
|
-
|
|
39
35
|
# Unlike the SoloRunner, the node AND server object are yielded for
|
|
40
36
|
# customization
|
|
41
37
|
yield node, self if block_given?
|
|
42
38
|
end
|
|
43
39
|
|
|
44
|
-
#
|
|
45
|
-
# Upload the cookbooks to the Chef Server.
|
|
46
|
-
#
|
|
47
|
-
def upload_cookbooks!
|
|
48
|
-
loader = Chef::CookbookLoader.new(Chef::Config[:cookbook_path])
|
|
49
|
-
loader.load_cookbooks
|
|
50
|
-
cookbook_uploader_for(loader).upload_cookbooks
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
#
|
|
54
|
-
# The uploader for the cookbooks.
|
|
55
|
-
#
|
|
56
|
-
# @param [Chef::CookbookLoader] loader
|
|
57
|
-
# the Chef cookbook loader
|
|
58
|
-
#
|
|
59
|
-
# @return [Chef::CookbookUploader]
|
|
60
|
-
#
|
|
61
|
-
def cookbook_uploader_for(loader)
|
|
62
|
-
Chef::CookbookUploader.new(loader.cookbooks)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
40
|
# @see (SoloRunner#converge)
|
|
66
41
|
def converge(*recipe_names)
|
|
67
|
-
upload_cookbooks!
|
|
42
|
+
ChefSpec::ZeroServer.upload_cookbooks!
|
|
68
43
|
|
|
69
44
|
super do
|
|
70
45
|
yield if block_given?
|
|
@@ -93,20 +68,5 @@ module ChefSpec
|
|
|
93
68
|
at_exit { FileUtils.rm_rf(tmp) }
|
|
94
69
|
path
|
|
95
70
|
end
|
|
96
|
-
|
|
97
|
-
#
|
|
98
|
-
# A randomly assigned, open port for run the Chef Zero server.
|
|
99
|
-
#
|
|
100
|
-
# @return [Fixnum]
|
|
101
|
-
#
|
|
102
|
-
def port
|
|
103
|
-
return @port if @port
|
|
104
|
-
|
|
105
|
-
@server = TCPServer.new('127.0.0.1', 0)
|
|
106
|
-
@port = @server.addr[1].to_i
|
|
107
|
-
@server.close
|
|
108
|
-
|
|
109
|
-
return @port
|
|
110
|
-
end
|
|
111
71
|
end
|
|
112
72
|
end
|
data/lib/chefspec/version.rb
CHANGED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
require 'chef_zero/server'
|
|
2
|
+
|
|
3
|
+
module ChefSpec
|
|
4
|
+
# Rather than create a ChefZero instance per test case, simply create one
|
|
5
|
+
# ChefZero instance and reset it for every test case.
|
|
6
|
+
class ZeroServer
|
|
7
|
+
class << self
|
|
8
|
+
extend Forwardable
|
|
9
|
+
def_delegators :instance, :setup!, :teardown!, :reset!, :upload_cookbooks!, :server, :load_data
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
include Singleton
|
|
13
|
+
|
|
14
|
+
# Create the ChefZero Server
|
|
15
|
+
def initialize
|
|
16
|
+
@server ||= ChefZero::Server.new(
|
|
17
|
+
# Set the log level from RSpec, defaulting to warn
|
|
18
|
+
log_level: RSpec.configuration.log_level || :warn,
|
|
19
|
+
|
|
20
|
+
# Set the data store
|
|
21
|
+
data_store: data_store(RSpec.configuration.server_runner_data_store),
|
|
22
|
+
)
|
|
23
|
+
@cookbooks_uploaded = false
|
|
24
|
+
@data_loaded = {}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
#
|
|
28
|
+
# Start the ChefZero Server
|
|
29
|
+
#
|
|
30
|
+
def setup!
|
|
31
|
+
@server.start_background unless @server.running?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# Remove all the data we just loaded from the ChefZero server
|
|
36
|
+
#
|
|
37
|
+
def reset!
|
|
38
|
+
if RSpec.configuration.server_runner_clear_cookbooks
|
|
39
|
+
@server.clear_data
|
|
40
|
+
@cookbooks_uploaded = false
|
|
41
|
+
else
|
|
42
|
+
# If we don't want to do a full clear, iterate through each value that we
|
|
43
|
+
# set and manually remove it.
|
|
44
|
+
@data_loaded.each do |key, names|
|
|
45
|
+
if key == "data"
|
|
46
|
+
names.each { |n| @server.data_store.delete_dir(["organizations", "chef", key, n]) }
|
|
47
|
+
else
|
|
48
|
+
names.each { |n| @server.data_store.delete(["organizations", "chef", key, n]) }
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
@data_loaded = {}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
# Teardown the ChefZero Server
|
|
57
|
+
#
|
|
58
|
+
def teardown!
|
|
59
|
+
@server.stop if @server.running?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
#
|
|
63
|
+
# Upload the cookbooks to the Chef Server.
|
|
64
|
+
#
|
|
65
|
+
def upload_cookbooks!
|
|
66
|
+
return if @cookbooks_uploaded
|
|
67
|
+
loader = Chef::CookbookLoader.new(Chef::Config[:cookbook_path])
|
|
68
|
+
loader.load_cookbooks
|
|
69
|
+
cookbook_uploader_for(loader).upload_cookbooks
|
|
70
|
+
@cookbooks_uploaded = true
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
#
|
|
74
|
+
# The URL for the ChefZero Server
|
|
75
|
+
#
|
|
76
|
+
def server
|
|
77
|
+
@server
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
#
|
|
81
|
+
# Load (and track) data sent to the server
|
|
82
|
+
#
|
|
83
|
+
# @param [String] name
|
|
84
|
+
# the name or id of the item to load
|
|
85
|
+
# @param [String, Symbol] key
|
|
86
|
+
# the key to load
|
|
87
|
+
# @param [Hash] data
|
|
88
|
+
# the data for the object, which will be converted to JSON and uploaded
|
|
89
|
+
# to the server
|
|
90
|
+
#
|
|
91
|
+
def load_data(name, key, data)
|
|
92
|
+
@data_loaded[key] ||= []
|
|
93
|
+
@data_loaded[key] << name
|
|
94
|
+
@server.load_data({ key => { name => data } })
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
|
|
99
|
+
#
|
|
100
|
+
# The uploader for the cookbooks.
|
|
101
|
+
#
|
|
102
|
+
# @param [Chef::CookbookLoader] loader
|
|
103
|
+
# the Chef cookbook loader
|
|
104
|
+
#
|
|
105
|
+
# @return [Chef::CookbookUploader]
|
|
106
|
+
#
|
|
107
|
+
def cookbook_uploader_for(loader)
|
|
108
|
+
Chef::CookbookUploader.new(loader.cookbooks)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
#
|
|
112
|
+
# Generate the DataStore object to be passed in to the ChefZero::Server object
|
|
113
|
+
#
|
|
114
|
+
def data_store(option)
|
|
115
|
+
require "chef_zero/data_store/default_facade"
|
|
116
|
+
|
|
117
|
+
store = case option
|
|
118
|
+
when :in_memory
|
|
119
|
+
require "chef_zero/data_store/memory_store_v2"
|
|
120
|
+
ChefZero::DataStore::MemoryStoreV2.new
|
|
121
|
+
when :on_disk
|
|
122
|
+
require "tmpdir"
|
|
123
|
+
require "chef_zero/data_store/raw_file_store"
|
|
124
|
+
tmpdir = Dir.mktmpdir
|
|
125
|
+
ChefZero::DataStore::RawFileStore.new(Dir.mktmpdir)
|
|
126
|
+
else
|
|
127
|
+
raise ArgumentError, ":#{option} is not a valid server_runner_data_store option. Please use either :in_memory or :on_disk."
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
ChefZero::DataStore::DefaultFacade.new(store, "chef", true)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
RSpec.configure do |config|
|
|
136
|
+
config.before(:suite) { ChefSpec::ZeroServer.setup! }
|
|
137
|
+
config.after(:each) { ChefSpec::ZeroServer.reset! }
|
|
138
|
+
config.after(:suite) { ChefSpec::ZeroServer.teardown! }
|
|
139
|
+
end
|