spectre-core 1.8.3 → 1.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/spectre +53 -16
- data/lib/spectre/assertion.rb +15 -21
- data/lib/spectre/curl.rb +45 -22
- data/lib/spectre/helpers.rb +84 -14
- data/lib/spectre/http.rb +32 -17
- data/lib/spectre/mixin.rb +9 -16
- data/lib/spectre/reporter/console.rb +1 -0
- data/lib/spectre/reporter/junit.rb +2 -0
- data/lib/spectre.rb +17 -13
- metadata +19 -65
- data/lib/spectre/database/postgres.rb +0 -78
- data/lib/spectre/ftp.rb +0 -195
- data/lib/spectre/mysql.rb +0 -97
- data/lib/spectre/ssh.rb +0 -149
data/lib/spectre/ftp.rb
DELETED
@@ -1,195 +0,0 @@
|
|
1
|
-
require 'net/ftp'
|
2
|
-
require 'net/sftp'
|
3
|
-
require 'logger'
|
4
|
-
require 'json'
|
5
|
-
|
6
|
-
|
7
|
-
module Spectre
|
8
|
-
module FTP
|
9
|
-
@@cfg = {}
|
10
|
-
|
11
|
-
class FTPConnection < DslClass
|
12
|
-
def initialize host, username, password, opts, logger
|
13
|
-
@__logger = logger
|
14
|
-
@__session = nil
|
15
|
-
|
16
|
-
@__host = host
|
17
|
-
@__username = username
|
18
|
-
@__password = password
|
19
|
-
@__opts = opts
|
20
|
-
end
|
21
|
-
|
22
|
-
def connect!
|
23
|
-
return unless @__session == nil or @__session.closed?
|
24
|
-
@__logger.info "Connecting to '#{@__host}' with user '#{@__username}'"
|
25
|
-
@__session = Net::FTP.new(@__host, @__opts)
|
26
|
-
@__session.login @__username, @__password
|
27
|
-
end
|
28
|
-
|
29
|
-
def close
|
30
|
-
return unless @__session and not @__session.closed?
|
31
|
-
@__session.close
|
32
|
-
end
|
33
|
-
|
34
|
-
def can_connect?
|
35
|
-
begin
|
36
|
-
connect!
|
37
|
-
return true
|
38
|
-
rescue
|
39
|
-
return false
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def download remotefile, to: File.basename(remotefile)
|
44
|
-
connect!
|
45
|
-
@__logger.info "Downloading '#{@__username}@#{@__host}:#{File.join @__session.pwd, remotefile}' to '#{File.expand_path to}'"
|
46
|
-
@__session.getbinaryfile(remotefile, to)
|
47
|
-
end
|
48
|
-
|
49
|
-
def upload localfile, to: File.basename(localfile)
|
50
|
-
connect!
|
51
|
-
@__logger.info "Uploading '#{File.expand_path localfile}' to '#{@__username}@#{@__host}:#{File.join @__session.pwd, to}'"
|
52
|
-
@__session.putbinaryfile(localfile, to)
|
53
|
-
end
|
54
|
-
|
55
|
-
def list
|
56
|
-
connect!
|
57
|
-
file_list = @__session.list
|
58
|
-
@__logger.info "Listing file in #{@__session.pwd}\n#{file_list}"
|
59
|
-
file_list
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
class SFTPConnection < DslClass
|
65
|
-
def initialize host, username, opts, logger
|
66
|
-
opts[:non_interactive] = true
|
67
|
-
|
68
|
-
@__logger = logger
|
69
|
-
@__session = nil
|
70
|
-
@__host = host
|
71
|
-
@__username = username
|
72
|
-
@__opts = opts
|
73
|
-
end
|
74
|
-
|
75
|
-
def connect!
|
76
|
-
return unless @__session == nil or @__session.closed?
|
77
|
-
@__logger.info "Connecting to '#{@__host}' with user '#{@__username}'"
|
78
|
-
@__session = Net::SFTP.start(@__host, @__username, @__opts)
|
79
|
-
@__session.connect!
|
80
|
-
end
|
81
|
-
|
82
|
-
def close
|
83
|
-
return unless @__session and not @__session.closed?
|
84
|
-
# @__session.close!
|
85
|
-
end
|
86
|
-
|
87
|
-
def can_connect?
|
88
|
-
begin
|
89
|
-
connect!
|
90
|
-
return true
|
91
|
-
rescue
|
92
|
-
return false
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def download remotefile, to: File.basename(remotefile)
|
97
|
-
@__logger.info "Downloading '#{@__username}@#{@__host}:#{remotefile}' to '#{File.expand_path to}'"
|
98
|
-
connect!
|
99
|
-
@__session.download!(remotefile, to)
|
100
|
-
end
|
101
|
-
|
102
|
-
def upload localfile, to: File.basename(localfile)
|
103
|
-
@__logger.info "Uploading '#{File.expand_path localfile}' to '#{@__username}@#{@__host}:#{to}'"
|
104
|
-
connect!
|
105
|
-
@__session.upload!(localfile, to)
|
106
|
-
end
|
107
|
-
|
108
|
-
def stat path
|
109
|
-
connect!
|
110
|
-
file_info = @__session.stat! path
|
111
|
-
@__logger.info "Stat '#{path}'\n#{JSON.pretty_generate file_info.attributes}"
|
112
|
-
file_info.attributes
|
113
|
-
end
|
114
|
-
|
115
|
-
def exists path
|
116
|
-
begin
|
117
|
-
file_info = @__session.stat! path
|
118
|
-
|
119
|
-
rescue Net::SFTP::StatusException => e
|
120
|
-
return false if e.description == 'no such file'
|
121
|
-
raise e
|
122
|
-
end
|
123
|
-
|
124
|
-
return true
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
|
129
|
-
class << self
|
130
|
-
def ftp name, config={}, &block
|
131
|
-
raise "FTP connection '#{name}' not configured" unless @@cfg.key?(name) or config.count > 0
|
132
|
-
cfg = @@cfg[name] || {}
|
133
|
-
|
134
|
-
host = config[:host] || cfg['host'] || name
|
135
|
-
username = config[:username] || cfg['username']
|
136
|
-
password = config[:password] || cfg['password']
|
137
|
-
|
138
|
-
opts = {}
|
139
|
-
opts[:ssl] = config[:ssl]
|
140
|
-
opts[:port] = config[:port] || cfg['port'] || 21
|
141
|
-
|
142
|
-
@@logger.info "Connecting to #{host} with user #{username}"
|
143
|
-
|
144
|
-
ftp_conn = FTPConnection.new(host, username, password, opts, @@logger)
|
145
|
-
|
146
|
-
begin
|
147
|
-
ftp_conn.instance_eval &block
|
148
|
-
ensure
|
149
|
-
ftp_conn.close
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
def sftp name, config={}, &block
|
154
|
-
raise "FTP connection '#{name}' not configured" unless @@cfg.key?(name) or config.count > 0
|
155
|
-
|
156
|
-
cfg = @@cfg[name] || {}
|
157
|
-
|
158
|
-
host = config[:host] || cfg['host'] || name
|
159
|
-
username = config[:username] || cfg['username']
|
160
|
-
password = config[:password] || cfg['password']
|
161
|
-
|
162
|
-
opts = {}
|
163
|
-
opts[:password] = password
|
164
|
-
opts[:port] = config[:port] || cfg['port'] || 22
|
165
|
-
opts[:keys] = [cfg['key']] if cfg.key? 'key'
|
166
|
-
opts[:passphrase] = cfg['passphrase'] if cfg.key? 'passphrase'
|
167
|
-
|
168
|
-
opts[:auth_methods] = []
|
169
|
-
opts[:auth_methods].push 'publickey' if opts[:keys]
|
170
|
-
opts[:auth_methods].push 'password' if opts[:password]
|
171
|
-
|
172
|
-
sftp_con = SFTPConnection.new(host, username, opts, @@logger)
|
173
|
-
|
174
|
-
begin
|
175
|
-
sftp_con.instance_eval &block
|
176
|
-
ensure
|
177
|
-
sftp_con.close
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
Spectre.register do |config|
|
183
|
-
@@logger = ::Logger.new config['log_file'], progname: 'spectre/ftp'
|
184
|
-
|
185
|
-
if config.key? 'ftp'
|
186
|
-
|
187
|
-
config['ftp'].each do |name, cfg|
|
188
|
-
@@cfg[name] = cfg
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
Spectre.delegate :ftp, :sftp, to: self
|
194
|
-
end
|
195
|
-
end
|
data/lib/spectre/mysql.rb
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
require 'mysql2'
|
2
|
-
|
3
|
-
module Spectre
|
4
|
-
module MySQL
|
5
|
-
|
6
|
-
class MySqlQuery < DslClass
|
7
|
-
def initialize query
|
8
|
-
@__query = query
|
9
|
-
end
|
10
|
-
|
11
|
-
def host hostname
|
12
|
-
@__query['host'] = hostname
|
13
|
-
end
|
14
|
-
|
15
|
-
def username user
|
16
|
-
@__query['username'] = user
|
17
|
-
end
|
18
|
-
|
19
|
-
def password pass
|
20
|
-
@__query['password'] = pass
|
21
|
-
end
|
22
|
-
|
23
|
-
def database name
|
24
|
-
@__query['database'] = name
|
25
|
-
end
|
26
|
-
|
27
|
-
def query statement
|
28
|
-
@__query['query'] = [] if not @__query.key? 'query'
|
29
|
-
@__query['query'].append(statement)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
class << self
|
34
|
-
@@mysql_cfg = {}
|
35
|
-
@@result = nil
|
36
|
-
@@last_conn = nil
|
37
|
-
|
38
|
-
def mysql name = nil, &block
|
39
|
-
query = {}
|
40
|
-
|
41
|
-
if name != nil and @@mysql_cfg.key? name
|
42
|
-
query.merge! @@mysql_cfg[name]
|
43
|
-
raise "No `host' set for MySQL client '#{name}'. Check your MySQL config in your environment." if !query['host']
|
44
|
-
elsif name != nil
|
45
|
-
query['host'] = name
|
46
|
-
elsif @@last_conn == nil
|
47
|
-
raise 'No name given and there was no previous MySQL connection to use'
|
48
|
-
end
|
49
|
-
|
50
|
-
MySqlQuery.new(query).instance_eval(&block) if block_given?
|
51
|
-
|
52
|
-
if name != nil
|
53
|
-
@@last_conn = {
|
54
|
-
host: query['host'],
|
55
|
-
username: query['username'],
|
56
|
-
password: query['password'],
|
57
|
-
database: query['database']
|
58
|
-
}
|
59
|
-
end
|
60
|
-
|
61
|
-
@@logger.info "Connecting to database #{query['username']}@#{query['host']}:#{query['database']}"
|
62
|
-
|
63
|
-
client = ::Mysql2::Client.new(**@@last_conn)
|
64
|
-
|
65
|
-
res = []
|
66
|
-
|
67
|
-
query['query'].each do |statement|
|
68
|
-
@@logger.info 'Executing statement "' + statement + '"'
|
69
|
-
res = client.query(statement, cast_booleans: true)
|
70
|
-
end if query['query']
|
71
|
-
|
72
|
-
@@result = res.map { |row| OpenStruct.new row } if res
|
73
|
-
|
74
|
-
client.close
|
75
|
-
end
|
76
|
-
|
77
|
-
def result
|
78
|
-
raise 'No MySQL query has been executed yet' unless @@result
|
79
|
-
@@result
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
Spectre.register do |config|
|
84
|
-
@@logger = ::Logger.new config['log_file'], progname: 'spectre/mysql'
|
85
|
-
|
86
|
-
if config.key? 'mysql'
|
87
|
-
@@mysql_cfg = {}
|
88
|
-
|
89
|
-
config['mysql'].each do |name, cfg|
|
90
|
-
@@mysql_cfg[name] = cfg
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
Spectre.delegate :mysql, :result, to: self
|
96
|
-
end
|
97
|
-
end
|
data/lib/spectre/ssh.rb
DELETED
@@ -1,149 +0,0 @@
|
|
1
|
-
require 'net/ssh'
|
2
|
-
require 'logger'
|
3
|
-
|
4
|
-
|
5
|
-
module Spectre
|
6
|
-
module SSH
|
7
|
-
@@cfg = {}
|
8
|
-
|
9
|
-
class SSHConnection < DslClass
|
10
|
-
def initialize host, username, opts, logger
|
11
|
-
opts[:non_interactive] = true
|
12
|
-
|
13
|
-
@__logger = logger
|
14
|
-
@__host = host
|
15
|
-
@__username = username
|
16
|
-
@__opts = opts
|
17
|
-
@__session = nil
|
18
|
-
@__exit_code = nil
|
19
|
-
@__output = ''
|
20
|
-
end
|
21
|
-
|
22
|
-
def file_exists path
|
23
|
-
exec "ls #{path}"
|
24
|
-
exit_code == 0
|
25
|
-
end
|
26
|
-
|
27
|
-
def owner_of path
|
28
|
-
exec "stat -c %U #{path}"
|
29
|
-
output.chomp
|
30
|
-
end
|
31
|
-
|
32
|
-
def connect!
|
33
|
-
return unless @__session == nil or @__session.closed?
|
34
|
-
@__session = Net::SSH.start(@__host, @__username, @__opts)
|
35
|
-
end
|
36
|
-
|
37
|
-
def close
|
38
|
-
return unless @__session and not @__session.closed?
|
39
|
-
@__session.close
|
40
|
-
end
|
41
|
-
|
42
|
-
def can_connect?
|
43
|
-
@__output = nil
|
44
|
-
|
45
|
-
begin
|
46
|
-
connect!
|
47
|
-
@__session.open_channel.close
|
48
|
-
@__output = "successfully connected to #{@__host} with user #{@__username}"
|
49
|
-
@__exit_code = 0
|
50
|
-
return true
|
51
|
-
rescue Exception => e
|
52
|
-
@__logger.error e.message
|
53
|
-
@__output = "unable to connect to #{@__host} with user #{@__username}"
|
54
|
-
@__exit_code = 1
|
55
|
-
end
|
56
|
-
|
57
|
-
return false
|
58
|
-
end
|
59
|
-
|
60
|
-
def exec command
|
61
|
-
connect!
|
62
|
-
|
63
|
-
log_str = "#{@__session.options[:user]}@#{@__session.host} -p #{@__session.options[:port]} #{command}"
|
64
|
-
|
65
|
-
@channel = @__session.open_channel do |channel|
|
66
|
-
channel.exec(command) do |ch, success|
|
67
|
-
abort "could not execute #{command} on #{@__session.host}" unless success
|
68
|
-
|
69
|
-
@__output = ''
|
70
|
-
|
71
|
-
channel.on_data do |ch, data|
|
72
|
-
@__output += data
|
73
|
-
end
|
74
|
-
|
75
|
-
channel.on_extended_data do |ch,type,data|
|
76
|
-
@__output += data
|
77
|
-
end
|
78
|
-
|
79
|
-
channel.on_request('exit-status') do |ch, data|
|
80
|
-
@__exit_code = data.read_long
|
81
|
-
end
|
82
|
-
|
83
|
-
# channel.on_request('exit-signal') do |ch, data|
|
84
|
-
# exit_code = data.read_long
|
85
|
-
# end
|
86
|
-
end
|
87
|
-
|
88
|
-
end
|
89
|
-
|
90
|
-
@channel.wait
|
91
|
-
@__session.loop
|
92
|
-
|
93
|
-
log_str += "\n" + @__output
|
94
|
-
@__logger.info log_str
|
95
|
-
end
|
96
|
-
|
97
|
-
def output
|
98
|
-
@__output
|
99
|
-
end
|
100
|
-
|
101
|
-
def exit_code
|
102
|
-
@__exit_code
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
class << self
|
108
|
-
def ssh name, config = {}, &block
|
109
|
-
raise "SSH connection '#{name}' not configured" unless @@cfg.key?(name) or config.count > 0
|
110
|
-
|
111
|
-
cfg = @@cfg[name] || {}
|
112
|
-
|
113
|
-
host = cfg['host'] || name
|
114
|
-
username = config[:username] || cfg['username']
|
115
|
-
password = config[:password] || cfg['password']
|
116
|
-
|
117
|
-
opts = {}
|
118
|
-
opts[:password] = password
|
119
|
-
opts[:port] = config[:port] || cfg['port'] || 22
|
120
|
-
opts[:keys] = [cfg['key']] if cfg.key? 'key'
|
121
|
-
opts[:passphrase] = cfg['passphrase'] if cfg.key? 'passphrase'
|
122
|
-
|
123
|
-
opts[:auth_methods] = []
|
124
|
-
opts[:auth_methods].push 'publickey' if opts[:keys]
|
125
|
-
opts[:auth_methods].push 'password' if opts[:password]
|
126
|
-
|
127
|
-
ssh_con = SSHConnection.new(host, username, opts, @@logger)
|
128
|
-
|
129
|
-
begin
|
130
|
-
ssh_con.instance_eval &block
|
131
|
-
ensure
|
132
|
-
ssh_con.close
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
Spectre.register do |config|
|
138
|
-
@@logger = ::Logger.new config['log_file'], progname: 'spectre/ssh'
|
139
|
-
|
140
|
-
if config.key? 'ssh'
|
141
|
-
config['ssh'].each do |name, cfg|
|
142
|
-
@@cfg[name] = cfg
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
Spectre.delegate :ssh, to: self
|
148
|
-
end
|
149
|
-
end
|