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.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +3 -5
- data/lib/chef/api_client.rb +1 -1
- data/lib/chef/application.rb +16 -8
- data/lib/chef/chef_fs/chef_fs_data_store.rb +1 -1
- data/lib/chef/chef_fs/command_line.rb +1 -1
- data/lib/chef/chef_fs/file_system.rb +1 -1
- data/lib/chef/chef_fs/file_system/acl_entry.rb +1 -1
- data/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb +3 -3
- data/lib/chef/chef_fs/file_system/cookbook_file.rb +2 -2
- data/lib/chef/chef_fs/file_system/rest_list_dir.rb +2 -2
- data/lib/chef/chef_fs/file_system/rest_list_entry.rb +4 -4
- data/lib/chef/config.rb +6 -5
- data/lib/chef/config_fetcher.rb +1 -1
- data/lib/chef/cookbook/cookbook_version_loader.rb +126 -43
- data/lib/chef/cookbook/metadata.rb +102 -53
- data/lib/chef/cookbook/syntax_check.rb +1 -1
- data/lib/chef/cookbook_loader.rb +62 -14
- data/lib/chef/cookbook_site_streaming_uploader.rb +12 -1
- data/lib/chef/cookbook_version.rb +13 -4
- data/lib/chef/data_bag.rb +28 -15
- data/lib/chef/data_bag_item.rb +5 -7
- data/lib/chef/digester.rb +5 -9
- data/lib/chef/dsl/recipe.rb +14 -0
- data/lib/chef/encrypted_data_bag_item.rb +1 -0
- data/lib/chef/encrypted_data_bag_item/assertions.rb +57 -0
- data/lib/chef/encrypted_data_bag_item/decryptor.rb +52 -28
- data/lib/chef/encrypted_data_bag_item/encrypted_data_bag_item_assertions.rb +37 -0
- data/lib/chef/encrypted_data_bag_item/encryption_failure.rb +22 -0
- data/lib/chef/encrypted_data_bag_item/encryptor.rb +79 -8
- data/lib/chef/environment.rb +1 -3
- data/lib/chef/exceptions.rb +18 -3
- data/lib/chef/formatters/base.rb +7 -0
- data/lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb +1 -1
- data/lib/chef/handler/json_file.rb +0 -1
- data/lib/chef/http/json_output.rb +1 -1
- data/lib/chef/json_compat.rb +24 -6
- data/lib/chef/knife/bootstrap.rb +2 -2
- data/lib/chef/knife/client_delete.rb +1 -1
- data/lib/chef/knife/cookbook_site_download.rb +1 -1
- data/lib/chef/knife/cookbook_site_list.rb +1 -1
- data/lib/chef/knife/cookbook_site_search.rb +1 -1
- data/lib/chef/knife/cookbook_site_share.rb +2 -2
- data/lib/chef/knife/cookbook_site_show.rb +3 -3
- data/lib/chef/knife/cookbook_site_unshare.rb +1 -1
- data/lib/chef/knife/core/node_editor.rb +2 -3
- data/lib/chef/knife/core/ui.rb +2 -2
- data/lib/chef/knife/deps.rb +2 -3
- data/lib/chef/mixin/shell_out.rb +1 -1
- data/lib/chef/mixin/windows_architecture_helper.rb +1 -0
- data/lib/chef/node.rb +1 -2
- data/lib/chef/platform/provider_mapping.rb +33 -6
- data/lib/chef/provider.rb +0 -2
- data/lib/chef/provider/cookbook_file/content.rb +1 -1
- data/lib/chef/provider/cron.rb +11 -0
- data/lib/chef/provider/deploy.rb +3 -2
- data/lib/chef/provider/deploy/revision.rb +2 -2
- data/lib/chef/provider/env.rb +1 -1
- data/lib/chef/provider/env/windows.rb +5 -9
- data/lib/chef/provider/file.rb +84 -33
- data/lib/chef/provider/git.rb +2 -1
- data/lib/chef/provider/group/aix.rb +17 -2
- data/lib/chef/provider/group/dscl.rb +27 -9
- data/lib/chef/provider/group/pw.rb +8 -1
- data/lib/chef/provider/http_request.rb +4 -4
- data/lib/chef/provider/log.rb +4 -14
- data/lib/chef/provider/mount/mount.rb +2 -2
- data/lib/chef/provider/package/ips.rb +17 -23
- data/lib/chef/provider/package/paludis.rb +2 -2
- data/lib/chef/provider/package/rpm.rb +2 -2
- data/lib/chef/provider/package/rubygems.rb +2 -0
- data/lib/chef/provider/package/yum.rb +2 -0
- data/lib/chef/provider/package/zypper.rb +1 -1
- data/lib/chef/provider/remote_file/cache_control_data.rb +2 -2
- data/lib/chef/provider/service/windows.rb +87 -21
- data/lib/chef/provider/user/aix.rb +95 -0
- data/lib/chef/provider/user/dscl.rb +544 -156
- data/lib/chef/provider/user/useradd.rb +1 -0
- data/lib/chef/providers.rb +1 -0
- data/lib/chef/resource.rb +4 -3
- data/lib/chef/resource/freebsd_package.rb +10 -2
- data/lib/chef/resource/paludis_package.rb +1 -0
- data/lib/chef/resource/scm.rb +10 -0
- data/lib/chef/resource/user.rb +27 -0
- data/lib/chef/resource/windows_service.rb +53 -0
- data/lib/chef/resource_collection.rb +23 -12
- data/lib/chef/resource_reporter.rb +10 -10
- data/lib/chef/resources.rb +1 -0
- data/lib/chef/role.rb +3 -3
- data/lib/chef/run_list.rb +6 -3
- data/lib/chef/user.rb +1 -1
- data/lib/chef/util/diff.rb +1 -2
- data/lib/chef/version.rb +1 -1
- data/lib/chef/version_constraint.rb +4 -4
- data/spec/data/cookbooks/angrybash/metadata.rb +2 -0
- data/spec/data/cookbooks/apache2/metadata.rb +2 -0
- data/spec/data/cookbooks/borken/metadata.rb +2 -0
- data/spec/data/cookbooks/ignorken/metadata.rb +2 -0
- data/spec/data/cookbooks/java/metadata.rb +2 -0
- data/spec/data/cookbooks/name-mismatch-versionnumber/README.md +4 -0
- data/spec/data/cookbooks/name-mismatch-versionnumber/metadata.rb +8 -0
- data/spec/data/cookbooks/name-mismatch-versionnumber/recipes/default.rb +8 -0
- data/spec/data/cookbooks/openldap/files/default/remotedir/not_a_template.erb +2 -0
- data/spec/data/cookbooks/preseed/metadata.rb +2 -0
- data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/README.md +4 -0
- data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/metadata.rb +13 -0
- data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/recipes/default.rb +8 -0
- data/spec/data/invalid-metadata-chef-repo/invalid-metadata/README.md +4 -0
- data/spec/data/invalid-metadata-chef-repo/invalid-metadata/metadata.rb +10 -0
- data/spec/data/invalid-metadata-chef-repo/invalid-metadata/recipes/default.rb +8 -0
- data/spec/data/mac_users/10.7-8.plist.xml +559 -0
- data/spec/data/mac_users/10.7-8.shadow.xml +11 -0
- data/spec/data/mac_users/10.7.plist.xml +559 -0
- data/spec/data/mac_users/10.7.shadow.xml +11 -0
- data/spec/data/mac_users/10.8.plist.xml +559 -0
- data/spec/data/mac_users/10.8.shadow.xml +21 -0
- data/spec/data/mac_users/10.9.plist.xml +560 -0
- data/spec/data/mac_users/10.9.shadow.xml +21 -0
- data/spec/data/object_loader/environments/test.json +2 -0
- data/spec/data/object_loader/environments/test_json_class.json +2 -0
- data/spec/data/object_loader/nodes/test.json +2 -0
- data/spec/data/object_loader/nodes/test_json_class.json +2 -0
- data/spec/data/object_loader/roles/test.json +2 -0
- data/spec/data/object_loader/roles/test_json_class.json +2 -0
- data/spec/functional/resource/bff_spec.rb +1 -1
- data/spec/functional/resource/cron_spec.rb +20 -1
- data/spec/functional/resource/env_spec.rb +137 -0
- data/spec/functional/resource/group_spec.rb +7 -5
- data/spec/functional/resource/remote_file_spec.rb +12 -1
- data/spec/functional/resource/user/dscl_spec.rb +198 -0
- data/spec/functional/resource/{user_spec.rb → user/useradd_spec.rb} +175 -37
- data/spec/integration/client/client_spec.rb +6 -4
- data/spec/integration/client/ipv6_spec.rb +16 -14
- data/spec/integration/knife/chef_fs_data_store_spec.rb +57 -46
- data/spec/integration/knife/chef_repo_path_spec.rb +105 -78
- data/spec/integration/knife/chef_repository_file_system_spec.rb +100 -84
- data/spec/integration/knife/chefignore_spec.rb +76 -46
- data/spec/integration/knife/common_options_spec.rb +16 -21
- data/spec/integration/knife/cookbook_api_ipv6_spec.rb +3 -3
- data/spec/integration/knife/delete_spec.rb +66 -46
- data/spec/integration/knife/deps_spec.rb +145 -94
- data/spec/integration/knife/diff_spec.rb +176 -110
- data/spec/integration/knife/download_spec.rb +229 -133
- data/spec/integration/knife/list_spec.rb +62 -54
- data/spec/integration/knife/raw_spec.rb +24 -9
- data/spec/integration/knife/redirection_spec.rb +2 -2
- data/spec/integration/knife/serve_spec.rb +2 -2
- data/spec/integration/knife/show_spec.rb +32 -26
- data/spec/integration/knife/upload_spec.rb +308 -165
- data/spec/integration/recipes/lwrp_inline_resources_spec.rb +10 -8
- data/spec/integration/solo/solo_spec.rb +22 -11
- data/spec/spec_helper.rb +3 -0
- data/spec/support/lib/chef/resource/zen_follower.rb +46 -0
- data/spec/support/platform_helpers.rb +12 -0
- data/spec/support/shared/functional/file_resource.rb +10 -0
- data/spec/support/shared/integration/chef_zero_support.rb +130 -0
- data/spec/support/shared/integration/integration_helper.rb +100 -98
- data/spec/support/shared/integration/knife_support.rb +0 -1
- data/spec/support/shared/unit/provider/file.rb +6 -4
- data/spec/support/shared/unit/provider/useradd_based_user_provider.rb +10 -1
- data/spec/unit/api_client/registration_spec.rb +83 -74
- data/spec/unit/application_spec.rb +32 -9
- data/spec/unit/cookbook/cookbook_version_loader_spec.rb +179 -0
- data/spec/unit/cookbook/metadata_spec.rb +190 -150
- data/spec/unit/cookbook/syntax_check_spec.rb +3 -2
- data/spec/unit/cookbook_loader_spec.rb +114 -53
- data/spec/unit/{cookbook_site_streaming_uploader.rb → cookbook_site_streaming_uploader_spec.rb} +21 -1
- data/spec/unit/data_bag_spec.rb +88 -13
- data/spec/unit/deprecation_spec.rb +1 -2
- data/spec/unit/encrypted_data_bag_item_spec.rb +145 -9
- data/spec/unit/environment_spec.rb +1 -1
- data/spec/unit/formatters/base_spec.rb +48 -0
- data/spec/unit/json_compat_spec.rb +48 -17
- data/spec/unit/knife/client_delete_spec.rb +4 -4
- data/spec/unit/knife/client_show_spec.rb +15 -5
- data/spec/unit/knife/cookbook_site_download_spec.rb +1 -1
- data/spec/unit/knife/cookbook_site_share_spec.rb +3 -3
- data/spec/unit/knife/data_bag_from_file_spec.rb +0 -2
- data/spec/unit/knife/data_bag_show_spec.rb +23 -14
- data/spec/unit/knife/node_show_spec.rb +32 -15
- data/spec/unit/knife/role_show_spec.rb +59 -0
- data/spec/unit/platform_spec.rb +10 -0
- data/spec/unit/provider/deploy_spec.rb +4 -0
- data/spec/unit/provider/env_spec.rb +19 -0
- data/spec/unit/provider/git_spec.rb +22 -2
- data/spec/unit/provider/group/dscl_spec.rb +38 -1
- data/spec/unit/provider/group/pw_spec.rb +2 -2
- data/spec/unit/provider/http_request_spec.rb +8 -8
- data/spec/unit/provider/log_spec.rb +33 -53
- data/spec/unit/provider/mount/mount_spec.rb +12 -3
- data/spec/unit/provider/package/ips_spec.rb +96 -63
- data/spec/unit/provider/package/paludis_spec.rb +5 -5
- data/spec/unit/provider/package/rpm_spec.rb +12 -0
- data/spec/unit/provider/package/zypper_spec.rb +28 -16
- data/spec/unit/provider/service/windows_spec.rb +77 -17
- data/spec/unit/provider/user/dscl_spec.rb +659 -264
- data/spec/unit/provider/user/useradd_spec.rb +1 -0
- data/spec/unit/recipe_spec.rb +41 -0
- data/spec/unit/resource/scm_spec.rb +11 -0
- data/spec/unit/resource/user_spec.rb +4 -0
- data/spec/unit/resource/windows_service_spec.rb +46 -0
- data/spec/unit/resource_collection_spec.rb +33 -0
- data/spec/unit/resource_reporter_spec.rb +48 -0
- data/spec/unit/resource_spec.rb +9 -2
- data/spec/unit/role_spec.rb +6 -0
- data/spec/unit/version_constraint_spec.rb +28 -0
- 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(:
|
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(:
|
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(:
|
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(:
|
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, :
|
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 ==
|
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 ==
|
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 == "
|
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 == "
|
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 == "
|
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 == "
|
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 == "
|
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 == "
|
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) { "
|
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) { "
|
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) { "
|
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
|
+
|