serverspec 0.8.1 → 0.9.0
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/.gitignore +2 -0
- data/Rakefile +6 -8
- data/WindowsSupport.md +88 -0
- data/bin/serverspec-init +75 -0
- data/lib/serverspec/backend/base.rb +31 -0
- data/lib/serverspec/backend/cmd.rb +35 -0
- data/lib/serverspec/backend/exec.rb +1 -24
- data/lib/serverspec/backend/powershell/command.rb +36 -0
- data/lib/serverspec/backend/powershell/script_helper.rb +69 -0
- data/lib/serverspec/backend/powershell/support/check_file_access_rules.ps1 +12 -0
- data/lib/serverspec/backend/powershell/support/crop_text.ps1 +11 -0
- data/lib/serverspec/backend/powershell/support/find_group.ps1 +8 -0
- data/lib/serverspec/backend/powershell/support/find_installed_application.ps1 +7 -0
- data/lib/serverspec/backend/powershell/support/find_service.ps1 +5 -0
- data/lib/serverspec/backend/powershell/support/find_user.ps1 +8 -0
- data/lib/serverspec/backend/powershell/support/find_usergroup.ps1 +9 -0
- data/lib/serverspec/backend/powershell/support/is_port_listening.ps1 +13 -0
- data/lib/serverspec/backend/winrm.rb +26 -0
- data/lib/serverspec/backend.rb +5 -0
- data/lib/serverspec/commands/windows.rb +211 -0
- data/lib/serverspec/helper/cmd.rb +15 -0
- data/lib/serverspec/helper/type.rb +1 -1
- data/lib/serverspec/helper/windows.rb +9 -0
- data/lib/serverspec/helper/winrm.rb +15 -0
- data/lib/serverspec/helper.rb +3 -0
- data/lib/serverspec/setup.rb +59 -83
- data/lib/serverspec/type/windows_registry_key.rb +21 -0
- data/lib/serverspec/version.rb +1 -1
- data/lib/serverspec.rb +3 -0
- data/spec/backend/cmd/configuration_spec.rb +9 -0
- data/spec/backend/powershell/script_helper_spec.rb +77 -0
- data/spec/backend/winrm/configuration_spec.rb +9 -0
- data/spec/spec_helper.rb +18 -26
- data/spec/support/powershell_command_runner.rb +52 -0
- data/spec/windows/file_spec.rb +161 -0
- data/spec/windows/group_spec.rb +29 -0
- data/spec/windows/port_spec.rb +31 -0
- data/spec/windows/user_spec.rb +44 -0
- metadata +37 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af5097bb467c14c4f8d0f22747b6775ecf5d598a
|
4
|
+
data.tar.gz: fee035ec0e675c79cf74ef7367da9d2e028a7dbb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba213503e568d2c6bcb5a6f814f436508880546bf90bd43c39e5a944b7d6ada8ce9adbb36889e3024f3dafacb43106a382d7d89cb97eba9217b67694578c8295
|
7
|
+
data.tar.gz: c68841e54c3aa39773d997e330e612ddd74b619a9a93328461a362c326b26e1efea60e3f6d2582c52ab84f8a4ad97931941355c412a3a2baa82b5f51403025d4
|
data/.gitignore
CHANGED
data/Rakefile
CHANGED
@@ -4,9 +4,9 @@ require 'rspec/core/rake_task'
|
|
4
4
|
task :spec => 'spec:all'
|
5
5
|
|
6
6
|
namespace :spec do
|
7
|
-
oses = %w( darwin debian gentoo redhat solaris solaris10 solaris11 smartos )
|
7
|
+
oses = %w( darwin debian gentoo redhat solaris solaris10 solaris11 smartos windows)
|
8
8
|
|
9
|
-
task :all => [ oses.map {|os| "spec:#{os}" }, :helpers, :exec, :ssh ].flatten
|
9
|
+
task :all => [ oses.map {|os| "spec:#{os}" }, :helpers, :exec, :ssh, :cmd, :winrm, :powershell ].flatten
|
10
10
|
|
11
11
|
oses.each do |os|
|
12
12
|
RSpec::Core::RakeTask.new(os.to_sym) do |t|
|
@@ -18,11 +18,9 @@ namespace :spec do
|
|
18
18
|
t.pattern = "spec/helpers/*_spec.rb"
|
19
19
|
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
RSpec::Core::RakeTask.new(:ssh) do |t|
|
26
|
-
t.pattern = "spec/backend/ssh/*_spec.rb"
|
21
|
+
[:exec, :ssh, :cmd, :winrm, :powershell].each do |backend|
|
22
|
+
RSpec::Core::RakeTask.new(backend) do |t|
|
23
|
+
t.pattern = "spec/backend/#{backend.to_s}/*_spec.rb"
|
24
|
+
end
|
27
25
|
end
|
28
26
|
end
|
data/WindowsSupport.md
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
## Windows support
|
2
|
+
|
3
|
+
Serverspec is now providing a limited support for Microsoft Windows.
|
4
|
+
|
5
|
+
If you want to test Windows based machines you need to set the target host's OS explicitly in your `spec/spec_helper.rb`
|
6
|
+
|
7
|
+
For local testing (equivalent to the Exec option in Linux/Unix systems) simply do:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
require 'serverspec'
|
11
|
+
|
12
|
+
include Serverspec::Helper::Cmd
|
13
|
+
include Serverspec::Helper::Windows
|
14
|
+
|
15
|
+
```
|
16
|
+
|
17
|
+
For remote testing you have to configure Windows Remote Management in order to communicate to the target host:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'serverspec'
|
21
|
+
require 'winrm'
|
22
|
+
|
23
|
+
include Serverspec::Helper::WinRM
|
24
|
+
include Serverspec::Helper::Windows
|
25
|
+
|
26
|
+
RSpec.configure do |c|
|
27
|
+
user = <username>
|
28
|
+
pass = <password>
|
29
|
+
endpoint = "http://<hostname>:5985/wsman"
|
30
|
+
|
31
|
+
c.winrm = ::WinRM::WinRMWebService.new(endpoint, :ssl, :user => user, :pass => pass, :basic_auth_only => true)
|
32
|
+
c.winrm.set_timeout 300 # 5 minutes max timeout for any operation
|
33
|
+
end
|
34
|
+
```
|
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)
|
37
|
+
|
38
|
+
|
39
|
+
###RSpec Examples for windows target hosts
|
40
|
+
```ruby
|
41
|
+
describe file('c:/windows') do
|
42
|
+
it { should be_directory }
|
43
|
+
it { should be_readable }
|
44
|
+
it { should_not be_writable.by('Everyone') }
|
45
|
+
end
|
46
|
+
|
47
|
+
describe file('c:/temp/test.txt') do
|
48
|
+
it { should be_file }
|
49
|
+
it { should contain "some text" }
|
50
|
+
end
|
51
|
+
|
52
|
+
describe package('Adobe AIR') do
|
53
|
+
it { should be_installed}
|
54
|
+
end
|
55
|
+
|
56
|
+
describe service('DNS Client') do
|
57
|
+
it { should be_enabled }
|
58
|
+
it { should be_running }
|
59
|
+
end
|
60
|
+
|
61
|
+
describe port(139) do
|
62
|
+
it { should be_listening }
|
63
|
+
end
|
64
|
+
|
65
|
+
describe user('some.admin') do
|
66
|
+
it { should exist }
|
67
|
+
it { should belong_to_group('Administrators')}
|
68
|
+
end
|
69
|
+
|
70
|
+
describe group('Guests') do
|
71
|
+
it { should exist }
|
72
|
+
end
|
73
|
+
|
74
|
+
describe group('MYDOMAIN\Domain Users') do
|
75
|
+
it { should exist }
|
76
|
+
end
|
77
|
+
|
78
|
+
describe windows_registry_key('HKEY_USERS\S-1-5-21-1319311448-2088773778-316617838-32407\Test MyKey') do
|
79
|
+
it { should exist }
|
80
|
+
it { should have_property('string value') }
|
81
|
+
it { should have_property('binary value', :type_binary) }
|
82
|
+
it { should have_property('dword value', :type_dword) }
|
83
|
+
it { should have_value('test default data') }
|
84
|
+
it { should have_property_value('multistring value', :type_multistring, "test\nmulti\nstring\ndata") }
|
85
|
+
it { should have_property_value('qword value', :type_qword, 'adff32') }
|
86
|
+
it { should have_property_value('binary value', :type_binary, 'dfa0f066') }
|
87
|
+
end
|
88
|
+
```
|
data/bin/serverspec-init
CHANGED
@@ -5,3 +5,78 @@ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
|
5
5
|
require 'serverspec'
|
6
6
|
|
7
7
|
Serverspec::Setup.run
|
8
|
+
|
9
|
+
__END__
|
10
|
+
require 'serverspec'
|
11
|
+
<% if @os_type == 'UN*X' -%>
|
12
|
+
require 'pathname'
|
13
|
+
<% end -%>
|
14
|
+
<% if @backend_type == 'Ssh' -%>
|
15
|
+
require 'net/ssh'
|
16
|
+
<% end -%>
|
17
|
+
<% if @backend_type == 'WinRM' -%>
|
18
|
+
require 'winrm'
|
19
|
+
<% end -%>
|
20
|
+
|
21
|
+
include Serverspec::Helper::<%= @backend_type %>
|
22
|
+
<% if @os_type == 'UN*X' -%>
|
23
|
+
include Serverspec::Helper::DetectOS
|
24
|
+
<% else -%>
|
25
|
+
include Serverspec::Helper::Windows
|
26
|
+
<% end -%>
|
27
|
+
|
28
|
+
<% if @os_type == 'UN*X' -%>
|
29
|
+
RSpec.configure do |c|
|
30
|
+
if ENV['ASK_SUDO_PASSWORD']
|
31
|
+
require 'highline/import'
|
32
|
+
c.sudo_password = ask("Enter sudo password: ") { |q| q.echo = false }
|
33
|
+
else
|
34
|
+
c.sudo_password = ENV['SUDO_PASSWORD']
|
35
|
+
end
|
36
|
+
<%- if @backend_type == 'Ssh' -%>
|
37
|
+
c.before :all do
|
38
|
+
block = self.class.metadata[:example_group_block]
|
39
|
+
if RUBY_VERSION.start_with?('1.8')
|
40
|
+
file = block.to_s.match(/.*@(.*):[0-9]+>/)[1]
|
41
|
+
else
|
42
|
+
file = block.source_location.first
|
43
|
+
end
|
44
|
+
host = File.basename(Pathname.new(file).dirname)
|
45
|
+
if c.host != host
|
46
|
+
c.ssh.close if c.ssh
|
47
|
+
c.host = host
|
48
|
+
options = Net::SSH::Config.for(c.host)
|
49
|
+
user = options[:user] || Etc.getlogin
|
50
|
+
<%- if @vagrant -%>
|
51
|
+
vagrant_up = `vagrant up #{@hostname}`
|
52
|
+
config = `vagrant ssh-config #{@hostname}`
|
53
|
+
if config != ''
|
54
|
+
config.each_line do |line|
|
55
|
+
if match = /HostName (.*)/.match(line)
|
56
|
+
c.host = match[1]
|
57
|
+
elsif match = /User (.*)/.match(line)
|
58
|
+
user = match[1]
|
59
|
+
elsif match = /IdentityFile (.*)/.match(line)
|
60
|
+
options[:keys] = [match[1].gsub(/\"/,'')]
|
61
|
+
elsif match = /Port (.*)/.match(line)
|
62
|
+
options[:port] = match[1]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
<%- end -%>
|
67
|
+
c.ssh = Net::SSH.start(c.host, user, options)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
<%- end -%>
|
71
|
+
end
|
72
|
+
<% end -%>
|
73
|
+
<% if @backend_type == 'WinRM'-%>
|
74
|
+
RSpec.configure do |c|
|
75
|
+
user = <username>
|
76
|
+
pass = <password>
|
77
|
+
endpoint = "http://<hostname>:5985/wsman"
|
78
|
+
|
79
|
+
c.winrm = ::WinRM::WinRMWebService.new(endpoint, :ssl, :user => user, :pass => pass, :basic_auth_only => true)
|
80
|
+
c.winrm.set_timeout 300 # 5 minutes max timeout for any operation
|
81
|
+
end
|
82
|
+
<% end -%>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module Serverspec
|
4
|
+
module Backend
|
5
|
+
class Base
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
def set_commands(c)
|
9
|
+
@commands = c
|
10
|
+
end
|
11
|
+
|
12
|
+
def set_example(e)
|
13
|
+
@example = e
|
14
|
+
end
|
15
|
+
|
16
|
+
def commands
|
17
|
+
@commands
|
18
|
+
end
|
19
|
+
|
20
|
+
def check_zero(cmd, *args)
|
21
|
+
ret = run_command(commands.send(cmd, *args))
|
22
|
+
ret[:exit_status] == 0
|
23
|
+
end
|
24
|
+
|
25
|
+
# Default action is to call check_zero with args
|
26
|
+
def method_missing(meth, *args, &block)
|
27
|
+
check_zero(meth, *args)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Serverspec
|
4
|
+
module Backend
|
5
|
+
class Cmd < Base
|
6
|
+
include PowerShell::ScriptHelper
|
7
|
+
|
8
|
+
def run_command(cmd, opts={})
|
9
|
+
script = create_script(cmd)
|
10
|
+
result = execute_script script
|
11
|
+
|
12
|
+
if @example
|
13
|
+
@example.metadata[:command] = script
|
14
|
+
@example.metadata[:stdout] = result[:stdout] + result[:stderr]
|
15
|
+
end
|
16
|
+
{ :stdout => result[:stdout], :stderr => result[:stderr],
|
17
|
+
:exit_status => result[:status], :exit_signal => nil }
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute_script script
|
21
|
+
ps_script = %Q{powershell -encodedCommand #{encode_script(script)}}
|
22
|
+
if Open3.respond_to? :capture3
|
23
|
+
stdout, stderr, status = Open3.capture3(ps_script)
|
24
|
+
# powershell still exits with 0 even if there are syntax errors, although it spits the error out into stderr
|
25
|
+
# so we have to resort to return an error exit code if there is anything in the standard error
|
26
|
+
status = 1 if status == 0 and !stderr.empty?
|
27
|
+
{ :stdout => stdout, :stderr => stderr, :status => status }
|
28
|
+
else
|
29
|
+
stdout = `#{ps_script} 2>&1`
|
30
|
+
{ :stdout => stdout, :stderr => nil, :status => $? }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -2,20 +2,7 @@ require 'singleton'
|
|
2
2
|
|
3
3
|
module Serverspec
|
4
4
|
module Backend
|
5
|
-
class Exec
|
6
|
-
include Singleton
|
7
|
-
|
8
|
-
def set_commands(c)
|
9
|
-
@commands = c
|
10
|
-
end
|
11
|
-
|
12
|
-
def set_example(e)
|
13
|
-
@example = e
|
14
|
-
end
|
15
|
-
|
16
|
-
def commands
|
17
|
-
@commands
|
18
|
-
end
|
5
|
+
class Exec < Base
|
19
6
|
|
20
7
|
def run_command(cmd, opts={})
|
21
8
|
cmd = build_command(cmd)
|
@@ -52,16 +39,6 @@ module Serverspec
|
|
52
39
|
cmd
|
53
40
|
end
|
54
41
|
|
55
|
-
def check_zero(cmd, *args)
|
56
|
-
ret = run_command(commands.send(cmd, *args))
|
57
|
-
ret[:exit_status] == 0
|
58
|
-
end
|
59
|
-
|
60
|
-
# Default action is to call check_zero with args
|
61
|
-
def method_missing(meth, *args, &block)
|
62
|
-
check_zero(meth, *args)
|
63
|
-
end
|
64
|
-
|
65
42
|
def check_running(process)
|
66
43
|
ret = run_command(commands.check_running(process))
|
67
44
|
if ret[:exit_status] == 1 || ret[:stdout] =~ /stopped/
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Serverspec
|
2
|
+
module Backend
|
3
|
+
module PowerShell
|
4
|
+
class Command
|
5
|
+
attr_reader :import_functions, :script
|
6
|
+
def initialize &block
|
7
|
+
@import_functions = []
|
8
|
+
@script = ""
|
9
|
+
instance_eval &block if block_given?
|
10
|
+
end
|
11
|
+
|
12
|
+
def using *functions
|
13
|
+
functions.each { |f| import_functions << f }
|
14
|
+
end
|
15
|
+
|
16
|
+
def exec code
|
17
|
+
@script = code
|
18
|
+
end
|
19
|
+
|
20
|
+
def convert_regexp(target)
|
21
|
+
case target
|
22
|
+
when Regexp
|
23
|
+
target.source
|
24
|
+
else
|
25
|
+
target.to_s.gsub '/', ''
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_identity id
|
30
|
+
raise "You must provide a specific Windows user/group" if id =~ /(owner|group|others)/
|
31
|
+
identity = id || 'Everyone'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module Serverspec
|
4
|
+
module Backend
|
5
|
+
module PowerShell
|
6
|
+
module ScriptHelper
|
7
|
+
def build_command(cmd)
|
8
|
+
path = Serverspec.configuration.path || RSpec.configuration.path
|
9
|
+
if path
|
10
|
+
cmd.strip!
|
11
|
+
cmd =
|
12
|
+
<<-EOF
|
13
|
+
$env:path = "#{path};$env:path"
|
14
|
+
#{cmd}
|
15
|
+
EOF
|
16
|
+
end
|
17
|
+
cmd
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_pre_command(cmd)
|
21
|
+
path = Serverspec.configuration.path || RSpec.configuration.path
|
22
|
+
if Serverspec.configuration.pre_command
|
23
|
+
cmd.strip!
|
24
|
+
cmd =
|
25
|
+
<<-EOF
|
26
|
+
if (#{Serverspec.configuration.pre_command})
|
27
|
+
{
|
28
|
+
#{cmd}
|
29
|
+
}
|
30
|
+
EOF
|
31
|
+
cmd = "$env:path = \"#{path};$env:path\"\n#{cmd}" if path
|
32
|
+
end
|
33
|
+
cmd
|
34
|
+
end
|
35
|
+
|
36
|
+
def encode_script script
|
37
|
+
script_text = script.chars.to_a.join("\x00").chomp
|
38
|
+
script_text << "\x00" unless script_text[-1].eql? "\x00"
|
39
|
+
if script_text.respond_to?(:encode)
|
40
|
+
script_text = script_text.encode('ASCII-8BIT')
|
41
|
+
end
|
42
|
+
if Base64.respond_to?(:strict_encode64)
|
43
|
+
Base64.strict_encode64(script_text)
|
44
|
+
else
|
45
|
+
[ script_text ].pack("m").strip
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_script command
|
50
|
+
script = build_command(command.script)
|
51
|
+
script = add_pre_command(script)
|
52
|
+
ps_functions = command.import_functions.map { |f| File.read(File.join(File.dirname(__FILE__), 'support', f)) }
|
53
|
+
<<-EOF
|
54
|
+
$exitCode = 1
|
55
|
+
try {
|
56
|
+
#{ps_functions.join("\n")}
|
57
|
+
$success = (#{script})
|
58
|
+
if ($success -is [Boolean] -and $success) { $exitCode = 0 }
|
59
|
+
} catch {
|
60
|
+
Write-Output $_.Exception.Message
|
61
|
+
}
|
62
|
+
Write-Output "Exiting with code: $exitCode"
|
63
|
+
exit $exitCode
|
64
|
+
EOF
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
function CheckFileAccessRules
|
2
|
+
{
|
3
|
+
param($path, $identity, $rules)
|
4
|
+
|
5
|
+
$result = $false
|
6
|
+
$accessRules = (Get-Acl $path).access | Where-Object {$_.AccessControlType -eq 'Allow' -and $_.IdentityReference -eq $identity }
|
7
|
+
if ($accessRules) {
|
8
|
+
$match = $accessRules.FileSystemRights.ToString() -Split (', ') | ?{$rules -contains $_}
|
9
|
+
$result = $match -ne $null -or $match.length -gt 0
|
10
|
+
}
|
11
|
+
$result
|
12
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
function CropText
|
2
|
+
{
|
3
|
+
param($text, $fromPattern, $toPattern)
|
4
|
+
|
5
|
+
$from, $to = ([regex]::matches($text, $fromPattern)), ([regex]::matches($text, $toPattern))
|
6
|
+
if ($from.count -gt 0 -and $to.count -gt 0) {
|
7
|
+
$text.substring($from[0].index, $to[0].index + $to[0].length - $from[0].index)
|
8
|
+
} else {
|
9
|
+
""
|
10
|
+
}
|
11
|
+
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
function FindInstalledApplication
|
2
|
+
{
|
3
|
+
param($appName, $appVersion)
|
4
|
+
$selectionCriteria = "(Name like '$appName' or PackageName like '$appName') and InstallState = 5"
|
5
|
+
if ($appVersion -ne $null) { $selectionCriteria += " and version = '$appVersion'"}
|
6
|
+
Get-WmiObject Win32_Product -filter $selectionCriteria
|
7
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
function FindUser
|
2
|
+
{
|
3
|
+
param($userName, $domain)
|
4
|
+
if ($domain -eq $null) {$selectionCriteria = " and LocalAccount = true"}
|
5
|
+
else {$selectionCriteria = " and Domain = '$domain'"}
|
6
|
+
|
7
|
+
Get-WmiObject Win32_UserAccount -filter "Name = '$userName' $selectionCriteria"
|
8
|
+
}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
function FindUserGroup
|
2
|
+
{
|
3
|
+
param($userName, $groupName, $userDomain, $groupDomain)
|
4
|
+
$user = FindUser -userName $userName -domain $userDomain
|
5
|
+
$group = FindGroup -groupName $groupName -domain $groupDomain
|
6
|
+
if ($user -and $group) {
|
7
|
+
Get-WmiObject Win32_GroupUser -filter ("GroupComponent = 'Win32_Group.Domain=`"" + $group.domain + "`",Name=`"" + $group.name + "`"' and PartComponent = 'Win32_UserAccount.Domain=`"" + $user.domain + "`",Name=`"" + $user.name + "`"'")
|
8
|
+
}
|
9
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
function IsPortListening
|
2
|
+
{
|
3
|
+
param($portNumber, $protocol)
|
4
|
+
$netstatOutput = netstat -an | Out-String
|
5
|
+
$networkIPs = (Get-WmiObject Win32_NetworkAdapterConfiguration | ? {$_.IPEnabled}) | %{ $_.IPAddress[0] }
|
6
|
+
foreach ($ipaddress in $networkIPs)
|
7
|
+
{
|
8
|
+
$matchExpression = ("$ipaddress" + ":" + $portNumber)
|
9
|
+
if ($protocol) { $matchExpression = ($protocol.toUpper() + "\s+$matchExpression") }
|
10
|
+
if ($netstatOutput -match $matchExpression) { return $true }
|
11
|
+
}
|
12
|
+
$false
|
13
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Serverspec
|
2
|
+
module Backend
|
3
|
+
class WinRM < Base
|
4
|
+
include PowerShell::ScriptHelper
|
5
|
+
|
6
|
+
def run_command(cmd, opts={})
|
7
|
+
script = create_script(cmd)
|
8
|
+
winrm = RSpec.configuration.winrm
|
9
|
+
|
10
|
+
result = winrm.powershell(script)
|
11
|
+
stdout, stderr = [:stdout, :stderr].map do |s|
|
12
|
+
result[:data].select {|item| item.key? s}.map {|item| item[s]}.join
|
13
|
+
end
|
14
|
+
result[:exitcode] = 1 if result[:exitcode] == 0 and !stderr.empty?
|
15
|
+
|
16
|
+
if @example
|
17
|
+
@example.metadata[:command] = script
|
18
|
+
@example.metadata[:stdout] = stdout + stderr
|
19
|
+
end
|
20
|
+
|
21
|
+
{ :stdout => stdout, :stderr => stderr,
|
22
|
+
:exit_status => result[:exitcode], :exit_signal => nil }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/serverspec/backend.rb
CHANGED
@@ -1,2 +1,7 @@
|
|
1
|
+
require 'serverspec/backend/base'
|
1
2
|
require 'serverspec/backend/ssh'
|
2
3
|
require 'serverspec/backend/exec'
|
4
|
+
require 'serverspec/backend/powershell/script_helper'
|
5
|
+
require 'serverspec/backend/powershell/command'
|
6
|
+
require 'serverspec/backend/cmd'
|
7
|
+
require 'serverspec/backend/winrm'
|