watch_list 0.1.0
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 +17 -0
- data/.rspec +2 -0
- data/.travis.yml +12 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +99 -0
- data/Rakefile +5 -0
- data/bin/watch_list +122 -0
- data/lib/watch_list.rb +27 -0
- data/lib/watch_list/client.rb +156 -0
- data/lib/watch_list/constants.rb +16 -0
- data/lib/watch_list/driver.rb +146 -0
- data/lib/watch_list/dsl.rb +11 -0
- data/lib/watch_list/dsl/context.rb +40 -0
- data/lib/watch_list/dsl/context/alert_contact.rb +33 -0
- data/lib/watch_list/dsl/context/monitor.rb +82 -0
- data/lib/watch_list/dsl/context/monitor/http.rb +13 -0
- data/lib/watch_list/dsl/context/monitor/keyword.rb +30 -0
- data/lib/watch_list/dsl/context/monitor/ping.rb +4 -0
- data/lib/watch_list/dsl/context/monitor/port.rb +30 -0
- data/lib/watch_list/dsl/context/monitor/type.rb +24 -0
- data/lib/watch_list/dsl/converter.rb +107 -0
- data/lib/watch_list/exporter.rb +145 -0
- data/lib/watch_list/ext/string_ext.rb +25 -0
- data/lib/watch_list/logger.rb +30 -0
- data/lib/watch_list/utils.rb +14 -0
- data/lib/watch_list/version.rb +3 -0
- data/spec/alert_contact_spec.rb +153 -0
- data/spec/monitor_spec.rb +303 -0
- data/spec/paused_spec.rb +69 -0
- data/spec/spec_helper.rb +149 -0
- data/spec/status_spec.rb +31 -0
- data/watch_list.gemspec +27 -0
- metadata +154 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
module WatchList
|
2
|
+
module Monitor
|
3
|
+
Type = WatchList::Utils.const_to_hash(UptimeRobot::Monitor::Type)
|
4
|
+
SubType = WatchList::Utils.const_to_hash(UptimeRobot::Monitor::SubType)
|
5
|
+
KeywordType = WatchList::Utils.const_to_hash(UptimeRobot::Monitor::KeywordType)
|
6
|
+
Status = WatchList::Utils.const_to_hash(UptimeRobot::Monitor::Status)
|
7
|
+
end
|
8
|
+
|
9
|
+
module Log
|
10
|
+
Type = WatchList::Utils.const_to_hash(UptimeRobot::Log::Type)
|
11
|
+
end
|
12
|
+
|
13
|
+
module AlertContact
|
14
|
+
Type = WatchList::Utils.const_to_hash(UptimeRobot::AlertContact::Type)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
class WatchList::Driver
|
2
|
+
include WatchList::Logger::Helper
|
3
|
+
|
4
|
+
def initialize(uptimerobot, opts = {})
|
5
|
+
@uptimerobot = uptimerobot
|
6
|
+
@options = opts
|
7
|
+
end
|
8
|
+
|
9
|
+
def new_alert_contact(attrs)
|
10
|
+
updated = false
|
11
|
+
log(:info, "Create AlertContact: #{describe_alert_contacts(attrs)}", :color => :cyan)
|
12
|
+
|
13
|
+
unless @options[:dry_run]
|
14
|
+
response = @uptimerobot.newAlertContact(
|
15
|
+
:alertContactType => attrs[:Type],
|
16
|
+
:alertContactValue => attrs[:Value],
|
17
|
+
)
|
18
|
+
|
19
|
+
attrs[:ID] = response['alertcontact']['id']
|
20
|
+
updated = true
|
21
|
+
end
|
22
|
+
|
23
|
+
updated
|
24
|
+
end
|
25
|
+
|
26
|
+
def delete_alert_contact(attrs)
|
27
|
+
updated = false
|
28
|
+
log(:info, "Delete AlertContact: #{describe_alert_contacts(attrs)}", :color => :red)
|
29
|
+
|
30
|
+
unless @options[:dry_run]
|
31
|
+
@uptimerobot.deleteAlertContact(
|
32
|
+
:alertContactID => attrs[:ID],
|
33
|
+
)
|
34
|
+
|
35
|
+
updated = true
|
36
|
+
end
|
37
|
+
|
38
|
+
updated
|
39
|
+
end
|
40
|
+
|
41
|
+
def new_monitor(attrs, exist_alert_contacts)
|
42
|
+
updated = false
|
43
|
+
log(:info, "Create Monitor: #{attrs[:FriendlyName]}", :color => :cyan)
|
44
|
+
|
45
|
+
unless @options[:dry_run]
|
46
|
+
normalize_edit_attrs!(attrs)
|
47
|
+
params = monitor_to_params(attrs, exist_alert_contacts)
|
48
|
+
response = @uptimerobot.newMonitor(params)
|
49
|
+
attrs[:ID] = response['monitor']['id']
|
50
|
+
updated = true
|
51
|
+
end
|
52
|
+
|
53
|
+
updated
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete_monitor(attrs)
|
57
|
+
updated = false
|
58
|
+
log(:info, "Delete Monitor: #{attrs[:FriendlyName]}", :color => :red)
|
59
|
+
|
60
|
+
unless @options[:dry_run]
|
61
|
+
@uptimerobot.deleteMonitor(
|
62
|
+
:monitorID => attrs[:ID],
|
63
|
+
)
|
64
|
+
|
65
|
+
updated = true
|
66
|
+
end
|
67
|
+
|
68
|
+
updated
|
69
|
+
end
|
70
|
+
|
71
|
+
def edit_monitor(monitor_id, monitor_name, attrs, exist_alert_contacts)
|
72
|
+
updated = false
|
73
|
+
log(:info, "Update Monitor: #{monitor_name}", :color => :green)
|
74
|
+
|
75
|
+
attrs.each do |key, value|
|
76
|
+
log(:info, " set #{key}=#{value}", :color => :green)
|
77
|
+
end
|
78
|
+
|
79
|
+
unless @options[:dry_run]
|
80
|
+
params = monitor_to_params(attrs, exist_alert_contacts)
|
81
|
+
params[:monitorID] = monitor_id
|
82
|
+
@uptimerobot.editMonitor(params)
|
83
|
+
updated = true
|
84
|
+
end
|
85
|
+
|
86
|
+
updated
|
87
|
+
end
|
88
|
+
|
89
|
+
def pause_monitor(monitor_id, monitor_name, paused)
|
90
|
+
updated = false
|
91
|
+
log(:info, (paused ? 'Pause' : 'Unpause') + " Monitor: #{monitor_name}", :color => :green)
|
92
|
+
|
93
|
+
unless @options[:dry_run]
|
94
|
+
@uptimerobot.editMonitor(
|
95
|
+
:monitorID => monitor_id,
|
96
|
+
:monitorStatus => (paused ? 0 : 1),
|
97
|
+
)
|
98
|
+
|
99
|
+
updated = true
|
100
|
+
end
|
101
|
+
|
102
|
+
updated
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def describe_alert_contacts(attrs)
|
108
|
+
type = WatchList::AlertContact::Type.key(attrs[:Type])
|
109
|
+
"#{type}, #{attrs[:Value]}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def monitor_to_params(attrs, exist_alert_contacts)
|
113
|
+
params = {}
|
114
|
+
attrs = attrs.dup
|
115
|
+
attrs.delete(:Paused)
|
116
|
+
alert_contacts = attrs.delete(:AlertContacts) || []
|
117
|
+
|
118
|
+
attrs.each do |key, value|
|
119
|
+
params["monitor#{key}"] = value unless value.nil?
|
120
|
+
end
|
121
|
+
|
122
|
+
unless alert_contacts.empty?
|
123
|
+
params[:monitorAlertContacts] = alert_contacts.map {|alert_contact|
|
124
|
+
exist_alert_contact = exist_alert_contacts.find {|i|
|
125
|
+
i.values_at(:Type, :Value) == alert_contact.values_at(:Type, :Value)
|
126
|
+
}
|
127
|
+
|
128
|
+
raise "AlertContact does not exist: #{alert_contact.inspect}" unless exist_alert_contact
|
129
|
+
|
130
|
+
exist_alert_contact[:ID]
|
131
|
+
}.join(',')
|
132
|
+
end
|
133
|
+
|
134
|
+
params
|
135
|
+
end
|
136
|
+
|
137
|
+
def normalize_edit_attrs!(attrs)
|
138
|
+
# XXX: Other parameter is required in order to update the "HTTPUsername" and "HTTPPassword"
|
139
|
+
attrs[:Interval] ||= expected[:Interval]
|
140
|
+
|
141
|
+
# Remove by an empty parameter
|
142
|
+
attrs.keys.each do |key|
|
143
|
+
attrs[key] ||= ''
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class WatchList::DSL
|
2
|
+
class << self
|
3
|
+
def convert(exported, opts = {})
|
4
|
+
WatchList::DSL::Converter.convert(exported, opts)
|
5
|
+
end
|
6
|
+
|
7
|
+
def parse(dsl, path, opts = {})
|
8
|
+
WatchList::DSL::Context.eval(dsl, path, opts).result
|
9
|
+
end
|
10
|
+
end # of class methods
|
11
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class WatchList::DSL::Context
|
2
|
+
class << self
|
3
|
+
def eval(dsl, path, opts = {})
|
4
|
+
self.new(path, opts) {
|
5
|
+
Kernel.eval(dsl, binding, path)
|
6
|
+
}
|
7
|
+
end
|
8
|
+
end # of class methods
|
9
|
+
|
10
|
+
attr_reader :result
|
11
|
+
|
12
|
+
def initialize(path, options = {}, &block)
|
13
|
+
@path = path
|
14
|
+
@options = options
|
15
|
+
@result = {:monitors => {}, :alert_contacts => []}
|
16
|
+
instance_eval(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def require(file)
|
20
|
+
robotfile = File.expand_path(File.join(File.dirname(@path), file))
|
21
|
+
|
22
|
+
if File.exist?(robotfile)
|
23
|
+
instance_eval(File.read(robotfile), robotfile)
|
24
|
+
elsif File.exist?(robotfile + '.rb')
|
25
|
+
instance_eval(File.read(robotfile + '.rb'), robotfile + '.rb')
|
26
|
+
else
|
27
|
+
Kernel.require(file)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def monitor(name, &block)
|
32
|
+
raise 'Monitor: "friendlyname" is required' unless name
|
33
|
+
raise "Monitor `#{name}` is already defined" if @result[:monitors][name]
|
34
|
+
@result[:monitors][name] = WatchList::DSL::Context::Monitor.new(name, &block).result
|
35
|
+
end
|
36
|
+
|
37
|
+
def alert_contact(&block)
|
38
|
+
@result[:alert_contacts] << WatchList::DSL::Context::AlertContact.new(&block).result
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class WatchList::DSL::Context::AlertContact
|
2
|
+
def initialize(&block)
|
3
|
+
@result = {}
|
4
|
+
instance_eval(&block)
|
5
|
+
end
|
6
|
+
|
7
|
+
def result
|
8
|
+
[:Type, :Value].each do |key|
|
9
|
+
raise %!AlertContact: "#{key.to_s.downcase}" is required! unless @result[key]
|
10
|
+
end
|
11
|
+
|
12
|
+
@result
|
13
|
+
end
|
14
|
+
|
15
|
+
def type(value, &block)
|
16
|
+
if value.kind_of?(Integer)
|
17
|
+
alert_contact_type = value
|
18
|
+
else
|
19
|
+
alert_contact_type = WatchList::AlertContact::Type[value.to_s]
|
20
|
+
end
|
21
|
+
|
22
|
+
unless WatchList::AlertContact::Type.values.include?(alert_contact_type)
|
23
|
+
raise %!AlertContact: "type" is invalid: #{value.inspect}!
|
24
|
+
end
|
25
|
+
|
26
|
+
@result[:Type] = alert_contact_type
|
27
|
+
end
|
28
|
+
|
29
|
+
def value(value)
|
30
|
+
raise %!AlertContact: "value" is invalid: #{value.inspect}! if value.nil?
|
31
|
+
@result[:Value] = value.to_s
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
class WatchList::DSL::Context::Monitor
|
2
|
+
def initialize(name, &block)
|
3
|
+
@name = name
|
4
|
+
|
5
|
+
@result = {
|
6
|
+
:FriendlyName => name,
|
7
|
+
:Paused => false,
|
8
|
+
:AlertContacts => [],
|
9
|
+
}
|
10
|
+
|
11
|
+
instance_eval(&block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def result
|
15
|
+
raise %!Monitor `#{@name}`: "target" is required! unless @result[:URL]
|
16
|
+
|
17
|
+
[:Interval, :Type].each do |key|
|
18
|
+
raise %!Monitor `#{@name}`: "#{key.to_s.downcase}" is required! unless @result[key]
|
19
|
+
end
|
20
|
+
|
21
|
+
@result
|
22
|
+
end
|
23
|
+
|
24
|
+
def target(value)
|
25
|
+
raise %!Monitor `#{@name}`: "target" is invalid: #{value.inspect}! if value.nil?
|
26
|
+
@result[:URL] = value.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def interval(value)
|
30
|
+
raise %!Monitor `#{@name}`: "interval" is invalid: #{value.inspect}! unless value.kind_of?(Integer)
|
31
|
+
@result[:Interval] = value
|
32
|
+
end
|
33
|
+
|
34
|
+
def paused(value)
|
35
|
+
unless [TrueClass, FalseClass].any? {|i| value.kind_of?(i) }
|
36
|
+
raise %!Monitor `#{@name}`: "paused" is invalid: #{value.inspect}!
|
37
|
+
end
|
38
|
+
|
39
|
+
@result[:Paused] = value
|
40
|
+
end
|
41
|
+
|
42
|
+
def alert_contact(type, value)
|
43
|
+
if type.kind_of?(Integer)
|
44
|
+
alert_contact_type = type
|
45
|
+
else
|
46
|
+
alert_contact_type = WatchList::AlertContact::Type[type.to_s]
|
47
|
+
end
|
48
|
+
|
49
|
+
unless WatchList::AlertContact::Type.values.include?(alert_contact_type)
|
50
|
+
raise %!Monitor `#{@name}`: "alert_contact" type is invalid: #{type.inspect}!
|
51
|
+
end
|
52
|
+
|
53
|
+
raise %!Monitor `#{@name}`: "alert_contact" value is invalid: #{value.inspect}! if value.nil?
|
54
|
+
|
55
|
+
hash = {:Type => alert_contact_type, :Value => value.to_s}
|
56
|
+
|
57
|
+
if @result[:AlertContacts].include?(hash)
|
58
|
+
raise %!Monitor `#{@name}`: "alert_contact"(#{type}, #{value}) is already defined!
|
59
|
+
end
|
60
|
+
|
61
|
+
@result[:AlertContacts] << hash
|
62
|
+
end
|
63
|
+
|
64
|
+
def type(value, &block)
|
65
|
+
if value.kind_of?(Integer)
|
66
|
+
monitor_type = value
|
67
|
+
else
|
68
|
+
monitor_type = WatchList::Monitor::Type[value.to_s]
|
69
|
+
end
|
70
|
+
|
71
|
+
unless WatchList::Monitor::Type.values.include?(monitor_type)
|
72
|
+
raise %!Monitor `#{@name}`: "type" is invalid: #{value.inspect}!
|
73
|
+
end
|
74
|
+
|
75
|
+
@result[:Type] = monitor_type
|
76
|
+
|
77
|
+
type_class = WatchList::DSL::Context::Monitor::Type[value.to_s]
|
78
|
+
raise "Monitor `#{@name}`: #{value.inspect} is unimplemented type" unless type_class
|
79
|
+
|
80
|
+
@result.update(type_class.new(@name, &block).result)
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class WatchList::DSL::Context::Monitor
|
2
|
+
class HTTP < Type
|
3
|
+
def httpusername(value)
|
4
|
+
raise %!Monitor `#{@monitor_name}`: "httpusername" is invalid: #{value.inspect}! if value.nil?
|
5
|
+
@result[:HTTPUsername] = value.to_s
|
6
|
+
end
|
7
|
+
|
8
|
+
def httppassword(value)
|
9
|
+
raise %!Monitor `#{@monitor_name}`: "httppassword" is invalid: #{value.inspect}! if value.nil?
|
10
|
+
@result[:HTTPPassword] = value.to_s
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class WatchList::DSL::Context::Monitor
|
2
|
+
class Keyword < HTTP
|
3
|
+
def result
|
4
|
+
[:KeywordType, :KeywordValue].each do |key|
|
5
|
+
raise %!Monitor `#{@monitor_name}`: "#{key.to_s.downcase}" is required! unless @result[key]
|
6
|
+
end
|
7
|
+
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def keywordtype(value)
|
12
|
+
if value.kind_of?(Integer)
|
13
|
+
type = value
|
14
|
+
else
|
15
|
+
type = WatchList::Monitor::KeywordType[value.to_s]
|
16
|
+
end
|
17
|
+
|
18
|
+
unless WatchList::Monitor::KeywordType.values.include?(type)
|
19
|
+
raise %!Monitor `#{@monitor_name}`: "keywordtype" is invalid: #{value.inspect}!
|
20
|
+
end
|
21
|
+
|
22
|
+
@result[:KeywordType] = type
|
23
|
+
end
|
24
|
+
|
25
|
+
def keywordvalue(value)
|
26
|
+
raise %!Monitor `#{@monitor_name}`: "keywordvalue" is invalid: #{value.inspect}! if value.nil?
|
27
|
+
@result[:KeywordValue] = value.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class WatchList::DSL::Context::Monitor
|
2
|
+
class Port < Type
|
3
|
+
def result
|
4
|
+
[:SubType, :Port].each do |key|
|
5
|
+
raise %!Monitor `#{@monitor_name}`: "#{key.to_s.downcase}" is required! unless @result[key]
|
6
|
+
end
|
7
|
+
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def subtype(value)
|
12
|
+
if value.kind_of?(Integer)
|
13
|
+
type = value
|
14
|
+
else
|
15
|
+
type = WatchList::Monitor::SubType[value.to_s]
|
16
|
+
end
|
17
|
+
|
18
|
+
unless WatchList::Monitor::SubType.values.include?(type)
|
19
|
+
raise %!Monitor `#{@monitor_name}`: "subtype" is invalid: #{value.inspect}!
|
20
|
+
end
|
21
|
+
|
22
|
+
@result[:SubType] = type
|
23
|
+
end
|
24
|
+
|
25
|
+
def port(value)
|
26
|
+
raise %!Monitor `#{@monitor_name}`: "port" is invalid: #{value.inspect}! unless value.kind_of?(Integer)
|
27
|
+
@result[:Port] = value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class WatchList::DSL::Context::Monitor::Type
|
2
|
+
CHILDREN = {}
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def inherited(child)
|
6
|
+
name = child.to_s.split('::').last.downcase
|
7
|
+
CHILDREN[name] = child
|
8
|
+
end
|
9
|
+
|
10
|
+
def [](name)
|
11
|
+
CHILDREN[name]
|
12
|
+
end
|
13
|
+
end # of class methods
|
14
|
+
|
15
|
+
def initialize(monitor_name, &block)
|
16
|
+
@monitor_name = monitor_name
|
17
|
+
@result = {}
|
18
|
+
instance_eval(&block) if block
|
19
|
+
end
|
20
|
+
|
21
|
+
def result
|
22
|
+
@result
|
23
|
+
end
|
24
|
+
end
|