chefspec 5.4.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -2
  3. data/CHANGELOG.md +12 -1
  4. data/README.md +17 -3
  5. data/chefspec.gemspec +2 -3
  6. data/examples/apt_package/spec/install_spec.rb +1 -1
  7. data/examples/apt_package/spec/purge_spec.rb +1 -1
  8. data/examples/apt_package/spec/reconfig_spec.rb +1 -1
  9. data/examples/apt_package/spec/remove_spec.rb +1 -1
  10. data/examples/apt_package/spec/upgrade_spec.rb +1 -1
  11. data/examples/apt_repository/spec/add_spec.rb +1 -1
  12. data/examples/apt_repository/spec/remove_spec.rb +1 -1
  13. data/examples/apt_update/spec/periodic_spec.rb +1 -1
  14. data/examples/apt_update/spec/update_spec.rb +1 -1
  15. data/examples/batch/spec/run_spec.rb +1 -1
  16. data/examples/cab_package/recipes/install.rb +13 -0
  17. data/examples/cab_package/recipes/remove.rb +13 -0
  18. data/examples/cab_package/spec/install_spec.rb +26 -0
  19. data/examples/cab_package/spec/remove_spec.rb +22 -0
  20. data/examples/chocolatey_package/spec/install_spec.rb +1 -1
  21. data/examples/chocolatey_package/spec/remove_spec.rb +1 -1
  22. data/examples/chocolatey_package/spec/upgrade_spec.rb +1 -1
  23. data/examples/dnf_package/recipes/install.rb +13 -0
  24. data/examples/dnf_package/recipes/purge.rb +13 -0
  25. data/examples/dnf_package/recipes/remove.rb +13 -0
  26. data/examples/dnf_package/recipes/upgrade.rb +13 -0
  27. data/examples/dnf_package/spec/install_spec.rb +26 -0
  28. data/examples/dnf_package/spec/purge_spec.rb +22 -0
  29. data/examples/dnf_package/spec/remove_spec.rb +22 -0
  30. data/examples/dnf_package/spec/upgrade_spec.rb +22 -0
  31. data/examples/dpkg_package/spec/install_spec.rb +1 -1
  32. data/examples/dpkg_package/spec/purge_spec.rb +1 -1
  33. data/examples/dpkg_package/spec/remove_spec.rb +1 -1
  34. data/examples/dsc_resource/spec/run_spec.rb +4 -4
  35. data/examples/dsc_script/spec/run_spec.rb +1 -1
  36. data/examples/env/spec/create_spec.rb +1 -1
  37. data/examples/env/spec/delete_spec.rb +1 -1
  38. data/examples/env/spec/modify_spec.rb +1 -1
  39. data/examples/freebsd_package/spec/install_spec.rb +1 -1
  40. data/examples/freebsd_package/spec/remove_spec.rb +1 -1
  41. data/examples/ips_package/spec/install_spec.rb +1 -1
  42. data/examples/ips_package/spec/remove_spec.rb +1 -1
  43. data/examples/ips_package/spec/upgrade_spec.rb +1 -1
  44. data/examples/msu_package/recipes/install.rb +13 -0
  45. data/examples/msu_package/recipes/remove.rb +13 -0
  46. data/examples/msu_package/spec/install_spec.rb +26 -0
  47. data/examples/msu_package/spec/remove_spec.rb +22 -0
  48. data/examples/pacman_package/spec/install_spec.rb +1 -1
  49. data/examples/pacman_package/spec/purge_spec.rb +1 -1
  50. data/examples/pacman_package/spec/remove_spec.rb +1 -1
  51. data/examples/pacman_package/spec/upgrade_spec.rb +1 -1
  52. data/examples/portage_package/spec/install_spec.rb +1 -1
  53. data/examples/portage_package/spec/purge_spec.rb +1 -1
  54. data/examples/portage_package/spec/remove_spec.rb +1 -1
  55. data/examples/portage_package/spec/upgrade_spec.rb +1 -1
  56. data/examples/powershell_script/spec/run_spec.rb +1 -1
  57. data/examples/registry_key/spec/create_if_missing_spec.rb +1 -1
  58. data/examples/registry_key/spec/create_spec.rb +1 -1
  59. data/examples/registry_key/spec/delete_key_spec.rb +1 -1
  60. data/examples/registry_key/spec/delete_spec.rb +1 -1
  61. data/examples/roles/roles/role.rb +2 -2
  62. data/examples/rpm_package/spec/install_spec.rb +1 -1
  63. data/examples/rpm_package/spec/remove_spec.rb +1 -1
  64. data/examples/rpm_package/spec/upgrade_spec.rb +1 -1
  65. data/examples/server/spec/data_bag_spec.rb +9 -11
  66. data/examples/smartos_package/spec/install_spec.rb +1 -1
  67. data/examples/smartos_package/spec/remove_spec.rb +1 -1
  68. data/examples/smartos_package/spec/upgrade_spec.rb +1 -1
  69. data/examples/solaris_package/spec/install_spec.rb +1 -1
  70. data/examples/solaris_package/spec/remove_spec.rb +1 -1
  71. data/examples/step_into/spec/default_spec.rb +2 -2
  72. data/examples/use_inline_resources/spec/default_spec.rb +1 -1
  73. data/examples/windows_package/spec/install_spec.rb +1 -1
  74. data/examples/windows_package/spec/remove_spec.rb +1 -1
  75. data/examples/windows_service/spec/configure_startup_spec.rb +1 -1
  76. data/examples/windows_service/spec/disable_spec.rb +1 -1
  77. data/examples/windows_service/spec/enable_spec.rb +1 -1
  78. data/examples/windows_service/spec/reload_spec.rb +1 -1
  79. data/examples/windows_service/spec/restart_spec.rb +1 -1
  80. data/examples/windows_service/spec/start_spec.rb +1 -1
  81. data/examples/windows_service/spec/stop_spec.rb +1 -1
  82. data/examples/yum_package/spec/install_spec.rb +1 -1
  83. data/examples/yum_package/spec/purge_spec.rb +1 -1
  84. data/examples/yum_package/spec/remove_spec.rb +1 -1
  85. data/examples/yum_package/spec/upgrade_spec.rb +1 -1
  86. data/examples/yum_repository/spec/add_spec.rb +1 -1
  87. data/examples/yum_repository/spec/create_spec.rb +1 -1
  88. data/examples/yum_repository/spec/delete_spec.rb +1 -1
  89. data/examples/yum_repository/spec/makecache_spec.rb +1 -1
  90. data/examples/yum_repository/spec/remove_spec.rb +1 -1
  91. data/features/cab_package.feature +21 -0
  92. data/features/dnf_package.feature +26 -0
  93. data/features/msu_package.feature +23 -0
  94. data/features/support/env.rb +8 -0
  95. data/lib/chefspec.rb +0 -1
  96. data/lib/chefspec/api.rb +3 -0
  97. data/lib/chefspec/api/cab_package.rb +80 -0
  98. data/lib/chefspec/api/dnf_package.rb +154 -0
  99. data/lib/chefspec/api/msu_package.rb +81 -0
  100. data/lib/chefspec/rspec.rb +1 -0
  101. data/lib/chefspec/server_methods.rb +4 -35
  102. data/lib/chefspec/server_runner.rb +2 -42
  103. data/lib/chefspec/version.rb +1 -1
  104. data/lib/chefspec/zero_server.rb +139 -0
  105. metadata +31 -6
  106. 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
@@ -20,4 +20,5 @@ RSpec.configure do |config|
20
20
  config.add_setting :platform
21
21
  config.add_setting :version
22
22
  config.add_setting :server_runner_data_store, default: :in_memory
23
+ config.add_setting :server_runner_clear_cookbooks, default: true
23
24
  end
@@ -10,16 +10,7 @@ module ChefSpec
10
10
  # @return [ChefZero::Server]
11
11
  #
12
12
  def server
13
- @server ||= ChefZero::Server.new(
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
- @server.load_data({ key => { name => data } })
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
- @server.data_store.list(args)
164
+ server.data_store.list(args)
174
165
  else
175
- @server.data_store.get(args)
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
@@ -1,3 +1,3 @@
1
1
  module ChefSpec
2
- VERSION = '5.4.0'
2
+ VERSION = '6.0.0'
3
3
  end
@@ -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