chef 16.5.77 → 16.6.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/lib/chef/application/client.rb +6 -1
- data/lib/chef/client.rb +2 -31
- data/lib/chef/data_collector.rb +1 -1
- data/lib/chef/mixin/powershell_exec.rb +22 -10
- data/lib/chef/mixin/powershell_out.rb +12 -5
- data/lib/chef/node/mixin/immutablize_hash.rb +2 -0
- data/lib/chef/powershell.rb +3 -2
- data/lib/chef/provider/ifconfig.rb +1 -1
- data/lib/chef/provider/ifconfig/debian.rb +33 -15
- data/lib/chef/provider/ifconfig/redhat.rb +51 -17
- data/lib/chef/provider/powershell_script.rb +12 -1
- data/lib/chef/pwsh.rb +64 -0
- data/lib/chef/resource/apt_repository.rb +2 -3
- data/lib/chef/resource/chef_client_config.rb +313 -0
- data/lib/chef/resource/chef_client_cron.rb +5 -5
- data/lib/chef/resource/chef_client_scheduled_task.rb +4 -4
- data/lib/chef/resource/chef_client_systemd_timer.rb +5 -5
- data/lib/chef/resource/chef_sleep.rb +1 -1
- data/lib/chef/resource/cron/cron_d.rb +2 -2
- data/lib/chef/resource/kernel_module.rb +1 -1
- data/lib/chef/resource/launchd.rb +15 -15
- data/lib/chef/resource/mount.rb +1 -1
- data/lib/chef/resource/powershell_script.rb +7 -1
- data/lib/chef/resource/support/client.erb +65 -0
- data/lib/chef/resource/windows_audit_policy.rb +26 -24
- data/lib/chef/resources.rb +1 -0
- data/lib/chef/version.rb +1 -1
- data/spec/functional/mixin/powershell_out_spec.rb +9 -1
- data/spec/functional/resource/powershell_script_spec.rb +57 -14
- data/spec/spec_helper.rb +1 -0
- data/spec/support/platform_helpers.rb +6 -1
- data/spec/unit/mixin/powershell_exec_spec.rb +40 -3
- data/spec/unit/mixin/powershell_out_spec.rb +14 -0
- data/spec/unit/provider/powershell_script_spec.rb +11 -0
- data/spec/unit/resource/chef_client_config_spec.rb +137 -0
- data/spec/unit/resource/powershell_script_spec.rb +2 -2
- metadata +11 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9601a0e75782478aa0b49ba679d1636eefd626471cf89fdc1f3bc03ece08d0d9
|
4
|
+
data.tar.gz: 55a6507691792de235cecee29b666c915f8dfaa67d54c7928b5bf6b6843aee1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7123ac0cd41df9a3a5dd64f766e468f1e1ec3cfacd4a85bca99d2a2361154fa0db1cebdc6a09fc19594bcea77ea9bba8994a34e98be870fd7b8e0b9b527c04c4
|
7
|
+
data.tar.gz: 5474902d65ae70b1c4bf3698452c6ce6599fe741c49133e073f0bbc4eaefa51a73a3f1da64ab8a77cf0cff26567c2869ef9000a7617d383ef89f0bceb660d7f9
|
data/Gemfile
CHANGED
@@ -87,7 +87,7 @@ eval_gemfile("./Gemfile.local") if File.exist?("./Gemfile.local")
|
|
87
87
|
if RUBY_PLATFORM.match?(/mswin|mingw|windows/)
|
88
88
|
instance_eval do
|
89
89
|
ruby_exe_dir = RbConfig::CONFIG["bindir"]
|
90
|
-
assemblies = Dir.glob(File.expand_path("distro/ruby_bin_folder", __dir__) + "
|
90
|
+
assemblies = Dir.glob(File.expand_path("distro/ruby_bin_folder/#{ENV["PROCESSOR_ARCHITECTURE"]}", __dir__) + "**/*")
|
91
91
|
FileUtils.cp_r assemblies, ruby_exe_dir, verbose: false unless ENV["_BUNDLER_WINDOWS_DLLS_COPIED"]
|
92
92
|
ENV["_BUNDLER_WINDOWS_DLLS_COPIED"] = "1"
|
93
93
|
end
|
@@ -27,6 +27,7 @@ module Mixlib
|
|
27
27
|
autoload :Log, "mixlib/authentication"
|
28
28
|
end
|
29
29
|
end
|
30
|
+
autoload :Train, "train"
|
30
31
|
|
31
32
|
# DO NOT MAKE EDITS, see Chef::Application::Base
|
32
33
|
#
|
@@ -115,8 +116,12 @@ class Chef::Application::Client < Chef::Application::Base
|
|
115
116
|
Chef::Config.chef_zero.port = config[:chef_zero_port] if config[:chef_zero_port]
|
116
117
|
|
117
118
|
if config[:target] || Chef::Config.target
|
118
|
-
Chef::Config.target_mode.enabled = true
|
119
119
|
Chef::Config.target_mode.host = config[:target] || Chef::Config.target
|
120
|
+
if URI.parse(Chef::Config.target_mode.host).scheme
|
121
|
+
train_config = Train.unpack_target_from_uri(Chef::Config.target_mode.host)
|
122
|
+
Chef::Config.target_mode = train_config
|
123
|
+
end
|
124
|
+
Chef::Config.target_mode.enabled = true
|
120
125
|
Chef::Config.node_name = Chef::Config.target_mode.host unless Chef::Config.node_name
|
121
126
|
end
|
122
127
|
|
data/lib/chef/client.rb
CHANGED
@@ -251,11 +251,7 @@ class Chef
|
|
251
251
|
logger.debug("#{ChefUtils::Dist::Infra::CLIENT.capitalize} request_id: #{request_id}")
|
252
252
|
ENV["PATH"] = ChefUtils::DSL::DefaultPaths.default_paths if Chef::Config[:enforce_default_paths] || Chef::Config[:enforce_path_sanity]
|
253
253
|
|
254
|
-
|
255
|
-
get_ohai_data_remotely
|
256
|
-
else
|
257
|
-
run_ohai
|
258
|
-
end
|
254
|
+
run_ohai
|
259
255
|
|
260
256
|
unless Chef::Config[:solo_legacy_mode]
|
261
257
|
register
|
@@ -575,32 +571,6 @@ class Chef
|
|
575
571
|
end
|
576
572
|
end
|
577
573
|
|
578
|
-
#
|
579
|
-
# Populate the minimal ohai attributes defined in #run_ohai with data train collects.
|
580
|
-
#
|
581
|
-
# Eventually ohai may support colleciton of data.
|
582
|
-
#
|
583
|
-
def get_ohai_data_remotely
|
584
|
-
ohai.data[:fqdn] = if transport_connection.respond_to?(:hostname)
|
585
|
-
transport_connection.hostname
|
586
|
-
else
|
587
|
-
Chef::Config[:target_mode][:host]
|
588
|
-
end
|
589
|
-
if transport_connection.respond_to?(:os)
|
590
|
-
ohai.data[:platform] = transport_connection.os.name
|
591
|
-
ohai.data[:platform_version] = transport_connection.os.release
|
592
|
-
ohai.data[:os] = transport_connection.os.family_hierarchy[1]
|
593
|
-
ohai.data[:platform_family] = transport_connection.os.family
|
594
|
-
end
|
595
|
-
# train does not collect these specifically
|
596
|
-
# ohai.data[:machinename] = nil
|
597
|
-
# ohai.data[:hostname] = nil
|
598
|
-
# ohai.data[:os_version] = nil # kernel version
|
599
|
-
|
600
|
-
ohai.data[:ohai_time] = Time.now.to_f
|
601
|
-
events.ohai_completed(node)
|
602
|
-
end
|
603
|
-
|
604
574
|
#
|
605
575
|
# Run ohai plugins. Runs all ohai plugins unless minimal_ohai is specified.
|
606
576
|
#
|
@@ -613,6 +583,7 @@ class Chef
|
|
613
583
|
#
|
614
584
|
def run_ohai
|
615
585
|
filter = Chef::Config[:minimal_ohai] ? %w{fqdn machinename hostname platform platform_version ohai_time os os_version init_package} : nil
|
586
|
+
ohai.transport_connection = transport_connection if Chef::Config.target_mode?
|
616
587
|
ohai.all_plugins(filter)
|
617
588
|
events.ohai_completed(node)
|
618
589
|
end
|
data/lib/chef/data_collector.rb
CHANGED
@@ -16,11 +16,14 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
18
|
require_relative "../powershell"
|
19
|
+
require_relative "../pwsh"
|
19
20
|
|
20
|
-
# The powershell_exec mixin provides in-process access to PowerShell engine
|
21
|
-
# a COM interop (installed by the Chef Client installer).
|
21
|
+
# The powershell_exec mixin provides in-process access to the PowerShell engine.
|
22
22
|
#
|
23
|
-
# powershell_exec
|
23
|
+
# powershell_exec is initialized with a string that should be set to the script
|
24
|
+
# to run and also takes an optional interpreter argument which must be either
|
25
|
+
# :powershell (Windows PowerShell which is the default) or :pwsh (PowerShell
|
26
|
+
# Core). It will return a Chef::PowerShell object that provides 4 methods:
|
24
27
|
#
|
25
28
|
# .result - returns a hash representing the results returned by executing the
|
26
29
|
# PowerShell script block
|
@@ -42,6 +45,9 @@ require_relative "../powershell"
|
|
42
45
|
# > powershell_exec("$a = $true; $a").result
|
43
46
|
# => true
|
44
47
|
#
|
48
|
+
# > powershell_exec("$PSVersionTable", :pwsh).result["PSEdition"]
|
49
|
+
# => "Core"
|
50
|
+
#
|
45
51
|
# > powershell_exec("not-found").errors
|
46
52
|
# => ["ObjectNotFound: (not-found:String) [], CommandNotFoundException: The
|
47
53
|
# term 'not-found' is not recognized as the name of a cmdlet, function, script
|
@@ -90,22 +96,28 @@ require_relative "../powershell"
|
|
90
96
|
class Chef
|
91
97
|
module Mixin
|
92
98
|
module PowershellExec
|
93
|
-
# Run a command under PowerShell via a managed (.NET)
|
94
|
-
# This implementation requires the managed dll to be registered on the
|
95
|
-
# target machine.
|
99
|
+
# Run a command under PowerShell via a managed (.NET) API.
|
96
100
|
#
|
97
101
|
# Requires: .NET Framework 4.0 or higher on the target machine.
|
98
102
|
#
|
99
103
|
# @param script [String] script to run
|
104
|
+
# @param interpreter [Symbol] the interpreter type, `:powershell` or `:pwsh`
|
100
105
|
# @return [Chef::PowerShell] output
|
101
|
-
def powershell_exec(script)
|
102
|
-
|
106
|
+
def powershell_exec(script, interpreter = :powershell)
|
107
|
+
case interpreter
|
108
|
+
when :powershell
|
109
|
+
Chef::PowerShell.new(script)
|
110
|
+
when :pwsh
|
111
|
+
Chef::Pwsh.new(script)
|
112
|
+
else
|
113
|
+
raise ArgumentError, "Expected interpreter of :powershell or :pwsh"
|
114
|
+
end
|
103
115
|
end
|
104
116
|
|
105
117
|
# The same as the #powershell_exec method except this will raise
|
106
118
|
# Chef::PowerShell::CommandFailed if the command fails
|
107
|
-
def powershell_exec!(script)
|
108
|
-
cmd =
|
119
|
+
def powershell_exec!(script, interpreter = :powershell)
|
120
|
+
cmd = powershell_exec(script, interpreter)
|
109
121
|
cmd.error!
|
110
122
|
cmd
|
111
123
|
end
|
@@ -28,19 +28,24 @@ class Chef
|
|
28
28
|
# can be set to :i386 or :x86_64 to force the windows architecture.
|
29
29
|
#
|
30
30
|
# @param script [String] script to run
|
31
|
+
# @param interpreter [Symbol] the interpreter type, `:powershell` or `:pwsh`
|
31
32
|
# @param options [Hash] options hash
|
32
33
|
# @return [Mixlib::Shellout] mixlib-shellout object
|
33
34
|
def powershell_out(*command_args)
|
34
35
|
script = command_args.first
|
35
36
|
options = command_args.last.is_a?(Hash) ? command_args.last : nil
|
37
|
+
interpreter = command_args[1].is_a?(Symbol) ? command_args[1] : :powershell
|
36
38
|
|
37
|
-
|
39
|
+
raise ArgumentError, "Expected interpreter of :powershell or :pwsh" unless %i{powershell pwsh}.include?(interpreter)
|
40
|
+
|
41
|
+
run_command_with_os_architecture(script, interpreter, options)
|
38
42
|
end
|
39
43
|
|
40
44
|
# Run a command under powershell with the same API as shell_out!
|
41
45
|
# (raises exceptions on errors)
|
42
46
|
#
|
43
47
|
# @param script [String] script to run
|
48
|
+
# @param interpreter [Symbol] the interpreter type, `:powershell` or `:pwsh`
|
44
49
|
# @param options [Hash] options hash
|
45
50
|
# @return [Mixlib::Shellout] mixlib-shellout object
|
46
51
|
def powershell_out!(*command_args)
|
@@ -56,16 +61,17 @@ class Chef
|
|
56
61
|
# because chef-client runs as a 32-bit app on 64-bit windows).
|
57
62
|
#
|
58
63
|
# @param script [String] script to run
|
64
|
+
# @param interpreter [Symbol] the interpreter type, `:powershell` or `:pwsh`
|
59
65
|
# @param options [Hash] options hash
|
60
66
|
# @return [Mixlib::Shellout] mixlib-shellout object
|
61
|
-
def run_command_with_os_architecture(script, options)
|
67
|
+
def run_command_with_os_architecture(script, interpreter, options)
|
62
68
|
options ||= {}
|
63
69
|
options = options.dup
|
64
70
|
arch = options.delete(:architecture)
|
65
71
|
|
66
72
|
with_os_architecture(nil, architecture: arch) do
|
67
73
|
shell_out(
|
68
|
-
build_powershell_command(script),
|
74
|
+
build_powershell_command(script, interpreter),
|
69
75
|
**options
|
70
76
|
)
|
71
77
|
end
|
@@ -74,8 +80,9 @@ class Chef
|
|
74
80
|
# Helper to build a powershell command around the script to run.
|
75
81
|
#
|
76
82
|
# @param script [String] script to run
|
83
|
+
# @param interpreter [Symbol] the interpreter type, `:powershell` or `:pwsh`
|
77
84
|
# @return [String] powershell command to execute
|
78
|
-
def build_powershell_command(script)
|
85
|
+
def build_powershell_command(script, interpreter)
|
79
86
|
flags = [
|
80
87
|
# Hides the copyright banner at startup.
|
81
88
|
"-NoLogo",
|
@@ -91,7 +98,7 @@ class Chef
|
|
91
98
|
"-InputFormat None",
|
92
99
|
]
|
93
100
|
|
94
|
-
"
|
101
|
+
"#{interpreter}.exe #{flags.join(" ")} -Command \"#{script.gsub('"', '\"')}\""
|
95
102
|
end
|
96
103
|
end
|
97
104
|
end
|
data/lib/chef/powershell.rb
CHANGED
@@ -36,6 +36,7 @@ class Chef
|
|
36
36
|
def initialize(script)
|
37
37
|
raise "Chef::PowerShell can only be used on the Windows platform." unless RUBY_PLATFORM.match?(/mswin|mingw32|windows/)
|
38
38
|
|
39
|
+
@dll ||= "Chef.PowerShell.Wrapper.dll"
|
39
40
|
exec(script)
|
40
41
|
end
|
41
42
|
|
@@ -59,10 +60,10 @@ class Chef
|
|
59
60
|
raise Chef::PowerShell::CommandFailed, "Unexpected exit in PowerShell command: #{@errors}" if error?
|
60
61
|
end
|
61
62
|
|
62
|
-
|
63
|
+
protected
|
63
64
|
|
64
65
|
def exec(script)
|
65
|
-
FFI.ffi_lib
|
66
|
+
FFI.ffi_lib @dll
|
66
67
|
FFI.attach_function :execute_powershell, :ExecuteScript, [:string], :pointer
|
67
68
|
execution = FFI.execute_powershell(script).read_utf16string
|
68
69
|
hashed_outcome = Chef::JSONCompat.parse(execution)
|
@@ -236,7 +236,7 @@ class Chef
|
|
236
236
|
return unless can_generate_config?
|
237
237
|
|
238
238
|
b = binding
|
239
|
-
template = ::ERB.new(@config_template)
|
239
|
+
template = ::ERB.new(@config_template, nil, "-")
|
240
240
|
config = resource_for_config(@config_path)
|
241
241
|
config.content(template.result(b))
|
242
242
|
config.run_action(:create)
|
@@ -32,25 +32,43 @@ class Chef
|
|
32
32
|
def initialize(new_resource, run_context)
|
33
33
|
super(new_resource, run_context)
|
34
34
|
@config_template = %{
|
35
|
-
<% if new_resource.device
|
36
|
-
<% if new_resource.onboot == "yes"
|
35
|
+
<% if new_resource.device -%>
|
36
|
+
<% if new_resource.onboot == "yes" -%>
|
37
|
+
auto <%= new_resource.device %>
|
38
|
+
<% end -%>
|
37
39
|
<% case new_resource.bootproto
|
38
|
-
when "dhcp"
|
40
|
+
when "dhcp" -%>
|
39
41
|
iface <%= new_resource.device %> <%= new_resource.family %> dhcp
|
40
|
-
<% when "bootp"
|
42
|
+
<% when "bootp" -%>
|
41
43
|
iface <%= new_resource.device %> <%= new_resource.family %> bootp
|
42
|
-
<% else
|
44
|
+
<% else -%>
|
43
45
|
iface <%= new_resource.device %> <%= new_resource.family %> static
|
44
|
-
<% if new_resource.target
|
45
|
-
|
46
|
-
<%
|
47
|
-
<% if new_resource.
|
48
|
-
|
49
|
-
<%
|
50
|
-
<% if new_resource.
|
51
|
-
|
52
|
-
<% end
|
53
|
-
<%
|
46
|
+
<% if new_resource.target -%>
|
47
|
+
address <%= new_resource.target %>
|
48
|
+
<% end -%>
|
49
|
+
<% if new_resource.mask -%>
|
50
|
+
netmask <%= new_resource.mask %>
|
51
|
+
<% end -%>
|
52
|
+
<% if new_resource.network -%>
|
53
|
+
network <%= new_resource.network %>
|
54
|
+
<% end -%>
|
55
|
+
<% if new_resource.bcast -%>
|
56
|
+
broadcast <%= new_resource.bcast %>
|
57
|
+
<% end -%>
|
58
|
+
<% if new_resource.metric -%>
|
59
|
+
metric <%= new_resource.metric %>
|
60
|
+
<% end -%>
|
61
|
+
<% if new_resource.hwaddr -%>
|
62
|
+
hwaddress <%= new_resource.hwaddr %>
|
63
|
+
<% end -%>
|
64
|
+
<% if new_resource.mtu -%>
|
65
|
+
mtu <%= new_resource.mtu %>
|
66
|
+
<% end -%>
|
67
|
+
<% if new_resource.gateway -%>
|
68
|
+
gateway <%= new_resource.gateway %>
|
69
|
+
<% end -%>
|
70
|
+
<% end -%>
|
71
|
+
<% end -%>
|
54
72
|
}
|
55
73
|
@config_path = "#{INTERFACES_DOT_D_DIR}/ifcfg-#{new_resource.device}"
|
56
74
|
end
|
@@ -27,23 +27,57 @@ class Chef
|
|
27
27
|
def initialize(new_resource, run_context)
|
28
28
|
super(new_resource, run_context)
|
29
29
|
@config_template = %{
|
30
|
-
<% if new_resource.device
|
31
|
-
|
32
|
-
<%
|
33
|
-
<% if new_resource.
|
34
|
-
|
35
|
-
<%
|
36
|
-
<% if new_resource.
|
37
|
-
|
38
|
-
<%
|
39
|
-
<% if new_resource.
|
40
|
-
|
41
|
-
<%
|
42
|
-
<% if new_resource.
|
43
|
-
|
44
|
-
<%
|
45
|
-
<% if new_resource.
|
46
|
-
|
30
|
+
<% if new_resource.device -%>
|
31
|
+
DEVICE=<%= new_resource.device %>
|
32
|
+
<% end -%>
|
33
|
+
<% if new_resource.onboot == "yes" -%>
|
34
|
+
ONBOOT=<%= new_resource.onboot %>
|
35
|
+
<% end -%>
|
36
|
+
<% if new_resource.bootproto -%>
|
37
|
+
BOOTPROTO=<%= new_resource.bootproto %>
|
38
|
+
<% end -%>
|
39
|
+
<% if new_resource.target -%>
|
40
|
+
IPADDR=<%= new_resource.target %>
|
41
|
+
<% end -%>
|
42
|
+
<% if new_resource.mask -%>
|
43
|
+
NETMASK=<%= new_resource.mask %>
|
44
|
+
<% end -%>
|
45
|
+
<% if new_resource.network -%>
|
46
|
+
NETWORK=<%= new_resource.network %>
|
47
|
+
<% end -%>
|
48
|
+
<% if new_resource.bcast -%>
|
49
|
+
BROADCAST=<%= new_resource.bcast %>
|
50
|
+
<% end -%>
|
51
|
+
<% if new_resource.onparent -%>
|
52
|
+
ONPARENT=<%= new_resource.onparent %>
|
53
|
+
<% end -%>
|
54
|
+
<% if new_resource.hwaddr -%>
|
55
|
+
HWADDR=<%= new_resource.hwaddr %>
|
56
|
+
<% end -%>
|
57
|
+
<% if new_resource.metric -%>
|
58
|
+
METRIC=<%= new_resource.metric %>
|
59
|
+
<% end -%>
|
60
|
+
<% if new_resource.mtu -%>
|
61
|
+
MTU=<%= new_resource.mtu %>
|
62
|
+
<% end -%>
|
63
|
+
<% if new_resource.ethtool_opts -%>
|
64
|
+
ETHTOOL_OPTS="<%= new_resource.ethtool_opts %>"
|
65
|
+
<% end -%>
|
66
|
+
<% if new_resource.bonding_opts -%>
|
67
|
+
BONDING_OPTS="<%= new_resource.bonding_opts %>"
|
68
|
+
<% end -%>
|
69
|
+
<% if new_resource.master -%>
|
70
|
+
MASTER=<%= new_resource.master %>
|
71
|
+
<% end -%>
|
72
|
+
<% if new_resource.slave -%>
|
73
|
+
SLAVE=<%= new_resource.slave %>
|
74
|
+
<% end -%>
|
75
|
+
<% if new_resource.vlan -%>
|
76
|
+
VLAN=<%= new_resource.vlan %>
|
77
|
+
<% end -%>
|
78
|
+
<% if new_resource.gateway -%>
|
79
|
+
GATEWAY=<%= new_resource.gateway %>
|
80
|
+
<% end -%>
|
47
81
|
}
|
48
82
|
@config_path = "/etc/sysconfig/network-scripts/ifcfg-#{new_resource.device}"
|
49
83
|
end
|
@@ -54,7 +54,18 @@ class Chef
|
|
54
54
|
|
55
55
|
def interpreter_path
|
56
56
|
# Powershell.exe is always in "v1.0" folder (for backwards compatibility)
|
57
|
-
|
57
|
+
# pwsh is the other interpreter and we will assume that it is on the path.
|
58
|
+
# It will exist in different folders depending on the installed version.
|
59
|
+
# There can also be multiple versions installed. Depending on how it was installed,
|
60
|
+
# there might be a registry entry pointing to the installation path. The key will
|
61
|
+
# differ depending on version and architecture. It seems best to let the PATH
|
62
|
+
# determine the file path to use since that will provide the same pwsh.exe one
|
63
|
+
# would invoke from any shell.
|
64
|
+
if interpreter == "powershell"
|
65
|
+
Chef::Util::PathHelper.join(basepath, "WindowsPowerShell", "v1.0", "#{interpreter}.exe")
|
66
|
+
else
|
67
|
+
interpreter
|
68
|
+
end
|
58
69
|
end
|
59
70
|
|
60
71
|
def code
|
data/lib/chef/pwsh.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Matt Wrock (<mwrock@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 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
|
+
class Chef
|
19
|
+
class Pwsh < Chef::PowerShell
|
20
|
+
|
21
|
+
# Run a command under pwsh (powershell core) via FFI
|
22
|
+
# This implementation requires the managed dll, native wrapper and a
|
23
|
+
# published, self contained dotnet core directory tree to exist in the
|
24
|
+
# bindir directory.
|
25
|
+
#
|
26
|
+
# @param script [String] script to run
|
27
|
+
# @return [Object] output
|
28
|
+
def initialize(script)
|
29
|
+
@dll = Pwsh.dll
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def exec(script)
|
36
|
+
# Note that we need to override the location of the shared dotnet core library
|
37
|
+
# location. With most .net core applications, you can simply publish them as a
|
38
|
+
# "self-contained" application allowing consumers of the application to run them
|
39
|
+
# and use its own stand alone version of the .net core runtime. However because
|
40
|
+
# this is simply a dll and not an exe, it will look for the runtime in the shared
|
41
|
+
# .net core installation folder. By setting DOTNET_MULTILEVEL_LOOKUP to 0 we can
|
42
|
+
# override that folder's location with DOTNET_ROOT. To avoid the possibility of
|
43
|
+
# interfering with other .net core processes that might rely on the common shared
|
44
|
+
# location, we revert these variables after the script completes.
|
45
|
+
original_dml = ENV["DOTNET_MULTILEVEL_LOOKUP"]
|
46
|
+
original_dotnet_root = ENV["DOTNET_ROOT"]
|
47
|
+
original_dotnet_root_x86 = ENV["DOTNET_ROOT(x86)"]
|
48
|
+
|
49
|
+
ENV["DOTNET_MULTILEVEL_LOOKUP"] = "0"
|
50
|
+
ENV["DOTNET_ROOT"] = RbConfig::CONFIG["bindir"]
|
51
|
+
ENV["DOTNET_ROOT(x86)"] = RbConfig::CONFIG["bindir"]
|
52
|
+
|
53
|
+
super
|
54
|
+
ensure
|
55
|
+
ENV["DOTNET_MULTILEVEL_LOOKUP"] = original_dml
|
56
|
+
ENV["DOTNET_ROOT"] = original_dotnet_root
|
57
|
+
ENV["DOTNET_ROOT(x86)"] = original_dotnet_root_x86
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.dll
|
61
|
+
@dll ||= Dir.glob("#{RbConfig::CONFIG["bindir"]}/**/Chef.PowerShell.Wrapper.Core.dll").last
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|