spectre-core 1.10.0 → 1.12.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/exe/spectre +51 -46
- data/lib/spectre/assertion.rb +39 -20
- data/lib/spectre/bag.rb +4 -2
- data/lib/spectre/curl.rb +62 -33
- data/lib/spectre/diagnostic.rb +12 -2
- data/lib/spectre/environment.rb +9 -5
- data/lib/spectre/helpers.rb +68 -27
- data/lib/spectre/http/basic_auth.rb +5 -2
- data/lib/spectre/http/keystone.rb +76 -73
- data/lib/spectre/http.rb +379 -358
- data/lib/spectre/logger/console.rb +7 -6
- data/lib/spectre/logger/file.rb +96 -96
- data/lib/spectre/logger.rb +146 -144
- data/lib/spectre/mixin.rb +35 -18
- data/lib/spectre/reporter/console.rb +2 -5
- data/lib/spectre/reporter/junit.rb +5 -3
- data/lib/spectre/resources.rb +7 -4
- data/lib/spectre.rb +58 -45
- metadata +12 -12
data/lib/spectre/environment.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
require_relative '../spectre'
|
2
|
+
|
1
3
|
require 'ostruct'
|
2
4
|
|
3
5
|
def to_recursive_ostruct(hash)
|
4
|
-
OpenStruct.new(
|
5
|
-
|
6
|
-
|
6
|
+
OpenStruct.new(
|
7
|
+
hash.each_with_object({}) do |(key, val), memo|
|
8
|
+
memo[key] = val.is_a?(Hash) ? to_recursive_ostruct(val) : val
|
9
|
+
end
|
10
|
+
)
|
7
11
|
end
|
8
12
|
|
9
13
|
module Spectre
|
@@ -21,6 +25,6 @@ module Spectre
|
|
21
25
|
@@environment.freeze
|
22
26
|
end
|
23
27
|
|
24
|
-
Spectre.delegate :env, to:
|
28
|
+
Spectre.delegate :env, to: self
|
25
29
|
end
|
26
|
-
end
|
30
|
+
end
|
data/lib/spectre/helpers.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative '../spectre'
|
2
|
+
|
1
3
|
require 'securerandom'
|
2
4
|
require 'json'
|
3
5
|
require 'date'
|
@@ -13,15 +15,8 @@ class ::String
|
|
13
15
|
DateTime.parse(self)
|
14
16
|
end
|
15
17
|
|
16
|
-
def
|
17
|
-
|
18
|
-
file_content = File.read(self)
|
19
|
-
|
20
|
-
if with
|
21
|
-
file_content.with(with)
|
22
|
-
else
|
23
|
-
file_content
|
24
|
-
end
|
18
|
+
def as_timestamp
|
19
|
+
DateTime.parse(self).to_time.to_i
|
25
20
|
end
|
26
21
|
|
27
22
|
def with mapping
|
@@ -30,25 +25,15 @@ class ::String
|
|
30
25
|
new_string = self
|
31
26
|
|
32
27
|
mapping.each do |key, value|
|
33
|
-
new_string = new_string.gsub
|
28
|
+
new_string = new_string.gsub('#{' + key.to_s + '}', value.to_s)
|
34
29
|
end
|
35
30
|
|
36
31
|
new_string
|
37
32
|
end
|
38
33
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def remove!
|
44
|
-
fail "'#{self}' is not a file path, or the file does not exist." if !File.exists? self
|
45
|
-
|
46
|
-
File.delete self
|
47
|
-
end
|
48
|
-
|
49
|
-
def trim count = 50
|
50
|
-
if (self.length + 3) > count
|
51
|
-
return self[0..count-4] + '...'
|
34
|
+
def trim size = 50
|
35
|
+
if (self.length + 3) > size
|
36
|
+
return self[0..size-4] + '...'
|
52
37
|
end
|
53
38
|
|
54
39
|
self
|
@@ -59,13 +44,41 @@ class ::String
|
|
59
44
|
|
60
45
|
begin
|
61
46
|
JsonPath.on(self, path)
|
62
|
-
|
63
47
|
rescue MultiJson::ParseError
|
64
48
|
# do nothing and return nil
|
65
49
|
end
|
66
50
|
end
|
67
|
-
end
|
68
51
|
|
52
|
+
# File helpers
|
53
|
+
|
54
|
+
def content with: nil
|
55
|
+
fail "'#{self}' is not a file path, or the file does not exist." unless File.exists? self
|
56
|
+
|
57
|
+
file_content = File.read(self)
|
58
|
+
|
59
|
+
if with
|
60
|
+
file_content.with(with)
|
61
|
+
else
|
62
|
+
file_content
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def file_size
|
67
|
+
fail "'#{self}' is not a file path, or the file does not exist." unless File.exists? self
|
68
|
+
|
69
|
+
File.size(self)
|
70
|
+
end
|
71
|
+
|
72
|
+
def exists?
|
73
|
+
File.exists? self
|
74
|
+
end
|
75
|
+
|
76
|
+
def remove!
|
77
|
+
fail "'#{self}' is not a file path, or the file does not exist." unless File.exists? self
|
78
|
+
|
79
|
+
File.delete self
|
80
|
+
end
|
81
|
+
end
|
69
82
|
|
70
83
|
class ::OpenStruct
|
71
84
|
def to_json *args, **kwargs
|
@@ -77,16 +90,44 @@ class ::OpenStruct
|
|
77
90
|
|
78
91
|
JsonPath.on(self, path)
|
79
92
|
end
|
80
|
-
end
|
81
93
|
|
94
|
+
def default_to! defaults
|
95
|
+
defaults.each_key do |key|
|
96
|
+
unless self[key] != nil
|
97
|
+
self[key] = defaults[key]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
alias :defaults_to! :default_to!
|
103
|
+
end
|
82
104
|
|
83
105
|
class ::Hash
|
84
106
|
def symbolize_keys
|
85
107
|
self.inject({}) { |memo, (k,v)| memo[k.to_sym] = v; memo }
|
86
108
|
end
|
109
|
+
|
110
|
+
def default_to! defaults
|
111
|
+
defaults.each_key do |key|
|
112
|
+
unless self[key] != nil
|
113
|
+
self[key] = defaults[key]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
alias :defaults_to! :default_to!
|
87
119
|
end
|
88
120
|
|
121
|
+
class ::Array
|
122
|
+
def last_element
|
123
|
+
self[-1]
|
124
|
+
end
|
125
|
+
end
|
89
126
|
|
90
127
|
def uuid length = 5
|
91
128
|
SecureRandom.uuid().gsub('-', '')[0..length-1]
|
92
|
-
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def now
|
132
|
+
Time.now
|
133
|
+
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
require_relative '../http'
|
2
|
+
|
1
3
|
module Spectre::Http
|
2
4
|
class SpectreHttpRequest
|
3
5
|
def basic_auth username, password
|
4
|
-
@__req['basic_auth'] = {}
|
6
|
+
@__req['basic_auth'] = {} unless @__req.key? 'basic_auth'
|
5
7
|
|
6
8
|
@__req['basic_auth']['username'] = username
|
7
9
|
@__req['basic_auth']['password'] = password
|
@@ -11,8 +13,9 @@ module Spectre::Http
|
|
11
13
|
end
|
12
14
|
|
13
15
|
module BasicAuth
|
14
|
-
def self.on_req
|
16
|
+
def self.on_req _http, net_req, req
|
15
17
|
return unless req.key? 'basic_auth' and req['auth'] == 'basic_auth'
|
18
|
+
|
16
19
|
basic_auth_cfg = req['basic_auth']
|
17
20
|
net_req.basic_auth(basic_auth_cfg['username'], basic_auth_cfg['password'])
|
18
21
|
end
|
@@ -1,98 +1,101 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
require_relative '../http'
|
2
|
+
|
3
|
+
module Spectre::Http
|
4
|
+
class SpectreHttpRequest
|
5
|
+
def keystone url, username, password, project, domain, cert=nil
|
6
|
+
@__req['keystone'] = {} unless @__req.key? 'keystone'
|
7
|
+
|
8
|
+
@__req['keystone']['url'] = url
|
9
|
+
@__req['keystone']['username'] = username
|
10
|
+
@__req['keystone']['password'] = password
|
11
|
+
@__req['keystone']['project'] = project
|
12
|
+
@__req['keystone']['domain'] = domain
|
13
|
+
@__req['keystone']['cert'] = cert
|
14
|
+
|
15
|
+
@__req['auth'] = 'keystone'
|
16
|
+
end
|
13
17
|
end
|
14
|
-
end
|
15
18
|
|
19
|
+
module Keystone
|
20
|
+
@@cache = {}
|
16
21
|
|
17
|
-
|
18
|
-
|
22
|
+
def self.on_req _http, net_req, req
|
23
|
+
return unless req.key? 'keystone' and req['auth'] == 'keystone'
|
19
24
|
|
20
|
-
|
21
|
-
return unless req.key? 'keystone' and req['auth'] == 'keystone'
|
25
|
+
keystone_cfg = req['keystone']
|
22
26
|
|
23
|
-
|
27
|
+
if @@cache.key? keystone_cfg
|
28
|
+
token = @@cache[keystone_cfg]
|
29
|
+
else
|
30
|
+
token, _ = authenticate(
|
31
|
+
keystone_cfg['url'],
|
32
|
+
keystone_cfg['username'],
|
33
|
+
keystone_cfg['password'],
|
34
|
+
keystone_cfg['project'],
|
35
|
+
keystone_cfg['domain'],
|
36
|
+
keystone_cfg['cert'],
|
37
|
+
)
|
24
38
|
|
25
|
-
|
26
|
-
|
27
|
-
else
|
28
|
-
token, _ = authenticate(
|
29
|
-
keystone_cfg['url'],
|
30
|
-
keystone_cfg['username'],
|
31
|
-
keystone_cfg['password'],
|
32
|
-
keystone_cfg['project'],
|
33
|
-
keystone_cfg['domain'],
|
34
|
-
keystone_cfg['cert'],
|
35
|
-
)
|
39
|
+
@@cache[keystone_cfg] = token
|
40
|
+
end
|
36
41
|
|
37
|
-
|
42
|
+
net_req['X-Auth-Token'] = token
|
38
43
|
end
|
39
44
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
domain: {
|
55
|
-
name: domain,
|
45
|
+
private
|
46
|
+
|
47
|
+
def self.authenticate keystone_url, username, password, project, domain, cert
|
48
|
+
auth_data = {
|
49
|
+
auth: {
|
50
|
+
identity: {
|
51
|
+
methods: ['password'],
|
52
|
+
password: {
|
53
|
+
user: {
|
54
|
+
name: username,
|
55
|
+
password: password,
|
56
|
+
domain: {
|
57
|
+
name: domain,
|
58
|
+
},
|
56
59
|
},
|
57
60
|
},
|
58
61
|
},
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
scope: {
|
63
|
+
project: {
|
64
|
+
name: project,
|
65
|
+
domain: {
|
66
|
+
name: domain,
|
67
|
+
},
|
65
68
|
},
|
66
69
|
},
|
67
70
|
},
|
68
|
-
}
|
69
|
-
}
|
71
|
+
}
|
70
72
|
|
71
|
-
|
73
|
+
keystone_url = keystone_url + '/' unless keystone_url.end_with? '/'
|
72
74
|
|
73
|
-
|
74
|
-
|
75
|
+
base_uri = URI(keystone_url)
|
76
|
+
uri = URI.join(base_uri, 'auth/tokens?nocatalog=true')
|
75
77
|
|
76
|
-
|
78
|
+
http = Net::HTTP.new(base_uri.host, base_uri.port)
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
80
|
+
if cert
|
81
|
+
http.use_ssl = true
|
82
|
+
http.ca_file = cert
|
83
|
+
end
|
82
84
|
|
83
|
-
|
84
|
-
|
85
|
-
|
85
|
+
req = Net::HTTP::Post.new(uri)
|
86
|
+
req.body = JSON.pretty_generate(auth_data)
|
87
|
+
req.content_type = 'application/json'
|
86
88
|
|
87
|
-
|
89
|
+
res = http.request(req)
|
88
90
|
|
89
|
-
|
91
|
+
raise "error while authenticating: #{res.code} #{res.message}\n#{res.body}" if res.code != '201'
|
90
92
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
93
|
+
[
|
94
|
+
res['X-Subject-Token'],
|
95
|
+
JSON.parse(res.body),
|
96
|
+
]
|
97
|
+
end
|
96
98
|
|
97
|
-
|
99
|
+
Spectre::Http.register(self)
|
100
|
+
end
|
98
101
|
end
|