chefspec 4.0.2 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
  #