chef 16.7.61-universal-mingw32 → 16.8.9-universal-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -2
- data/README.md +1 -1
- data/chef.gemspec +2 -1
- data/distro/ruby_bin_folder/AMD64/Chef.PowerShell.Wrapper.dll +0 -0
- data/distro/ruby_bin_folder/AMD64/Chef.PowerShell.dll +0 -0
- data/distro/ruby_bin_folder/AMD64/shared/Microsoft.NETCore.App/5.0.0/Chef.PowerShell.Wrapper.Core.dll +0 -0
- data/distro/ruby_bin_folder/AMD64/shared/Microsoft.NETCore.App/5.0.0/Chef.Powershell.Core.dll +0 -0
- data/distro/ruby_bin_folder/AMD64/shared/Microsoft.NETCore.App/5.0.0/Chef.Powershell.Core.pdb +0 -0
- data/distro/ruby_bin_folder/x86/Chef.PowerShell.dll +0 -0
- data/distro/ruby_bin_folder/x86/Chef.Powershell.Wrapper.dll +0 -0
- data/distro/ruby_bin_folder/x86/shared/Microsoft.NETCore.App/5.0.0/Chef.PowerShell.Wrapper.Core.dll +0 -0
- data/distro/ruby_bin_folder/x86/shared/Microsoft.NETCore.App/5.0.0/Chef.Powershell.Core.dll +0 -0
- data/distro/ruby_bin_folder/x86/shared/Microsoft.NETCore.App/5.0.0/Chef.Powershell.Core.pdb +0 -0
- data/lib/chef/application/base.rb +1 -1
- data/lib/chef/client.rb +3 -0
- data/lib/chef/compliance/default_attributes.rb +89 -0
- data/lib/chef/compliance/fetcher/automate.rb +69 -0
- data/lib/chef/compliance/fetcher/chef_server.rb +134 -0
- data/lib/chef/compliance/reporter/automate.rb +202 -0
- data/lib/chef/compliance/reporter/chef_server_automate.rb +92 -0
- data/lib/chef/compliance/reporter/compliance_enforcer.rb +20 -0
- data/lib/chef/compliance/reporter/json_file.rb +19 -0
- data/lib/chef/compliance/runner.rb +250 -0
- data/lib/chef/cookbook_manifest.rb +1 -0
- data/lib/chef/encrypted_data_bag_item/assertions.rb +1 -1
- data/lib/chef/exceptions.rb +4 -0
- data/lib/chef/http/ssl_policies.rb +6 -0
- data/lib/chef/knife/bootstrap/train_connector.rb +1 -1
- data/lib/chef/knife/core/ui.rb +4 -1
- data/lib/chef/knife/ssh.rb +1 -1
- data/lib/chef/mixin/powershell_exec.rb +3 -1
- data/lib/chef/platform/query_helpers.rb +4 -4
- data/lib/chef/powershell.rb +2 -0
- data/lib/chef/provider/dsc_resource.rb +12 -24
- data/lib/chef/provider/dsc_script.rb +16 -20
- data/lib/chef/provider/git.rb +5 -5
- data/lib/chef/resource/chef_client_config.rb +1 -1
- data/lib/chef/resource/dsc_script.rb +8 -1
- data/lib/chef/resource/hostname.rb +3 -3
- data/lib/chef/resource/template.rb +2 -2
- data/lib/chef/resource/windows_certificate.rb +7 -1
- data/lib/chef/resource_collection/resource_set.rb +1 -1
- data/lib/chef/util/dsc/configuration_generator.rb +52 -11
- data/lib/chef/util/dsc/lcm_output_parser.rb +3 -4
- data/lib/chef/util/dsc/local_configuration_manager.rb +17 -14
- data/lib/chef/util/dsc/resource_store.rb +5 -11
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/api/file.rb +4 -0
- data/spec/functional/resource/dsc_script_spec.rb +3 -6
- data/spec/integration/client/client_spec.rb +2 -1
- data/spec/integration/compliance/compliance_spec.rb +81 -0
- data/spec/integration/recipes/recipe_dsl_spec.rb +1 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/client_spec.rb +1 -0
- data/spec/unit/compliance/fetcher/automate_spec.rb +134 -0
- data/spec/unit/compliance/fetcher/chef_server_spec.rb +93 -0
- data/spec/unit/compliance/reporter/automate_spec.rb +427 -0
- data/spec/unit/compliance/reporter/chef_server_automate_spec.rb +177 -0
- data/spec/unit/compliance/reporter/compliance_enforcer_spec.rb +48 -0
- data/spec/unit/compliance/runner_spec.rb +113 -0
- data/spec/unit/http/ssl_policies_spec.rb +11 -0
- data/spec/unit/knife/core/node_editor_spec.rb +1 -1
- data/spec/unit/mixin/powershell_exec_spec.rb +1 -1
- data/spec/unit/platform/query_helpers_spec.rb +11 -12
- data/spec/unit/provider/dsc_resource_spec.rb +10 -27
- data/spec/unit/provider/dsc_script_spec.rb +1 -1
- data/spec/unit/provider/mount/windows_spec.rb +1 -0
- data/spec/unit/provider/systemd_unit_spec.rb +1 -1
- data/spec/unit/resource/windows_certificate_spec.rb +12 -0
- data/spec/unit/util/dsc/configuration_generator_spec.rb +79 -0
- data/spec/unit/util/dsc/local_configuration_manager_spec.rb +27 -35
- metadata +37 -12
- data/lib/chef/util/powershell/cmdlet.rb +0 -169
- data/lib/chef/util/powershell/cmdlet_result.rb +0 -61
- data/spec/functional/util/powershell/cmdlet_spec.rb +0 -111
- data/spec/unit/util/powershell/cmdlet_spec.rb +0 -106
data/lib/chef/knife/core/ui.rb
CHANGED
@@ -64,7 +64,10 @@ class Chef
|
|
64
64
|
# Creates a new object of class TTY::Prompt
|
65
65
|
# with interrupt as exit so that it can be terminated with status code.
|
66
66
|
def prompt
|
67
|
-
@prompt ||=
|
67
|
+
@prompt ||= begin
|
68
|
+
require "tty-prompt"
|
69
|
+
TTY::Prompt.new(interrupt: :exit)
|
70
|
+
end
|
68
71
|
end
|
69
72
|
|
70
73
|
# pastel.decorate is a lightweight replacement for highline.color
|
data/lib/chef/knife/ssh.rb
CHANGED
@@ -289,7 +289,7 @@ class Chef
|
|
289
289
|
opts[:port] = port unless port.nil?
|
290
290
|
opts[:logger] = Chef::Log.with_child(subsystem: "net/ssh") if Chef::Log.level == :trace
|
291
291
|
unless config[:host_key_verify]
|
292
|
-
opts[:verify_host_key] =
|
292
|
+
opts[:verify_host_key] = :never
|
293
293
|
opts[:user_known_hosts_file] = "/dev/null"
|
294
294
|
end
|
295
295
|
if ssh_config[:keepalive]
|
@@ -23,10 +23,12 @@ require_relative "../pwsh"
|
|
23
23
|
# powershell_exec is initialized with a string that should be set to the script
|
24
24
|
# to run and also takes an optional interpreter argument which must be either
|
25
25
|
# :powershell (Windows PowerShell which is the default) or :pwsh (PowerShell
|
26
|
-
# Core). It will return a Chef::PowerShell object that provides
|
26
|
+
# Core). It will return a Chef::PowerShell object that provides 5 methods:
|
27
27
|
#
|
28
28
|
# .result - returns a hash representing the results returned by executing the
|
29
29
|
# PowerShell script block
|
30
|
+
# .verbose - this is an array of string containing any messages written to the
|
31
|
+
# PowerShell verbose stream during execution
|
30
32
|
# .errors - this is an array of string containing any messages written to the
|
31
33
|
# PowerShell error stream during execution
|
32
34
|
# .error? - returns true if there were error messages written to the PowerShell
|
@@ -58,10 +58,10 @@ class Chef
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def dsc_refresh_mode_disabled?(node)
|
61
|
-
require_relative "../
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
require_relative "../powershell"
|
62
|
+
exec = Chef::PowerShell.new("Get-DscLocalConfigurationManager")
|
63
|
+
exec.error!
|
64
|
+
exec.result["RefreshMode"] == "Disabled"
|
65
65
|
end
|
66
66
|
|
67
67
|
def supported_powershell_version?(node, version_string)
|
data/lib/chef/powershell.rb
CHANGED
@@ -24,6 +24,7 @@ class Chef
|
|
24
24
|
|
25
25
|
attr_reader :result
|
26
26
|
attr_reader :errors
|
27
|
+
attr_reader :verbose
|
27
28
|
|
28
29
|
# Run a command under PowerShell via FFI
|
29
30
|
# This implementation requires the managed dll and native wrapper to be in the library search
|
@@ -72,6 +73,7 @@ class Chef
|
|
72
73
|
hashed_outcome = Chef::JSONCompat.parse(execution)
|
73
74
|
@result = Chef::JSONCompat.parse(hashed_outcome["result"])
|
74
75
|
@errors = hashed_outcome["errors"]
|
76
|
+
@verbose = hashed_outcome["verbose"]
|
75
77
|
end
|
76
78
|
end
|
77
79
|
end
|
@@ -15,7 +15,8 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
|
-
|
18
|
+
require "timeout" unless defined?(Timeout)
|
19
|
+
require_relative "../mixin/powershell_exec"
|
19
20
|
require_relative "../util/dsc/local_configuration_manager"
|
20
21
|
require_relative "../mixin/powershell_type_coercions"
|
21
22
|
require_relative "../util/dsc/resource_store"
|
@@ -130,27 +131,27 @@ class Chef
|
|
130
131
|
def test_resource
|
131
132
|
result = invoke_resource(:test)
|
132
133
|
add_dsc_verbose_log(result)
|
133
|
-
|
134
|
+
result.result["InDesiredState"]
|
134
135
|
end
|
135
136
|
|
136
137
|
def set_resource
|
137
138
|
result = invoke_resource(:set)
|
138
139
|
add_dsc_verbose_log(result)
|
139
|
-
create_reboot_resource if
|
140
|
-
result
|
140
|
+
create_reboot_resource if result.result["RebootRequired"]
|
141
|
+
result
|
141
142
|
end
|
142
143
|
|
143
144
|
def add_dsc_verbose_log(result)
|
144
145
|
# We really want this information from the verbose stream,
|
145
146
|
# however in some versions of WMF, Invoke-DscResource is not correctly
|
146
147
|
# writing to that stream and instead just dumping to stdout
|
147
|
-
verbose_output = result.
|
148
|
-
verbose_output = result.
|
148
|
+
verbose_output = result.verbose.join("\n")
|
149
|
+
verbose_output = result.result if verbose_output.empty?
|
149
150
|
|
150
151
|
if @converge_description.nil? || @converge_description.empty?
|
151
152
|
@converge_description = verbose_output
|
152
153
|
else
|
153
|
-
@converge_description << "\n"
|
154
|
+
@converge_description << "\n\n"
|
154
155
|
@converge_description << verbose_output
|
155
156
|
end
|
156
157
|
end
|
@@ -159,26 +160,13 @@ class Chef
|
|
159
160
|
@module_version.nil? ? module_name : "@{ModuleName='#{module_name}';ModuleVersion='#{@module_version}'}"
|
160
161
|
end
|
161
162
|
|
162
|
-
def invoke_resource(method
|
163
|
+
def invoke_resource(method)
|
163
164
|
properties = translate_type(new_resource.properties)
|
164
165
|
switches = "-Method #{method} -Name #{new_resource.resource}"\
|
165
166
|
" -Property #{properties} -Module #{module_info_object} -Verbose"
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
output_format
|
170
|
-
)
|
171
|
-
cmdlet.run!({}, { timeout: new_resource.timeout })
|
172
|
-
end
|
173
|
-
|
174
|
-
def return_dsc_resource_result(result, property_name)
|
175
|
-
if result.return_value.is_a?(Array)
|
176
|
-
# WMF Feb 2015 Preview
|
177
|
-
result.return_value[0][property_name]
|
178
|
-
else
|
179
|
-
# WMF April 2015 Preview
|
180
|
-
result.return_value[property_name]
|
181
|
-
end
|
167
|
+
Timeout.timeout(new_resource.timeout) {
|
168
|
+
powershell_exec!("Invoke-DscResource #{switches}")
|
169
|
+
}
|
182
170
|
end
|
183
171
|
|
184
172
|
def create_reboot_resource
|
@@ -16,7 +16,6 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require_relative "../util/powershell/cmdlet"
|
20
19
|
require_relative "../util/dsc/configuration_generator"
|
21
20
|
require_relative "../util/dsc/local_configuration_manager"
|
22
21
|
require_relative "../util/path_helper"
|
@@ -32,11 +31,11 @@ class Chef
|
|
32
31
|
@dsc_resource = dsc_resource
|
33
32
|
@resource_converged = false
|
34
33
|
@operations = {
|
35
|
-
set: Proc.new do |config_manager, document
|
36
|
-
config_manager.set_configuration(document
|
34
|
+
set: Proc.new do |config_manager, document|
|
35
|
+
config_manager.set_configuration(document)
|
37
36
|
end,
|
38
|
-
test: Proc.new do |config_manager, document
|
39
|
-
config_manager.test_configuration(document
|
37
|
+
test: Proc.new do |config_manager, document|
|
38
|
+
config_manager.test_configuration(document)
|
40
39
|
end }
|
41
40
|
end
|
42
41
|
|
@@ -85,20 +84,23 @@ class Chef
|
|
85
84
|
|
86
85
|
config_manager = Chef::Util::DSC::LocalConfigurationManager.new(@run_context.node, config_directory)
|
87
86
|
|
88
|
-
|
89
|
-
|
90
|
-
environment: @dsc_resource.environment,
|
91
|
-
timeout: @dsc_resource.timeout,
|
92
|
-
}
|
87
|
+
cwd = @dsc_resource.cwd || Dir.pwd
|
88
|
+
original_env = ENV.to_hash
|
93
89
|
|
94
90
|
begin
|
95
|
-
|
96
|
-
|
91
|
+
ENV.update(@dsc_resource.environment) if @dsc_resource.environment
|
92
|
+
Dir.chdir(cwd) do
|
93
|
+
Timeout.timeout(@dsc_resource.timeout) do
|
94
|
+
configuration_document = generate_configuration_document(config_directory, configuration_flags)
|
95
|
+
@operations[operation].call(config_manager, configuration_document)
|
96
|
+
end
|
97
|
+
end
|
97
98
|
rescue Exception => e
|
98
99
|
logger.error("DSC operation failed: #{e.message}")
|
99
100
|
raise e
|
100
101
|
ensure
|
101
102
|
::FileUtils.rm_rf(config_directory)
|
103
|
+
ENV.replace(original_env)
|
102
104
|
end
|
103
105
|
end
|
104
106
|
|
@@ -112,20 +114,14 @@ class Chef
|
|
112
114
|
end
|
113
115
|
|
114
116
|
def generate_configuration_document(config_directory, configuration_flags)
|
115
|
-
shellout_flags = {
|
116
|
-
cwd: @dsc_resource.cwd,
|
117
|
-
environment: @dsc_resource.environment,
|
118
|
-
timeout: @dsc_resource.timeout,
|
119
|
-
}
|
120
|
-
|
121
117
|
generator = Chef::Util::DSC::ConfigurationGenerator.new(@run_context.node, config_directory)
|
122
118
|
|
123
119
|
if @dsc_resource.command
|
124
|
-
generator.configuration_document_from_script_path(@dsc_resource.command, configuration_name, configuration_flags
|
120
|
+
generator.configuration_document_from_script_path(@dsc_resource.command, configuration_name, configuration_flags)
|
125
121
|
else
|
126
122
|
# If code is also not provided, we mimic what the other script resources do (execute nothing)
|
127
123
|
logger.warn("Neither code or command were provided for dsc_resource[#{@dsc_resource.name}].") unless @dsc_resource.code
|
128
|
-
generator.configuration_document_from_script_code(@dsc_resource.code || "", configuration_flags, @dsc_resource.imports
|
124
|
+
generator.configuration_document_from_script_code(@dsc_resource.code || "", configuration_flags, @dsc_resource.imports)
|
129
125
|
end
|
130
126
|
end
|
131
127
|
|
data/lib/chef/provider/git.rb
CHANGED
@@ -68,9 +68,9 @@ class Chef
|
|
68
68
|
a.assertion { !(new_resource.revision =~ %r{^origin/}) }
|
69
69
|
a.failure_message Chef::Exceptions::InvalidRemoteGitReference,
|
70
70
|
"Deploying remote branches is not supported. " +
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
"Specify the remote branch as a local branch for " +
|
72
|
+
"the git repository you're deploying from " +
|
73
|
+
"(ie: '#{new_resource.revision.gsub("origin/", "")}' rather than '#{new_resource.revision}')."
|
74
74
|
end
|
75
75
|
|
76
76
|
requirements.assert(:all_actions) do |a|
|
@@ -80,8 +80,8 @@ class Chef
|
|
80
80
|
a.assertion { !target_revision.nil? }
|
81
81
|
a.failure_message Chef::Exceptions::UnresolvableGitReference,
|
82
82
|
"Unable to parse SHA reference for '#{new_resource.revision}' in repository '#{new_resource.repository}'. " +
|
83
|
-
|
84
|
-
|
83
|
+
"Verify your (case-sensitive) repository URL and revision.\n" +
|
84
|
+
"`git ls-remote '#{new_resource.repository}' '#{rev_search_pattern}'` output: #{@resolved_reference}"
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
@@ -110,7 +110,7 @@ class Chef
|
|
110
110
|
property :config_directory, String,
|
111
111
|
description: "The directory to store the client.rb in.",
|
112
112
|
default: ChefConfig::Config.etc_chef_dir,
|
113
|
-
default_description: "`/etc/chef/` on *nix-like systems and `C
|
113
|
+
default_description: "`/etc/chef/` on *nix-like systems and `C:\\chef\\` on Windows"
|
114
114
|
|
115
115
|
property :user, String,
|
116
116
|
description: "The user that should own the client.rb file and the configuration directory if it needs to be created. Note: The configuration directory will not be created if it already exists, which allows you to further control the setup of that directory outside of this resource."
|
@@ -29,7 +29,14 @@ class Chef
|
|
29
29
|
unified_mode true
|
30
30
|
provides :dsc_script
|
31
31
|
|
32
|
-
description
|
32
|
+
description <<~DESC
|
33
|
+
Many DSC resources are comparable to built-in #{ChefUtils::Dist::Infra::PRODUCT} resources. For example, both DSC and #{ChefUtils::Dist::Infra::PRODUCT}
|
34
|
+
have file, package, and service resources. The dsc_script resource is most useful for those DSC resources that do not have a direct comparison to a
|
35
|
+
resource in #{ChefUtils::Dist::Infra::PRODUCT}, such as the Archive resource, a custom DSC resource, an existing DSC script that performs an important
|
36
|
+
task, and so on. Use the dsc_script resource to embed the code that defines a DSC configuration directly within a #{ChefUtils::Dist::Infra::PRODUCT} recipe.
|
37
|
+
|
38
|
+
Warning: The **dsc_script** resource may not be used with the 32 bit Chef Infra client. It must be executed from a 64 bit Chef Infra client.
|
39
|
+
DESC
|
33
40
|
|
34
41
|
default_action :run
|
35
42
|
|
@@ -131,18 +131,18 @@ class Chef
|
|
131
131
|
# darwin
|
132
132
|
declare_resource(:execute, "set HostName via scutil") do
|
133
133
|
command "/usr/sbin/scutil --set HostName #{new_resource.hostname}"
|
134
|
-
not_if { shell_out
|
134
|
+
not_if { shell_out("/usr/sbin/scutil --get HostName").stdout.chomp == new_resource.hostname }
|
135
135
|
notifies :reload, "ohai[reload hostname]"
|
136
136
|
end
|
137
137
|
declare_resource(:execute, "set ComputerName via scutil") do
|
138
138
|
command "/usr/sbin/scutil --set ComputerName #{new_resource.hostname}"
|
139
|
-
not_if { shell_out
|
139
|
+
not_if { shell_out("/usr/sbin/scutil --get ComputerName").stdout.chomp == new_resource.hostname }
|
140
140
|
notifies :reload, "ohai[reload hostname]"
|
141
141
|
end
|
142
142
|
shortname = new_resource.hostname[/[^\.]*/]
|
143
143
|
declare_resource(:execute, "set LocalHostName via scutil") do
|
144
144
|
command "/usr/sbin/scutil --set LocalHostName #{shortname}"
|
145
|
-
not_if { shell_out
|
145
|
+
not_if { shell_out("/usr/sbin/scutil --get LocalHostName").stdout.chomp == shortname }
|
146
146
|
notifies :reload, "ohai[reload hostname]"
|
147
147
|
end
|
148
148
|
when linux?
|
@@ -169,8 +169,8 @@ class Chef
|
|
169
169
|
elsif module_name.nil?
|
170
170
|
raise Exceptions::ValidationFailed,
|
171
171
|
"#helpers requires either a module name or inline module code as a block.\n" +
|
172
|
-
|
173
|
-
|
172
|
+
"e.g.: helpers do; helper_code; end;\n" +
|
173
|
+
"OR: helpers(MyHelpersModule)"
|
174
174
|
else
|
175
175
|
raise Exceptions::ValidationFailed,
|
176
176
|
"Argument to #helpers must be a module. You gave #{module_name.inspect} (#{module_name.class})"
|
@@ -87,6 +87,11 @@ class Chef
|
|
87
87
|
description: "Ensure that sensitive resource data is not logged by the #{ChefUtils::Dist::Infra::CLIENT}.",
|
88
88
|
default: lazy { pfx_password ? true : false }, skip_docs: true
|
89
89
|
|
90
|
+
property :exportable, [TrueClass, FalseClass],
|
91
|
+
description: "Ensure that imported pfx certificate is exportable. Please provide 'true' if you want the certificate to be exportable.",
|
92
|
+
default: false,
|
93
|
+
introduced: "16.8"
|
94
|
+
|
90
95
|
action :create do
|
91
96
|
description "Creates or updates a certificate."
|
92
97
|
|
@@ -162,8 +167,9 @@ class Chef
|
|
162
167
|
end
|
163
168
|
|
164
169
|
def add_pfx_cert
|
170
|
+
exportable = new_resource.exportable ? 1 : 0
|
165
171
|
store = ::Win32::Certstore.open(new_resource.store_name)
|
166
|
-
store.add_pfx(new_resource.source, new_resource.pfx_password)
|
172
|
+
store.add_pfx(new_resource.source, new_resource.pfx_password, exportable)
|
167
173
|
end
|
168
174
|
|
169
175
|
def delete_cert
|
@@ -131,7 +131,7 @@ class Chef
|
|
131
131
|
else
|
132
132
|
raise Chef::Exceptions::InvalidResourceSpecification,
|
133
133
|
"The object `#{query_object.inspect}' is not valid for resource collection lookup. " +
|
134
|
-
|
134
|
+
"Use a String like `resource_type[resource_name]' or a Chef::Resource object"
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
@@ -16,36 +16,34 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require_relative "
|
19
|
+
require_relative "../../mixin/powershell_exec"
|
20
20
|
|
21
21
|
class Chef::Util::DSC
|
22
22
|
class ConfigurationGenerator
|
23
|
+
include Chef::Mixin::PowershellExec
|
24
|
+
|
23
25
|
def initialize(node, config_directory)
|
24
26
|
@node = node
|
25
27
|
@config_directory = config_directory
|
26
28
|
end
|
27
29
|
|
28
|
-
def configuration_document_from_script_code(code, configuration_flags, imports
|
30
|
+
def configuration_document_from_script_code(code, configuration_flags, imports)
|
29
31
|
Chef::Log.trace("DSC: DSC code:\n '#{code}'")
|
30
32
|
generated_script_path = write_document_generation_script(code, "chef_dsc", imports)
|
31
33
|
begin
|
32
|
-
configuration_document_from_script_path(generated_script_path, "chef_dsc", configuration_flags
|
34
|
+
configuration_document_from_script_path(generated_script_path, "chef_dsc", configuration_flags)
|
33
35
|
ensure
|
34
36
|
::FileUtils.rm(generated_script_path)
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
|
-
def configuration_document_from_script_path(script_path, configuration_name, configuration_flags
|
40
|
+
def configuration_document_from_script_path(script_path, configuration_name, configuration_flags)
|
39
41
|
validate_configuration_name!(configuration_name)
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
configuration_document_generation_code(script_path, configuration_name)
|
44
|
-
)
|
45
|
-
|
46
|
-
merged_configuration_flags = get_merged_configuration_flags!(configuration_flags, configuration_name)
|
43
|
+
config_generation_code = configuration_document_generation_code(script_path, configuration_name)
|
44
|
+
switches_string = command_switches_string(get_merged_configuration_flags!(configuration_flags, configuration_name))
|
47
45
|
|
48
|
-
|
46
|
+
powershell_exec!("#{config_generation_code} #{switches_string}")
|
49
47
|
configuration_document_location = find_configuration_document(configuration_name)
|
50
48
|
|
51
49
|
unless configuration_document_location
|
@@ -59,6 +57,49 @@ class Chef::Util::DSC
|
|
59
57
|
|
60
58
|
protected
|
61
59
|
|
60
|
+
def validate_switch_name!(switch_parameter_name)
|
61
|
+
unless switch_parameter_name.match?(/\A[A-Za-z]+[_a-zA-Z0-9]*\Z/)
|
62
|
+
raise ArgumentError, "`#{switch_parameter_name}` is not a valid PowerShell cmdlet switch parameter name"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def escape_parameter_value(parameter_value)
|
67
|
+
parameter_value.gsub(/(`|'|"|#)/, '`\1')
|
68
|
+
end
|
69
|
+
|
70
|
+
def escape_string_parameter_value(parameter_value)
|
71
|
+
"'#{escape_parameter_value(parameter_value)}'"
|
72
|
+
end
|
73
|
+
|
74
|
+
def command_switches_string(switches)
|
75
|
+
command_switches = switches.map do |switch_name, switch_value|
|
76
|
+
if switch_name.class != Symbol
|
77
|
+
raise ArgumentError, "Invalid type `#{switch_name} `for PowerShell switch '#{switch_name}'. The switch must be specified as a Symbol'"
|
78
|
+
end
|
79
|
+
|
80
|
+
validate_switch_name!(switch_name)
|
81
|
+
|
82
|
+
switch_argument = ""
|
83
|
+
switch_present = true
|
84
|
+
|
85
|
+
case switch_value
|
86
|
+
when Numeric, Float
|
87
|
+
switch_argument = switch_value.to_s
|
88
|
+
when FalseClass
|
89
|
+
switch_present = false
|
90
|
+
when TrueClass
|
91
|
+
when String
|
92
|
+
switch_argument = escape_string_parameter_value(switch_value)
|
93
|
+
else
|
94
|
+
raise ArgumentError, "Invalid argument type `#{switch_value.class}` specified for PowerShell switch `:#{switch_name}`. Arguments to PowerShell must be of type `String`, `Numeric`, `Float`, `FalseClass`, or `TrueClass`"
|
95
|
+
end
|
96
|
+
|
97
|
+
switch_present ? ["-#{switch_name.to_s.downcase}", switch_argument].join(" ").strip : ""
|
98
|
+
end
|
99
|
+
|
100
|
+
command_switches.join(" ")
|
101
|
+
end
|
102
|
+
|
62
103
|
# From PowerShell error help for the Configuration language element:
|
63
104
|
# Standard names may only contain letters (a-z, A-Z), numbers (0-9), and underscore (_).
|
64
105
|
# The name may not be null or empty, and should start with a letter.
|
@@ -75,15 +75,15 @@ class Chef
|
|
75
75
|
#
|
76
76
|
|
77
77
|
def self.parse(lcm_output, test_dsc_configuration)
|
78
|
+
lcm_output = String(lcm_output).split("\n")
|
78
79
|
test_dsc_configuration ? test_dsc_parser(lcm_output) : what_if_parser(lcm_output)
|
79
80
|
end
|
80
81
|
|
81
82
|
def self.test_dsc_parser(lcm_output)
|
82
|
-
lcm_output ||= ""
|
83
83
|
current_resource = {}
|
84
84
|
|
85
85
|
resources = []
|
86
|
-
lcm_output.
|
86
|
+
lcm_output.each do |line|
|
87
87
|
op_action , op_value = line.strip.split(":")
|
88
88
|
op_action&.strip!
|
89
89
|
case op_action
|
@@ -107,11 +107,10 @@ class Chef
|
|
107
107
|
end
|
108
108
|
|
109
109
|
def self.what_if_parser(lcm_output)
|
110
|
-
lcm_output ||= ""
|
111
110
|
current_resource = {}
|
112
111
|
|
113
112
|
resources = []
|
114
|
-
lcm_output.
|
113
|
+
lcm_output.each do |line|
|
115
114
|
op_action, op_type, info = parse_line(line)
|
116
115
|
|
117
116
|
case op_action
|