diff options
-rw-r--r-- | .gitattributes | 1 | ||||
-rw-r--r-- | RELEASE_NOTES.md | 6 | ||||
-rw-r--r-- | appveyor.yml | 1 | ||||
-rw-r--r-- | appveyor_registry.reg | 29 | ||||
-rw-r--r-- | distro/powershell/chef/Chef.PowerShell.dll | bin | 0 -> 6144 bytes | |||
-rw-r--r-- | distro/powershell/chef/Newtonsoft.Json.dll | bin | 0 -> 664576 bytes | |||
-rw-r--r-- | lib/chef/dsl/universal.rb | 2 | ||||
-rw-r--r-- | lib/chef/mixin/powershell_exec.rb | 36 | ||||
-rw-r--r-- | lib/chef/powershell.rb | 55 | ||||
-rw-r--r-- | omnibus/Gemfile | 2 | ||||
-rw-r--r-- | omnibus/Gemfile.lock | 2 | ||||
-rw-r--r-- | omnibus/resources/chef/msi/source.wxs.erb | 30 | ||||
-rw-r--r-- | spec/unit/mixin/powershell_exec_spec.rb | 43 |
13 files changed, 205 insertions, 2 deletions
diff --git a/.gitattributes b/.gitattributes index bb9914a8b6..3122278bd5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,3 +4,4 @@ distro/common/html/* merge=ignore distro/common/man/man1/* merge=ignore distro/common/man/man8/* merge=ignore lib/chef/version.rb merge=ignore +*.reg text eol=crlf
\ No newline at end of file diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 71f1909145..15e95c736a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -2,6 +2,12 @@ _This file holds "in progress" release notes for the current release under devel # Unreleased +# Chef Client Release Notes 14.TBC: + +## New Windows PowerShell mixin `powershell_exec` + +Since our supported Windows platforms can all run .NET Framework 4.0 and PowerShell 4.0 we have taken time to add a new interop that will allow faster and safer interactions with the system PowerShell. You will be able to use the `powershell_exec` mixin in most places where you would have previously used `powershell_out`. + # Chef Client Release Notes 13.7: ## The `windows_task` Resource should be better behaved diff --git a/appveyor.yml b/appveyor.yml index ddc6009bf8..19b127fa98 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,6 +23,7 @@ branches: install: - systeminfo - winrm quickconfig -q + - regedit /s c:\projects\chef\appveyor_registry.reg - SET PATH=C:\Ruby%ruby_version%\bin;%PATH% - echo %PATH% - appveyor DownloadFile http://curl.haxx.se/ca/cacert.pem -FileName C:\cacert.pem diff --git a/appveyor_registry.reg b/appveyor_registry.reg new file mode 100644 index 0000000000..293e98dd07 --- /dev/null +++ b/appveyor_registry.reg @@ -0,0 +1,29 @@ +REGEDIT4 + +[HKEY_CLASSES_ROOT\Chef.PowerShell] +@="Chef.PowerShell" + +[HKEY_CLASSES_ROOT\Chef.PowerShell\CLSID] +@="{9008CA83-83E4-41FF-9C07-696E2CC47B52}" + +[HKEY_CLASSES_ROOT\CLSID\{9008CA83-83E4-41FF-9C07-696E2CC47B52}] +@="Chef.PowerShell" + +[HKEY_CLASSES_ROOT\CLSID\{9008CA83-83E4-41FF-9C07-696E2CC47B52}\InprocServer32] +@="c:\\windows\\system32\\mscoree.dll" +"ThreadingModel"="Both" +"Class"="Chef.PowerShell" +"Assembly"="Chef.PowerShell, Version=1.0.14.0, Culture=neutral, PublicKeyToken=7def9f799d039a95" +"RuntimeVersion"="v4.0.30319" +"CodeBase"="file:///C:/projects/chef/distro/powershell/chef/Chef.PowerShell.dll" + +[HKEY_CLASSES_ROOT\CLSID\{9008CA83-83E4-41FF-9C07-696E2CC47B52}\InprocServer32\1.0.0.0] +"Class"="Chef.PowerShell" +"Assembly"="Chef.PowerShell, Version=1.0.14.0, Culture=neutral, PublicKeyToken=7def9f799d039a95" +"RuntimeVersion"="v4.0.30319" +"CodeBase"="file:///C:/projects/chef/distro/powershell/chef/Chef.PowerShell.dll" + +[HKEY_CLASSES_ROOT\CLSID\{9008CA83-83E4-41FF-9C07-696E2CC47B52}\ProgId] +@="Chef.PowerShell" + +[HKEY_CLASSES_ROOT\CLSID\{9008CA83-83E4-41FF-9C07-696E2CC47B52}\Implemented Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}] diff --git a/distro/powershell/chef/Chef.PowerShell.dll b/distro/powershell/chef/Chef.PowerShell.dll Binary files differnew file mode 100644 index 0000000000..9aa1c62850 --- /dev/null +++ b/distro/powershell/chef/Chef.PowerShell.dll diff --git a/distro/powershell/chef/Newtonsoft.Json.dll b/distro/powershell/chef/Newtonsoft.Json.dll Binary files differnew file mode 100644 index 0000000000..1971a35679 --- /dev/null +++ b/distro/powershell/chef/Newtonsoft.Json.dll diff --git a/lib/chef/dsl/universal.rb b/lib/chef/dsl/universal.rb index 6e3d162b6f..f3b79b1d60 100644 --- a/lib/chef/dsl/universal.rb +++ b/lib/chef/dsl/universal.rb @@ -18,6 +18,7 @@ # require "chef/dsl/platform_introspection" +require "chef/mixin/powershell_exec" require "chef/mixin/powershell_out" require "chef/mixin/shell_out" @@ -43,6 +44,7 @@ class Chef # module Universal include Chef::DSL::PlatformIntrospection + include Chef::Mixin::PowershellExec include Chef::Mixin::PowershellOut include Chef::Mixin::ShellOut end diff --git a/lib/chef/mixin/powershell_exec.rb b/lib/chef/mixin/powershell_exec.rb new file mode 100644 index 0000000000..4e276b307d --- /dev/null +++ b/lib/chef/mixin/powershell_exec.rb @@ -0,0 +1,36 @@ +# +# Author:: Stuart Preston (<stuart@chef.io>) +# Copyright:: Copyright 2018, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "chef/powershell" + +class Chef + module Mixin + module PowershellExec + # Run a command under PowerShell via a managed (.NET) COM interop API. + # This implementation requires the managed dll to be registered on the + # target machine. + # + # Requires: .NET Framework 4.0 or higher on the target machine. + # + # @param script [String] script to run + # @return [Chef::PowerShell] output + def powershell_exec(script) + Chef::PowerShell.new(script) + end + end + end +end diff --git a/lib/chef/powershell.rb b/lib/chef/powershell.rb new file mode 100644 index 0000000000..0d3f82590a --- /dev/null +++ b/lib/chef/powershell.rb @@ -0,0 +1,55 @@ +# +# Author:: Stuart Preston (<stuart@chef.io>) +# Copyright:: Copyright 2018, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "chef/json_compat" +require "win32ole" if RUBY_PLATFORM =~ /mswin|mingw32|windows/ + +class Chef + class PowerShell + + attr_reader :result + attr_reader :errors + + # Run a command under PowerShell via a managed (.NET) COM interop API. + # This implementation requires the managed dll to be registered on the + # target machine. + # + # Requires: .NET Framework 4.0 or higher on the target machine. + # + # @param script [String] script to run + # @return [Object] output + def initialize(script) + raise "Chef::PowerShell can only be used on the Windows platform." unless RUBY_PLATFORM =~ /mswin|mingw32|windows/ + exec(script) + end + + def error? + return true if errors.count > 0 + false + end + + private + + def exec(script) + ps = WIN32OLE.new("Chef.PowerShell") + outcome = ps.ExecuteScript(script) + hashed_outcome = Chef::JSONCompat.parse(outcome) + @result = Chef::JSONCompat.parse(hashed_outcome["result"]) + @errors = hashed_outcome["errors"] + end + end +end diff --git a/omnibus/Gemfile b/omnibus/Gemfile index 0de03a5ea2..5457f0f40b 100644 --- a/omnibus/Gemfile +++ b/omnibus/Gemfile @@ -18,7 +18,7 @@ group :development do # Use Test Kitchen with Vagrant for converging the build environment gem "test-kitchen", "~> 1.13" - gem "kitchen-vagrant", "~> 0.19.0" + gem "kitchen-vagrant", "~> 1.3.1" gem "winrm-fs", "~> 1.0" gem "pry" gem "pry-byebug" diff --git a/omnibus/Gemfile.lock b/omnibus/Gemfile.lock index 1c6856f758..4ca8eb4536 100644 --- a/omnibus/Gemfile.lock +++ b/omnibus/Gemfile.lock @@ -258,7 +258,7 @@ PLATFORMS DEPENDENCIES berkshelf (~> 4.0) - kitchen-vagrant (~> 0.19.0) + kitchen-vagrant (~> 1.3.1) ohai (~> 13.0) omnibus! omnibus-software! diff --git a/omnibus/resources/chef/msi/source.wxs.erb b/omnibus/resources/chef/msi/source.wxs.erb index 2249262b1f..5977e9283b 100644 --- a/omnibus/resources/chef/msi/source.wxs.erb +++ b/omnibus/resources/chef/msi/source.wxs.erb @@ -151,6 +151,35 @@ <Environment Id="ChefPSModulePathEnvironment" Name="PSModulePath" Action="set" Part="last" System="yes" Value="[PSMODULES]" /> </Component> + <Component Id="ChefPowerShellRegistryEntries" Guid="{3715B7AB-C3CA-4C69-8FAF-79C8CF58FD89}"> + <RegistryKey Root="HKCR" Key="Chef.PowerShell"> + <RegistryValue Type="string" Value="Chef.PowerShell" /> + </RegistryKey> + <RegistryKey Root="HKCR" Key="Chef.PowerShell\CLSID"> + <RegistryValue Type="string" Value="{9008CA83-83E4-41FF-9C07-696E2CC47B52}" /> + </RegistryKey> + <RegistryKey Root="HKCR" Key="CLSID\{9008CA83-83E4-41FF-9C07-696E2CC47B52}"> + <RegistryValue Type="string" Value="Chef.PowerShell" /> + </RegistryKey> + <RegistryKey Root="HKCR" Key="CLSID\{9008CA83-83E4-41FF-9C07-696E2CC47B52}\InprocServer32"> + <RegistryValue Type="string" Value="[System64Folder]mscoree.dll" /> + <RegistryValue Type="string" Name="ThreadingModel" Value="Both" /> + <RegistryValue Type="string" Name="Class" Value="Chef.PowerShell" /> + <RegistryValue Type="string" Name="Assembly" Value="Chef.PowerShell, Version=1.0.14.0, Culture=neutral, PublicKeyToken=7def9f799d039a95" /> + <RegistryValue Type="string" Name="RuntimeVersion" Value="v4.0.30319" /> + <RegistryValue Type="string" Name="CodeBase" Value="[PSMODULES]chef\Chef.PowerShell.dll" /> + </RegistryKey> + <RegistryKey Root="HKCR" Key="CLSID\{9008CA83-83E4-41FF-9C07-696E2CC47B52}\InprocServer32\1.0.0.0"> + <RegistryValue Type="string" Name="Class" Value="Chef.PowerShell" /> + <RegistryValue Type="string" Name="Assembly" Value="Chef.PowerShell, Version=1.0.14.0, Culture=neutral, PublicKeyToken=7def9f799d039a95" /> + <RegistryValue Type="string" Name="RuntimeVersion" Value="v4.0.30319" /> + <RegistryValue Type="string" Name="CodeBase" Value="[PSMODULES]chef\Chef.PowerShell.dll" /> + </RegistryKey> + <RegistryKey Root="HKCR" Key="CLSID\{9008CA83-83E4-41FF-9C07-696E2CC47B52}\ProgId"> + <RegistryValue Type="string" Value="Chef.PowerShell" /> + </RegistryKey> + <RegistryKey Root="HKCR" Key="CLSID\{9008CA83-83E4-41FF-9C07-696E2CC47B52}\Implemented Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}" /> + </Component> </Directory> <Directory Id="EMBEDDED" Name="embedded" > <Directory Id="EMBEDDEDBIN" Name="bin" > @@ -197,6 +226,7 @@ <ComponentRef Id="ChefClientPath" /> <ComponentRef Id="CONFIGLOCATIONDIR" /> <ComponentRef Id="ChefClientLog" /> + <ComponentRef Id="ChefPowerShellRegistryEntries" /> </Feature> <Feature Id="ChefPSModuleFeature" Title="!(loc.FeaturePSModuleName)" Level="1000" AllowAdvertise="no"> diff --git a/spec/unit/mixin/powershell_exec_spec.rb b/spec/unit/mixin/powershell_exec_spec.rb new file mode 100644 index 0000000000..72619bdc8a --- /dev/null +++ b/spec/unit/mixin/powershell_exec_spec.rb @@ -0,0 +1,43 @@ +# +# Author:: Stuart Preston (<stuart@chef.io>) +# Copyright:: Copyright 2018, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "spec_helper" +require "chef/mixin/powershell_exec" + +describe Chef::Mixin::PowershellExec, :windows_only do + let(:powershell_mixin) { Class.new { include Chef::Mixin::PowershellExec } } + subject(:object) { powershell_mixin.new } + + describe "#powershell_exec" do + it "runs a basic command and returns a Chef::PowerShell object" do + expect(object.powershell_exec("$PSVersionTable")).to be_kind_of(Chef::PowerShell) + end + + it "runs a command that fails with a non-terminating error and can trap the error via .error?" do + execution = object.powershell_exec("this-should-error") + expect(execution.error?).to eql(true) + end + + it "runs a command that fails with a non-terminating error and can list the errors" do + execution = object.powershell_exec("this-should-error") + expect(execution.errors).to be_a_kind_of(Array) + expect(execution.errors[0]).to be_a_kind_of(String) + expect(execution.errors[0]).to include("CommandNotFoundException") + end + end +end |