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 +4 -4
- data/README.md +29 -25
- data/lib/puppet/provider/dsc_base_provider/dsc_base_provider.rb +3 -0
- data/lib/pwsh/version.rb +1 -1
- data/lib/pwsh.rb +1 -1
- data/lib/templates/init.ps1 +11 -1
- data/spec/acceptance/dsc/basic.rb +205 -0
- data/spec/acceptance/dsc/cim_instances.rb +82 -0
- data/spec/acceptance/dsc/class.rb +129 -0
- data/spec/acceptance/dsc/complex.rb +139 -0
- data/spec/exit-27.ps1 +1 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/unit/puppet/provider/dsc_base_provider/dsc_base_provider_spec.rb +2026 -0
- data/spec/unit/pwsh/util_spec.rb +286 -0
- data/spec/unit/pwsh/version_spec.rb +10 -0
- data/spec/unit/pwsh/windows_powershell_spec.rb +116 -0
- data/spec/unit/pwsh_spec.rb +823 -0
- metadata +17 -22
- data/.gitattributes +0 -2
- data/.github/workflows/ci.yml +0 -109
- data/.gitignore +0 -23
- data/.pmtignore +0 -21
- data/.rspec +0 -3
- data/CHANGELOG.md +0 -196
- data/CODEOWNERS +0 -2
- data/CONTRIBUTING.md +0 -155
- data/DESIGN.md +0 -70
- data/Gemfile +0 -54
- data/LICENSE.txt +0 -21
- data/Rakefile +0 -188
- data/design-comms.png +0 -0
- data/metadata.json +0 -82
- data/pwshlib.md +0 -92
- data/ruby-pwsh.gemspec +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: adc4879de83f4b7756c10664ab59c44ab3b34e93e848ebedcefb049c969137f8
|
4
|
+
data.tar.gz: 7ffc7b8c36775a252075fe3c0bffbb60c8b2e287bcbec65d61c1594f6ff4522a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
79
|
+
git checkout -b maint-release_prep_xyz
|
80
80
|
```
|
81
|
-
|
82
|
-
|
83
|
-
|
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
|
-
|
91
|
-
|
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
|
-
|
98
|
-
|
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
|
-
|
99
|
+
git push -u origin maint_release_prep_xyz
|
105
100
|
```
|
106
|
-
|
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
|
-
|
109
|
-
|
106
|
+
git checkout main
|
107
|
+
git pull
|
110
108
|
```
|
111
|
-
|
112
|
-
|
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
|
-
|
112
|
+
git tag -a xyx -m "Release xyz"
|
113
|
+
git push --follow-tags
|
115
114
|
```
|
116
|
-
|
117
|
-
|
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
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
|
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
|
data/lib/templates/init.ps1
CHANGED
@@ -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
|
-
|
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
|