ruby-pwsh 0.9.0 → 0.10.2

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.
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: []