nagira 0.2.5
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.
- data/History.md +89 -0
- data/Rakefile +128 -0
- data/bin/nagira +11 -0
- data/bin/nagira-setup +6 -0
- data/config/defaults.rb +74 -0
- data/config/environment.rb +44 -0
- data/config/nagira.defaults +66 -0
- data/config/nagira.init_d +133 -0
- data/lib/app.rb +330 -0
- data/lib/app/routes/get/config.rb +22 -0
- data/lib/app/routes/get/objects.rb +71 -0
- data/lib/app/routes/get/status.rb +153 -0
- data/lib/app/routes/put.rb +52 -0
- data/lib/app/routes/put/status.rb +139 -0
- data/lib/nagira.rb +55 -0
- data/lib/nagira/background_parse.rb +28 -0
- data/lib/nagira/nagios.rb +20 -0
- data/lib/nagira/timed_parse.rb +77 -0
- data/spec/00_configuration_spec.rb +62 -0
- data/spec/01_nagira_response_spec.rb +122 -0
- data/spec/02_0_status_spec.rb +53 -0
- data/spec/02_nagira_data_spec.rb +101 -0
- data/spec/03_api_spec.rb +48 -0
- data/spec/spec_helper.rb +4 -0
- data/test/benchmark.rb +26 -0
- data/test/data/bad/README +1 -0
- data/test/data/bad/nagios.cfg +1305 -0
- data/test/data/bad/objects.cache +1868 -0
- data/test/data/bad/status.dat +1766 -0
- data/test/data/json/GET.txt +15 -0
- data/test/data/json/README.txt +9 -0
- data/test/data/json/host_check.json +4 -0
- data/test/data/json/host_check.sh +4 -0
- data/test/data/json/ping.json +5 -0
- data/test/data/json/ping_and_http.json +12 -0
- data/test/data/json/ping_and_http_check.sh +4 -0
- data/test/data/json/ping_check.sh +4 -0
- data/test/data/nagios.cfg +1305 -0
- data/test/data/objects.cache +1868 -0
- data/test/data/status.dat +1652 -0
- data/version.txt +1 -0
- metadata +384 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
class Nagira < Sinatra::Base
|
2
|
+
|
3
|
+
# @method parse_input_data
|
4
|
+
# @overload before("Parse PUT request body")
|
5
|
+
#
|
6
|
+
# Process the data before on each HTTP request.
|
7
|
+
#
|
8
|
+
# @return [Array] @input Sets @input instance variable.
|
9
|
+
#
|
10
|
+
before do
|
11
|
+
if request.put?
|
12
|
+
data = request.body.read
|
13
|
+
@input = case @format
|
14
|
+
when :json then JSON.parse data
|
15
|
+
when :xml then Hash.from_xml data
|
16
|
+
when :yaml then YAML.load data
|
17
|
+
end
|
18
|
+
# Make sure we always return an Array
|
19
|
+
@input = [@input] if @input.is_a? Hash
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Define helpers for put methods
|
24
|
+
helpers do
|
25
|
+
|
26
|
+
# Helper to send PUT update to Nagios::ExternalCommands
|
27
|
+
#
|
28
|
+
# @param [Hash] params
|
29
|
+
# @param [Symbol] action Nagios external command name
|
30
|
+
#
|
31
|
+
# FIXME: This only accepts single service. Modify to use Arrays too
|
32
|
+
def put_update action, params
|
33
|
+
res = $nagios[:commands].write(params.merge({ :action => action }))
|
34
|
+
{ :status => res[:result], :object => res[:data]}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Small helper to submit data to ::Nagios::ExternalCommands
|
39
|
+
# object. For status updates sends external coond via
|
40
|
+
# ::Nagios::ExternalCommands.send method.
|
41
|
+
def update_service_status params
|
42
|
+
put_update :PROCESS_SERVICE_CHECK_RESULT, params
|
43
|
+
end
|
44
|
+
|
45
|
+
# Small helper to submit data to ::Nagios::ExternalCommands
|
46
|
+
# object. For host status updates sends external command via
|
47
|
+
# ::Nagios::ExternalCommands.write method.
|
48
|
+
def update_host_status params
|
49
|
+
put_update :PROCESS_HOST_CHECK_RESULT, params
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
class Nagira < Sinatra::Base
|
2
|
+
|
3
|
+
|
4
|
+
# @method put_status
|
5
|
+
# @overload put("/_status")
|
6
|
+
#
|
7
|
+
# Submit JSON Hash for multiple services, on multiple hosts.
|
8
|
+
put "/_status" do
|
9
|
+
"TODO: Not implemented"
|
10
|
+
end
|
11
|
+
|
12
|
+
# @method put_status_host_name
|
13
|
+
# @overload put("/_status/:host_name")
|
14
|
+
#
|
15
|
+
# Update hoststatus information only for the given host. URL
|
16
|
+
# hostname always override hostname given in the JSON file.
|
17
|
+
#
|
18
|
+
# == Example
|
19
|
+
#
|
20
|
+
# $ curl -i -H "Accept: application/json" -d @host.json -X
|
21
|
+
# PUT http://localhost:4567/_status/svaroh
|
22
|
+
#
|
23
|
+
# => {"status": true, "object": [{"data": {"host_name":"svaroh",
|
24
|
+
# "status_code": "0", "plugin_output": "ping OK", "action":
|
25
|
+
# "PROCESS_HOST_CHECK_RESULT"}, "result":true, "messages": []}]}
|
26
|
+
#
|
27
|
+
# == Example JSON
|
28
|
+
#
|
29
|
+
# {
|
30
|
+
# "status_code":"0",
|
31
|
+
# "plugin_output" : "ping OK"
|
32
|
+
# }
|
33
|
+
put "/_status/:host_name" do
|
34
|
+
@data = update_host_status @input.first.merge({
|
35
|
+
'host_name' => params['host_name']
|
36
|
+
})
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# Same as /_status/:host_name (Not implemented)
|
41
|
+
#
|
42
|
+
# @method put__host_status_host_name
|
43
|
+
# @overload put("/_host_status/:host_name")
|
44
|
+
#
|
45
|
+
put "/_host_status/:host_name" do
|
46
|
+
"Not implemented: TODO"
|
47
|
+
end
|
48
|
+
|
49
|
+
# @method put_status_host_name_services
|
50
|
+
# @overload put("/_status/:host_name/_services")
|
51
|
+
#
|
52
|
+
# Update multiple services on the same host.
|
53
|
+
#
|
54
|
+
# Hostname from URL always overrides host_name if it's is provided
|
55
|
+
# in the JSON data.
|
56
|
+
#
|
57
|
+
# == Example return JSON data
|
58
|
+
#
|
59
|
+
# $ curl -i -H "Accept: application/json" -d @dat_m.json -X PUT
|
60
|
+
# http://localhost:4567/_status/svaroh/_services
|
61
|
+
#
|
62
|
+
# [{"status":true, "object":[{"data":{"host_name":"svaroh",
|
63
|
+
# "service_description":"PING", "return_code":"0",
|
64
|
+
# "plugin_output":"OK",
|
65
|
+
# "action":"PROCESS_SERVICE_CHECK_RESULT"}, "result":true,
|
66
|
+
# "messages":[]}]}, {"status":true,
|
67
|
+
# "object":[{"data":{"host_name":"svaroh",
|
68
|
+
# "service_description":"Apache", "return_code":"r20",
|
69
|
+
# "plugin_output":"cwfailedOK",
|
70
|
+
# "action":"PROCESS_SERVICE_CHECK_RESULT"}, "result":true,
|
71
|
+
# "messages":[]}]}]%
|
72
|
+
#
|
73
|
+
# == Example JSON for submit
|
74
|
+
#
|
75
|
+
# All attributes provided in the example below are requried for host
|
76
|
+
# service status information:
|
77
|
+
# - host_name
|
78
|
+
# - service_description
|
79
|
+
# - return_code
|
80
|
+
# - plugin_output
|
81
|
+
#
|
82
|
+
#
|
83
|
+
# [{ "host_name":"viy",
|
84
|
+
# "service_description":"PING",
|
85
|
+
# "return_code":"0",
|
86
|
+
# "plugin_output":"64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.046 ms "
|
87
|
+
# },
|
88
|
+
#
|
89
|
+
# {"host_name":"svaroh",
|
90
|
+
# "service_description":"Apache",
|
91
|
+
# "return_code":"2",
|
92
|
+
# "plugin_output":"HTTP GEt failed"
|
93
|
+
# }
|
94
|
+
# ]
|
95
|
+
#
|
96
|
+
#
|
97
|
+
put "/_status/:host_name/_services" do
|
98
|
+
|
99
|
+
data = []
|
100
|
+
@input.each do |datum|
|
101
|
+
# FIXME - this calls update for each service. Should be batching them together
|
102
|
+
data << update_service_status(
|
103
|
+
datum.merge({
|
104
|
+
'host_name' => params['host_name']
|
105
|
+
})
|
106
|
+
)
|
107
|
+
end
|
108
|
+
@data = data
|
109
|
+
nil
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
# Update single service on a single host by JSON data.
|
114
|
+
put "/_status/:host_name/_services/:service_description" do
|
115
|
+
@data = update_service_status \
|
116
|
+
@input.first.merge({
|
117
|
+
'service_description' => params['service_description'],
|
118
|
+
'host_name' => params['host_name']
|
119
|
+
})
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
|
123
|
+
# @method put_status_as_http_parms
|
124
|
+
# @overload put(/_status/:host_name/_services/:service_description/_return_code/:return_code/_plugin_output/:plugin_output)
|
125
|
+
#
|
126
|
+
# Update single service status on a single host. Use data provided
|
127
|
+
# in RESTful path as parameters.
|
128
|
+
#
|
129
|
+
# == Example
|
130
|
+
# curl -d "test data" \
|
131
|
+
# -X PUT http://localhost:4567/_status/viy/_services/PING/_return_code/0/_plugin_output/OK
|
132
|
+
# # => ok
|
133
|
+
put "/_status/:host_name/_services/:service_description/_return_code/:return_code/_plugin_output/:plugin_output" do
|
134
|
+
|
135
|
+
@data = update_service_status params
|
136
|
+
nil
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
data/lib/nagira.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'active_model/serialization'
|
2
|
+
require 'active_model/serializers/xml' # for Hash.to_xml
|
3
|
+
|
4
|
+
require 'active_support/inflector'
|
5
|
+
require 'active_support/inflector/inflections'
|
6
|
+
require 'active_support/core_ext/hash/slice' # for Hash.slice
|
7
|
+
|
8
|
+
require 'json'
|
9
|
+
require 'yaml'
|
10
|
+
require 'sinatra'
|
11
|
+
require 'sinatra/reloader'
|
12
|
+
|
13
|
+
$: << File.dirname(__FILE__) << File.dirname(File.dirname(__FILE__))
|
14
|
+
|
15
|
+
require 'config/defaults'
|
16
|
+
|
17
|
+
require "app/routes/get/config"
|
18
|
+
require "app/routes/get/objects"
|
19
|
+
require "app/routes/get/status"
|
20
|
+
|
21
|
+
require "app/routes/put"
|
22
|
+
require "app/routes/put/status"
|
23
|
+
|
24
|
+
|
25
|
+
#
|
26
|
+
# environment file must go after default, some settings override
|
27
|
+
# defaults.
|
28
|
+
#
|
29
|
+
require 'config/environment'
|
30
|
+
require 'nagira/nagios'
|
31
|
+
|
32
|
+
class Nagira < Sinatra::Base
|
33
|
+
|
34
|
+
VERSION = File.read(File.expand_path(File.dirname(__FILE__)) + '/../version.txt').strip
|
35
|
+
GITHUB = "http://dmytro.github.com/nagira/"
|
36
|
+
|
37
|
+
# Get all routes that Nagira provides.
|
38
|
+
def api
|
39
|
+
api = { }
|
40
|
+
|
41
|
+
param_regex = Regexp.new '\(\[\^\\\\\/\?\#\]\+\)'
|
42
|
+
Nagira.routes.keys.each do |method|
|
43
|
+
api[method] ||= []
|
44
|
+
Nagira.routes[method].each do |r|
|
45
|
+
path = r[0].inspect[3..-3]
|
46
|
+
r[1].each do |parm|
|
47
|
+
path.sub!(param_regex,":#{parm}")
|
48
|
+
end
|
49
|
+
path.gsub!('\\','')
|
50
|
+
api[method] << path unless path.empty?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
api
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'nagios'
|
2
|
+
|
3
|
+
module Nagios
|
4
|
+
##
|
5
|
+
# Background parsing of status.dat file in separate thread. Runs on
|
6
|
+
# regular intervals slightly shorter than :ttl
|
7
|
+
#
|
8
|
+
class BackgroundParser
|
9
|
+
|
10
|
+
##
|
11
|
+
#
|
12
|
+
# If :ttl is not defined set to 0 and do not run
|
13
|
+
# background parsing.
|
14
|
+
#
|
15
|
+
def initialize
|
16
|
+
interval = [::DEFAULT[:ttl],1].max || nil
|
17
|
+
if interval && ::DEFAULT[:start_background_parser]
|
18
|
+
puts "[#{Time.now}] Starting background parser thread with interval #{interval} sec"
|
19
|
+
$bg = Thread.new {
|
20
|
+
loop {
|
21
|
+
$nagios[:status].parse
|
22
|
+
sleep interval
|
23
|
+
} #loop
|
24
|
+
} # thread
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Nagios
|
2
|
+
|
3
|
+
require 'nagira/timed_parse'
|
4
|
+
require 'nagira/background_parse'
|
5
|
+
|
6
|
+
# Extensions to Nagios::Status and Objects classes for use with
|
7
|
+
# Nagira: keep track of file modification times and parse only
|
8
|
+
# changed files.
|
9
|
+
class Config
|
10
|
+
include Nagios::TimedParse
|
11
|
+
end
|
12
|
+
|
13
|
+
class Status
|
14
|
+
include Nagios::TimedParse
|
15
|
+
end
|
16
|
+
|
17
|
+
class Nagios::Objects
|
18
|
+
include Nagios::TimedParse
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'nagios'
|
2
|
+
|
3
|
+
module Nagios
|
4
|
+
# Keep track of last parsed time and last changed time of the
|
5
|
+
# status/cache file to avoid parsing on each HTTP request.
|
6
|
+
module TimedParse
|
7
|
+
|
8
|
+
# Set some minimum interval for re-parsing of the status file:
|
9
|
+
# even if file changes often, we do not want to parse it more
|
10
|
+
# often, then this number of seconds.
|
11
|
+
|
12
|
+
TTL = ::DEFAULT[:ttl] || 0
|
13
|
+
|
14
|
+
# Override constructor and parse method from ::Nagios::Objects or
|
15
|
+
# ::Nagios::Status classes, add instance variables to handle
|
16
|
+
# modification and parseing times of status file.
|
17
|
+
# Original methods are aliased:
|
18
|
+
# - initialize -> constructor
|
19
|
+
# - parse -> parse!
|
20
|
+
# See also
|
21
|
+
# http://www.ruby-forum.com/topic/969161
|
22
|
+
def self.included(base)
|
23
|
+
base.class_eval do
|
24
|
+
alias_method :parse!, :parse
|
25
|
+
alias_method :constructor, :initialize
|
26
|
+
|
27
|
+
# @method initialize
|
28
|
+
# Extend current constructor with some additional data to
|
29
|
+
# track file change time
|
30
|
+
#
|
31
|
+
# @param [String] file Path to status file
|
32
|
+
# @param [Fixnum] parse_interval Number of seconds between
|
33
|
+
# re-parsing of the file
|
34
|
+
def initialize(file, parse_interval=TTL)
|
35
|
+
constructor(file)
|
36
|
+
|
37
|
+
# Time when status file was last time parsed, set it to 0 secs
|
38
|
+
# epoch to make sure it will be parsed
|
39
|
+
@last_parsed = Time.at(0)
|
40
|
+
|
41
|
+
# Last time file was changed
|
42
|
+
@last_changed = File.mtime(@path)
|
43
|
+
@parse_interval = parse_interval
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# Extend original parse method: parse file only if it needs
|
48
|
+
# parsing and set time of parser run to current time.
|
49
|
+
def parse
|
50
|
+
if need_parsing?
|
51
|
+
parse!
|
52
|
+
@last_parsed = Time.now
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
attr_accessor :last_parsed, :parse_interval
|
59
|
+
|
60
|
+
def last_changed
|
61
|
+
@last_changed = File.mtime(@path)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Return true if file is changed since it was parsed last time
|
65
|
+
def changed?
|
66
|
+
self.last_changed > self.last_parsed
|
67
|
+
end
|
68
|
+
|
69
|
+
# Check if:
|
70
|
+
# - file changed?
|
71
|
+
# - was it parsed recently?
|
72
|
+
def need_parsing?
|
73
|
+
changed? && ((Time.now - self.last_parsed) > @parse_interval)
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Configuration" do
|
4
|
+
|
5
|
+
set :environment, ENV['RACK_ENV'] || :test
|
6
|
+
|
7
|
+
before {
|
8
|
+
@cfg = Nagios::Config.new(Nagira.settings.nagios_cfg)
|
9
|
+
}
|
10
|
+
|
11
|
+
context "nagios.cfg" do
|
12
|
+
|
13
|
+
it { File.should exist @cfg.path }
|
14
|
+
|
15
|
+
it "should be parseable" do
|
16
|
+
lambda { @cfg.parse }.should_not raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
context "parsing nagios.cfg file" do
|
20
|
+
|
21
|
+
before { @cfg.parse }
|
22
|
+
|
23
|
+
it "should have PATH to objects file" do
|
24
|
+
@cfg.object_cache_file.should be_a_kind_of String
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should have PATH to status file" do
|
28
|
+
@cfg.status_file.should be_a_kind_of String
|
29
|
+
end
|
30
|
+
|
31
|
+
end # parsing nagios.cfg file
|
32
|
+
end # nagios.cfg
|
33
|
+
|
34
|
+
context "data files" do
|
35
|
+
before { @cfg.parse }
|
36
|
+
|
37
|
+
context Nagios::Status do
|
38
|
+
|
39
|
+
subject { Nagios::Status.new( Nagira.settings.status_cfg || @cfg.status_file ) }
|
40
|
+
|
41
|
+
it { File.should exist( subject.path ) }
|
42
|
+
|
43
|
+
it "should be parseable" do
|
44
|
+
lambda { subject.parse }.should_not raise_error
|
45
|
+
end
|
46
|
+
end # Nagios::Status
|
47
|
+
|
48
|
+
|
49
|
+
context Nagios::Objects do
|
50
|
+
|
51
|
+
subject { Nagios::Objects.new( Nagira.settings.objects_cfg || @cfg.object_cache_file) }
|
52
|
+
|
53
|
+
it { File.should exist subject.path }
|
54
|
+
|
55
|
+
it "should be parseable" do
|
56
|
+
lambda { subject.parse }.should_not raise_error
|
57
|
+
end
|
58
|
+
end # Nagios::Objects
|
59
|
+
|
60
|
+
end # data files
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Nagira do
|
4
|
+
|
5
|
+
set :environment, ENV['RACK_ENV'] || :test
|
6
|
+
|
7
|
+
include Rack::Test::Methods
|
8
|
+
|
9
|
+
def app
|
10
|
+
@app ||= Nagira
|
11
|
+
end
|
12
|
+
|
13
|
+
TOP_PAGES = %w{ _config _objects _status _api }
|
14
|
+
FORMATS = %w{ xml yaml json}
|
15
|
+
DEFAULT_FORMAT = ::Nagira.settings.format
|
16
|
+
TYPES = %w{state list}
|
17
|
+
|
18
|
+
context "simple page load" do
|
19
|
+
TOP_PAGES.each do |page|
|
20
|
+
it "/#{page} should load" do
|
21
|
+
get "/#{page}"
|
22
|
+
last_response.should be_ok
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# Check 3 different formats
|
27
|
+
FORMATS.each do |format|
|
28
|
+
|
29
|
+
it "should load '#{page}.#{format}' page" do
|
30
|
+
get "/#{page}.#{format}"
|
31
|
+
last_response.should be_ok
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "data format check" do
|
39
|
+
|
40
|
+
TOP_PAGES.each do |page|
|
41
|
+
context page do
|
42
|
+
|
43
|
+
FORMATS.each do |format|
|
44
|
+
|
45
|
+
context format do
|
46
|
+
|
47
|
+
before do
|
48
|
+
get "/#{page}.#{format}"
|
49
|
+
@header = last_response.header
|
50
|
+
@body = last_response.body
|
51
|
+
end
|
52
|
+
|
53
|
+
it "Content-type: application/#{format}" do
|
54
|
+
@header['Content-Type'].should =~ /^application\/#{format}.*/
|
55
|
+
end
|
56
|
+
|
57
|
+
it "body should have content" do
|
58
|
+
@body.should_not be_empty
|
59
|
+
end
|
60
|
+
|
61
|
+
it "#{format} should be parseable" do
|
62
|
+
case format
|
63
|
+
when 'json'
|
64
|
+
lambda { JSON.parse @body }.should_not raise_error
|
65
|
+
when 'xml'
|
66
|
+
lambda { Hash.from_xml @body }.should_not raise_error
|
67
|
+
when 'yaml'
|
68
|
+
lambda { YAML.load @body }.should_not raise_error
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'default format' do
|
76
|
+
it "/#{page}.#{Nagira.settings.format} response should be the same as /#{page}" do
|
77
|
+
get "/#{page}.#{Nagira.settings.format}"
|
78
|
+
a = last_response.body
|
79
|
+
get "/#{page}"
|
80
|
+
b = last_response.body
|
81
|
+
a.should eq b
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# GET /config
|
90
|
+
# ----------------------------------------
|
91
|
+
context "/config" do
|
92
|
+
|
93
|
+
before do
|
94
|
+
get "/_config.json"
|
95
|
+
@data = JSON.parse last_response.body
|
96
|
+
end
|
97
|
+
|
98
|
+
context "important items in Nagios configuration" do
|
99
|
+
|
100
|
+
# Configuration strings
|
101
|
+
|
102
|
+
%w{ log_file object_cache_file resource_file status_file
|
103
|
+
nagios_user nagios_group }.each do |key|
|
104
|
+
|
105
|
+
it "attribute #{key} should be a String" do
|
106
|
+
@data[key].should be_a_kind_of String
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Congiration arrays
|
111
|
+
%w{cfg_file cfg_dir}.each do |key|
|
112
|
+
it "attribute #{key} should be an Array" do
|
113
|
+
@data[key].should be_a_kind_of Array
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end # /config
|
119
|
+
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|