ruby-pwsh 0.10.2 → 0.11.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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