chefspec 4.0.2 → 4.1.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.
Files changed (264) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -1
  3. data/CHANGELOG.md +19 -0
  4. data/README.md +84 -87
  5. data/chefspec.gemspec +1 -1
  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/attributes/spec/default_spec.rb +1 -1
  12. data/examples/batch/spec/run_spec.rb +1 -1
  13. data/examples/cached/spec/default_spec.rb +1 -1
  14. data/examples/chef_gem/spec/install_spec.rb +1 -1
  15. data/examples/chef_gem/spec/purge_spec.rb +1 -1
  16. data/examples/chef_gem/spec/reconfig_spec.rb +1 -1
  17. data/examples/chef_gem/spec/remove_spec.rb +1 -1
  18. data/examples/chef_gem/spec/upgrade_spec.rb +1 -1
  19. data/examples/compile_time/spec/default_spec.rb +1 -1
  20. data/examples/cookbook_file/spec/create_if_missing_spec.rb +1 -1
  21. data/examples/cookbook_file/spec/create_spec.rb +1 -1
  22. data/examples/cookbook_file/spec/delete_spec.rb +1 -1
  23. data/examples/cookbook_file/spec/touch_spec.rb +1 -1
  24. data/examples/cron/spec/create_spec.rb +1 -1
  25. data/examples/cron/spec/delete_spec.rb +1 -1
  26. data/examples/custom_matcher/libraries/matcher.rb +1 -1
  27. data/examples/custom_matcher/spec/install_spec.rb +1 -1
  28. data/examples/custom_matcher/spec/remove_spec.rb +1 -1
  29. data/examples/deploy/spec/deploy_spec.rb +1 -1
  30. data/examples/deploy/spec/force_deploy_spec.rb +1 -1
  31. data/examples/deploy/spec/rollback_spec.rb +1 -1
  32. data/examples/directory/spec/create_spec.rb +1 -1
  33. data/examples/directory/spec/delete_spec.rb +1 -1
  34. data/examples/do_nothing/spec/default_spec.rb +1 -1
  35. data/examples/dpkg_package/spec/install_spec.rb +1 -1
  36. data/examples/dpkg_package/spec/purge_spec.rb +1 -1
  37. data/examples/dpkg_package/spec/remove_spec.rb +1 -1
  38. data/examples/easy_install_package/spec/install_spec.rb +1 -1
  39. data/examples/easy_install_package/spec/purge_spec.rb +1 -1
  40. data/examples/easy_install_package/spec/remove_spec.rb +1 -1
  41. data/examples/easy_install_package/spec/upgrade_spec.rb +1 -1
  42. data/examples/env/spec/create_spec.rb +1 -1
  43. data/examples/env/spec/delete_spec.rb +1 -1
  44. data/examples/env/spec/modify_spec.rb +1 -1
  45. data/examples/erl_call/spec/run_spec.rb +1 -1
  46. data/examples/execute/spec/run_spec.rb +1 -1
  47. data/examples/expect_exception/spec/compile_error_spec.rb +1 -1
  48. data/examples/expect_exception/spec/converge_error_spec.rb +1 -1
  49. data/examples/expect_exception/spec/no_error_spec.rb +1 -1
  50. data/examples/file/spec/create_if_missing_spec.rb +1 -1
  51. data/examples/file/spec/create_spec.rb +1 -1
  52. data/examples/file/spec/delete_spec.rb +1 -1
  53. data/examples/file/spec/touch_spec.rb +1 -1
  54. data/examples/freebsd_package/spec/install_spec.rb +1 -1
  55. data/examples/freebsd_package/spec/remove_spec.rb +1 -1
  56. data/examples/gem_package/spec/install_spec.rb +1 -1
  57. data/examples/gem_package/spec/purge_spec.rb +1 -1
  58. data/examples/gem_package/spec/reconfig_spec.rb +1 -1
  59. data/examples/gem_package/spec/remove_spec.rb +1 -1
  60. data/examples/gem_package/spec/upgrade_spec.rb +1 -1
  61. data/examples/git/spec/checkout_spec.rb +1 -1
  62. data/examples/git/spec/export_spec.rb +1 -1
  63. data/examples/git/spec/sync_spec.rb +1 -1
  64. data/examples/group/spec/create_spec.rb +1 -1
  65. data/examples/group/spec/manage_spec.rb +1 -1
  66. data/examples/group/spec/modify_spec.rb +1 -1
  67. data/examples/group/spec/remove_spec.rb +1 -1
  68. data/examples/guards/spec/default_spec.rb +1 -1
  69. data/examples/heavy_provider_light_resource/spec/provider_service_spec.rb +1 -1
  70. data/examples/http_request/spec/delete_spec.rb +1 -1
  71. data/examples/http_request/spec/get_spec.rb +1 -1
  72. data/examples/http_request/spec/head_spec.rb +1 -1
  73. data/examples/http_request/spec/options_spec.rb +1 -1
  74. data/examples/http_request/spec/post_spec.rb +1 -1
  75. data/examples/http_request/spec/put_spec.rb +1 -1
  76. data/examples/ifconfig/spec/add_spec.rb +1 -1
  77. data/examples/ifconfig/spec/delete_spec.rb +1 -1
  78. data/examples/ifconfig/spec/disable_spec.rb +1 -1
  79. data/examples/ifconfig/spec/enable_spec.rb +1 -1
  80. data/examples/include_recipe/spec/default_spec.rb +1 -1
  81. data/examples/inherits/spec/default_spec.rb +1 -1
  82. data/examples/ips_package/spec/install_spec.rb +1 -1
  83. data/examples/ips_package/spec/remove_spec.rb +1 -1
  84. data/examples/ips_package/spec/upgrade_spec.rb +1 -1
  85. data/examples/link/spec/create_spec.rb +1 -1
  86. data/examples/link/spec/delete_spec.rb +1 -1
  87. data/examples/link/spec/link_to_spec.rb +1 -1
  88. data/examples/log/spec/write_spec.rb +1 -1
  89. data/examples/macports_package/spec/install_spec.rb +1 -1
  90. data/examples/macports_package/spec/purge_spec.rb +1 -1
  91. data/examples/macports_package/spec/remove_spec.rb +1 -1
  92. data/examples/macports_package/spec/upgrade_spec.rb +1 -1
  93. data/examples/mdadm/spec/assemble_spec.rb +1 -1
  94. data/examples/mdadm/spec/create_spec.rb +1 -1
  95. data/examples/mdadm/spec/stop_spec.rb +1 -1
  96. data/examples/mount/spec/disable_spec.rb +1 -1
  97. data/examples/mount/spec/enable_spec.rb +1 -1
  98. data/examples/mount/spec/mount_spec.rb +1 -1
  99. data/examples/mount/spec/remount_spec.rb +1 -1
  100. data/examples/mount/spec/umount_spec.rb +1 -1
  101. data/examples/multiple_actions/spec/default_spec.rb +1 -1
  102. data/examples/multiple_actions/spec/sequential_spec.rb +4 -1
  103. data/examples/multiple_run_action/spec/default_spec.rb +1 -1
  104. data/examples/notifications/spec/chained_spec.rb +1 -1
  105. data/examples/notifications/spec/default_spec.rb +1 -1
  106. data/examples/notifications/spec/delayed_spec.rb +1 -1
  107. data/examples/notifications/spec/immediately_spec.rb +1 -1
  108. data/examples/ohai/spec/reload_spec.rb +1 -1
  109. data/examples/package/spec/install_spec.rb +1 -1
  110. data/examples/package/spec/purge_spec.rb +1 -1
  111. data/examples/package/spec/reconfig_spec.rb +1 -1
  112. data/examples/package/spec/remove_spec.rb +1 -1
  113. data/examples/package/spec/upgrade_spec.rb +1 -1
  114. data/examples/pacman_package/spec/install_spec.rb +1 -1
  115. data/examples/pacman_package/spec/purge_spec.rb +1 -1
  116. data/examples/pacman_package/spec/remove_spec.rb +1 -1
  117. data/examples/pacman_package/spec/upgrade_spec.rb +1 -1
  118. data/examples/portage_package/spec/install_spec.rb +1 -1
  119. data/examples/portage_package/spec/purge_spec.rb +1 -1
  120. data/examples/portage_package/spec/remove_spec.rb +1 -1
  121. data/examples/portage_package/spec/upgrade_spec.rb +1 -1
  122. data/examples/powershell_script/spec/run_spec.rb +1 -1
  123. data/examples/registry_key/spec/create_if_missing_spec.rb +1 -1
  124. data/examples/registry_key/spec/create_spec.rb +1 -1
  125. data/examples/registry_key/spec/delete_key_spec.rb +1 -1
  126. data/examples/registry_key/spec/delete_spec.rb +1 -1
  127. data/examples/remote_directory/spec/create_if_missing_spec.rb +1 -1
  128. data/examples/remote_directory/spec/create_spec.rb +1 -1
  129. data/examples/remote_directory/spec/delete_spec.rb +1 -1
  130. data/examples/remote_file/spec/create_if_missing_spec.rb +1 -1
  131. data/examples/remote_file/spec/create_spec.rb +1 -1
  132. data/examples/remote_file/spec/delete_spec.rb +1 -1
  133. data/examples/remote_file/spec/touch_spec.rb +1 -1
  134. data/examples/render_file/spec/default_spec.rb +1 -1
  135. data/examples/render_file/spec/template_helpers_spec.rb +1 -1
  136. data/examples/roles/spec/default_spec.rb +1 -1
  137. data/examples/route/spec/add_spec.rb +1 -1
  138. data/examples/route/spec/delete_spec.rb +1 -1
  139. data/examples/rpm_package/spec/install_spec.rb +1 -1
  140. data/examples/rpm_package/spec/remove_spec.rb +1 -1
  141. data/examples/rpm_package/spec/upgrade_spec.rb +1 -1
  142. data/examples/ruby_block/spec/run_spec.rb +1 -1
  143. data/examples/script/spec/run_bash_spec.rb +1 -1
  144. data/examples/script/spec/run_csh_spec.rb +1 -1
  145. data/examples/script/spec/run_perl_spec.rb +1 -1
  146. data/examples/script/spec/run_python_spec.rb +1 -1
  147. data/examples/script/spec/run_ruby_spec.rb +1 -1
  148. data/examples/script/spec/run_script_spec.rb +1 -1
  149. data/examples/server/spec/client_spec.rb +5 -4
  150. data/examples/server/spec/data_bag_spec.rb +10 -9
  151. data/examples/server/spec/environment_spec.rb +5 -4
  152. data/examples/server/spec/node_spec.rb +20 -14
  153. data/examples/server/spec/render_with_cached_spec.rb +1 -2
  154. data/examples/server/spec/role_spec.rb +5 -4
  155. data/examples/server/spec/search_spec.rb +7 -8
  156. data/examples/service/spec/disable_spec.rb +1 -1
  157. data/examples/service/spec/enable_spec.rb +1 -1
  158. data/examples/service/spec/reload_spec.rb +1 -1
  159. data/examples/service/spec/restart_spec.rb +1 -1
  160. data/examples/service/spec/start_spec.rb +1 -1
  161. data/examples/service/spec/stop_spec.rb +1 -1
  162. data/examples/smartos_package/spec/install_spec.rb +1 -1
  163. data/examples/smartos_package/spec/remove_spec.rb +1 -1
  164. data/examples/smartos_package/spec/upgrade_spec.rb +1 -1
  165. data/examples/solaris_package/spec/install_spec.rb +1 -1
  166. data/examples/solaris_package/spec/remove_spec.rb +1 -1
  167. data/examples/state_attrs/spec/default_spec.rb +2 -2
  168. data/examples/step_into/spec/default_spec.rb +5 -2
  169. data/examples/stub_command/spec/default_spec.rb +1 -1
  170. data/examples/stub_data_bag/spec/default_spec.rb +1 -1
  171. data/examples/stub_data_bag_item/spec/default_spec.rb +1 -1
  172. data/examples/stub_search/spec/default_spec.rb +1 -1
  173. data/examples/subscribes/spec/chained_spec.rb +1 -1
  174. data/examples/subscribes/spec/default_spec.rb +1 -1
  175. data/examples/subscribes/spec/delayed_spec.rb +1 -1
  176. data/examples/subscribes/spec/immediately_spec.rb +1 -1
  177. data/examples/subversion/spec/checkout_spec.rb +1 -1
  178. data/examples/subversion/spec/export_spec.rb +1 -1
  179. data/examples/subversion/spec/force_export_spec.rb +1 -1
  180. data/examples/subversion/spec/sync_spec.rb +1 -1
  181. data/examples/template/spec/create_if_missing_spec.rb +1 -1
  182. data/examples/template/spec/create_spec.rb +1 -1
  183. data/examples/template/spec/delete_spec.rb +1 -1
  184. data/examples/template/spec/touch_spec.rb +1 -1
  185. data/examples/use_inline_resources/spec/default_spec.rb +4 -1
  186. data/examples/user/spec/create_spec.rb +1 -1
  187. data/examples/user/spec/lock_spec.rb +1 -1
  188. data/examples/user/spec/manage_spec.rb +1 -1
  189. data/examples/user/spec/modify_spec.rb +1 -1
  190. data/examples/user/spec/remove_spec.rb +1 -1
  191. data/examples/user/spec/unlock_spec.rb +1 -1
  192. data/examples/yum_package/spec/install_spec.rb +1 -1
  193. data/examples/yum_package/spec/purge_spec.rb +1 -1
  194. data/examples/yum_package/spec/remove_spec.rb +1 -1
  195. data/examples/yum_package/spec/upgrade_spec.rb +1 -1
  196. data/features/batch.feature +0 -3
  197. data/features/powershell_script.feature +0 -3
  198. data/features/render_file.feature +1 -6
  199. data/features/server.feature +0 -3
  200. data/features/smartos_package.feature +0 -4
  201. data/features/solaris_package.feature +0 -4
  202. data/features/state_attrs.feature +0 -4
  203. data/features/support/env.rb +0 -7
  204. data/gemfiles/{chef-11.12.0.gemfile → chef-11.16.0.gemfile} +1 -1
  205. data/gemfiles/chef-12.0.0.alpha.gemfile +5 -0
  206. data/lib/chefspec.rb +46 -14
  207. data/lib/chefspec/api.rb +0 -2
  208. data/lib/chefspec/api/apt_package.rb +1 -1
  209. data/lib/chefspec/api/batch.rb +1 -1
  210. data/lib/chefspec/api/chef_gem.rb +1 -1
  211. data/lib/chefspec/api/cookbook_file.rb +1 -1
  212. data/lib/chefspec/api/cron.rb +1 -1
  213. data/lib/chefspec/api/deploy.rb +1 -1
  214. data/lib/chefspec/api/directory.rb +1 -1
  215. data/lib/chefspec/api/dpkg_package.rb +1 -1
  216. data/lib/chefspec/api/easy_install_package.rb +1 -1
  217. data/lib/chefspec/api/env.rb +1 -1
  218. data/lib/chefspec/api/erl_call.rb +1 -1
  219. data/lib/chefspec/api/execute.rb +1 -1
  220. data/lib/chefspec/api/file.rb +1 -1
  221. data/lib/chefspec/api/freebsd_package.rb +1 -1
  222. data/lib/chefspec/api/gem_package.rb +1 -1
  223. data/lib/chefspec/api/git.rb +1 -1
  224. data/lib/chefspec/api/group.rb +1 -1
  225. data/lib/chefspec/api/http_request.rb +1 -1
  226. data/lib/chefspec/api/ifconfig.rb +1 -1
  227. data/lib/chefspec/api/ips_package.rb +1 -1
  228. data/lib/chefspec/api/link.rb +1 -1
  229. data/lib/chefspec/api/log.rb +1 -1
  230. data/lib/chefspec/api/macports_package.rb +1 -1
  231. data/lib/chefspec/api/mdadm.rb +1 -1
  232. data/lib/chefspec/api/mount.rb +1 -1
  233. data/lib/chefspec/api/ohai.rb +2 -2
  234. data/lib/chefspec/api/package.rb +1 -1
  235. data/lib/chefspec/api/pacman_package.rb +1 -1
  236. data/lib/chefspec/api/portage_package.rb +1 -1
  237. data/lib/chefspec/api/powershell_script.rb +1 -1
  238. data/lib/chefspec/api/registry_key.rb +1 -1
  239. data/lib/chefspec/api/remote_directory.rb +4 -4
  240. data/lib/chefspec/api/remote_file.rb +1 -1
  241. data/lib/chefspec/api/route.rb +1 -1
  242. data/lib/chefspec/api/rpm_package.rb +1 -1
  243. data/lib/chefspec/api/ruby_block.rb +1 -1
  244. data/lib/chefspec/api/script.rb +6 -6
  245. data/lib/chefspec/api/service.rb +1 -1
  246. data/lib/chefspec/api/smartos_package.rb +1 -1
  247. data/lib/chefspec/api/solaris_package.rb +1 -1
  248. data/lib/chefspec/api/subversion.rb +1 -1
  249. data/lib/chefspec/api/template.rb +1 -1
  250. data/lib/chefspec/api/user.rb +1 -1
  251. data/lib/chefspec/api/yum_package.rb +1 -1
  252. data/lib/chefspec/coverage/filters.rb +3 -0
  253. data/lib/chefspec/deprecations.rb +19 -123
  254. data/lib/chefspec/macros.rb +2 -2
  255. data/lib/chefspec/matchers/render_file_matcher.rb +2 -2
  256. data/lib/chefspec/matchers/resource_matcher.rb +1 -1
  257. data/lib/chefspec/matchers/state_attrs_matcher.rb +1 -1
  258. data/lib/chefspec/server.rb +4 -361
  259. data/lib/chefspec/server_methods.rb +175 -0
  260. data/lib/chefspec/server_runner.rb +86 -0
  261. data/lib/chefspec/{runner.rb → solo_runner.rb} +92 -43
  262. data/lib/chefspec/version.rb +1 -1
  263. data/spec/unit/{runner_spec.rb → solo_runner_spec.rb} +31 -25
  264. metadata +13 -10
@@ -0,0 +1,175 @@
1
+ module ChefSpec
2
+ # This module contains the list of methods that are specific to creating and
3
+ # managing resources within an Chef Zero instance. It is designed to be
4
+ # included in a class which exposes a `server` instance variable or method
5
+ # that returns a {ChefZero::Server} instance.
6
+ module ServerMethods
7
+ #
8
+ # The actual Chef Zero Server object.
9
+ #
10
+ # @return [ChefZero::Server]
11
+ #
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
+ end
21
+
22
+ #
23
+ # @macro entity
24
+ # @method create_$1(name, data = {})
25
+ # Create a new $1 on the Chef Server
26
+ #
27
+ # @param [String] name
28
+ # the name of the $1
29
+ # @param [Hash] data
30
+ # the list of data to load
31
+ #
32
+ #
33
+ # @method $1(name)
34
+ # Find a $1 at the given name
35
+ #
36
+ # @param [String] name
37
+ # the name of the $1
38
+ #
39
+ # @return [$2, nil]
40
+ #
41
+ #
42
+ # @method $3
43
+ # The list of $1 on the Chef Server
44
+ #
45
+ # @return [Array<Hash>]
46
+ # all the $1 on the Chef Server
47
+ #
48
+ #
49
+ # @method has_$1?(name)
50
+ # Determine if the Chef Server has the given $1
51
+ #
52
+ # @param [String] name
53
+ # the name of the $1 to find
54
+ #
55
+ # @return [true, false]
56
+ #
57
+ def self.entity(method, klass, key)
58
+ class_eval <<-EOH, __FILE__, __LINE__ + 1
59
+ def create_#{method}(name, data = {})
60
+ # Automatically set the "name" if no explicit one was given
61
+ data[:name] ||= name
62
+
63
+ # Convert it to JSON
64
+ data = JSON.fast_generate(data)
65
+
66
+ load_data(name, '#{key}', data)
67
+ end
68
+
69
+ def get_#{method}(name)
70
+ data = get('#{key}', name)
71
+ json = JSON.parse(data)
72
+
73
+ if #{klass}.respond_to?(:json_create)
74
+ #{klass}.json_create(json)
75
+ else
76
+ #{klass}.new(json)
77
+ end
78
+ rescue ChefZero::DataStore::DataNotFoundError
79
+ nil
80
+ end
81
+
82
+ def get_#{key}
83
+ get('#{key}')
84
+ end
85
+
86
+ def has_#{method}?(name)
87
+ !get('#{key}', name).nil?
88
+ rescue ChefZero::DataStore::DataNotFoundError
89
+ false
90
+ end
91
+ EOH
92
+ end
93
+
94
+ entity :client, Chef::Client, 'clients'
95
+ entity :data_bag, Chef::DataBag, 'data'
96
+ entity :environment, Chef::Environment, 'environments'
97
+ entity :node, Chef::Node, 'nodes'
98
+ entity :role, Chef::Role, 'roles'
99
+
100
+ #
101
+ # Create a new data_bag on the Chef Server. This overrides the method
102
+ # created by {entity}
103
+ #
104
+ # @param [String] name
105
+ # the name of the data bag
106
+ # @param [Hash] data
107
+ # the data to load into the data bag
108
+ #
109
+ def create_data_bag(name, data = {})
110
+ load_data(name, 'data', data)
111
+ end
112
+
113
+ #
114
+ # Create a new node on the Chef Server. This overrides the method created
115
+ # by {entity}, permitting users to pass a raw +Chef::Node+ object in
116
+ # addition to a hash.
117
+ #
118
+ # @example Create a node from a hash
119
+ #
120
+ # create_node('bacon', attribute: 'value')
121
+ #
122
+ # @example Create a node from a +Chef::Node+ object
123
+ #
124
+ # node = stub_node('bacon', platform: 'ubuntu', version: '12.04')
125
+ # create_node(node)
126
+ #
127
+ # @param [String, Chef::Node] object
128
+ # the object to create; this can be the name of the node, or an actual
129
+ # +Chef::Node+ object
130
+ # @param [Hash] data
131
+ # the list of data to populate the node with; this is ignored if an
132
+ # actual node object is given
133
+ #
134
+ def create_node(object, data = {})
135
+ if object.is_a?(Chef::Node)
136
+ name = object.name
137
+ data = object.to_json
138
+ else
139
+ name = object.to_s
140
+ data[:name] ||= name
141
+ data = JSON.fast_generate(data)
142
+ end
143
+
144
+ load_data(name, 'nodes', data)
145
+ end
146
+
147
+ #
148
+ # Shortcut method for loading data into Chef Zero.
149
+ #
150
+ # @param [String] name
151
+ # the name or id of the item to load
152
+ # @param [String, Symbol] key
153
+ # the key to load
154
+ # @param [Hash] data
155
+ # the data for the object, which will be converted to JSON and uploaded
156
+ # to the server
157
+ #
158
+ def load_data(name, key, data = {})
159
+ @server.load_data({ key => { name => data } })
160
+ end
161
+
162
+ #
163
+ # Get the path to an item in the data store.
164
+ #
165
+ def get(*args)
166
+ args.unshift('organizations', 'chef')
167
+
168
+ if args.size == 3
169
+ @server.data_store.list(args)
170
+ else
171
+ @server.data_store.get(args)
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,86 @@
1
+ require 'chef_zero/server'
2
+ require 'chef/cookbook_loader'
3
+ require 'chef/cookbook_uploader'
4
+
5
+ require_relative 'server_methods'
6
+ require_relative 'solo_runner'
7
+
8
+ module ChefSpec
9
+ class ServerRunner < SoloRunner
10
+ include ChefSpec::ServerMethods
11
+
12
+ # @see (SoloRunner#initialize)
13
+ def initialize(options = {})
14
+ # Call super, but do not pass in the block because we want to customize
15
+ # our yielding.
16
+ super(options, &nil)
17
+
18
+ Chef::Config[:client_key] = client_key
19
+ Chef::Config[:client_name] = 'chefspec'
20
+ Chef::Config[:node_name] = 'chefspec'
21
+ Chef::Config[:solo] = false
22
+
23
+ Chef::Config[:chef_server_url] = server.url
24
+ Chef::Config[:http_retry_count] = 0
25
+
26
+ # Start the Chef Zero instance in the background
27
+ server.start_background
28
+ at_exit { server.stop if server.running? }
29
+
30
+ # Unlike the SoloRunner, the node AND server object are yielded for
31
+ # customization
32
+ yield node, self if block_given?
33
+ end
34
+
35
+ #
36
+ # Upload the cookbooks to the Chef Server.
37
+ #
38
+ def upload_cookbooks!
39
+ loader = Chef::CookbookLoader.new(Chef::Config[:cookbook_path])
40
+ loader.load_cookbooks
41
+
42
+ uploader = Chef::CookbookUploader.new(loader.cookbooks, loader.cookbook_paths)
43
+ uploader.upload_cookbooks
44
+ end
45
+
46
+ # @see (SoloRunner#converge)
47
+ def converge(*recipe_names)
48
+ upload_cookbooks!
49
+ super
50
+ end
51
+
52
+ private
53
+
54
+ #
55
+ # The path to the insecure Chef Zero private key on disk. Because Chef
56
+ # requires the path to a file instead of the contents of the key (why),
57
+ # this method dynamically writes the +ChefZero::PRIVATE_KEY+ to disk and
58
+ # then returns that path.
59
+ #
60
+ # @return [String]
61
+ # the path to the client key on disk
62
+ #
63
+ def client_key
64
+ tmp = Dir.mktmpdir
65
+ path = File.join(tmp, 'client.pem')
66
+ File.open(path, 'wb') { |f| f.write(ChefZero::PRIVATE_KEY) }
67
+ at_exit { FileUtils.rm_rf(tmp) }
68
+ path
69
+ end
70
+
71
+ #
72
+ # A randomly assigned, open port for run the Chef Zero server.
73
+ #
74
+ # @return [Fixnum]
75
+ #
76
+ def port
77
+ return @port if @port
78
+
79
+ @server = TCPServer.new('127.0.0.1', 0)
80
+ @port = @server.addr[1].to_i
81
+ @server.close
82
+
83
+ return @port
84
+ end
85
+ end
86
+ end
@@ -5,25 +5,22 @@ require 'chef/providers'
5
5
  require 'chef/resources'
6
6
 
7
7
  module ChefSpec
8
- class Runner
9
- include ChefSpec::Normalize
10
-
8
+ class SoloRunner
11
9
  #
12
- # Defines a new runner method on the +ChefSpec::Runner+.
10
+ # Handy class method for just converging a runner if you do not care about
11
+ # initializing the runner with custom options.
13
12
  #
14
- # @param [Symbol] resource_name
15
- # the name of the resource to define a method
13
+ # @example
14
+ # ChefSpec::SoloRunner.converge('cookbook::recipe')
16
15
  #
17
- # @return [self]
18
- #
19
- def self.define_runner_method(resource_name)
20
- define_method(resource_name) do |identity|
21
- find_resource(resource_name, identity)
16
+ def self.converge(*recipe_names)
17
+ new.tap do |instance|
18
+ instance.converge(*recipe_names)
22
19
  end
23
-
24
- self
25
20
  end
26
21
 
22
+ include ChefSpec::Normalize
23
+
27
24
  # @return [Hash]
28
25
  attr_reader :options
29
26
 
@@ -31,19 +28,19 @@ module ChefSpec
31
28
  attr_reader :run_context
32
29
 
33
30
  #
34
- # Instantiate a new Runner to run examples with.
31
+ # Instantiate a new SoloRunner to run examples with.
35
32
  #
36
33
  # @example Instantiate a new Runner
37
- # ChefSpec::Runner.new
34
+ # ChefSpec::SoloRunner.new
38
35
  #
39
36
  # @example Specifying the platform and version
40
- # ChefSpec::Runner.new(platform: 'ubuntu', version: '12.04')
37
+ # ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '12.04')
41
38
  #
42
39
  # @example Specifying the cookbook path
43
- # ChefSpec::Runner.new(cookbook_path: ['/cookbooks'])
40
+ # ChefSpec::SoloRunner.new(cookbook_path: ['/cookbooks'])
44
41
  #
45
42
  # @example Specifying the log level
46
- # ChefSpec::Runner.new(log_level: :info)
43
+ # ChefSpec::SoloRunner.new(log_level: :info)
47
44
  #
48
45
  #
49
46
  # @param [Hash] options
@@ -62,35 +59,32 @@ module ChefSpec
62
59
  #
63
60
  # @yield [node] Configuration block for Chef::Node
64
61
  #
65
- def initialize(options = {}, &block)
66
- @options = options = {
67
- cookbook_path: RSpec.configuration.cookbook_path || calling_cookbook_path(caller),
68
- role_path: RSpec.configuration.role_path || default_role_path,
69
- log_level: RSpec.configuration.log_level,
70
- path: RSpec.configuration.path,
71
- platform: RSpec.configuration.platform,
72
- version: RSpec.configuration.version,
73
- }.merge(options)
62
+ def initialize(options = {})
63
+ @options = with_default_options(options)
74
64
 
75
- Chef::Log.level = options[:log_level]
65
+ Chef::Log.level = @options[:log_level]
76
66
 
77
67
  Chef::Config.reset!
78
68
  Chef::Config.formatters.clear
79
69
  Chef::Config.add_formatter('chefspec')
80
- Chef::Config[:cache_type] = 'Memory'
81
- Chef::Config[:client_key] = nil
82
- Chef::Config[:cookbook_path] = Array(options[:cookbook_path])
83
- Chef::Config[:no_lazy_load] = true
84
- Chef::Config[:role_path] = Array(options[:role_path])
85
- Chef::Config[:force_logger] = true
86
- Chef::Config[:solo] = true
70
+ Chef::Config[:cache_type] = 'Memory'
71
+ Chef::Config[:client_key] = nil
72
+ Chef::Config[:client_name] = nil
73
+ Chef::Config[:node_name] = nil
74
+ Chef::Config[:file_cache_path] = file_cache_path
75
+ Chef::Config[:cookbook_path] = Array(@options[:cookbook_path])
76
+ Chef::Config[:no_lazy_load] = true
77
+ Chef::Config[:role_path] = Array(@options[:role_path])
78
+ Chef::Config[:force_logger] = true
79
+ Chef::Config[:solo] = true
87
80
 
88
81
  yield node if block_given?
89
82
  end
90
83
 
91
84
  #
92
85
  # Execute the given `run_list` on the node, without actually converging
93
- # the node.
86
+ # the node. Each time {#converge} is called, the `run_list` is reset to the
87
+ # new value (it is **not** additive).
94
88
  #
95
89
  # @example Converging a single recipe
96
90
  # chef_run.converge('example::default')
@@ -102,7 +96,7 @@ module ChefSpec
102
96
  # @param [Array] recipe_names
103
97
  # The names of the recipe or recipes to converge
104
98
  #
105
- # @return [ChefSpec::Runner]
99
+ # @return [ChefSpec::SoloRunner]
106
100
  # A reference to the calling Runner (for chaining purposes)
107
101
  #
108
102
  def converge(*recipe_names)
@@ -203,7 +197,7 @@ module ChefSpec
203
197
  # Boolean method to determine the current phase of the Chef run (compiling
204
198
  # or converging)
205
199
  #
206
- # @return [Boolean]
200
+ # @return [true, false]
207
201
  #
208
202
  def compiling?
209
203
  !@converging
@@ -221,7 +215,7 @@ module ChefSpec
221
215
  # @param [Chef::Resource] resource
222
216
  # the Chef resource to try and step in to
223
217
  #
224
- # @return [Boolean]
218
+ # @return [true, false]
225
219
  #
226
220
  def step_into?(resource)
227
221
  key = resource_name(resource)
@@ -231,7 +225,7 @@ module ChefSpec
231
225
  #
232
226
  # Boolean method to determine if this Runner is in `dry_run` mode.
233
227
  #
234
- # @return [Boolean]
228
+ # @return [true, false]
235
229
  #
236
230
  def dry_run?
237
231
  !!options[:dry_run]
@@ -244,8 +238,7 @@ module ChefSpec
244
238
  # may change between versions of this gem.
245
239
  #
246
240
  def to_s
247
- return "chef_run: #{node.run_list.to_s}" unless node.run_list.empty?
248
- 'chef_run'
241
+ "#<#{self.class.name} run_list: [#{node.run_list}]>"
249
242
  end
250
243
 
251
244
  #
@@ -254,11 +247,67 @@ module ChefSpec
254
247
  # @return [String]
255
248
  #
256
249
  def inspect
257
- "#<#{self.class} options: #{options.inspect}, run_list: '#{node.run_list.to_s}'>"
250
+ "#<#{self.class.name}" \
251
+ " options: #{options.inspect}," \
252
+ " run_list: [#{node.run_list}]>"
253
+ end
254
+
255
+ #
256
+ # Respond to custom matchers defined by the user.
257
+ #
258
+ def method_missing(m, *args, &block)
259
+ if block = ChefSpec.matchers[resource_name(m.to_sym)]
260
+ instance_exec(args.first, &block)
261
+ else
262
+ super
263
+ end
264
+ end
265
+
266
+ #
267
+ # Inform Ruby that we respond to methods that are defined as custom
268
+ # matchers.
269
+ #
270
+ def respond_to_missing?(m, include_private = false)
271
+ ChefSpec.matchers.key?(m.to_sym) || super
258
272
  end
259
273
 
260
274
  private
261
275
 
276
+ #
277
+ # The path to cache files on disk. This value is created using
278
+ # {Dir.mktmpdir}. The method adds a {Kernel.at_exit} handler to ensure the
279
+ # temporary directory is deleted when the system exits.
280
+ #
281
+ # **This method creates a new temporary directory on each call!** As such,
282
+ # you should cache the result to a variable inside you system.
283
+ #
284
+ def file_cache_path
285
+ path = Dir.mktmpdir
286
+ at_exit { FileUtils.rm_rf(path) }
287
+ path
288
+ end
289
+
290
+ #
291
+ # Set the default options, with the given options taking precedence.
292
+ #
293
+ # @param [Hash] options
294
+ # the list of options to take precedence
295
+ #
296
+ # @return [Hash] options
297
+ #
298
+ def with_default_options(options)
299
+ config = RSpec.configuration
300
+
301
+ {
302
+ cookbook_path: config.cookbook_path || calling_cookbook_path(caller),
303
+ role_path: config.role_path || default_role_path,
304
+ log_level: config.log_level,
305
+ path: config.path,
306
+ platform: config.platform,
307
+ version: config.version,
308
+ }.merge(options)
309
+ end
310
+
262
311
  #
263
312
  # The inferred path from the calling spec.
264
313
  #