chef 11.14.6 → 11.16.0.rc.0

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.
@@ -107,8 +107,11 @@ RSpec.configure do |config|
107
107
  config.filter_run_excluding :not_supported_on_win2k3 => true if windows_win2k3?
108
108
  config.filter_run_excluding :not_supported_on_solaris => true if solaris?
109
109
  config.filter_run_excluding :win2k3_only => true unless windows_win2k3?
110
+ config.filter_run_excluding :windows_2008r2_or_later => true unless windows_2008r2_or_later?
110
111
  config.filter_run_excluding :windows64_only => true unless windows64?
111
112
  config.filter_run_excluding :windows32_only => true unless windows32?
113
+ config.filter_run_excluding :windows_powershell_dsc_only => true unless windows_powershell_dsc?
114
+ config.filter_run_excluding :windows_powershell_no_dsc_only => true unless ! windows_powershell_dsc?
112
115
  config.filter_run_excluding :windows_domain_joined_only => true unless windows_domain_joined?
113
116
  config.filter_run_excluding :solaris_only => true unless solaris?
114
117
  config.filter_run_excluding :system_windows_service_gem_only => true unless system_windows_service_gem?
@@ -43,6 +43,30 @@ def windows_win2k3?
43
43
  (host['version'] && host['version'].start_with?("5.2"))
44
44
  end
45
45
 
46
+ def windows_2008r2_or_later?
47
+ return false unless windows?
48
+ wmi = WmiLite::Wmi.new
49
+ host = wmi.first_of('Win32_OperatingSystem')
50
+ version = host['version']
51
+ return false unless version
52
+ components = version.split('.').map do | component |
53
+ component.to_i
54
+ end
55
+ components.length >=2 && components[0] >= 6 && components[1] >= 1
56
+ end
57
+
58
+ def windows_powershell_dsc?
59
+ return false unless windows?
60
+ supports_dsc = false
61
+ begin
62
+ wmi = WmiLite::Wmi.new('root/microsoft/windows/desiredstateconfiguration')
63
+ lcm = wmi.query("SELECT * FROM meta_class WHERE __this ISA 'MSFT_DSCLocalConfigurationManager'")
64
+ supports_dsc = !! lcm
65
+ rescue WmiLite::WmiException
66
+ end
67
+ supports_dsc
68
+ end
69
+
46
70
  def mac_osx_106?
47
71
  if File.exists? "/usr/bin/sw_vers"
48
72
  result = shell_out("/usr/bin/sw_vers")
@@ -0,0 +1,141 @@
1
+ #
2
+ # Author:: Jay Mundrawala (<jdm@getchef.com>)
3
+ #
4
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'chef'
21
+ require 'chef/util/dsc/resource_info'
22
+ require 'spec_helper'
23
+
24
+ describe Chef::Provider::DscScript do
25
+ let (:node) { Chef::Node.new }
26
+ let (:events) { Chef::EventDispatch::Dispatcher.new }
27
+ let (:run_context) { Chef::RunContext.new(node, {}, events) }
28
+ let (:resource) { Chef::Resource::DscScript.new("script", run_context) }
29
+ let (:provider) do
30
+ Chef::Provider::DscScript.new(resource, run_context)
31
+ end
32
+
33
+ describe '#load_current_resource' do
34
+ it "describes the resource as converged if there were 0 DSC resources" do
35
+ allow(provider).to receive(:run_configuration).with(:test).and_return([])
36
+ provider.load_current_resource
37
+ provider.instance_variable_get('@resource_converged').should be_true
38
+ end
39
+
40
+ it "describes the resource as not converged if there is 1 DSC resources that is converged" do
41
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
42
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
43
+ provider.load_current_resource
44
+ provider.instance_variable_get('@resource_converged').should be_true
45
+ end
46
+
47
+ it "describes the resource as not converged if there is 1 DSC resources that is not converged" do
48
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
49
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
50
+ provider.load_current_resource
51
+ provider.instance_variable_get('@resource_converged').should be_false
52
+ end
53
+
54
+ it "describes the resource as not converged if there are any DSC resources that are not converged" do
55
+ dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
56
+ dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
57
+
58
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
59
+ provider.load_current_resource
60
+ provider.instance_variable_get('@resource_converged').should be_false
61
+ end
62
+
63
+ it "describes the resource as converged if all DSC resources that are converged" do
64
+ dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
65
+ dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
66
+
67
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
68
+ provider.load_current_resource
69
+ provider.instance_variable_get('@resource_converged').should be_true
70
+ end
71
+ end
72
+
73
+ describe '#generate_configuration_document' do
74
+ # I think integration tests should cover these cases
75
+
76
+ it 'uses configuration_document_from_script_path when a dsc script file is given' do
77
+ allow(provider).to receive(:load_current_resource)
78
+ resource.command("path_to_script")
79
+ generator = double('Chef::Util::DSC::ConfigurationGenerator')
80
+ generator.should_receive(:configuration_document_from_script_path)
81
+ allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
82
+ provider.send(:generate_configuration_document, 'tmp', nil)
83
+ end
84
+
85
+ it 'uses configuration_document_from_script_code when a the dsc resource is given' do
86
+ allow(provider).to receive(:load_current_resource)
87
+ resource.code("ImADSCResource{}")
88
+ generator = double('Chef::Util::DSC::ConfigurationGenerator')
89
+ generator.should_receive(:configuration_document_from_script_code)
90
+ allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
91
+ provider.send(:generate_configuration_document, 'tmp', nil)
92
+ end
93
+
94
+ it 'should noop if neither code or command are provided' do
95
+ allow(provider).to receive(:load_current_resource)
96
+ generator = double('Chef::Util::DSC::ConfigurationGenerator')
97
+ generator.should_receive(:configuration_document_from_script_code).with('', anything(), anything())
98
+ allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
99
+ provider.send(:generate_configuration_document, 'tmp', nil)
100
+ end
101
+ end
102
+
103
+ describe 'action_run' do
104
+ it 'should converge the script if it is not converged' do
105
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
106
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
107
+ allow(provider).to receive(:run_configuration).with(:set)
108
+
109
+ provider.run_action(:run)
110
+ resource.should be_updated
111
+ end
112
+
113
+ it 'should not converge if the script is already converged' do
114
+ allow(provider).to receive(:run_configuration).with(:test).and_return([])
115
+
116
+ provider.run_action(:run)
117
+ resource.should_not be_updated
118
+ end
119
+ end
120
+
121
+ describe '#generate_description' do
122
+ it 'removes the resource name from the beginning of any log line from the LCM' do
123
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
124
+ provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
125
+ provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing something/)
126
+ end
127
+
128
+ it 'ignores the last line' do
129
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
130
+ provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
131
+ provider.send(:generate_description)[1].should_not match(/lastline/)
132
+ end
133
+
134
+ it 'reports a dsc resource has not been changed if the LCM reported no change was required' do
135
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', false, ['resourcename does nothing', 'lastline'])
136
+ provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
137
+ provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing nothing/)
138
+ end
139
+ end
140
+ end
141
+
@@ -0,0 +1,94 @@
1
+ #
2
+ # Author:: Adam Edwards (<adamed@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::Resource::DscScript do
22
+ let(:dsc_test_run_context) {
23
+ node = Chef::Node.new
24
+ empty_events = Chef::EventDispatch::Dispatcher.new
25
+ Chef::RunContext.new(node, {}, empty_events)
26
+ }
27
+ let(:dsc_test_resource_name) { 'DSCTest' }
28
+ let(:dsc_test_resource) {
29
+ Chef::Resource::DscScript.new(dsc_test_resource_name, dsc_test_run_context)
30
+ }
31
+ let(:configuration_code) {'echo "This is supposed to create a configuration document."'}
32
+ let(:configuration_path) {'c:/myconfigs/formatc.ps1'}
33
+ let(:configuration_name) { 'formatme' }
34
+ let(:configuration_data) { '@{AllNodes = @( @{ NodeName = "localhost"; PSDscAllowPlainTextPassword = $true })}' }
35
+ let(:configuration_data_script) { 'c:/myconfigs/data/safedata.psd1' }
36
+
37
+ it "has a default action of `:run`" do
38
+ expect(dsc_test_resource.action).to eq(:run)
39
+ end
40
+
41
+ it "has an allowed_actions attribute with only the `:run` and `:nothing` attributes" do
42
+ expect(dsc_test_resource.allowed_actions.to_set).to eq([:run,:nothing].to_set)
43
+ end
44
+
45
+ it "allows the code attribute to be set" do
46
+ dsc_test_resource.code(configuration_code)
47
+ expect(dsc_test_resource.code).to eq(configuration_code)
48
+ end
49
+
50
+ it "allows the command attribute to be set" do
51
+ dsc_test_resource.command(configuration_path)
52
+ expect(dsc_test_resource.command).to eq(configuration_path)
53
+ end
54
+
55
+ it "allows the configuration_name attribute to be set" do
56
+ dsc_test_resource.configuration_name(configuration_name)
57
+ expect(dsc_test_resource.configuration_name).to eq(configuration_name)
58
+ end
59
+
60
+ it "allows the configuration_data attribute to be set" do
61
+ dsc_test_resource.configuration_data(configuration_data)
62
+ expect(dsc_test_resource.configuration_data).to eq(configuration_data)
63
+ end
64
+
65
+ it "allows the configuration_data_script attribute to be set" do
66
+ dsc_test_resource.configuration_data_script(configuration_data_script)
67
+ expect(dsc_test_resource.configuration_data_script).to eq(configuration_data_script)
68
+ end
69
+
70
+ it "raises an ArgumentError exception if an attempt is made to set the code attribute when the command attribute is already set" do
71
+ dsc_test_resource.command(configuration_path)
72
+ expect { dsc_test_resource.code(configuration_code) }.to raise_error(ArgumentError)
73
+ end
74
+
75
+ it "raises an ArgumentError exception if an attempt is made to set the command attribute when the code attribute is already set" do
76
+ dsc_test_resource.code(configuration_code)
77
+ expect { dsc_test_resource.command(configuration_path) }.to raise_error(ArgumentError)
78
+ end
79
+
80
+ it "raises an ArgumentError exception if an attempt is made to set the configuration_name attribute when the code attribute is already set" do
81
+ dsc_test_resource.code(configuration_code)
82
+ expect { dsc_test_resource.configuration_name(configuration_name) }.to raise_error(ArgumentError)
83
+ end
84
+
85
+ it "raises an ArgumentError exception if an attempt is made to set the configuration_data attribute when the configuration_data_script attribute is already set" do
86
+ dsc_test_resource.configuration_data_script(configuration_data_script)
87
+ expect { dsc_test_resource.configuration_data(configuration_data) }.to raise_error(ArgumentError)
88
+ end
89
+
90
+ it "raises an ArgumentError exception if an attempt is made to set the configuration_data_script attribute when the configuration_data attribute is already set" do
91
+ dsc_test_resource.configuration_data(configuration_data)
92
+ expect { dsc_test_resource.configuration_data_script(configuration_data_script) }.to raise_error(ArgumentError)
93
+ end
94
+ end
@@ -0,0 +1,173 @@
1
+ #
2
+ # Author:: Jay Mundrawala <jmundrawala@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 'chef'
20
+ require 'chef/util/dsc/configuration_generator'
21
+
22
+ describe Chef::Util::DSC::ConfigurationGenerator do
23
+ before (:all) do
24
+ @node = Chef::Node.new
25
+ @conf_man = Chef::Util::DSC::ConfigurationGenerator.new(@node, 'tmp')
26
+ end
27
+
28
+ describe '#validate_configuration_name!' do
29
+ it 'should not raise an error if a name contains all upper case letters' do
30
+ @conf_man.send(:validate_configuration_name!, "HELLO")
31
+ end
32
+
33
+ it 'should not raise an error if the name contains all lower case letters' do
34
+ @conf_man.send(:validate_configuration_name!, "hello")
35
+ end
36
+
37
+ it 'should not raise an error if no special characters are used except _' do
38
+ @conf_man.send(:validate_configuration_name!, "hello_world")
39
+ end
40
+
41
+ %w{! @ # $ % ^ & * & * ( ) - = + \{ \} . ? < > \\ /}.each do |sym|
42
+ it "raises an Argument error if it configuration name contains #{sym}" do
43
+ expect {
44
+ @conf_man.send(:validate_configuration_name!, "Hello#{sym}")
45
+ }.to raise_error(ArgumentError)
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "#get_merged_configuration_flags" do
51
+ context 'when strings are used as switches' do
52
+ it 'should merge the hash if there are no restricted switches' do
53
+ merged = @conf_man.send(:get_merged_configuration_flags!, {'flag' => 'a'}, 'hello')
54
+ merged.should include(:flag)
55
+ merged[:flag].should eql('a')
56
+ merged.should include(:outputpath)
57
+ end
58
+
59
+ it 'should raise an ArgumentError if you try to override outputpath' do
60
+ expect {
61
+ @conf_man.send(:get_merged_configuration_flags!, {'outputpath' => 'a'}, 'hello')
62
+ }.to raise_error(ArgumentError)
63
+ end
64
+
65
+ it 'should be case insensitive for switches that are not allowed' do
66
+ expect {
67
+ @conf_man.send(:get_merged_configuration_flags!, {'OutputPath' => 'a'}, 'hello')
68
+ }.to raise_error(ArgumentError)
69
+ end
70
+
71
+ it 'should be case insensitive to switches that are allowed' do
72
+ merged = @conf_man.send(:get_merged_configuration_flags!, {'FLAG' => 'a'}, 'hello')
73
+ merged.should include(:flag)
74
+ end
75
+ end
76
+
77
+ context 'when symbols are used as switches' do
78
+ it 'should merge the hash if there are no restricted switches' do
79
+ merged = @conf_man.send(:get_merged_configuration_flags!, {:flag => 'a'}, 'hello')
80
+ merged.should include(:flag)
81
+ merged[:flag].should eql('a')
82
+ merged.should include(:outputpath)
83
+ end
84
+
85
+ it 'should raise an ArgumentError if you try to override outputpath' do
86
+ expect {
87
+ @conf_man.send(:get_merged_configuration_flags!, {:outputpath => 'a'}, 'hello')
88
+ }.to raise_error(ArgumentError)
89
+ end
90
+
91
+ it 'should be case insensitive for switches that are not allowed' do
92
+ expect {
93
+ @conf_man.send(:get_merged_configuration_flags!, {:OutputPath => 'a'}, 'hello')
94
+ }.to raise_error(ArgumentError)
95
+ end
96
+
97
+ it 'should be case insensitive to switches that are allowed' do
98
+ merged = @conf_man.send(:get_merged_configuration_flags!, {:FLAG => 'a'}, 'hello')
99
+ merged.should include(:flag)
100
+ end
101
+ end
102
+
103
+ context 'when there are no flags' do
104
+ it 'should supply an output path if configuration_flags is an empty hash' do
105
+ merged = @conf_man.send(:get_merged_configuration_flags!, {}, 'hello')
106
+ merged.should include(:outputpath)
107
+ merged.length.should eql(1)
108
+ end
109
+
110
+ it 'should supply an output path if configuration_flags is an empty hash' do
111
+ merged = @conf_man.send(:get_merged_configuration_flags!, nil, 'hello')
112
+ merged.should include(:outputpath)
113
+ merged.length.should eql(1)
114
+ end
115
+ end
116
+
117
+ # What should happen if configuration flags contains duplicates?
118
+ # flagA => 'a', flaga => 'a'
119
+ # or
120
+ # flagA => 'a', flaga => 'b'
121
+ #
122
+ end
123
+
124
+ describe '#write_document_generation_script' do
125
+ before (:each) do
126
+ @file_like_object = double("file like object")
127
+ end
128
+
129
+ it "should write the input to a file" do
130
+ File.stub(:open).and_yield(@file_like_object)
131
+ @file_like_object.stub(:write).with(anything())
132
+ File.stub(:join) do |a, b|
133
+ [a,b].join("++")
134
+ end
135
+ @conf_man.send(:write_document_generation_script, 'file', 'hello')
136
+ expect(@file_like_object).to have_received(:write)
137
+ end
138
+ end
139
+
140
+ describe "#find_configuration_document" do
141
+ it "should find the mof file" do
142
+ # These tests seem way too implementation specific. Unfortunatly, File and Dir
143
+ # need to be mocked because they are OS specific
144
+
145
+ File.stub(:join) do |a, b|
146
+ [a,b].join("++")
147
+ end
148
+ Dir.stub(:entries).with("tmp++hello") {['f1', 'f2', 'hello.mof', 'f3']}
149
+ expect(@conf_man.send(:find_configuration_document, 'hello')).to eql('tmp++hello++hello.mof')
150
+ end
151
+
152
+ it "should return nil if the mof file is not found" do
153
+ File.stub(:join) do |a, b|
154
+ [a,b].join("++")
155
+ end
156
+ Dir.stub(:entries).with("tmp++hello") {['f1', 'f2', 'f3']}
157
+ expect(@conf_man.send(:find_configuration_document, 'hello')).to be_nil
158
+ end
159
+ end
160
+
161
+ describe "#configuration_code" do
162
+ it "should build dsc" do
163
+ dsc = @conf_man.send(:configuration_code, 'archive{}', 'hello')
164
+ found_configuration = false
165
+ dsc.split(';').each do |command|
166
+ if command.downcase =~ /\s*configuration\s+'hello'\s*\{\s*node\s+'localhost'\s*\{\s*archive\s*\{\s*\}\s*\}\s*\}\s*/
167
+ found_configuration = true
168
+ end
169
+ end
170
+ expect(found_configuration).to be_true
171
+ end
172
+ end
173
+ end