chef 12.0.0.alpha.0 → 12.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (207) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +3 -5
  3. data/lib/chef/api_client.rb +1 -1
  4. data/lib/chef/application.rb +16 -8
  5. data/lib/chef/chef_fs/chef_fs_data_store.rb +1 -1
  6. data/lib/chef/chef_fs/command_line.rb +1 -1
  7. data/lib/chef/chef_fs/file_system.rb +1 -1
  8. data/lib/chef/chef_fs/file_system/acl_entry.rb +1 -1
  9. data/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb +3 -3
  10. data/lib/chef/chef_fs/file_system/cookbook_file.rb +2 -2
  11. data/lib/chef/chef_fs/file_system/rest_list_dir.rb +2 -2
  12. data/lib/chef/chef_fs/file_system/rest_list_entry.rb +4 -4
  13. data/lib/chef/config.rb +6 -5
  14. data/lib/chef/config_fetcher.rb +1 -1
  15. data/lib/chef/cookbook/cookbook_version_loader.rb +126 -43
  16. data/lib/chef/cookbook/metadata.rb +102 -53
  17. data/lib/chef/cookbook/syntax_check.rb +1 -1
  18. data/lib/chef/cookbook_loader.rb +62 -14
  19. data/lib/chef/cookbook_site_streaming_uploader.rb +12 -1
  20. data/lib/chef/cookbook_version.rb +13 -4
  21. data/lib/chef/data_bag.rb +28 -15
  22. data/lib/chef/data_bag_item.rb +5 -7
  23. data/lib/chef/digester.rb +5 -9
  24. data/lib/chef/dsl/recipe.rb +14 -0
  25. data/lib/chef/encrypted_data_bag_item.rb +1 -0
  26. data/lib/chef/encrypted_data_bag_item/assertions.rb +57 -0
  27. data/lib/chef/encrypted_data_bag_item/decryptor.rb +52 -28
  28. data/lib/chef/encrypted_data_bag_item/encrypted_data_bag_item_assertions.rb +37 -0
  29. data/lib/chef/encrypted_data_bag_item/encryption_failure.rb +22 -0
  30. data/lib/chef/encrypted_data_bag_item/encryptor.rb +79 -8
  31. data/lib/chef/environment.rb +1 -3
  32. data/lib/chef/exceptions.rb +18 -3
  33. data/lib/chef/formatters/base.rb +7 -0
  34. data/lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb +1 -1
  35. data/lib/chef/handler/json_file.rb +0 -1
  36. data/lib/chef/http/json_output.rb +1 -1
  37. data/lib/chef/json_compat.rb +24 -6
  38. data/lib/chef/knife/bootstrap.rb +2 -2
  39. data/lib/chef/knife/client_delete.rb +1 -1
  40. data/lib/chef/knife/cookbook_site_download.rb +1 -1
  41. data/lib/chef/knife/cookbook_site_list.rb +1 -1
  42. data/lib/chef/knife/cookbook_site_search.rb +1 -1
  43. data/lib/chef/knife/cookbook_site_share.rb +2 -2
  44. data/lib/chef/knife/cookbook_site_show.rb +3 -3
  45. data/lib/chef/knife/cookbook_site_unshare.rb +1 -1
  46. data/lib/chef/knife/core/node_editor.rb +2 -3
  47. data/lib/chef/knife/core/ui.rb +2 -2
  48. data/lib/chef/knife/deps.rb +2 -3
  49. data/lib/chef/mixin/shell_out.rb +1 -1
  50. data/lib/chef/mixin/windows_architecture_helper.rb +1 -0
  51. data/lib/chef/node.rb +1 -2
  52. data/lib/chef/platform/provider_mapping.rb +33 -6
  53. data/lib/chef/provider.rb +0 -2
  54. data/lib/chef/provider/cookbook_file/content.rb +1 -1
  55. data/lib/chef/provider/cron.rb +11 -0
  56. data/lib/chef/provider/deploy.rb +3 -2
  57. data/lib/chef/provider/deploy/revision.rb +2 -2
  58. data/lib/chef/provider/env.rb +1 -1
  59. data/lib/chef/provider/env/windows.rb +5 -9
  60. data/lib/chef/provider/file.rb +84 -33
  61. data/lib/chef/provider/git.rb +2 -1
  62. data/lib/chef/provider/group/aix.rb +17 -2
  63. data/lib/chef/provider/group/dscl.rb +27 -9
  64. data/lib/chef/provider/group/pw.rb +8 -1
  65. data/lib/chef/provider/http_request.rb +4 -4
  66. data/lib/chef/provider/log.rb +4 -14
  67. data/lib/chef/provider/mount/mount.rb +2 -2
  68. data/lib/chef/provider/package/ips.rb +17 -23
  69. data/lib/chef/provider/package/paludis.rb +2 -2
  70. data/lib/chef/provider/package/rpm.rb +2 -2
  71. data/lib/chef/provider/package/rubygems.rb +2 -0
  72. data/lib/chef/provider/package/yum.rb +2 -0
  73. data/lib/chef/provider/package/zypper.rb +1 -1
  74. data/lib/chef/provider/remote_file/cache_control_data.rb +2 -2
  75. data/lib/chef/provider/service/windows.rb +87 -21
  76. data/lib/chef/provider/user/aix.rb +95 -0
  77. data/lib/chef/provider/user/dscl.rb +544 -156
  78. data/lib/chef/provider/user/useradd.rb +1 -0
  79. data/lib/chef/providers.rb +1 -0
  80. data/lib/chef/resource.rb +4 -3
  81. data/lib/chef/resource/freebsd_package.rb +10 -2
  82. data/lib/chef/resource/paludis_package.rb +1 -0
  83. data/lib/chef/resource/scm.rb +10 -0
  84. data/lib/chef/resource/user.rb +27 -0
  85. data/lib/chef/resource/windows_service.rb +53 -0
  86. data/lib/chef/resource_collection.rb +23 -12
  87. data/lib/chef/resource_reporter.rb +10 -10
  88. data/lib/chef/resources.rb +1 -0
  89. data/lib/chef/role.rb +3 -3
  90. data/lib/chef/run_list.rb +6 -3
  91. data/lib/chef/user.rb +1 -1
  92. data/lib/chef/util/diff.rb +1 -2
  93. data/lib/chef/version.rb +1 -1
  94. data/lib/chef/version_constraint.rb +4 -4
  95. data/spec/data/cookbooks/angrybash/metadata.rb +2 -0
  96. data/spec/data/cookbooks/apache2/metadata.rb +2 -0
  97. data/spec/data/cookbooks/borken/metadata.rb +2 -0
  98. data/spec/data/cookbooks/ignorken/metadata.rb +2 -0
  99. data/spec/data/cookbooks/java/metadata.rb +2 -0
  100. data/spec/data/cookbooks/name-mismatch-versionnumber/README.md +4 -0
  101. data/spec/data/cookbooks/name-mismatch-versionnumber/metadata.rb +8 -0
  102. data/spec/data/cookbooks/name-mismatch-versionnumber/recipes/default.rb +8 -0
  103. data/spec/data/cookbooks/openldap/files/default/remotedir/not_a_template.erb +2 -0
  104. data/spec/data/cookbooks/preseed/metadata.rb +2 -0
  105. data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/README.md +4 -0
  106. data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/metadata.rb +13 -0
  107. data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/recipes/default.rb +8 -0
  108. data/spec/data/invalid-metadata-chef-repo/invalid-metadata/README.md +4 -0
  109. data/spec/data/invalid-metadata-chef-repo/invalid-metadata/metadata.rb +10 -0
  110. data/spec/data/invalid-metadata-chef-repo/invalid-metadata/recipes/default.rb +8 -0
  111. data/spec/data/mac_users/10.7-8.plist.xml +559 -0
  112. data/spec/data/mac_users/10.7-8.shadow.xml +11 -0
  113. data/spec/data/mac_users/10.7.plist.xml +559 -0
  114. data/spec/data/mac_users/10.7.shadow.xml +11 -0
  115. data/spec/data/mac_users/10.8.plist.xml +559 -0
  116. data/spec/data/mac_users/10.8.shadow.xml +21 -0
  117. data/spec/data/mac_users/10.9.plist.xml +560 -0
  118. data/spec/data/mac_users/10.9.shadow.xml +21 -0
  119. data/spec/data/object_loader/environments/test.json +2 -0
  120. data/spec/data/object_loader/environments/test_json_class.json +2 -0
  121. data/spec/data/object_loader/nodes/test.json +2 -0
  122. data/spec/data/object_loader/nodes/test_json_class.json +2 -0
  123. data/spec/data/object_loader/roles/test.json +2 -0
  124. data/spec/data/object_loader/roles/test_json_class.json +2 -0
  125. data/spec/functional/resource/bff_spec.rb +1 -1
  126. data/spec/functional/resource/cron_spec.rb +20 -1
  127. data/spec/functional/resource/env_spec.rb +137 -0
  128. data/spec/functional/resource/group_spec.rb +7 -5
  129. data/spec/functional/resource/remote_file_spec.rb +12 -1
  130. data/spec/functional/resource/user/dscl_spec.rb +198 -0
  131. data/spec/functional/resource/{user_spec.rb → user/useradd_spec.rb} +175 -37
  132. data/spec/integration/client/client_spec.rb +6 -4
  133. data/spec/integration/client/ipv6_spec.rb +16 -14
  134. data/spec/integration/knife/chef_fs_data_store_spec.rb +57 -46
  135. data/spec/integration/knife/chef_repo_path_spec.rb +105 -78
  136. data/spec/integration/knife/chef_repository_file_system_spec.rb +100 -84
  137. data/spec/integration/knife/chefignore_spec.rb +76 -46
  138. data/spec/integration/knife/common_options_spec.rb +16 -21
  139. data/spec/integration/knife/cookbook_api_ipv6_spec.rb +3 -3
  140. data/spec/integration/knife/delete_spec.rb +66 -46
  141. data/spec/integration/knife/deps_spec.rb +145 -94
  142. data/spec/integration/knife/diff_spec.rb +176 -110
  143. data/spec/integration/knife/download_spec.rb +229 -133
  144. data/spec/integration/knife/list_spec.rb +62 -54
  145. data/spec/integration/knife/raw_spec.rb +24 -9
  146. data/spec/integration/knife/redirection_spec.rb +2 -2
  147. data/spec/integration/knife/serve_spec.rb +2 -2
  148. data/spec/integration/knife/show_spec.rb +32 -26
  149. data/spec/integration/knife/upload_spec.rb +308 -165
  150. data/spec/integration/recipes/lwrp_inline_resources_spec.rb +10 -8
  151. data/spec/integration/solo/solo_spec.rb +22 -11
  152. data/spec/spec_helper.rb +3 -0
  153. data/spec/support/lib/chef/resource/zen_follower.rb +46 -0
  154. data/spec/support/platform_helpers.rb +12 -0
  155. data/spec/support/shared/functional/file_resource.rb +10 -0
  156. data/spec/support/shared/integration/chef_zero_support.rb +130 -0
  157. data/spec/support/shared/integration/integration_helper.rb +100 -98
  158. data/spec/support/shared/integration/knife_support.rb +0 -1
  159. data/spec/support/shared/unit/provider/file.rb +6 -4
  160. data/spec/support/shared/unit/provider/useradd_based_user_provider.rb +10 -1
  161. data/spec/unit/api_client/registration_spec.rb +83 -74
  162. data/spec/unit/application_spec.rb +32 -9
  163. data/spec/unit/cookbook/cookbook_version_loader_spec.rb +179 -0
  164. data/spec/unit/cookbook/metadata_spec.rb +190 -150
  165. data/spec/unit/cookbook/syntax_check_spec.rb +3 -2
  166. data/spec/unit/cookbook_loader_spec.rb +114 -53
  167. data/spec/unit/{cookbook_site_streaming_uploader.rb → cookbook_site_streaming_uploader_spec.rb} +21 -1
  168. data/spec/unit/data_bag_spec.rb +88 -13
  169. data/spec/unit/deprecation_spec.rb +1 -2
  170. data/spec/unit/encrypted_data_bag_item_spec.rb +145 -9
  171. data/spec/unit/environment_spec.rb +1 -1
  172. data/spec/unit/formatters/base_spec.rb +48 -0
  173. data/spec/unit/json_compat_spec.rb +48 -17
  174. data/spec/unit/knife/client_delete_spec.rb +4 -4
  175. data/spec/unit/knife/client_show_spec.rb +15 -5
  176. data/spec/unit/knife/cookbook_site_download_spec.rb +1 -1
  177. data/spec/unit/knife/cookbook_site_share_spec.rb +3 -3
  178. data/spec/unit/knife/data_bag_from_file_spec.rb +0 -2
  179. data/spec/unit/knife/data_bag_show_spec.rb +23 -14
  180. data/spec/unit/knife/node_show_spec.rb +32 -15
  181. data/spec/unit/knife/role_show_spec.rb +59 -0
  182. data/spec/unit/platform_spec.rb +10 -0
  183. data/spec/unit/provider/deploy_spec.rb +4 -0
  184. data/spec/unit/provider/env_spec.rb +19 -0
  185. data/spec/unit/provider/git_spec.rb +22 -2
  186. data/spec/unit/provider/group/dscl_spec.rb +38 -1
  187. data/spec/unit/provider/group/pw_spec.rb +2 -2
  188. data/spec/unit/provider/http_request_spec.rb +8 -8
  189. data/spec/unit/provider/log_spec.rb +33 -53
  190. data/spec/unit/provider/mount/mount_spec.rb +12 -3
  191. data/spec/unit/provider/package/ips_spec.rb +96 -63
  192. data/spec/unit/provider/package/paludis_spec.rb +5 -5
  193. data/spec/unit/provider/package/rpm_spec.rb +12 -0
  194. data/spec/unit/provider/package/zypper_spec.rb +28 -16
  195. data/spec/unit/provider/service/windows_spec.rb +77 -17
  196. data/spec/unit/provider/user/dscl_spec.rb +659 -264
  197. data/spec/unit/provider/user/useradd_spec.rb +1 -0
  198. data/spec/unit/recipe_spec.rb +41 -0
  199. data/spec/unit/resource/scm_spec.rb +11 -0
  200. data/spec/unit/resource/user_spec.rb +4 -0
  201. data/spec/unit/resource/windows_service_spec.rb +46 -0
  202. data/spec/unit/resource_collection_spec.rb +33 -0
  203. data/spec/unit/resource_reporter_spec.rb +48 -0
  204. data/spec/unit/resource_spec.rb +9 -2
  205. data/spec/unit/role_spec.rb +6 -0
  206. data/spec/unit/version_constraint_spec.rb +28 -0
  207. metadata +61 -4
@@ -63,7 +63,6 @@ module KnifeSupport
63
63
  Chef::Config[:verbosity] = ( DEBUG ? 2 : 0 )
64
64
  instance.config[:config_file] = File.join(CHEF_SPEC_DATA, "null_config.rb")
65
65
 
66
-
67
66
  # Configure chef with a (mostly) blank knife.rb
68
67
  # We set a global and then mutate it in our stub knife.rb so we can be
69
68
  # extra sure that we're not loading someone's real knife.rb and then
@@ -460,17 +460,19 @@ shared_examples_for Chef::Provider::File do
460
460
  context "when the file exists" do
461
461
  before { setup_normal_file }
462
462
  it "should not create the file" do
463
+ provider.load_current_resource
463
464
  provider.deployment_strategy.should_not_receive(:create).with(resource_path)
464
465
  provider.send(:do_create_file)
465
- provider.send(:file_created?).should == false
466
+ provider.send(:needs_creating?).should == false
466
467
  end
467
468
  end
468
469
  context "when the file does not exist" do
469
470
  before { setup_missing_file }
470
471
  it "should create the file" do
472
+ provider.load_current_resource
471
473
  provider.deployment_strategy.should_receive(:create).with(resource_path)
472
474
  provider.send(:do_create_file)
473
- provider.send(:file_created?).should == true
475
+ provider.send(:needs_creating?).should == true
474
476
  end
475
477
  end
476
478
  end
@@ -503,7 +505,7 @@ shared_examples_for Chef::Provider::File do
503
505
  provider.deployment_strategy.should_receive(:deploy).with(tempfile_path, normalized_path)
504
506
  end
505
507
  context "when the file was created" do
506
- before { provider.should_receive(:file_created?).at_least(:once).and_return(true) }
508
+ before { provider.should_receive(:needs_creating?).at_least(:once).and_return(true) }
507
509
  it "does not backup the file and does not produce a diff for reporting" do
508
510
  provider.should_not_receive(:do_backup)
509
511
  provider.send(:do_contents_changes)
@@ -511,7 +513,7 @@ shared_examples_for Chef::Provider::File do
511
513
  end
512
514
  end
513
515
  context "when the file was not created" do
514
- before { provider.should_receive(:file_created?).at_least(:once).and_return(false) }
516
+ before { provider.should_receive(:needs_creating?).at_least(:once).and_return(false) }
515
517
  it "backs up the file and produces a diff for reporting" do
516
518
  provider.should_receive(:do_backup)
517
519
  provider.send(:do_contents_changes)
@@ -33,6 +33,7 @@ shared_examples_for "a useradd-based user provider" do |supported_useradd_option
33
33
  @new_resource.password "abracadabra"
34
34
  @new_resource.system false
35
35
  @new_resource.manage_home false
36
+ @new_resource.force false
36
37
  @new_resource.non_unique false
37
38
  @current_resource = Chef::Resource::User.new("adam", @run_context)
38
39
  @current_resource.comment "Adam Jacob"
@@ -43,6 +44,7 @@ shared_examples_for "a useradd-based user provider" do |supported_useradd_option
43
44
  @current_resource.password "abracadabra"
44
45
  @current_resource.system false
45
46
  @current_resource.manage_home false
47
+ @current_resource.force false
46
48
  @current_resource.non_unique false
47
49
  @current_resource.supports({:manage_home => false, :non_unique => false})
48
50
  end
@@ -71,6 +73,7 @@ shared_examples_for "a useradd-based user provider" do |supported_useradd_option
71
73
  it "should set the option for #{attribute} if the new resources #{attribute} is not nil, without homedir management (using real attributes)" do
72
74
  @new_resource.stub(:manage_home).and_return(false)
73
75
  @new_resource.stub(:non_unique).and_return(false)
76
+ @new_resource.stub(:non_unique).and_return(false)
74
77
  @new_resource.stub(attribute).and_return("hola")
75
78
  provider.universal_options.should eql([option, 'hola'])
76
79
  end
@@ -255,6 +258,12 @@ shared_examples_for "a useradd-based user provider" do |supported_useradd_option
255
258
  provider.should_receive(:shell_out!).with("userdel", @new_resource.username).and_return(true)
256
259
  provider.remove_user
257
260
  end
261
+
262
+ it "should run userdel with the new resources user name and -f if force is true" do
263
+ @new_resource.force(true)
264
+ provider.should_receive(:shell_out!).with("userdel", "-f", @new_resource.username).and_return(true)
265
+ provider.remove_user
266
+ end
258
267
  end
259
268
 
260
269
  describe "when checking the lock" do
@@ -344,7 +353,7 @@ shared_examples_for "a useradd-based user provider" do |supported_useradd_option
344
353
  and_return(passwd_status)
345
354
  Chef::Config[:why_run] = true
346
355
  end
347
-
356
+
348
357
  it "should return false if the user does not exist" do
349
358
  provider.check_lock.should eql(false)
350
359
  end
@@ -38,11 +38,11 @@ describe Chef::ApiClient::Registration do
38
38
  let(:http_mock) { double("Chef::REST mock") }
39
39
 
40
40
  let(:expected_post_data) do
41
- { :name => client_name, :admin => false }
41
+ { :name => client_name, :admin => false, :public_key => generated_public_key.to_pem }
42
42
  end
43
43
 
44
44
  let(:expected_put_data) do
45
- { :name => client_name, :admin => false, :private_key => true }
45
+ { :name => client_name, :admin => false, :public_key => generated_public_key.to_pem }
46
46
  end
47
47
 
48
48
  let(:server_v10_response) do
@@ -61,9 +61,31 @@ describe Chef::ApiClient::Registration do
61
61
  let(:response_409) { Net::HTTPConflict.new("1.1", "409", "Conflict") }
62
62
  let(:exception_409) { Net::HTTPServerException.new("409 conflict", response_409) }
63
63
 
64
+ let(:generated_private_key_pem) { IO.read(File.expand_path('ssl/private_key.pem', CHEF_SPEC_DATA)) }
65
+ let(:generated_private_key) { OpenSSL::PKey::RSA.new(generated_private_key_pem) }
66
+ let(:generated_public_key) { generated_private_key.public_key }
67
+
68
+
69
+ let(:create_with_pkey_response) do
70
+ {
71
+ "uri" => "",
72
+ "public_key" => generated_public_key.to_pem
73
+ }
74
+ end
75
+
76
+ let(:update_with_pkey_response) do
77
+ {"name"=>client_name,
78
+ "admin"=>false,
79
+ "public_key"=> generated_public_key,
80
+ "validator"=>false,
81
+ "private_key"=>false,
82
+ "clientname"=>client_name}
83
+ end
84
+
64
85
  before do
65
86
  Chef::Config[:validation_client_name] = "test-validator"
66
87
  Chef::Config[:validation_key] = File.expand_path('ssl/private_key.pem', CHEF_SPEC_DATA)
88
+ OpenSSL::PKey::RSA.stub(:generate).with(2048).and_return(generated_private_key)
67
89
  end
68
90
 
69
91
  after do
@@ -81,74 +103,6 @@ describe Chef::ApiClient::Registration do
81
103
  registration.stub(:http_api).and_return(http_mock)
82
104
  end
83
105
 
84
- it "creates a new ApiClient on the server using the validator identity" do
85
- http_mock.should_receive(:post).
86
- with("clients", expected_post_data).
87
- and_return(server_v10_response)
88
- registration.create_or_update.should == server_v10_response
89
- registration.private_key.should == "--begin rsa key etc--"
90
- end
91
-
92
- context "and the client already exists on a Chef 10 server" do
93
- it "requests a new key from the server and saves it" do
94
- http_mock.should_receive(:post).with("clients", expected_post_data).
95
- and_raise(exception_409)
96
- http_mock.should_receive(:put).
97
- with("clients/#{client_name}", expected_put_data).
98
- and_return(server_v10_response)
99
- registration.create_or_update.should == server_v10_response
100
- registration.private_key.should == "--begin rsa key etc--"
101
- end
102
- end
103
-
104
- context "and the client already exists on a Chef 11 server" do
105
- it "requests a new key from the server and saves it" do
106
- http_mock.should_receive(:post).and_raise(exception_409)
107
- http_mock.should_receive(:put).
108
- with("clients/#{client_name}", expected_put_data).
109
- and_return(server_v11_response)
110
- registration.create_or_update.should == server_v11_response
111
- registration.private_key.should == "--begin rsa key etc--"
112
- end
113
- end
114
- end
115
-
116
- context "when local key generation is enabled", :nofocus do
117
- let(:generated_private_key_pem) { IO.read(File.expand_path('ssl/private_key.pem', CHEF_SPEC_DATA)) }
118
- let(:generated_private_key) { OpenSSL::PKey::RSA.new(generated_private_key_pem) }
119
- let(:generated_public_key) { generated_private_key.public_key }
120
-
121
- let(:expected_post_data) do
122
- { :name => client_name, :admin => false, :public_key => generated_public_key.to_pem }
123
- end
124
-
125
- let(:expected_put_data) do
126
- { :name => client_name, :admin => false, :public_key => generated_public_key.to_pem }
127
- end
128
-
129
- let(:create_with_pkey_response) do
130
- {
131
- "uri" => "",
132
- "public_key" => generated_public_key.to_pem
133
- }
134
- end
135
-
136
- let(:update_with_pkey_response) do
137
- {"name"=>client_name,
138
- "admin"=>false,
139
- "public_key"=> generated_public_key,
140
- "validator"=>false,
141
- "private_key"=>false,
142
- "clientname"=>client_name}
143
- end
144
-
145
-
146
- before do
147
- registration.stub(:http_api).and_return(http_mock)
148
- Chef::Config.local_key_generation = true
149
- OpenSSL::PKey::RSA.should_receive(:generate).with(2048).and_return(generated_private_key)
150
- end
151
-
152
106
  it "posts a locally generated public key to the server to create a client" do
153
107
  http_mock.should_receive(:post).
154
108
  with("clients", expected_post_data).
@@ -176,6 +130,63 @@ describe Chef::ApiClient::Registration do
176
130
  IO.read(key_location).should == generated_private_key_pem
177
131
  end
178
132
 
133
+ context "and the client already exists on a Chef 11 server" do
134
+ it "requests a new key from the server and saves it" do
135
+ http_mock.should_receive(:post).and_raise(exception_409)
136
+ http_mock.should_receive(:put).
137
+ with("clients/#{client_name}", expected_put_data).
138
+ and_return(update_with_pkey_response)
139
+ registration.create_or_update.should == update_with_pkey_response
140
+ registration.private_key.should == generated_private_key_pem
141
+ end
142
+ end
143
+
144
+ context "when local key generation is disabled" do
145
+
146
+ let(:expected_post_data) do
147
+ { :name => client_name, :admin => false }
148
+ end
149
+
150
+ let(:expected_put_data) do
151
+ { :name => client_name, :admin => false, :private_key => true }
152
+ end
153
+
154
+ before do
155
+ Chef::Config[:local_key_generation] = false
156
+ OpenSSL::PKey::RSA.should_not_receive(:generate)
157
+ end
158
+
159
+ it "creates a new ApiClient on the server using the validator identity" do
160
+ http_mock.should_receive(:post).
161
+ with("clients", expected_post_data).
162
+ and_return(server_v10_response)
163
+ registration.create_or_update.should == server_v10_response
164
+ registration.private_key.should == "--begin rsa key etc--"
165
+ end
166
+
167
+ context "and the client already exists on a Chef 11 server" do
168
+ it "requests a new key from the server and saves it" do
169
+ http_mock.should_receive(:post).and_raise(exception_409)
170
+ http_mock.should_receive(:put).
171
+ with("clients/#{client_name}", expected_put_data).
172
+ and_return(server_v11_response)
173
+ registration.create_or_update.should == server_v11_response
174
+ registration.private_key.should == "--begin rsa key etc--"
175
+ end
176
+ end
177
+
178
+ context "and the client already exists on a Chef 10 server" do
179
+ it "requests a new key from the server and saves it" do
180
+ http_mock.should_receive(:post).with("clients", expected_post_data).
181
+ and_raise(exception_409)
182
+ http_mock.should_receive(:put).
183
+ with("clients/#{client_name}", expected_put_data).
184
+ and_return(server_v10_response)
185
+ registration.create_or_update.should == server_v10_response
186
+ registration.private_key.should == "--begin rsa key etc--"
187
+ end
188
+ end
189
+ end
179
190
  end
180
191
 
181
192
  describe "when writing the private key to disk" do
@@ -209,7 +220,7 @@ describe Chef::ApiClient::Registration do
209
220
  it "creates the client on the server and writes the key" do
210
221
  http_mock.should_receive(:post).ordered.and_return(server_v10_response)
211
222
  registration.run
212
- IO.read(key_location).should == "--begin rsa key etc--"
223
+ IO.read(key_location).should == generated_private_key_pem
213
224
  end
214
225
 
215
226
  it "retries up to 5 times" do
@@ -224,7 +235,7 @@ describe Chef::ApiClient::Registration do
224
235
 
225
236
  http_mock.should_receive(:post).ordered.and_return(server_v10_response)
226
237
  registration.run
227
- IO.read(key_location).should == "--begin rsa key etc--"
238
+ IO.read(key_location).should == generated_private_key_pem
228
239
  end
229
240
 
230
241
  it "gives up retrying after the max attempts" do
@@ -239,5 +250,3 @@ describe Chef::ApiClient::Registration do
239
250
  end
240
251
 
241
252
  end
242
-
243
-
@@ -255,7 +255,12 @@ describe Chef::Application do
255
255
 
256
256
  it "should set ENV['http_proxy']" do
257
257
  @app.configure_proxy_environment_variables
258
- @env['http_proxy'].should == "http://#{address}:#{port}"
258
+ @env['http_proxy'].should == "#{scheme}://#{address}:#{port}"
259
+ end
260
+
261
+ it "should set ENV['HTTP_PROXY']" do
262
+ @app.configure_proxy_environment_variables
263
+ @env['HTTP_PROXY'].should == "#{scheme}://#{address}:#{port}"
259
264
  end
260
265
 
261
266
  describe "when Chef::Config[:http_proxy_user] is set" do
@@ -265,7 +270,8 @@ describe Chef::Application do
265
270
 
266
271
  it "should set ENV['http_proxy'] with the username" do
267
272
  @app.configure_proxy_environment_variables
268
- @env['http_proxy'].should == "http://username@#{address}:#{port}"
273
+ @env['http_proxy'].should == "#{scheme}://username@#{address}:#{port}"
274
+ @env['HTTP_PROXY'].should == "#{scheme}://username@#{address}:#{port}"
269
275
  end
270
276
 
271
277
  context "when :http_proxy_user contains '@' and/or ':'" do
@@ -275,7 +281,8 @@ describe Chef::Application do
275
281
 
276
282
  it "should set ENV['http_proxy'] with the escaped username" do
277
283
  @app.configure_proxy_environment_variables
278
- @env['http_proxy'].should == "http://my%3Ausern%40me@#{address}:#{port}"
284
+ @env['http_proxy'].should == "#{scheme}://my%3Ausern%40me@#{address}:#{port}"
285
+ @env['HTTP_PROXY'].should == "#{scheme}://my%3Ausern%40me@#{address}:#{port}"
279
286
  end
280
287
  end
281
288
 
@@ -286,7 +293,8 @@ describe Chef::Application do
286
293
 
287
294
  it "should set ENV['http_proxy'] with the password" do
288
295
  @app.configure_proxy_environment_variables
289
- @env['http_proxy'].should == "http://username:password@#{address}:#{port}"
296
+ @env['http_proxy'].should == "#{scheme}://username:password@#{address}:#{port}"
297
+ @env['HTTP_PROXY'].should == "#{scheme}://username:password@#{address}:#{port}"
290
298
  end
291
299
 
292
300
  context "when :http_proxy_pass contains '@' and/or ':'" do
@@ -296,7 +304,8 @@ describe Chef::Application do
296
304
 
297
305
  it "should set ENV['http_proxy'] with the escaped password" do
298
306
  @app.configure_proxy_environment_variables
299
- @env['http_proxy'].should == "http://username:%3AP%40ssword101@#{address}:#{port}"
307
+ @env['http_proxy'].should == "#{scheme}://username:%3AP%40ssword101@#{address}:#{port}"
308
+ @env['HTTP_PROXY'].should == "#{scheme}://username:%3AP%40ssword101@#{address}:#{port}"
300
309
  end
301
310
  end
302
311
  end
@@ -310,7 +319,8 @@ describe Chef::Application do
310
319
 
311
320
  it "should set ENV['http_proxy']" do
312
321
  @app.configure_proxy_environment_variables
313
- @env['http_proxy'].should == "http://#{address}:#{port}"
322
+ @env['http_proxy'].should == "#{scheme}://#{address}:#{port}"
323
+ @env['HTTP_PROXY'].should == "#{scheme}://#{address}:#{port}"
314
324
  end
315
325
  end
316
326
  end
@@ -338,30 +348,43 @@ describe Chef::Application do
338
348
 
339
349
  describe "when Chef::Config[:http_proxy] is set" do
340
350
  context "when given an FQDN" do
351
+ let(:scheme) { "http" }
352
+ let(:address) { "proxy.example.org" }
353
+ let(:port) { 8080 }
354
+ let(:http_proxy) { "#{scheme}://#{address}:#{port}" }
355
+
356
+ it_should_behave_like "setting ENV['http_proxy']"
357
+ end
358
+
359
+ context "when given an HTTPS URL" do
360
+ let(:scheme) { "https" }
341
361
  let(:address) { "proxy.example.org" }
342
362
  let(:port) { 8080 }
343
- let(:http_proxy) { "http://#{address}:#{port}" }
363
+ let(:http_proxy) { "#{scheme}://#{address}:#{port}" }
344
364
 
345
365
  it_should_behave_like "setting ENV['http_proxy']"
346
366
  end
347
367
 
348
368
  context "when given an IP" do
369
+ let(:scheme) { "http" }
349
370
  let(:address) { "127.0.0.1" }
350
371
  let(:port) { 22 }
351
- let(:http_proxy) { "http://#{address}:#{port}" }
372
+ let(:http_proxy) { "#{scheme}://#{address}:#{port}" }
352
373
 
353
374
  it_should_behave_like "setting ENV['http_proxy']"
354
375
  end
355
376
 
356
377
  context "when given an IPv6" do
378
+ let(:scheme) { "http" }
357
379
  let(:address) { "[2001:db8::1]" }
358
380
  let(:port) { 80 }
359
- let(:http_proxy) { "http://#{address}:#{port}" }
381
+ let(:http_proxy) { "#{scheme}://#{address}:#{port}" }
360
382
 
361
383
  it_should_behave_like "setting ENV['http_proxy']"
362
384
  end
363
385
 
364
386
  context "when given without including http://" do
387
+ let(:scheme) { "http" }
365
388
  let(:address) { "proxy.example.org" }
366
389
  let(:port) { 8181 }
367
390
  let(:http_proxy) { "#{address}:#{port}" }
@@ -0,0 +1,179 @@
1
+ #
2
+ # Author:: Daniel DeLeo (<dan@getchef.com>)
3
+ # Copyright:: Copyright (c) 2014 Chef Software, 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
+
19
+ require 'spec_helper'
20
+
21
+ describe Chef::Cookbook::CookbookVersionLoader do
22
+
23
+ describe "loading a cookbook" do
24
+
25
+ let(:chefignore) { nil }
26
+
27
+ let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "cookbooks/openldap") }
28
+
29
+ let(:cookbook_loader) { Chef::Cookbook::CookbookVersionLoader.new(cookbook_path, chefignore) }
30
+
31
+ let(:loaded_cookbook) do
32
+ cookbook_loader.load!
33
+ cookbook_loader.cookbook_version
34
+ end
35
+
36
+ def full_path(cookbook_relative_path)
37
+ File.join(cookbook_path, cookbook_relative_path)
38
+ end
39
+
40
+ it "loads attribute files of the cookbook" do
41
+ expect(loaded_cookbook.attribute_filenames).to include(full_path("/attributes/default.rb"))
42
+ expect(loaded_cookbook.attribute_filenames).to include(full_path("/attributes/smokey.rb"))
43
+ end
44
+
45
+ it "loads definition files" do
46
+ expect(loaded_cookbook.definition_filenames).to include(full_path("/definitions/client.rb"))
47
+ expect(loaded_cookbook.definition_filenames).to include(full_path("/definitions/server.rb"))
48
+ end
49
+
50
+ it "loads recipes" do
51
+ expect(loaded_cookbook.recipe_filenames).to include(full_path("/recipes/default.rb"))
52
+ expect(loaded_cookbook.recipe_filenames).to include(full_path("/recipes/gigantor.rb"))
53
+ expect(loaded_cookbook.recipe_filenames).to include(full_path("/recipes/one.rb"))
54
+ expect(loaded_cookbook.recipe_filenames).to include(full_path("/recipes/return.rb"))
55
+ end
56
+
57
+ it "loads static files in the files/ dir" do
58
+ expect(loaded_cookbook.file_filenames).to include(full_path("/files/default/remotedir/remotesubdir/remote_subdir_file1.txt"))
59
+ expect(loaded_cookbook.file_filenames).to include(full_path("/files/default/remotedir/remotesubdir/remote_subdir_file2.txt"))
60
+ end
61
+
62
+ it "loads files that start with a ." do
63
+ expect(loaded_cookbook.file_filenames).to include(full_path("/files/default/.dotfile"))
64
+ expect(loaded_cookbook.file_filenames).to include(full_path("/files/default/.ssh/id_rsa"))
65
+ expect(loaded_cookbook.file_filenames).to include(full_path("/files/default/remotedir/.a_dotdir/.a_dotfile_in_a_dotdir"))
66
+ end
67
+
68
+ it "should load the metadata for the cookbook" do
69
+ loaded_cookbook.metadata.name.to_s.should == "openldap"
70
+ loaded_cookbook.metadata.should be_a_kind_of(Chef::Cookbook::Metadata)
71
+ end
72
+
73
+ context "when a cookbook has ignored files" do
74
+
75
+ let(:chefignore) { Chef::Cookbook::Chefignore.new(File.join(CHEF_SPEC_DATA, "cookbooks")) }
76
+
77
+ let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "kitchen/openldap") }
78
+
79
+ it "skips ignored files" do
80
+ expect(loaded_cookbook.recipe_filenames).to include(full_path("recipes/gigantor.rb"))
81
+ expect(loaded_cookbook.recipe_filenames).to include(full_path("recipes/woot.rb"))
82
+ expect(loaded_cookbook.recipe_filenames).to_not include(full_path("recipes/ignoreme.rb"))
83
+ end
84
+
85
+ end
86
+
87
+ context "when the given path is not actually a cookbook" do
88
+
89
+ let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "cookbooks/NOTHING_HERE_FOLKS") }
90
+
91
+ it "raises an error when loading with #load!" do
92
+ expect { cookbook_loader.load! }.to raise_error(Chef::Exceptions::CookbookNotFoundInRepo)
93
+ end
94
+
95
+ it "skips the cookbook when called with #load" do
96
+ expect { cookbook_loader.load }.to_not raise_error
97
+ end
98
+
99
+ end
100
+
101
+ context "when a cookbook has a metadata name different than directory basename" do
102
+
103
+ let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "cookbooks/name-mismatch-versionnumber") }
104
+
105
+ it "prefers the metadata name to the directory basename" do
106
+ expect(loaded_cookbook.name).to eq(:"name-mismatch")
107
+ end
108
+
109
+ end
110
+
111
+ context "when a cookbook has a metadata file with a ruby error [CHEF-2923]" do
112
+
113
+ let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "invalid-metadata-chef-repo/invalid-metadata") }
114
+
115
+ it "raises an error when loading with #load!" do
116
+ expect { cookbook_loader.load! }.to raise_error("THIS METADATA HAS A BUG")
117
+ end
118
+
119
+ it "raises an error when called with #load" do
120
+ expect { cookbook_loader.load }.to raise_error("THIS METADATA HAS A BUG")
121
+ end
122
+
123
+ it "doesn't raise an error when determining the cookbook name" do
124
+ expect { cookbook_loader.cookbook_name }.to_not raise_error
125
+ end
126
+
127
+ it "doesn't raise an error when metadata is first generated" do
128
+ expect { cookbook_loader.metadata }.to_not raise_error
129
+ end
130
+
131
+ it "sets an error flag containing error information" do
132
+ cookbook_loader.metadata
133
+ expect(cookbook_loader.metadata_error).to be_a(StandardError)
134
+ expect(cookbook_loader.metadata_error.message).to eq("THIS METADATA HAS A BUG")
135
+ end
136
+
137
+ end
138
+
139
+ context "when a cookbook has a metadata file with invalid metadata" do
140
+
141
+ let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "incomplete-metadata-chef-repo/incomplete-metadata") }
142
+
143
+ let(:error_message) do
144
+ "Cookbook loaded at path(s) [#{cookbook_path}] has invalid metadata: The `name' attribute is required in cookbook metadata"
145
+ end
146
+
147
+ it "raises an error when loading with #load!" do
148
+ expect { cookbook_loader.load! }.to raise_error(Chef::Exceptions::MetadataNotValid, error_message)
149
+ end
150
+
151
+ it "raises an error when called with #load" do
152
+ expect { cookbook_loader.load }.to raise_error(Chef::Exceptions::MetadataNotValid, error_message)
153
+ end
154
+
155
+ it "uses the inferred cookbook name [CHEF-2923]" do
156
+ # This behavior is intended to support the CHEF-2923 feature where
157
+ # invalid metadata doesn't prevent you from uploading other cookbooks.
158
+ #
159
+ # The metadata is the definitive source of the cookbook name, but if
160
+ # the metadata is incomplete/invalid, we can't read the name from it.
161
+ #
162
+ # The CookbookLoader stores CookbookVersionLoaders in a Hash with
163
+ # cookbook names as the keys, and finds the loader in this Hash to call
164
+ # #load on it when the user runs a command like `knife cookbook upload specific-cookbook`
165
+ #
166
+ # Most of the time this will work, but if the user tries to upload a
167
+ # specific cookbook by name, has customized that cookbook's name (so it
168
+ # doesn't match the inferred name), and that metadata file has a syntax
169
+ # error, we might report a "cookbook not found" error instead of the
170
+ # metadata syntax error that is the actual cause.
171
+ expect(cookbook_loader.cookbook_name).to eq(:"incomplete-metadata")
172
+ end
173
+
174
+ end
175
+
176
+ end
177
+
178
+ end
179
+