Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package rubygem-mixlib-shellout for openSUSE:Factory checked in at 2021-01-21 21:55:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-mixlib-shellout (Old) and /work/SRC/openSUSE:Factory/.rubygem-mixlib-shellout.new.28504 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-mixlib-shellout" Thu Jan 21 21:55:55 2021 rev:23 rq:865207 version:3.2.2 Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-mixlib-shellout/rubygem-mixlib-shellout.changes 2020-03-07 21:39:00.616303414 +0100 +++ /work/SRC/openSUSE:Factory/.rubygem-mixlib-shellout.new.28504/rubygem-mixlib-shellout.changes 2021-01-21 21:55:57.117818863 +0100 @@ -1,0 +2,12 @@ +Wed Jan 20 12:55:40 UTC 2021 - Stephan Kulow <co...@suse.com> + +updated to version 3.2.2 + no changelog found + +------------------------------------------------------------------- +Fri Sep 25 14:19:18 UTC 2020 - Stephan Kulow <co...@suse.com> + +updated to version 3.1.6 + no changelog found + +------------------------------------------------------------------- Old: ---- mixlib-shellout-3.0.9.gem New: ---- mixlib-shellout-3.2.2.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-mixlib-shellout.spec ++++++ --- /var/tmp/diff_new_pack.YSZil1/_old 2021-01-21 21:55:57.805819342 +0100 +++ /var/tmp/diff_new_pack.YSZil1/_new 2021-01-21 21:55:57.809819345 +0100 @@ -1,7 +1,7 @@ # # spec file for package rubygem-mixlib-shellout # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -24,12 +24,12 @@ # Name: rubygem-mixlib-shellout -Version: 3.0.9 +Version: 3.2.2 Release: 0 %define mod_name mixlib-shellout %define mod_full_name %{mod_name}-%{version} BuildRoot: %{_tmppath}/%{name}-%{version}-build -BuildRequires: %{ruby >= 2.2} +BuildRequires: %{ruby >= 2.4} BuildRequires: %{rubygem gem2rpm} BuildRequires: ruby-macros >= 5 URL: https://github.com/chef/mixlib-shellout ++++++ mixlib-shellout-3.0.9.gem -> mixlib-shellout-3.2.2.gem ++++++ Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/mixlib/shellout/helper.rb new/lib/mixlib/shellout/helper.rb --- old/lib/mixlib/shellout/helper.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/lib/mixlib/shellout/helper.rb 2020-11-16 20:51:59.000000000 +0100 @@ -0,0 +1,197 @@ +#-- +# Author:: Daniel DeLeo (<d...@chef.io>) +# Copyright:: Copyright (c) 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_relative "../shellout" +require "chef-utils" unless defined?(ChefUtils) +require "chef-utils/dsl/default_paths" +require "chef-utils/internal" + +module Mixlib + class ShellOut + module Helper + include ChefUtils::Internal + include ChefUtils::DSL::DefaultPaths + + # + # These APIs are considered public for use in ohai and chef (by cookbooks and plugins, etc) + # but are considered private/experimental for now for the direct users of mixlib-shellout. + # + # You can see an example of how to handle the "dependency injection" in the rspec unit test. + # That backend API is left deliberately undocumented for now and may not follow SemVer and may + # break at any time (at least for the rest of 2020). + # + + def shell_out(*args, **options) + options = options.dup + options = __maybe_add_timeout(self, options) + if options.empty? + shell_out_compacted(*__clean_array(*args)) + else + shell_out_compacted(*__clean_array(*args), **options) + end + end + + def shell_out!(*args, **options) + options = options.dup + options = __maybe_add_timeout(self, options) + if options.empty? + shell_out_compacted!(*__clean_array(*args)) + else + shell_out_compacted!(*__clean_array(*args), **options) + end + end + + private + + # helper sugar for resources that support passing timeouts to shell_out + # + # module method to not pollute namespaces, but that means we need self injected as an arg + # @api private + def __maybe_add_timeout(obj, options) + options = options.dup + # historically resources have not properly declared defaults on their timeouts, so a default default of 900s was enforced here + default_val = 900 + return options if options.key?(:timeout) + + # FIXME: need to nuke descendent tracker out of Chef::Provider so we can just define that class here without requiring the + # world, and then just use symbol lookup + if obj.class.ancestors.map(&:name).include?("Chef::Provider") && obj.respond_to?(:new_resource) && obj.new_resource.respond_to?(:timeout) && !options.key?(:timeout) + options[:timeout] = obj.new_resource.timeout ? obj.new_resource.timeout.to_f : default_val + end + options + end + + # helper function to mangle options when `default_env` is true + # + # @api private + def __apply_default_env(options) + options = options.dup + default_env = options.delete(:default_env) + default_env = true if default_env.nil? + if default_env + env_key = options.key?(:env) ? :env : :environment + options[env_key] = { + "LC_ALL" => __config[:internal_locale], + "LANGUAGE" => __config[:internal_locale], + "LANG" => __config[:internal_locale], + __env_path_name => default_paths, + }.update(options[env_key] || {}) + end + options + end + + # The shell_out_compacted/shell_out_compacted! APIs are private but are intended for use + # in rspec tests. They should always be used in rspec tests instead of shell_out to allow + # for less brittle rspec tests. + # + # This expectation: + # + # allow(provider).to receive(:shell_out_compacted!).with("foo", "bar", "baz") + # + # Is met by many different possible calling conventions that mean the same thing: + # + # provider.shell_out!("foo", [ "bar", nil, "baz"]) + # provider.shell_out!(["foo", nil, "bar" ], ["baz"]) + # + # Note that when setting `default_env: false` that you should just setup an expectation on + # :shell_out_compacted for `default_env: false`, rather than the expanded env settings so + # that the default_env implementation can change without breaking unit tests. + # + def shell_out_compacted(*args, **options) + options = __apply_default_env(options) + if options.empty? + __shell_out_command(*args) + else + __shell_out_command(*args, **options) + end + end + + def shell_out_compacted!(*args, **options) + options = __apply_default_env(options) + cmd = if options.empty? + __shell_out_command(*args) + else + __shell_out_command(*args, **options) + end + cmd.error! + cmd + end + + # Helper for subclasses to reject nil out of an array. It allows using the array form of + # shell_out (which avoids the need to surround arguments with quote marks to deal with shells). + # + # @param args [String] variable number of string arguments + # @return [Array] array of strings with nil and null string rejection + # + def __clean_array(*args) + args.flatten.compact.map(&:to_s) + end + + def __shell_out_command(*args, **options) + if __transport_connection + FakeShellOut.new(args, options, __transport_connection.run_command(args.join(" "))) # FIXME: train should accept run_command(*args) + else + cmd = if options.empty? + Mixlib::ShellOut.new(*args) + else + Mixlib::ShellOut.new(*args, **options) + end + cmd.live_stream ||= __io_for_live_stream + cmd.run_command + cmd + end + end + + def __io_for_live_stream + if !STDOUT.closed? && __log.trace? + STDOUT + else + nil + end + end + + def __env_path_name + if ChefUtils.windows? + "Path" + else + "PATH" + end + end + + class FakeShellOut + attr_reader :stdout, :stderr, :exitstatus, :status + + def initialize(args, options, result) + @args = args + @options = options + @stdout = result.stdout + @stderr = result.stderr + @exitstatus = result.exit_status + @status = OpenStruct.new(success?: ( exitstatus == 0 )) + end + + def error? + exitstatus != 0 + end + + def error! + raise Mixlib::ShellOut::ShellCommandFailed, "Unexpected exit status of #{exitstatus} running #{@args}" if error? + end + end + end + end +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/mixlib/shellout/unix.rb new/lib/mixlib/shellout/unix.rb --- old/lib/mixlib/shellout/unix.rb 2019-12-30 03:41:46.000000000 +0100 +++ new/lib/mixlib/shellout/unix.rb 2020-11-16 20:51:59.000000000 +0100 @@ -1,6 +1,6 @@ # # Author:: Daniel DeLeo (<d...@chef.io>) -# Copyright:: Copyright (c) 2010-2016 Chef Software, Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -370,11 +370,11 @@ return if attempt_reap @terminate_reason = "Command exceeded allowed execution time, process terminated" - logger.error("Command exceeded allowed execution time, sending TERM") if logger + logger&.error("Command exceeded allowed execution time, sending TERM") Process.kill(:TERM, child_pgid) sleep 3 attempt_reap - logger.error("Command exceeded allowed execution time, sending KILL") if logger + logger&.error("Command exceeded allowed execution time, sending KILL") Process.kill(:KILL, child_pgid) reap diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/mixlib/shellout/version.rb new/lib/mixlib/shellout/version.rb --- old/lib/mixlib/shellout/version.rb 2019-12-30 03:41:46.000000000 +0100 +++ new/lib/mixlib/shellout/version.rb 2020-11-16 20:51:59.000000000 +0100 @@ -1,5 +1,5 @@ module Mixlib class ShellOut - VERSION = "3.0.9".freeze + VERSION = "3.2.2".freeze end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/mixlib/shellout/windows/core_ext.rb new/lib/mixlib/shellout/windows/core_ext.rb --- old/lib/mixlib/shellout/windows/core_ext.rb 2019-12-30 03:41:46.000000000 +0100 +++ new/lib/mixlib/shellout/windows/core_ext.rb 2020-11-16 20:51:59.000000000 +0100 @@ -1,7 +1,7 @@ -#-- +# # Author:: Daniel DeLeo (<d...@chef.io>) # Author:: John Keiser (<jkei...@chef.io>) -# Copyright:: Copyright (c) 2011-2016 Chef Software, Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,10 +18,10 @@ # require "win32/process" +require "ffi/win32/extensions" # Add new constants for Logon module Process::Constants - private LOGON32_LOGON_INTERACTIVE = 0x00000002 LOGON32_LOGON_BATCH = 0x00000004 @@ -45,6 +45,8 @@ WIN32_PROFILETYPE_PT_MANDATORY = 0x04 WIN32_PROFILETYPE_PT_ROAMING_PREEXISTING = 0x08 + # The environment block list ends with two nulls (\0\0). + ENVIRONMENT_BLOCK_ENDS = "\0\0".freeze end # Structs required for data handling @@ -78,6 +80,12 @@ attach_pfunc :UnloadUserProfile, %i{handle handle}, :bool + attach_pfunc :CreateEnvironmentBlock, + %i{pointer ulong bool}, :bool + + attach_pfunc :DestroyEnvironmentBlock, + %i{pointer}, :bool + ffi_lib :advapi32 attach_pfunc :LogonUserW, @@ -148,15 +156,13 @@ si_hash = {} # If the startup_info key is present, validate its subkeys - if hash["startup_info"] - hash["startup_info"].each do |key, val| - key = key.to_s.downcase - unless valid_si_keys.include?(key) - raise ArgumentError, "invalid startup_info key '#{key}'" - end - - si_hash[key] = val + hash["startup_info"]&.each do |key, val| + key = key.to_s.downcase + unless valid_si_keys.include?(key) + raise ArgumentError, "invalid startup_info key '#{key}'" end + + si_hash[key] = val end # The +command_line+ key is mandatory unless the +app_name+ key @@ -172,9 +178,25 @@ env = nil + # Retrieve the environment variables for the specified user. + if hash["with_logon"] + logon, passwd, domain = format_creds_from_hash(hash) + logon_type = hash["elevated"] ? LOGON32_LOGON_BATCH : LOGON32_LOGON_INTERACTIVE + token = logon_user(logon, domain, passwd, logon_type) + logon_ptr = FFI::MemoryPointer.from_string(logon) + profile = PROFILEINFO.new.tap do |dat| + dat[:dwSize] = dat.size + dat[:dwFlags] = 1 + dat[:lpUserName] = logon_ptr + end + + load_user_profile(token, profile.pointer) + env_list = retrieve_environment_variables(token) + end + # The env string should be passed as a string of ';' separated paths. if hash["environment"] - env = hash["environment"] + env = env_list.nil? ? hash["environment"] : merge_env_variables(env_list, hash["environment"]) unless env.respond_to?(:join) env = hash["environment"].split(File::PATH_SEPARATOR) @@ -396,6 +418,33 @@ true end + # Retrieves the environment variables for the specified user. + # + # @param env_pointer [Pointer] The environment block is an array of null-terminated Unicode strings. + # @param token [Integer] User token handle. + # @return [Boolean] true if successfully retrieves the environment variables for the specified user. + # + def create_environment_block(env_pointer, token) + unless CreateEnvironmentBlock(env_pointer, token, false) + raise SystemCallError.new("CreateEnvironmentBlock", FFI.errno) + end + + true + end + + # Frees environment variables created by the CreateEnvironmentBlock function. + # + # @param env_pointer [Pointer] The environment block is an array of null-terminated Unicode strings. + # @return [Boolean] true if successfully frees environment variables created by the CreateEnvironmentBlock function. + # + def destroy_environment_block(env_pointer) + unless DestroyEnvironmentBlock(env_pointer) + raise SystemCallError.new("DestroyEnvironmentBlock", FFI.errno) + end + + true + end + def create_process_as_user(token, app, cmd, process_security, thread_security, inherit, creation_flags, env, cwd, startinfo, procinfo) @@ -530,5 +579,51 @@ [ logon, passwd, domain ] end + # Retrieves the environment variables for the specified user. + # + # @param token [Integer] User token handle. + # @return env_list [Array<String>] Environment variables of specified user. + # + def retrieve_environment_variables(token) + env_list = [] + env_pointer = FFI::MemoryPointer.new(:pointer) + create_environment_block(env_pointer, token) + str_ptr = env_pointer.read_pointer + offset = 0 + loop do + new_str_pointer = str_ptr + offset + break if new_str_pointer.read_string(2) == ENVIRONMENT_BLOCK_ENDS + + environment = new_str_pointer.read_wstring + env_list << environment + offset = offset + environment.length * 2 + 2 + end + + # To free the buffer when we have finished with the environment block + destroy_environment_block(str_ptr) + env_list + end + + # Merge environment variables of specified user and current environment variables. + # + # @param fetched_env [Array<String>] environment variables of specified user. + # @param current_env [Array<String>] current environment variables. + # @return [Array<String>] Merged environment variables. + # + def merge_env_variables(fetched_env, current_env) + env_hash_1 = environment_list_to_hash(fetched_env) + env_hash_2 = environment_list_to_hash(current_env) + merged_env = env_hash_2.merge(env_hash_1) + merged_env.map { |k, v| "#{k}=#{v}" } + end + + # Convert an array to a hash. + # + # @param env_var [Array<String>] Environment variables. + # @return [Hash] Converted an array to hash. + # + def environment_list_to_hash(env_var) + Hash[ env_var.map { |pair| pair.split("=", 2) } ] + end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/mixlib/shellout/windows.rb new/lib/mixlib/shellout/windows.rb --- old/lib/mixlib/shellout/windows.rb 2019-12-30 03:41:46.000000000 +0100 +++ new/lib/mixlib/shellout/windows.rb 2020-11-16 20:51:59.000000000 +0100 @@ -2,7 +2,7 @@ # Author:: Daniel DeLeo (<d...@chef.io>) # Author:: John Keiser (<jkei...@chef.io>) # Author:: Ho-Sheng Hsiao (<h...@chef.io>) -# Copyright:: Copyright (c) 2011-2019, Chef Software Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -89,7 +89,7 @@ # Start the process # process, profile, token = Process.create3(create_process_args) - logger.debug(format_process(process, app_name, command_line, timeout)) if logger + logger&.debug(format_process(process, app_name, command_line, timeout)) begin # Start pushing data into input stdin_write << input if input @@ -124,7 +124,7 @@ kill_process_tree(process.process_id, wmi, logger) Process.kill(:KILL, process.process_id) rescue SystemCallError - logger.warn("Failed to kill timed out process #{process.process_id}") if logger + logger&.warn("Failed to kill timed out process #{process.process_id}") end raise Mixlib::ShellOut::CommandTimeout, [ @@ -208,7 +208,7 @@ # 4. if the argument must be quoted by #1 and terminates in a sequence of backslashes then all the backlashes must themselves # be backslash excaped (double the backslashes). # 5. if an interior quote that must be escaped by #2 has a sequence of backslashes before it then all the backslashes must - # themselves be backslash excaped along with the backslash ecape of the interior quote (double plus one backslashes). + # themselves be backslash excaped along with the backslash escape of the interior quote (double plus one backslashes). # # And to restate. We are constructing a string which will be parsed by the windows parser into arguments, and we want those # arguments to match the *args array we are passed here. So call the windows parser operation A then we need to apply A^-1 to @@ -398,20 +398,16 @@ def kill_process(instance, logger) child_pid = instance.wmi_ole_object.processid - if logger - logger.debug([ + logger&.debug([ "killing child process #{child_pid}::", "#{instance.wmi_ole_object.Name} of parent #{pid}", ].join) - end Process.kill(:KILL, instance.wmi_ole_object.processid) rescue SystemCallError - if logger - logger.debug([ + logger&.debug([ "Failed to kill child process #{child_pid}::", "#{instance.wmi_ole_object.Name} of parent #{pid}", ].join) - end end def format_process(process, app_name, command_line, timeout) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/mixlib/shellout.rb new/lib/mixlib/shellout.rb --- old/lib/mixlib/shellout.rb 2019-12-30 03:41:46.000000000 +0100 +++ new/lib/mixlib/shellout.rb 2020-11-16 20:51:59.000000000 +0100 @@ -1,6 +1,6 @@ #-- # Author:: Daniel DeLeo (<d...@chef.io>) -# Copyright:: Copyright (c) 2010-2016 Chef Software, Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,8 +16,8 @@ # limitations under the License. # -require "etc" -require "tmpdir" +require "etc" unless defined?(Etc) +require "tmpdir" unless defined?(Dir.mktmpdir) require "fcntl" require_relative "shellout/exceptions" @@ -65,7 +65,7 @@ # as the subprocess is running. attr_accessor :live_stderr - # ShellOut will push data from :input down the stdin of the subprocss. + # ShellOut will push data from :input down the stdin of the subprocess. # Normally set via options passed to new. # Default: nil attr_accessor :input @@ -122,7 +122,7 @@ # === Options: # If the last argument is a Hash, it is removed from the list of args passed # to exec and used as an options hash. The following options are available: - # * +user+: the user the commmand should run as. if an integer is given, it is + # * +user+: the user the command should run as. if an integer is given, it is # used as a uid. A string is treated as a username and resolved to a uid # with Etc.getpwnam # * +group+: the group the command should run as. works similarly to +user+ @@ -248,7 +248,7 @@ # running or died without setting an exit status (e.g., terminated by # `kill -9`). def exitstatus - @status && @status.exitstatus + @status&.exitstatus end # Run the command, writing the command's standard out and standard error diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 2019-12-30 03:41:46.000000000 +0100 +++ new/metadata 2020-11-16 20:51:59.000000000 +0100 @@ -1,15 +1,29 @@ --- !ruby/object:Gem::Specification name: mixlib-shellout version: !ruby/object:Gem::Version - version: 3.0.9 + version: 3.2.2 platform: ruby authors: - Chef Software Inc. autorequire: bindir: bin cert_chain: [] -date: 2019-12-30 00:00:00.000000000 Z -dependencies: [] +date: 2020-11-16 00:00:00.000000000 Z +dependencies: +- !ruby/object:Gem::Dependency + name: chef-utils + requirement: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: '0' + type: :runtime + prerelease: false + version_requirements: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: '0' description: Run external commands on Unix or Windows email: i...@chef.io executables: [] @@ -19,6 +33,7 @@ - LICENSE - lib/mixlib/shellout.rb - lib/mixlib/shellout/exceptions.rb +- lib/mixlib/shellout/helper.rb - lib/mixlib/shellout/unix.rb - lib/mixlib/shellout/version.rb - lib/mixlib/shellout/windows.rb @@ -34,7 +49,7 @@ requirements: - - ">=" - !ruby/object:Gem::Version - version: '2.2' + version: '2.4' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">="