serverspec 0.10.6 → 0.10.7
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/{WindowsSupport.md → WINDOWS_SUPPORT.md} +11 -2
- data/lib/serverspec/backend/cmd.rb +3 -4
- data/lib/serverspec/backend/powershell/command.rb +4 -0
- data/lib/serverspec/backend/powershell/script_helper.rb +20 -4
- data/lib/serverspec/backend/powershell/support/check_file_access_rules.ps1 +3 -7
- data/lib/serverspec/backend/powershell/support/is_port_listening.ps1 +1 -1
- data/lib/serverspec/commands/windows.rb +3 -1
- data/lib/serverspec/version.rb +1 -1
- data/spec/backend/powershell/script_helper_spec.rb +27 -0
- data/spec/spec_helper.rb +1 -4
- data/spec/windows/command_spec.rb +71 -0
- data/spec/windows/service_spec.rb +9 -0
- data/spec/windows/windows_registry_key_spec.rb +68 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05c1dc06b5b4833b7e537d596b488b3bb07aba0e
|
4
|
+
data.tar.gz: c8fa93b1eab1507daa911da2a1e1b55c20dcac9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eeab306443ccc7261c6dacf25553d98481fed15453e650c55f79c574223485a02dab66ac73751b8ca7468275defb4fbf5de8d66dbc763b941023c26f4a00c5e4
|
7
|
+
data.tar.gz: 7c53f323cfcee38681c359ce7bdbef51b0e85089cec4dda10537a11aebf1af200ec93f1ca8a88a4d26e7a1084f5533b8483f57d44eba993737ccadf66ee2ba60
|
@@ -33,7 +33,7 @@ RSpec.configure do |c|
|
|
33
33
|
end
|
34
34
|
```
|
35
35
|
|
36
|
-
For different authentication mechanisms check the Microsoft WinRM documentation and verify the ones that are supported by [WinRb/WinRM](https://github.com/WinRb/WinRM)
|
36
|
+
For how to configure the guest to accept WinRM connections and the different authentication mechanisms check the Microsoft WinRM documentation and verify the ones that are supported by [WinRb/WinRM](https://github.com/WinRb/WinRM).
|
37
37
|
|
38
38
|
|
39
39
|
###RSpec Examples for windows target hosts
|
@@ -75,6 +75,10 @@ describe group('MYDOMAIN\Domain Users') do
|
|
75
75
|
it { should exist }
|
76
76
|
end
|
77
77
|
|
78
|
+
describe command('& "ipconfig"') do
|
79
|
+
it { should return_stdout(/IPv4 Address(\.| )*: 192\.168\.1\.100/) }
|
80
|
+
end
|
81
|
+
|
78
82
|
describe windows_registry_key('HKEY_USERS\S-1-5-21-1319311448-2088773778-316617838-32407\Test MyKey') do
|
79
83
|
it { should exist }
|
80
84
|
it { should have_property('string value') }
|
@@ -85,4 +89,9 @@ describe windows_registry_key('HKEY_USERS\S-1-5-21-1319311448-2088773778-3166178
|
|
85
89
|
it { should have_property_value('qword value', :type_qword, 'adff32') }
|
86
90
|
it { should have_property_value('binary value', :type_binary, 'dfa0f066') }
|
87
91
|
end
|
88
|
-
```
|
92
|
+
```
|
93
|
+
|
94
|
+
###Notes:
|
95
|
+
* Not all the matchers you are used to in Linux-like OS are supported in Windows, some because of differences between the operating systems (e.g. users and permissions model), some because they haven't been yet implemented.
|
96
|
+
* All commands in the windows backend are run via powershell, so the output in case of stderr is a pretty ugly xml-like thing. Still it should contain some information to help troubleshooting.
|
97
|
+
* The *command* type is executed again through powershell, so bear that in mind if you mean to run old CMD windows batch or programs. (i.e run the command using the **Invoke-Expression** Cmdlet, or the **&** Call Operator)
|
@@ -7,7 +7,7 @@ module Serverspec
|
|
7
7
|
|
8
8
|
def run_command(cmd, opts={})
|
9
9
|
script = create_script(cmd)
|
10
|
-
result = execute_script script
|
10
|
+
result = execute_script %Q{powershell -encodedCommand #{encode_script(script)}}
|
11
11
|
|
12
12
|
if @example
|
13
13
|
@example.metadata[:command] = script
|
@@ -18,15 +18,14 @@ module Serverspec
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def execute_script script
|
21
|
-
ps_script = %Q{powershell -encodedCommand #{encode_script(script)}}
|
22
21
|
if Open3.respond_to? :capture3
|
23
|
-
stdout, stderr, status = Open3.capture3(
|
22
|
+
stdout, stderr, status = Open3.capture3(script)
|
24
23
|
# powershell still exits with 0 even if there are syntax errors, although it spits the error out into stderr
|
25
24
|
# so we have to resort to return an error exit code if there is anything in the standard error
|
26
25
|
status = 1 if status == 0 and !stderr.empty?
|
27
26
|
{ :stdout => stdout, :stderr => stderr, :status => status }
|
28
27
|
else
|
29
|
-
stdout = `#{
|
28
|
+
stdout = `#{script} 2>&1`
|
30
29
|
{ :stdout => stdout, :stderr => nil, :status => $? }
|
31
30
|
end
|
32
31
|
end
|
@@ -47,10 +47,11 @@ EOF
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def create_script command
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
if command.is_a? Command
|
51
|
+
ps_functions = command.import_functions.map { |f| File.read(File.join(File.dirname(__FILE__), 'support', f)) }
|
52
|
+
script = build_command(command.script)
|
53
|
+
script = add_pre_command(script)
|
54
|
+
<<-EOF
|
54
55
|
$exitCode = 1
|
55
56
|
try {
|
56
57
|
#{ps_functions.join("\n")}
|
@@ -62,6 +63,21 @@ try {
|
|
62
63
|
Write-Output "Exiting with code: $exitCode"
|
63
64
|
exit $exitCode
|
64
65
|
EOF
|
66
|
+
else
|
67
|
+
script = build_command(command.to_s)
|
68
|
+
add_pre_command(script)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def check_running(process)
|
73
|
+
ret = run_command(commands.check_running(process))
|
74
|
+
|
75
|
+
# If the service is not registered, check the process
|
76
|
+
if ret[:exit_status] == 1
|
77
|
+
ret = run_command(commands.check_process(process))
|
78
|
+
end
|
79
|
+
|
80
|
+
ret[:exit_status] == 0
|
65
81
|
end
|
66
82
|
end
|
67
83
|
end
|
@@ -2,11 +2,7 @@ function CheckFileAccessRules
|
|
2
2
|
{
|
3
3
|
param($path, $identity, $rules)
|
4
4
|
|
5
|
-
$
|
6
|
-
$
|
7
|
-
|
8
|
-
$match = $accessRules.FileSystemRights.ToString() -Split (', ') | ?{$rules -contains $_}
|
9
|
-
$result = $match -ne $null -or $match.length -gt 0
|
10
|
-
}
|
11
|
-
$result
|
5
|
+
$accessRules = @((Get-Acl $path).access | Where-Object {$_.AccessControlType -eq 'Allow' -and $_.IdentityReference -eq $identity })
|
6
|
+
$match = @($accessRules | Where-Object {($_.FileSystemRights.ToString().Split(',') | % {$_.trim()} | ? {$rules -contains $_}) -ne $null})
|
7
|
+
$match.count -gt 0
|
12
8
|
}
|
@@ -6,7 +6,7 @@ function IsPortListening
|
|
6
6
|
foreach ($ipaddress in $networkIPs)
|
7
7
|
{
|
8
8
|
$matchExpression = ("$ipaddress" + ":" + $portNumber)
|
9
|
-
if ($protocol) { $matchExpression = ($protocol.toUpper() + "\s+$matchExpression") }
|
9
|
+
if ($protocol) { $matchExpression = ($protocol.toUpper() + "\s+$matchExpression") }
|
10
10
|
if ($netstatOutput -match $matchExpression) { return $true }
|
11
11
|
}
|
12
12
|
$false
|
@@ -192,7 +192,9 @@ module Serverspec
|
|
192
192
|
when :type_binary
|
193
193
|
byte_array = [property[:value]].pack('H*').bytes.to_a
|
194
194
|
"([byte[]] #{byte_array.join(',')})"
|
195
|
-
when:type_dword
|
195
|
+
when :type_dword
|
196
|
+
[property[:value].scan(/[0-9a-f]{2}/i).reverse.join].pack("H*").unpack("l").first
|
197
|
+
when :type_qword
|
196
198
|
property[:value].hex
|
197
199
|
else
|
198
200
|
string_array = property[:value].split("\n").map {|s| "'#{s}'"}.reduce {|acc, s| "#{acc},#{s}"}
|
data/lib/serverspec/version.rb
CHANGED
@@ -75,3 +75,30 @@ describe "script encoding" do
|
|
75
75
|
script.should == "dABlAHMAdABfAHAAbwB3AGUAcgBzAGgAZQBsAGwAXwBzAGMAcgBpAHAAdAA="
|
76
76
|
end
|
77
77
|
end
|
78
|
+
|
79
|
+
describe 'script creation' do
|
80
|
+
context "powershell command" do
|
81
|
+
File.should_receive(:read).with(/test_function1.ps1/).and_return 'function test1'
|
82
|
+
command = Backend::PowerShell::Command.new do
|
83
|
+
using 'test_function1.ps1'
|
84
|
+
exec 'test command'
|
85
|
+
end
|
86
|
+
script = create_script command
|
87
|
+
script.should == <<-eof
|
88
|
+
$exitCode = 1
|
89
|
+
try {
|
90
|
+
function test1
|
91
|
+
$success = (test command)
|
92
|
+
if ($success -is [Boolean] -and $success) { $exitCode = 0 }
|
93
|
+
} catch {
|
94
|
+
Write-Output $_.Exception.Message
|
95
|
+
}
|
96
|
+
Write-Output "Exiting with code: $exitCode"
|
97
|
+
exit $exitCode
|
98
|
+
eof
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'simple command' do
|
102
|
+
create_script('test command').should == 'test command'
|
103
|
+
end
|
104
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -39,10 +39,7 @@ module Serverspec
|
|
39
39
|
clz.class_eval do
|
40
40
|
include TestCommandRunner
|
41
41
|
def run_command(cmd)
|
42
|
-
|
43
|
-
cmd = cmd.script
|
44
|
-
end
|
45
|
-
cmd = build_command(cmd)
|
42
|
+
cmd = build_command(cmd.to_s)
|
46
43
|
cmd = add_pre_command(cmd)
|
47
44
|
do_run cmd
|
48
45
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Serverspec::Helper::Cmd
|
4
|
+
RSpec.configure do |c|
|
5
|
+
c.os = 'Windows'
|
6
|
+
end
|
7
|
+
|
8
|
+
describe command('test_cmd /test/path/file') do
|
9
|
+
let(:stdout) { "test output 1.2.3\r\n" }
|
10
|
+
it { should return_stdout("test output 1.2.3") }
|
11
|
+
its(:command) { should eq 'test_cmd /test/path/file' }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'complete matching of stdout' do
|
15
|
+
context command('test_cmd /test/path/file') do
|
16
|
+
let(:stdout) { "foocontent-should-be-includedbar\r\n" }
|
17
|
+
it { should_not return_stdout('content-should-be-included') }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'regexp matching of stdout' do
|
22
|
+
context command('test_cmd /test/path/file') do
|
23
|
+
let(:stdout) { "test output 1.2.3\r\n" }
|
24
|
+
it { should return_stdout(/1\.2\.3/) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe command('test_cmd /test/path/file') do
|
29
|
+
let(:stdout) { "No such file or directory\r\n" }
|
30
|
+
it { should return_stderr("No such file or directory") }
|
31
|
+
its(:command) { should eq 'test_cmd /test/path/file' }
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'complete matching of stderr' do
|
35
|
+
context command('test_cmd /test/path/file') do
|
36
|
+
let(:stdout) { "No such file or directory\r\n" }
|
37
|
+
it { should_not return_stdout('file') }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'regexp matching of stderr' do
|
42
|
+
context command('test_cmd /test/path/file') do
|
43
|
+
let(:stdout) { "No such file or directory\r\n" }
|
44
|
+
it { should return_stderr(/file/) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe command('test_cmd /test/path/file') do
|
49
|
+
it { should return_exit_status 0 }
|
50
|
+
its(:command) { should eq 'test_cmd /test/path/file' }
|
51
|
+
end
|
52
|
+
|
53
|
+
describe command('dir "c:\"') do
|
54
|
+
let(:stdout) { <<EOF
|
55
|
+
Directory: C:\
|
56
|
+
|
57
|
+
Mode LastWriteTime Length Name
|
58
|
+
---- ------------- ------ ----
|
59
|
+
d-r-- 23/09/2013 10:46 AM Program Files
|
60
|
+
d-r-- 23/09/2013 1:21 PM Program Files (x86)
|
61
|
+
d---- 17/10/2013 8:46 PM temp
|
62
|
+
d-r-- 23/09/2013 11:52 AM Users
|
63
|
+
d---- 23/09/2013 1:21 PM Windows
|
64
|
+
EOF
|
65
|
+
}
|
66
|
+
|
67
|
+
its(:stdout) { should match /Program Files/ }
|
68
|
+
its(:stderr) { should match /Program Files/ }
|
69
|
+
|
70
|
+
its(:stdout) { should eq stdout }
|
71
|
+
end
|
@@ -22,3 +22,12 @@ end
|
|
22
22
|
describe service('invalid-daemon') do
|
23
23
|
it { should_not be_running }
|
24
24
|
end
|
25
|
+
|
26
|
+
describe service('Test service') do
|
27
|
+
it "should raise error if trying to check service process controller" do
|
28
|
+
expect { should be_running.under('supervisor') }.to raise_error
|
29
|
+
end
|
30
|
+
it "should raise error if trying to check service monitoring" do
|
31
|
+
expect { should_not be_monitored_by('monit') }.to raise_error
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Serverspec::Helper::Cmd
|
4
|
+
RSpec.configure do |c|
|
5
|
+
c.os = 'Windows'
|
6
|
+
end
|
7
|
+
|
8
|
+
describe windows_registry_key('PATH/TO/THE_KEY') do
|
9
|
+
it { should exist }
|
10
|
+
its(:command) { should == "(Get-Item 'Registry::PATH/TO/THE_KEY') -ne $null" }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe windows_registry_key('PATH/TO/THE_KEY') do
|
14
|
+
it { should have_value('Test Value') }
|
15
|
+
its(:command) { should == "(Compare-Object (Get-Item 'Registry::PATH/TO/THE_KEY').GetValue('') @('Test Value')) -eq $null" }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'Key value types' do
|
19
|
+
context 'default type' do
|
20
|
+
describe windows_registry_key('PATH/TO/THE_KEY') do
|
21
|
+
it { should have_property('TestProperty') }
|
22
|
+
its(:command) { should == "(Get-Item 'Registry::PATH/TO/THE_KEY').GetValueKind('TestProperty') -eq 'String'" }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
{
|
27
|
+
:type_string => 'String',
|
28
|
+
:type_binary => 'Binary',
|
29
|
+
:type_dword => 'DWord',
|
30
|
+
:type_qword => 'QWord',
|
31
|
+
:type_multistring => 'MultiString',
|
32
|
+
:type_expandstring => 'ExpandString'
|
33
|
+
}.each do |sym, type|
|
34
|
+
context "type #{type}" do
|
35
|
+
describe windows_registry_key('PATH/TO/THE_KEY') do
|
36
|
+
it { should have_property('TestProperty', sym) }
|
37
|
+
its(:command) { should == "(Get-Item 'Registry::PATH/TO/THE_KEY').GetValueKind('TestProperty') -eq '#{type}'" }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe windows_registry_key('PATH/TO/THE_KEY') do
|
44
|
+
it { should have_property_value('TestProperty', :type_binary, '12a07b') }
|
45
|
+
its(:command) { should == "(Compare-Object (Get-Item 'Registry::PATH/TO/THE_KEY').GetValue('TestProperty') ([byte[]] 18,160,123)) -eq $null" }
|
46
|
+
end
|
47
|
+
|
48
|
+
describe windows_registry_key('PATH/TO/THE_KEY') do
|
49
|
+
it { should have_property_value('TestProperty', :type_dword, 'fffffd6c') }
|
50
|
+
its(:command) { should == "(Compare-Object (Get-Item 'Registry::PATH/TO/THE_KEY').GetValue('TestProperty') -660) -eq $null" }
|
51
|
+
end
|
52
|
+
|
53
|
+
describe windows_registry_key('PATH/TO/THE_KEY') do
|
54
|
+
it { should have_property_value('TestProperty', :type_qword, '1e240') }
|
55
|
+
its(:command) { should == "(Compare-Object (Get-Item 'Registry::PATH/TO/THE_KEY').GetValue('TestProperty') 123456) -eq $null" }
|
56
|
+
end
|
57
|
+
|
58
|
+
describe windows_registry_key('PATH/TO/THE_KEY') do
|
59
|
+
it {
|
60
|
+
value = <<-EOF
|
61
|
+
test line1
|
62
|
+
test line2
|
63
|
+
test line3
|
64
|
+
EOF
|
65
|
+
should have_property_value('TestProperty', :type_multistring, value)
|
66
|
+
}
|
67
|
+
its(:command) { should == "(Compare-Object (Get-Item 'Registry::PATH/TO/THE_KEY').GetValue('TestProperty') @('test line1','test line2','test line3')) -eq $null" }
|
68
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: serverspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gosuke Miyashita
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-ssh
|
@@ -95,7 +95,7 @@ files:
|
|
95
95
|
- LICENSE.txt
|
96
96
|
- README.md
|
97
97
|
- Rakefile
|
98
|
-
-
|
98
|
+
- WINDOWS_SUPPORT.md
|
99
99
|
- bin/serverspec-init
|
100
100
|
- lib/serverspec.rb
|
101
101
|
- lib/serverspec/attributes.rb
|
@@ -368,11 +368,13 @@ files:
|
|
368
368
|
- spec/solaris11/zfs_spec.rb
|
369
369
|
- spec/spec_helper.rb
|
370
370
|
- spec/support/powershell_command_runner.rb
|
371
|
+
- spec/windows/command_spec.rb
|
371
372
|
- spec/windows/file_spec.rb
|
372
373
|
- spec/windows/group_spec.rb
|
373
374
|
- spec/windows/port_spec.rb
|
374
375
|
- spec/windows/service_spec.rb
|
375
376
|
- spec/windows/user_spec.rb
|
377
|
+
- spec/windows/windows_registry_key_spec.rb
|
376
378
|
homepage: http://serverspec.org/
|
377
379
|
licenses:
|
378
380
|
- MIT
|
@@ -564,8 +566,10 @@ test_files:
|
|
564
566
|
- spec/solaris11/zfs_spec.rb
|
565
567
|
- spec/spec_helper.rb
|
566
568
|
- spec/support/powershell_command_runner.rb
|
569
|
+
- spec/windows/command_spec.rb
|
567
570
|
- spec/windows/file_spec.rb
|
568
571
|
- spec/windows/group_spec.rb
|
569
572
|
- spec/windows/port_spec.rb
|
570
573
|
- spec/windows/service_spec.rb
|
571
574
|
- spec/windows/user_spec.rb
|
575
|
+
- spec/windows/windows_registry_key_spec.rb
|