summaryrefslogtreecommitdiff
path: root/lib/chef/mixin/powershell_exec.rb
diff options
context:
space:
mode:
authorStuart Preston <stuart@chef.io>2018-03-09 10:02:10 -0800
committerStuart Preston <stuart@chef.io>2018-03-09 10:02:10 -0800
commit0875f93aad1680cb6346ff98d7cc1291c69e3e9e (patch)
tree16c9f4cff742ba4cc058aab9206370a7bb4d5102 /lib/chef/mixin/powershell_exec.rb
parente3bbbb4cbe7f8d0a6f15416f4b9bf86e3ea83dbb (diff)
downloadchef-sp/powershell_exec.tar.gz
Addressing feedback, adding docs and examplessp/powershell_exec
Signed-off-by: Stuart Preston <stuart@chef.io>
Diffstat (limited to 'lib/chef/mixin/powershell_exec.rb')
-rw-r--r--lib/chef/mixin/powershell_exec.rb69
1 files changed, 69 insertions, 0 deletions
diff --git a/lib/chef/mixin/powershell_exec.rb b/lib/chef/mixin/powershell_exec.rb
index 4e276b307d..cdd5450fa3 100644
--- a/lib/chef/mixin/powershell_exec.rb
+++ b/lib/chef/mixin/powershell_exec.rb
@@ -17,6 +17,75 @@
require "chef/powershell"
+# The powershell_exec mixin provides in-process access to PowerShell engine via
+# a COM interop (installed by the Chef Client installer).
+#
+# powershell_exec returns a Chef::PowerShell object that provides 3 methods:
+#
+# .result - returns a hash representing the results returned by executing the
+# PowerShell script block
+# .errors - this is an array of string containing any messages written to the
+# PowerShell error stream during execution
+# .error? - returns true if there were error messages written to the PowerShell
+# error stream during execution
+#
+# Some examples of usage:
+#
+# > powershell_exec("(Get-Item c:\\windows\\system32\\w32time.dll).VersionInfo"
+# ).result["FileVersion"]
+# => "10.0.14393.0 (rs1_release.160715-1616)"
+#
+# > powershell_exec("(get-process ruby).Mainmodule").result["FileName"]
+# => C:\\opscode\\chef\\embedded\\bin\\ruby.exe"
+#
+# > powershell_exec("$a = $true; $a").result
+# => true
+#
+# > powershell_exec("not-found").errors
+# => ["ObjectNotFound: (not-found:String) [], CommandNotFoundException: The
+# term 'not-found' is not recognized as the name of a cmdlet, function, script
+# file, or operable program. Check the spelling of the name, or if a path was
+# included, verify that the path is correct and try again. (at <ScriptBlock>,
+# <No file>: line 1)"]
+#
+# > powershell_exec("not-found").error?
+# => true
+#
+# > powershell_exec("get-item c:\\notfound -erroraction stop")
+# WIN32OLERuntimeError: (in OLE method `ExecuteScript': )
+# OLE error code:80131501 in System.Management.Automation
+# The running command stopped because the preference variable
+# "ErrorActionPreference" or common parameter is set to Stop: Cannot find
+# path 'C:\notfound' because it does not exist.
+#
+# *Why use this and not powershell_out?* Startup time to invoke the PowerShell
+# engine is much faster (over 7X faster in tests) than writing the PowerShell
+# to disk, shelling out to powershell.exe and retrieving the .stdout or .stderr
+# methods afterwards. Additionally we are able to have a higher fidelity
+# conversation with PowerShell because we are now working with the objects that
+# are returned by the script, rather than having to parse the stdout of
+# powershell.exe to get a result.
+#
+# *How does this work?* In .NET terms, when you run a PowerShell script block
+# through the engine, behind the scenes you get a Collection<PSObject> returned
+# and simply we are serializing this, adding any errors that were generated to
+# a custom JSON string transferred in memory to Ruby. The easiest way to
+# develop for this approach is to imagine that the last thing that happens in
+# your PowerShell script block is "ConvertTo-Json". That's exactly what we are
+# doing here behind the scenes.
+#
+# There are a handful of current limitations with this approach:
+# - Windows UAC elevation is controlled by the token assigned to the account
+# that Ruby.exe is running under.
+# - Terminating errors will result in a WIN32OLERuntimeError and typically are
+# handled as an exception.
+# - There are no return/error codes, as we are not shelling out to
+# powershell.exe but calling a method inline, no errors codes are returned.
+# - There is no settable timeout on powershell_exec method execution.
+# - It is not possible to impersonate another user running powershell, the
+# credentials of the user running Chef Client are used.
+#
+
class Chef
module Mixin
module PowershellExec