diff options
author | nimesh-msys <nimesh.patni@msystechnologies.com> | 2018-07-23 16:17:20 +0530 |
---|---|---|
committer | nimesh-msys <nimesh.patni@msystechnologies.com> | 2018-07-23 17:27:13 +0530 |
commit | 4b5f73868ea131780ac29c3b8d6dfb7506b02afa (patch) | |
tree | 49e0308aa32cb62cfd3a3c50b925eaa41d0dbb62 | |
parent | 1bd742d6833a27c685907c414c3bb9c16d543bdd (diff) | |
download | chef-4b5f73868ea131780ac29c3b8d6dfb7506b02afa.tar.gz |
Handling quotes in Windows Task commands
- Added a custom method to split the command and its arguments
- Checked the beaviour when they are inclusive of single/double quotes
- Added their specs to test the functionality. Covered a [tpec](https://github.com/chef/chef/compare/sp/7413)
Fixes: MSYS-855
Signed-off-by: nimesh-msys <nimesh.patni@msystechnologies.com>
-rw-r--r-- | chef-config/lib/chef-config/path_helper.rb | 23 | ||||
-rw-r--r-- | lib/chef/provider/windows_task.rb | 4 | ||||
-rw-r--r-- | spec/functional/resource/windows_task_spec.rb | 32 |
3 files changed, 49 insertions, 10 deletions
diff --git a/chef-config/lib/chef-config/path_helper.rb b/chef-config/lib/chef-config/path_helper.rb index 053c7a3c32..f1dc47a489 100644 --- a/chef-config/lib/chef-config/path_helper.rb +++ b/chef-config/lib/chef-config/path_helper.rb @@ -295,5 +295,28 @@ module ChefConfig ChefConfig.logger.error("Cannot write to a SIP Path on OS X 10.11+") false end + + # Splits a string into an array of tokens as commands and arguments + # + # str = 'command with "some arguments"' + # split_args(str) => ["command", "with", "\"some arguments\""] + # + def self.split_args(line) + cmd_args = [] + field = "" + line.scan(/\s*(?>([^\s\\"]+|"([^"]*)"|'([^']*)')|(\S))(\s|\z)?/m) do |word, within_dq, within_sq, esc, sep| + + # Appand the string with Word & Escape Character + field << (word || esc.gsub(/\\(.)/, '\\1')) + + # Re-build the field when any whitespace character or + # End of string is encountered + if sep + cmd_args << field + field = "" + end + end + cmd_args + end end end diff --git a/lib/chef/provider/windows_task.rb b/lib/chef/provider/windows_task.rb index 4fb4817020..b1c59ec41c 100644 --- a/lib/chef/provider/windows_task.rb +++ b/lib/chef/provider/windows_task.rb @@ -21,6 +21,7 @@ require "rexml/document" require "iso8601" require "chef/mixin/powershell_out" require "chef/provider" +require "chef/util/path_helper" require "win32/taskscheduler" if Chef::Platform.windows? class Chef @@ -229,8 +230,7 @@ class Chef # seprated command arguments from :command property def set_command_and_arguments - new_resource.command = new_resource.command.gsub(/\\/, '\&\&') - cmd, *args = Shellwords.split(new_resource.command) + cmd, *args = Chef::Util::PathHelper.split_args(new_resource.command) new_resource.command = cmd new_resource.command_arguments = args.join(" ") end diff --git a/spec/functional/resource/windows_task_spec.rb b/spec/functional/resource/windows_task_spec.rb index 05f46d20ce..a4cee114f4 100644 --- a/spec/functional/resource/windows_task_spec.rb +++ b/spec/functional/resource/windows_task_spec.rb @@ -61,14 +61,14 @@ describe Chef::Resource::WindowsTask, :windows_only do expect(subject).not_to be_updated_by_last_action end - it "creates scheduled task and sets command arguments" do + it "creates scheduled task and sets command arguments when arguments inclusive single quotes" do subject.command "chef-client -W -L 'C:\\chef\\chef-ad-join.log'" call_for_create_action # loading current resource again to check new task is creted and it matches task parameters current_resource = call_for_load_current_resource expect(current_resource.exists).to eq(true) expect(current_resource.task.application_name).to eq("chef-client") - expect(current_resource.task.parameters).to eq("-W -L C:\\\\chef\\\\chef-ad-join.log") + expect(current_resource.task.parameters).to eq("-W -L 'C:\\chef\\chef-ad-join.log'") end it "does not converge the resource if it is already converged" do @@ -79,20 +79,36 @@ describe Chef::Resource::WindowsTask, :windows_only do expect(subject).not_to be_updated_by_last_action end - it "creates scheduled task and sets command arguments" do - subject.command '"C:\\Program Files\\example\program.exe" -arg1 --arg2' + it "creates scheduled task and sets command arguments with spaces in command" do + subject.command '"C:\\Program Files\\example\\program.exe" -arg1 --arg2' call_for_create_action - # loading current resource again to check new task is creted and it matches task parameters current_resource = call_for_load_current_resource expect(current_resource.exists).to eq(true) - expect(current_resource.task.application_name).to eq("C:\\Program Files\\example\\program.exe") + expect(current_resource.task.application_name).to eq('"C:\\Program Files\\example\\program.exe"') expect(current_resource.task.parameters).to eq("-arg1 --arg2") end it "does not converge the resource if it is already converged" do - subject.command '"C:\\Program Files\\example\program.exe" -arg1 --arg2' + subject.command '"C:\\Program Files\\example\\program.exe" -arg1 --arg2' + subject.run_action(:create) + subject.command '"C:\\Program Files\\example\\program.exe" -arg1 --arg2' + subject.run_action(:create) + expect(subject).not_to be_updated_by_last_action + end + + it "creates scheduled task and sets command arguments with spaces in arguments" do + subject.command 'powershell.exe -file "C:\\Program Files\\app\\script.ps1"' + call_for_create_action + current_resource = call_for_load_current_resource + expect(current_resource.exists).to eq(true) + expect(current_resource.task.application_name).to eq("powershell.exe") + expect(current_resource.task.parameters).to eq('-file "C:\\Program Files\\app\\script.ps1"') + end + + it "does not converge the resource if it is already converged" do + subject.command 'powershell.exe -file "C:\\Program Files\\app\\script.ps1"' subject.run_action(:create) - subject.command '"C:\\Program Files\\example\program.exe" -arg1 --arg2' + subject.command 'powershell.exe -file "C:\\Program Files\\app\\script.ps1"' subject.run_action(:create) expect(subject).not_to be_updated_by_last_action end |