microwave 1.0.4 → 11.400.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (249) hide show
  1. data/CONTRIBUTING.md +155 -0
  2. data/README.md +89 -0
  3. data/Rakefile +2 -2
  4. data/bin/chef-apply +25 -0
  5. data/bin/chef-shell +34 -0
  6. data/bin/chef-solo +0 -2
  7. data/bin/shef +6 -5
  8. data/lib/chef.rb +2 -4
  9. data/spec/data/big_json.json +2 -1
  10. data/spec/data/big_json_plus_one.json +2 -1
  11. data/spec/data/cookbooks/chefignore +2 -0
  12. data/spec/data/cookbooks/openldap/attributes/default.rb +10 -9
  13. data/spec/data/cookbooks/openldap/attributes/smokey.rb +1 -1
  14. data/spec/data/git_bundles/sinatra-test-app-with-callback-files.gitbundle +0 -0
  15. data/spec/data/git_bundles/sinatra-test-app-with-symlinks.gitbundle +0 -0
  16. data/spec/data/git_bundles/sinatra-test-app.gitbundle +0 -0
  17. data/spec/data/lwrp/providers/inline_compiler.rb +26 -0
  18. data/spec/data/nodes/default.rb +3 -3
  19. data/spec/data/nodes/test.example.com.rb +3 -3
  20. data/spec/data/nodes/test.rb +3 -3
  21. data/spec/data/partial_one.erb +1 -0
  22. data/spec/data/run_context/cookbooks/circular-dep1/attributes/default.rb +4 -0
  23. data/spec/data/run_context/cookbooks/circular-dep1/definitions/circular_dep1_res.rb +1 -0
  24. data/spec/data/run_context/cookbooks/circular-dep1/libraries/lib.rb +2 -0
  25. data/spec/data/run_context/cookbooks/circular-dep1/metadata.rb +2 -0
  26. data/spec/data/run_context/cookbooks/circular-dep1/providers/provider.rb +1 -0
  27. data/spec/data/run_context/cookbooks/circular-dep1/recipes/default.rb +0 -0
  28. data/spec/data/run_context/cookbooks/circular-dep1/resources/resource.rb +1 -0
  29. data/spec/data/run_context/cookbooks/circular-dep2/attributes/default.rb +3 -0
  30. data/spec/data/run_context/cookbooks/circular-dep2/definitions/circular_dep2_res.rb +1 -0
  31. data/spec/data/run_context/cookbooks/circular-dep2/libraries/lib.rb +2 -0
  32. data/spec/data/run_context/cookbooks/circular-dep2/metadata.rb +2 -0
  33. data/spec/data/run_context/cookbooks/circular-dep2/providers/provider.rb +1 -0
  34. data/spec/data/run_context/cookbooks/circular-dep2/recipes/default.rb +0 -0
  35. data/spec/data/run_context/cookbooks/circular-dep2/resources/resource.rb +1 -0
  36. data/spec/data/run_context/cookbooks/dependency1/attributes/aa_first.rb +2 -0
  37. data/spec/data/run_context/cookbooks/dependency1/attributes/default.rb +2 -0
  38. data/spec/data/run_context/cookbooks/dependency1/attributes/zz_last.rb +3 -0
  39. data/spec/data/run_context/cookbooks/dependency1/definitions/dependency1_res.rb +1 -0
  40. data/spec/data/run_context/cookbooks/dependency1/libraries/lib.rb +2 -0
  41. data/spec/data/run_context/cookbooks/dependency1/providers/provider.rb +1 -0
  42. data/spec/data/run_context/cookbooks/dependency1/recipes/default.rb +0 -0
  43. data/spec/data/run_context/cookbooks/dependency1/resources/resource.rb +1 -0
  44. data/spec/data/run_context/cookbooks/dependency2/attributes/default.rb +3 -0
  45. data/spec/data/run_context/cookbooks/dependency2/definitions/dependency2_res.rb +1 -0
  46. data/spec/data/run_context/cookbooks/dependency2/libraries/lib.rb +2 -0
  47. data/spec/data/run_context/cookbooks/dependency2/providers/provider.rb +1 -0
  48. data/spec/data/run_context/cookbooks/dependency2/recipes/default.rb +0 -0
  49. data/spec/data/run_context/cookbooks/dependency2/resources/resource.rb +1 -0
  50. data/spec/data/run_context/cookbooks/no-default-attr/attributes/server.rb +3 -0
  51. data/spec/data/run_context/cookbooks/no-default-attr/definitions/no_default-attr_res.rb +1 -0
  52. data/spec/data/run_context/cookbooks/no-default-attr/providers/provider.rb +1 -0
  53. data/spec/data/run_context/cookbooks/no-default-attr/recipes/default.rb +0 -0
  54. data/spec/data/run_context/cookbooks/no-default-attr/resources/resource.rb +1 -0
  55. data/spec/data/run_context/cookbooks/test-with-circular-deps/attributes/default.rb +3 -0
  56. data/spec/data/run_context/cookbooks/test-with-circular-deps/definitions/test_with-circular-deps_res.rb +1 -0
  57. data/spec/data/run_context/cookbooks/test-with-circular-deps/libraries/lib.rb +2 -0
  58. data/spec/data/run_context/cookbooks/test-with-circular-deps/metadata.rb +2 -0
  59. data/spec/data/run_context/cookbooks/test-with-circular-deps/providers/provider.rb +1 -0
  60. data/spec/data/run_context/cookbooks/test-with-circular-deps/recipes/default.rb +0 -0
  61. data/spec/data/run_context/cookbooks/test-with-circular-deps/resources/resource.rb +1 -0
  62. data/spec/data/run_context/cookbooks/test-with-deps/attributes/default.rb +3 -0
  63. data/spec/data/run_context/cookbooks/test-with-deps/definitions/test_with-deps_res.rb +1 -0
  64. data/spec/data/run_context/cookbooks/test-with-deps/libraries/lib.rb +1 -0
  65. data/spec/data/run_context/cookbooks/test-with-deps/metadata.rb +3 -0
  66. data/spec/data/run_context/cookbooks/test-with-deps/providers/provider.rb +1 -0
  67. data/spec/data/run_context/cookbooks/test-with-deps/recipes/default.rb +0 -0
  68. data/spec/data/run_context/cookbooks/test-with-deps/recipes/server.rb +0 -0
  69. data/spec/data/run_context/cookbooks/test-with-deps/resources/resource.rb +1 -0
  70. data/spec/data/run_context/cookbooks/test/attributes/default.rb +0 -0
  71. data/spec/data/run_context/cookbooks/test/attributes/george.rb +1 -1
  72. data/spec/data/run_context/cookbooks/test/definitions/test_res.rb +1 -0
  73. data/spec/data/run_context/cookbooks/test/providers/provider.rb +1 -0
  74. data/spec/data/run_context/cookbooks/test/resources/resource.rb +1 -0
  75. data/spec/data/shef-config.rb +10 -0
  76. data/spec/functional/dsl/registry_helper_spec.rb +63 -0
  77. data/spec/functional/knife/cookbook_delete_spec.rb +0 -2
  78. data/spec/functional/knife/exec_spec.rb +4 -6
  79. data/spec/functional/knife/smoke_test.rb +34 -0
  80. data/spec/functional/knife/ssh_spec.rb +64 -3
  81. data/spec/functional/resource/cookbook_file_spec.rb +33 -2
  82. data/spec/functional/resource/deploy_revision_spec.rb +515 -0
  83. data/spec/functional/resource/directory_spec.rb +4 -0
  84. data/spec/functional/resource/file_spec.rb +56 -22
  85. data/spec/functional/resource/link_spec.rb +12 -10
  86. data/spec/functional/resource/registry_spec.rb +572 -0
  87. data/spec/functional/resource/remote_directory_spec.rb +142 -36
  88. data/spec/functional/resource/remote_file_spec.rb +28 -3
  89. data/spec/functional/resource/template_spec.rb +23 -2
  90. data/spec/functional/run_lock_spec.rb +238 -0
  91. data/spec/functional/shell_spec.rb +101 -0
  92. data/spec/functional/tiny_server_spec.rb +5 -4
  93. data/spec/functional/win32/registry_helper_spec.rb +632 -0
  94. data/spec/functional/win32/security_spec.rb +37 -0
  95. data/spec/spec_helper.rb +15 -3
  96. data/spec/stress/win32/security_spec.rb +5 -5
  97. data/spec/support/chef_helpers.rb +14 -3
  98. data/spec/support/lib/chef/resource/cat.rb +3 -5
  99. data/spec/support/lib/chef/resource/one_two_three_four.rb +8 -10
  100. data/spec/support/lib/chef/resource/zen_master.rb +8 -10
  101. data/spec/support/matchers/leak.rb +1 -1
  102. data/spec/support/platform_helpers.rb +18 -0
  103. data/spec/support/shared/functional/directory_resource.rb +85 -23
  104. data/spec/support/shared/functional/file_resource.rb +198 -53
  105. data/spec/support/shared/functional/securable_resource.rb +140 -105
  106. data/spec/support/shared/functional/securable_resource_with_reporting.rb +375 -0
  107. data/spec/support/shared/unit/file_system_support.rb +110 -0
  108. data/spec/support/shared/unit/platform_introspector.rb +162 -0
  109. data/spec/tiny_server.rb +29 -10
  110. data/spec/unit/api_client/registration_spec.rb +172 -0
  111. data/spec/unit/api_client_spec.rb +156 -103
  112. data/spec/unit/application/apply.rb +84 -0
  113. data/spec/unit/application/knife_spec.rb +5 -0
  114. data/spec/unit/application_spec.rb +57 -2
  115. data/spec/unit/chef_fs/diff_spec.rb +329 -0
  116. data/spec/unit/chef_fs/file_pattern_spec.rb +526 -0
  117. data/spec/unit/chef_fs/file_system/chef_server_root_dir_spec.rb +237 -0
  118. data/spec/unit/chef_fs/file_system/cookbooks_dir_spec.rb +568 -0
  119. data/spec/unit/chef_fs/file_system/data_bags_dir_spec.rb +220 -0
  120. data/spec/unit/chef_fs/file_system_spec.rb +136 -0
  121. data/spec/unit/client_spec.rb +188 -16
  122. data/spec/unit/config_spec.rb +54 -4
  123. data/spec/unit/cookbook/chefignore_spec.rb +2 -1
  124. data/spec/unit/cookbook/syntax_check_spec.rb +48 -109
  125. data/spec/unit/cookbook_loader_spec.rb +153 -91
  126. data/spec/unit/cookbook_manifest_spec.rb +81 -81
  127. data/spec/unit/cookbook_spec.rb +3 -20
  128. data/spec/unit/cookbook_version_spec.rb +23 -122
  129. data/spec/unit/digester_spec.rb +50 -0
  130. data/spec/unit/dsl/data_query_spec.rb +66 -0
  131. data/spec/unit/dsl/platform_introspection_spec.rb +130 -0
  132. data/spec/unit/dsl/regsitry_helper_spec.rb +55 -0
  133. data/spec/unit/encrypted_data_bag_item_spec.rb +126 -10
  134. data/spec/unit/environment_spec.rb +0 -130
  135. data/spec/unit/exceptions_spec.rb +2 -3
  136. data/spec/unit/formatters/error_inspectors/resource_failure_inspector_spec.rb +23 -3
  137. data/spec/unit/json_compat_spec.rb +69 -0
  138. data/spec/unit/knife/bootstrap_spec.rb +81 -28
  139. data/spec/unit/knife/client_reregister_spec.rb +23 -22
  140. data/spec/unit/knife/configure_spec.rb +29 -26
  141. data/spec/unit/knife/cookbook_metadata_spec.rb +11 -4
  142. data/spec/unit/knife/cookbook_site_install_spec.rb +12 -2
  143. data/spec/unit/knife/cookbook_test_spec.rb +1 -0
  144. data/spec/unit/knife/cookbook_upload_spec.rb +41 -2
  145. data/spec/unit/knife/core/bootstrap_context_spec.rb +8 -1
  146. data/spec/unit/knife/core/ui_spec.rb +156 -7
  147. data/spec/unit/knife/data_bag_create_spec.rb +14 -0
  148. data/spec/unit/knife/data_bag_edit_spec.rb +14 -4
  149. data/spec/unit/knife/data_bag_from_file_spec.rb +17 -5
  150. data/spec/unit/knife/data_bag_show_spec.rb +11 -4
  151. data/spec/unit/knife/index_rebuild_spec.rb +96 -33
  152. data/spec/unit/knife/knife_help.rb +7 -7
  153. data/spec/unit/knife/node_run_list_remove_spec.rb +2 -1
  154. data/spec/unit/knife/ssh_spec.rb +121 -15
  155. data/spec/unit/knife/status_spec.rb +2 -2
  156. data/spec/unit/knife/user_create_spec.rb +86 -0
  157. data/spec/unit/knife/user_delete_spec.rb +39 -0
  158. data/spec/unit/knife/user_edit_spec.rb +42 -0
  159. data/spec/unit/knife/user_list_spec.rb +32 -0
  160. data/spec/unit/knife/user_reregister_spec.rb +53 -0
  161. data/spec/unit/knife/user_show_spec.rb +41 -0
  162. data/spec/unit/knife_spec.rb +53 -0
  163. data/spec/unit/lwrp_spec.rb +59 -17
  164. data/spec/unit/mixin/checksum_spec.rb +2 -2
  165. data/spec/unit/mixin/deep_merge_spec.rb +56 -491
  166. data/spec/unit/mixin/deprecation_spec.rb +23 -0
  167. data/spec/unit/mixin/enforce_ownership_and_permissions_spec.rb +6 -1
  168. data/spec/unit/mixin/params_validate_spec.rb +4 -2
  169. data/spec/unit/mixin/securable_spec.rb +5 -3
  170. data/spec/unit/mixin/template_spec.rb +119 -0
  171. data/spec/unit/node/attribute_spec.rb +272 -137
  172. data/spec/unit/node/immutable_collections_spec.rb +139 -0
  173. data/spec/unit/node_spec.rb +411 -339
  174. data/spec/unit/platform_spec.rb +8 -8
  175. data/spec/unit/provider/breakpoint_spec.rb +8 -8
  176. data/spec/unit/provider/cookbook_file_spec.rb +4 -8
  177. data/spec/unit/provider/deploy/revision_spec.rb +2 -8
  178. data/spec/unit/provider/deploy_spec.rb +6 -40
  179. data/spec/unit/provider/directory_spec.rb +103 -68
  180. data/spec/unit/provider/erl_call_spec.rb +0 -2
  181. data/spec/unit/provider/file_spec.rb +69 -59
  182. data/spec/unit/provider/git_spec.rb +0 -10
  183. data/spec/unit/provider/group/groupadd_spec.rb +1 -1
  184. data/spec/unit/provider/group/usermod_spec.rb +2 -2
  185. data/spec/unit/provider/http_request_spec.rb +28 -69
  186. data/spec/unit/provider/ifconfig_spec.rb +2 -2
  187. data/spec/unit/provider/link_spec.rb +1 -1
  188. data/spec/unit/provider/ohai_spec.rb +4 -4
  189. data/spec/unit/provider/package/apt_spec.rb +0 -1
  190. data/spec/unit/provider/package/ips_spec.rb +0 -1
  191. data/spec/unit/provider/package/rubygems_spec.rb +0 -18
  192. data/spec/unit/provider/package/yum_spec.rb +79 -15
  193. data/spec/unit/provider/package_spec.rb +7 -5
  194. data/spec/unit/provider/registry_key_spec.rb +269 -0
  195. data/spec/unit/provider/remote_directory_spec.rb +24 -7
  196. data/spec/unit/provider/remote_file_spec.rb +36 -0
  197. data/spec/unit/provider/route_spec.rb +3 -6
  198. data/spec/unit/provider/ruby_block_spec.rb +8 -0
  199. data/spec/unit/provider/service/arch_service_spec.rb +4 -4
  200. data/spec/unit/provider/service/debian_service_spec.rb +1 -1
  201. data/spec/unit/provider/service/freebsd_service_spec.rb +4 -4
  202. data/spec/unit/provider/service/init_service_spec.rb +26 -3
  203. data/spec/unit/provider/service/insserv_service_spec.rb +1 -1
  204. data/spec/unit/provider/service/invokercd_service_spec.rb +3 -3
  205. data/spec/unit/provider/service/redhat_spec.rb +1 -1
  206. data/spec/unit/provider/service/simple_service_spec.rb +3 -3
  207. data/spec/unit/provider/service/upstart_service_spec.rb +7 -7
  208. data/spec/unit/provider/service_spec.rb +2 -2
  209. data/spec/unit/provider/subversion_spec.rb +1 -1
  210. data/spec/unit/provider/template_spec.rb +35 -11
  211. data/spec/unit/provider/user/dscl_spec.rb +57 -31
  212. data/spec/unit/provider/user_spec.rb +7 -16
  213. data/spec/unit/provider_spec.rb +4 -3
  214. data/spec/unit/recipe_spec.rb +10 -8
  215. data/spec/unit/registry_helper_spec.rb +376 -0
  216. data/spec/unit/resource/log_spec.rb +9 -0
  217. data/spec/unit/resource/registry_key_spec.rb +171 -0
  218. data/spec/unit/resource/remote_file_spec.rb +21 -23
  219. data/spec/unit/resource/ruby_block_spec.rb +7 -3
  220. data/spec/unit/resource/service_spec.rb +11 -0
  221. data/spec/unit/resource_spec.rb +27 -4
  222. data/spec/unit/rest/auth_credentials_spec.rb +2 -14
  223. data/spec/unit/rest_spec.rb +122 -187
  224. data/spec/unit/run_context/cookbook_compiler_spec.rb +181 -0
  225. data/spec/unit/run_context_spec.rb +18 -4
  226. data/spec/unit/run_list_spec.rb +0 -209
  227. data/spec/unit/run_lock_spec.rb +37 -0
  228. data/spec/unit/runner_spec.rb +101 -2
  229. data/spec/unit/scan_access_control_spec.rb +4 -4
  230. data/spec/unit/{shef → shell}/model_wrapper_spec.rb +5 -5
  231. data/spec/unit/{shef/shef_ext_spec.rb → shell/shell_ext_spec.rb} +21 -21
  232. data/spec/unit/{shef/shef_session_spec.rb → shell/shell_session_spec.rb} +12 -12
  233. data/spec/unit/shell_out_spec.rb +18 -0
  234. data/spec/unit/{shef_spec.rb → shell_spec.rb} +20 -20
  235. data/spec/unit/user_spec.rb +255 -0
  236. metadata +162 -157
  237. data/README.rdoc +0 -177
  238. data/spec/unit/certificate_spec.rb +0 -76
  239. data/spec/unit/checksum_cache_spec.rb +0 -209
  240. data/spec/unit/checksum_spec.rb +0 -94
  241. data/spec/unit/couchdb_spec.rb +0 -274
  242. data/spec/unit/index_queue_spec.rb +0 -391
  243. data/spec/unit/json_compat_spect.rb +0 -53
  244. data/spec/unit/mixin/language_spec.rb +0 -305
  245. data/spec/unit/openid_registration_spec.rb +0 -153
  246. data/spec/unit/solr_query/query_transform_spec.rb +0 -454
  247. data/spec/unit/solr_query/solr_http_request_spec.rb +0 -244
  248. data/spec/unit/solr_query_spec.rb +0 -203
  249. data/spec/unit/webui_user_spec.rb +0 -238
@@ -22,12 +22,15 @@ describe Chef::Resource::RemoteDirectory do
22
22
  include_context Chef::Resource::Directory
23
23
 
24
24
  let(:directory_base) { "directory_spec" }
25
+ let(:default_mode) { "755" }
25
26
 
26
27
  def create_resource
27
28
  cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
28
29
  Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) }
29
30
  node = Chef::Node.new
30
- cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(cookbook_repo))
31
+ cl = Chef::CookbookLoader.new(cookbook_repo)
32
+ cl.load_cookbooks
33
+ cookbook_collection = Chef::CookbookCollection.new(cl)
31
34
  events = Chef::EventDispatch::Dispatcher.new
32
35
  run_context = Chef::RunContext.new(node, cookbook_collection, events)
33
36
 
@@ -37,57 +40,90 @@ describe Chef::Resource::RemoteDirectory do
37
40
  resource
38
41
  end
39
42
 
43
+ def create_extraneous_files
44
+ FileUtils.mkdir_p(File.join(path, 'remotesubdir'))
45
+ @existing1 = File.join(path, 'marked_for_death.txt')
46
+ @existing2 = File.join(path, 'remotesubdir', 'marked_for_death_again.txt')
47
+ FileUtils.touch(@existing1)
48
+ FileUtils.touch(@existing2)
49
+ end
50
+
40
51
  let!(:resource) do
41
52
  create_resource
42
53
  end
43
54
 
55
+ let(:resource_second_pass) do
56
+ create_resource
57
+ end
58
+
59
+ # See spec/data/cookbooks/openldap/files/default
60
+ let(:expected_files) do
61
+ [
62
+ File.join(path, 'remote_dir_file1.txt'),
63
+ File.join(path, 'remote_dir_file2.txt'),
64
+ File.join(path, 'remotesubdir', 'remote_subdir_file1.txt'),
65
+ File.join(path, 'remotesubdir', 'remote_subdir_file2.txt'),
66
+ File.join(path, 'remotesubdir', '.a_dotfile'),
67
+ File.join(path, '.a_dotdir', '.a_dotfile_in_a_dotdir')
68
+ ]
69
+ end
70
+
44
71
  it_behaves_like "a directory resource"
45
72
 
46
- context "when creating the remote directory" do
47
- it "transfers the directory with all contents" do
48
- resource.run_action(:create)
49
- File.should exist(File.join(path, 'remote_dir_file1.txt'))
50
- File.should exist(File.join(path, 'remote_dir_file2.txt'))
51
- File.should exist(File.join(path, 'remotesubdir', 'remote_subdir_file1.txt'))
52
- File.should exist(File.join(path, 'remotesubdir', 'remote_subdir_file2.txt'))
53
- File.should exist(File.join(path, 'remotesubdir', '.a_dotfile'))
54
- File.should exist(File.join(path, '.a_dotdir', '.a_dotfile_in_a_dotdir'))
55
- end
73
+ it_behaves_like "a securable resource with reporting"
56
74
 
57
- context "with purging enabled" do
58
- before(:each) do
59
- resource.purge(true)
75
+ context "when creating the remote directory with purging disabled" do
76
+
77
+ context "and the directory does not yet exist" do
78
+ before do
79
+ resource.run_action(:create)
60
80
  end
61
81
 
62
- it "removes existing files if purge is true" do
63
- FileUtils.mkdir_p(File.join(path, 'remotesubdir'))
64
- existing1 = File.join(path, 'marked_for_death.txt')
65
- existing2 = File.join(path, 'remotesubdir', 'marked_for_death_again.txt')
66
- FileUtils.touch(existing1)
67
- FileUtils.touch(existing2)
82
+ it "transfers the directory with all contents" do
83
+ expected_files.each do |file_path|
84
+ File.should exist(file_path)
85
+ end
86
+ end
87
+
88
+ it "is marked as updated by last action" do
89
+ resource.should be_updated_by_last_action
90
+ end
91
+ end
68
92
 
93
+ context "and there are extraneous files in the directory" do
94
+ before do
95
+ create_extraneous_files
69
96
  resource.run_action(:create)
70
- File.should_not exist(existing1)
71
- File.should_not exist(existing2)
72
97
  end
73
98
 
74
- it "removes files in subdirectories before files above" do
75
- FileUtils.mkdir_p(File.join(path, 'a', 'multiply', 'nested', 'directory'))
76
- existing1 = File.join(path, 'a', 'foo.txt')
77
- existing2 = File.join(path, 'a', 'multiply', 'bar.txt')
78
- existing3 = File.join(path, 'a', 'multiply', 'nested', 'baz.txt')
79
- existing4 = File.join(path, 'a', 'multiply', 'nested', 'directory', 'qux.txt')
80
- FileUtils.touch(existing1)
81
- FileUtils.touch(existing2)
82
- FileUtils.touch(existing3)
83
- FileUtils.touch(existing4)
99
+ it "does not modify the expected state of the directory" do
100
+ expected_files.each do |file_path|
101
+ File.should exist(file_path)
102
+ end
103
+ end
84
104
 
105
+ it "does not remove unmanaged files" do
106
+ File.should exist(@existing1)
107
+ File.should exist(@existing2)
108
+ end
109
+ end
110
+
111
+ context "and the directory is in the desired state" do
112
+ before do
85
113
  resource.run_action(:create)
86
- File.should_not exist(existing1)
87
- File.should_not exist(existing2)
88
- File.should_not exist(existing3)
89
- File.should_not exist(existing4)
114
+ resource_second_pass.run_action(:create)
90
115
  end
116
+
117
+ it "does not modify the expected state of the directory" do
118
+ expected_files.each do |file_path|
119
+ File.should exist(file_path)
120
+ end
121
+ end
122
+
123
+ it "is not marked as updated by last action" do
124
+ resource_second_pass.should_not be_updated_by_last_action
125
+ end
126
+
91
127
  end
92
128
 
93
129
  describe "with overwrite disabled" do
@@ -111,4 +147,74 @@ describe Chef::Resource::RemoteDirectory do
111
147
  end
112
148
  end
113
149
  end
150
+
151
+ context "when creating the directory with purging enabled" do
152
+ before(:each) do
153
+ resource.purge(true)
154
+ end
155
+
156
+ context "and there are no extraneous files in the directory" do
157
+ before do
158
+ resource.run_action(:create)
159
+ end
160
+
161
+ it "creates the directory contents as normal" do
162
+ expected_files.each do |file_path|
163
+ File.should exist(file_path)
164
+ end
165
+ end
166
+
167
+ end
168
+
169
+ context "and there are extraneous files in the directory" do
170
+ before do
171
+ create_extraneous_files
172
+ resource.run_action(:create)
173
+ end
174
+
175
+ it "removes unmanaged files" do
176
+ File.should_not exist(@existing1)
177
+ File.should_not exist(@existing2)
178
+ end
179
+
180
+ it "does not modify managed files" do
181
+ expected_files.each do |file_path|
182
+ File.should exist(file_path)
183
+ end
184
+ end
185
+
186
+ it "is marked as updated by last action" do
187
+ resource.should be_updated_by_last_action
188
+ end
189
+ end
190
+
191
+ context "and there are deeply nested extraneous files in the directory" do
192
+ before do
193
+ FileUtils.mkdir_p(File.join(path, 'a', 'multiply', 'nested', 'directory'))
194
+ @existing1 = File.join(path, 'a', 'foo.txt')
195
+ @existing2 = File.join(path, 'a', 'multiply', 'bar.txt')
196
+ @existing3 = File.join(path, 'a', 'multiply', 'nested', 'baz.txt')
197
+ @existing4 = File.join(path, 'a', 'multiply', 'nested', 'directory', 'qux.txt')
198
+ FileUtils.touch(@existing1)
199
+ FileUtils.touch(@existing2)
200
+ FileUtils.touch(@existing3)
201
+ FileUtils.touch(@existing4)
202
+
203
+ resource.run_action(:create)
204
+ end
205
+
206
+ it "removes files in subdirectories before files above" do
207
+ File.should_not exist(@existing1)
208
+ File.should_not exist(@existing2)
209
+ File.should_not exist(@existing3)
210
+ File.should_not exist(@existing4)
211
+ end
212
+
213
+ it "is marked as updated by last action" do
214
+ resource.should be_updated_by_last_action
215
+ end
216
+
217
+ end
218
+ end
219
+
114
220
  end
@@ -24,7 +24,13 @@ describe Chef::Resource::RemoteFile do
24
24
 
25
25
  let(:file_base) { "remote_file_spec" }
26
26
  let(:source) { 'http://localhost:9000/nyan_cat.png' }
27
- let(:expected_content) { IO.read(File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png')) }
27
+ let(:expected_content) do
28
+ content = File.open(File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png'), "rb") do |f|
29
+ f.read
30
+ end
31
+ content.force_encoding(Encoding::BINARY) if content.respond_to?(:force_encoding)
32
+ content
33
+ end
28
34
 
29
35
  def create_resource
30
36
  node = Chef::Node.new
@@ -39,14 +45,31 @@ describe Chef::Resource::RemoteFile do
39
45
  create_resource
40
46
  end
41
47
 
48
+ let(:default_mode) do
49
+ # TODO: Lots of ugly here :(
50
+ # RemoteFile uses FileUtils.cp. FileUtils does a copy by opening the
51
+ # destination file and writing to it. Before 1.9.3, it does not preserve
52
+ # the mode of the copied file. In 1.9.3 and after, it does. So we have to
53
+ # figure out what the default mode ought to be via heuristic.
54
+
55
+ t = Tempfile.new("get-the-mode")
56
+ path = t.path
57
+ path_2 = t.path + "fileutils-mode-test"
58
+ FileUtils.cp(path, path_2)
59
+ t.close
60
+ m = File.stat(path_2).mode
61
+ (07777 & m).to_s(8)
62
+ end
63
+
42
64
  before(:all) do
43
- Thin::Logging.silent = false
44
65
  @server = TinyServer::Manager.new
45
66
  @server.start
46
67
  @api = TinyServer::API.instance
47
68
  @api.clear
48
69
  @api.get("/nyan_cat.png", 200) {
49
- IO.read(File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png'))
70
+ File.open(File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png'), "rb") do |f|
71
+ f.read
72
+ end
50
73
  }
51
74
  end
52
75
 
@@ -55,4 +78,6 @@ describe Chef::Resource::RemoteFile do
55
78
  end
56
79
 
57
80
  it_behaves_like "a file resource"
81
+
82
+ it_behaves_like "a securable resource with reporting"
58
83
  end
@@ -27,14 +27,16 @@ describe Chef::Resource::Template do
27
27
 
28
28
  let(:node) do
29
29
  node = Chef::Node.new
30
- node[:slappiness] = "a warm gun"
30
+ node.normal[:slappiness] = "a warm gun"
31
31
  node
32
32
  end
33
33
 
34
34
  def create_resource
35
35
  cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
36
36
  Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) }
37
- cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(cookbook_repo))
37
+ cl = Chef::CookbookLoader.new(cookbook_repo)
38
+ cl.load_cookbooks
39
+ cookbook_collection = Chef::CookbookCollection.new(cl)
38
40
  events = Chef::EventDispatch::Dispatcher.new
39
41
  run_context = Chef::RunContext.new(node, cookbook_collection, events)
40
42
  resource = Chef::Resource::Template.new(path, run_context)
@@ -47,8 +49,27 @@ describe Chef::Resource::Template do
47
49
  create_resource
48
50
  end
49
51
 
52
+ let(:default_mode) do
53
+ # TODO: Lots of ugly here :(
54
+ # RemoteFile uses FileUtils.cp. FileUtils does a copy by opening the
55
+ # destination file and writing to it. Before 1.9.3, it does not preserve
56
+ # the mode of the copied file. In 1.9.3 and after, it does. So we have to
57
+ # figure out what the default mode ought to be via heuristic.
58
+
59
+ t = Tempfile.new("get-the-mode")
60
+ path = t.path
61
+ path_2 = t.path + "fileutils-mode-test"
62
+ FileUtils.cp(path, path_2)
63
+ t.close
64
+ m = File.stat(path_2).mode
65
+ (07777 & m).to_s(8)
66
+ end
67
+
68
+
50
69
  it_behaves_like "a file resource"
51
70
 
71
+ it_behaves_like "a securable resource with reporting"
72
+
52
73
  context "when the target file does not exist" do
53
74
  it "creates the template with the rendered content using the variable attribute when the :create action is run" do
54
75
  resource.source('openldap_variable_stuff.conf.erb')
@@ -0,0 +1,238 @@
1
+ #
2
+ # Author:: Daniel DeLeo (<dan@opscode.com>)
3
+ # Copyright:: Copyright (c) 2012 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require File.expand_path('../../spec_helper', __FILE__)
19
+ require 'chef/client'
20
+
21
+ describe Chef::RunLock do
22
+
23
+ # This behavior is believed to work on windows, but the tests use UNIX APIs.
24
+ describe "when locking the chef-client run", :unix_only => true do
25
+
26
+ ##
27
+ # Lockfile location and helpers
28
+
29
+ let(:random_temp_root) do
30
+ Kernel.srand(Time.now.to_i + Process.pid)
31
+ "/tmp/#{Kernel.rand(Time.now.to_i + Process.pid)}"
32
+ end
33
+
34
+ let(:file_cache_path){ "/var/chef/cache" }
35
+ let(:lockfile){ "#{random_temp_root}/this/long/path/does/not/exist/chef-client-running.pid" }
36
+
37
+ # make sure to start with a clean slate.
38
+ before(:each){ FileUtils.rm_r(random_temp_root) if File.exist?(random_temp_root) }
39
+ after(:each){ FileUtils.rm_r(random_temp_root) }
40
+
41
+ def wait_on_lock
42
+ tries = 0
43
+ until File.exist?(lockfile)
44
+ raise "Lockfile never created, abandoning test" if tries > 10
45
+ tries += 1
46
+ sleep 0.1
47
+ end
48
+ end
49
+
50
+ ##
51
+ # Side channel via a pipe allows child processes to send errors to the parent
52
+
53
+ # Don't lazy create the pipe or else we might not share it with subprocesses
54
+ let!(:error_pipe) do
55
+ r,w = IO.pipe
56
+ w.sync = true
57
+ [r,w]
58
+ end
59
+
60
+ let(:error_read) { error_pipe[0] }
61
+ let(:error_write) { error_pipe[1] }
62
+
63
+ after do
64
+ error_read.close unless error_read.closed?
65
+ error_write.close unless error_write.closed?
66
+ end
67
+
68
+ # Send a RuntimeError from the child process to the parent process. Also
69
+ # prints error to $stdout, just in case something goes wrong with the error
70
+ # marshaling stuff.
71
+ def send_side_channel_error(message)
72
+ $stderr.puts(message)
73
+ $stderr.puts(caller)
74
+ e = RuntimeError.new(message)
75
+ error_write.print(Marshal.dump(e))
76
+ end
77
+
78
+ # Read the error (if any) from the error channel. If a marhaled error is
79
+ # present, it is unmarshaled and raised (which will fail the test)
80
+ def raise_side_channel_error!
81
+ error_write.close
82
+ err = error_read.read
83
+ error_read.close
84
+ begin
85
+ # ArgumentError from Marshal.load indicates no data, which we assume
86
+ # means no error in child process.
87
+ raise Marshal.load(err)
88
+ rescue ArgumentError
89
+ nil
90
+ end
91
+ end
92
+
93
+ ##
94
+ # Interprocess synchronization via a pipe. This allows us to control the
95
+ # state of the processes competing over the lock without relying on sleep.
96
+
97
+ let!(:sync_pipe) do
98
+ r,w = IO.pipe
99
+ w.sync = true
100
+ [r,w]
101
+ end
102
+ let(:sync_read) { sync_pipe[0] }
103
+ let(:sync_write) { sync_pipe[1] }
104
+
105
+ after do
106
+ sync_read.close unless sync_read.closed?
107
+ sync_write.close unless sync_write.closed?
108
+ end
109
+
110
+ # Wait on synchronization signal. If not received within the timeout, an
111
+ # error is sent via the error channel, and the process exits.
112
+ def sync_wait
113
+ if IO.select([sync_read], nil, nil, 20).nil?
114
+ # timeout reading from the sync pipe.
115
+ send_side_channel_error("Error syncing processes in run lock test (timeout)")
116
+ exit!(1)
117
+ else
118
+ sync_read.getc
119
+ end
120
+ end
121
+
122
+ # Sends a character in the sync pipe, which wakes ("unlocks") another
123
+ # process that is waiting on the sync signal
124
+ def sync_send
125
+ sync_write.putc("!")
126
+ sync_write.flush
127
+ end
128
+
129
+ ##
130
+ # IPC to record test results in a pipe. Tests can read pipe contents to
131
+ # check that operations occur in the expected order.
132
+
133
+ let!(:results_pipe) do
134
+ r,w = IO.pipe
135
+ w.sync = true
136
+ [r,w]
137
+ end
138
+ let(:results_read) { results_pipe[0] }
139
+ let(:results_write) { results_pipe[1] }
140
+
141
+ after do
142
+ results_read.close unless results_read.closed?
143
+ results_write.close unless results_write.closed?
144
+ end
145
+
146
+ # writes the message to the results pipe for later checking.
147
+ # note that nothing accounts for the pipe filling and waiting forever on a
148
+ # read or write call, so don't put too much data in.
149
+ def record(message)
150
+ results_write.puts(message)
151
+ results_write.flush
152
+ end
153
+
154
+ def results
155
+ results_write.flush
156
+ results_write.close
157
+ message = results_read.read
158
+ results_read.close
159
+ message
160
+ end
161
+
162
+ ##
163
+ # Run lock is the system under test
164
+ let!(:run_lock) { Chef::RunLock.new(:file_cache_path => file_cache_path, :lockfile => lockfile) }
165
+
166
+ it "creates the full path to the lockfile" do
167
+ lambda { run_lock.acquire }.should_not raise_error(Errno::ENOENT)
168
+ File.should exist(lockfile)
169
+ end
170
+
171
+ it "allows only one chef client run per lockfile" do
172
+ # First process, gets the lock and keeps it.
173
+ p1 = fork do
174
+ run_lock.acquire
175
+ record "p1 has lock"
176
+ # Wait until the other process is trying to get the lock:
177
+ sync_wait
178
+ # sleep a little bit to make process p2 wait on the lock
179
+ sleep 2
180
+ record "p1 releasing lock"
181
+ run_lock.release
182
+ exit!(0)
183
+ end
184
+
185
+ # Wait until p1 creates the lockfile
186
+ wait_on_lock
187
+
188
+ p2 = fork do
189
+ # inform process p1 that we're trying to get the lock
190
+ sync_send
191
+ run_lock.acquire
192
+ record "p2 has lock"
193
+ run_lock.release
194
+ exit!(0)
195
+ end
196
+
197
+ Process.waitpid2(p1)
198
+ Process.waitpid2(p2)
199
+
200
+ raise_side_channel_error!
201
+
202
+ expected=<<-E
203
+ p1 has lock
204
+ p1 releasing lock
205
+ p2 has lock
206
+ E
207
+ results.should == expected
208
+ end
209
+
210
+ it "clears the lock if the process dies unexpectedly" do
211
+ p1 = fork do
212
+ run_lock.acquire
213
+ record "p1 has lock"
214
+ sleep 60
215
+ record "p1 still has lock"
216
+ exit! 1
217
+ end
218
+
219
+ wait_on_lock
220
+ Process.kill(:KILL, p1)
221
+ Process.waitpid2(p1)
222
+
223
+
224
+ p2 = fork do
225
+ run_lock.acquire
226
+ record "p2 has lock"
227
+ run_lock.release
228
+ exit! 0
229
+ end
230
+
231
+ Process.waitpid2(p2)
232
+
233
+ results.should =~ /p2 has lock\Z/
234
+ end
235
+ end
236
+
237
+ end
238
+