spectre-core 1.8.1 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc992f089d223d10e25ed3ab390e2fa2b3ea826b24c3943bf60ea04992d14163
4
- data.tar.gz: c95f4a37b887bef1d79fe22f221ddd35957e259d03d3e1c2513b973d3c54f564
3
+ metadata.gz: 76697e95cde1f8359db1f305ba1d15869bd53903d49a0575fa1ee6f2cda7bf98
4
+ data.tar.gz: 72562ba547d8f8ff68e880d8f196bd31c7da8f1fd5639231bb56aa838830879a
5
5
  SHA512:
6
- metadata.gz: b7e9166af9137aab37688aa5a1a975296765d903c53e4547a7e1e74de8347cd4ce6e0860a0fd23dd494cc90fd8baafced1fff3381ecd99316159189f80a44629
7
- data.tar.gz: d762e949fdffe4b5faac4a35192eb2ca130a8799f714667eb10b2e09550ccbff13047581f72e5753e3262b4771f4a4bc65aa46e58615ad6d0e894c9c63f9e0d2
6
+ metadata.gz: e1ce860bd80ee58af11d506ad9e297f9a432a6f71f62b7702574c5dd52af0f6a6de7fa8bd2e35c167e387e063f86f97a77f51e0541399a866133c0a3524b22a9
7
+ data.tar.gz: eebfbac67335a7663f407a26094336ee9815a02ebe74789b82254a45ca6539ccc036f289a3eed37cfc581b8e178986f70cbdf5d3c1af49a657ebce4c9ce7246b
data/exe/spectre CHANGED
@@ -48,6 +48,7 @@ DEFAULT_CONFIG = {
48
48
  },
49
49
  'debug' => false,
50
50
  'out_path' => './reports',
51
+ 'secure_keys' => ['password', 'secret', 'token', 'secure', 'authorization'],
51
52
  'spec_patterns' => ['./specs/**/*.spec.rb'],
52
53
  'mixin_patterns' => ['../common/mixins/**/*.mixin.rb', './mixins/**/*.mixin.rb'],
53
54
  'env_patterns' => ['./environments/**/*.env.yml'],
@@ -68,10 +69,6 @@ DEFAULT_CONFIG = {
68
69
  'spectre/http/basic_auth',
69
70
  'spectre/http/keystone',
70
71
  'spectre/resources',
71
- 'spectre/ssh',
72
- 'spectre/ftp',
73
- 'spectre/mysql',
74
- # 'spectre/postgres',
75
72
  ],
76
73
  'include' => [
77
74
 
@@ -126,11 +123,15 @@ Specific options:}
126
123
  cmd_options['colored'] = false
127
124
  end
128
125
 
126
+ opts.on('--ignore-failure', 'Always exit with code 0') do
127
+ cmd_options['ignore_failure'] = true
128
+ end
129
+
129
130
  opts.on('-o PATH', '--out PATH', 'Output directory path') do |path|
130
- cmd_options['out_path'] = path
131
+ cmd_options['out_path'] = File.absolute_path(path)
131
132
  end
132
133
 
133
- opts.on('-r NAME', '--reporter NAME', Array, "A list of reporters to use") do |reporters|
134
+ opts.on('-r NAME', '--reporters NAME', Array, "A list of reporters to use") do |reporters|
134
135
  cmd_options['reporters'] = reporters
135
136
  end
136
137
 
@@ -205,8 +206,9 @@ envs = {}
205
206
  read_env_files = {}
206
207
  cfg['env_patterns'].each do |pattern|
207
208
  Dir.glob(pattern).each do|f|
208
- spec_env = YAML.load_file(f)
209
- name = spec_env.delete('name') || 'default'
209
+ spec_env = YAML.load_file(f) || {}
210
+
211
+ name = spec_env['name'] || 'default'
210
212
 
211
213
  if envs.key? name
212
214
  existing_env_file = read_env_files[name]
@@ -295,7 +297,7 @@ if action == 'run'
295
297
  })
296
298
 
297
299
  log_dir = File.dirname cfg['log_file']
298
- Dir.mkdir log_dir if !Dir.exists? log_dir
300
+ FileUtils.makedirs log_dir if !Dir.exists? log_dir
299
301
 
300
302
  # Load Modules
301
303
  cfg['modules']
@@ -303,12 +305,19 @@ if action == 'run'
303
305
  .select { |mod| !cfg['exclude'].include? mod }
304
306
  .each do |mod|
305
307
  begin
306
- if !File.exists? mod
307
- require_relative File.join('../lib', mod)
308
- else
308
+ spectre_lib_mod = File.join('../lib', mod)
309
+
310
+ if File.exists? mod
309
311
  require_relative mod
312
+
313
+ elsif File.exists? spectre_lib_mod
314
+ require_relative spectre_lib_mod
315
+
316
+ else
317
+ require mod
310
318
  end
311
- rescue => e
319
+
320
+ rescue LoadError => e
312
321
  puts "Unable to load module #{mod}. Check if the module exists or remove it from your spectre config:\n#{e.message}"
313
322
  exit 1
314
323
  end
@@ -337,7 +346,11 @@ if action == 'run'
337
346
  reporter.report(run_infos)
338
347
  end
339
348
 
340
- exit 0
349
+ errors = run_infos.select { |x| x.error != nil or x.failure != nil }
350
+
351
+ exit 0 if cfg['ignore_failure'] or errors.count == 0
352
+
353
+ exit 1
341
354
  end
342
355
 
343
356
 
@@ -464,6 +477,16 @@ reports/
464
477
  **/environments/*.env.secret.yml
465
478
  ]
466
479
 
480
+ DEFAULT_GEMFILE = %[source 'https://rubygems.org'
481
+
482
+ gem 'spectre-core', '>= #{Spectre::VERSION}'
483
+ # gem 'spectre-mysql', '>= 1.0.0'
484
+ # gem 'spectre-ssh', '>= 1.0.0'
485
+ # gem 'spectre-ftp', '>= 1.0.0'
486
+ # gem 'spectre-curl', '>= 1.0.0'
487
+ # gem 'spectre-git', '>= 0.1.0'
488
+ ]
489
+
467
490
  if action == 'init'
468
491
  DEFAULT_FILES = [
469
492
  ['./environments/default.env.yml', DEFAULT_ENV_CFG],
@@ -471,6 +494,7 @@ if action == 'init'
471
494
  ['./specs/sample.spec.rb', SAMPLE_SPEC],
472
495
  ['./spectre.yml', DEFAULT_SPECTRE_CFG],
473
496
  ['./.gitignore', DEFAULT_GITIGNORE],
497
+ ['./Gemfile', DEFAULT_GEMFILE],
474
498
  ]
475
499
 
476
500
  %w(environments logs specs).each do |dir_name|
data/lib/spectre.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Spectre
2
2
  module Version
3
3
  MAJOR = 1
4
- MINOR = 8
5
- TINY = 1
4
+ MINOR = 10
5
+ TINY = 0
6
6
  end
7
7
 
8
8
  VERSION = [Version::MAJOR, Version::MINOR, Version::TINY].compact * '.'
@@ -6,7 +6,7 @@ module Spectre
6
6
  module Assertion
7
7
  class ::Object
8
8
  def should_be(val)
9
- raise AssertionFailure.new("The value '#{self.to_s.trim}' should be '#{val.to_s.trim}'", val, self) unless self.to_s == val.to_s
9
+ raise AssertionFailure.new("The value '#{self.to_s.trim}' should be '#{val.to_s.trim}'", val, self) unless self.to_s == val.to_s
10
10
  end
11
11
 
12
12
  def should_be_empty
@@ -14,11 +14,11 @@ module Spectre
14
14
  end
15
15
 
16
16
  def should_not_be(val)
17
- raise AssertionFailure.new("The value '#{self.to_s.trim}' should not be '#{val.to_s.trim}'", val, self) unless self.to_s != val.to_s
17
+ raise AssertionFailure.new("The value '#{self.to_s.trim}' should not be '#{val.to_s.trim}'", val, self) unless self.to_s != val.to_s
18
18
  end
19
19
 
20
20
  def should_not_exist
21
- raise AssertionFailure.new("The value '#{self.to_s.trim}' should not exist, but it does", val, self) unless self.to_s != nil
21
+ raise AssertionFailure.new("The value '#{self.to_s.trim}' should not exist, but it does", val, self) unless self.to_s != nil
22
22
  end
23
23
 
24
24
  def should_not_be_empty
@@ -76,7 +76,7 @@ module Spectre
76
76
  val = OpenStruct.new(val)
77
77
  end
78
78
 
79
- raise AssertionFailure.new("The list [#{list.join(', ').trim}] should contain '#{val.trim}'", val, list) unless list.include? val
79
+ raise AssertionFailure.new("The list [#{list.join(', ').trim}] should contain '#{val.to_s.trim}'", val, list) unless list.include? val
80
80
  end
81
81
 
82
82
  def should_not_contain(val)
@@ -87,7 +87,7 @@ module Spectre
87
87
  val = OpenStruct.new(val)
88
88
  end
89
89
 
90
- raise AssertionFailure.new("The list [#{list.join(', ').trim}] should not contain '#{val.trim}'", val, list) if list.include? val
90
+ raise AssertionFailure.new("The list [#{list.join(', ').trim}] should not contain '#{val.to_s.trim}'", val, list) if list.include? val
91
91
  end
92
92
 
93
93
  def should_be_empty
@@ -110,7 +110,7 @@ module Spectre
110
110
  end
111
111
 
112
112
  def should_not_be(val)
113
- raise AssertionFailure.new("The text '#{self.trim}' should not be '#{val.to_s.trim}'", val, self) unless self != val
113
+ raise AssertionFailure.new("The text '#{self.trim}' should not be '#{val.to_s.trim}'", val, self) unless self != val
114
114
  end
115
115
 
116
116
  def should_not_be_empty
@@ -118,8 +118,10 @@ module Spectre
118
118
  end
119
119
 
120
120
  def should_contain(value)
121
+ raise AssertionFailure.new("`value' must not be nil") if value.nil?
122
+
121
123
  predicate = proc { |x| self.include? x.to_s }
122
- evaluation = SingleEvaluation.new value
124
+ evaluation = SingleEvaluation.new(value)
123
125
  success = evaluation.call(predicate)
124
126
 
125
127
  return if success
@@ -165,7 +167,7 @@ module Spectre
165
167
 
166
168
  class SingleEvaluation < Evaluation
167
169
  def initialize value
168
- super value, nil
170
+ super(value, nil)
169
171
  end
170
172
 
171
173
  def call predicate
@@ -180,7 +182,7 @@ module Spectre
180
182
 
181
183
  class OrEvaluation < Evaluation
182
184
  def initialize value, other
183
- super value, other
185
+ super(value, other)
184
186
  end
185
187
 
186
188
  def call predicate
@@ -195,7 +197,7 @@ module Spectre
195
197
 
196
198
  class AndEvaluation < Evaluation
197
199
  def initialize value, other
198
- super value, other
200
+ super(value, other)
199
201
  end
200
202
 
201
203
  def call predicate
@@ -222,14 +224,6 @@ module Spectre
222
224
  class << self
223
225
  @@success = nil
224
226
 
225
- def eval_assertion predicate, val
226
- if val.is_a? Proc
227
- val.call(predicate)
228
- else
229
- predicate.call(val)
230
- end
231
- end
232
-
233
227
  def expect desc
234
228
  begin
235
229
  Logger.log_process("expect #{desc}")
@@ -2,6 +2,7 @@ require 'securerandom'
2
2
  require 'json'
3
3
  require 'date'
4
4
  require 'ostruct'
5
+ require 'jsonpath'
5
6
 
6
7
  class ::String
7
8
  def as_json
@@ -17,12 +18,22 @@ class ::String
17
18
  file_content = File.read(self)
18
19
 
19
20
  if with
20
- with.each do |key, value|
21
- file_content = file_content.gsub '#{' + key.to_s + '}', value.to_s
22
- end
21
+ file_content.with(with)
22
+ else
23
+ file_content
23
24
  end
25
+ end
26
+
27
+ def with mapping
28
+ return self unless mapping and mapping.is_a? Hash
24
29
 
25
- file_content
30
+ new_string = self
31
+
32
+ mapping.each do |key, value|
33
+ new_string = new_string.gsub '#{' + key.to_s + '}', value.to_s
34
+ end
35
+
36
+ new_string
26
37
  end
27
38
 
28
39
  def exists?
@@ -35,13 +46,24 @@ class ::String
35
46
  File.delete self
36
47
  end
37
48
 
38
- def trim count=50
49
+ def trim count = 50
39
50
  if (self.length + 3) > count
40
- return self[0..count] + '...'
51
+ return self[0..count-4] + '...'
41
52
  end
42
53
 
43
54
  self
44
55
  end
56
+
57
+ def pick path
58
+ raise ArgumentError.new("`path' must not be nil or empty") if path.nil? or path.empty?
59
+
60
+ begin
61
+ JsonPath.on(self, path)
62
+
63
+ rescue MultiJson::ParseError
64
+ # do nothing and return nil
65
+ end
66
+ end
45
67
  end
46
68
 
47
69
 
@@ -49,6 +71,12 @@ class ::OpenStruct
49
71
  def to_json *args, **kwargs
50
72
  self.to_h.inject({}) { |memo, (k,v)| memo[k] = v.is_a?(OpenStruct) ? v.to_h : v; memo }.to_json(*args, **kwargs)
51
73
  end
74
+
75
+ def pick path
76
+ raise ArgumentError.new("`path' must not be nil or empty") if path.nil? or path.empty?
77
+
78
+ JsonPath.on(self, path)
79
+ end
52
80
  end
53
81
 
54
82
 
@@ -60,5 +88,5 @@ end
60
88
 
61
89
 
62
90
  def uuid length = 5
63
- SecureRandom.uuid().gsub('-', '')[0..length]
91
+ SecureRandom.uuid().gsub('-', '')[0..length-1]
64
92
  end
data/lib/spectre/http.rb CHANGED
@@ -62,8 +62,7 @@ module Spectre
62
62
  end
63
63
 
64
64
  def body body_content
65
- raise 'Body value must be a string' if not body_content.is_a? String
66
- @__req['body'] = body_content
65
+ @__req['body'] = body_content.to_s
67
66
  end
68
67
 
69
68
  def ensure_success!
@@ -102,6 +101,7 @@ module Spectre
102
101
  end
103
102
 
104
103
  def [] key
104
+ return nil if not @headers.has_key?(key.downcase)
105
105
  @headers[key.downcase].first
106
106
  end
107
107
 
@@ -166,6 +166,7 @@ module Spectre
166
166
  @@response = nil
167
167
  @@request = nil
168
168
  @@modules = []
169
+ @@secure_keys = []
169
170
 
170
171
  def https name, &block
171
172
  http(name, secure: true, &block)
@@ -209,7 +210,8 @@ module Spectre
209
210
  return str unless str or str.empty?
210
211
 
211
212
  begin
212
- json = JSON.parse str
213
+ json = JSON.parse(str)
214
+ json.obfuscate!(@@secure_keys) if not @@debug
213
215
 
214
216
  if pretty
215
217
  str = JSON.pretty_generate(json)
@@ -223,6 +225,19 @@ module Spectre
223
225
  str
224
226
  end
225
227
 
228
+ def is_secure? key
229
+ @@secure_keys.any? { |x| key.to_s.downcase.include? x.downcase }
230
+ end
231
+
232
+ def header_to_s headers
233
+ s = ''
234
+ headers.each_header.each do |header, value|
235
+ value = '*****' if is_secure?(header) and not @@debug
236
+ s += "#{header.to_s.ljust(30, '.')}: #{value.to_s}\n"
237
+ end
238
+ s
239
+ end
240
+
226
241
  def invoke req
227
242
  @@request = nil
228
243
 
@@ -275,28 +290,28 @@ module Spectre
275
290
 
276
291
  req_id = SecureRandom.uuid()[0..5]
277
292
 
293
+ # Run HTTP modules
294
+
295
+ @@modules.each do |mod|
296
+ mod.on_req(net_http, net_req, req) if mod.respond_to? :on_req
297
+ end
298
+
278
299
  # Log request
279
300
 
280
- req_log = "[>] #{req_id} #{req['method']} #{uri}"
281
- req['headers'].each do |header|
282
- req_log += "\n#{header[0].to_s.ljust(30, '.')}: #{header[1].to_s}"
283
- end if req['headers']
284
- req_log += "\n" + try_format_json(req['body'], pretty: true) if req['body'] != nil and not req['body'].empty?
301
+ req_log = "[>] #{req_id} #{req['method']} #{uri}\n"
302
+ req_log += header_to_s(net_req)
303
+ req_log += try_format_json(req['body'], pretty: true) if req['body'] != nil and not req['body'].empty?
285
304
 
286
305
  @@logger.info req_log
287
306
 
288
307
  # Request
289
308
 
290
309
  start_time = Time.now
291
-
292
- @@modules.each do |mod|
293
- mod.on_req(net_http, net_req, req) if mod.respond_to? :on_req
294
- end
295
-
296
310
  net_res = net_http.request(net_req)
297
-
298
311
  end_time = Time.now
299
312
 
313
+ # Run HTTP modules
314
+
300
315
  @@modules.each do |mod|
301
316
  mod.on_res(net_http, net_res, req) if mod.respond_to? :on_res
302
317
  end
@@ -304,9 +319,7 @@ module Spectre
304
319
  # Log response
305
320
 
306
321
  res_log = "[<] #{req_id} #{net_res.code} #{net_res.message} (#{end_time - start_time}s)\n"
307
- net_res.each_header do |header, value|
308
- res_log += "#{header.to_s.ljust(30, '.')}: #{value}\n"
309
- end
322
+ res_log += header_to_s(net_res)
310
323
  res_log += try_format_json(net_res.body, pretty: true) if net_res.body != nil and !net_res.body.empty?
311
324
 
312
325
  @@logger.info(res_log)
@@ -328,6 +341,8 @@ module Spectre
328
341
 
329
342
  Spectre.register do |config|
330
343
  @@logger = ::Logger.new config['log_file'], progname: 'spectre/http'
344
+ @@secure_keys = config['secure_keys'] || []
345
+ @@debug = config['debug']
331
346
 
332
347
  if config.key? 'http'
333
348
  @@http_cfg = {}
@@ -97,6 +97,7 @@ module Spectre::Reporter
97
97
  str += " line.....: #{line}\n"
98
98
  str += " type.....: #{error.class}\n"
99
99
  str += " message..: #{error.message}\n"
100
+ str += " backtrace: \n #{error.backtrace.join("\n ")}\n" if @config['debug']
100
101
  str
101
102
  end
102
103
  end
metadata CHANGED
@@ -1,85 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spectre-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.1
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Neubauer
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-05-18 00:00:00.000000000 Z
11
+ date: 2021-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ectoplasm
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.1.0
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: 1.1.0
27
- - !ruby/object:Gem::Dependency
28
- name: openssl
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: 2.2.0
19
+ version: 1.2.0
34
20
  type: :runtime
35
21
  prerelease: false
36
22
  version_requirements: !ruby/object:Gem::Requirement
37
23
  requirements:
38
- - - "~>"
24
+ - - ">="
39
25
  - !ruby/object:Gem::Version
40
- version: 2.2.0
26
+ version: 1.2.0
41
27
  - !ruby/object:Gem::Dependency
42
- name: net-ssh
28
+ name: jsonpath
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: 6.1.0
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
31
+ - - ">="
53
32
  - !ruby/object:Gem::Version
54
- version: 6.1.0
55
- - !ruby/object:Gem::Dependency
56
- name: net-sftp
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 3.0.0
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 3.0.0
69
- - !ruby/object:Gem::Dependency
70
- name: mysql2
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: 0.5.3
33
+ version: 1.1.0
76
34
  type: :runtime
77
35
  prerelease: false
78
36
  version_requirements: !ruby/object:Gem::Requirement
79
37
  requirements:
80
- - - "~>"
38
+ - - ">="
81
39
  - !ruby/object:Gem::Version
82
- version: 0.5.3
40
+ version: 1.1.0
83
41
  description: A DSL and command line tool to describe and run automated tests
84
42
  email:
85
43
  - me@christianneubauer.de
@@ -93,10 +51,8 @@ files:
93
51
  - lib/spectre/assertion.rb
94
52
  - lib/spectre/bag.rb
95
53
  - lib/spectre/curl.rb
96
- - lib/spectre/database/postgres.rb
97
54
  - lib/spectre/diagnostic.rb
98
55
  - lib/spectre/environment.rb
99
- - lib/spectre/ftp.rb
100
56
  - lib/spectre/helpers.rb
101
57
  - lib/spectre/http.rb
102
58
  - lib/spectre/http/basic_auth.rb
@@ -105,20 +61,18 @@ files:
105
61
  - lib/spectre/logger/console.rb
106
62
  - lib/spectre/logger/file.rb
107
63
  - lib/spectre/mixin.rb
108
- - lib/spectre/mysql.rb
109
64
  - lib/spectre/reporter/console.rb
110
65
  - lib/spectre/reporter/junit.rb
111
66
  - lib/spectre/resources.rb
112
- - lib/spectre/ssh.rb
113
- homepage: https://bitbucket.org/cneubaur/spectre-core
67
+ homepage: https://github.com/cneubauer/spectre-core
114
68
  licenses:
115
69
  - MIT
116
70
  metadata:
117
71
  allowed_push_host: https://rubygems.org/
118
- homepage_uri: https://bitbucket.org/cneubaur/spectre-core
119
- source_code_uri: https://bitbucket.org/cneubaur/spectre-core
120
- changelog_uri: https://bitbucket.org/cneubaur/spectre-core/src/master/CHANGELOG.md
121
- post_install_message:
72
+ homepage_uri: https://github.com/cneubauer/spectre-core
73
+ source_code_uri: https://github.com/cneubauer/spectre-core
74
+ changelog_uri: https://github.com/cneubauer/spectre-core/blob/master/CHANGELOG.md
75
+ post_install_message:
122
76
  rdoc_options: []
123
77
  require_paths:
124
78
  - lib
@@ -133,8 +87,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
87
  - !ruby/object:Gem::Version
134
88
  version: '0'
135
89
  requirements: []
136
- rubygems_version: 3.2.3
137
- signing_key:
90
+ rubygems_version: 3.0.8
91
+ signing_key:
138
92
  specification_version: 4
139
93
  summary: Describe and run automated tests
140
94
  test_files: []
@@ -1,78 +0,0 @@
1
- require 'pg'
2
-
3
-
4
- class PG::Result
5
- alias :count :ntuples
6
- end
7
-
8
-
9
- module Spectre
10
- module Database
11
- module Postgres
12
- @@modules = []
13
-
14
- class SQLStatement
15
- attr_accessor :query, :params
16
-
17
- def initialize
18
- @query = nil
19
- @params = []
20
- end
21
-
22
- def statement query
23
- @query = query
24
- end
25
-
26
- def param val
27
- @params << val
28
- end
29
- end
30
-
31
-
32
- class << self
33
- def postgres name, &block
34
- raise "postgres '#{name}' not configured" unless @@db_cfg.key? name
35
-
36
- statement = SQLStatement.new
37
- statement.instance_eval &block
38
-
39
- cfg = @@db_cfg[name]
40
-
41
- begin
42
- con = PG.connect({
43
- host: cfg['host'],
44
- port: cfg['port'],
45
- dbname: cfg['database'],
46
- user: cfg['username'],
47
- password: cfg['username'],
48
- })
49
-
50
- if statement.params
51
- @@result = con.exec_params(statement.query, statement.params)
52
- else
53
- @@result = con.exec(statement.query)
54
- end
55
-
56
- ensure
57
- con.close if con
58
- end
59
- end
60
-
61
-
62
- def result
63
- @@result
64
- end
65
- end
66
-
67
- Spectre.register do |config|
68
- @@db_cfg = {}
69
-
70
- config['postgres'].each do |name, cfg|
71
- @@db_cfg[name] = cfg
72
- end
73
- end
74
-
75
- Spectre.delegate :postgres, :result, to: self
76
- end
77
- end
78
- end
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