ruby-pwsh 0.9.0 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4290cf1b35c8aa2ca227d4db7dd4adc437f7e40b060ea88a233cf3fe33ddff98
4
- data.tar.gz: ebc560396873912932449a51a694b4d0e03b007f8311cc385bb4e03f368f0d4a
3
+ metadata.gz: c0192c9fd1e6f719c01cfbc185c847943ec0878c1fbfda56749a52dfd5d7fca7
4
+ data.tar.gz: 5d40c16d7f2efe2585a0c65d0e6050aaa72e4083510cbac376038a85ec725264
5
5
  SHA512:
6
- metadata.gz: a6f766d3740eda4d7046f0c0c20bca5c5569433a05c463fd8bee31da759a20ad050ff0c5e7701b46449bc9a50b2f0c3258769f4bec89e7496809d9be001fe2f7
7
- data.tar.gz: 1a3fbe17709118963af1a278868910db76996185bca5b76200df6d3864cfb6c41a794a4f741163cd29542a70c5a371d436d2331f52e670bfa53277f89a830a83
6
+ metadata.gz: 1e1356eb57e96fa78906861bdd6bf887c5f9eb14175f5408e4db779a3b66ac1bc9bf92d1436f36d019da8b3e18f0bfbc175170d8e3058eff6c3e51235b433ac0
7
+ data.tar.gz: de4bdce317e05453eb9179df50f065c09c16da4529b304ed0adb7e4becc3c8378ea0f67d69444209ac72d6a5f19881b594f624c311412e8fa32fdcb4bdb9b34d
data/.gitignore CHANGED
@@ -18,4 +18,6 @@ Gemfile.lock
18
18
  /ruby-pwsh-*.gem
19
19
 
20
20
  # Acceptance Testing fixtures
21
- /spec/fixtures/modules/
21
+ /spec/fixtures/modules/
22
+ /spec/fixtures/test.pp
23
+ /spec/fixtures/website/
data/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org).
4
4
 
5
+ ## [v0.10.2](https://github.com/puppetlabs/ruby-pwsh/tree/v0.10.2) - 2022-06-24
6
+
7
+ [Full Changelog](https://github.com/puppetlabs/ruby-pwsh/compare/0.10.1...v0.10.2)
8
+
9
+ ### Fixed
10
+
11
+ - (GH-188) Filter current environment variables [#189](https://github.com/puppetlabs/ruby-pwsh/pull/189) ([chelnak](https://github.com/chelnak))
12
+
13
+ ## [0.10.1](https://github.com/puppetlabs/ruby-pwsh/tree/0.10.1) (2021-08-23)
14
+
15
+ [Full Changelog](https://github.com/puppetlabs/ruby-pwsh/compare/0.10.0...0.10.1)
16
+
17
+ ### Fixed
18
+
19
+ - \(GH-180\) Ensure instance\_key respects full uniqueness of options [\#181](https://github.com/puppetlabs/ruby-pwsh/pull/181) ([michaeltlombardi](https://github.com/michaeltlombardi))
20
+ - \(GH-165\) Ensure null-value nested cim instance arrays are appropriately munged [\#177](https://github.com/puppetlabs/ruby-pwsh/pull/177) ([michaeltlombardi](https://github.com/michaeltlombardi))
21
+
22
+ ## [0.10.0](https://github.com/puppetlabs/ruby-pwsh/tree/0.10.0) (2021-07-02)
23
+
24
+ [Full Changelog](https://github.com/puppetlabs/ruby-pwsh/compare/0.9.0...0.10.0)
25
+
26
+ ### Added
27
+
28
+ - \(GH-172\) Enable use of class-based DSC Resources by munging PSModulePath [\#173](https://github.com/puppetlabs/ruby-pwsh/pull/173) ([michaeltlombardi](https://github.com/michaeltlombardi))
29
+
5
30
  ## [0.9.0](https://github.com/puppetlabs/ruby-pwsh/tree/0.9.0) (2021-06-28)
6
31
 
7
32
  [Full Changelog](https://github.com/puppetlabs/ruby-pwsh/compare/0.8.0...0.9.0)
data/Rakefile CHANGED
@@ -99,6 +99,63 @@ task :build_module do
99
99
  File.open('README.md', 'wb') { |file| file.write(actual_readme_content) }
100
100
  end
101
101
 
102
+ # Used in vendor_dsc_module
103
+ TAR_LONGLINK = '././@LongLink'
104
+
105
+ # Vendor a Puppetized DSC Module to spec/fixtures/modules.
106
+ #
107
+ # This is necessary because `puppet module install` fails on modules with
108
+ # long file paths, like xpsdesiredstateconfiguration
109
+ #
110
+ # @param command [String] command to execute.
111
+ # @return [Object] the standard out stream.
112
+ def vendor_dsc_module(name, version, destination)
113
+ require 'open-uri'
114
+ require 'rubygems/package'
115
+ require 'zlib'
116
+
117
+ module_uri = "https://forge.puppet.com/v3/files/dsc-#{name}-#{version}.tar.gz"
118
+ tar_gz_archive = File.expand_path("#{name}.tar.gz", ENV['TEMP'])
119
+
120
+ # Download the archive from the forge
121
+ File.open(tar_gz_archive, 'wb') do |file|
122
+ file.write(URI.open(module_uri).read) # rubocop:disable Security/Open
123
+ end
124
+
125
+ # Unzip to destination
126
+ # Taken directly from StackOverflow:
127
+ # - https://stackoverflow.com/a/19139114
128
+ Gem::Package::TarReader.new(Zlib::GzipReader.open(tar_gz_archive)) do |tar|
129
+ dest = nil
130
+ tar.each do |entry|
131
+ if entry.full_name == TAR_LONGLINK
132
+ dest = File.join(destination, entry.read.strip)
133
+ next
134
+ end
135
+ dest ||= File.join(destination, entry.full_name)
136
+ if entry.directory?
137
+ File.delete(dest) if File.file?(dest)
138
+ FileUtils.mkdir_p(dest, mode: entry.header.mode, verbose: false)
139
+ elsif entry.file?
140
+ FileUtils.rm_rf(dest) if File.directory?(dest)
141
+ File.open(dest, 'wb') do |f|
142
+ f.print(entry.read)
143
+ end
144
+ FileUtils.chmod(entry.header.mode, dest, verbose: false)
145
+ elsif entry.header.typeflag == '2' # Symlink!
146
+ File.symlink(entry.header.linkname, dest)
147
+ end
148
+ dest = nil
149
+ end
150
+ end
151
+
152
+ # Rename folder to just the module name, as needed by Puppet
153
+ Dir.glob("#{destination}/*#{name}*").each do |existing_folder|
154
+ new_folder = File.expand_path(name, destination)
155
+ FileUtils.mv(existing_folder, new_folder)
156
+ end
157
+ end
158
+
102
159
  namespace :dsc do
103
160
  namespace :acceptance do
104
161
  desc 'Prep for running DSC acceptance tests'
@@ -107,20 +164,21 @@ namespace :dsc do
107
164
  modules_folder = File.expand_path('spec/fixtures/modules', File.dirname(__FILE__))
108
165
  FileUtils.mkdir_p(modules_folder) unless Dir.exist?(modules_folder)
109
166
  # symlink the parent folder to the modules folder for puppet
110
- File.symlink(File.dirname(__FILE__), File.expand_path('pwshlib', modules_folder))
167
+ symlink_path = File.expand_path('pwshlib', modules_folder)
168
+ File.symlink(File.dirname(__FILE__), symlink_path) unless Dir.exist?(symlink_path)
111
169
  # Install each of the required modules for acceptance testing
112
170
  # Note: This only works for modules in the dsc namespace on the forge.
113
- [{ name: 'powershellget', version: '2.2.5-0-1' }].each do |puppet_module|
171
+ puppetized_dsc_modules = [
172
+ { name: 'powershellget', version: '2.2.5-0-1' },
173
+ { name: 'jeadsc', version: '0.7.2-0-3' },
174
+ { name: 'xpsdesiredstateconfiguration', version: '9.1.0-0-1' },
175
+ { name: 'xwebadministration', version: '3.2.0-0-2' },
176
+ { name: 'accesscontroldsc', version: '1.4.1-0-3' }
177
+ ]
178
+ puppetized_dsc_modules.each do |puppet_module|
114
179
  next if Dir.exist?(File.expand_path(puppet_module[:name], modules_folder))
115
180
 
116
- install_command = [
117
- 'bundle exec puppet module install',
118
- "dsc-#{puppet_module[:name]}",
119
- "--version #{puppet_module[:version]}",
120
- '--ignore-dependencies',
121
- "--target-dir #{modules_folder}"
122
- ].join(' ')
123
- run_local_command(install_command)
181
+ vendor_dsc_module(puppet_module[:name], puppet_module[:version], modules_folder)
124
182
  end
125
183
  end
126
184
  RSpec::Core::RakeTask.new(:spec) do |t|
@@ -416,7 +416,7 @@ class Puppet::Provider::DscBaseProvider
416
416
  def invocable_resource(should, context, dsc_invoke_method)
417
417
  resource = {}
418
418
  resource[:parameters] = {}
419
- %i[name dscmeta_resource_friendly_name dscmeta_resource_name dscmeta_module_name dscmeta_module_version].each do |k|
419
+ %i[name dscmeta_resource_friendly_name dscmeta_resource_name dscmeta_resource_implementation dscmeta_module_name dscmeta_module_version].each do |k|
420
420
  resource[k] = context.type.definition[k]
421
421
  end
422
422
  should.each do |k, v|
@@ -655,6 +655,27 @@ class Puppet::Provider::DscBaseProvider
655
655
  modified_string
656
656
  end
657
657
 
658
+ # Parses a resource definition (as from `invocable_resource`) and, if the resource is implemented
659
+ # as a PowerShell class, ensures the System environment variable for PSModulePath is munged to
660
+ # include the vendored PowerShell modules. Due to a bug in PSDesiredStateConfiguration, class-based
661
+ # DSC Resources cannot be called via Invoke-DscResource by path, only by module name, *and* the
662
+ # module must be discoverable in the system-level PSModulePath. The postscript for invocation has
663
+ # logic to reset the system PSModulePath as stored in the script lines returned by this method.
664
+ #
665
+ # @param resource [Hash] a hash with the information needed to run `Invoke-DscResource`
666
+ # @return [String] A multi-line string which sets the PSModulePath at the system level
667
+ def munge_psmodulepath(resource)
668
+ return unless resource[:dscmeta_resource_implementation] == 'Class'
669
+
670
+ vendor_path = resource[:vendored_modules_path].gsub('/', '\\')
671
+ <<~MUNGE_PSMODULEPATH.strip
672
+ $UnmungedPSModulePath = [System.Environment]::GetEnvironmentVariable('PSModulePath','machine')
673
+ $MungedPSModulePath = $env:PSModulePath + ';#{vendor_path}'
674
+ [System.Environment]::SetEnvironmentVariable('PSModulePath', $MungedPSModulePath, [System.EnvironmentVariableTarget]::Machine)
675
+ $env:PSModulePath = [System.Environment]::GetEnvironmentVariable('PSModulePath','machine')
676
+ MUNGE_PSMODULEPATH
677
+ end
678
+
658
679
  # Parses a resource definition (as from `invocable_resource`) for any properties which are PowerShell
659
680
  # Credentials. As these values need to be serialized into PSCredential objects, return an array of
660
681
  # PowerShell lines, each of which instantiates a variable which holds the value as a PSCredential.
@@ -784,7 +805,11 @@ class Puppet::Provider::DscBaseProvider
784
805
  }
785
806
  if resource.key?(:dscmeta_module_version)
786
807
  params[:ModuleName] = {}
787
- params[:ModuleName][:ModuleName] = "#{resource[:vendored_modules_path]}/#{resource[:dscmeta_module_name]}/#{resource[:dscmeta_module_name]}.psd1"
808
+ params[:ModuleName][:ModuleName] = if resource[:dscmeta_resource_implementation] == 'Class'
809
+ resource[:dscmeta_module_name]
810
+ else
811
+ "#{resource[:vendored_modules_path]}/#{resource[:dscmeta_module_name]}/#{resource[:dscmeta_module_name]}.psd1"
812
+ end
788
813
  params[:ModuleName][:RequiredVersion] = resource[:dscmeta_module_version]
789
814
  else
790
815
  params[:ModuleName] = resource[:dscmeta_module_name]
@@ -841,13 +866,14 @@ class Puppet::Provider::DscBaseProvider
841
866
  # The postscript defines the invocation error and result handling; expects `$InvokeParams` to be defined
842
867
  postscript = File.new("#{template_path}/invoke_dsc_resource_postscript.ps1").read
843
868
  # The blocks define the variables to define for the postscript.
869
+ module_path_block = munge_psmodulepath(resource)
844
870
  credential_block = prepare_credentials(resource)
845
871
  cim_instances_block = prepare_cim_instances(resource)
846
872
  parameters_block = invoke_params(resource)
847
873
  # clean them out of the temporary cache now that they're not needed; failure to do so can goof up future executions in this run
848
874
  clear_instantiated_variables!
849
875
 
850
- [functions, preamble, credential_block, cim_instances_block, parameters_block, postscript].join("\n")
876
+ [functions, preamble, module_path_block, credential_block, cim_instances_block, parameters_block, postscript].join("\n")
851
877
  end
852
878
 
853
879
  # Convert a Puppet/Ruby value into a PowerShell representation. Requires some slight additional
@@ -115,7 +115,7 @@ Function ConvertTo-CanonicalResult {
115
115
  }
116
116
 
117
117
  if ($Property.Definition -match 'InstanceArray') {
118
- If ($Value.GetType().Name -notmatch '\[\]') { $Value = @($Value) }
118
+ If ($null -eq $Value -or $Value.GetType().Name -notmatch '\[\]') { $Value = @($Value) }
119
119
  }
120
120
 
121
121
  $ResultObject.$PropertyName = $Value
@@ -3,6 +3,12 @@ Try {
3
3
  } catch {
4
4
  $Response.errormessage = $_.Exception.Message
5
5
  return ($Response | ConvertTo-Json -Compress)
6
+ } Finally {
7
+ If (![string]::IsNullOrEmpty($UnmungedPSModulePath)) {
8
+ # Reset the PSModulePath
9
+ [System.Environment]::SetEnvironmentVariable('PSModulePath', $UnmungedPSModulePath, [System.EnvironmentVariableTarget]::Machine)
10
+ $env:PSModulePath = [System.Environment]::GetEnvironmentVariable('PSModulePath', 'machine')
11
+ }
6
12
  }
7
13
 
8
14
  # keep the switch for when Test passes back changed properties
data/lib/pwsh/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Pwsh
4
4
  # The version of the ruby-pwsh gem
5
- VERSION = '0.9.0'
5
+ VERSION = '0.10.2'
6
6
  end
data/lib/pwsh.rb CHANGED
@@ -406,7 +406,7 @@ Invoke-PowerShellUserCode @params
406
406
  #
407
407
  # @return[String] Unique string representing the manager instance.
408
408
  def self.instance_key(cmd, args, options)
409
- cmd + args.join(' ') + options[:debug].to_s
409
+ cmd + args.join(' ') + options.to_s
410
410
  end
411
411
 
412
412
  # Return whether or not a particular stream is valid and readable
@@ -35,8 +35,18 @@ $global:ourFunctions = @'
35
35
  function Reset-ProcessEnvironmentVariables {
36
36
  param($CachedEnvironmentVariables)
37
37
 
38
+ # When Protected Event Logging and PowerShell Script Block logging are enabled together
39
+ # the SystemRoot environment variable is a requirement. If it is removed as part of this purge
40
+ # it causes the PowerShell process to crash, therefore breaking the pipe between Ruby and the
41
+ # remote PowerShell session.
42
+ # The least descructive way to avoid this is to filter out SystemRoot when pulling our current list
43
+ # of environment variables. Then we can continue safely with the removal.
44
+ $CurrentEnvironmentVariables = Get-ChildItem -Path Env:\* |
45
+ Where-Object {$_.Name -ne "SystemRoot"}
46
+
38
47
  # Delete existing environment variables
39
- Remove-Item -Path Env:\* -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Recurse
48
+ $CurrentEnvironmentVariables |
49
+ ForEach-Object -Process { Remove-Item -Path "ENV:\$($_.Name)" -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Recurse }
40
50
 
41
51
  # Re-add the cached environment variables
42
52
  $CachedEnvironmentVariables |
data/metadata.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "puppetlabs-pwshlib",
3
- "version": "0.9.0",
3
+ "version": "0.10.2",
4
4
  "author": "puppetlabs",
5
5
  "summary": "Provide library code for interoperating with PowerShell.",
6
6
  "license": "MIT",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-pwsh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet, Inc.
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-28 00:00:00.000000000 Z
11
+ date: 2022-06-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: PowerShell code manager for ruby.
14
14
  email:
@@ -54,7 +54,7 @@ metadata:
54
54
  homepage_uri: https://github.com/puppetlabs/ruby-pwsh
55
55
  source_code_uri: https://github.com/puppetlabs/ruby-pwsh
56
56
  changelog_uri: https://github.com/puppetlabs/ruby-pwsh
57
- post_install_message:
57
+ post_install_message:
58
58
  rdoc_options: []
59
59
  require_paths:
60
60
  - lib
@@ -69,8 +69,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
69
  - !ruby/object:Gem::Version
70
70
  version: '0'
71
71
  requirements: []
72
- rubygems_version: 3.2.17
73
- signing_key:
72
+ rubygems_version: 3.0.3.1
73
+ signing_key:
74
74
  specification_version: 4
75
75
  summary: PowerShell code manager for ruby.
76
76
  test_files: []