ruby-pwsh 0.10.2 → 0.11.0.rc.1

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.
@@ -0,0 +1,209 @@
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
+
68
+ context 'Creating' do
69
+ let(:manifest) do
70
+ [
71
+ "dsc_psmodule { 'Install BurntToast':",
72
+ "dsc_name => 'BurntToast',",
73
+ "dsc_ensure => 'Present',",
74
+ '}'
75
+ ].join(' ')
76
+ end
77
+
78
+ before(:all) do
79
+ reset_command = <<~RESET_COMMAND
80
+ $ErrorActionPreference = 'Stop'
81
+ Import-Module PowerShellGet
82
+ Get-InstalledModule -Name BurntToast -ErrorAction SilentlyContinue |
83
+ Uninstall-Module -Force
84
+ RESET_COMMAND
85
+ execute_reset_command(reset_command)
86
+ end
87
+
88
+ it 'applies idempotently' do
89
+ first_run_result = powershell.execute(command)
90
+ expect(first_run_result[:exitcode]).to be(2)
91
+ expect(first_run_result[:native_stdout]).to match(/dsc_ensure changed 'Absent' to 'Present'/)
92
+ expect(first_run_result[:native_stdout]).to match(/Creating: Finished/)
93
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
94
+ second_run_result = powershell.execute(command)
95
+ expect(second_run_result[:exitcode]).to be(0)
96
+ end
97
+ end
98
+
99
+ context 'Deleting' do
100
+ let(:manifest) do
101
+ [
102
+ "dsc_psmodule { 'Install BurntToast':",
103
+ "dsc_name => 'BurntToast',",
104
+ "dsc_ensure => 'Absent',",
105
+ '}'
106
+ ].join(' ')
107
+ end
108
+
109
+ before(:all) do
110
+ reset_command = <<~RESET_COMMAND
111
+ $ErrorActionPreference = 'Stop'
112
+ Import-Module PowerShellGet
113
+ $Installed = Get-InstalledModule -Name BurntToast -ErrorAction SilentlyContinue
114
+ If($null -eq $Installed) {
115
+ Install-Module -Name BurntToast -Scope AllUsers -Force
116
+ }
117
+ RESET_COMMAND
118
+ execute_reset_command(reset_command)
119
+ end
120
+
121
+ it 'applies idempotently' do
122
+ first_run_result = powershell.execute(command)
123
+ expect(first_run_result[:exitcode]).to be(2)
124
+ expect(first_run_result[:native_stdout]).to match(/dsc_ensure changed 'Present' to 'Absent'/)
125
+ expect(first_run_result[:native_stdout]).to match(/Deleting: Finished/)
126
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
127
+ second_run_result = powershell.execute(command)
128
+ expect(second_run_result[:exitcode]).to be(0)
129
+ end
130
+ end
131
+
132
+ context 'PSDscRunAsCredential' do
133
+ before(:all) do
134
+ prep_command = <<~PREP_USER.strip
135
+ $ErrorActionPreference = 'Stop'
136
+ $User = Get-LocalUser -Name #{local_user} -ErrorAction SilentlyContinue
137
+ If ($null -eq $User) {
138
+ $Secure = ConvertTo-SecureString -String '#{local_pw}' -AsPlainText -Force
139
+ $User = New-LocalUser -Name #{local_user} -Password $Secure -Verbose
140
+ }
141
+ If ($User.Name -notin (Get-LocalGroupMember -Group Administrators).Name) {
142
+ Add-LocalGroupMember -Group Administrators -Member $User -Verbose
143
+ }
144
+ Get-LocalGroupMember -Group Administrators |
145
+ Where-Object Name -match '#{local_user}'
146
+ PREP_USER
147
+ execute_reset_command(prep_command)
148
+ end
149
+
150
+ after(:all) do
151
+ cleanup_command = <<~CLEANUP_USER.strip
152
+ Remove-LocalUser -Name #{local_user} -ErrorAction Stop
153
+ CLEANUP_USER
154
+ execute_reset_command(cleanup_command)
155
+ end
156
+
157
+ context 'with a valid credential' do
158
+ let(:manifest) do
159
+ [
160
+ "dsc_psrepository { 'Trust PSGallery':",
161
+ "dsc_name => 'PSGallery',",
162
+ "dsc_ensure => 'Present',",
163
+ "dsc_installationpolicy => 'Trusted',",
164
+ 'dsc_psdscrunascredential => {',
165
+ "'user' => '#{local_user}',",
166
+ "'password' => Sensitive('#{local_pw}')",
167
+ '}',
168
+ '}'
169
+ ].join(' ')
170
+ end
171
+
172
+ it 'applies idempotently without leaking secrets' do
173
+ first_run_result = powershell.execute(command)
174
+ expect(first_run_result[:exitcode]).to be(2)
175
+ expect(first_run_result[:native_stdout]).to match(/dsc_installationpolicy changed 'Untrusted' to 'Trusted'/)
176
+ expect(first_run_result[:native_stdout]).to match(/Updating: Finished/)
177
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
178
+ expect(first_run_result[:native_stdout]).to match(/'#<Sensitive \[value redacted\]>'/)
179
+ expect(first_run_result[:native_stdout]).not_to match(local_pw)
180
+ second_run_result = powershell.execute(command)
181
+ expect(second_run_result[:exitcode]).to be(0)
182
+ end
183
+ end
184
+
185
+ context 'with an invalid credential' do
186
+ let(:manifest) do
187
+ [
188
+ "dsc_psrepository { 'Trust PSGallery':",
189
+ "dsc_name => 'PSGallery',",
190
+ "dsc_ensure => 'Present',",
191
+ "dsc_installationpolicy => 'Trusted',",
192
+ 'dsc_psdscrunascredential => {',
193
+ "'user' => 'definitely_do_not_exist_here',",
194
+ "'password' => Sensitive('#{local_pw}')",
195
+ '}',
196
+ '}'
197
+ ].join(' ')
198
+ end
199
+
200
+ it 'errors loudly without leaking secrets' do
201
+ first_run_result = powershell.execute(command)
202
+ expect(first_run_result[:exitcode]).to be(4)
203
+ expect(first_run_result[:stderr].first).to match(/dsc_psrepository: The user name or password is incorrect/)
204
+ expect(first_run_result[:native_stdout]).to match(/'#<Sensitive \[value redacted\]>'/)
205
+ expect(first_run_result[:native_stdout]).not_to match(local_pw)
206
+ end
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: Test against mcollera/AccessControlDsc for CIM instance behavior
4
+ # 1. Make sure valid nested CIM instances can be passed to Invoke-DscResource
5
+ # 2. Make sure nested CIM instances can be read back from Invoke-DscResource
6
+
7
+ require 'spec_helper'
8
+ require 'ruby-pwsh'
9
+
10
+ # Needs to be declared here so it is usable in before and it blocks alike
11
+ test_manifest = File.expand_path('../../fixtures/test.pp', File.dirname(__FILE__))
12
+ fixtures_path = File.expand_path('../../fixtures', File.dirname(__FILE__))
13
+
14
+ def execute_reset_command(reset_command)
15
+ manager = Pwsh::Manager.instance(Pwsh::Manager.powershell_path, Pwsh::Manager.powershell_args)
16
+ result = manager.execute(reset_command)
17
+ raise result[:errormessage] unless result[:errormessage].nil?
18
+ end
19
+
20
+ RSpec.describe 'DSC Acceptance: Complex' do
21
+ let(:powershell) { Pwsh::Manager.instance(Pwsh::Manager.powershell_path, Pwsh::Manager.powershell_args) }
22
+ let(:module_path) { File.expand_path('../../fixtures/modules', File.dirname(__FILE__)) }
23
+ let(:puppet_apply) do
24
+ "bundle exec puppet apply #{test_manifest} --modulepath #{module_path} --detailed-exitcodes --trace"
25
+ end
26
+
27
+ context 'Managing the access control list of a folder' do
28
+ before do
29
+ reset_command = <<~RESET_COMMAND
30
+ $TestFolderPath = Join-Path -Path "#{fixtures_path}" -Childpath access_control
31
+ # Delete the test folder if it exists (to clear access control modifications)
32
+ If (Test-Path -Path $TestFolderPath -PathType Container) {
33
+ Remove-Item $TestFolderPath -Recurse -Force
34
+ }
35
+ # Create the test folder
36
+ New-Item $TestFolderPath -ItemType Directory
37
+ RESET_COMMAND
38
+ execute_reset_command(reset_command)
39
+ end
40
+
41
+ it 'applies idempotently' do
42
+ content = <<~MANIFEST.strip
43
+ $test_folder_path = "#{fixtures_path}/access_control"
44
+ # Configure access to the test folder
45
+ dsc_ntfsaccessentry {'Test':
46
+ dsc_path => $test_folder_path,
47
+ dsc_accesscontrollist => [
48
+ {
49
+ principal => 'Everyone',
50
+ forceprincipal => true,
51
+ accesscontrolentry => [
52
+ {
53
+ accesscontroltype => 'Allow',
54
+ filesystemrights => ['FullControl'],
55
+ inheritance => 'This folder and files',
56
+ ensure => 'Present',
57
+ cim_instance_type => 'NTFSAccessControlEntry',
58
+ }
59
+ ]
60
+ }
61
+ ]
62
+ }
63
+ MANIFEST
64
+ File.write(test_manifest, content)
65
+ # Apply the test manifest
66
+ first_run_result = powershell.execute(puppet_apply)
67
+ expect(first_run_result[:exitcode]).to be(2)
68
+ # Access Control Set
69
+ expect(first_run_result[:native_stdout]).to match(/dsc_accesscontrollist: dsc_accesscontrollist changed/)
70
+ expect(first_run_result[:native_stdout]).to match(%r{dsc_ntfsaccessentry\[{:name=>"Test", :dsc_path=>".+/spec/fixtures/access_control"}\]: Updating: Finished})
71
+ expect(first_run_result[:stderr]).not_to match(/Error/)
72
+ expect(first_run_result[:stderr]).not_to match(/Warning: Provider returned data that does not match the Type Schema/)
73
+ expect(first_run_result[:stderr]).not_to match(/Value type mismatch/)
74
+ # Run finished
75
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
76
+ # Second run is idempotent
77
+ second_run_result = powershell.execute(puppet_apply)
78
+ expect(second_run_result[:exitcode]).to be(0)
79
+ end
80
+ end
81
+ 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 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 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 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
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'ruby-pwsh'
5
+
6
+ # Needs to be declared here so it is usable in before and it blocks alike
7
+ test_manifest = File.expand_path('../../fixtures/test.pp', File.dirname(__FILE__))
8
+ fixtures_path = File.expand_path('../../fixtures', 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: Complex' do
17
+ let(:powershell) { Pwsh::Manager.instance(Pwsh::Manager.powershell_path, Pwsh::Manager.powershell_args) }
18
+ let(:module_path) { File.expand_path('../../fixtures/modules', File.dirname(__FILE__)) }
19
+ let(:puppet_apply) do
20
+ "bundle exec puppet apply #{test_manifest} --modulepath #{module_path} --detailed-exitcodes --trace"
21
+ end
22
+
23
+ context 'Adding a new website' do
24
+ before do
25
+ reset_command = <<~RESET_COMMAND
26
+ # Ensure IIS is not installed
27
+ $Feature = Get-WindowsFeature -Name 'Web-Asp-Net45'
28
+ If ($Feature.Installed) {
29
+ Remove-WindowsFeature -Name $Feature.Name -ErrorAction Stop
30
+ }
31
+ $DefaultSite = Get-Website 'Default Web Site' -ErrorAction Continue
32
+ $ExampleSite = Get-Website 'Puppet DSC Site' -ErrorAction Continue
33
+ If ($DefaultSite.State -eq 'Stopped') {
34
+ Start-Website -Name $DefaultSite.Name
35
+ }
36
+ If ($ExampleSite) {
37
+ Stop-Website -Name $ExampleSite.Name
38
+ Remove-Website -Name $ExampleSite.Name
39
+ Remove-Item -Path '#{fixtures_path}/website' -Recurse -Force -ErrorAction SilentlyContinue
40
+ }
41
+ RESET_COMMAND
42
+ execute_reset_command(reset_command)
43
+ end
44
+
45
+ it 'applies idempotently' do
46
+ content = <<~MANIFEST.strip
47
+ $destination_path = '#{fixtures_path}/website'
48
+ $website_name = 'Puppet DSC Site'
49
+ $site_id = 7
50
+ $index_html = @(INDEXHTML)
51
+ <!doctype html>
52
+ <html lang=en>
53
+
54
+ <head>
55
+ <meta charset=utf-8>
56
+ <title>blah</title>
57
+ </head>
58
+
59
+ <body>
60
+ <p>I'm the content</p>
61
+ </body>
62
+
63
+ </html>
64
+ | INDEXHTML
65
+ # Install the IIS role
66
+ dsc_xwindowsfeature { 'IIS':
67
+ dsc_ensure => 'Present',
68
+ dsc_name => 'Web-Server',
69
+ }
70
+
71
+ # Stop the default website
72
+ dsc_xwebsite { 'DefaultSite':
73
+ dsc_ensure => 'Present',
74
+ dsc_name => 'Default Web Site',
75
+ dsc_state => 'Stopped',
76
+ dsc_serverautostart => false,
77
+ dsc_physicalpath => 'C:\inetpub\wwwroot',
78
+ require => Dsc_xwindowsfeature['IIS'],
79
+ }
80
+
81
+ # Install the ASP .NET 4.5 role
82
+ dsc_xwindowsfeature { 'AspNet45':
83
+ dsc_ensure => 'Present',
84
+ dsc_name => 'Web-Asp-Net45',
85
+ }
86
+
87
+ file { 'WebContentFolder':
88
+ ensure => directory,
89
+ path => $destination_path,
90
+ require => Dsc_xwindowsfeature['AspNet45'],
91
+ }
92
+
93
+ # Copy the website content
94
+ file { 'WebContentIndex':
95
+ path => "${destination_path}/index.html",
96
+ content => $index_html,
97
+ require => File['WebContentFolder'],
98
+ }
99
+
100
+ # Create the new Website
101
+ dsc_xwebsite { 'NewWebsite':
102
+ dsc_ensure => 'Present',
103
+ dsc_name => $website_name,
104
+ dsc_siteid => $site_id,
105
+ dsc_state => 'Started',
106
+ dsc_serverautostart => true,
107
+ dsc_physicalpath => $destination_path,
108
+ require => File['WebContentIndex'],
109
+ }
110
+ MANIFEST
111
+ File.write(test_manifest, content)
112
+ # Puppet apply the test manifest
113
+ first_run_result = powershell.execute(puppet_apply)
114
+ expect(first_run_result[:exitcode]).to be(2)
115
+ # The Default Site is stopped
116
+ expect(first_run_result[:native_stdout]).to match(%r{Dsc_xwebsite\[DefaultSite\]/dsc_state: dsc_state changed 'Started' to 'Stopped'})
117
+ expect(first_run_result[:native_stdout]).to match(/dsc_xwebsite\[{:name=>"DefaultSite", :dsc_name=>"Default Web Site"}\]: Updating: Finished/)
118
+ # AspNet45 is installed
119
+ expect(first_run_result[:native_stdout]).to match(%r{Dsc_xwindowsfeature\[AspNet45\]/dsc_ensure: dsc_ensure changed 'Absent' to 'Present'})
120
+ expect(first_run_result[:native_stdout]).to match(/dsc_xwindowsfeature\[{:name=>"AspNet45", :dsc_name=>"Web-Asp-Net45"}\]: Creating: Finished/)
121
+ # Web content folder created
122
+ expect(first_run_result[:native_stdout]).to match(%r{File\[WebContentFolder\]/ensure: created})
123
+ # Web content index created
124
+ expect(first_run_result[:native_stdout]).to match(%r{File\[WebContentIndex\]/ensure: defined content as '.+'})
125
+ # Web site created
126
+ expect(first_run_result[:native_stdout]).to match(%r{Dsc_xwebsite\[NewWebsite\]/dsc_siteid: dsc_siteid changed to 7})
127
+ expect(first_run_result[:native_stdout]).to match(%r{Dsc_xwebsite\[NewWebsite\]/dsc_ensure: dsc_ensure changed 'Absent' to 'Present'})
128
+ expect(first_run_result[:native_stdout]).to match(%r{Dsc_xwebsite\[NewWebsite\]/dsc_physicalpath: dsc_physicalpath changed to '.+fixtures/website'})
129
+ expect(first_run_result[:native_stdout]).to match(%r{Dsc_xwebsite\[NewWebsite\]/dsc_state: dsc_state changed to 'Started'})
130
+ expect(first_run_result[:native_stdout]).to match(%r{Dsc_xwebsite\[NewWebsite\]/dsc_serverautostart: dsc_serverautostart changed to 'true'})
131
+ expect(first_run_result[:native_stdout]).to match(/dsc_xwebsite\[{:name=>"NewWebsite", :dsc_name=>"Puppet DSC Site"}\]: Creating: Finished/)
132
+ # Run finished
133
+ expect(first_run_result[:native_stdout]).to match(/Applied catalog/)
134
+ # Second run is idempotent
135
+ second_run_result = powershell.execute(puppet_apply)
136
+ expect(second_run_result[:exitcode]).to be(0)
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,6 @@
1
+ Get-ChildItem WSMan:\localhost\Listener\ -OutVariable Listeners | Format-List * -Force
2
+ $HTTPListener = $Listeners | Where-Object -FilterScript { $_.Keys.Contains('Transport=HTTP') }
3
+ If ($HTTPListener.Count -eq 0) {
4
+ winrm create winrm/config/Listener?Address=*+Transport=HTTP
5
+ winrm e winrm/config/listener
6
+ }
data/spec/exit-27.ps1 ADDED
@@ -0,0 +1 @@
1
+ exit 27
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'ruby-pwsh'
5
+
6
+ RSpec.configure do |config|
7
+ # Enable flags like --only-failures and --next-failure
8
+ config.example_status_persistence_file_path = '.rspec_status'
9
+
10
+ # Disable RSpec exposing methods globally on `Module` and `main`
11
+ config.disable_monkey_patching!
12
+
13
+ config.expect_with :rspec do |c|
14
+ c.syntax = :expect
15
+ end
16
+ end