specinfra 0.0.1 → 0.0.2
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/Rakefile +10 -0
- data/lib/specinfra.rb +24 -2
- data/lib/specinfra/backend.rb +7 -0
- data/lib/specinfra/backend/base.rb +31 -0
- data/lib/specinfra/backend/cmd.rb +39 -0
- data/lib/specinfra/backend/exec.rb +218 -0
- data/lib/specinfra/backend/powershell/command.rb +40 -0
- data/lib/specinfra/backend/powershell/script_helper.rb +85 -0
- data/lib/specinfra/backend/powershell/support/check_file_access_rules.ps1 +8 -0
- data/lib/specinfra/backend/powershell/support/crop_text.ps1 +11 -0
- data/lib/specinfra/backend/powershell/support/find_group.ps1 +8 -0
- data/lib/specinfra/backend/powershell/support/find_installed_application.ps1 +7 -0
- data/lib/specinfra/backend/powershell/support/find_service.ps1 +5 -0
- data/lib/specinfra/backend/powershell/support/find_user.ps1 +8 -0
- data/lib/specinfra/backend/powershell/support/find_usergroup.ps1 +9 -0
- data/lib/specinfra/backend/powershell/support/is_port_listening.ps1 +13 -0
- data/lib/specinfra/backend/ssh.rb +93 -0
- data/lib/specinfra/backend/winrm.rb +26 -0
- data/lib/specinfra/configuration.rb +12 -0
- data/lib/specinfra/helper.rb +7 -0
- data/lib/specinfra/helper/backend.rb +18 -0
- data/lib/specinfra/helper/configuration.rb +37 -0
- data/lib/specinfra/helper/detect_os.rb +18 -0
- data/lib/specinfra/helper/os.rb +27 -0
- data/lib/specinfra/helper/properties.rb +14 -0
- data/lib/specinfra/properties.rb +17 -0
- data/lib/specinfra/version.rb +1 -1
- data/spec/helpers/properties_spec.rb +11 -0
- data/spec/spec_helper.rb +4 -0
- metadata +31 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e123d78d06d4075c043995799a8c0e9f2c3593d
|
4
|
+
data.tar.gz: 9a4ce0fdd1c2ff46c42d8323d3a2d31ffc4185e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7440fae579eef9fa415ade153a00dbd556ef529fd4f8bd4f3cc0404ec8d2486e403e4dfcdffe0779e425d73f9e885f3eb14f64008e57445663dc32f6c151ddfa
|
7
|
+
data.tar.gz: 7320a36b630ee5ed5317a12546f94b54b79c0697e4b42e04dd5663ea34a8b815ec1847d53572133c4f5a7f5d4d94ff7531e27e81a15b7c02356235ccd607df44
|
data/Rakefile
CHANGED
data/lib/specinfra.rb
CHANGED
@@ -1,5 +1,27 @@
|
|
1
1
|
require "specinfra/version"
|
2
|
+
require "specinfra/helper"
|
3
|
+
require "specinfra/backend"
|
4
|
+
require "specinfra/configuration"
|
2
5
|
|
3
|
-
|
4
|
-
|
6
|
+
include SpecInfra
|
7
|
+
|
8
|
+
module SpecInfra
|
9
|
+
class << self
|
10
|
+
def configuration
|
11
|
+
SpecInfra::Configuration
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
RSpec.configure do |c|
|
17
|
+
c.include(SpecInfra::Helper::Configuration)
|
18
|
+
c.add_setting :os, :default => nil
|
19
|
+
c.add_setting :host, :default => nil
|
20
|
+
c.add_setting :ssh, :default => nil
|
21
|
+
c.add_setting :sudo_password, :default => nil
|
22
|
+
c.add_setting :winrm, :default => nil
|
23
|
+
SpecInfra.configuration.defaults.each { |k, v| c.add_setting k, :default => v }
|
24
|
+
c.before :each do
|
25
|
+
backend.set_example(example) if defined?(SPEC_TYPE)
|
26
|
+
end
|
5
27
|
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'specinfra/backend/base'
|
2
|
+
require 'specinfra/backend/exec'
|
3
|
+
require 'specinfra/backend/ssh'
|
4
|
+
require 'specinfra/backend/powershell/script_helper'
|
5
|
+
require 'specinfra/backend/powershell/command'
|
6
|
+
require 'specinfra/backend/cmd'
|
7
|
+
require 'specinfra/backend/winrm'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module SpecInfra
|
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,39 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module SpecInfra
|
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 %Q{powershell -encodedCommand #{encode_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
|
+
if Open3.respond_to? :capture3
|
22
|
+
stdout, stderr, status = Open3.capture3(script)
|
23
|
+
# powershell still exits with 0 even if there are syntax errors, although it spits the error out into stderr
|
24
|
+
# so we have to resort to return an error exit code if there is anything in the standard error
|
25
|
+
status = 1 if status == 0 and !stderr.empty?
|
26
|
+
{ :stdout => stdout, :stderr => stderr, :status => status }
|
27
|
+
else
|
28
|
+
stdout = `#{script} 2>&1`
|
29
|
+
{ :stdout => stdout, :stderr => nil, :status => $? }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def check_os
|
34
|
+
# Dirty hack for specs
|
35
|
+
'Windows'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module SpecInfra
|
4
|
+
module Backend
|
5
|
+
class Exec < Base
|
6
|
+
|
7
|
+
def run_command(cmd, opts={})
|
8
|
+
cmd = build_command(cmd)
|
9
|
+
cmd = add_pre_command(cmd)
|
10
|
+
stdout = run_with_no_ruby_environment do
|
11
|
+
`#{build_command(cmd)} 2>&1`
|
12
|
+
end
|
13
|
+
# In ruby 1.9, it is possible to use Open3.capture3, but not in 1.8
|
14
|
+
#stdout, stderr, status = Open3.capture3(cmd)
|
15
|
+
|
16
|
+
if @example
|
17
|
+
@example.metadata[:command] = cmd
|
18
|
+
@example.metadata[:stdout] = stdout
|
19
|
+
end
|
20
|
+
|
21
|
+
{ :stdout => stdout, :stderr => nil,
|
22
|
+
:exit_status => $?.exitstatus, :exit_signal => nil }
|
23
|
+
end
|
24
|
+
|
25
|
+
def run_with_no_ruby_environment
|
26
|
+
keys = %w[BUNDLER_EDITOR BUNDLE_BIN_PATH BUNDLE_GEMFILE
|
27
|
+
RUBYOPT GEM_HOME GEM_PATH GEM_CACHE]
|
28
|
+
|
29
|
+
keys.each { |key| ENV["_SPECINFRA_#{key}"] = ENV[key] ; ENV.delete(key) }
|
30
|
+
yield
|
31
|
+
ensure
|
32
|
+
keys.each { |key| ENV[key] = ENV.delete("_SPECINFRA_#{key}") }
|
33
|
+
end
|
34
|
+
|
35
|
+
def build_command(cmd)
|
36
|
+
path = SpecInfra.configuration.path || RSpec.configuration.path
|
37
|
+
if path
|
38
|
+
cmd = "env PATH=#{path}:$PATH #{cmd}"
|
39
|
+
cmd.gsub!(/(\&\&\s*!?\(?\s*)/, "\\1env PATH=#{path}:$PATH ")
|
40
|
+
cmd.gsub!(/(\|\|\s*!?\(?\s*)/, "\\1env PATH=#{path}:$PATH ")
|
41
|
+
end
|
42
|
+
cmd
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_pre_command(cmd)
|
46
|
+
path = SpecInfra.configuration.path || RSpec.configuration.path
|
47
|
+
if SpecInfra.configuration.pre_command
|
48
|
+
cmd = "#{SpecInfra.configuration.pre_command} && #{cmd}"
|
49
|
+
cmd = "env PATH=#{path}:$PATH #{cmd}" if path
|
50
|
+
end
|
51
|
+
cmd
|
52
|
+
end
|
53
|
+
|
54
|
+
def check_running(process)
|
55
|
+
ret = run_command(commands.check_running(process))
|
56
|
+
|
57
|
+
# In Ubuntu, some services are under upstart and "service foo status" returns
|
58
|
+
# exit status 0 even though they are stopped.
|
59
|
+
# So return false if stdout contains "stopped/waiting".
|
60
|
+
return false if ret[:stdout] =~ /stopped\/waiting/
|
61
|
+
|
62
|
+
# If the service is not registered, check by ps command
|
63
|
+
if ret[:exit_status] == 1
|
64
|
+
ret = run_command(commands.check_process(process))
|
65
|
+
end
|
66
|
+
|
67
|
+
ret[:exit_status] == 0
|
68
|
+
end
|
69
|
+
|
70
|
+
def check_monitored_by_monit(process)
|
71
|
+
ret = run_command(commands.check_monitored_by_monit(process))
|
72
|
+
return false unless ret[:stdout] != nil && ret[:exit_status] == 0
|
73
|
+
|
74
|
+
retlines = ret[:stdout].split(/[\r\n]+/).map(&:strip)
|
75
|
+
proc_index = retlines.index("Process '#{process}'")
|
76
|
+
return false unless proc_index
|
77
|
+
|
78
|
+
retlines[proc_index+2].match(/\Amonitoring status\s+monitored\Z/i) != nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def check_readable(file, by_whom)
|
82
|
+
mode = sprintf('%04s',run_command(commands.get_mode(file))[:stdout].strip)
|
83
|
+
mode = mode.split('')
|
84
|
+
mode_octal = mode[0].to_i * 512 + mode[1].to_i * 64 + mode[2].to_i * 8 + mode[3].to_i * 1
|
85
|
+
case by_whom
|
86
|
+
when nil
|
87
|
+
mode_octal & 0444 != 0
|
88
|
+
when 'owner'
|
89
|
+
mode_octal & 0400 != 0
|
90
|
+
when 'group'
|
91
|
+
mode_octal & 0040 != 0
|
92
|
+
when 'others'
|
93
|
+
mode_octal & 0004 != 0
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def check_writable(file, by_whom)
|
98
|
+
mode = sprintf('%04s',run_command(commands.get_mode(file))[:stdout].strip)
|
99
|
+
mode = mode.split('')
|
100
|
+
mode_octal = mode[0].to_i * 512 + mode[1].to_i * 64 + mode[2].to_i * 8 + mode[3].to_i * 1
|
101
|
+
case by_whom
|
102
|
+
when nil
|
103
|
+
mode_octal & 0222 != 0
|
104
|
+
when 'owner'
|
105
|
+
mode_octal & 0200 != 0
|
106
|
+
when 'group'
|
107
|
+
mode_octal & 0020 != 0
|
108
|
+
when 'others'
|
109
|
+
mode_octal & 0002 != 0
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def check_executable(file, by_whom)
|
114
|
+
mode = sprintf('%04s',run_command(commands.get_mode(file))[:stdout].strip)
|
115
|
+
mode = mode.split('')
|
116
|
+
mode_octal = mode[0].to_i * 512 + mode[1].to_i * 64 + mode[2].to_i * 8 + mode[3].to_i * 1
|
117
|
+
case by_whom
|
118
|
+
when nil
|
119
|
+
mode_octal & 0111 != 0
|
120
|
+
when 'owner'
|
121
|
+
mode_octal & 0100 != 0
|
122
|
+
when 'group'
|
123
|
+
mode_octal & 0010 != 0
|
124
|
+
when 'others'
|
125
|
+
mode_octal & 0001 != 0
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def check_mounted(path, expected_attr, only_with)
|
130
|
+
ret = run_command(commands.check_mounted(path))
|
131
|
+
if expected_attr.nil? || ret[:exit_status] != 0
|
132
|
+
return ret[:exit_status] == 0
|
133
|
+
end
|
134
|
+
|
135
|
+
mount = ret[:stdout].scan(/\S+/)
|
136
|
+
actual_attr = { :device => mount[0], :type => mount[4] }
|
137
|
+
mount[5].gsub(/\(|\)/, '').split(',').each do |option|
|
138
|
+
name, val = option.split('=')
|
139
|
+
if val.nil?
|
140
|
+
actual_attr[name.to_sym] = true
|
141
|
+
else
|
142
|
+
val = val.to_i if val.match(/^\d+$/)
|
143
|
+
actual_attr[name.to_sym] = val
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
if ! expected_attr[:options].nil?
|
148
|
+
expected_attr.merge!(expected_attr[:options])
|
149
|
+
expected_attr.delete(:options)
|
150
|
+
end
|
151
|
+
|
152
|
+
if only_with
|
153
|
+
actual_attr == expected_attr
|
154
|
+
else
|
155
|
+
expected_attr.each do |key, val|
|
156
|
+
return false if actual_attr[key] != val
|
157
|
+
end
|
158
|
+
true
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def check_routing_table(expected_attr)
|
163
|
+
return false if ! expected_attr[:destination]
|
164
|
+
ret = run_command(commands.check_routing_table(expected_attr[:destination]))
|
165
|
+
return false if ret[:exit_status] != 0
|
166
|
+
|
167
|
+
ret[:stdout] =~ /^(\S+)(?: via (\S+))? dev (\S+).+\r\n(?:default via (\S+))?/
|
168
|
+
actual_attr = {
|
169
|
+
:destination => $1,
|
170
|
+
:gateway => $2 ? $2 : $4,
|
171
|
+
:interface => expected_attr[:interface] ? $3 : nil
|
172
|
+
}
|
173
|
+
|
174
|
+
expected_attr.each do |key, val|
|
175
|
+
return false if actual_attr[key] != val
|
176
|
+
end
|
177
|
+
true
|
178
|
+
end
|
179
|
+
|
180
|
+
def check_os
|
181
|
+
return RSpec.configuration.os if RSpec.configuration.os
|
182
|
+
if run_command('ls /etc/redhat-release')[:exit_status] == 0
|
183
|
+
line = run_command('cat /etc/redhat-release')[:stdout]
|
184
|
+
if line =~ /release (\d[\d.]*)/
|
185
|
+
release = $1
|
186
|
+
end
|
187
|
+
{ :family => 'RedHat', :release => release }
|
188
|
+
elsif run_command('ls /etc/system-release')[:exit_status] == 0
|
189
|
+
{ :family => 'RedHat', :release => nil } # Amazon Linux
|
190
|
+
elsif run_command('ls /etc/debian_version')[:exit_status] == 0
|
191
|
+
{ :family => 'Debian', :release => nil }
|
192
|
+
elsif run_command('ls /etc/gentoo-release')[:exit_status] == 0
|
193
|
+
{ :family => 'Gentoo', :release => nil }
|
194
|
+
elsif run_command('ls /usr/lib/setup/Plamo-*')[:exit_status] == 0
|
195
|
+
{ :family => 'Plamo', :release => nil }
|
196
|
+
elsif run_command('uname -s')[:stdout] =~ /AIX/i
|
197
|
+
{ :family => 'AIX', :release => nil }
|
198
|
+
elsif (os = run_command('uname -sr')[:stdout]) && os =~ /SunOS/i
|
199
|
+
if os =~ /5.10/
|
200
|
+
{ :family => 'Solaris10', :release => nil }
|
201
|
+
elsif run_command('grep -q "Oracle Solaris 11" /etc/release')[:exit_status] == 0
|
202
|
+
{ :family => 'Solaris11', :release => nil }
|
203
|
+
elsif run_command('grep -q SmartOS /etc/release')[:exit_status] == 0
|
204
|
+
{ :family => 'SmartOS', :release => nil }
|
205
|
+
else
|
206
|
+
{ :family => 'Solaris', :release => nil }
|
207
|
+
end
|
208
|
+
elsif run_command('uname -s')[:stdout] =~ /Darwin/i
|
209
|
+
{ :family => 'Darwin', :release => nil }
|
210
|
+
elsif run_command('uname -s')[:stdout] =~ /FreeBSD/i
|
211
|
+
{ :family => 'FreeBSD', :release => nil }
|
212
|
+
else
|
213
|
+
{ :family => 'Base', :release => nil }
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module SpecInfra
|
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
|
+
|
34
|
+
def to_s
|
35
|
+
@script
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module SpecInfra
|
4
|
+
module Backend
|
5
|
+
module PowerShell
|
6
|
+
module ScriptHelper
|
7
|
+
def build_command(cmd)
|
8
|
+
path = SpecInfra.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 = SpecInfra.configuration.path || RSpec.configuration.path
|
22
|
+
if SpecInfra.configuration.pre_command
|
23
|
+
cmd.strip!
|
24
|
+
cmd =
|
25
|
+
<<-EOF
|
26
|
+
if (#{SpecInfra.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
|
+
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
|
55
|
+
$exitCode = 1
|
56
|
+
try {
|
57
|
+
#{ps_functions.join("\n")}
|
58
|
+
$success = (#{script})
|
59
|
+
if ($success -is [Boolean] -and $success) { $exitCode = 0 }
|
60
|
+
} catch {
|
61
|
+
Write-Output $_.Exception.Message
|
62
|
+
}
|
63
|
+
Write-Output "Exiting with code: $exitCode"
|
64
|
+
exit $exitCode
|
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
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
function CheckFileAccessRules
|
2
|
+
{
|
3
|
+
param($path, $identity, $rules)
|
4
|
+
|
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
|
8
|
+
}
|
@@ -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,93 @@
|
|
1
|
+
require 'specinfra/backend/exec'
|
2
|
+
|
3
|
+
module SpecInfra
|
4
|
+
module Backend
|
5
|
+
class Ssh < Exec
|
6
|
+
def run_command(cmd, opt={})
|
7
|
+
cmd = build_command(cmd)
|
8
|
+
cmd = add_pre_command(cmd)
|
9
|
+
ret = ssh_exec!(cmd)
|
10
|
+
|
11
|
+
ret[:stdout].gsub!(/\r\n/, "\n")
|
12
|
+
|
13
|
+
if @example
|
14
|
+
@example.metadata[:command] = cmd
|
15
|
+
@example.metadata[:stdout] = ret[:stdout]
|
16
|
+
end
|
17
|
+
|
18
|
+
ret
|
19
|
+
end
|
20
|
+
|
21
|
+
def build_command(cmd)
|
22
|
+
cmd = super(cmd)
|
23
|
+
if RSpec.configuration.ssh.options[:user] != 'root'
|
24
|
+
cmd = "#{sudo} #{cmd}"
|
25
|
+
cmd.gsub!(/(\&\&\s*!?\(?\s*)/, "\\1#{sudo} ")
|
26
|
+
cmd.gsub!(/(\|\|\s*!?\(?\s*)/, "\\1#{sudo} ")
|
27
|
+
end
|
28
|
+
cmd
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_pre_command(cmd)
|
32
|
+
cmd = super(cmd)
|
33
|
+
user = RSpec.configuration.ssh.options[:user]
|
34
|
+
pre_command = SpecInfra.configuration.pre_command
|
35
|
+
if pre_command && user != 'root'
|
36
|
+
cmd = "#{sudo} #{cmd}"
|
37
|
+
end
|
38
|
+
cmd
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def ssh_exec!(command)
|
43
|
+
stdout_data = ''
|
44
|
+
stderr_data = ''
|
45
|
+
exit_status = nil
|
46
|
+
exit_signal = nil
|
47
|
+
pass_prompt = RSpec.configuration.pass_prompt || /^\[sudo\] password for/
|
48
|
+
|
49
|
+
ssh = RSpec.configuration.ssh
|
50
|
+
ssh.open_channel do |channel|
|
51
|
+
channel.request_pty do |ch, success|
|
52
|
+
abort "Could not obtain pty " if !success
|
53
|
+
end
|
54
|
+
channel.exec("#{command}") do |ch, success|
|
55
|
+
abort "FAILED: couldn't execute command (ssh.channel.exec)" if !success
|
56
|
+
channel.on_data do |ch, data|
|
57
|
+
if data.match pass_prompt
|
58
|
+
abort "Please set sudo password by using SUDO_PASSWORD or ASK_SUDO_PASSWORD environment variable" if RSpec.configuration.sudo_password.nil?
|
59
|
+
channel.send_data "#{RSpec.configuration.sudo_password}\n"
|
60
|
+
else
|
61
|
+
stdout_data += data
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
channel.on_extended_data do |ch, type, data|
|
66
|
+
stderr_data += data
|
67
|
+
end
|
68
|
+
|
69
|
+
channel.on_request("exit-status") do |ch, data|
|
70
|
+
exit_status = data.read_long
|
71
|
+
end
|
72
|
+
|
73
|
+
channel.on_request("exit-signal") do |ch, data|
|
74
|
+
exit_signal = data.read_long
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
ssh.loop
|
79
|
+
{ :stdout => stdout_data, :stderr => stderr_data, :exit_status => exit_status, :exit_signal => exit_signal }
|
80
|
+
end
|
81
|
+
|
82
|
+
def sudo
|
83
|
+
sudo_path = SpecInfra.configuration.sudo_path || RSpec.configuration.sudo_path
|
84
|
+
if sudo_path
|
85
|
+
"#{sudo_path}/sudo"
|
86
|
+
else
|
87
|
+
'sudo'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SpecInfra
|
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
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module SpecInfra
|
2
|
+
module Configuration
|
3
|
+
class << self
|
4
|
+
VALID_OPTIONS_KEYS = [:path, :pre_command, :stdout, :stderr, :sudo_path, :pass_prompt].freeze
|
5
|
+
attr_accessor(*VALID_OPTIONS_KEYS)
|
6
|
+
|
7
|
+
def defaults
|
8
|
+
VALID_OPTIONS_KEYS.inject({}) { |o, k| o.merge!(k => send(k)) }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SpecInfra
|
2
|
+
module Helper
|
3
|
+
['Exec', 'Ssh', 'Cmd', 'WinRM'].each do |backend|
|
4
|
+
eval <<-EOF
|
5
|
+
module #{backend}
|
6
|
+
def backend(commands_object=nil)
|
7
|
+
if ! respond_to?(:commands)
|
8
|
+
commands_object = self.class.const_get(SPEC_TYPE).const_get('Commands').const_get('Base').new
|
9
|
+
end
|
10
|
+
instance = self.class.const_get('SpecInfra').const_get('Backend').const_get('#{backend}').instance
|
11
|
+
instance.set_commands(commands_object || commands)
|
12
|
+
instance
|
13
|
+
end
|
14
|
+
end
|
15
|
+
EOF
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module SpecInfra
|
2
|
+
module Helper
|
3
|
+
module Configuration
|
4
|
+
def subject
|
5
|
+
example.metadata[:subject] = described_class
|
6
|
+
build_configurations
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
# You can create a set of configurations provided to all specs in your spec_helper:
|
11
|
+
#
|
12
|
+
# RSpec.configure { |c| c.pre_command = "source ~/.zshrc" }
|
13
|
+
#
|
14
|
+
# Any configurations you provide with `let(:option_name)` in a spec will
|
15
|
+
# automatically be merged on top of the configurations.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
#
|
19
|
+
# describe 'Gem' do
|
20
|
+
# let(:pre_command) { "source ~/.zshrc" }
|
21
|
+
#
|
22
|
+
# %w(pry awesome_print bundler).each do |p|
|
23
|
+
# describe package(p) do
|
24
|
+
# it { should be_installed.by('gem') }
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
def build_configurations
|
29
|
+
SpecInfra::Configuration.defaults.keys.each do |c|
|
30
|
+
value = self.respond_to?(c.to_sym) ?
|
31
|
+
self.send(c) : RSpec.configuration.send(c)
|
32
|
+
SpecInfra::Configuration.send(:"#{c}=", value)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SpecInfra
|
2
|
+
module Helper
|
3
|
+
module DetectOS
|
4
|
+
def commands
|
5
|
+
property[:os_by_host] = {} if ! property[:os_by_host]
|
6
|
+
host = RSpec.configuration.ssh ? RSpec.configuration.ssh.host : 'localhost'
|
7
|
+
|
8
|
+
if property[:os_by_host][host]
|
9
|
+
os = property[:os_by_host][host]
|
10
|
+
else
|
11
|
+
os = backend(self.class.const_get(SPEC_TYPE).const_get('Commands').const_get('Base')).check_os
|
12
|
+
property[:os_by_host][host] = os
|
13
|
+
end
|
14
|
+
self.class.const_get(SPEC_TYPE).const_get('Commands').const_get(os[:family]).new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SpecInfra
|
2
|
+
module Helper
|
3
|
+
[
|
4
|
+
'Base',
|
5
|
+
'AIX',
|
6
|
+
'Darwin',
|
7
|
+
'Debian',
|
8
|
+
'FreeBSD',
|
9
|
+
'Gentoo',
|
10
|
+
'Plamo',
|
11
|
+
'RedHat',
|
12
|
+
'SmartOS',
|
13
|
+
'Solaris',
|
14
|
+
'Solaris10',
|
15
|
+
'Solaris11',
|
16
|
+
'Windows',
|
17
|
+
].each do |os|
|
18
|
+
eval <<-EOF
|
19
|
+
module #{os}
|
20
|
+
def commands
|
21
|
+
self.class.const_get(SPEC_TYPE).const_get('Commands').const_get('#{os}').new
|
22
|
+
end
|
23
|
+
end
|
24
|
+
EOF
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'specinfra/properties'
|
2
|
+
|
3
|
+
module SpecInfra
|
4
|
+
module Helper
|
5
|
+
module Properties
|
6
|
+
def property
|
7
|
+
SpecInfra::Properties.instance.properties
|
8
|
+
end
|
9
|
+
def set_property(prop)
|
10
|
+
SpecInfra::Properties.instance.properties(prop)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/specinfra/version.rb
CHANGED
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: specinfra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
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-11-
|
11
|
+
date: 2013-11-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -51,7 +51,33 @@ files:
|
|
51
51
|
- README.md
|
52
52
|
- Rakefile
|
53
53
|
- lib/specinfra.rb
|
54
|
+
- lib/specinfra/backend.rb
|
55
|
+
- lib/specinfra/backend/base.rb
|
56
|
+
- lib/specinfra/backend/cmd.rb
|
57
|
+
- lib/specinfra/backend/exec.rb
|
58
|
+
- lib/specinfra/backend/powershell/command.rb
|
59
|
+
- lib/specinfra/backend/powershell/script_helper.rb
|
60
|
+
- lib/specinfra/backend/powershell/support/check_file_access_rules.ps1
|
61
|
+
- lib/specinfra/backend/powershell/support/crop_text.ps1
|
62
|
+
- lib/specinfra/backend/powershell/support/find_group.ps1
|
63
|
+
- lib/specinfra/backend/powershell/support/find_installed_application.ps1
|
64
|
+
- lib/specinfra/backend/powershell/support/find_service.ps1
|
65
|
+
- lib/specinfra/backend/powershell/support/find_user.ps1
|
66
|
+
- lib/specinfra/backend/powershell/support/find_usergroup.ps1
|
67
|
+
- lib/specinfra/backend/powershell/support/is_port_listening.ps1
|
68
|
+
- lib/specinfra/backend/ssh.rb
|
69
|
+
- lib/specinfra/backend/winrm.rb
|
70
|
+
- lib/specinfra/configuration.rb
|
71
|
+
- lib/specinfra/helper.rb
|
72
|
+
- lib/specinfra/helper/backend.rb
|
73
|
+
- lib/specinfra/helper/configuration.rb
|
74
|
+
- lib/specinfra/helper/detect_os.rb
|
75
|
+
- lib/specinfra/helper/os.rb
|
76
|
+
- lib/specinfra/helper/properties.rb
|
77
|
+
- lib/specinfra/properties.rb
|
54
78
|
- lib/specinfra/version.rb
|
79
|
+
- spec/helpers/properties_spec.rb
|
80
|
+
- spec/spec_helper.rb
|
55
81
|
- specinfra.gemspec
|
56
82
|
homepage: ''
|
57
83
|
licenses:
|
@@ -77,4 +103,6 @@ rubygems_version: 2.0.3
|
|
77
103
|
signing_key:
|
78
104
|
specification_version: 4
|
79
105
|
summary: Common layer for serverspec and configspec
|
80
|
-
test_files:
|
106
|
+
test_files:
|
107
|
+
- spec/helpers/properties_spec.rb
|
108
|
+
- spec/spec_helper.rb
|