Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2019-10-18 11:01:56 -0500 using RuboCop version 0.49.1.
# on 2019-10-29 17:24:12 -0500 using RuboCop version 0.49.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

# Offense count: 4
# Offense count: 6
GetText/DecorateFunctionMessage:
Exclude:
- 'lib/puppet/provider/exec/powershell.rb'
- 'lib/puppet/provider/exec/pwsh.rb'
- 'spec/spec_helper_acceptance.rb'

# Offense count: 1
# Offense count: 3
GetText/DecorateString:
Exclude:
- 'lib/puppet/provider/exec/powershell.rb'
- 'lib/puppet/provider/exec/pwsh.rb'
21 changes: 14 additions & 7 deletions lib/puppet/provider/exec/powershell.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
require 'puppet/provider/exec'
require 'ruby-pwsh'
begin
require 'ruby-pwsh'
rescue LoadError
raise 'Could not load the "ruby-pwsh" library; is the module puppetlabs-pwshlib installed in this environment?'
end

Puppet::Type.type(:exec).provide :powershell, :parent => Puppet::Provider::Exec do
confine :operatingsystem => :windows

commands :powershell => Pwsh::Manager.powershell_path

desc <<-EOT
Executes Powershell commands. One of the `onlyif`, `unless`, or `creates`
parameters should be specified to ensure the command is idempotent.
Expand Down Expand Up @@ -42,19 +44,24 @@
have .NET Framework 3.5 installed.
UPGRADE

def self.upgrade_message
def get_powershell_command
defined?(Pwsh::Manager.powershell_path) ? Pwsh::Manager.powershell_path : nil
end

def upgrade_message
Puppet.warning POWERSHELL_MODULE_UPGRADE_MSG if !@upgrade_warning_issued
@upgrade_warning_issued = true
end

def ps_manager
debug_output = Puppet::Util::Log.level == :debug
Pwsh::Manager.instance(command(:powershell), Pwsh::Manager.powershell_args, debug: debug_output)
Pwsh::Manager.instance(@powershell_command, Pwsh::Manager.powershell_args, debug: debug_output)
end

def run(command, check = false)
@powershell_command ||= get_powershell_command
unless Pwsh::Manager.windows_powershell_supported?
self.class.upgrade_message
upgrade_message
write_script(command) do |native_path|
# Ideally, we could keep a handle open on the temp file in this
# process (to prevent TOCTOU attacks), and execute powershell
Expand All @@ -64,7 +71,7 @@ def run(command, check = false)
# we redirect powershell's stdin to read from the file. Current
# versions of Windows use per-user temp directories with strong
# permissions, but I'd rather not make (poor) assumptions.
return super("cmd.exe /c \"\"#{native_path(command(:powershell))}\" #{legacy_args} -Command - < \"#{native_path}\"\"", check)
return super("cmd.exe /c \"\"#{native_path(@powershell_command)}\" #{legacy_args} -Command - < \"#{native_path}\"\"", check)
end
else
return execute_resource(command, resource)
Expand Down
6 changes: 5 additions & 1 deletion lib/puppet/provider/exec/pwsh.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
require 'puppet/provider/exec'
require 'ruby-pwsh'
begin
require 'ruby-pwsh'
rescue LoadError
raise 'Could not load the "ruby-pwsh" library; is the module puppetlabs-pwshlib installed in this environment?'
end

Puppet::Type.type(:exec).provide :pwsh, :parent => Puppet::Provider::Exec do
desc <<-EOT
Expand Down
83 changes: 7 additions & 76 deletions spec/unit/provider/exec/powershell_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
provider.run_spec_override(command)
end

it "should raise an upgrade message warning" do
Puppet::Type::Exec::ProviderPowershell.any_instance.expects(:upgrade_message).once

provider.run_spec_override(command)
end

context "on windows", :if => Puppet.features.microsoft_windows? do
it "should call cmd.exe /c" do
Puppet::Type::Exec::ProviderPowershell.any_instance.expects(:run)
Expand Down Expand Up @@ -84,6 +90,7 @@

context "actual runs" do
context "on Windows", :if => Puppet.features.microsoft_windows? do

it "returns the output and status" do
output, status = provider.run(command)

Expand Down Expand Up @@ -156,80 +163,4 @@
end
end
end

describe 'when applying a catalog' do
let(:manifest) { <<-MANIFEST
exec { 'PS':
command => 'exit 0',
provider => powershell,
}
MANIFEST
}
let(:tmpdir) { Dir.mktmpdir('statetmp').encode!(Encoding::UTF_8) }

before :each do
skip('Not on Windows platform') unless Puppet.features.microsoft_windows?
# a statedir setting must now exist per the new transactionstore code
# introduced in Puppet 4.6 for corrective changes, as a new YAML file
# called transactionstore.yaml will be written under this path
# which defaults to c:\dev\null when not set on Windows
Puppet[:statedir] = tmpdir
end

after :each do
FileUtils.rm_rf(tmpdir)
end

def compile_to_catalog(string, node = Puppet::Node.new('foonode'))
Puppet[:code] = string

# see lib/puppet/indirector/catalog/compiler.rb#filter
Puppet::Parser::Compiler.compile(node).filter { |r| r.virtual? }
end

def compile_to_ral(manifest)
catalog = compile_to_catalog(manifest)
ral = catalog.to_ral
ral.finalize
ral
end

def apply_compiled_manifest(manifest)
catalog = compile_to_ral(manifest)

# ensure compilation works from Puppet 3.0.0 forward
args = [catalog, Puppet::Transaction::Report.new('apply')]
args << Puppet::Graph::SequentialPrioritizer.new if defined?(Puppet::Graph)
transaction = Puppet::Transaction.new(*args)
transaction.evaluate
transaction.report.finalize_report

transaction
end

it 'does not emit a warning message when PowerShellManager is usable in a Windows environment' do

Pwsh::Manager.stubs(:win32console_enabled?).returns(false)

expect(Pwsh::Manager.windows_powershell_supported?).to eq(true)

# given PowerShellManager is supported, never emit an upgrade message
Puppet::Type::Exec::ProviderPowershell.expects(:upgrade_message).never

apply_compiled_manifest(manifest)
end

it 'emits a warning message when PowerShellManager cannot be used in a Windows environment' do

# pretend we're Ruby 1.9.3 / Puppet 3.x x86
Pwsh::Manager.stubs(:win32console_enabled?).returns(true)

expect(Pwsh::Manager.windows_powershell_supported?).to eq(false)

# given PowerShellManager is NOT supported, emit an upgrade message
Puppet::Type::Exec::ProviderPowershell.expects(:upgrade_message).once

apply_compiled_manifest(manifest)
end
end
end