ruby-pwsh 0.10.3 → 0.11.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +16 -38
- data/lib/puppet/provider/dsc_base_provider/dsc_base_provider.rb +20 -20
- data/lib/pwsh/version.rb +1 -1
- data/lib/pwsh/windows_powershell.rb +2 -2
- data/lib/pwsh.rb +31 -34
- data/spec/acceptance/dsc/basic.rb +4 -0
- data/spec/acceptance/dsc/cim_instances.rb +3 -4
- data/spec/acceptance/dsc/class.rb +3 -3
- data/spec/acceptance/dsc/complex.rb +2 -2
- data/spec/acceptance/support/setup_winrm.ps1 +6 -0
- data/spec/unit/puppet/provider/dsc_base_provider/dsc_base_provider_spec.rb +171 -113
- data/spec/unit/pwsh/util_spec.rb +100 -93
- data/spec/unit/pwsh/version_spec.rb +2 -2
- data/spec/unit/pwsh/windows_powershell_spec.rb +18 -13
- data/spec/unit/pwsh_spec.rb +61 -63
- metadata +6 -5
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
|
+
require 'puppet/resource_api'
|
4
5
|
require 'puppet/type'
|
5
6
|
require 'puppet/provider/dsc_base_provider/dsc_base_provider'
|
6
7
|
require 'json'
|
@@ -8,21 +9,21 @@ require 'json'
|
|
8
9
|
RSpec.describe Puppet::Provider::DscBaseProvider do
|
9
10
|
subject(:provider) { described_class.new }
|
10
11
|
|
11
|
-
let(:context) { instance_double(
|
12
|
-
let(:type) { instance_double(
|
13
|
-
let(:ps_manager) { instance_double(
|
12
|
+
let(:context) { instance_double(Puppet::ResourceApi::PuppetContext) }
|
13
|
+
let(:type) { instance_double(Puppet::ResourceApi::TypeDefinition) }
|
14
|
+
let(:ps_manager) { instance_double(Pwsh::Manager) }
|
14
15
|
let(:execute_response) { { stdout: nil, stderr: nil, exitcode: 0 } }
|
15
16
|
|
16
17
|
# Reset the caches after each run
|
17
|
-
after
|
18
|
+
after do
|
18
19
|
described_class.class_variable_set(:@@cached_canonicalized_resource, nil) # rubocop:disable Style/ClassVars
|
19
20
|
described_class.class_variable_set(:@@cached_query_results, nil) # rubocop:disable Style/ClassVars
|
20
21
|
described_class.class_variable_set(:@@cached_test_results, nil) # rubocop:disable Style/ClassVars
|
21
22
|
described_class.class_variable_set(:@@logon_failures, nil) # rubocop:disable Style/ClassVars
|
22
23
|
end
|
23
24
|
|
24
|
-
|
25
|
-
before
|
25
|
+
describe '.initialize' do
|
26
|
+
before do
|
26
27
|
# Need to initialize the provider to load the class variables
|
27
28
|
provider
|
28
29
|
end
|
@@ -30,18 +31,21 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
30
31
|
it 'initializes the cached_canonicalized_resource class variable' do
|
31
32
|
expect(described_class.class_variable_get(:@@cached_canonicalized_resource)).to eq([])
|
32
33
|
end
|
34
|
+
|
33
35
|
it 'initializes the cached_query_results class variable' do
|
34
36
|
expect(described_class.class_variable_get(:@@cached_query_results)).to eq([])
|
35
37
|
end
|
38
|
+
|
36
39
|
it 'initializes the cached_test_results class variable' do
|
37
40
|
expect(described_class.class_variable_get(:@@cached_test_results)).to eq([])
|
38
41
|
end
|
42
|
+
|
39
43
|
it 'initializes the logon_failures class variable' do
|
40
44
|
expect(described_class.class_variable_get(:@@logon_failures)).to eq([])
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
44
|
-
|
48
|
+
describe '.cached_test_results' do
|
45
49
|
let(:cache_value) { %w[foo bar] }
|
46
50
|
|
47
51
|
it 'returns the value of the @@cached_test_results class variable' do
|
@@ -50,7 +54,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
50
54
|
end
|
51
55
|
end
|
52
56
|
|
53
|
-
|
57
|
+
describe '.fetch_cached_hashes' do
|
54
58
|
let(:cached_hashes) { [{ foo: 1, bar: 2, baz: 3 }, { foo: 4, bar: 5, baz: 6 }] }
|
55
59
|
let(:findable_full_hash) { { foo: 1, bar: 2, baz: 3 } }
|
56
60
|
let(:findable_sub_hash) { { foo: 1 } }
|
@@ -59,15 +63,17 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
59
63
|
it 'finds a hash that exactly matches one in the cache' do
|
60
64
|
expect(provider.fetch_cached_hashes(cached_hashes, [findable_full_hash])).to eq([findable_full_hash])
|
61
65
|
end
|
66
|
+
|
62
67
|
it 'finds a hash that is wholly contained by a hash in the cache' do
|
63
68
|
expect(provider.fetch_cached_hashes(cached_hashes, [findable_sub_hash])).to eq([findable_full_hash])
|
64
69
|
end
|
70
|
+
|
65
71
|
it 'returns an empty array if there is no match' do
|
66
72
|
expect(provider.fetch_cached_hashes(cached_hashes, [undiscoverable_hash])).to eq([])
|
67
73
|
end
|
68
74
|
end
|
69
75
|
|
70
|
-
|
76
|
+
describe '.canonicalize' do
|
71
77
|
subject(:canonicalized_resource) { provider.canonicalize(context, [manifest_resource]) }
|
72
78
|
|
73
79
|
let(:resource_name_hash) { { name: 'foo', dsc_name: 'foo' } }
|
@@ -76,7 +82,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
76
82
|
let(:credential_hash) { { 'username' => 'foo', 'password' => 'bar' } }
|
77
83
|
let(:base_resource) { resource_name_hash.dup }
|
78
84
|
|
79
|
-
before
|
85
|
+
before do
|
80
86
|
allow(context).to receive(:debug)
|
81
87
|
allow(provider).to receive(:namevar_attributes).and_return(namevar_keys)
|
82
88
|
allow(provider).to receive(:fetch_cached_hashes).and_return(cached_canonicalized_resource)
|
@@ -88,7 +94,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
88
94
|
let(:cached_canonicalized_resource) { expected_resource.dup }
|
89
95
|
|
90
96
|
it 'does not get removed as part of the canonicalization' do
|
91
|
-
expect(canonicalized_resource.first[:noop]).to
|
97
|
+
expect(canonicalized_resource.first[:noop]).to be(true)
|
92
98
|
end
|
93
99
|
end
|
94
100
|
|
@@ -105,7 +111,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
105
111
|
context 'when a manifest resource not in the canonicalized resource cache' do
|
106
112
|
let(:cached_canonicalized_resource) { [] }
|
107
113
|
|
108
|
-
before
|
114
|
+
before do
|
109
115
|
allow(provider).to receive(:invoke_get_method).and_return(actual_resource)
|
110
116
|
end
|
111
117
|
|
@@ -119,7 +125,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
119
125
|
end
|
120
126
|
|
121
127
|
context 'when invoke_get_method returns a resource' do
|
122
|
-
before
|
128
|
+
before do
|
123
129
|
allow(provider).to receive(:parameter_attributes).and_return(parameter_keys)
|
124
130
|
allow(provider).to receive(:enum_attributes).and_return([])
|
125
131
|
end
|
@@ -148,7 +154,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
148
154
|
let(:actual_resource) { base_resource.merge({ dsc_property: 'Bar' }) }
|
149
155
|
|
150
156
|
it 'treats the manifest value as canonical' do
|
151
|
-
expect(canonicalized_resource.first[:dsc_property]).to
|
157
|
+
expect(canonicalized_resource.first[:dsc_property]).to be_nil
|
152
158
|
end
|
153
159
|
end
|
154
160
|
|
@@ -165,7 +171,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
165
171
|
let(:manifest_resource) { base_resource.merge({ dsc_property: 'Dword' }) }
|
166
172
|
let(:actual_resource) { base_resource.merge({ dsc_property: 'DWord' }) }
|
167
173
|
|
168
|
-
before
|
174
|
+
before do
|
169
175
|
allow(provider).to receive(:enum_attributes).and_return([:dsc_property])
|
170
176
|
end
|
171
177
|
|
@@ -230,8 +236,8 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
230
236
|
end
|
231
237
|
end
|
232
238
|
|
233
|
-
|
234
|
-
after
|
239
|
+
describe '.get' do
|
240
|
+
after do
|
235
241
|
described_class.class_variable_set(:@@cached_canonicalized_resource, []) # rubocop:disable Style/ClassVars
|
236
242
|
end
|
237
243
|
|
@@ -242,6 +248,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
242
248
|
expect(provider).not_to receive(:invoke_get_method)
|
243
249
|
expect(provider.get(context, [{ name: 'foo' }])).to eq([{ name: 'foo', property: 'bar' }])
|
244
250
|
end
|
251
|
+
|
245
252
|
it 'adds mandatory properties to the name hash when calling invoke_get_method' do
|
246
253
|
described_class.class_variable_set(:@@cached_canonicalized_resource, [{ name: 'foo', property: 'bar', dsc_some_parameter: 'baz' }]) # rubocop:disable Style/ClassVars
|
247
254
|
allow(context).to receive(:debug)
|
@@ -253,7 +260,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
253
260
|
end
|
254
261
|
end
|
255
262
|
|
256
|
-
|
263
|
+
describe '.set' do
|
257
264
|
subject(:result) { provider.set(context, change_set) }
|
258
265
|
|
259
266
|
let(:name_hash) { { name: 'foo', dsc_name: 'foo' } }
|
@@ -261,7 +268,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
261
268
|
# Empty because we can mock everything but calling .keys on the hash
|
262
269
|
let(:attributes) { { name: {}, dsc_name: {}, dsc_setting: {} } }
|
263
270
|
|
264
|
-
before
|
271
|
+
before do
|
265
272
|
allow(context).to receive(:type).and_return(type)
|
266
273
|
allow(type).to receive(:namevars).and_return(%i[name dsc_name])
|
267
274
|
allow(type).to receive(:attributes).and_return(attributes)
|
@@ -342,6 +349,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
342
349
|
context 'when `is` is nil' do
|
343
350
|
let(:change_set) { { name_hash => { should: should_state } } }
|
344
351
|
let(:should_state) { name_hash.merge(dsc_setting: 'Foo') }
|
352
|
+
|
345
353
|
it 'attempts to retrieve the resource from the machine to populate `is` value' do
|
346
354
|
pending('Implementation only works for when `get` returns an array, but `get` returns one resource as a hash')
|
347
355
|
expect(provider).to receive(:get).with(context, [name_hash]).and_return(name_hash.merge(dsc_setting: 'Bar'))
|
@@ -353,7 +361,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
353
361
|
end
|
354
362
|
end
|
355
363
|
|
356
|
-
|
364
|
+
describe '.create' do
|
357
365
|
it 'calls invoke_set_method' do
|
358
366
|
allow(context).to receive(:debug)
|
359
367
|
expect(provider).to receive(:invoke_set_method)
|
@@ -361,7 +369,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
361
369
|
end
|
362
370
|
end
|
363
371
|
|
364
|
-
|
372
|
+
describe '.update' do
|
365
373
|
it 'calls invoke_set_method' do
|
366
374
|
allow(context).to receive(:debug)
|
367
375
|
expect(provider).to receive(:invoke_set_method)
|
@@ -369,7 +377,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
369
377
|
end
|
370
378
|
end
|
371
379
|
|
372
|
-
|
380
|
+
describe '.delete' do
|
373
381
|
it 'calls invoke_set_method' do
|
374
382
|
allow(context).to receive(:debug)
|
375
383
|
expect(provider).to receive(:invoke_set_method)
|
@@ -377,7 +385,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
377
385
|
end
|
378
386
|
end
|
379
387
|
|
380
|
-
|
388
|
+
describe '.insync?' do
|
381
389
|
let(:name) { { name: 'foo' } }
|
382
390
|
let(:attribute_name) { :foo }
|
383
391
|
let(:is_hash) { { name: 'foo', foo: 1 } }
|
@@ -391,22 +399,24 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
391
399
|
expect(provider).to receive(:invoke_test_method).and_return(true)
|
392
400
|
expect(provider.send(:insync?, context, name, attribute_name, is_hash, should_hash_validate_by_resource)).to be true
|
393
401
|
end
|
402
|
+
|
394
403
|
it 'does not call invoke_test_method if the result of a test is already cached' do
|
395
404
|
expect(provider).to receive(:fetch_cached_hashes).and_return(cached_test_result)
|
396
405
|
expect(provider).not_to receive(:invoke_test_method)
|
397
406
|
expect(provider.send(:insync?, context, name, attribute_name, is_hash, should_hash_validate_by_resource)).to be true
|
398
407
|
end
|
399
408
|
end
|
409
|
+
|
400
410
|
context 'when the validation_mode is "property"' do
|
401
411
|
it 'does not call invoke_test_method and returns nil' do
|
402
412
|
expect(provider).not_to receive(:fetch_cached_hashes)
|
403
413
|
expect(provider).not_to receive(:invoke_test_method)
|
404
|
-
expect(provider.send(:insync?, context, name, attribute_name, is_hash, should_hash_validate_by_property)).to
|
414
|
+
expect(provider.send(:insync?, context, name, attribute_name, is_hash, should_hash_validate_by_property)).to be_nil
|
405
415
|
end
|
406
416
|
end
|
407
417
|
end
|
408
418
|
|
409
|
-
|
419
|
+
describe '.invoke_get_method' do
|
410
420
|
subject(:result) { provider.invoke_get_method(context, name_hash) }
|
411
421
|
|
412
422
|
let(:attributes) do
|
@@ -508,7 +518,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
508
518
|
}
|
509
519
|
end
|
510
520
|
|
511
|
-
before
|
521
|
+
before do
|
512
522
|
allow(context).to receive(:debug)
|
513
523
|
allow(provider).to receive(:mandatory_get_attributes).and_return(mandatory_get_attributes)
|
514
524
|
allow(provider).to receive(:invocable_resource).with(query_props, context, 'get').and_return(resource)
|
@@ -520,12 +530,12 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
520
530
|
allow(type).to receive(:attributes).and_return(attributes)
|
521
531
|
end
|
522
532
|
|
523
|
-
after
|
533
|
+
after do
|
524
534
|
described_class.class_variable_set(:@@cached_query_results, nil) # rubocop:disable Style/ClassVars
|
525
535
|
end
|
526
536
|
|
527
537
|
context 'when the invocation script returns data without errors' do
|
528
|
-
before
|
538
|
+
before do
|
529
539
|
allow(ps_manager).to receive(:execute).with(script).and_return({ stdout: 'DSC Data' })
|
530
540
|
allow(JSON).to receive(:parse).with('DSC Data').and_return(parsed_invocation_data)
|
531
541
|
allow(Puppet::Pops::Time::Timestamp).to receive(:parse).with('2100-01-01').and_return('TimeStamp:2100-01-01')
|
@@ -536,32 +546,40 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
536
546
|
expect(provider).not_to receive(:logon_failed_already?)
|
537
547
|
expect { result }.not_to raise_error
|
538
548
|
end
|
549
|
+
|
539
550
|
it 'writes no errors to the context' do
|
540
551
|
expect(context).not_to receive(:err)
|
541
552
|
expect { result }.not_to raise_error
|
542
553
|
end
|
554
|
+
|
543
555
|
it 're-adds the puppet name to the resource' do
|
544
556
|
expect(result[:name]).to eq('foo')
|
545
557
|
end
|
558
|
+
|
546
559
|
it 'caches the result' do
|
547
560
|
expect { result }.not_to raise_error
|
548
561
|
expect(described_class.class_variable_get(:@@cached_query_results)).to eq([result])
|
549
562
|
end
|
563
|
+
|
550
564
|
it 'removes unrelated properties from the result' do
|
551
565
|
expect(result.keys).not_to include('UnusedProperty')
|
552
566
|
expect(result.keys).not_to include('unusedproperty')
|
553
567
|
expect(result.keys).not_to include(:unusedproperty)
|
554
568
|
end
|
569
|
+
|
555
570
|
it 'removes parameters from the result' do
|
556
571
|
expect(result[:dsc_param]).to be_nil
|
557
572
|
end
|
573
|
+
|
558
574
|
it 'handles timestamps' do
|
559
575
|
expect(result[:dsc_time]).to eq('TimeStamp:2100-01-01')
|
560
576
|
end
|
577
|
+
|
561
578
|
it 'downcases keys in cim instance properties' do
|
562
579
|
expect(result[:dsc_nestedciminstance].keys).to eq(%w[baz nestedproperty])
|
563
580
|
expect(result[:dsc_nestedciminstance]['nestedproperty'].keys).to eq(%w[cim_instance_type nestedbar nestedfoo])
|
564
581
|
end
|
582
|
+
|
565
583
|
it 'recursively sorts the result for order-insensitive comparisons' do
|
566
584
|
expect(result.keys).to eq(%i[dsc_array dsc_ciminstance dsc_ensure dsc_name dsc_nestedciminstance dsc_time name])
|
567
585
|
expect(result[:dsc_array]).to eq(%w[bar foo])
|
@@ -643,7 +661,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
643
661
|
end
|
644
662
|
|
645
663
|
context 'when handling DateTimes' do
|
646
|
-
before
|
664
|
+
before do
|
647
665
|
allow(ps_manager).to receive(:execute).with(script).and_return({ stdout: 'DSC Data' })
|
648
666
|
allow(JSON).to receive(:parse).with('DSC Data').and_return(parsed_invocation_data)
|
649
667
|
allow(provider).to receive(:fetch_cached_hashes).and_return([])
|
@@ -657,7 +675,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
657
675
|
|
658
676
|
it 'returns nil for the value' do
|
659
677
|
expect(context).not_to receive(:err)
|
660
|
-
expect(result[:dsc_time]).to
|
678
|
+
expect(result[:dsc_time]).to be_nil
|
661
679
|
end
|
662
680
|
end
|
663
681
|
|
@@ -669,7 +687,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
669
687
|
|
670
688
|
it 'writes an error and sets the value of `dsc_time` to nil' do
|
671
689
|
expect(context).to receive(:err).with(/Value returned for DateTime/)
|
672
|
-
expect(result[:dsc_time]).to
|
690
|
+
expect(result[:dsc_time]).to be_nil
|
673
691
|
end
|
674
692
|
end
|
675
693
|
|
@@ -681,7 +699,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
681
699
|
|
682
700
|
it 'writes an error and sets the value of `dsc_time` to nil' do
|
683
701
|
expect(context).to receive(:err).with(/Value returned for DateTime/)
|
684
|
-
expect(result[:dsc_time]).to
|
702
|
+
expect(result[:dsc_time]).to be_nil
|
685
703
|
end
|
686
704
|
end
|
687
705
|
end
|
@@ -694,23 +712,26 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
694
712
|
let(:query_props) { { dsc_name: 'foo', dsc_psdscrunascredential: credential_hash } }
|
695
713
|
|
696
714
|
context 'when the credential is invalid' do
|
697
|
-
before
|
715
|
+
before do
|
698
716
|
allow(provider).to receive(:logon_failed_already?).and_return(false)
|
699
717
|
allow(ps_manager).to receive(:execute).with(script).and_return({ stdout: 'DSC Data' })
|
700
718
|
allow(JSON).to receive(:parse).with('DSC Data').and_return({ 'errormessage' => dsc_logon_failure_error })
|
701
719
|
allow(context).to receive(:err).with(name_hash[:name], puppet_logon_failure_error)
|
702
720
|
end
|
703
|
-
|
721
|
+
|
722
|
+
after do
|
704
723
|
described_class.class_variable_set(:@@logon_failures, nil) # rubocop:disable Style/ClassVars
|
705
724
|
end
|
706
725
|
|
707
726
|
it 'errors specifically for a logon failure and returns nil' do
|
708
727
|
expect(result).to be_nil
|
709
728
|
end
|
729
|
+
|
710
730
|
it 'caches the logon failure' do
|
711
731
|
expect { result }.not_to raise_error
|
712
732
|
expect(described_class.class_variable_get(:@@logon_failures)).to eq([credential_hash])
|
713
733
|
end
|
734
|
+
|
714
735
|
it 'caches the query results' do
|
715
736
|
expect { result }.not_to raise_error
|
716
737
|
expect(described_class.class_variable_get(:@@cached_query_results)).to eq([name_hash])
|
@@ -727,7 +748,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
727
748
|
end
|
728
749
|
end
|
729
750
|
|
730
|
-
|
751
|
+
describe '.invoke_set_method' do
|
731
752
|
subject(:result) { provider.invoke_set_method(context, name, should_hash) }
|
732
753
|
|
733
754
|
let(:name) { { name: 'foo', dsc_name: 'foo' } }
|
@@ -736,7 +757,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
736
757
|
let(:resource) { "Resource: #{apply_props}" }
|
737
758
|
let(:script) { "Script: #{apply_props}" }
|
738
759
|
|
739
|
-
before
|
760
|
+
before do
|
740
761
|
allow(context).to receive(:debug)
|
741
762
|
allow(provider).to receive(:invocable_resource).with(apply_props, context, 'set').and_return(resource)
|
742
763
|
allow(provider).to receive(:ps_script_content).with(resource).and_return(script)
|
@@ -750,7 +771,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
750
771
|
it 'returns immediately' do
|
751
772
|
expect(provider).to receive(:logon_failed_already?).and_return(true)
|
752
773
|
expect(context).to receive(:err).with('Logon credentials are invalid')
|
753
|
-
expect(result).to
|
774
|
+
expect(result).to be_nil
|
754
775
|
end
|
755
776
|
end
|
756
777
|
|
@@ -766,7 +787,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
766
787
|
it 'writes the error via context but does not raise and returns nil' do
|
767
788
|
expect(ps_manager).to receive(:execute).and_return({ stdout: '{"errormessage": "DSC Error!"}' })
|
768
789
|
expect(context).to receive(:err).with('DSC Error!')
|
769
|
-
expect(result).to
|
790
|
+
expect(result).to be_nil
|
770
791
|
end
|
771
792
|
end
|
772
793
|
|
@@ -779,7 +800,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
779
800
|
end
|
780
801
|
end
|
781
802
|
|
782
|
-
|
803
|
+
describe '.puppetize_name' do
|
783
804
|
it 'downcases the input string' do
|
784
805
|
expect(provider.puppetize_name('FooBar')).to eq('foobar')
|
785
806
|
end
|
@@ -793,7 +814,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
793
814
|
end
|
794
815
|
end
|
795
816
|
|
796
|
-
|
817
|
+
describe '.invocable_resource' do
|
797
818
|
subject(:result) { provider.invocable_resource(should_hash, context, 'Get') }
|
798
819
|
|
799
820
|
let(:definition) do
|
@@ -843,7 +864,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
843
864
|
let(:should_hash) { { dsc_name: 'foo' } }
|
844
865
|
let(:vendored_modules_path) { 'C:/code/puppetlabs/gems/ruby-pwsh/lib/puppet_x/puppetdsc/dsc_resources' }
|
845
866
|
|
846
|
-
before
|
867
|
+
before do
|
847
868
|
allow(context).to receive(:debug)
|
848
869
|
allow(context).to receive(:type).and_return(type)
|
849
870
|
allow(type).to receive(:definition).and_return(definition)
|
@@ -892,11 +913,11 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
892
913
|
end
|
893
914
|
end
|
894
915
|
|
895
|
-
|
916
|
+
describe '.vendored_modules_path' do
|
896
917
|
let(:load_path) { [] }
|
897
918
|
let(:new_path_nil_root_module) { 'C:/code/puppetlabs/gems/ruby-pwsh/lib/puppet_x/puppetdsc/dsc_resources' }
|
898
919
|
|
899
|
-
before
|
920
|
+
before do
|
900
921
|
allow(provider).to receive(:load_path).and_return(load_path)
|
901
922
|
allow(File).to receive(:exist?).and_call_original
|
902
923
|
end
|
@@ -954,34 +975,34 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
954
975
|
end
|
955
976
|
end
|
956
977
|
|
957
|
-
|
978
|
+
describe '.load_path' do
|
958
979
|
it 'returns the ruby LOAD_PATH global variable' do
|
959
980
|
expect(provider.load_path).to eq($LOAD_PATH)
|
960
981
|
end
|
961
982
|
end
|
962
983
|
|
963
|
-
|
964
|
-
subject(:result) { provider.invoke_test_method(context, name,
|
984
|
+
describe '.invoke_test_method' do
|
985
|
+
subject(:result) { provider.invoke_test_method(context, name, test_should) }
|
965
986
|
|
966
987
|
let(:name) { { name: 'foo', dsc_name: 'bar' } }
|
967
|
-
let(:
|
968
|
-
let(:test_properties) {
|
988
|
+
let(:test_should) { name.merge(dsc_ensure: 'present') }
|
989
|
+
let(:test_properties) { test_should.reject { |k, _v| k == :name } }
|
969
990
|
let(:invoke_dsc_resource_data) { nil }
|
970
991
|
|
971
|
-
before
|
992
|
+
before do
|
972
993
|
allow(context).to receive(:notice)
|
973
994
|
allow(context).to receive(:debug)
|
974
995
|
allow(provider).to receive(:invoke_dsc_resource).with(context, name, test_properties, 'test').and_return(invoke_dsc_resource_data)
|
975
996
|
end
|
976
997
|
|
977
|
-
after
|
998
|
+
after do
|
978
999
|
described_class.class_variable_set(:@@cached_test_results, []) # rubocop:disable Style/ClassVars
|
979
1000
|
end
|
980
1001
|
|
981
1002
|
context 'when something went wrong calling Invoke-DscResource' do
|
982
1003
|
it 'falls back on property-by-property state comparison and does not cache anything' do
|
983
1004
|
expect(context).not_to receive(:err)
|
984
|
-
expect(result).to
|
1005
|
+
expect(result).to be_nil
|
985
1006
|
expect(provider.cached_test_results).to eq([])
|
986
1007
|
end
|
987
1008
|
end
|
@@ -991,7 +1012,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
991
1012
|
|
992
1013
|
it 'returns true and caches the result' do
|
993
1014
|
expect(context).not_to receive(:err)
|
994
|
-
expect(result).to
|
1015
|
+
expect(result).to be(true)
|
995
1016
|
expect(provider.cached_test_results).to eq([name.merge(in_desired_state: true)])
|
996
1017
|
end
|
997
1018
|
end
|
@@ -1002,7 +1023,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1002
1023
|
it 'returns false and caches the result' do
|
1003
1024
|
expect(context).not_to receive(:err)
|
1004
1025
|
# Resource is not in the desired state
|
1005
|
-
expect(result.first).to
|
1026
|
+
expect(result.first).to be(false)
|
1006
1027
|
# Custom out-of-sync message passed
|
1007
1028
|
expect(result.last).to match(/not in the desired state/)
|
1008
1029
|
expect(provider.cached_test_results).to eq([name.merge(in_desired_state: false)])
|
@@ -1010,33 +1031,34 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1010
1031
|
end
|
1011
1032
|
end
|
1012
1033
|
|
1013
|
-
|
1034
|
+
describe '.random_variable_name' do
|
1014
1035
|
it 'creates random variables' do
|
1015
1036
|
expect(provider.random_variable_name).not_to be_nil
|
1016
1037
|
end
|
1017
1038
|
|
1018
1039
|
it 'includes underscores instead of hyphens' do
|
1019
1040
|
expect(provider.random_variable_name).to match(/_/)
|
1020
|
-
expect(provider.random_variable_name).
|
1041
|
+
expect(provider.random_variable_name).not_to match(/-/)
|
1021
1042
|
end
|
1022
1043
|
end
|
1023
1044
|
|
1024
|
-
|
1025
|
-
after
|
1045
|
+
describe '.instantiated_variables' do
|
1046
|
+
after do
|
1026
1047
|
described_class.class_variable_set(:@@instantiated_variables, nil) # rubocop:disable Style/ClassVars
|
1027
1048
|
end
|
1028
1049
|
|
1029
1050
|
it 'sets the instantiated_variables class variable to {} if not initialized' do
|
1030
1051
|
expect(provider.instantiated_variables).to eq({})
|
1031
1052
|
end
|
1053
|
+
|
1032
1054
|
it 'returns the instantiated_variables class variable if already initialized' do
|
1033
1055
|
described_class.class_variable_set(:@@instantiated_variables, { foo: 'bar' }) # rubocop:disable Style/ClassVars
|
1034
1056
|
expect(provider.instantiated_variables).to eq({ foo: 'bar' })
|
1035
1057
|
end
|
1036
1058
|
end
|
1037
1059
|
|
1038
|
-
|
1039
|
-
after
|
1060
|
+
describe '.clear_instantiated_variables!' do
|
1061
|
+
after do
|
1040
1062
|
described_class.class_variable_set(:@@instantiated_variables, nil) # rubocop:disable Style/ClassVars
|
1041
1063
|
end
|
1042
1064
|
|
@@ -1047,40 +1069,41 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1047
1069
|
end
|
1048
1070
|
end
|
1049
1071
|
|
1050
|
-
|
1051
|
-
let(:good_password) { instance_double(
|
1052
|
-
let(:bad_password) { instance_double(
|
1072
|
+
describe '.logon_failed_already?' do
|
1073
|
+
let(:good_password) { instance_double(Puppet::Pops::Types::PSensitiveType::Sensitive, 'foo') }
|
1074
|
+
let(:bad_password) { instance_double(Puppet::Pops::Types::PSensitiveType::Sensitive, 'bar') }
|
1053
1075
|
let(:good_credential_hash) { { 'user' => 'foo', 'password' => good_password } }
|
1054
1076
|
let(:bad_credential_hash) { { 'user' => 'bar', 'password' => bad_password } }
|
1055
1077
|
|
1056
1078
|
context 'when the logon_failures cache is empty' do
|
1057
1079
|
it 'returns false' do
|
1058
|
-
expect(provider.logon_failed_already?(good_credential_hash)).to
|
1080
|
+
expect(provider.logon_failed_already?(good_credential_hash)).to be(false)
|
1059
1081
|
end
|
1060
1082
|
end
|
1061
1083
|
|
1062
1084
|
context 'when the logon_failures cache has entries' do
|
1063
|
-
before
|
1085
|
+
before do
|
1064
1086
|
allow(good_password).to receive(:unwrap).and_return('foo')
|
1065
1087
|
allow(bad_password).to receive(:unwrap).and_return('bar')
|
1066
1088
|
end
|
1067
1089
|
|
1068
|
-
after
|
1090
|
+
after do
|
1069
1091
|
described_class.class_variable_set(:@@logon_failures, nil) # rubocop:disable Style/ClassVars
|
1070
1092
|
end
|
1071
1093
|
|
1072
1094
|
it 'returns false if there have been no failed logons with the username/password combination' do
|
1073
1095
|
described_class.class_variable_set(:@@logon_failures, [bad_credential_hash]) # rubocop:disable Style/ClassVars
|
1074
|
-
expect(provider.logon_failed_already?(good_credential_hash)).to
|
1096
|
+
expect(provider.logon_failed_already?(good_credential_hash)).to be(false)
|
1075
1097
|
end
|
1098
|
+
|
1076
1099
|
it 'returns true if the username/password specified are found in the logon_failures class variable' do
|
1077
1100
|
described_class.class_variable_set(:@@logon_failures, [good_credential_hash, bad_credential_hash]) # rubocop:disable Style/ClassVars
|
1078
|
-
expect(provider.logon_failed_already?(bad_credential_hash)).to
|
1101
|
+
expect(provider.logon_failed_already?(bad_credential_hash)).to be(true)
|
1079
1102
|
end
|
1080
1103
|
end
|
1081
1104
|
end
|
1082
1105
|
|
1083
|
-
|
1106
|
+
describe '.downcase_hash_keys!' do
|
1084
1107
|
let(:test_hash) do
|
1085
1108
|
{
|
1086
1109
|
'SomeKey' => 'value',
|
@@ -1116,7 +1139,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1116
1139
|
end
|
1117
1140
|
end
|
1118
1141
|
|
1119
|
-
|
1142
|
+
describe '.munge_cim_instances!' do
|
1120
1143
|
let(:cim_instance) do
|
1121
1144
|
{
|
1122
1145
|
'CertificateSubject' => nil,
|
@@ -1147,7 +1170,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1147
1170
|
}
|
1148
1171
|
end
|
1149
1172
|
|
1150
|
-
before
|
1173
|
+
before { provider.munge_cim_instances!(value) }
|
1151
1174
|
|
1152
1175
|
context 'when called against a non-nested cim instance' do
|
1153
1176
|
let(:value) { cim_instance.dup }
|
@@ -1164,6 +1187,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1164
1187
|
end
|
1165
1188
|
end
|
1166
1189
|
end
|
1190
|
+
|
1167
1191
|
context 'when called against a nested cim instance' do
|
1168
1192
|
let(:value) { nested_cim_instance.dup }
|
1169
1193
|
|
@@ -1190,7 +1214,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1190
1214
|
end
|
1191
1215
|
end
|
1192
1216
|
|
1193
|
-
|
1217
|
+
describe '.recursively_downcase' do
|
1194
1218
|
let(:test_hash) do
|
1195
1219
|
{
|
1196
1220
|
SomeKey: 'Value',
|
@@ -1234,7 +1258,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1234
1258
|
end
|
1235
1259
|
end
|
1236
1260
|
|
1237
|
-
|
1261
|
+
describe '.recursively_sort' do
|
1238
1262
|
let(:test_hash) do
|
1239
1263
|
{
|
1240
1264
|
SomeKey: 'Value',
|
@@ -1276,26 +1300,30 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1276
1300
|
end
|
1277
1301
|
end
|
1278
1302
|
|
1279
|
-
|
1303
|
+
describe '.same?' do
|
1280
1304
|
it 'compares hashes regardless of order' do
|
1281
1305
|
expect(provider.same?({ foo: 1, bar: 2 }, { bar: 2, foo: 1 })).to be true
|
1282
1306
|
end
|
1307
|
+
|
1283
1308
|
it 'compares hashes with nested arrays regardless of order' do
|
1284
1309
|
expect(provider.same?({ foo: [1, 2], bar: { baz: [1, 2] } }, { foo: [2, 1], bar: { baz: [2, 1] } })).to be true
|
1285
1310
|
end
|
1311
|
+
|
1286
1312
|
it 'compares arrays regardless of order' do
|
1287
1313
|
expect(provider.same?([1, 2], [2, 1])).to be true
|
1288
1314
|
end
|
1315
|
+
|
1289
1316
|
it 'compares arrays with nested arrays regardless of order' do
|
1290
1317
|
expect(provider.same?([1, [1, 2]], [[2, 1], 1])).to be true
|
1291
1318
|
end
|
1319
|
+
|
1292
1320
|
it 'compares non enumerables directly' do
|
1293
1321
|
expect(provider.same?(1, 1)).to be true
|
1294
1322
|
expect(provider.same?(1, 2)).to be false
|
1295
1323
|
end
|
1296
1324
|
end
|
1297
1325
|
|
1298
|
-
|
1326
|
+
describe '.mandatory_get_attributes' do
|
1299
1327
|
let(:attributes) do
|
1300
1328
|
{
|
1301
1329
|
name: { type: 'String' },
|
@@ -1312,7 +1340,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1312
1340
|
end
|
1313
1341
|
end
|
1314
1342
|
|
1315
|
-
|
1343
|
+
describe '.mandatory_set_attributes' do
|
1316
1344
|
let(:attributes) do
|
1317
1345
|
{
|
1318
1346
|
name: { type: 'String' },
|
@@ -1329,7 +1357,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1329
1357
|
end
|
1330
1358
|
end
|
1331
1359
|
|
1332
|
-
|
1360
|
+
describe '.namevar_attributes' do
|
1333
1361
|
let(:attributes) do
|
1334
1362
|
{
|
1335
1363
|
name: { type: 'String', behaviour: :namevar },
|
@@ -1347,7 +1375,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1347
1375
|
end
|
1348
1376
|
end
|
1349
1377
|
|
1350
|
-
|
1378
|
+
describe '.parameter_attributes' do
|
1351
1379
|
let(:attributes) do
|
1352
1380
|
{
|
1353
1381
|
name: { type: 'String', behaviour: :namevar },
|
@@ -1365,7 +1393,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1365
1393
|
end
|
1366
1394
|
end
|
1367
1395
|
|
1368
|
-
|
1396
|
+
describe '.enum_attributes' do
|
1369
1397
|
let(:enum_test_attributes) do
|
1370
1398
|
{
|
1371
1399
|
name: { type: 'String' },
|
@@ -1382,7 +1410,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1382
1410
|
end
|
1383
1411
|
end
|
1384
1412
|
|
1385
|
-
|
1413
|
+
describe '.interpolate_variables' do
|
1386
1414
|
let(:instantiated_variables) do
|
1387
1415
|
{
|
1388
1416
|
some_variable_name: 'FooBar',
|
@@ -1391,26 +1419,27 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1391
1419
|
}
|
1392
1420
|
end
|
1393
1421
|
|
1394
|
-
before
|
1422
|
+
before do
|
1395
1423
|
allow(provider).to receive(:instantiated_variables).and_return(instantiated_variables)
|
1396
1424
|
end
|
1397
1425
|
|
1398
1426
|
it 'replaces all discovered pointers to a variable with the variable' do
|
1399
1427
|
expect(provider.interpolate_variables("'FooBar' ; 'FooBar'")).to eq('$some_variable_name ; $some_variable_name')
|
1400
1428
|
end
|
1429
|
+
|
1401
1430
|
it 'replaces discovered pointers in reverse order they were stored' do
|
1402
1431
|
expect(provider.interpolate_variables("'Get-Foo \"bar\"'")).to eq('$third_variable_name')
|
1403
1432
|
end
|
1404
1433
|
end
|
1405
1434
|
|
1406
|
-
|
1435
|
+
describe '.munge_psmodulepath' do
|
1407
1436
|
subject(:result) { provider.munge_psmodulepath(test_resource) }
|
1408
1437
|
|
1409
1438
|
context 'when the resource does not have the dscmeta_resource_implementation key' do
|
1410
1439
|
let(:test_resource) { {} }
|
1411
1440
|
|
1412
1441
|
it 'returns nil' do
|
1413
|
-
expect(result).to
|
1442
|
+
expect(result).to be_nil
|
1414
1443
|
end
|
1415
1444
|
end
|
1416
1445
|
|
@@ -1418,7 +1447,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1418
1447
|
let(:test_resource) { { dscmeta_resource_implementation: 'MOF' } }
|
1419
1448
|
|
1420
1449
|
it 'returns nil' do
|
1421
|
-
expect(result).to
|
1450
|
+
expect(result).to be_nil
|
1422
1451
|
end
|
1423
1452
|
end
|
1424
1453
|
|
@@ -1428,19 +1457,22 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1428
1457
|
it 'sets $UnmungedPSModulePath to the current PSModulePath' do
|
1429
1458
|
expect(result).to match(/\$UnmungedPSModulePath = .+GetEnvironmentVariable.+PSModulePath.+machine/)
|
1430
1459
|
end
|
1460
|
+
|
1431
1461
|
it 'sets $MungedPSModulePath the vendor path with backslash separators' do
|
1432
1462
|
expect(result).to match(/\$MungedPSModulePath = .+;C:\\foo\\bar/)
|
1433
1463
|
end
|
1464
|
+
|
1434
1465
|
it 'updates the system PSModulePath to $MungedPSModulePath' do
|
1435
1466
|
expect(result).to match(/SetEnvironmentVariable\('PSModulePath', \$MungedPSModulePath/)
|
1436
1467
|
end
|
1468
|
+
|
1437
1469
|
it 'sets the process level PSModulePath to the modified system PSModulePath' do
|
1438
1470
|
expect(result).to match(/\$env:PSModulePath = .+GetEnvironmentVariable.+PSModulePath.+machine/)
|
1439
1471
|
end
|
1440
1472
|
end
|
1441
1473
|
end
|
1442
1474
|
|
1443
|
-
|
1475
|
+
describe '.prepare_credentials' do
|
1444
1476
|
subject(:result) { provider.prepare_credentials(test_resource) }
|
1445
1477
|
|
1446
1478
|
let(:base_resource) do
|
@@ -1460,8 +1492,8 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1460
1492
|
end
|
1461
1493
|
|
1462
1494
|
context 'when one or more PSCredentials are passed as parameters' do
|
1463
|
-
let(:foo_password) { instance_double(
|
1464
|
-
let(:bar_password) { instance_double(
|
1495
|
+
let(:foo_password) { instance_double(Puppet::Pops::Types::PSensitiveType::Sensitive, 'foo') }
|
1496
|
+
let(:bar_password) { instance_double(Puppet::Pops::Types::PSensitiveType::Sensitive, 'bar') }
|
1465
1497
|
let(:additional_parameters) do
|
1466
1498
|
{
|
1467
1499
|
parameters: {
|
@@ -1473,12 +1505,12 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1473
1505
|
end
|
1474
1506
|
let(:test_resource) { base_resource.merge(additional_parameters) }
|
1475
1507
|
|
1476
|
-
before
|
1508
|
+
before do
|
1477
1509
|
allow(foo_password).to receive(:unwrap).and_return('foo')
|
1478
1510
|
allow(bar_password).to receive(:unwrap).and_return('bar')
|
1479
1511
|
end
|
1480
1512
|
|
1481
|
-
after
|
1513
|
+
after do
|
1482
1514
|
described_class.class_variable_set(:@@instantiated_variables, nil) # rubocop:disable Style/ClassVars
|
1483
1515
|
end
|
1484
1516
|
|
@@ -1491,6 +1523,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1491
1523
|
expect(first_credential_hash).to eq({ 'user' => 'foo', 'password' => 'foo' })
|
1492
1524
|
expect(second_credential_hash).to eq({ 'user' => 'bar', 'password' => 'bar' })
|
1493
1525
|
end
|
1526
|
+
|
1494
1527
|
it 'returns an array of strings each containing the instantiation of a PowerShell variable representing the credential hash' do
|
1495
1528
|
expect(result[0]).to match(/^\$\w+ = New-PSCredential -User foo -Password 'foo#PuppetSensitive'/)
|
1496
1529
|
expect(result[1]).to match(/^\$\w+ = New-PSCredential -User bar -Password 'bar#PuppetSensitive'/)
|
@@ -1498,7 +1531,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1498
1531
|
end
|
1499
1532
|
end
|
1500
1533
|
|
1501
|
-
|
1534
|
+
describe '.format_pscredential' do
|
1502
1535
|
let(:credential_hash) { { 'user' => 'foo', 'password' => 'bar' } }
|
1503
1536
|
|
1504
1537
|
it 'returns a string representing the instantiation of a PowerShell variable representing the credential hash' do
|
@@ -1507,10 +1540,10 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1507
1540
|
end
|
1508
1541
|
end
|
1509
1542
|
|
1510
|
-
|
1543
|
+
describe '.prepare_cim_instances' do
|
1511
1544
|
subject(:result) { provider.prepare_cim_instances(test_resource) }
|
1512
1545
|
|
1513
|
-
after
|
1546
|
+
after do
|
1514
1547
|
described_class.class_variable_set(:@@instantiated_variables, nil) # rubocop:disable Style/ClassVars
|
1515
1548
|
end
|
1516
1549
|
|
@@ -1528,7 +1561,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1528
1561
|
}
|
1529
1562
|
end
|
1530
1563
|
|
1531
|
-
before
|
1564
|
+
before do
|
1532
1565
|
allow(provider).to receive(:nested_cim_instances).with(test_resource[:parameters][:dsc_someciminstance][:value]).and_return([nil, nil])
|
1533
1566
|
allow(provider).to receive(:random_variable_name).and_return('cim_foo')
|
1534
1567
|
end
|
@@ -1566,7 +1599,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1566
1599
|
[[[{ 'accesscontroltype' => 'Allow', 'ensure' => 'Present', 'cim_instance_type' => 'NTFSAccessControlEntry' }], nil]]
|
1567
1600
|
end
|
1568
1601
|
|
1569
|
-
before
|
1602
|
+
before do
|
1570
1603
|
allow(provider).to receive(:nested_cim_instances).with(test_resource[:parameters][:dsc_accesscontrollist][:value]).and_return(nested_cim_instances)
|
1571
1604
|
allow(provider).to receive(:random_variable_name).and_return('cim_foo', 'cim_bar')
|
1572
1605
|
end
|
@@ -1576,6 +1609,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1576
1609
|
expect(cim_instance_declarations.first).to match(/\$cim_foo =/)
|
1577
1610
|
expect(cim_instance_declarations.first).to match(/ClassName 'NTFSAccessControlEntry'/)
|
1578
1611
|
end
|
1612
|
+
|
1579
1613
|
it 'references nested cim instances as variables in the parent cim instance' do
|
1580
1614
|
cim_instance_declarations = result.split("\n")
|
1581
1615
|
expect(cim_instance_declarations[1]).to match(/\$cim_bar =.+Property @{'accesscontrolentry' = \[CimInstance\[\]\]@\(\$cim_foo\); 'principal' = 'veryRealUserName'}/)
|
@@ -1597,7 +1631,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1597
1631
|
end
|
1598
1632
|
end
|
1599
1633
|
|
1600
|
-
|
1634
|
+
describe '.nested_cim_instances' do
|
1601
1635
|
subject(:nested_cim_instances) { provider.nested_cim_instances(enumerable).flatten }
|
1602
1636
|
|
1603
1637
|
let(:enumerable) do
|
@@ -1617,8 +1651,8 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1617
1651
|
end
|
1618
1652
|
end
|
1619
1653
|
|
1620
|
-
|
1621
|
-
after
|
1654
|
+
describe '.format_ciminstance' do
|
1655
|
+
after do
|
1622
1656
|
described_class.class_variable_set(:@@instantiated_variables, nil) # rubocop:disable Style/ClassVars
|
1623
1657
|
end
|
1624
1658
|
|
@@ -1627,11 +1661,13 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1627
1661
|
expected_command = "$foo = New-CimInstance -ClientOnly -ClassName 'SomeClass' -Property @{'foo' = 1; 'bar' = 'two'}"
|
1628
1662
|
expect(provider.format_ciminstance('foo', 'SomeClass', property_hash)).to eq(expected_command)
|
1629
1663
|
end
|
1664
|
+
|
1630
1665
|
it 'handles arrays of cim instances' do
|
1631
1666
|
property_hash = [{ 'foo' => 1, 'bar' => 'two' }, { 'foo' => 3, 'bar' => 'four' }]
|
1632
1667
|
expected_cim_instance_array_regex = /Property \[CimInstance\[\]\]@\(@\{'foo' = 1; 'bar' = 'two'}, @\{'foo' = 3; 'bar' = 'four'\}\)/
|
1633
1668
|
expect(provider.format_ciminstance('foo', 'SomeClass', property_hash)).to match(expected_cim_instance_array_regex)
|
1634
1669
|
end
|
1670
|
+
|
1635
1671
|
it 'interpolates variables in the case of a cim instance containing a nested instance' do
|
1636
1672
|
described_class.class_variable_set(:@@instantiated_variables, { 'SomeVariable' => { 'bar' => 'ope' } }) # rubocop:disable Style/ClassVars
|
1637
1673
|
property_hash = { 'foo' => { 'bar' => 'ope' } }
|
@@ -1639,7 +1675,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1639
1675
|
end
|
1640
1676
|
end
|
1641
1677
|
|
1642
|
-
|
1678
|
+
describe '.invoke_params' do
|
1643
1679
|
subject(:result) { provider.invoke_params(test_resource) }
|
1644
1680
|
|
1645
1681
|
let(:test_parameter) { { dsc_name: { value: 'foo', mof_type: 'String', mof_is_embedded: false } } }
|
@@ -1659,9 +1695,11 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1659
1695
|
it 'includes the DSC Resource name in the output hash' do
|
1660
1696
|
expect(result).to match(/Name = 'Foo'/)
|
1661
1697
|
end
|
1698
|
+
|
1662
1699
|
it 'includes the specified method in the output hash' do
|
1663
1700
|
expect(result).to match(/Method = 'Get'/)
|
1664
1701
|
end
|
1702
|
+
|
1665
1703
|
it 'includes the properties as a hashtable to pass the DSC Resource in the output hash' do
|
1666
1704
|
expect(result).to match(/Property = @\{name = 'foo'\}/)
|
1667
1705
|
end
|
@@ -1685,7 +1723,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1685
1723
|
}
|
1686
1724
|
end
|
1687
1725
|
let(:expected_module_name) do
|
1688
|
-
"ModuleName =
|
1726
|
+
"ModuleName = @{ModuleName = 'C:/path/to/ruby-pwsh/lib/puppet_x/puppetdsc/dsc_resources/PuppetDsc/PuppetDsc.psd1'; RequiredVersion = '1.2.3.4'}"
|
1689
1727
|
end
|
1690
1728
|
|
1691
1729
|
it 'includes the ModuleName in the output hash as a hashtable of name and version' do
|
@@ -1696,7 +1734,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1696
1734
|
|
1697
1735
|
context 'parameter handling' do
|
1698
1736
|
context 'PSCredential' do
|
1699
|
-
let(:password) { instance_double(
|
1737
|
+
let(:password) { instance_double(Puppet::Pops::Types::PSensitiveType::Sensitive, 'FooPassword') }
|
1700
1738
|
let(:test_parameter) do
|
1701
1739
|
{ dsc_credential: { value: { 'user' => 'foo', 'password' => password }, mof_type: 'PSCredential', mof_is_embedded: false } }
|
1702
1740
|
end
|
@@ -1715,7 +1753,7 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1715
1753
|
end
|
1716
1754
|
|
1717
1755
|
context 'DateTime' do
|
1718
|
-
let(:date_time) { instance_double(
|
1756
|
+
let(:date_time) { instance_double(Puppet::Pops::Time::Timestamp, '2100-01-01') }
|
1719
1757
|
let(:test_parameter) do
|
1720
1758
|
{ dsc_datetime: { value: date_time, mof_type: 'DateTime', mof_is_embedded: false } }
|
1721
1759
|
end
|
@@ -1748,17 +1786,17 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1748
1786
|
end
|
1749
1787
|
end
|
1750
1788
|
|
1751
|
-
|
1752
|
-
let(:gem_root) { File.expand_path('
|
1789
|
+
describe '.ps_script_content' do
|
1790
|
+
let(:gem_root) { File.expand_path('../../../../..', __dir__) }
|
1753
1791
|
let(:template_path) { "#{gem_root}/lib/puppet/provider/dsc_base_provider" }
|
1754
|
-
let(:functions_file_handle) { instance_double(
|
1755
|
-
let(:preamble_file_handle) { instance_double(
|
1756
|
-
let(:postscript_file_handle) { instance_double(
|
1792
|
+
let(:functions_file_handle) { instance_double(File, 'functions_file') }
|
1793
|
+
let(:preamble_file_handle) { instance_double(File, 'preamble_file') }
|
1794
|
+
let(:postscript_file_handle) { instance_double(File, 'postscript_file') }
|
1757
1795
|
let(:expected_script_content) do
|
1758
1796
|
"Functions Block\nPreamble Block\n\n\n\nParameters Block\nPostscript Block"
|
1759
1797
|
end
|
1760
1798
|
|
1761
|
-
before
|
1799
|
+
before do
|
1762
1800
|
allow(File).to receive(:new).with("#{template_path}/invoke_dsc_resource_functions.ps1").and_return(functions_file_handle)
|
1763
1801
|
allow(functions_file_handle).to receive(:read).and_return('Functions Block')
|
1764
1802
|
allow(File).to receive(:new).with("#{template_path}/invoke_dsc_resource_preamble.ps1").and_return(preamble_file_handle)
|
@@ -1777,64 +1815,76 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1777
1815
|
it 'returns a powershell script with the helper functions' do
|
1778
1816
|
expect(provider.ps_script_content('Basic')).to match("Functions Block\n")
|
1779
1817
|
end
|
1818
|
+
|
1780
1819
|
it 'includes the preamble' do
|
1781
1820
|
expect(provider.ps_script_content('Basic')).to match("Preamble Block\n")
|
1782
1821
|
end
|
1822
|
+
|
1783
1823
|
it 'includes the module path block, if needed' do
|
1784
1824
|
expect(provider.ps_script_content('Basic')).not_to match("PSModulePath Block\n")
|
1785
1825
|
expect(provider.ps_script_content('ClassBasedResource')).to match("PSModulePath Block\n")
|
1786
1826
|
end
|
1827
|
+
|
1787
1828
|
it 'includes the credential block, if needed' do
|
1788
1829
|
expect(provider.ps_script_content('Basic')).not_to match("Credential Block\n")
|
1789
1830
|
expect(provider.ps_script_content('ResourceWithCredentials')).to match("Credential Block\n")
|
1790
1831
|
end
|
1832
|
+
|
1791
1833
|
it 'includes the cim instances block, if needed' do
|
1792
1834
|
expect(provider.ps_script_content('Basic')).not_to match("Cim Instance Block\n")
|
1793
1835
|
expect(provider.ps_script_content('ResourceWithCimInstances')).to match("Cim Instance Block\n")
|
1794
1836
|
end
|
1837
|
+
|
1795
1838
|
it 'includes the parameters block' do
|
1796
1839
|
expect(provider.ps_script_content('Basic')).to match("Parameters Block\n")
|
1797
1840
|
end
|
1841
|
+
|
1798
1842
|
it 'includes the postscript block' do
|
1799
1843
|
expect(provider.ps_script_content('Basic')).to match('Postscript Block')
|
1800
1844
|
end
|
1845
|
+
|
1801
1846
|
it 'returns a single string with all the blocks joined' do
|
1802
1847
|
expect(provider.ps_script_content('Basic')).to eq(expected_script_content)
|
1803
1848
|
end
|
1804
1849
|
end
|
1805
1850
|
|
1806
|
-
|
1851
|
+
describe '.format' do
|
1807
1852
|
let(:sensitive_string) { Puppet::Pops::Types::PSensitiveType::Sensitive.new('foo') }
|
1808
1853
|
|
1809
1854
|
it 'uses Pwsh::Util to format the values' do
|
1810
1855
|
expect(Pwsh::Util).to receive(:format_powershell_value).with('foo').and_return('bar')
|
1811
1856
|
expect(provider.format('foo')).to eq('bar')
|
1812
1857
|
end
|
1858
|
+
|
1813
1859
|
it 'handles sensitive values especially' do
|
1814
1860
|
expect(Pwsh::Util).to receive(:format_powershell_value).with(sensitive_string).and_raise(RuntimeError, 'Could not format Sensitive [value redacted]')
|
1815
1861
|
expect(provider).to receive(:unwrap).with(sensitive_string).and_return('foo#PuppetSensitive')
|
1816
1862
|
expect(Pwsh::Util).to receive(:format_powershell_value).with('foo#PuppetSensitive').and_return("'foo#PuppetSensitive'")
|
1817
1863
|
expect(provider.format(sensitive_string)).to eq("'foo#PuppetSensitive'")
|
1818
1864
|
end
|
1865
|
+
|
1819
1866
|
it 'raises an error if Pwsh::Util raises any error not related to unwrapping a sensitive string' do
|
1820
1867
|
expect(Pwsh::Util).to receive(:format_powershell_value).with('foo').and_raise(RuntimeError, 'Ope!')
|
1821
1868
|
expect { provider.format('foo') }.to raise_error(RuntimeError, 'Ope!')
|
1822
1869
|
end
|
1823
1870
|
end
|
1824
1871
|
|
1825
|
-
|
1872
|
+
describe '.unwrap' do
|
1826
1873
|
let(:sensitive_string) { Puppet::Pops::Types::PSensitiveType::Sensitive.new('foo') }
|
1827
1874
|
let(:unwrapped_string) { 'foo#PuppetSensitive' }
|
1828
1875
|
|
1829
1876
|
it 'unwraps a sensitive string, appending "#PuppetSensitive" to the end' do
|
1830
1877
|
expect(provider.unwrap(sensitive_string)).to eq(unwrapped_string)
|
1831
1878
|
end
|
1879
|
+
|
1832
1880
|
it 'handles sensitive values in a hash' do
|
1833
1881
|
expect(provider.unwrap({ key: sensitive_string })).to eq({ key: unwrapped_string })
|
1834
1882
|
end
|
1883
|
+
|
1835
1884
|
it 'handles sensitive values in an array' do
|
1836
1885
|
expect(provider.unwrap([1, sensitive_string])).to eq([1, unwrapped_string])
|
1837
1886
|
end
|
1887
|
+
|
1838
1888
|
it 'handles sensitive values in a deeply nested structure' do
|
1839
1889
|
sensitive_structure = {
|
1840
1890
|
array: [sensitive_string, 'ope'],
|
@@ -1854,12 +1904,13 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1854
1904
|
expect(result[:hash][:nested_array]).to eq([unwrapped_string, 'bar'])
|
1855
1905
|
expect(result[:hash][:nested_hash][:deeply_nested_value]).to eq(unwrapped_string)
|
1856
1906
|
end
|
1907
|
+
|
1857
1908
|
it 'returns the input if it does not include any sensitive strings' do
|
1858
1909
|
expect(provider.unwrap('foo bar baz')).to eq('foo bar baz')
|
1859
1910
|
end
|
1860
1911
|
end
|
1861
1912
|
|
1862
|
-
|
1913
|
+
describe '.escape_quotes' do
|
1863
1914
|
let(:no_quotes) { 'foo bar baz' }
|
1864
1915
|
let(:single_quotes) { "foo 'bar' baz" }
|
1865
1916
|
let(:double_quotes) { 'foo "bar" baz' }
|
@@ -1869,13 +1920,14 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1869
1920
|
expect(provider.escape_quotes(no_quotes)).to eq(no_quotes)
|
1870
1921
|
expect(provider.escape_quotes(double_quotes)).to eq(double_quotes)
|
1871
1922
|
end
|
1923
|
+
|
1872
1924
|
it "replaces single ' with '' in a given string" do
|
1873
1925
|
expect(provider.escape_quotes(single_quotes)).to eq("foo ''bar'' baz")
|
1874
1926
|
expect(provider.escape_quotes(mixed_quotes)).to eq("''foo'' \"bar\" ''\"baz\"''")
|
1875
1927
|
end
|
1876
1928
|
end
|
1877
1929
|
|
1878
|
-
|
1930
|
+
describe '.redact_secrets' do
|
1879
1931
|
let(:unsensitive_string) { 'some very unsecret text' }
|
1880
1932
|
let(:sensitive_string) { "$foo = New-PSCredential -User foo -Password 'foo#PuppetSensitive'" }
|
1881
1933
|
let(:redacted_string) { "$foo = New-PSCredential -User foo -Password '#<Sensitive [value redacted]>'" }
|
@@ -1929,19 +1981,21 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1929
1981
|
it 'does not modify a string without any secrets' do
|
1930
1982
|
expect(provider.redact_secrets(unsensitive_string)).to eq(unsensitive_string)
|
1931
1983
|
end
|
1984
|
+
|
1932
1985
|
it 'replaces any unwrapped secret with "#<Sensitive [Value redacted]>"' do
|
1933
1986
|
expect(provider.redact_secrets(sensitive_string)).to eq(redacted_string)
|
1934
1987
|
expect(provider.redact_secrets(sensitive_array)).to eq(redacted_array)
|
1935
1988
|
expect(provider.redact_secrets(sensitive_hash)).to eq(redacted_hash)
|
1936
1989
|
expect(provider.redact_secrets(sensitive_complex)).to eq(redacted_complex)
|
1937
1990
|
end
|
1991
|
+
|
1938
1992
|
it 'replaces unwrapped secrets in a multiline string' do
|
1939
1993
|
expect(provider.redact_secrets(multiline_sensitive_string)).to eq(multiline_redacted_string)
|
1940
1994
|
expect(provider.redact_secrets(multiline_sensitive_complex)).to eq(multiline_redacted_complex)
|
1941
1995
|
end
|
1942
1996
|
end
|
1943
1997
|
|
1944
|
-
|
1998
|
+
describe '.remove_secret_identifiers' do
|
1945
1999
|
let(:unsensitive_string) { 'some very unsecret text' }
|
1946
2000
|
let(:sensitive_string) { "$foo = New-PSCredential -User foo -Password 'foo#PuppetSensitive'" }
|
1947
2001
|
let(:redacted_string) { "$foo = New-PSCredential -User foo -Password 'foo'" }
|
@@ -1995,28 +2049,32 @@ RSpec.describe Puppet::Provider::DscBaseProvider do
|
|
1995
2049
|
it 'does not modify a string without any secrets' do
|
1996
2050
|
expect(provider.remove_secret_identifiers(unsensitive_string)).to eq(unsensitive_string)
|
1997
2051
|
end
|
2052
|
+
|
1998
2053
|
it 'removes the secret identifier from any unwrapped secret' do
|
1999
2054
|
expect(provider.remove_secret_identifiers(sensitive_string)).to eq(redacted_string)
|
2000
2055
|
expect(provider.remove_secret_identifiers(sensitive_array)).to eq(redacted_array)
|
2001
2056
|
expect(provider.remove_secret_identifiers(sensitive_hash)).to eq(redacted_hash)
|
2002
2057
|
expect(provider.remove_secret_identifiers(sensitive_complex)).to eq(redacted_complex)
|
2003
2058
|
end
|
2059
|
+
|
2004
2060
|
it 'removes the secret identifier from any unwrapped secrets in a multiline string' do
|
2005
2061
|
expect(provider.remove_secret_identifiers(multiline_sensitive_string)).to eq(multiline_redacted_string)
|
2006
2062
|
expect(provider.remove_secret_identifiers(multiline_sensitive_complex)).to eq(multiline_redacted_complex)
|
2007
2063
|
end
|
2008
2064
|
end
|
2009
2065
|
|
2010
|
-
|
2011
|
-
before
|
2066
|
+
describe '.ps_manager' do
|
2067
|
+
before do
|
2012
2068
|
allow(Pwsh::Manager).to receive(:powershell_path).and_return('pwsh')
|
2013
2069
|
allow(Pwsh::Manager).to receive(:powershell_args).and_return('args')
|
2014
2070
|
end
|
2071
|
+
|
2015
2072
|
it 'Initializes an instance of the Pwsh::Manager' do
|
2016
2073
|
expect(Puppet::Util::Log).to receive(:level).and_return(:normal)
|
2017
2074
|
expect(Pwsh::Manager).to receive(:instance).with('pwsh', 'args', debug: false)
|
2018
2075
|
expect { provider.ps_manager }.not_to raise_error
|
2019
2076
|
end
|
2077
|
+
|
2020
2078
|
it 'passes debug as true if Puppet::Util::Log.level is debug' do
|
2021
2079
|
expect(Puppet::Util::Log).to receive(:level).and_return(:debug)
|
2022
2080
|
expect(Pwsh::Manager).to receive(:instance).with('pwsh', 'args', debug: true)
|