spectre-core 1.8.3 → 1.11.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/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
|