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.
@@ -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