ruby-pwsh 0.10.1 → 0.10.3

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: bdcbcec4cceaa40f4fabaad50f9d7409382c14eb1a98a345af5770aa1ae78f31
4
- data.tar.gz: 48f16a70a2305b398a9098d453ae743a6c2630a94cdc8d6716250e1e4ee83464
3
+ metadata.gz: adc4879de83f4b7756c10664ab59c44ab3b34e93e848ebedcefb049c969137f8
4
+ data.tar.gz: 7ffc7b8c36775a252075fe3c0bffbb60c8b2e287bcbec65d61c1594f6ff4522a
5
5
  SHA512:
6
- metadata.gz: 7c19486fd5452d81c71e7939fddaa78c66972ddb425806fc894b1aeecf0cb94b917955d29245130095ee5c4c85d63f2ba12176b6ef8fe4ce7e6f9f653bb0224c
7
- data.tar.gz: b12c1ab52269745152a29ce446876a3e06f3b9f9aab1d254157d8f93c6cccb1e7f997c118488229e22d8800a1a1a17af0557a8c0af2ea386d3e80e80c2f5bfd0
6
+ metadata.gz: 638fb1d09d7c0ec4fe29ee0473dba74cdbf2aa142a730eed6c43b0e472ec2f3a7452a87e18ff8c36a4dd95f0897ec8388d30357406481aea8772d409087183b7
7
+ data.tar.gz: d5de2cb597e68c7c911b36c1cd92cbfc50a13916570f744bc8674b138ed62c30cc728ac2dba8f50a2856e6915ceb48ceede851c6f11a91cf8cca1af2d6cdfe9c
data/README.md CHANGED
@@ -74,47 +74,51 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
74
74
 
75
75
  Steps to release an update to the gem and module include:
76
76
 
77
- 1. Ensure that the release branch is up to date with the main:
77
+ 1. From main, checkout a new working branch for the release prep (where xyz is the appropriate version, sans periods):
78
78
  ```bash
79
- git push upstream upstream/main:release --force
79
+ git checkout -b maint-release_prep_xyz
80
80
  ```
81
- 1. Checkout a new working branch for the release prep (where xyz is the appropriate version, sans periods):
82
- ```bash
83
- git checkout -b maint/release/prep-xyz upstream/release
84
- ```
85
- 1. Update the version in `lib/pwsh/version.rb` and `metadata.json` to the appropriate version for the new release.
86
- 1. Run the changelog update task (make sure to verify the changelog, correctly tagging PRs as needed):
81
+
82
+ 2. Update the version in `lib/pwsh/version.rb` and `metadata.json` to the appropriate version for the new release.
83
+
84
+ 3. Run the changelog update task (make sure to verify the changelog, correctly tagging PRs as needed):
87
85
  ```bash
88
86
  bundle exec rake changelog
89
87
  ```
90
- 1. Commit your changes with a short, sensible commit message, like:
91
- ```text
88
+
89
+ 4. Commit your changes with a short, sensible commit message, like:
90
+ ```bash
92
91
  git add lib/pwsh/version.rb
93
92
  git add metadata.json
94
93
  git add CHANGELOG.md
95
94
  git commit -m '(MAINT) Prep for x.y.z release'
96
95
  ```
97
- 1. Push your changes and submit a pull request for review _against the **release** branch_:
98
- ```bash
99
- git push -u origin maint/release/prep-xyz
100
- ```
101
- 1. Ensure tests pass and the code is merged to `release`.
102
- 1. Grab the commit hash from the merge commit on release, use that as the tag for the version (replacing `x.y.z` with the appropriate version and `commithash` with the relevant one), then push the tags to upstream:
96
+
97
+ 5. Push your changes and submit a pull request for review _against main:
103
98
  ```bash
104
- bundle exec rake tag['x.y.z', 'commithash']
99
+ git push -u origin maint_release_prep_xyz
105
100
  ```
106
- 1. Build the Ruby gem and publish:
101
+
102
+ 6. Ensure tests pass and the code is merged to `main`.
103
+
104
+ 7. Once the release_prep PR has been merged, checkout main and pull down the latests changes.
107
105
  ```bash
108
- bundle exec rake build
109
- bundle exec rake push['ruby-pwsh-x.y.z.gem']
106
+ git checkout main
107
+ git pull
110
108
  ```
111
- 1. Verify that the correct version now exists on [RubyGems](https://rubygems.org/search?query=ruby-pwsh)
112
- 1. Build the Puppet module:
109
+
110
+ 8. Assuming that the release_prep merge commit is at the HEAD of main we can simply create and push a tag as follows (replacing xyz with the appropriate version).
113
111
  ```bash
114
- bundle exec rake build_module
112
+ git tag -a xyx -m "Release xyz"
113
+ git push --follow-tags
115
114
  ```
116
- 1. Publish the updated module version (found in the `pkg` folder) to [the Forge](https://forge.puppet.com/puppetlabs/pwshlib).
117
- 1. Submit the [mergeback PR from the release branch to main](https://github.com/puppetlabs/ruby-pwsh/compare/main...release).
115
+
116
+ 9. Execute the publish workflow. This will:
117
+ - Create a GitHub release
118
+ - Build and publish the Gem
119
+ - Build and publish the Puppet module
120
+
121
+ 10. Finally check that the expected versions are present on rubygems.org and the Forge.
118
122
 
119
123
  ## Known Issues
120
124
 
@@ -79,6 +79,9 @@ class Puppet::Provider::DscBaseProvider
79
79
  end
80
80
  downcased_result = recursively_downcase(canonicalized)
81
81
  downcased_resource = recursively_downcase(r)
82
+ # Ensure that metaparameters are preserved when we canonicalize the resource.
83
+ metaparams = downcased_resource.select { |key, _value| Puppet::Type.metaparam?(key) }
84
+ canonicalized.merge!(metaparams) unless metaparams.nil?
82
85
  downcased_result.each do |key, value|
83
86
  # Canonicalize to the manifest value unless the downcased strings match and the attribute is not an enum:
84
87
  # - When the values don't match at all, the manifest value is desired;
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.10.1'
5
+ VERSION = '0.10.3'
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 |
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'ruby-pwsh'
5
+ require 'securerandom'
6
+
7
+ powershell = Pwsh::Manager.instance(Pwsh::Manager.powershell_path, Pwsh::Manager.powershell_args)
8
+ module_path = File.expand_path('../../fixtures/modules', File.dirname(__FILE__))
9
+ powershellget_path = File.expand_path('powershellget/lib/puppet_x/powershellget/dsc_resources/PowerShellGet', module_path)
10
+ local_user = ['dsc', SecureRandom.uuid.slice(0, 7)].join('_')
11
+ local_pw = SecureRandom.uuid
12
+
13
+ def execute_reset_command(reset_command)
14
+ manager = Pwsh::Manager.instance(Pwsh::Manager.powershell_path, Pwsh::Manager.powershell_args)
15
+ result = manager.execute(reset_command)
16
+ raise result[:errormessage] unless result[:errormessage].nil?
17
+ end
18
+
19
+ RSpec.describe 'DSC Acceptance: Basic' do
20
+ let(:puppet_apply) do
21
+ "bundle exec puppet apply --modulepath #{module_path} --detailed-exitcodes --debug --trace"
22
+ end
23
+ let(:command) { "#{puppet_apply} -e \"#{manifest}\"" }
24
+
25
+ context 'Updating' do
26
+ let(:manifest) do
27
+ # This very awkward pattern is because we're not writing
28
+ # manifest files and need to pass them directly to puppet apply.
29
+ [
30
+ "dsc_psrepository { 'Trust PSGallery':",
31
+ "dsc_name => 'PSGallery',",
32
+ "dsc_ensure => 'Present',",
33
+ "dsc_installationpolicy => 'Trusted'",
34
+ '}'
35
+ ].join(' ')
36
+ end
37
+
38
+ before(:all) do
39
+ reset_command = <<~RESET_COMMAND
40
+ $ErrorActionPreference = 'Stop'
41
+ Import-Module PowerShellGet
42
+ $ResetParameters = @{
43
+ Name = 'PSRepository'
44
+ ModuleName = '#{powershellget_path}'
45
+ Method = 'Set'
46
+ Property = @{
47
+ Name = 'PSGallery'
48
+ Ensure = 'Present'
49
+ InstallationPolicy = 'Untrusted'
50
+ }
51
+ }
52
+ Invoke-DscResource @ResetParameters | ConvertTo-Json -Compress
53
+ RESET_COMMAND
54
+ execute_reset_command(reset_command)
55
+ end
56
+
57
+ it 'applies idempotently' do
58
+ first_run_result = powershell.execute(command)
59
+ expect(first_run_result[:exitcode]).to be(2)
60
+ expect(first_run_result[:native_stdout]).to match(/dsc_installationpolicy changed 'Untrusted' to 'Trusted'/)
61
+ expect(first_run_result[:native_stdout]).to match(/Updating: Finished/)
62
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
63
+ second_run_result = powershell.execute(command)
64
+ expect(second_run_result[:exitcode]).to be(0)
65
+ end
66
+ end
67
+ context 'Creating' do
68
+ let(:manifest) do
69
+ [
70
+ "dsc_psmodule { 'Install BurntToast':",
71
+ "dsc_name => 'BurntToast',",
72
+ "dsc_ensure => 'Present',",
73
+ '}'
74
+ ].join(' ')
75
+ end
76
+
77
+ before(:all) do
78
+ reset_command = <<~RESET_COMMAND
79
+ $ErrorActionPreference = 'Stop'
80
+ Import-Module PowerShellGet
81
+ Get-InstalledModule -Name BurntToast -ErrorAction SilentlyContinue |
82
+ Uninstall-Module -Force
83
+ RESET_COMMAND
84
+ execute_reset_command(reset_command)
85
+ end
86
+
87
+ it 'applies idempotently' do
88
+ first_run_result = powershell.execute(command)
89
+ expect(first_run_result[:exitcode]).to be(2)
90
+ expect(first_run_result[:native_stdout]).to match(/dsc_ensure changed 'Absent' to 'Present'/)
91
+ expect(first_run_result[:native_stdout]).to match(/Creating: Finished/)
92
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
93
+ second_run_result = powershell.execute(command)
94
+ expect(second_run_result[:exitcode]).to be(0)
95
+ end
96
+ end
97
+
98
+ context 'Deleting' do
99
+ let(:manifest) do
100
+ [
101
+ "dsc_psmodule { 'Install BurntToast':",
102
+ "dsc_name => 'BurntToast',",
103
+ "dsc_ensure => 'Absent',",
104
+ '}'
105
+ ].join(' ')
106
+ end
107
+
108
+ before(:all) do
109
+ reset_command = <<~RESET_COMMAND
110
+ $ErrorActionPreference = 'Stop'
111
+ Import-Module PowerShellGet
112
+ $Installed = Get-InstalledModule -Name BurntToast -ErrorAction SilentlyContinue
113
+ If($null -eq $Installed) {
114
+ Install-Module -Name BurntToast -Scope AllUsers -Force
115
+ }
116
+ RESET_COMMAND
117
+ execute_reset_command(reset_command)
118
+ end
119
+
120
+ it 'applies idempotently' do
121
+ first_run_result = powershell.execute(command)
122
+ expect(first_run_result[:exitcode]).to be(2)
123
+ expect(first_run_result[:native_stdout]).to match(/dsc_ensure changed 'Present' to 'Absent'/)
124
+ expect(first_run_result[:native_stdout]).to match(/Deleting: Finished/)
125
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
126
+ second_run_result = powershell.execute(command)
127
+ expect(second_run_result[:exitcode]).to be(0)
128
+ end
129
+ end
130
+ context 'PSDscRunAsCredential' do
131
+ before(:all) do
132
+ prep_command = <<~PREP_USER.strip
133
+ $ErrorActionPreference = 'Stop'
134
+ $User = Get-LocalUser -Name #{local_user} -ErrorAction SilentlyContinue
135
+ If ($null -eq $User) {
136
+ $Secure = ConvertTo-SecureString -String '#{local_pw}' -AsPlainText -Force
137
+ $User = New-LocalUser -Name #{local_user} -Password $Secure -Verbose
138
+ }
139
+ If ($User.Name -notin (Get-LocalGroupMember -Group Administrators).Name) {
140
+ Add-LocalGroupMember -Group Administrators -Member $User -Verbose
141
+ }
142
+ Get-LocalGroupMember -Group Administrators |
143
+ Where-Object Name -match '#{local_user}'
144
+ PREP_USER
145
+ execute_reset_command(prep_command)
146
+ end
147
+ after(:all) do
148
+ cleanup_command = <<~CLEANUP_USER.strip
149
+ Remove-LocalUser -Name #{local_user} -ErrorAction Stop
150
+ CLEANUP_USER
151
+ execute_reset_command(cleanup_command)
152
+ end
153
+
154
+ context 'with a valid credential' do
155
+ let(:manifest) do
156
+ [
157
+ "dsc_psrepository { 'Trust PSGallery':",
158
+ "dsc_name => 'PSGallery',",
159
+ "dsc_ensure => 'Present',",
160
+ "dsc_installationpolicy => 'Trusted',",
161
+ 'dsc_psdscrunascredential => {',
162
+ "'user' => '#{local_user}',",
163
+ "'password' => Sensitive('#{local_pw}')",
164
+ '}',
165
+ '}'
166
+ ].join(' ')
167
+ end
168
+
169
+ it 'applies idempotently without leaking secrets' do
170
+ first_run_result = powershell.execute(command)
171
+ expect(first_run_result[:exitcode]).to be(2)
172
+ expect(first_run_result[:native_stdout]).to match(/dsc_installationpolicy changed 'Untrusted' to 'Trusted'/)
173
+ expect(first_run_result[:native_stdout]).to match(/Updating: Finished/)
174
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
175
+ expect(first_run_result[:native_stdout]).to match(/'#<Sensitive \[value redacted\]>'/)
176
+ expect(first_run_result[:native_stdout]).not_to match(local_pw)
177
+ second_run_result = powershell.execute(command)
178
+ expect(second_run_result[:exitcode]).to be(0)
179
+ end
180
+ end
181
+ context 'with an invalid credential' do
182
+ let(:manifest) do
183
+ [
184
+ "dsc_psrepository { 'Trust PSGallery':",
185
+ "dsc_name => 'PSGallery',",
186
+ "dsc_ensure => 'Present',",
187
+ "dsc_installationpolicy => 'Trusted',",
188
+ 'dsc_psdscrunascredential => {',
189
+ "'user' => 'definitely_do_not_exist_here',",
190
+ "'password' => Sensitive('#{local_pw}')",
191
+ '}',
192
+ '}'
193
+ ].join(' ')
194
+ end
195
+
196
+ it 'errors loudly without leaking secrets' do
197
+ first_run_result = powershell.execute(command)
198
+ expect(first_run_result[:exitcode]).to be(4)
199
+ expect(first_run_result[:stderr].first).to match(/dsc_psrepository: The user name or password is incorrect/)
200
+ expect(first_run_result[:native_stdout]).to match(/'#<Sensitive \[value redacted\]>'/)
201
+ expect(first_run_result[:native_stdout]).not_to match(local_pw)
202
+ end
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+ # TODO: Test against mcollera/AccessControlDsc for CIM instance behavior
3
+ # 1. Make sure valid nested CIM instances can be passed to Invoke-DscResource
4
+ # 2. Make sure nested CIM instances can be read back from Invoke-DscResource
5
+
6
+ # frozen_string_literal: true
7
+
8
+ require 'spec_helper'
9
+ require 'ruby-pwsh'
10
+
11
+ # Needs to be declared here so it is usable in before and it blocks alike
12
+ test_manifest = File.expand_path('../../fixtures/test.pp', File.dirname(__FILE__))
13
+ fixtures_path = File.expand_path('../../fixtures', File.dirname(__FILE__))
14
+
15
+ def execute_reset_command(reset_command)
16
+ manager = Pwsh::Manager.instance(Pwsh::Manager.powershell_path, Pwsh::Manager.powershell_args)
17
+ result = manager.execute(reset_command)
18
+ raise result[:errormessage] unless result[:errormessage].nil?
19
+ end
20
+
21
+ RSpec.describe 'DSC Acceptance: Complex' do
22
+ let(:powershell) { Pwsh::Manager.instance(Pwsh::Manager.powershell_path, Pwsh::Manager.powershell_args) }
23
+ let(:module_path) { File.expand_path('../../fixtures/modules', File.dirname(__FILE__)) }
24
+ let(:puppet_apply) do
25
+ "bundle exec puppet apply #{test_manifest} --modulepath #{module_path} --detailed-exitcodes --trace"
26
+ end
27
+
28
+ context 'Managing the access control list of a folder' do
29
+ before(:each) do
30
+ reset_command = <<~RESET_COMMAND
31
+ $TestFolderPath = Join-Path -Path "#{fixtures_path}" -Childpath access_control
32
+ # Delete the test folder if it exists (to clear access control modifications)
33
+ If (Test-Path -Path $TestFolderPath -PathType Container) {
34
+ Remove-Item $TestFolderPath -Recurse -Force
35
+ }
36
+ # Create the test folder
37
+ New-Item $TestFolderPath -ItemType Directory
38
+ RESET_COMMAND
39
+ execute_reset_command(reset_command)
40
+ end
41
+
42
+ it 'applies idempotently' do
43
+ content = <<~MANIFEST.strip
44
+ $test_folder_path = "#{fixtures_path}/access_control"
45
+ # Configure access to the test folder
46
+ dsc_ntfsaccessentry {'Test':
47
+ dsc_path => $test_folder_path,
48
+ dsc_accesscontrollist => [
49
+ {
50
+ principal => 'Everyone',
51
+ forceprincipal => true,
52
+ accesscontrolentry => [
53
+ {
54
+ accesscontroltype => 'Allow',
55
+ filesystemrights => ['FullControl'],
56
+ inheritance => 'This folder and files',
57
+ ensure => 'Present',
58
+ cim_instance_type => 'NTFSAccessControlEntry',
59
+ }
60
+ ]
61
+ }
62
+ ]
63
+ }
64
+ MANIFEST
65
+ File.open(test_manifest, 'w') { |file| file.write(content) }
66
+ # Apply the test manifest
67
+ first_run_result = powershell.execute(puppet_apply)
68
+ expect(first_run_result[:exitcode]).to be(2)
69
+ # Access Control Set
70
+ expect(first_run_result[:native_stdout]).to match(/dsc_accesscontrollist: dsc_accesscontrollist changed/)
71
+ expect(first_run_result[:native_stdout]).to match(%r{dsc_ntfsaccessentry\[{:name=>"Test", :dsc_path=>".+/spec/fixtures/access_control"}\]: Updating: Finished})
72
+ expect(first_run_result[:stderr]).not_to match(/Error/)
73
+ expect(first_run_result[:stderr]).not_to match(/Warning: Provider returned data that does not match the Type Schema/)
74
+ expect(first_run_result[:stderr]).not_to match(/Value type mismatch/)
75
+ # Run finished
76
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
77
+ # Second run is idempotent
78
+ second_run_result = powershell.execute(puppet_apply)
79
+ expect(second_run_result[:exitcode]).to be(0)
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'ruby-pwsh'
5
+
6
+ powershell = Pwsh::Manager.instance(Pwsh::Manager.powershell_path, Pwsh::Manager.powershell_args)
7
+ module_path = File.expand_path('../../fixtures/modules', File.dirname(__FILE__))
8
+ psrc_path = File.expand_path('../../fixtures/example.psrc', File.dirname(__FILE__))
9
+
10
+ def execute_reset_command(reset_command)
11
+ manager = Pwsh::Manager.instance(Pwsh::Manager.powershell_path, Pwsh::Manager.powershell_args)
12
+ result = manager.execute(reset_command)
13
+ raise result[:errormessage] unless result[:errormessage].nil?
14
+ end
15
+
16
+ RSpec.describe 'DSC Acceptance: Class-Based Resource' do
17
+ let(:puppet_apply) do
18
+ "bundle exec puppet apply --modulepath #{module_path} --detailed-exitcodes --debug --trace"
19
+ end
20
+ let(:command) { "#{puppet_apply} -e \"#{manifest}\"" }
21
+
22
+ context 'Creating' do
23
+ let(:manifest) do
24
+ # This very awkward pattern is because we're not writing
25
+ # manifest files and need to pass them directly to puppet apply.
26
+ [
27
+ "dsc_jearolecapabilities { 'ExampleRoleCapability':",
28
+ "dsc_ensure => 'Present',",
29
+ "dsc_path => '#{psrc_path}',",
30
+ "dsc_description => 'Example role capability file'",
31
+ '}'
32
+ ].join(' ')
33
+ end
34
+
35
+ before(:each) do
36
+ reset_command = <<~RESET_COMMAND
37
+ $PsrcPath = '#{psrc_path}'
38
+ # Delete the test PSRC fixture if it exists
39
+ If (Test-Path -Path $PsrcPath -PathType Leaf) {
40
+ Remove-Item $PsrcPath -Force
41
+ }
42
+ RESET_COMMAND
43
+ execute_reset_command(reset_command)
44
+ end
45
+
46
+ it 'applies idempotently' do
47
+ first_run_result = powershell.execute(command)
48
+ expect(first_run_result[:exitcode]).to be(2)
49
+ expect(first_run_result[:native_stdout]).to match(//)
50
+ expect(first_run_result[:native_stdout]).to match(/dsc_description changed to 'Example role capability file'/)
51
+ expect(first_run_result[:native_stdout]).to match(/Creating: Finished/)
52
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
53
+ second_run_result = powershell.execute(command)
54
+ expect(second_run_result[:exitcode]).to be(0)
55
+ end
56
+ end
57
+
58
+ context 'Updating' do
59
+ let(:manifest) do
60
+ # This very awkward pattern is because we're not writing
61
+ # manifest files and need to pass them directly to puppet apply.
62
+ [
63
+ "dsc_jearolecapabilities { 'ExampleRoleCapability':",
64
+ "dsc_ensure => 'Present',",
65
+ "dsc_path => '#{psrc_path}',",
66
+ "dsc_description => 'Updated role capability file'",
67
+ '}'
68
+ ].join(' ')
69
+ end
70
+
71
+ before(:each) do
72
+ reset_command = <<~RESET_COMMAND
73
+ $PsrcPath = '#{psrc_path}'
74
+ # Delete the test PSRC fixture if it exists
75
+ If (Test-Path -Path $PsrcPath -PathType Leaf) {
76
+ Remove-Item $PsrcPath -Force
77
+ }
78
+ # Create the test PSRC fixture
79
+ New-Item $PsrcPath -ItemType File -Value "@{'Description' = 'Example role capability file'}"
80
+ RESET_COMMAND
81
+ execute_reset_command(reset_command)
82
+ end
83
+
84
+ it 'applies idempotently' do
85
+ first_run_result = powershell.execute(command)
86
+ expect(first_run_result[:exitcode]).to be(2)
87
+ expect(first_run_result[:native_stdout]).to match(/dsc_description changed 'Example role capability file' to 'Updated role capability file'/)
88
+ expect(first_run_result[:native_stdout]).to match(/Updating: Finished/)
89
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
90
+ second_run_result = powershell.execute(command)
91
+ expect(second_run_result[:exitcode]).to be(0)
92
+ end
93
+ end
94
+
95
+ context 'Deleting' do
96
+ let(:manifest) do
97
+ # This very awkward pattern is because we're not writing
98
+ # manifest files and need to pass them directly to puppet apply.
99
+ [
100
+ "dsc_jearolecapabilities { 'ExampleRoleCapability':",
101
+ "dsc_ensure => 'Absent',",
102
+ "dsc_path => '#{psrc_path}'",
103
+ '}'
104
+ ].join(' ')
105
+ end
106
+
107
+ before(:each) do
108
+ reset_command = <<~RESET_COMMAND
109
+ $PsrcPath = '#{psrc_path}'
110
+ # Delete the test PSRC fixture if it exists
111
+ If (!(Test-Path -Path $PsrcPath -PathType Leaf)) {
112
+ # Create the test PSRC fixture
113
+ New-Item $PsrcPath -ItemType File -Value "@{'Description' = 'Updated'}"
114
+ }
115
+ RESET_COMMAND
116
+ execute_reset_command(reset_command)
117
+ end
118
+
119
+ it 'applies idempotently' do
120
+ first_run_result = powershell.execute(command)
121
+ expect(first_run_result[:exitcode]).to be(2)
122
+ expect(first_run_result[:native_stdout]).to match(/dsc_ensure changed 'Present' to 'Absent'/)
123
+ expect(first_run_result[:native_stdout]).to match(/Deleting: Finished/)
124
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
125
+ second_run_result = powershell.execute(command)
126
+ expect(second_run_result[:exitcode]).to be(0)
127
+ end
128
+ end
129
+ end