nagira 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +11 -0
- data/Rakefile +1 -1
- data/app/app.rb +44 -298
- data/app/concerns/host_status_name_concerneable.rb +18 -0
- data/app/concerns/output_typeable.rb +22 -0
- data/app/controllers/api_help_controller.rb +25 -0
- data/app/controllers/host_status_controller.rb +82 -0
- data/{lib/nagira/hostgroup.rb → app/controllers/hostgroup_controller.rb} +1 -1
- data/app/controllers/resource_status_controler.rb +65 -0
- data/app/controllers/service_status_controler.rb +50 -0
- data/{lib/nagira/servicegroup.rb → app/controllers/servicegroups_controller.rb} +1 -1
- data/app/filters/after.rb +76 -0
- data/app/filters/before.rb +156 -0
- data/app/filters/configure.rb +34 -0
- data/app/helpers/put_helpers.rb +11 -0
- data/{lib/nagira → app/loggers}/simple_logger.rb +0 -0
- data/{lib/nagira → app/parsers}/background_parse.rb +0 -0
- data/{lib/nagira → app/parsers}/parser.rb +1 -9
- data/app/routes/get.rb +50 -0
- data/app/routes/get/config.rb +11 -0
- data/app/{get → routes/get}/objects.rb +4 -24
- data/app/routes/get/status.rb +98 -0
- data/app/{get → routes/get}/status/hostgroups.rb +3 -14
- data/app/routes/get/status/servicegroups.rb +16 -0
- data/app/{put → routes/put}/host.rb +1 -4
- data/app/{put → routes/put}/status.rb +13 -20
- data/app/writers/external_command_writer.rb +52 -0
- data/bin/nagira +1 -1
- data/config/defaults.rb +20 -12
- data/config/environment.rb +2 -1
- data/lib/nagira/timed_parse.rb +1 -1
- data/spec/01_background_parser.rb +5 -5
- data/spec/01_data_format/01_nagira_response_spec.rb +6 -6
- data/spec/01_data_format/02_0_status_spec.rb +1 -1
- data/spec/01_data_format/02_nagira_data_spec.rb +8 -8
- data/spec/01_data_format/03_api_spec.rb +3 -3
- data/spec/get/status/comments_spec.rb +2 -2
- data/spec/get/status/endpoints_spec.rb +11 -11
- data/spec/get/status/hostgroup.rb +3 -3
- data/spec/get/status/hosts_spec.rb +1 -1
- data/spec/get/status/servicegroup.rb +4 -4
- data/spec/get/status/services_spec.rb +1 -1
- data/spec/put/host_spec.rb +4 -4
- data/spec/put/status_spec.rb +5 -5
- data/spec/put/support.rb +3 -3
- data/spec/spec_helper.rb +3 -3
- data/version.txt +1 -1
- metadata +70 -60
- data/app/get/config.rb +0 -24
- data/app/get/status.rb +0 -189
- data/app/get/status/servicegroups.rb +0 -28
- data/app/put.rb +0 -53
- data/lib/nagira.rb +0 -67
@@ -0,0 +1,22 @@
|
|
1
|
+
module OutputTypeable
|
2
|
+
def list?
|
3
|
+
@output == :list
|
4
|
+
end
|
5
|
+
|
6
|
+
def state?
|
7
|
+
@output == :state
|
8
|
+
end
|
9
|
+
|
10
|
+
def full?
|
11
|
+
@output == :full
|
12
|
+
end
|
13
|
+
|
14
|
+
def body_with_list(body)
|
15
|
+
if list?
|
16
|
+
body.keys
|
17
|
+
else
|
18
|
+
body
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Nagira < Sinatra::Base
|
2
|
+
|
3
|
+
# Parse routes, exposed by Sinatra and build human readable list of
|
4
|
+
# API endpoints.
|
5
|
+
class ApiHelpController
|
6
|
+
# Get all routes that Nagira provides.
|
7
|
+
def self.get
|
8
|
+
api = { }
|
9
|
+
|
10
|
+
param_regex = Regexp.new '\(\[\^\\\\\/\?\#\]\+\)'
|
11
|
+
Nagira.routes.keys.each do |method|
|
12
|
+
api[method] ||= []
|
13
|
+
Nagira.routes[method].each do |r|
|
14
|
+
path = r[0].inspect[3..-3]
|
15
|
+
r[1].each do |parm|
|
16
|
+
path.sub!(param_regex,":#{parm}")
|
17
|
+
end
|
18
|
+
path.gsub!('\\','')
|
19
|
+
api[method] << path unless path.empty?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
api
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
class Nagira < Sinatra::Base
|
2
|
+
class HostStatusController
|
3
|
+
include OutputTypeable
|
4
|
+
|
5
|
+
def initialize(status, output: nil, hostname: nil)
|
6
|
+
@status = status
|
7
|
+
@output = output
|
8
|
+
@hostname = hostname
|
9
|
+
@http_status = 200
|
10
|
+
end
|
11
|
+
attr_accessor :http_status
|
12
|
+
|
13
|
+
# Type of the output for data: full, normal, state or list
|
14
|
+
attr_accessor :output
|
15
|
+
|
16
|
+
# [optional] hostname, if not given then return data for all hosts
|
17
|
+
attr_accessor :hostname
|
18
|
+
|
19
|
+
# Get host status, depending on the type of output required: full,
|
20
|
+
# normal, state or list.
|
21
|
+
def get
|
22
|
+
body = case
|
23
|
+
when full? ; then status
|
24
|
+
when state? ; then state
|
25
|
+
when list? ; then list
|
26
|
+
|
27
|
+
else normal
|
28
|
+
end
|
29
|
+
[@http_status, body]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Update host status
|
33
|
+
def put(params)
|
34
|
+
Writer.new(:PROCESS_HOST_CHECK_RESULT)
|
35
|
+
.put(with_host(params))
|
36
|
+
end
|
37
|
+
|
38
|
+
def with_host(params)
|
39
|
+
params.merge({'host_name' => hostname})
|
40
|
+
end
|
41
|
+
|
42
|
+
# Status data: for all hosts or single host if hostname provided.
|
43
|
+
#
|
44
|
+
# @return [Hash] Nagios parsed data (Parser.status)
|
45
|
+
def status
|
46
|
+
if hostname
|
47
|
+
{ hostname => @status[hostname] }
|
48
|
+
else
|
49
|
+
@status
|
50
|
+
end
|
51
|
+
.tap { |x| @http_status = 404 if x.values.compact.empty? }
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# List of hosts
|
57
|
+
def list
|
58
|
+
status.keys
|
59
|
+
end
|
60
|
+
|
61
|
+
# Short state of the host: only hostname and state
|
62
|
+
def state
|
63
|
+
normal.inject({ }) { |hash,elem|
|
64
|
+
hash[elem.first] = elem.last.slice("host_name", "current_state")
|
65
|
+
hash
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
# Normal is 'reduced' hoststate: excluding services, i.e. only
|
70
|
+
# hoststate
|
71
|
+
def normal
|
72
|
+
status.inject({ }) do |hash,elem|
|
73
|
+
hash[elem.first] = elem.last.try(:[], 'hoststatus')
|
74
|
+
hash
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
# LocalWords: hoststate hoststatus
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class Nagira < Sinatra::Base
|
2
|
+
class ResourceStatusController
|
3
|
+
|
4
|
+
include OutputTypeable
|
5
|
+
|
6
|
+
# @param nagios_status [Hash] output of the Nagios status file parser
|
7
|
+
# @param output [Symbol(:state, :list)] Output data: full, short state or list
|
8
|
+
# @param hostname [String]
|
9
|
+
# @param service_name [String]
|
10
|
+
#
|
11
|
+
# @param resource [String] Resource to be reported. Currently
|
12
|
+
# supported 'servicestatus', 'servicecomments', 'hostcomments'
|
13
|
+
def initialize(nagios_status, output: nil, hostname: nil, service_name: nil, resource: "servicestatus")
|
14
|
+
|
15
|
+
@nagios_status = nagios_status
|
16
|
+
@output = output
|
17
|
+
@hostname = hostname
|
18
|
+
@service_name = service_name
|
19
|
+
@resource = if resource == 'services'
|
20
|
+
"servicestatus"
|
21
|
+
else
|
22
|
+
resource
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Return status of the resource
|
27
|
+
def get
|
28
|
+
case
|
29
|
+
when state?; then slice
|
30
|
+
when list?; then list
|
31
|
+
else
|
32
|
+
with_service_name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Narrow the status hash to include only 3 keys host_name,
|
39
|
+
# current_state and service_description
|
40
|
+
def slice
|
41
|
+
with_service_name.inject({ }) do |hash, elem|
|
42
|
+
hash[elem.first] = elem.last.slice("host_name", "current_state", "service_description")
|
43
|
+
hash
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# @return [Array] List of resources (services, servicecomments).
|
49
|
+
#
|
50
|
+
# Note: _hostcomments is an Array, return full array if status
|
51
|
+
# data structure is not Hash.
|
52
|
+
def list
|
53
|
+
if status.respond_to? :keys
|
54
|
+
status.keys
|
55
|
+
else
|
56
|
+
status
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
include HostStatusNameConcerneable
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# LocalWords: param servicestatus servicecomments hostcomments
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Nagira < Sinatra::Base
|
2
|
+
class ServiceStatusController
|
3
|
+
|
4
|
+
include OutputTypeable
|
5
|
+
|
6
|
+
# @param nagios_status [Hash] output of the Nagios status file parser
|
7
|
+
# @param output [Symbol(:state)] Output data: full or short state
|
8
|
+
# @param hostname [String]
|
9
|
+
# @param service_name [String]
|
10
|
+
def initialize(nagios_status, output: nil, hostname: nil, service_name: nil)
|
11
|
+
|
12
|
+
@nagios_status = nagios_status
|
13
|
+
@output = output
|
14
|
+
@hostname = hostname
|
15
|
+
@service_name = service_name
|
16
|
+
@resource = "servicestatus"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Read all statuses of the hosts' services. Format output: full
|
20
|
+
# service state hash, or state only: name and state.
|
21
|
+
def get
|
22
|
+
case
|
23
|
+
when state?
|
24
|
+
with_service_name
|
25
|
+
.values
|
26
|
+
.first
|
27
|
+
.slice("host_name", "current_state")
|
28
|
+
else
|
29
|
+
with_service_name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def put(params)
|
34
|
+
Writer.new(:PROCESS_SERVICE_CHECK_RESULT).put with_service_and_host(params)
|
35
|
+
end
|
36
|
+
|
37
|
+
def with_service_and_host(params)
|
38
|
+
params.merge({
|
39
|
+
'service_description' => @service_name,
|
40
|
+
'host_name' => @hostname
|
41
|
+
})
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
include HostStatusNameConcerneable
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# LocalWords: param servicestatus
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class Nagira < Sinatra::Base
|
2
|
+
# Bad request. If you are requesting for the route that does not
|
3
|
+
# exist.
|
4
|
+
after do
|
5
|
+
if response.status == 404
|
6
|
+
halt [404, {
|
7
|
+
:message => "Bad route or request",
|
8
|
+
:error => "HTTP::Notfound"
|
9
|
+
}.send("to_#{@format}")
|
10
|
+
]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
##
|
14
|
+
# @method object_not_found
|
15
|
+
# @overload after("Object not found or bad request")
|
16
|
+
#
|
17
|
+
# If result-set of object/status search is empty return HTTP 404 .
|
18
|
+
# This can happen when you are requesting status for not existing
|
19
|
+
# host and/or service.
|
20
|
+
#
|
21
|
+
after do
|
22
|
+
if response.body.empty?
|
23
|
+
halt [404, {
|
24
|
+
:message => "Object not found or bad request",
|
25
|
+
:error => "HTTP::Notfound"
|
26
|
+
}.send("to_#{@format}")
|
27
|
+
]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# @method argument_error
|
33
|
+
# @overload after("ArgumentError")
|
34
|
+
#
|
35
|
+
# Return 400 if result of PUT operation is not success.
|
36
|
+
#
|
37
|
+
after do
|
38
|
+
if request.put? && ! response.body[:result]
|
39
|
+
halt [400, response.body.send("to_#{@format}") ]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# @method convert_to_active_resource
|
45
|
+
# @overload after("Return Array for ActiveResouce routes")
|
46
|
+
#
|
47
|
+
#
|
48
|
+
after do
|
49
|
+
response.body = response.body.values if @active_resource && response.body.is_a?(Hash)
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# @method return_jsonp_data
|
54
|
+
# @overload after("Return formatted data")
|
55
|
+
#
|
56
|
+
# If it's a JSON-P request, return its data with prepended @callback
|
57
|
+
# function name. JSONP request is detected by +before+ method.
|
58
|
+
#
|
59
|
+
# If no callback paramete given, then simply return formatted data
|
60
|
+
# as XML, JSON, or YAML in response body.
|
61
|
+
#
|
62
|
+
# = Example
|
63
|
+
#
|
64
|
+
# $ curl 'http://localhost:4567/?callback=test'
|
65
|
+
# test(["{\"application\":\"Nagira\",\"version\":\"0.1.3\",\"url\":\"http://dmytro.github.com/nagira/\"}"])
|
66
|
+
#
|
67
|
+
after do
|
68
|
+
body(
|
69
|
+
if @callback
|
70
|
+
"#{@callback.to_s} (#{response.body.to_json})"
|
71
|
+
else
|
72
|
+
response.body.send "to_#{@format}"
|
73
|
+
end
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
class Nagira < Sinatra::Base
|
2
|
+
|
3
|
+
##
|
4
|
+
# Parse nagios files.
|
5
|
+
#
|
6
|
+
# Note: *.parse methods are monkey-patched here (if you have required
|
7
|
+
# 'lib/nagira' above) to set min parsing interval to avoid file paring
|
8
|
+
# on each HTTP request. File is parsed only if it was changed and if
|
9
|
+
# it was parsed more then 60 (default) seconds ago. See
|
10
|
+
# +lib/nagira/timed_parse.rb+ for mor more info.
|
11
|
+
#
|
12
|
+
# In development mode use files located under +./test/data+
|
13
|
+
# directory. This allows to do development on the host where Nagios is
|
14
|
+
# notinstalled. If you want to change this edit configuration in
|
15
|
+
# config/environment.rb file.
|
16
|
+
#
|
17
|
+
# See also comments in config/default.rb file regarding nagios_cfg,
|
18
|
+
# status_cfg, objects_cfg.
|
19
|
+
#
|
20
|
+
# @method parse_nagios_files
|
21
|
+
# @overload before("Parse Nagios files")
|
22
|
+
before do
|
23
|
+
Logger.log("BackgroundParser is not running", :warning) if
|
24
|
+
BackgroundParser.configured? && BackgroundParser.dead?
|
25
|
+
|
26
|
+
Parser.parse
|
27
|
+
|
28
|
+
@status = Parser.status['hosts']
|
29
|
+
@objects = Parser.objects
|
30
|
+
|
31
|
+
#
|
32
|
+
# Add plural keys to use ActiveResource with Nagira
|
33
|
+
#
|
34
|
+
@objects.keys.each do |singular|
|
35
|
+
@objects[singular.to_s.pluralize.to_sym] = @objects[singular]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# @method clear_instance_data
|
41
|
+
# @overload before("clear data")
|
42
|
+
#
|
43
|
+
# Clear values onf instance variables before start.
|
44
|
+
#
|
45
|
+
before do
|
46
|
+
@data = []
|
47
|
+
@format = @output = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# @method strip_extensions
|
52
|
+
# @overload before("detect format")
|
53
|
+
#
|
54
|
+
# Detect and strip output format extension
|
55
|
+
#
|
56
|
+
# Strip extension (@format) from HTTP route and set it as instance
|
57
|
+
# variable @format. Valid formats are .xml, .json, .yaml. If format
|
58
|
+
# is not specified, it is set to default format
|
59
|
+
# (Nagira.settings.format).
|
60
|
+
#
|
61
|
+
# \@format can be assigned one of the symbols: :xml, :json, :yaml.
|
62
|
+
#
|
63
|
+
# = Examples
|
64
|
+
#
|
65
|
+
# GET /_objects # => default format
|
66
|
+
# GET /_objects.json # => :json
|
67
|
+
# GET /_status/_list.yaml # => :yaml
|
68
|
+
#
|
69
|
+
before do
|
70
|
+
request.path_info.sub!(/#{settings.format_extensions}/, '')
|
71
|
+
@format = ($1 || settings.format).to_sym
|
72
|
+
content_type "application/#{@format.to_s}"
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# @method detect_ar_type
|
77
|
+
# @overload before('detect ActiveResource mode')
|
78
|
+
#
|
79
|
+
# Detect if this a request for ActiveResource PATH
|
80
|
+
#
|
81
|
+
before do
|
82
|
+
@active_resource = request.path_info =~ %r{^#{Nagira::AR_PREFIX}/}
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# @method strip_output_type
|
87
|
+
# @overload before('detect output mode')
|
88
|
+
#
|
89
|
+
# Detect output mode modifier
|
90
|
+
#
|
91
|
+
# Detect and strip output type from HTTP route. Full list of
|
92
|
+
# output types is +:list+, +:state+ or +:full+, corresponding to
|
93
|
+
# (+/list, +/state+, +/full+ routes).
|
94
|
+
#
|
95
|
+
# Output type defined by route modifier appended to the end of HTTP
|
96
|
+
# route. If no output type specfied it is set to +:full+. Output
|
97
|
+
# mode can be followed by format extension (+.json+, +.xml+ or
|
98
|
+
# +.yaml+).
|
99
|
+
#
|
100
|
+
# = Examples
|
101
|
+
#
|
102
|
+
# GET /_objects/_list # => :list
|
103
|
+
# GET /_status/_state # => :state
|
104
|
+
# GET /_status/:hostname # => :full
|
105
|
+
# GET /_status # => :normal
|
106
|
+
#
|
107
|
+
before do
|
108
|
+
request.path_info.sub!(/\/_(list|state|full)$/, '')
|
109
|
+
@output = ($1 || :normal).to_sym
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# @method find_jsonp_callback
|
114
|
+
# @overload before('find callback name')
|
115
|
+
#
|
116
|
+
# Detects if request is using jQuery JSON-P and sets @callback
|
117
|
+
# variable. @callback variable is used if after method and prepends
|
118
|
+
# JSON data with callback function name.
|
119
|
+
#
|
120
|
+
# = Example
|
121
|
+
#
|
122
|
+
# GET /_api?callback=jQuery12313123123 # @callback == jQuery12313123123
|
123
|
+
#
|
124
|
+
# JSONP support is based on the code from +sinatra/jsonp+ Gem
|
125
|
+
# https://github.com/shtirlic/sinatra-jsonp.
|
126
|
+
#
|
127
|
+
before do
|
128
|
+
if @format == :json
|
129
|
+
['callback','jscallback','jsonp','jsoncallback'].each do |x|
|
130
|
+
@callback = params.delete(x) unless @callback
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# @method parse_input_data
|
136
|
+
# @overload before("Parse PUT request body")
|
137
|
+
#
|
138
|
+
# Process the data before on each HTTP request.
|
139
|
+
#
|
140
|
+
# @return [Array] @input Sets @input instance variable.
|
141
|
+
#
|
142
|
+
before do
|
143
|
+
if request.put?
|
144
|
+
data = request.body.read
|
145
|
+
@input = case @format
|
146
|
+
when :json then JSON.parse data
|
147
|
+
when :xml then Hash.from_xml data
|
148
|
+
when :yaml then YAML.load data
|
149
|
+
end
|
150
|
+
# Make sure we always return an Array
|
151
|
+
@input = [@input] if @input.is_a? Hash
|
152
|
+
@input
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|