kashi 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,9 @@
1
+ class String
2
+ def to_snake()
3
+ self
4
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
5
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
6
+ .tr("-", "_")
7
+ .downcase
8
+ end
9
+ 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
@@ -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
@@ -0,0 +1,3 @@
1
+ module Kashi
2
+ VERSION = '0.1.0.beta1'
3
+ end
data/lib/kashi.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'logger'
2
+ require 'kashi/version'
3
+ require 'kashi/ext/string-ext'
4
+
5
+ module Kashi
6
+ def self.logger
7
+ @logger ||=
8
+ begin
9
+ $stdout.sync = true
10
+ Logger.new($stdout).tap do |l|
11
+ l.level = Logger::INFO
12
+ end
13
+ end
14
+ end
15
+ end