nagira 0.5.1 → 0.5.2
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 +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
|