ruby-pwsh 0.5.1 → 0.6.0

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: 37a20d5c79da4ea0b065cb85afc8e99933128576ef73c759a9f8113b7f738eed
4
- data.tar.gz: 9da59c07a8037eee9bb03591726ed83e4909b95009579b362fb49a4d2e4ac171
3
+ metadata.gz: 164dc89d750a5544dd4c100bd2166c0fe9d26447d5636bb18b0eec7d8dfc142f
4
+ data.tar.gz: bdf317f119bd2e5a7261a711a2a5c4721feda199a955feb5265af07c6f94d8d8
5
5
  SHA512:
6
- metadata.gz: 760bbbdd326042ff79e4e0f28bbfe48447ddc17fb6968f569ce1c5d75848a83e3b3042022250fb309d98124d97580c9ad1a7a9a8a629aadbbdc57b7de7718f60
7
- data.tar.gz: 1c57dec6a7bd3db1e4b32adfd0e61abb996157317fa2f74f20110f246a3daf8f6302aa0569aef07e863299e9a8ba126631b89f9df3055f5b013a8c720ff308e0
6
+ metadata.gz: 8430d204e301ce7577148a95d37a8581b3e0d37da1c3e97fcb5dce3c3a2b66601b651dd48ef3a2810d802d09cf28579dfc986712bf407e54ecb3ca8f23ab9283
7
+ data.tar.gz: ed31dd3ec848dc4c7fd108ee040c5b39e532ea50fe406ba8f98dfb6bb2cf5c804b0d758c393ead8b560785d34717a629380e346f24baae6963e34094889c6fdc
@@ -2,6 +2,21 @@
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
+ ## [0.6.0](https://github.com/puppetlabs/ruby-pwsh/tree/0.6.0) (2020-11-24)
6
+
7
+ [Full Changelog](https://github.com/puppetlabs/ruby-pwsh/compare/0.5.1...0.6.0)
8
+
9
+ ### Added
10
+
11
+ - \(GH-81\) Handle parameters in the dsc base provider [\#62](https://github.com/puppetlabs/ruby-pwsh/pull/62) ([michaeltlombardi](https://github.com/michaeltlombardi))
12
+ - \(GH-74\) Remove special handling for ensure in the dsc base provider [\#61](https://github.com/puppetlabs/ruby-pwsh/pull/61) ([michaeltlombardi](https://github.com/michaeltlombardi))
13
+ - \(GH-59\) Refactor away from Simple Provider [\#60](https://github.com/puppetlabs/ruby-pwsh/pull/60) ([michaeltlombardi](https://github.com/michaeltlombardi))
14
+
15
+ ### Fixed
16
+
17
+ - \(GH-57\) Handle datetimes in dsc [\#58](https://github.com/puppetlabs/ruby-pwsh/pull/58) ([michaeltlombardi](https://github.com/michaeltlombardi))
18
+ - \(GH-55\) Handle intentionally empty arrays [\#56](https://github.com/puppetlabs/ruby-pwsh/pull/56) ([michaeltlombardi](https://github.com/michaeltlombardi))
19
+
5
20
  ## [0.5.1](https://github.com/puppetlabs/ruby-pwsh/tree/0.5.1) (2020-09-25)
6
21
 
7
22
  [Full Changelog](https://github.com/puppetlabs/ruby-pwsh/compare/0.5.0...0.5.1)
@@ -2,7 +2,7 @@
2
2
  version: 1.1.x.{build}
3
3
  branches:
4
4
  only:
5
- - master
5
+ - main
6
6
  - release
7
7
  clone_depth: 10
8
8
  environment:
@@ -1,12 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'puppet/resource_api/simple_provider'
4
3
  require 'securerandom'
5
4
  require 'ruby-pwsh'
6
5
  require 'pathname'
7
6
  require 'json'
8
7
 
9
- class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
8
+ class Puppet::Provider::DscBaseProvider
10
9
  # Initializes the provider, preparing the class variables which cache:
11
10
  # - the canonicalized resources across calls
12
11
  # - query results
@@ -15,6 +14,7 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
15
14
  @@cached_canonicalized_resource = []
16
15
  @@cached_query_results = []
17
16
  @@logon_failures = []
17
+ super
18
18
  end
19
19
 
20
20
  # Look through a cache to retrieve the hashes specified, if they have been cached.
@@ -109,6 +109,77 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
109
109
  end
110
110
  end
111
111
 
112
+ # Determines whether a resource is ensurable and which message to write (create, update, or delete),
113
+ # then passes the appropriate values along to the various sub-methods which themselves call the Set
114
+ # method of Invoke-DscResource. Implementation borrowed directly from the Resource API Simple Provider
115
+ #
116
+ # @param context [Object] the Puppet runtime context to operate in and send feedback to
117
+ # @param changes [Hash] the hash of whose key is the name_hash and value is the is and should hashes
118
+ def set(context, changes)
119
+ changes.each do |name, change|
120
+ is = change.key?(:is) ? change[:is] : (get(context, [name]) || []).find { |r| r[:name] == name }
121
+ context.type.check_schema(is) unless change.key?(:is)
122
+
123
+ should = change[:should]
124
+
125
+ name_hash = if context.type.namevars.length > 1
126
+ # pass a name_hash containing the values of all namevars
127
+ name_hash = {}
128
+ context.type.namevars.each do |namevar|
129
+ name_hash[namevar] = change[:should][namevar]
130
+ end
131
+ name_hash
132
+ else
133
+ name
134
+ end
135
+
136
+ # for compatibility sake, we use dsc_ensure instead of ensure, so context.type.ensurable? does not work
137
+ if !context.type.attributes.key?(:dsc_ensure)
138
+ is = create_absent(:name, name) if is.nil?
139
+ should = create_absent(:name, name) if should.nil?
140
+
141
+ # HACK: If the DSC Resource is ensurable but doesn't report a default value
142
+ # for ensure, we assume it to be `Present` - this is the most common pattern.
143
+ should_ensure = should[:dsc_ensure].nil? ? 'Present' : should[:dsc_ensure].to_s
144
+ is_ensure = is[:dsc_ensure].to_s
145
+
146
+ if is_ensure == 'Absent' && should_ensure == 'Present'
147
+ context.creating(name) do
148
+ create(context, name_hash, should)
149
+ end
150
+ elsif is_ensure == 'Present' && should_ensure == 'Present'
151
+ context.updating(name) do
152
+ update(context, name_hash, should)
153
+ end
154
+ elsif is_ensure == 'Present' && should_ensure == 'Absent'
155
+ context.deleting(name) do
156
+ delete(context, name_hash)
157
+ end
158
+ end
159
+ else
160
+ context.updating(name) do
161
+ update(context, name_hash, should)
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ # Creates a hash with the name / name_hash and sets dsc_ensure to absent for comparison
168
+ # purposes; this handles cases where the resource isn't found on the node.
169
+ #
170
+ # @param namevar [Object] the name of the variable being used for the resource name
171
+ # @param title [Hash] the hash of namevar properties and their values
172
+ # @return [Hash] returns a hash representing the absent state of the resource
173
+ def create_absent(namevar, title)
174
+ result = if title.is_a? Hash
175
+ title.dup
176
+ else
177
+ { namevar => title }
178
+ end
179
+ result[:dsc_ensure] = 'Absent'
180
+ result
181
+ end
182
+
112
183
  # Attempts to set an instance of the DSC resource, invoking the `Set` method and thinly wrapping
113
184
  # the `invoke_set_method` method; whether this method, `update`, or `delete` is called is entirely
114
185
  # up to the Resource API based on the results
@@ -158,9 +229,7 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
158
229
  context.debug("retrieving #{name_hash.inspect}")
159
230
 
160
231
  # Do not bother running if the logon credentials won't work
161
- unless name_hash[:dsc_psdscrunascredential].nil?
162
- return name_hash if logon_failed_already?(name_hash[:dsc_psdscrunascredential])
163
- end
232
+ return name_hash if !name_hash[:dsc_psdscrunascredential].nil? && logon_failed_already?(name_hash[:dsc_psdscrunascredential])
164
233
 
165
234
  query_props = name_hash.select { |k, v| mandatory_get_attributes(context).include?(k) || (k == :dsc_psdscrunascredential && !v.nil?) }
166
235
  resource = should_to_resource(query_props, context, 'get')
@@ -190,28 +259,27 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
190
259
  # DSC gives back information we don't care about; filter down to only
191
260
  # those properties exposed in the type definition.
192
261
  valid_attributes = context.type.attributes.keys.collect(&:to_s)
262
+ parameters = context.type.attributes.select { |_name, properties| [properties[:behaviour]].collect.include?(:parameter) }.keys.collect(&:to_s)
193
263
  data.select! { |key, _value| valid_attributes.include?("dsc_#{key.downcase}") }
264
+ data.reject! { |key, _value| parameters.include?("dsc_#{key.downcase}") }
194
265
  # Canonicalize the results to match the type definition representation;
195
266
  # failure to do so will prevent the resource_api from comparing the result
196
267
  # to the should hash retrieved from the resource definition in the manifest.
197
- data.keys.each do |key|
268
+ data.keys.each do |key| # rubocop:disable Style/HashEachMethods
198
269
  type_key = "dsc_#{key.downcase}".to_sym
199
270
  data[type_key] = data.delete(key)
200
271
  camelcase_hash_keys!(data[type_key]) if data[type_key].is_a?(Enumerable)
272
+ # Convert DateTime back to appropriate type
273
+ data[type_key] = Puppet::Pops::Time::Timestamp.parse(data[type_key]) if context.type.attributes[type_key][:mof_type] =~ /DateTime/i
274
+ # PowerShell does not distinguish between a return of empty array/string
275
+ # and null but Puppet does; revert to those values if specified.
276
+ if data[type_key].nil? && query_props.keys.include?(type_key) && query_props[type_key].is_a?(Array)
277
+ data[type_key] = query_props[type_key].empty? ? query_props[type_key] : []
278
+ end
201
279
  end
202
- # If a resource is found, it's present, so refill these two Puppet-only keys
280
+ # If a resource is found, it's present, so refill this Puppet-only key
203
281
  data.merge!({ name: name_hash[:name] })
204
- if ensurable?(context)
205
- ensure_value = data.key?(:dsc_ensure) ? data[:dsc_ensure].downcase : 'present'
206
- data.merge!({ ensure: ensure_value })
207
- end
208
- # TODO: Handle PSDscRunAsCredential flapping
209
- # Resources do not return the account under which they were discovered, so re-add that
210
- if name_hash[:dsc_psdscrunascredential].nil?
211
- data.delete(:dsc_psdscrunascredential)
212
- else
213
- data.merge!({ dsc_psdscrunascredential: name_hash[:dsc_psdscrunascredential] })
214
- end
282
+
215
283
  # Cache the query to prevent a second lookup
216
284
  @@cached_query_results << data.dup if fetch_cached_hashes(@@cached_query_results, [data]).empty?
217
285
  context.debug("Returned to Puppet as #{data}")
@@ -229,9 +297,7 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
229
297
  context.debug("Invoking Set Method for '#{name}' with #{should.inspect}")
230
298
 
231
299
  # Do not bother running if the logon credentials won't work
232
- unless should[:dsc_psdscrunascredential].nil?
233
- return nil if logon_failed_already?(should[:dsc_psdscrunascredential])
234
- end
300
+ return nil if !should[:dsc_psdscrunascredential].nil? && logon_failed_already?(should[:dsc_psdscrunascredential])
235
301
 
236
302
  apply_props = should.select { |k, _v| k.to_s =~ /^dsc_/ }
237
303
  resource = should_to_resource(apply_props, context, 'set')
@@ -265,7 +331,6 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
265
331
  resource[k] = context.type.definition[k]
266
332
  end
267
333
  should.each do |k, v|
268
- next if k == :ensure
269
334
  # PSDscRunAsCredential is considered a namevar and will always be passed, even if nil
270
335
  # To prevent flapping during runs, remove it from the resource definition unless specified
271
336
  next if k == :dsc_psdscrunascredential && v.nil?
@@ -283,9 +348,9 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
283
348
  # During a Puppet agent run, the code lives in the cache so we can use the file expansion to discover the correct folder.
284
349
  root_module_path = $LOAD_PATH.select { |path| path.match?(%r{#{resource[:dscmeta_module_name].downcase}/lib}) }.first
285
350
  resource[:vendored_modules_path] = if root_module_path.nil?
286
- File.expand_path(Pathname.new(__FILE__).dirname + '../../../' + 'puppet_x/dsc_resources')
351
+ File.expand_path(Pathname.new(__FILE__).dirname + '../../../' + 'puppet_x/dsc_resources') # rubocop:disable Style/StringConcatenation
287
352
  else
288
- File.expand_path(root_module_path + '/puppet_x/dsc_resources')
353
+ File.expand_path("#{root_module_path}/puppet_x/dsc_resources")
289
354
  end
290
355
  resource[:attributes] = nil
291
356
  context.debug("should_to_resource: #{resource.inspect}")
@@ -331,7 +396,7 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
331
396
  # @return [Enumerable] returns the input object with hash keys recursively camelCased
332
397
  def camelcase_hash_keys!(enumerable)
333
398
  if enumerable.is_a?(Hash)
334
- enumerable.keys.each do |key|
399
+ enumerable.keys.each do |key| # rubocop:disable Style/HashEachMethods
335
400
  name = key.dup
336
401
  name[0] = name[0].downcase
337
402
  enumerable[name] = enumerable.delete(key)
@@ -363,14 +428,6 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
363
428
  end
364
429
  end
365
430
 
366
- # Checks to see whether the DSC resource being managed is defined as ensurable
367
- #
368
- # @param context [Object] the Puppet runtime context to operate in and send feedback to
369
- # @return [Bool] returns true if the DSC Resource is ensurable, otherwise false.
370
- def ensurable?(context)
371
- context.type.attributes.keys.include?(:ensure)
372
- end
373
-
374
431
  # Parses the DSC resource type definition to retrieve the names of any attributes which are specified as mandatory for get operations
375
432
  #
376
433
  # @param context [Object] the Puppet runtime context to operate in and send feedback to
@@ -441,8 +498,7 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
441
498
  # @param credential_hash [Hash] the Properties which define the PSCredential Object
442
499
  # @return [String] A line of PowerShell which defines the PSCredential object and stores it to a variable
443
500
  def format_pscredential(variable_name, credential_hash)
444
- definition = "$#{variable_name} = New-PSCredential -User #{credential_hash['user']} -Password '#{credential_hash['password']}' # PuppetSensitive"
445
- definition
501
+ "$#{variable_name} = New-PSCredential -User #{credential_hash['user']} -Password '#{credential_hash['password']}' # PuppetSensitive"
446
502
  end
447
503
 
448
504
  # Parses a resource definition (as from `should_to_resource`) for any properties which are CIM instances
@@ -522,8 +578,7 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
522
578
  # EVEN WORSE HACK - this one we can't even be sure it's a cim instance...
523
579
  # but I don't _think_ anything but nested cim instances show up as hashes inside an array
524
580
  definition = definition.gsub('@(@{', '[CimInstance[]]@(@{')
525
- definition = interpolate_variables(definition)
526
- definition
581
+ interpolate_variables(definition)
527
582
  end
528
583
 
529
584
  # Munge a resource definition (as from `should_to_resource`) into valid PowerShell which represents
@@ -548,18 +603,32 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
548
603
  resource[:parameters].each do |property_name, property_hash|
549
604
  # strip dsc_ from the beginning of the property name declaration
550
605
  name = property_name.to_s.gsub(/^dsc_/, '').to_sym
551
- params[:Property][name] = if property_hash[:mof_type] == 'PSCredential'
606
+ params[:Property][name] = case property_hash[:mof_type]
607
+ when 'PSCredential'
552
608
  # format can't unwrap Sensitive strings nested in arbitrary hashes/etc, so make
553
609
  # the Credential hash interpolable as it will be replaced by a variable reference.
554
610
  {
555
611
  'user' => property_hash[:value]['user'],
556
612
  'password' => escape_quotes(property_hash[:value]['password'].unwrap)
557
613
  }
614
+ when 'DateTime'
615
+ # These have to be handled specifically because they rely on the *Puppet* DateTime,
616
+ # not a generic ruby data type (and so can't go in the shared util in ruby-pwsh)
617
+ "[DateTime]#{property_hash[:value].format('%FT%T%z')}"
558
618
  else
559
619
  property_hash[:value]
560
620
  end
561
621
  end
562
622
  params_block = interpolate_variables("$InvokeParams = #{format(params)}")
623
+ # Move the Apostrophe for DateTime declarations
624
+ params_block = params_block.gsub("'[DateTime]", "[DateTime]'")
625
+ # HACK: Handle intentionally empty arrays - need to strongly type them because
626
+ # CIM instances do not do a consistent job of casting an empty array properly.
627
+ empty_array_parameters = resource[:parameters].select { |_k, v| v[:value].empty? }
628
+ empty_array_parameters.each do |name, properties|
629
+ param_block_name = name.to_s.gsub(/^dsc_/, '')
630
+ params_block = params_block.gsub("#{param_block_name} = @()", "#{param_block_name} = [#{properties[:mof_type]}]@()")
631
+ end
563
632
  # HACK: make CIM instances work:
564
633
  resource[:parameters].select { |_key, hash| hash[:mof_is_embedded] && hash[:mof_type] =~ /\[\]/ }.each do |_property_name, property_hash|
565
634
  formatted_property_hash = interpolate_variables(format(property_hash[:value]))
@@ -577,11 +646,11 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
577
646
  def ps_script_content(resource)
578
647
  template_path = File.expand_path('../', __FILE__)
579
648
  # Defines the helper functions
580
- functions = File.new(template_path + '/invoke_dsc_resource_functions.ps1').read
649
+ functions = File.new("#{template_path}/invoke_dsc_resource_functions.ps1").read
581
650
  # Defines the response hash and the runtime settings
582
- preamble = File.new(template_path + '/invoke_dsc_resource_preamble.ps1').read
651
+ preamble = File.new("#{template_path}/invoke_dsc_resource_preamble.ps1").read
583
652
  # The postscript defines the invocation error and result handling; expects `$InvokeParams` to be defined
584
- postscript = File.new(template_path + '/invoke_dsc_resource_postscript.ps1').read
653
+ postscript = File.new("#{template_path}/invoke_dsc_resource_postscript.ps1").read
585
654
  # The blocks define the variables to define for the postscript.
586
655
  credential_block = prepare_credentials(resource)
587
656
  cim_instances_block = prepare_cim_instances(resource)
@@ -589,8 +658,7 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
589
658
  # 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
590
659
  clear_instantiated_variables!
591
660
 
592
- content = [functions, preamble, credential_block, cim_instances_block, parameters_block, postscript].join("\n")
593
- content
661
+ [functions, preamble, credential_block, cim_instances_block, parameters_block, postscript].join("\n")
594
662
  end
595
663
 
596
664
  # Convert a Puppet/Ruby value into a PowerShell representation. Requires some slight additional
@@ -614,15 +682,16 @@ class Puppet::Provider::DscBaseProvider < Puppet::ResourceApi::SimpleProvider
614
682
  # @param value [Object] The object to unwrap sensitive data inside of
615
683
  # @return [Object] The object with any sensitive strings unwrapped and annotated
616
684
  def unwrap(value)
617
- if value.class.name == 'Puppet::Pops::Types::PSensitiveType::Sensitive'
685
+ case value
686
+ when Puppet::Pops::Types::PSensitiveType::Sensitive
618
687
  "#{value.unwrap}#PuppetSensitive"
619
- elsif value.class.name == 'Hash'
688
+ when Hash
620
689
  unwrapped = {}
621
690
  value.each do |k, v|
622
691
  unwrapped[k] = unwrap(v)
623
692
  end
624
693
  unwrapped
625
- elsif value.class.name == 'Array'
694
+ when Array
626
695
  unwrapped = []
627
696
  value.each do |v|
628
697
  unwrapped << unwrap(v)
@@ -68,6 +68,10 @@ Function ConvertTo-CanonicalResult {
68
68
  $Value = $null
69
69
  }
70
70
  }
71
+ elseif ($Result.$PropertyName.GetType().Name -match 'DateTime') {
72
+ # Handle DateTimes especially since they're an edge case
73
+ $Value = Get-Date $Result.$PropertyName -UFormat "%Y-%m-%dT%H:%M:%S%Z"
74
+ }
71
75
  else {
72
76
  # Looks like a nested CIM instance, recurse if we're not too deep in already.
73
77
  $RecursionLevel++
@@ -14,10 +14,10 @@ require 'logger'
14
14
  module Pwsh
15
15
  # Standard errors
16
16
  class Error < StandardError; end
17
+
17
18
  # Create an instance of a PowerShell host and manage execution of PowerShell code inside that host.
18
19
  class Manager
19
- attr_reader :powershell_command
20
- attr_reader :powershell_arguments
20
+ attr_reader :powershell_command, :powershell_arguments
21
21
 
22
22
  # We actually want this to be a class variable.
23
23
  @@instances = {} # rubocop:disable Style/ClassVars
@@ -70,7 +70,7 @@ module Pwsh
70
70
  def self.win32console_enabled?
71
71
  @win32console_enabled ||= defined?(Win32) &&
72
72
  defined?(Win32::Console) &&
73
- Win32::Console.class == Class
73
+ Win32::Console.instance_of?(Class)
74
74
  end
75
75
 
76
76
  # TODO: This thing isn't called anywhere and the variable it sets is never referenced...
@@ -117,16 +117,16 @@ module Pwsh
117
117
  #
118
118
  # @return [String] representation of the value for interpolation
119
119
  def format_powershell_value(object)
120
- if %i[true false].include?(object) || %w[trueclass falseclass].include?(object.class.name.downcase) # rubocop:disable Lint/BooleanSymbol
120
+ if %i[true false].include?(object) || %w[trueclass falseclass].include?(object.class.name.downcase)
121
121
  "$#{object}"
122
- elsif object.class.name == 'Symbol' || object.class.ancestors.include?(Numeric)
122
+ elsif object.instance_of?(Symbol) || object.class.ancestors.include?(Numeric)
123
123
  object.to_s
124
- elsif object.class.name == 'String'
124
+ elsif object.instance_of?(String)
125
125
  "'#{escape_quotes(object)}'"
126
- elsif object.class.name == 'Array'
127
- '@(' + object.collect { |item| format_powershell_value(item) }.join(', ') + ')'
128
- elsif object.class.name == 'Hash'
129
- '@{' + object.collect { |k, v| format_powershell_value(k) + ' = ' + format_powershell_value(v) }.join('; ') + '}'
126
+ elsif object.instance_of?(Array)
127
+ "@(#{object.collect { |item| format_powershell_value(item) }.join(', ')})"
128
+ elsif object.instance_of?(Hash)
129
+ "@{#{object.collect { |k, v| "#{format_powershell_value(k)} = #{format_powershell_value(v)}" }.join('; ')}}"
130
130
  else
131
131
  raise "unsupported type #{object.class} of value '#{object}'"
132
132
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Pwsh
4
4
  # The version of the ruby-pwsh gem
5
- VERSION = '0.5.1'
5
+ VERSION = '0.6.0'
6
6
  end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "puppetlabs-pwshlib",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
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.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet, Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-25 00:00:00.000000000 Z
11
+ date: 2020-11-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: PowerShell code manager for ruby.
14
14
  email: