kashi 0.1.0.beta1
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 +7 -0
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +117 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/kashi +4 -0
- data/kashi.gemspec +31 -0
- data/lib/kashi/cli.rb +70 -0
- data/lib/kashi/client.rb +229 -0
- data/lib/kashi/client_wrapper.rb +17 -0
- data/lib/kashi/converter.rb +21 -0
- data/lib/kashi/dsl/cake.rb +49 -0
- data/lib/kashi/dsl/contact_group.rb +125 -0
- data/lib/kashi/dsl/test.rb +275 -0
- data/lib/kashi/dsl.rb +54 -0
- data/lib/kashi/ext/string-ext.rb +9 -0
- data/lib/kashi/output_test.erb +89 -0
- data/lib/kashi/utils.rb +52 -0
- data/lib/kashi/version.rb +3 -0
- data/lib/kashi.rb +15 -0
- metadata +163 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'kashi/utils'
|
2
|
+
require 'kashi/client_wrapper'
|
3
|
+
|
4
|
+
module Kashi
|
5
|
+
class DSL
|
6
|
+
class ContactGroup
|
7
|
+
attr_reader :result
|
8
|
+
|
9
|
+
class Result
|
10
|
+
PARAMS = %i/ContactID GroupName DesktopAlert Email Boxcar Pushover PingURL Mobile/
|
11
|
+
ATTRIBUTES = %i/contact_id group_name desktop_alert email boxcar pushover ping_url mobile/
|
12
|
+
attr_accessor *ATTRIBUTES
|
13
|
+
|
14
|
+
def initialize(context)
|
15
|
+
@context = context
|
16
|
+
@options = context.options
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
Hash[ATTRIBUTES.sort.map { |name| [name, public_send(name)] }]
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_params
|
24
|
+
hash = modify_params
|
25
|
+
hash.delete(:ContactID)
|
26
|
+
hash
|
27
|
+
end
|
28
|
+
|
29
|
+
def modify_params
|
30
|
+
hash = to_h.select { |k, _| ATTRIBUTES.include?(k) }
|
31
|
+
ATTRIBUTES.zip(PARAMS).each do |from, to|
|
32
|
+
hash[to] = hash.delete(from)
|
33
|
+
end
|
34
|
+
hash[:Email] = Array(hash[:Email]).join(',')
|
35
|
+
hash
|
36
|
+
end
|
37
|
+
|
38
|
+
def create
|
39
|
+
Kashi.logger.info("Create ContactGroup `#{group_name}`")
|
40
|
+
Kashi.logger.debug(create_params)
|
41
|
+
return { 'Success' => true } if @options[:dry_run]
|
42
|
+
|
43
|
+
client.contactgroups_update(create_params)
|
44
|
+
end
|
45
|
+
|
46
|
+
def cake(sc_contact_group)
|
47
|
+
@sc_contact_group = sc_contact_group
|
48
|
+
self.contact_id = sc_contact_group['ContactID']
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
def dsl_hash
|
53
|
+
Kashi::Utils.normalize_hash(to_h)
|
54
|
+
end
|
55
|
+
|
56
|
+
def sc_hash
|
57
|
+
hash = @sc_contact_group.to_h.keys.each_with_object({}) do |k, h|
|
58
|
+
h[k.to_s.to_snake.to_sym] = @sc_contact_group.to_h[k]
|
59
|
+
end
|
60
|
+
{ emails: :email, mobiles: :mobile }.each do |k, v|
|
61
|
+
hash[v] = hash.delete(k)
|
62
|
+
end
|
63
|
+
Kashi::Utils.normalize_hash(hash)
|
64
|
+
end
|
65
|
+
|
66
|
+
def updated?
|
67
|
+
dsl_hash != sc_hash
|
68
|
+
end
|
69
|
+
|
70
|
+
def modify
|
71
|
+
return unless updated?
|
72
|
+
Kashi.logger.info("Modify ContactGroup `#{group_name}` #{contact_id}")
|
73
|
+
Kashi.logger.info("<diff>\n#{Kashi::Utils.diff(sc_hash, dsl_hash, color: @options[:color])}")
|
74
|
+
Kashi.logger.debug(modify_params)
|
75
|
+
return if @options[:dry_run]
|
76
|
+
|
77
|
+
client.contactgroups_update(modify_params)
|
78
|
+
end
|
79
|
+
|
80
|
+
def client
|
81
|
+
@client ||= ClientWrapper.new(@options)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def initialize(context, contact_id, &block)
|
86
|
+
@context = context.merge(contact_id: contact_id)
|
87
|
+
|
88
|
+
@result = Result.new(@context)
|
89
|
+
@result.contact_id = contact_id
|
90
|
+
|
91
|
+
instance_eval(&block)
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def group_name(name)
|
97
|
+
@result.group_name = name
|
98
|
+
end
|
99
|
+
|
100
|
+
def desktop_alert(alert)
|
101
|
+
@result.desktop_alert = alert
|
102
|
+
end
|
103
|
+
|
104
|
+
def email(email)
|
105
|
+
@result.email = Array(email)
|
106
|
+
end
|
107
|
+
|
108
|
+
def boxcar(boxcar)
|
109
|
+
@result.boxcar = boxcar
|
110
|
+
end
|
111
|
+
|
112
|
+
def pushover(pushover)
|
113
|
+
@result.pushover = pushover
|
114
|
+
end
|
115
|
+
|
116
|
+
def ping_url(url)
|
117
|
+
@result.ping_url = url
|
118
|
+
end
|
119
|
+
|
120
|
+
def mobile(mobile)
|
121
|
+
@result.mobile = mobile
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,275 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Kashi
|
4
|
+
class DSL
|
5
|
+
class Test
|
6
|
+
class Result
|
7
|
+
PARAMS = %i/
|
8
|
+
TestID Paused WebsiteName WebsiteURL Port NodeLocations Timeout CustomHeader Confirmation CheckRate
|
9
|
+
DNSServer DNSIP BasicUser BasicPass LogoImage UseJar WebsiteHost Virus FindString DoNotFind
|
10
|
+
TestType ContactGroup TriggerRate TestTags StatusCodes EnableSSLWarning FollowRedirect
|
11
|
+
/ # PingURL RealBrowser Public Branding
|
12
|
+
ATTRIBUTES = %i/
|
13
|
+
test_id paused website_name website_url port node_locations timeout custom_header confirmation check_rate
|
14
|
+
dns_server dns_ip basic_user basic_pass logo_image use_jar website_host virus find_string do_not_find
|
15
|
+
test_type contact_group trigger_rate test_tags status_codes enable_ssl_warning follow_redirect
|
16
|
+
/ # ping_url real_browser public branding
|
17
|
+
attr_accessor *ATTRIBUTES
|
18
|
+
|
19
|
+
def initialize(context)
|
20
|
+
@context = context
|
21
|
+
@options = context.options
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_h
|
25
|
+
Hash[ATTRIBUTES.sort.map { |name| [name, public_send(name)] }]
|
26
|
+
end
|
27
|
+
|
28
|
+
def modify_params
|
29
|
+
hash = to_h.select { |k, _| ATTRIBUTES.include?(k) }
|
30
|
+
ATTRIBUTES.zip(PARAMS).each do |from, to|
|
31
|
+
hash[to] = hash.delete(from)
|
32
|
+
end
|
33
|
+
%i/NodeLocations TestTags StatusCodes/.each do |k|
|
34
|
+
hash[k] = Array(hash[k]).join(',')
|
35
|
+
end
|
36
|
+
contact_group_id_by_group_name = client.contactgroups.each_with_object({}) do |contact_group, h|
|
37
|
+
h[contact_group['GroupName']] = contact_group['ContactID']
|
38
|
+
end
|
39
|
+
hash[:ContactGroup] = contact_group.map { |name|
|
40
|
+
contact_group_id_by_group_name[name]
|
41
|
+
}.compact.join(',')
|
42
|
+
hash
|
43
|
+
end
|
44
|
+
|
45
|
+
def create_params
|
46
|
+
hash = modify_params
|
47
|
+
hash.delete(:TestID)
|
48
|
+
hash
|
49
|
+
end
|
50
|
+
|
51
|
+
def create
|
52
|
+
Kashi.logger.info("Create Test `#{website_name}`")
|
53
|
+
Kashi.logger.debug(create_params)
|
54
|
+
return { 'Success' => true } if @options[:dry_run]
|
55
|
+
|
56
|
+
client.tests_update(create_params)
|
57
|
+
end
|
58
|
+
|
59
|
+
def cake(sc_test)
|
60
|
+
@sc_test = sc_test
|
61
|
+
self.test_id = sc_test['TestID']
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def dsl_hash
|
66
|
+
Kashi::Utils.normalize_hash(to_h)
|
67
|
+
end
|
68
|
+
|
69
|
+
def sc_hash
|
70
|
+
hash = @sc_test.to_h.keys.each_with_object({}) do |k, h|
|
71
|
+
next if %w/DownTimes LastTested NextLocation Processing ProcessingOn ProcessingState Sensitive Status Uptime Method ContactGroup ContactID/.include?(k)
|
72
|
+
h[k.to_s.to_snake.to_sym] = @sc_test.to_h[k]
|
73
|
+
end
|
74
|
+
# rename
|
75
|
+
{ uri: :website_url, dnsip: :dns_ip, tags: :test_tags }.each do |k, v|
|
76
|
+
hash[v] = hash.delete(k)
|
77
|
+
end
|
78
|
+
%i/basic_user basic_pass/.each do |k|
|
79
|
+
hash[k] = ''
|
80
|
+
end
|
81
|
+
%i/port use_jar virus/.each do |k|
|
82
|
+
hash[k] = '' unless hash.key?(k)
|
83
|
+
end
|
84
|
+
%i/paused enable_ssl_warning follow_redirect do_not_find/.each do |k|
|
85
|
+
hash[k] = hash[k] ? 1 : 0
|
86
|
+
end
|
87
|
+
hash[:contact_group] = hash.delete(:contact_groups).map { |contact_group| contact_group['Name'] }
|
88
|
+
hash[:test_tags] = Array(hash[:test_tags])
|
89
|
+
if hash[:custom_header] == false || hash[:custom_header] == ''
|
90
|
+
hash[:custom_header] = ''
|
91
|
+
else
|
92
|
+
hash[:custom_header] = JSON.parse(hash[:custom_header]).to_json
|
93
|
+
end
|
94
|
+
Kashi::Utils.normalize_hash(hash)
|
95
|
+
end
|
96
|
+
|
97
|
+
def updated?
|
98
|
+
dsl_hash != sc_hash
|
99
|
+
end
|
100
|
+
|
101
|
+
def modify
|
102
|
+
return unless updated?
|
103
|
+
Kashi.logger.info("Modify Test `#{website_name}` #{test_id}")
|
104
|
+
Kashi.logger.info("<diff>\n#{Kashi::Utils.diff(sc_hash, dsl_hash, color: @options[:color])}")
|
105
|
+
Kashi.logger.debug(modify_params)
|
106
|
+
return if @options[:dry_run]
|
107
|
+
|
108
|
+
client.tests_update(modify_params)
|
109
|
+
end
|
110
|
+
|
111
|
+
def client
|
112
|
+
@client ||= ClientWrapper.new(@options)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
attr_reader :result
|
117
|
+
|
118
|
+
def initialize(context, test_id, &block)
|
119
|
+
@context = context.merge(test_id: test_id)
|
120
|
+
|
121
|
+
@result = Result.new(@context)
|
122
|
+
@result.test_id = test_id
|
123
|
+
|
124
|
+
# default values
|
125
|
+
@result.paused = 0
|
126
|
+
@result.timeout = 30
|
127
|
+
@result.confirmation = 0
|
128
|
+
@result.check_rate = 300
|
129
|
+
# @result.public = 0
|
130
|
+
# @result.use_jar = 0
|
131
|
+
# @result.branding = 0
|
132
|
+
@result.do_not_find = 0
|
133
|
+
# @result.real_browser = 0
|
134
|
+
@result.trigger_rate = 5
|
135
|
+
@result.enable_ssl_warning = 1
|
136
|
+
@result.follow_redirect = 1
|
137
|
+
@result.test_tags = []
|
138
|
+
@result.node_locations = ['']
|
139
|
+
@result.status_codes = []
|
140
|
+
@result.virus = ''
|
141
|
+
|
142
|
+
instance_eval(&block)
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def paused(paused)
|
148
|
+
@result.paused = paused
|
149
|
+
end
|
150
|
+
|
151
|
+
def website_url(url)
|
152
|
+
@result.website_url = url
|
153
|
+
end
|
154
|
+
|
155
|
+
def website_name(name)
|
156
|
+
@result.website_name = name
|
157
|
+
end
|
158
|
+
|
159
|
+
def port(port)
|
160
|
+
@result.port = port
|
161
|
+
end
|
162
|
+
|
163
|
+
# def ping_url(url)
|
164
|
+
# @result.ping_url = url
|
165
|
+
# end
|
166
|
+
|
167
|
+
def custom_header(header)
|
168
|
+
if header == '' || header == nil
|
169
|
+
@result.custom_header = ''
|
170
|
+
else
|
171
|
+
@result.custom_header = header.to_json
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def confirmation(confirmation)
|
176
|
+
@result.confirmation = confirmation
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_type(type)
|
180
|
+
@result.test_type = type
|
181
|
+
end
|
182
|
+
|
183
|
+
def contact_group(groups)
|
184
|
+
@result.contact_group = Array(groups)
|
185
|
+
end
|
186
|
+
|
187
|
+
def check_rate(rate)
|
188
|
+
@result.check_rate = rate
|
189
|
+
end
|
190
|
+
|
191
|
+
def timeout(timeout)
|
192
|
+
@result.timeout = timeout
|
193
|
+
end
|
194
|
+
|
195
|
+
def website_host(host)
|
196
|
+
@result.website_host = host
|
197
|
+
end
|
198
|
+
|
199
|
+
def node_locations(locations)
|
200
|
+
@result.node_locations = locations
|
201
|
+
end
|
202
|
+
|
203
|
+
def find_string(str)
|
204
|
+
@result.find_string = str
|
205
|
+
end
|
206
|
+
|
207
|
+
def do_not_find(do_not_find)
|
208
|
+
@result.do_not_find = do_not_find
|
209
|
+
end
|
210
|
+
|
211
|
+
def basic_user(user)
|
212
|
+
@result.basic_user = user
|
213
|
+
end
|
214
|
+
|
215
|
+
def basic_pass(pass)
|
216
|
+
@result.basic_pass = pass
|
217
|
+
end
|
218
|
+
|
219
|
+
# def public(pub)
|
220
|
+
# @result.public = pub
|
221
|
+
# end
|
222
|
+
|
223
|
+
def logo_image(logo)
|
224
|
+
@result.logo_image = logo
|
225
|
+
end
|
226
|
+
|
227
|
+
def use_jar(use_jar)
|
228
|
+
@result.use_jar = use_jar
|
229
|
+
end
|
230
|
+
|
231
|
+
# def branding(branding)
|
232
|
+
# @result.branding = branding
|
233
|
+
# end
|
234
|
+
|
235
|
+
def virus(virus)
|
236
|
+
@result.virus = virus
|
237
|
+
end
|
238
|
+
|
239
|
+
# def real_browser(real_browser)
|
240
|
+
# @result.real_browser = real_browser
|
241
|
+
# end
|
242
|
+
|
243
|
+
def dns_server(dns_server)
|
244
|
+
@result.dns_server = dns_server
|
245
|
+
end
|
246
|
+
|
247
|
+
def dns_ip(ip)
|
248
|
+
@result.dns_ip = ip
|
249
|
+
end
|
250
|
+
|
251
|
+
def trigger_rate(rate)
|
252
|
+
@result.trigger_rate = rate
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_tags(tags)
|
256
|
+
if tags == nil
|
257
|
+
@result.test_tags = []
|
258
|
+
end
|
259
|
+
@result.test_tags = Array(tags)
|
260
|
+
end
|
261
|
+
|
262
|
+
def status_codes(codes)
|
263
|
+
@result.status_codes = codes
|
264
|
+
end
|
265
|
+
|
266
|
+
def enable_ssl_warning(enable_ssl_warning)
|
267
|
+
@result.enable_ssl_warning = enable_ssl_warning
|
268
|
+
end
|
269
|
+
|
270
|
+
def follow_redirect(follow_redirect)
|
271
|
+
@result.follow_redirect = follow_redirect
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
data/lib/kashi/dsl.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'hashie'
|
3
|
+
require 'kashi/dsl/cake'
|
4
|
+
|
5
|
+
module Kashi
|
6
|
+
class DSL
|
7
|
+
class << self
|
8
|
+
def define(source, filepath, options)
|
9
|
+
self.new(filepath, options) do
|
10
|
+
eval(source, binding, filepath)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :result
|
16
|
+
|
17
|
+
def initialize(filepath, options, &block)
|
18
|
+
@filepath = filepath
|
19
|
+
@result = OpenStruct.new(cake: nil)
|
20
|
+
|
21
|
+
@context = Hashie::Mash.new(
|
22
|
+
filepath: filepath,
|
23
|
+
templates: {},
|
24
|
+
options: options,
|
25
|
+
)
|
26
|
+
|
27
|
+
instance_eval(&block)
|
28
|
+
end
|
29
|
+
|
30
|
+
def require(file)
|
31
|
+
scfile = (file =~ %r|\A/|) ? file : File.expand_path(File.join(File.dirname(@filepath), file))
|
32
|
+
|
33
|
+
if File.exist?(scfile)
|
34
|
+
instance_eval(File.read(scfile), scfile)
|
35
|
+
elsif File.exist?("#{scfile}.rb")
|
36
|
+
instance_eval(File.read("#{scfile}.rb"), "#{scfile}.rb")
|
37
|
+
else
|
38
|
+
Kernel.require(file)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def template(name, &block)
|
43
|
+
@context.templates[name.to_s] = block
|
44
|
+
end
|
45
|
+
|
46
|
+
def cake(&block)
|
47
|
+
if @result.cake
|
48
|
+
@result.cake = Cake.new(@context, @result.cake.tests, @result.cake.contact_groups, &block).result
|
49
|
+
else
|
50
|
+
@result.cake = Cake.new(@context, &block).result
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
cake do
|
2
|
+
<%- contact_groups_by_id.each do |contact_id, contact_group| -%>
|
3
|
+
contact_group <%= contact_id %> do
|
4
|
+
group_name <%= contact_group['GroupName'].inspect %>
|
5
|
+
desktop_alert <%= contact_group['DesktopAlert'].inspect %>
|
6
|
+
email <%= contact_group['Emails'].inspect %>
|
7
|
+
boxcar <%= contact_group['Boxcar'].inspect %>
|
8
|
+
pushover <%= contact_group['Pushover'].inspect %>
|
9
|
+
ping_url <%= contact_group['PingURL'].inspect %>
|
10
|
+
mobile <%= contact_group['Mobiles'].inspect %>
|
11
|
+
end
|
12
|
+
<%- if contact_groups_by_id.keys.last != contact_id -%>
|
13
|
+
|
14
|
+
<%- end -%>
|
15
|
+
<%- end -%>
|
16
|
+
<%- if !contact_groups_by_id.empty? && !tests_by_id.empty? -%>
|
17
|
+
|
18
|
+
<%- end -%>
|
19
|
+
<%- tests_by_id.each do |test_id, test| -%>
|
20
|
+
test <%= test_id.inspect %> do
|
21
|
+
paused <%= test['Paused'] ? 1 : 0 %>
|
22
|
+
|
23
|
+
test_type <%= test['TestType'].inspect %>
|
24
|
+
|
25
|
+
# Required Details
|
26
|
+
website_name <%= test['WebsiteName'].inspect %>
|
27
|
+
website_url <%= test['URI'].inspect %>
|
28
|
+
<%- if %w/SMTP SSH TCP/.include?(test['TestType']) -%>
|
29
|
+
port <%= test['Port'].inspect %>
|
30
|
+
<%- end -%>
|
31
|
+
<%- if test['TestType'] == 'DNS' -%>
|
32
|
+
dns_ip <%= test['DNSIP'].inspect %>
|
33
|
+
dns_server <%= test['DNSServer'].inspect %>
|
34
|
+
<%- end -%>
|
35
|
+
<%- if %w/HTTP HEAD SSH/.include?(test['TestType']) -%>
|
36
|
+
<%- if test['BasicUser'] -%>
|
37
|
+
basic_user <%= test['BasicUser'].inspect %>
|
38
|
+
<%- end -%>
|
39
|
+
<%- if test['BasicPass'] -%>
|
40
|
+
basic_pass <%= test['BasicPass'].inspect %>
|
41
|
+
<%- end -%>
|
42
|
+
<%- end -%>
|
43
|
+
|
44
|
+
contact_group <%= test['ContactGroups'].map { |contact_group| contact_group['Name'] }.inspect %>
|
45
|
+
|
46
|
+
<%- if %w/HTTP HEAD/.include?(test['TestType']) -%>
|
47
|
+
# Scans
|
48
|
+
enable_ssl_warning <%= test['EnableSSLWarning'] ? 1 : 0 %>
|
49
|
+
<%- if test['Virus'] -%>
|
50
|
+
virus 1
|
51
|
+
<%- end -%>
|
52
|
+
|
53
|
+
# HTTP Communication Options
|
54
|
+
find_string <%= test['FindString'].inspect %>
|
55
|
+
do_not_find <%= test['DoNotFind'] ? 1 : 0 %>
|
56
|
+
<%- if test['UseJar'] -%>
|
57
|
+
use_jar <%= test['UseJar'].inspect %>
|
58
|
+
<%- end -%>
|
59
|
+
follow_redirect <%= test['FollowRedirect'] ? 1 : 0 %>
|
60
|
+
custom_header(
|
61
|
+
<%= (test['CustomHeader'] == '' ? '' : JSON.parse(test['CustomHeader'])).inspect %>
|
62
|
+
)
|
63
|
+
status_codes <%= test['StatusCodes'].inspect %>
|
64
|
+
<%- end -%>
|
65
|
+
|
66
|
+
logo_image <%= test['LogoImage'].inspect %>
|
67
|
+
|
68
|
+
<%- if test['NodeLocations'] -%>
|
69
|
+
# Test Locations
|
70
|
+
node_locations <%= test['NodeLocations'].inspect %>
|
71
|
+
<%- end -%>
|
72
|
+
|
73
|
+
# Threshold Control
|
74
|
+
trigger_rate <%= test['TriggerRate'].inspect %>
|
75
|
+
confirmation <%= test['Confirmation'].inspect %>
|
76
|
+
|
77
|
+
# Additional Options
|
78
|
+
check_rate <%= test['CheckRate'].inspect %>
|
79
|
+
timeout <%= test['Timeout'].inspect %>
|
80
|
+
<%- if test['Tags'] -%>
|
81
|
+
test_tags <%= test['Tags'].inspect %>
|
82
|
+
<%- end -%>
|
83
|
+
website_host <%= test['WebsiteHost'].inspect %>
|
84
|
+
end
|
85
|
+
<%- if tests_by_id.keys.last != test_id -%>
|
86
|
+
|
87
|
+
<%- end -%>
|
88
|
+
<%- end -%>
|
89
|
+
end
|
data/lib/kashi/utils.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'diffy'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
module Kashi
|
5
|
+
class Utils
|
6
|
+
class << self
|
7
|
+
def normalize_hash(hash)
|
8
|
+
hash.dup.each do |k, v|
|
9
|
+
if v.kind_of?(Array)
|
10
|
+
v.sort!
|
11
|
+
if v.first.kind_of?(Hash)
|
12
|
+
hash[k] = v.map { |o| normalize_hash(o) }
|
13
|
+
elsif v.first.respond_to?(:to_h)
|
14
|
+
hash[k] = v.map { |o| normalize_hash(o.to_h) }
|
15
|
+
end
|
16
|
+
elsif v == nil
|
17
|
+
hash[k] = ''
|
18
|
+
elsif v.respond_to?(:to_h)
|
19
|
+
hash[k] = normalize_hash(v.to_h)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
sort_keys(hash)
|
23
|
+
end
|
24
|
+
|
25
|
+
def sort_keys(hash)
|
26
|
+
hash = Hash[hash.sort]
|
27
|
+
hash.each do |k, v|
|
28
|
+
if v.kind_of?(Array)
|
29
|
+
if v.first.kind_of?(Hash)
|
30
|
+
hash[k] = v.map { |h| sort_keys(h) }
|
31
|
+
end
|
32
|
+
elsif v.kind_of?(Hash)
|
33
|
+
hash[k] = sort_keys(v)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
hash
|
37
|
+
end
|
38
|
+
|
39
|
+
def diff(obj1, obj2, options = {})
|
40
|
+
diffy = Diffy::Diff.new(
|
41
|
+
obj1.pretty_inspect,
|
42
|
+
obj2.pretty_inspect,
|
43
|
+
:diff => '-u'
|
44
|
+
)
|
45
|
+
|
46
|
+
out = diffy.to_s(options[:color] ? :color : :text).gsub(/\s+\z/m, '')
|
47
|
+
out.gsub!(/^/, options[:indent]) if options[:indent]
|
48
|
+
out
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/kashi.rb
ADDED