chef 11.16.4-x86-mingw32 → 11.18.0-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +2 -2
  3. data/lib/chef/api_client.rb +1 -1
  4. data/lib/chef/chef_fs/chef_fs_data_store.rb +3 -2
  5. data/lib/chef/chef_fs/command_line.rb +3 -2
  6. data/lib/chef/chef_fs/data_handler/group_data_handler.rb +5 -1
  7. data/lib/chef/chef_fs/file_system/acl_entry.rb +2 -1
  8. data/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb +2 -1
  9. data/lib/chef/chef_fs/file_system/rest_list_dir.rb +3 -2
  10. data/lib/chef/chef_fs/file_system/rest_list_entry.rb +5 -4
  11. data/lib/chef/config_fetcher.rb +1 -1
  12. data/lib/chef/cookbook/cookbook_version_loader.rb +4 -4
  13. data/lib/chef/cookbook/metadata.rb +1 -1
  14. data/lib/chef/cookbook_version.rb +2 -2
  15. data/lib/chef/data_bag.rb +1 -1
  16. data/lib/chef/data_bag_item.rb +1 -1
  17. data/lib/chef/encrypted_data_bag_item/decryptor.rb +3 -3
  18. data/lib/chef/environment.rb +1 -1
  19. data/lib/chef/exceptions.rb +19 -2
  20. data/lib/chef/json_compat.rb +64 -45
  21. data/lib/chef/knife/bootstrap.rb +2 -2
  22. data/lib/chef/knife/bootstrap/archlinux-gems.erb +2 -2
  23. data/lib/chef/knife/bootstrap/centos5-gems.erb +2 -2
  24. data/lib/chef/knife/bootstrap/chef-aix.erb +2 -2
  25. data/lib/chef/knife/bootstrap/chef-full.erb +2 -2
  26. data/lib/chef/knife/bootstrap/fedora13-gems.erb +2 -2
  27. data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +2 -2
  28. data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +2 -2
  29. data/lib/chef/knife/bootstrap/ubuntu12.04-gems.erb +2 -2
  30. data/lib/chef/knife/cookbook_site_download.rb +1 -1
  31. data/lib/chef/knife/cookbook_site_install.rb +34 -10
  32. data/lib/chef/knife/cookbook_site_list.rb +1 -1
  33. data/lib/chef/knife/cookbook_site_search.rb +1 -1
  34. data/lib/chef/knife/cookbook_site_share.rb +2 -2
  35. data/lib/chef/knife/cookbook_site_show.rb +3 -3
  36. data/lib/chef/knife/cookbook_site_unshare.rb +1 -1
  37. data/lib/chef/knife/core/subcommand_loader.rb +24 -0
  38. data/lib/chef/knife/deps.rb +3 -2
  39. data/lib/chef/node.rb +1 -1
  40. data/lib/chef/provider/deploy/revision.rb +1 -1
  41. data/lib/chef/provider/dsc_script.rb +32 -5
  42. data/lib/chef/provider/env.rb +25 -10
  43. data/lib/chef/provider/remote_file/cache_control_data.rb +1 -1
  44. data/lib/chef/resource.rb +1 -1
  45. data/lib/chef/resource/dsc_script.rb +2 -16
  46. data/lib/chef/resource_collection.rb +1 -1
  47. data/lib/chef/resource_reporter.rb +3 -3
  48. data/lib/chef/role.rb +1 -1
  49. data/lib/chef/run_list.rb +1 -1
  50. data/lib/chef/user.rb +1 -1
  51. data/lib/chef/util/dsc/local_configuration_manager.rb +15 -11
  52. data/lib/chef/util/powershell/cmdlet_result.rb +2 -2
  53. data/lib/chef/version.rb +1 -2
  54. data/spec/data/bootstrap/test-hints.erb +1 -1
  55. data/spec/data/bootstrap/test.erb +1 -1
  56. data/spec/functional/knife/cookbook_delete_spec.rb +3 -3
  57. data/spec/functional/knife/exec_spec.rb +1 -1
  58. data/spec/functional/resource/dsc_script_spec.rb +92 -47
  59. data/spec/functional/resource/env_spec.rb +3 -4
  60. data/spec/functional/util/powershell/cmdlet_spec.rb +1 -2
  61. data/spec/integration/knife/chef_fs_data_store_spec.rb +1 -1
  62. data/spec/integration/knife/chef_repo_path_spec.rb +6 -1
  63. data/spec/integration/knife/chef_repository_file_system_spec.rb +1 -1
  64. data/spec/integration/knife/chefignore_spec.rb +1 -1
  65. data/spec/integration/knife/common_options_spec.rb +1 -1
  66. data/spec/integration/knife/cookbook_api_ipv6_spec.rb +1 -1
  67. data/spec/integration/knife/delete_spec.rb +1 -1
  68. data/spec/integration/knife/deps_spec.rb +1 -1
  69. data/spec/integration/knife/diff_spec.rb +3 -3
  70. data/spec/integration/knife/download_spec.rb +3 -3
  71. data/spec/integration/knife/list_spec.rb +1 -1
  72. data/spec/integration/knife/raw_spec.rb +11 -1
  73. data/spec/integration/knife/redirection_spec.rb +1 -1
  74. data/spec/integration/knife/serve_spec.rb +1 -1
  75. data/spec/integration/knife/show_spec.rb +1 -1
  76. data/spec/integration/knife/upload_spec.rb +9 -9
  77. data/spec/spec_helper.rb +6 -0
  78. data/spec/support/shared/integration/integration_helper.rb +1 -2
  79. data/spec/support/shared/shared_examples.rb +10 -0
  80. data/spec/tiny_server.rb +2 -1
  81. data/spec/unit/api_client_spec.rb +3 -3
  82. data/spec/unit/chef_fs/data_handler/group_handler_spec.rb +63 -0
  83. data/spec/unit/config_fetcher_spec.rb +1 -1
  84. data/spec/unit/cookbook/metadata_spec.rb +7 -3
  85. data/spec/unit/cookbook_loader_spec.rb +1 -1
  86. data/spec/unit/cookbook_version_spec.rb +4 -0
  87. data/spec/unit/data_bag_item_spec.rb +5 -1
  88. data/spec/unit/data_bag_spec.rb +5 -1
  89. data/spec/unit/deprecation_spec.rb +1 -1
  90. data/spec/unit/encrypted_data_bag_item_spec.rb +14 -7
  91. data/spec/unit/environment_spec.rb +7 -3
  92. data/spec/unit/exceptions_spec.rb +6 -0
  93. data/spec/unit/json_compat_spec.rb +58 -17
  94. data/spec/unit/knife/cookbook_metadata_from_file_spec.rb +0 -1
  95. data/spec/unit/knife/cookbook_site_download_spec.rb +2 -1
  96. data/spec/unit/knife/cookbook_site_install_spec.rb +161 -116
  97. data/spec/unit/knife/cookbook_site_share_spec.rb +6 -6
  98. data/spec/unit/knife/core/bootstrap_context_spec.rb +2 -2
  99. data/spec/unit/knife/core/subcommand_loader_spec.rb +66 -1
  100. data/spec/unit/knife/data_bag_from_file_spec.rb +1 -2
  101. data/spec/unit/node_spec.rb +4 -0
  102. data/spec/unit/provider/dsc_script_spec.rb +134 -105
  103. data/spec/unit/provider/env/windows_spec.rb +2 -2
  104. data/spec/unit/provider/env_spec.rb +76 -11
  105. data/spec/unit/provider/remote_file/cache_control_data_spec.rb +1 -1
  106. data/spec/unit/resource/dsc_script_spec.rb +0 -29
  107. data/spec/unit/resource_collection_spec.rb +5 -1
  108. data/spec/unit/resource_reporter_spec.rb +3 -3
  109. data/spec/unit/resource_spec.rb +5 -1
  110. data/spec/unit/role_spec.rb +4 -0
  111. data/spec/unit/run_list_spec.rb +5 -1
  112. data/spec/unit/user_spec.rb +5 -1
  113. data/spec/unit/util/dsc/local_configuration_manager_spec.rb +15 -10
  114. metadata +11 -9
@@ -108,16 +108,16 @@ describe Chef::Knife::CookbookSiteShare do
108
108
  File.stub(:open).and_return(true)
109
109
  end
110
110
 
111
- it 'should post the cookbook to "http://cookbooks.opscode.com"' do
112
- response_text = {:uri => 'http://cookbooks.opscode.com/cookbooks/cookbook_name'}.to_json
111
+ it 'should post the cookbook to "https://supermarket.getchef.com"' do
112
+ response_text = {:uri => 'https://supermarket.getchef.com/cookbooks/cookbook_name'}.to_json
113
113
  @upload_response.stub(:body).and_return(response_text)
114
114
  @upload_response.stub(:code).and_return(201)
115
- Chef::CookbookSiteStreamingUploader.should_receive(:post).with(/cookbooks\.opscode\.com/, anything(), anything(), anything())
115
+ Chef::CookbookSiteStreamingUploader.should_receive(:post).with(/supermarket\.getchef\.com/, anything(), anything(), anything())
116
116
  @knife.run
117
117
  end
118
118
 
119
119
  it 'should alert the user when a version already exists' do
120
- response_text = {:error_messages => ['Version already exists']}.to_json
120
+ response_text = Chef::JSONCompat.to_json({:error_messages => ['Version already exists']})
121
121
  @upload_response.stub(:body).and_return(response_text)
122
122
  @upload_response.stub(:code).and_return(409)
123
123
  lambda { @knife.run }.should raise_error(SystemExit)
@@ -125,7 +125,7 @@ describe Chef::Knife::CookbookSiteShare do
125
125
  end
126
126
 
127
127
  it 'should pass any errors on to the user' do
128
- response_text = {:error_messages => ["You're holding it wrong"]}.to_json
128
+ response_text = Chef::JSONCompat.to_json({:error_messages => ["You're holding it wrong"]})
129
129
  @upload_response.stub(:body).and_return(response_text)
130
130
  @upload_response.stub(:code).and_return(403)
131
131
  lambda { @knife.run }.should raise_error(SystemExit)
@@ -133,7 +133,7 @@ describe Chef::Knife::CookbookSiteShare do
133
133
  end
134
134
 
135
135
  it 'should print the body if no errors are exposed on failure' do
136
- response_text = {:system_error => "Your call was dropped", :reason => "There's a map for that"}.to_json
136
+ response_text = Chef::JSONCompat.to_json({:system_error => "Your call was dropped", :reason => "There's a map for that"})
137
137
  @upload_response.stub(:body).and_return(response_text)
138
138
  @upload_response.stub(:code).and_return(500)
139
139
  @knife.ui.should_receive(:error).with(/#{Regexp.escape(response_text)}/)#.ordered
@@ -116,13 +116,13 @@ EXPECTED
116
116
  describe "when JSON attributes are given" do
117
117
  let(:config) { {:first_boot_attributes => {:baz => :quux}} }
118
118
  it "adds the attributes to first_boot" do
119
- bootstrap_context.first_boot.to_json.should eq({:baz => :quux, :run_list => run_list}.to_json)
119
+ Chef::JSONCompat.to_json(bootstrap_context.first_boot).should eq(Chef::JSONCompat.to_json({:baz => :quux, :run_list => run_list}))
120
120
  end
121
121
  end
122
122
 
123
123
  describe "when JSON attributes are NOT given" do
124
124
  it "sets first_boot equal to run_list" do
125
- bootstrap_context.first_boot.to_json.should eq({:run_list => run_list}.to_json)
125
+ Chef::JSONCompat.to_json(bootstrap_context.first_boot).should eq(Chef::JSONCompat.to_json({:run_list => run_list}))
126
126
  end
127
127
  end
128
128
 
@@ -73,7 +73,72 @@ describe Chef::Knife::SubcommandLoader do
73
73
  @loader.site_subcommands.should include(expected_command)
74
74
  end
75
75
 
76
- describe "finding 3rd party plugins" do
76
+ # https://github.com/opscode/chef-dk/issues/227
77
+ #
78
+ # `knife` in ChefDK isn't from a gem install, it's directly run from a clone
79
+ # of the source, but there can be one or more versions of chef also installed
80
+ # as a gem. If the gem install contains a command that doesn't exist in the
81
+ # source tree of the "primary" chef install, it can be loaded and cause an
82
+ # error. We also want to ensure that we only load builtin commands from the
83
+ # "primary" chef install.
84
+ context "when a different version of chef is also installed as a gem" do
85
+
86
+ let(:all_found_commands) do
87
+ [
88
+ "/opt/chefdk/embedded/apps/chef/lib/chef/knife/bootstrap.rb",
89
+ "/opt/chefdk/embedded/apps/chef/lib/chef/knife/client_bulk_delete.rb",
90
+ "/opt/chefdk/embedded/apps/chef/lib/chef/knife/client_create.rb",
91
+ # We use the fake version 1.0.0 because that version doesn't exist,
92
+ # which ensures it won't ever equal "chef-#{Chef::VERSION}"
93
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-1.0.0/lib/chef/knife/bootstrap.rb",
94
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-1.0.0/lib/chef/knife/client_bulk_delete.rb",
95
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-1.0.0/lib/chef/knife/client_create.rb",
96
+ # This command is "extra" compared to what's in the embedded/apps/chef install:
97
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-1.0.0/lib/chef/knife/data_bag_secret_options.rb",
98
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-vault-2.2.4/lib/chef/knife/decrypt.rb",
99
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/knife-spork-1.4.1/lib/chef/knife/spork-bump.rb",
100
+ # These are fake commands that have names designed to test that the
101
+ # regex is strict enough
102
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-foo-#{Chef::VERSION}/lib/chef/knife/chef-foo.rb",
103
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/foo-chef-#{Chef::VERSION}/lib/chef/knife/foo-chef.rb",
104
+ # In a real scenario, we'd use rubygems APIs to only select the most
105
+ # recent gem, but for this test we want to check that we're doing the
106
+ # right thing both when the plugin version matches and does not match
107
+ # the current chef version. Looking at
108
+ # `SubcommandLoader::MATCHES_THIS_CHEF_GEM` and
109
+ # `SubcommandLoader::MATCHES_CHEF_GEM` should make it clear why we want
110
+ # to test these two cases.
111
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-bar-1.0.0/lib/chef/knife/chef-bar.rb",
112
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/bar-chef-1.0.0/lib/chef/knife/bar-chef.rb"
113
+ ]
114
+ end
115
+
116
+ let(:expected_valid_commands) do
117
+ [
118
+ "/opt/chefdk/embedded/apps/chef/lib/chef/knife/bootstrap.rb",
119
+ "/opt/chefdk/embedded/apps/chef/lib/chef/knife/client_bulk_delete.rb",
120
+ "/opt/chefdk/embedded/apps/chef/lib/chef/knife/client_create.rb",
121
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-vault-2.2.4/lib/chef/knife/decrypt.rb",
122
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/knife-spork-1.4.1/lib/chef/knife/spork-bump.rb",
123
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-foo-#{Chef::VERSION}/lib/chef/knife/chef-foo.rb",
124
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/foo-chef-#{Chef::VERSION}/lib/chef/knife/foo-chef.rb",
125
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-bar-1.0.0/lib/chef/knife/chef-bar.rb",
126
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/bar-chef-1.0.0/lib/chef/knife/bar-chef.rb"
127
+ ]
128
+ end
129
+
130
+ before do
131
+ expect(@loader).to receive(:find_files_latest_gems).with("chef/knife/*.rb").and_return(all_found_commands)
132
+ expect(@loader).to receive(:find_subcommands_via_dirglob).and_return({})
133
+ end
134
+
135
+ it "ignores commands from the non-matching gem install" do
136
+ expect(@loader.find_subcommands_via_rubygems.values).to eq(expected_valid_commands)
137
+ end
138
+
139
+ end
140
+
141
+ describe "finding 3rd party plugins" do
77
142
  let(:env_home) { "/home/alice" }
78
143
  let(:manifest_path) { env_home + "/.chef/plugin_manifest.json" }
79
144
 
@@ -21,7 +21,6 @@ require 'spec_helper'
21
21
  require 'chef/data_bag_item'
22
22
  require 'chef/encrypted_data_bag_item'
23
23
  require 'tempfile'
24
- require 'json'
25
24
 
26
25
  Chef::Knife::DataBagFromFile.load_deps
27
26
 
@@ -46,7 +45,7 @@ describe Chef::Knife::DataBagFromFile do
46
45
  "greeting" => "hello",
47
46
  "nested" => { "a1" => [1, 2, 3], "a2" => { "b1" => true }}
48
47
  }
49
- @db_file.write(@plain_data.to_json)
48
+ @db_file.write(Chef::JSONCompat.to_json(@plain_data))
50
49
  @db_file.flush
51
50
  @knife.instance_variable_set(:@name_args, ['bag_name', @db_file.path])
52
51
  end
@@ -762,6 +762,10 @@ describe Chef::Node do
762
762
  end
763
763
  serialized_node.run_list.should == node.run_list
764
764
  end
765
+
766
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
767
+ let(:subject) { node.from_file(File.expand_path("nodes/test.example.com.rb", CHEF_SPEC_DATA)) }
768
+ end
765
769
  end
766
770
 
767
771
  describe "to_s" do
@@ -22,123 +22,152 @@ require 'chef/util/dsc/resource_info'
22
22
  require 'spec_helper'
23
23
 
24
24
  describe Chef::Provider::DscScript do
25
- let (:node) {
26
- node = Chef::Node.new
27
- node.automatic[:languages][:powershell][:version] = '4.0'
28
- node
29
- }
30
- let (:events) { Chef::EventDispatch::Dispatcher.new }
31
- let (:run_context) { Chef::RunContext.new(node, {}, events) }
32
- let (:resource) { Chef::Resource::DscScript.new("script", run_context) }
33
- let (:provider) do
34
- Chef::Provider::DscScript.new(resource, run_context)
35
- end
36
-
37
- describe '#load_current_resource' do
38
- it "describes the resource as converged if there were 0 DSC resources" do
39
- allow(provider).to receive(:run_configuration).with(:test).and_return([])
40
- provider.load_current_resource
41
- provider.instance_variable_get('@resource_converged').should be_true
25
+ context 'when DSC is available' do
26
+ let (:node) {
27
+ node = Chef::Node.new
28
+ node.automatic[:languages][:powershell][:version] = '4.0'
29
+ node
30
+ }
31
+ let (:events) { Chef::EventDispatch::Dispatcher.new }
32
+ let (:run_context) { Chef::RunContext.new(node, {}, events) }
33
+ let (:resource) { Chef::Resource::DscScript.new("script", run_context) }
34
+ let (:provider) do
35
+ Chef::Provider::DscScript.new(resource, run_context)
42
36
  end
43
37
 
44
- it "describes the resource as not converged if there is 1 DSC resources that is converged" do
45
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
46
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
47
- provider.load_current_resource
48
- provider.instance_variable_get('@resource_converged').should be_true
38
+ describe '#load_current_resource' do
39
+ it "describes the resource as converged if there were 0 DSC resources" do
40
+ allow(provider).to receive(:run_configuration).with(:test).and_return([])
41
+ provider.load_current_resource
42
+ provider.instance_variable_get('@resource_converged').should be_true
43
+ end
44
+
45
+ it "describes the resource as not converged if there is 1 DSC resources that is converged" do
46
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
47
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
48
+ provider.load_current_resource
49
+ provider.instance_variable_get('@resource_converged').should be_true
50
+ end
51
+
52
+ it "describes the resource as not converged if there is 1 DSC resources that is not converged" do
53
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
54
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
55
+ provider.load_current_resource
56
+ provider.instance_variable_get('@resource_converged').should be_false
57
+ end
58
+
59
+ it "describes the resource as not converged if there are any DSC resources that are not converged" do
60
+ dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
61
+ dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
62
+
63
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
64
+ provider.load_current_resource
65
+ provider.instance_variable_get('@resource_converged').should be_false
66
+ end
67
+
68
+ it "describes the resource as converged if all DSC resources that are converged" do
69
+ dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
70
+ dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
71
+
72
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
73
+ provider.load_current_resource
74
+ provider.instance_variable_get('@resource_converged').should be_true
75
+ end
49
76
  end
50
77
 
51
- it "describes the resource as not converged if there is 1 DSC resources that is not converged" do
52
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
53
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
54
- provider.load_current_resource
55
- provider.instance_variable_get('@resource_converged').should be_false
78
+ describe '#generate_configuration_document' do
79
+ # I think integration tests should cover these cases
80
+
81
+ it 'uses configuration_document_from_script_path when a dsc script file is given' do
82
+ allow(provider).to receive(:load_current_resource)
83
+ resource.command("path_to_script")
84
+ generator = double('Chef::Util::DSC::ConfigurationGenerator')
85
+ generator.should_receive(:configuration_document_from_script_path)
86
+ allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
87
+ provider.send(:generate_configuration_document, 'tmp', nil)
88
+ end
89
+
90
+ it 'uses configuration_document_from_script_code when a the dsc resource is given' do
91
+ allow(provider).to receive(:load_current_resource)
92
+ resource.code("ImADSCResource{}")
93
+ generator = double('Chef::Util::DSC::ConfigurationGenerator')
94
+ generator.should_receive(:configuration_document_from_script_code)
95
+ allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
96
+ provider.send(:generate_configuration_document, 'tmp', nil)
97
+ end
98
+
99
+ it 'should noop if neither code or command are provided' do
100
+ allow(provider).to receive(:load_current_resource)
101
+ generator = double('Chef::Util::DSC::ConfigurationGenerator')
102
+ generator.should_receive(:configuration_document_from_script_code).with('', anything(), anything())
103
+ allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
104
+ provider.send(:generate_configuration_document, 'tmp', nil)
105
+ end
56
106
  end
57
107
 
58
- it "describes the resource as not converged if there are any DSC resources that are not converged" do
59
- dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
60
- dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
61
-
62
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
63
- provider.load_current_resource
64
- provider.instance_variable_get('@resource_converged').should be_false
108
+ describe 'action_run' do
109
+ it 'should converge the script if it is not converged' do
110
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
111
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
112
+ allow(provider).to receive(:run_configuration).with(:set)
113
+
114
+ provider.run_action(:run)
115
+ resource.should be_updated
116
+ end
117
+
118
+ it 'should not converge if the script is already converged' do
119
+ allow(provider).to receive(:run_configuration).with(:test).and_return([])
120
+
121
+ provider.run_action(:run)
122
+ resource.should_not be_updated
123
+ end
65
124
  end
66
125
 
67
- it "describes the resource as converged if all DSC resources that are converged" do
68
- dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
69
- dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
70
-
71
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
72
- provider.load_current_resource
73
- provider.instance_variable_get('@resource_converged').should be_true
126
+ describe '#generate_description' do
127
+ it 'removes the resource name from the beginning of any log line from the LCM' do
128
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
129
+ provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
130
+ provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing something/)
131
+ end
132
+
133
+ it 'ignores the last line' do
134
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
135
+ provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
136
+ provider.send(:generate_description)[1].should_not match(/lastline/)
137
+ end
138
+
139
+ it 'reports a dsc resource has not been changed if the LCM reported no change was required' do
140
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', false, ['resourcename does nothing', 'lastline'])
141
+ provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
142
+ provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing nothing/)
143
+ end
74
144
  end
75
145
  end
76
146
 
77
- describe '#generate_configuration_document' do
78
- # I think integration tests should cover these cases
79
-
80
- it 'uses configuration_document_from_script_path when a dsc script file is given' do
81
- allow(provider).to receive(:load_current_resource)
82
- resource.command("path_to_script")
83
- generator = double('Chef::Util::DSC::ConfigurationGenerator')
84
- generator.should_receive(:configuration_document_from_script_path)
85
- allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
86
- provider.send(:generate_configuration_document, 'tmp', nil)
87
- end
88
-
89
- it 'uses configuration_document_from_script_code when a the dsc resource is given' do
90
- allow(provider).to receive(:load_current_resource)
91
- resource.code("ImADSCResource{}")
92
- generator = double('Chef::Util::DSC::ConfigurationGenerator')
93
- generator.should_receive(:configuration_document_from_script_code)
94
- allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
95
- provider.send(:generate_configuration_document, 'tmp', nil)
96
- end
97
-
98
- it 'should noop if neither code or command are provided' do
99
- allow(provider).to receive(:load_current_resource)
100
- generator = double('Chef::Util::DSC::ConfigurationGenerator')
101
- generator.should_receive(:configuration_document_from_script_code).with('', anything(), anything())
102
- allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
103
- provider.send(:generate_configuration_document, 'tmp', nil)
104
- end
105
- end
106
-
107
- describe 'action_run' do
108
- it 'should converge the script if it is not converged' do
109
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
110
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
111
- allow(provider).to receive(:run_configuration).with(:set)
112
-
113
- provider.run_action(:run)
114
- resource.should be_updated
115
- end
116
-
117
- it 'should not converge if the script is already converged' do
118
- allow(provider).to receive(:run_configuration).with(:test).and_return([])
119
-
120
- provider.run_action(:run)
121
- resource.should_not be_updated
122
- end
123
- end
124
-
125
- describe '#generate_description' do
126
- it 'removes the resource name from the beginning of any log line from the LCM' do
127
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
128
- provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
129
- provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing something/)
130
- end
131
-
132
- it 'ignores the last line' do
133
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
134
- provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
135
- provider.send(:generate_description)[1].should_not match(/lastline/)
136
- end
147
+ context 'when Dsc is not available' do
148
+ let (:node) { Chef::Node.new }
149
+ let (:events) { Chef::EventDispatch::Dispatcher.new }
150
+ let (:run_context) { Chef::RunContext.new(node, {}, events) }
151
+ let (:resource) { Chef::Resource::DscScript.new('script', run_context) }
152
+ let (:provider) { Chef::Provider::DscScript.new(resource, run_context) }
153
+
154
+ describe 'action_run' do
155
+ ['1.0', '2.0', '3.0'].each do |version|
156
+ it "raises an exception for powershell version '#{version}'" do
157
+ node.automatic[:languages][:powershell][:version] = version
158
+
159
+ expect {
160
+ provider.run_action(:run)
161
+ }.to raise_error(Chef::Exceptions::NoProviderAvailable)
162
+ end
163
+ end
164
+
165
+ it 'raises an exception if Powershell is not present' do
166
+ expect {
167
+ provider.run_action(:run)
168
+ }.to raise_error(Chef::Exceptions::NoProviderAvailable)
169
+ end
137
170
 
138
- it 'reports a dsc resource has not been changed if the LCM reported no change was required' do
139
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', false, ['resourcename does nothing', 'lastline'])
140
- provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
141
- provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing nothing/)
142
171
  end
143
172
  end
144
173
  end
@@ -53,7 +53,7 @@ describe Chef::Provider::Env::Windows, :windows_only do
53
53
  end
54
54
 
55
55
  it "should update the ruby ENV object when it updates the value" do
56
- provider.should_receive(:compare_value).and_return(true)
56
+ provider.should_receive(:requires_modify_or_create?).and_return(true)
57
57
  new_resource.value("foobar")
58
58
  provider.action_modify
59
59
  expect(ENV['CHEF_WINDOWS_ENV_TEST']).to eql('foobar')
@@ -92,7 +92,7 @@ describe Chef::Provider::Env::Windows, :windows_only do
92
92
  end
93
93
 
94
94
  it "replaces Windows system variables" do
95
- provider.should_receive(:compare_value).and_return(true)
95
+ provider.should_receive(:requires_modify_or_create?).and_return(true)
96
96
  provider.should_receive(:expand_path).with(system_root).and_return(system_root_value)
97
97
  provider.action_modify
98
98
  expect(ENV['PATH']).to eql(system_root_value)
@@ -88,20 +88,20 @@ describe Chef::Provider::Env do
88
88
 
89
89
  it "should check to see if the values are the same if the key exists" do
90
90
  @provider.key_exists = true
91
- @provider.should_receive(:compare_value).and_return(false)
91
+ @provider.should_receive(:requires_modify_or_create?).and_return(false)
92
92
  @provider.action_create
93
93
  end
94
94
 
95
95
  it "should call modify_env if the key exists and values are not equal" do
96
96
  @provider.key_exists = true
97
- @provider.stub(:compare_value).and_return(true)
97
+ @provider.stub(:requires_modify_or_create?).and_return(true)
98
98
  @provider.should_receive(:modify_env).and_return(true)
99
99
  @provider.action_create
100
100
  end
101
101
 
102
102
  it "should set the new_resources updated flag when it updates an existing value" do
103
103
  @provider.key_exists = true
104
- @provider.stub(:compare_value).and_return(true)
104
+ @provider.stub(:requires_modify_or_create?).and_return(true)
105
105
  @provider.stub(:modify_env).and_return(true)
106
106
  @provider.action_create
107
107
  @new_resource.should be_updated
@@ -147,20 +147,20 @@ describe Chef::Provider::Env do
147
147
  end
148
148
 
149
149
  it "should call modify_group if the key exists and values are not equal" do
150
- @provider.should_receive(:compare_value).and_return(true)
150
+ @provider.should_receive(:requires_modify_or_create?).and_return(true)
151
151
  @provider.should_receive(:modify_env).and_return(true)
152
152
  @provider.action_modify
153
153
  end
154
154
 
155
155
  it "should set the new resources updated flag to true if modify_env is called" do
156
- @provider.stub(:compare_value).and_return(true)
156
+ @provider.stub(:requires_modify_or_create?).and_return(true)
157
157
  @provider.stub(:modify_env).and_return(true)
158
158
  @provider.action_modify
159
159
  @new_resource.should be_updated
160
160
  end
161
161
 
162
162
  it "should not call modify_env if the key exists but the values are equal" do
163
- @provider.should_receive(:compare_value).and_return(false)
163
+ @provider.should_receive(:requires_modify_or_create?).and_return(false)
164
164
  @provider.should_not_receive(:modify_env)
165
165
  @provider.action_modify
166
166
  end
@@ -198,9 +198,31 @@ describe Chef::Provider::Env do
198
198
  @provider.delete_element.should eql(true)
199
199
  @new_resource.should be_updated
200
200
  end
201
+
202
+ context "when new_resource's value contains the delimiter" do
203
+ it "should return false if all the elements are deleted" do
204
+ # This indicates that the entire key needs to be deleted
205
+ @new_resource.value("C:/foo/bin;C:/bar/bin")
206
+ @provider.delete_element.should eql(false)
207
+ @new_resource.should_not be_updated # This will be updated in action_delete
208
+ end
209
+
210
+ it "should return true if any, but not all, of the elements are deleted" do
211
+ @new_resource.value("C:/foo/bin;C:/notbaz/bin")
212
+ @provider.should_receive(:create_env)
213
+ @provider.delete_element.should eql(true)
214
+ @new_resource.should be_updated
215
+ end
216
+
217
+ it "should return true if none of the elements are deleted" do
218
+ @new_resource.value("C:/notfoo/bin;C:/notbaz/bin")
219
+ @provider.delete_element.should eql(true)
220
+ @new_resource.should_not be_updated
221
+ end
222
+ end
201
223
  end
202
224
 
203
- describe "compare_value" do
225
+ describe "requires_modify_or_create?" do
204
226
  before(:each) do
205
227
  @new_resource.value("C:/bar")
206
228
  @current_resource = @new_resource.clone
@@ -208,25 +230,68 @@ describe Chef::Provider::Env do
208
230
  end
209
231
 
210
232
  it "should return false if the values are equal" do
211
- @provider.compare_value.should be_false
233
+ @provider.requires_modify_or_create?.should be_false
212
234
  end
213
235
 
214
236
  it "should return true if the values not are equal" do
215
237
  @new_resource.value("C:/elsewhere")
216
- @provider.compare_value.should be_true
238
+ @provider.requires_modify_or_create?.should be_true
217
239
  end
218
240
 
219
241
  it "should return false if the current value contains the element" do
220
242
  @new_resource.delim(";")
221
243
  @current_resource.value("C:/bar;C:/foo;C:/baz")
222
244
 
223
- @provider.compare_value.should be_false
245
+ @provider.requires_modify_or_create?.should be_false
224
246
  end
225
247
 
226
248
  it "should return true if the current value does not contain the element" do
227
249
  @new_resource.delim(";")
228
250
  @current_resource.value("C:/biz;C:/foo/bin;C:/baz")
229
- @provider.compare_value.should be_true
251
+ @provider.requires_modify_or_create?.should be_true
252
+ end
253
+
254
+ context "when new_resource's value contains the delimiter" do
255
+ it "should return false if all the current values are contained" do
256
+ @new_resource.value("C:/biz;C:/baz")
257
+ @new_resource.delim(";")
258
+ @current_resource.value("C:/biz;C:/foo/bin;C:/baz")
259
+ @provider.requires_modify_or_create?.should be_false
260
+ end
261
+
262
+ it "should return true if any of the new values are not contained" do
263
+ @new_resource.value("C:/biz;C:/baz;C:/bin")
264
+ @new_resource.delim(";")
265
+ @current_resource.value("C:/biz;C:/foo/bin;C:/baz")
266
+ @provider.requires_modify_or_create?.should be_true
267
+ end
268
+ end
269
+ end
270
+
271
+ describe "modify_env" do
272
+ before(:each) do
273
+ @provider.stub(:create_env).and_return(true)
274
+ @new_resource.delim ";"
275
+
276
+ @current_resource = Chef::Resource::Env.new("FOO")
277
+ @current_resource.value "C:/foo/bin"
278
+ @provider.current_resource = @current_resource
279
+ end
280
+
281
+ it "should not modify the variable passed to the resource" do
282
+ new_value = "C:/bar/bin"
283
+ passed_value = new_value.dup
284
+ @new_resource.value(passed_value)
285
+ @provider.modify_env
286
+ passed_value.should == new_value
287
+ end
288
+
289
+ it "should only add values not already contained when a delimiter is provided" do
290
+ @new_resource.value("C:/foo;C:/bar;C:/baz")
291
+ @new_resource.delim(";")
292
+ @current_resource.value("C:/foo/bar;C:/bar;C:/baz")
293
+ @provider.modify_env
294
+ @new_resource.value.should eq("C:/foo;C:/foo/bar;C:/bar;C:/baz")
230
295
  end
231
296
  end
232
297
  end