chef 16.5.77 → 16.6.14

Sign up to get free protection for your applications and to get access to all the features.
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