serverspec 0.8.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|