chef 16.5.77 → 16.6.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/lib/chef/application/client.rb +6 -1
  4. data/lib/chef/client.rb +2 -31
  5. data/lib/chef/data_collector.rb +1 -1
  6. data/lib/chef/mixin/powershell_exec.rb +22 -10
  7. data/lib/chef/mixin/powershell_out.rb +12 -5
  8. data/lib/chef/node/mixin/immutablize_hash.rb +2 -0
  9. data/lib/chef/powershell.rb +3 -2
  10. data/lib/chef/provider/ifconfig.rb +1 -1
  11. data/lib/chef/provider/ifconfig/debian.rb +33 -15
  12. data/lib/chef/provider/ifconfig/redhat.rb +51 -17
  13. data/lib/chef/provider/powershell_script.rb +12 -1
  14. data/lib/chef/pwsh.rb +64 -0
  15. data/lib/chef/resource/apt_repository.rb +2 -3
  16. data/lib/chef/resource/chef_client_config.rb +313 -0
  17. data/lib/chef/resource/chef_client_cron.rb +5 -5
  18. data/lib/chef/resource/chef_client_scheduled_task.rb +4 -4
  19. data/lib/chef/resource/chef_client_systemd_timer.rb +5 -5
  20. data/lib/chef/resource/chef_sleep.rb +1 -1
  21. data/lib/chef/resource/cron/cron_d.rb +2 -2
  22. data/lib/chef/resource/kernel_module.rb +1 -1
  23. data/lib/chef/resource/launchd.rb +15 -15
  24. data/lib/chef/resource/mount.rb +1 -1
  25. data/lib/chef/resource/powershell_script.rb +7 -1
  26. data/lib/chef/resource/support/client.erb +65 -0
  27. data/lib/chef/resource/windows_audit_policy.rb +26 -24
  28. data/lib/chef/resources.rb +1 -0
  29. data/lib/chef/version.rb +1 -1
  30. data/spec/functional/mixin/powershell_out_spec.rb +9 -1
  31. data/spec/functional/resource/powershell_script_spec.rb +57 -14
  32. data/spec/spec_helper.rb +1 -0
  33. data/spec/support/platform_helpers.rb +6 -1
  34. data/spec/unit/mixin/powershell_exec_spec.rb +40 -3
  35. data/spec/unit/mixin/powershell_out_spec.rb +14 -0
  36. data/spec/unit/provider/powershell_script_spec.rb +11 -0
  37. data/spec/unit/resource/chef_client_config_spec.rb +137 -0
  38. data/spec/unit/resource/powershell_script_spec.rb +2 -2
  39. metadata +11 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ecb1c8cef041de453fb311da3ac177182715df9d639a9caf096b9b352d5f3c5
4
- data.tar.gz: eb1f20fcf40bd5030d1f9c5d30e30279de93d480898391308ad09bfd18fc1e0b
3
+ metadata.gz: 9601a0e75782478aa0b49ba679d1636eefd626471cf89fdc1f3bc03ece08d0d9
4
+ data.tar.gz: 55a6507691792de235cecee29b666c915f8dfaa67d54c7928b5bf6b6843aee1b
5
5
  SHA512:
6
- metadata.gz: 15f3599c4f00acdf4f8378349691fda6e7f82f43563d8d9d757ac75875e29fc3ce6c271c54fbd67952f3fc07bd0a2784fb7acfac172dcedacefc50c52b2808e0
7
- data.tar.gz: 7eebcd332552adf6ffb9da9a8c2a0273e766cf3003b4511661349b755158726ecd4e283ec0e08d11a4a5d170b9d4e40f4e007d936cdaab96af803ae4f54b6066
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__) + "/*.dll")
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
 
@@ -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
- if Chef::Config.target_mode?
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
@@ -182,7 +182,7 @@ class Chef
182
182
  events.unregister(self) unless Chef::Config[:data_collector][:output_locations]
183
183
 
184
184
  begin
185
- code = e&.response&.code&.to_s
185
+ code = e&.response&.code.to_s
186
186
  rescue
187
187
  # i really don't care
188
188
  end
@@ -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 via
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 returns a Chef::PowerShell object that provides 4 methods:
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) COM interop API.
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
- Chef::PowerShell.new(script)
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 = Chef::PowerShell.new(script)
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
- run_command_with_os_architecture(script, options)
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
- "powershell.exe #{flags.join(" ")} -Command \"#{script.gsub('"', '\"')}\""
101
+ "#{interpreter}.exe #{flags.join(" ")} -Command \"#{script.gsub('"', '\"')}\""
95
102
  end
96
103
  end
97
104
  end
@@ -58,6 +58,7 @@ class Chef
58
58
  each_with_object
59
59
  empty?
60
60
  entries
61
+ except
61
62
  fetch
62
63
  fetch_values
63
64
  filter
@@ -137,6 +138,7 @@ class Chef
137
138
  default_proc=
138
139
  delete
139
140
  delete_if
141
+ except!
140
142
  filter!
141
143
  keep_if
142
144
  map!
@@ -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
- private
63
+ protected
63
64
 
64
65
  def exec(script)
65
- FFI.ffi_lib "Chef.PowerShell.Wrapper.dll"
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" %>auto <%= new_resource.device %><% end %>
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 %>address <%= new_resource.target %><% end %>
45
- <% if new_resource.mask %>netmask <%= new_resource.mask %><% end %>
46
- <% if new_resource.network %>network <%= new_resource.network %><% end %>
47
- <% if new_resource.bcast %>broadcast <%= new_resource.bcast %><% end %>
48
- <% if new_resource.metric %>metric <%= new_resource.metric %><% end %>
49
- <% if new_resource.hwaddr %>hwaddress <%= new_resource.hwaddr %><% end %>
50
- <% if new_resource.mtu %>mtu <%= new_resource.mtu %><% end %>
51
- <% if new_resource.gateway %>gateway <%= new_resource.gateway %><% end %>
52
- <% end %>
53
- <% end %>
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 %>DEVICE=<%= new_resource.device %><% end %>
31
- <% if new_resource.onboot == "yes" %>ONBOOT=<%= new_resource.onboot %><% end %>
32
- <% if new_resource.bootproto %>BOOTPROTO=<%= new_resource.bootproto %><% end %>
33
- <% if new_resource.target %>IPADDR=<%= new_resource.target %><% end %>
34
- <% if new_resource.mask %>NETMASK=<%= new_resource.mask %><% end %>
35
- <% if new_resource.network %>NETWORK=<%= new_resource.network %><% end %>
36
- <% if new_resource.bcast %>BROADCAST=<%= new_resource.bcast %><% end %>
37
- <% if new_resource.onparent %>ONPARENT=<%= new_resource.onparent %><% end %>
38
- <% if new_resource.hwaddr %>HWADDR=<%= new_resource.hwaddr %><% end %>
39
- <% if new_resource.metric %>METRIC=<%= new_resource.metric %><% end %>
40
- <% if new_resource.mtu %>MTU=<%= new_resource.mtu %><% end %>
41
- <% if new_resource.ethtool_opts %>ETHTOOL_OPTS="<%= new_resource.ethtool_opts %>"<% end %>
42
- <% if new_resource.bonding_opts %>BONDING_OPTS="<%= new_resource.bonding_opts %>"<% end %>
43
- <% if new_resource.master %>MASTER=<%= new_resource.master %><% end %>
44
- <% if new_resource.slave %>SLAVE=<%= new_resource.slave %><% end %>
45
- <% if new_resource.vlan %>VLAN=<%= new_resource.vlan %><% end %>
46
- <% if new_resource.gateway %>GATEWAY=<%= new_resource.gateway %><% end %>
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
- Chef::Util::PathHelper.join(basepath, "WindowsPowerShell", "v1.0", interpreter)
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
@@ -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