nagios_parser 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ Gemfile.lock
2
+ pkg/*
3
+ *.gem
4
+ .bundle
5
+ .rspec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in nagios_parser.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2010 Bernd Ahlers <bernd@tuneafish.de>
2
+
3
+ Permission to use, copy, modify, and distribute this software for any
4
+ purpose with or without fee is hereby granted, provided that the above
5
+ copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,134 @@
1
+ Nagios Parser
2
+ =============
3
+
4
+ # Description
5
+
6
+ The `nagios_parser` gem provides a parser for the Nagios `status.dat`
7
+ files and a parser for the Nagios object definition files.
8
+
9
+ * NagiosParser::Status::Parser
10
+ * NagiosParser::Object::Parser
11
+
12
+ Both parsers return plain hashes and arrays. There are no special
13
+ Nagios objects or something like that. That means you can create
14
+ your own wrapping objects or use the simple data structure
15
+ directly.
16
+
17
+ # Installation
18
+
19
+ # gem install nagios_parser
20
+
21
+ # Usage
22
+
23
+ ## Status Parser
24
+
25
+ require 'nagios_parser/status/parser'
26
+ require 'pp'
27
+
28
+ status = <<-STATUS
29
+ info {
30
+ created=1291408262
31
+ version=3.2.0
32
+ last_update_check=1291201457
33
+ update_available=1
34
+ last_version=3.2.0
35
+ new_version=3.2.3
36
+ }
37
+ hoststatus {
38
+ host_name=server1
39
+ modified_attributes=0
40
+ check_command=check-ping
41
+ check_period=24x7
42
+ notification_period=24x7
43
+ check_interval=5.000000
44
+ retry_interval=1.000000
45
+ event_handler=
46
+ has_been_checked=1
47
+ }
48
+ STATUS
49
+
50
+ data = NagiosParser::Status::Parser.parse(status)
51
+ pp data
52
+
53
+ This will print a data structure that looks like this.
54
+
55
+ {"info"=>
56
+ [{"last_version"=>"3.2.0",
57
+ "version"=>"3.2.0",
58
+ "last_update_check"=>1291201457,
59
+ "new_version"=>"3.2.3",
60
+ "update_available"=>1,
61
+ "created"=>1291408262}],
62
+ "hoststatus"=>
63
+ [{"check_command"=>"check-ping",
64
+ "host_name"=>"server1",
65
+ "notification_period"=>"24x7",
66
+ "check_period"=>"24x7",
67
+ "modified_attributes"=>0,
68
+ "retry_interval"=>"1.000000",
69
+ "has_been_checked"=>1,
70
+ "event_handler"=>nil,
71
+ "check_interval"=>"5.000000"}]}
72
+
73
+ ## Object Parser
74
+
75
+ require 'nagios_parser/object/parser'
76
+ require 'pp'
77
+
78
+ object = <<-OBJECT
79
+ define command {
80
+ command_name check-http
81
+ command_line $USER1$/check_http -I $HOSTADDRESS$ -w 420 -c 840
82
+ }
83
+ define host {
84
+ host_name server1
85
+ alias server1.example.com
86
+ address 10.0.0.1
87
+ }
88
+ OBJECT
89
+
90
+ data = NagiosParser::Object::Parser.parse(object)
91
+ pp data
92
+
93
+ This will print a data structure that looks like this.
94
+
95
+ {"command"=>
96
+ [{"command_name"=>"check-http",
97
+ "command_line"=>"$USER1$/check_http -I $HOSTADDRESS$ -w 420 -c 840"}],
98
+ "host"=>
99
+ [{"address"=>"10.0.0.1",
100
+ "host_name"=>"server1",
101
+ "alias"=>"server1.example.com"}]}
102
+
103
+ # Development
104
+
105
+ The parsers are based on the racc parser generator. racc is needed
106
+ at runtime, but that should be no problem since it's included in the
107
+ Ruby standard library.
108
+
109
+ To modify the parsers you have to modify the `.y` files and regenerate
110
+ the Ruby files afterwards. There are two rake tasks to help with that.
111
+
112
+ * `rake parser::status`
113
+ * `rake parser::object`
114
+
115
+ The bundler gem is used to handle the development dependencies.
116
+ Run `bundle install` to install them.
117
+
118
+ Please let me know if you have any questions or if you run into any
119
+ problems.
120
+
121
+ # Contribute
122
+
123
+ * Fork the project.
124
+ * Make your feature addition or bug fix.
125
+ * Add tests for it. This is important so I don't break it in a
126
+ future version unintentionally.
127
+ * Commit, do not mess with Rakefile, version, or history.
128
+ (if you want to have your own version, that is fine but bump version
129
+ in a commit by itself I can ignore when I pull)
130
+ * Send me a pull request. Bonus points for topic branches.
131
+
132
+ # Copyright
133
+
134
+ Copyright (c) 2010 Bernd Ahlers. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.rcov = false
8
+ end
9
+
10
+ namespace :parser do
11
+ desc 'Generate the status parser with racc'
12
+ task :status => [ 'lib/nagios_parser/status/parser.rb' ]
13
+
14
+ desc 'Generate the object parser with racc'
15
+ task :object => [ 'lib/nagios_parser/object/parser.rb' ]
16
+
17
+ rule '.rb' => '.y' do |target|
18
+ sh "racc -o #{target.name} #{target.source}"
19
+ end
20
+ end
@@ -0,0 +1,206 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.6
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+ require 'strscan'
10
+
11
+ module NagiosParser
12
+ module Object
13
+ class Parser < Racc::Parser
14
+
15
+ module_eval(<<'...end parser.y/module_eval...', 'parser.y', 34)
16
+
17
+ private
18
+ def last_is_key?(list)
19
+ list.last[0] == :KEY
20
+ end
21
+
22
+ public
23
+ def create_token(string)
24
+ result = []
25
+ inside = false
26
+ scanner = StringScanner.new(string)
27
+
28
+ until scanner.empty?
29
+ case
30
+ when scanner.scan(/\s+/)
31
+ # ignore whitespace
32
+ when scanner.scan(/#[^\n]*/)
33
+ # ignore comments
34
+ when scanner.scan(/define/)
35
+ result << [:DEFINE, nil]
36
+ when (!inside and match = scanner.scan(/\w+/))
37
+ result << [:TYPE, match]
38
+ when match = scanner.scan(/\{/)
39
+ inside = true
40
+ result << [:OPEN, nil]
41
+ when match = scanner.scan(/\}/)
42
+ inside = false
43
+ result << [:CLOSE, nil]
44
+ when (!last_is_key?(result) and match = scanner.scan(/\w+/))
45
+ result << [:KEY, match.chomp.gsub(/\s+$/, '')]
46
+ when (inside and match = scanner.scan(/\d+$/))
47
+ result << [:VALUE, match.to_i]
48
+ when (inside and match = scanner.scan(/[^\n\}]+/))
49
+ result << [:VALUE, match.gsub(/\s+$/, '')]
50
+ else
51
+ raise "Can't tokenize <#{scanner.peek(10)}>"
52
+ end
53
+ end
54
+
55
+ result << [false, false]
56
+ end
57
+
58
+ attr_accessor :token
59
+
60
+ def self.parse(string)
61
+ new.parse(string)
62
+ end
63
+
64
+ def parse(string)
65
+ @result = {}
66
+ @token = create_token(string)
67
+ do_parse
68
+ @result
69
+ end
70
+
71
+ def next_token
72
+ @token.shift
73
+ end
74
+ ...end parser.y/module_eval...
75
+ ##### State transition tables begin ###
76
+
77
+ racc_action_table = [
78
+ 5, 8, 1, 13, 11, 7, 1, 11, 4, 14 ]
79
+
80
+ racc_action_check = [
81
+ 2, 5, 2, 9, 9, 4, 0, 7, 1, 11 ]
82
+
83
+ racc_action_pointer = [
84
+ 4, 5, 0, nil, 1, 1, nil, 1, nil, -2,
85
+ nil, 2, nil, nil, nil ]
86
+
87
+ racc_action_default = [
88
+ -7, -7, -7, -1, -7, -7, -2, -7, 15, -7,
89
+ -4, -7, -5, -3, -6 ]
90
+
91
+ racc_goto_table = [
92
+ 10, 3, 12, 6, 9, 2 ]
93
+
94
+ racc_goto_check = [
95
+ 4, 2, 4, 2, 3, 1 ]
96
+
97
+ racc_goto_pointer = [
98
+ nil, 5, 1, -3, -7 ]
99
+
100
+ racc_goto_default = [
101
+ nil, nil, nil, nil, nil ]
102
+
103
+ racc_reduce_table = [
104
+ 0, 0, :racc_error,
105
+ 1, 9, :_reduce_none,
106
+ 2, 9, :_reduce_none,
107
+ 5, 10, :_reduce_3,
108
+ 1, 11, :_reduce_none,
109
+ 2, 11, :_reduce_5,
110
+ 2, 12, :_reduce_6 ]
111
+
112
+ racc_reduce_n = 7
113
+
114
+ racc_shift_n = 15
115
+
116
+ racc_token_table = {
117
+ false => 0,
118
+ :error => 1,
119
+ :DEFINE => 2,
120
+ :TYPE => 3,
121
+ :OPEN => 4,
122
+ :CLOSE => 5,
123
+ :KEY => 6,
124
+ :VALUE => 7 }
125
+
126
+ racc_nt_base = 8
127
+
128
+ racc_use_result_var = true
129
+
130
+ Racc_arg = [
131
+ racc_action_table,
132
+ racc_action_check,
133
+ racc_action_default,
134
+ racc_action_pointer,
135
+ racc_goto_table,
136
+ racc_goto_check,
137
+ racc_goto_default,
138
+ racc_goto_pointer,
139
+ racc_nt_base,
140
+ racc_reduce_table,
141
+ racc_token_table,
142
+ racc_shift_n,
143
+ racc_reduce_n,
144
+ racc_use_result_var ]
145
+
146
+ Racc_token_to_s_table = [
147
+ "$end",
148
+ "error",
149
+ "DEFINE",
150
+ "TYPE",
151
+ "OPEN",
152
+ "CLOSE",
153
+ "KEY",
154
+ "VALUE",
155
+ "$start",
156
+ "defines",
157
+ "define",
158
+ "assignments",
159
+ "assignment" ]
160
+
161
+ Racc_debug_parser = false
162
+
163
+ ##### State transition tables end #####
164
+
165
+ # reduce 0 omitted
166
+
167
+ # reduce 1 omitted
168
+
169
+ # reduce 2 omitted
170
+
171
+ module_eval(<<'.,.,', 'parser.y', 11)
172
+ def _reduce_3(val, _values, result)
173
+ @result[val[1]] ||= []
174
+ @result[val[1]] << val[3]
175
+
176
+ result
177
+ end
178
+ .,.,
179
+
180
+ # reduce 4 omitted
181
+
182
+ module_eval(<<'.,.,', 'parser.y', 18)
183
+ def _reduce_5(val, _values, result)
184
+ val[1].each do |key, value|
185
+ val[0][key] = value
186
+ end
187
+ result = val[0]
188
+
189
+ result
190
+ end
191
+ .,.,
192
+
193
+ module_eval(<<'.,.,', 'parser.y', 25)
194
+ def _reduce_6(val, _values, result)
195
+ result = {val[0] => val[1]}
196
+ result
197
+ end
198
+ .,.,
199
+
200
+ def _reduce_none(val, _values, result)
201
+ val[0]
202
+ end
203
+
204
+ end # class Parser
205
+ end # module Object
206
+ end # module NagiosParser
@@ -0,0 +1,91 @@
1
+ class NagiosParser::Object::Parser
2
+ token
3
+ DEFINE TYPE OPEN CLOSE KEY VALUE
4
+
5
+ rule
6
+ defines
7
+ : define
8
+ | defines define
9
+ ;
10
+ define
11
+ : DEFINE TYPE OPEN assignments CLOSE {
12
+ @result[val[1]] ||= []
13
+ @result[val[1]] << val[3]
14
+ }
15
+ ;
16
+ assignments
17
+ : assignment
18
+ | assignments assignment {
19
+ val[1].each do |key, value|
20
+ val[0][key] = value
21
+ end
22
+ result = val[0]
23
+ }
24
+ ;
25
+ assignment
26
+ : KEY VALUE { result = {val[0] => val[1]} }
27
+ ;
28
+ end
29
+
30
+ ---- header
31
+ require 'strscan'
32
+
33
+ ---- inner
34
+
35
+ private
36
+ def last_is_key?(list)
37
+ list.last[0] == :KEY
38
+ end
39
+
40
+ public
41
+ def create_token(string)
42
+ result = []
43
+ inside = false
44
+ scanner = StringScanner.new(string)
45
+
46
+ until scanner.empty?
47
+ case
48
+ when scanner.scan(/\s+/)
49
+ # ignore whitespace
50
+ when scanner.scan(/#[^\n]*/)
51
+ # ignore comments
52
+ when scanner.scan(/define/)
53
+ result << [:DEFINE, nil]
54
+ when (!inside and match = scanner.scan(/\w+/))
55
+ result << [:TYPE, match]
56
+ when match = scanner.scan(/\{/)
57
+ inside = true
58
+ result << [:OPEN, nil]
59
+ when match = scanner.scan(/\}/)
60
+ inside = false
61
+ result << [:CLOSE, nil]
62
+ when (!last_is_key?(result) and match = scanner.scan(/\w+/))
63
+ result << [:KEY, match.chomp.gsub(/\s+$/, '')]
64
+ when (inside and match = scanner.scan(/\d+$/))
65
+ result << [:VALUE, match.to_i]
66
+ when (inside and match = scanner.scan(/[^\n\}]+/))
67
+ result << [:VALUE, match.gsub(/\s+$/, '')]
68
+ else
69
+ raise "Can't tokenize <#{scanner.peek(10)}>"
70
+ end
71
+ end
72
+
73
+ result << [false, false]
74
+ end
75
+
76
+ attr_accessor :token
77
+
78
+ def self.parse(string)
79
+ new.parse(string)
80
+ end
81
+
82
+ def parse(string)
83
+ @result = {}
84
+ @token = create_token(string)
85
+ do_parse
86
+ @result
87
+ end
88
+
89
+ def next_token
90
+ @token.shift
91
+ end
@@ -0,0 +1,244 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.6
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+ require 'strscan'
10
+
11
+ module NagiosParser
12
+ module Status
13
+ class Parser < Racc::Parser
14
+
15
+ module_eval(<<'...end parser.y/module_eval...', 'parser.y', 39)
16
+
17
+ def create_token(string)
18
+ result = []
19
+ inside = false
20
+ scanner = StringScanner.new(string)
21
+
22
+ until scanner.empty?
23
+ case
24
+ when scanner.scan(/\s+/)
25
+ # ignore whitespace
26
+ when scanner.scan(/#[^\n]*/)
27
+ # ignore comments
28
+ when (!inside and match = scanner.scan(/\w+/))
29
+ result << [match, match]
30
+ when match = scanner.scan(/\{/)
31
+ inside = true
32
+ result << [:OPEN, nil]
33
+ when match = scanner.scan(/\}/)
34
+ inside = false
35
+ result << [:CLOSE, nil]
36
+ when match = scanner.scan(/\w+\s*\=/)
37
+ result << [:KEY, match.chop.gsub(/\s+$/, '')]
38
+ when (inside and match = scanner.scan(/\d+$/))
39
+ result << [:VALUE, match.to_i]
40
+ when (inside and match = scanner.scan(/[^\n\}]+/))
41
+ result << [:VALUE, match.gsub(/\s+$/, '')]
42
+ else
43
+ raise "Can't tokenize <#{scanner.peek(10)}>"
44
+ end
45
+ end
46
+
47
+ result << [false, false]
48
+ end
49
+
50
+ attr_accessor :token
51
+
52
+ def self.parse(string)
53
+ new.parse(string)
54
+ end
55
+
56
+ def parse(string)
57
+ @result = {}
58
+ @token = create_token(string)
59
+ do_parse
60
+ @result
61
+ end
62
+
63
+ def next_token
64
+ @token.shift
65
+ end
66
+ ...end parser.y/module_eval...
67
+ ##### State transition tables begin ###
68
+
69
+ racc_action_table = [
70
+ 11, 19, 15, 13, 15, 18, 6, 7, 8, 9,
71
+ 10, 1, 2, 6, 7, 8, 9, 10, 1, 2,
72
+ 14 ]
73
+
74
+ racc_action_check = [
75
+ 3, 16, 16, 5, 13, 15, 3, 3, 3, 3,
76
+ 3, 3, 3, 0, 0, 0, 0, 0, 0, 0,
77
+ 11 ]
78
+
79
+ racc_action_pointer = [
80
+ 7, nil, nil, 0, nil, 1, nil, nil, nil, nil,
81
+ nil, 20, nil, 0, nil, 0, -2, nil, nil, nil,
82
+ nil ]
83
+
84
+ racc_action_default = [
85
+ -15, -9, -10, -15, -1, -15, -4, -5, -6, -7,
86
+ -8, -15, -2, -15, 21, -13, -15, -11, -14, -3,
87
+ -12 ]
88
+
89
+ racc_goto_table = [
90
+ 17, 4, 16, 20, 12, 3 ]
91
+
92
+ racc_goto_check = [
93
+ 5, 2, 4, 5, 2, 1 ]
94
+
95
+ racc_goto_pointer = [
96
+ nil, 5, 1, nil, -11, -13 ]
97
+
98
+ racc_goto_default = [
99
+ nil, nil, nil, 5, nil, nil ]
100
+
101
+ racc_reduce_table = [
102
+ 0, 0, :racc_error,
103
+ 1, 14, :_reduce_none,
104
+ 2, 14, :_reduce_none,
105
+ 4, 15, :_reduce_3,
106
+ 1, 16, :_reduce_none,
107
+ 1, 16, :_reduce_none,
108
+ 1, 16, :_reduce_none,
109
+ 1, 16, :_reduce_none,
110
+ 1, 16, :_reduce_none,
111
+ 1, 16, :_reduce_none,
112
+ 1, 16, :_reduce_none,
113
+ 1, 17, :_reduce_none,
114
+ 2, 17, :_reduce_12,
115
+ 1, 18, :_reduce_13,
116
+ 2, 18, :_reduce_14 ]
117
+
118
+ racc_reduce_n = 15
119
+
120
+ racc_shift_n = 21
121
+
122
+ racc_token_table = {
123
+ false => 0,
124
+ :error => 1,
125
+ :OPEN => 2,
126
+ :CLOSE => 3,
127
+ :KEY => 4,
128
+ :VALUE => 5,
129
+ "hostcomment" => 6,
130
+ "servicestatus" => 7,
131
+ "info" => 8,
132
+ "programstatus" => 9,
133
+ "hoststatus" => 10,
134
+ "contactstatus" => 11,
135
+ "servicecomment" => 12 }
136
+
137
+ racc_nt_base = 13
138
+
139
+ racc_use_result_var = true
140
+
141
+ Racc_arg = [
142
+ racc_action_table,
143
+ racc_action_check,
144
+ racc_action_default,
145
+ racc_action_pointer,
146
+ racc_goto_table,
147
+ racc_goto_check,
148
+ racc_goto_default,
149
+ racc_goto_pointer,
150
+ racc_nt_base,
151
+ racc_reduce_table,
152
+ racc_token_table,
153
+ racc_shift_n,
154
+ racc_reduce_n,
155
+ racc_use_result_var ]
156
+
157
+ Racc_token_to_s_table = [
158
+ "$end",
159
+ "error",
160
+ "OPEN",
161
+ "CLOSE",
162
+ "KEY",
163
+ "VALUE",
164
+ "\"hostcomment\"",
165
+ "\"servicestatus\"",
166
+ "\"info\"",
167
+ "\"programstatus\"",
168
+ "\"hoststatus\"",
169
+ "\"contactstatus\"",
170
+ "\"servicecomment\"",
171
+ "$start",
172
+ "types",
173
+ "type",
174
+ "type_names",
175
+ "assignments",
176
+ "assignment" ]
177
+
178
+ Racc_debug_parser = false
179
+
180
+ ##### State transition tables end #####
181
+
182
+ # reduce 0 omitted
183
+
184
+ # reduce 1 omitted
185
+
186
+ # reduce 2 omitted
187
+
188
+ module_eval(<<'.,.,', 'parser.y', 11)
189
+ def _reduce_3(val, _values, result)
190
+ @result[val[0]] ||= []
191
+ @result[val[0]] << val[2]
192
+
193
+ result
194
+ end
195
+ .,.,
196
+
197
+ # reduce 4 omitted
198
+
199
+ # reduce 5 omitted
200
+
201
+ # reduce 6 omitted
202
+
203
+ # reduce 7 omitted
204
+
205
+ # reduce 8 omitted
206
+
207
+ # reduce 9 omitted
208
+
209
+ # reduce 10 omitted
210
+
211
+ # reduce 11 omitted
212
+
213
+ module_eval(<<'.,.,', 'parser.y', 22)
214
+ def _reduce_12(val, _values, result)
215
+ val[1].each do |key, value|
216
+ val[0][key] = value
217
+ end
218
+ result = val[0]
219
+
220
+ result
221
+ end
222
+ .,.,
223
+
224
+ module_eval(<<'.,.,', 'parser.y', 29)
225
+ def _reduce_13(val, _values, result)
226
+ result = {val[0] => nil}
227
+ result
228
+ end
229
+ .,.,
230
+
231
+ module_eval(<<'.,.,', 'parser.y', 30)
232
+ def _reduce_14(val, _values, result)
233
+ result = {val[0] => val[1]}
234
+ result
235
+ end
236
+ .,.,
237
+
238
+ def _reduce_none(val, _values, result)
239
+ val[0]
240
+ end
241
+
242
+ end # class Parser
243
+ end # module Status
244
+ end # module NagiosParser
@@ -0,0 +1,88 @@
1
+ class NagiosParser::Status::Parser
2
+ token
3
+ OPEN CLOSE KEY VALUE
4
+
5
+ rule
6
+ types
7
+ : type
8
+ | types type
9
+ ;
10
+ type
11
+ : type_names OPEN assignments CLOSE {
12
+ @result[val[0]] ||= []
13
+ @result[val[0]] << val[2]
14
+ }
15
+ ;
16
+ type_names
17
+ : 'hostcomment' | 'servicestatus' | 'info' | 'programstatus'
18
+ | 'hoststatus' | 'contactstatus' | 'servicecomment'
19
+ ;
20
+ assignments
21
+ : assignment
22
+ | assignments assignment {
23
+ val[1].each do |key, value|
24
+ val[0][key] = value
25
+ end
26
+ result = val[0]
27
+ }
28
+ ;
29
+ assignment
30
+ : KEY { result = {val[0] => nil}}
31
+ | KEY VALUE { result = {val[0] => val[1]} }
32
+ ;
33
+ end
34
+
35
+ ---- header
36
+ require 'strscan'
37
+
38
+ ---- inner
39
+
40
+ def create_token(string)
41
+ result = []
42
+ inside = false
43
+ scanner = StringScanner.new(string)
44
+
45
+ until scanner.empty?
46
+ case
47
+ when scanner.scan(/\s+/)
48
+ # ignore whitespace
49
+ when scanner.scan(/#[^\n]*/)
50
+ # ignore comments
51
+ when (!inside and match = scanner.scan(/\w+/))
52
+ result << [match, match]
53
+ when match = scanner.scan(/\{/)
54
+ inside = true
55
+ result << [:OPEN, nil]
56
+ when match = scanner.scan(/\}/)
57
+ inside = false
58
+ result << [:CLOSE, nil]
59
+ when match = scanner.scan(/\w+\s*\=/)
60
+ result << [:KEY, match.chop.gsub(/\s+$/, '')]
61
+ when (inside and match = scanner.scan(/\d+$/))
62
+ result << [:VALUE, match.to_i]
63
+ when (inside and match = scanner.scan(/[^\n\}]+/))
64
+ result << [:VALUE, match.gsub(/\s+$/, '')]
65
+ else
66
+ raise "Can't tokenize <#{scanner.peek(10)}>"
67
+ end
68
+ end
69
+
70
+ result << [false, false]
71
+ end
72
+
73
+ attr_accessor :token
74
+
75
+ def self.parse(string)
76
+ new.parse(string)
77
+ end
78
+
79
+ def parse(string)
80
+ @result = {}
81
+ @token = create_token(string)
82
+ do_parse
83
+ @result
84
+ end
85
+
86
+ def next_token
87
+ @token.shift
88
+ end
@@ -0,0 +1,3 @@
1
+ module NagiosParser
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,2 @@
1
+ require 'nagios_parser/object/parser'
2
+ require 'nagios_parser/status/parser'
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "nagios_parser/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "nagios_parser"
7
+ s.version = NagiosParser::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Bernd Ahlers"]
10
+ s.email = ["bernd@tuneafish.de"]
11
+ s.homepage = "http://rubygems.org/gems/nagios_parser"
12
+ s.summary = %q{parser lib for parsing Nagios status and config files}
13
+ s.description = %q{
14
+ The nagios_parser gem provides parsers for Nagios config
15
+ and status files.
16
+ }
17
+
18
+ #s.rubyforge_project = "nagios_parser"
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+
25
+ s.add_development_dependency "rake"
26
+ s.add_development_dependency "racc"
27
+ s.add_development_dependency "rspec"
28
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+ require 'nagios_parser/object/parser'
3
+
4
+ describe NagiosParser::Object::Parser do
5
+ let(:parser) { NagiosParser::Object::Parser.new }
6
+
7
+ describe ".parse" do
8
+ it "returns a hash of status types" do
9
+ data = parser.parse('define host { host_name foo }')
10
+ data['host'].first['host_name'].should == 'foo'
11
+ end
12
+ end
13
+
14
+ describe "#create_token" do
15
+ context "given a valid string" do
16
+ it "creates a valid token list" do
17
+ string = <<-RUBY
18
+ define host {
19
+ host_name foo.example.com
20
+ _plugin_path /usr/lib64/nagios/plugins
21
+ }
22
+ define service {
23
+ host_name foo.example.com
24
+ service_description SUPERD
25
+ }
26
+ RUBY
27
+
28
+ parser.create_token(string).should == [
29
+ [:DEFINE, nil],
30
+ [:TYPE, 'host'],
31
+ [:OPEN, nil],
32
+ [:KEY, 'host_name'],
33
+ [:VALUE, 'foo.example.com'],
34
+ [:KEY, '_plugin_path'],
35
+ [:VALUE, '/usr/lib64/nagios/plugins'],
36
+ [:CLOSE, nil],
37
+ [:DEFINE, nil],
38
+ [:TYPE, 'service'],
39
+ [:OPEN, nil],
40
+ [:KEY, 'host_name'],
41
+ [:VALUE, 'foo.example.com'],
42
+ [:KEY, 'service_description'],
43
+ [:VALUE, 'SUPERD'],
44
+ [:CLOSE, nil],
45
+ [false, false]
46
+ ]
47
+ end
48
+ end
49
+ end
50
+
51
+ describe "#next_token" do
52
+ it "returns shifts the next element off the token list" do
53
+ parser.token = [:one, :two, :three]
54
+ parser.next_token
55
+ parser.next_token.should == :two
56
+ end
57
+ end
58
+
59
+ describe "#parse" do
60
+ context "with a valid string" do
61
+ it "returns a hash of status types" do
62
+ string = <<-RUBY
63
+ define host {
64
+ host_name foo.example.com
65
+ notification_interval 40
66
+ }
67
+ RUBY
68
+
69
+ data = parser.parse(string)
70
+ data['host'].first['host_name'] == 'foo.example.com'
71
+ data['host'].first['notification_interval'] == 40
72
+ end
73
+ end
74
+
75
+ context "with an invalid status type" do
76
+ it "will raise an exception" do
77
+ expect {
78
+ parser.parse('FooBar { info test }')
79
+ }.to raise_error
80
+ end
81
+ end
82
+
83
+ context "with invalid status data" do
84
+ it "will raise an exception" do
85
+ expect {
86
+ parser.parse('define host { =test }')
87
+ }.to raise_error
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+ require 'nagios_parser/status/parser'
3
+
4
+ describe NagiosParser::Status::Parser do
5
+ let(:parser) { NagiosParser::Status::Parser.new }
6
+
7
+ describe ".parse" do
8
+ it "returns a hash of status types" do
9
+ data = parser.parse('info { version=3.2.0 }')
10
+ data['info'].first['version'].should == '3.2.0'
11
+ end
12
+ end
13
+
14
+ describe "#create_token" do
15
+ context "given a valid string" do
16
+ it "creates a valid token list" do
17
+ string = <<-RUBY
18
+ hoststatus {
19
+ bar=baz
20
+ hello = world
21
+ foo= bar
22
+ foo = bar baz hello world
23
+ eek = 1
24
+ }
25
+ info { version=3.2.0 }
26
+
27
+ programstatus {
28
+ last_command_check=1291408262
29
+ global_service_event_handler=
30
+ }
31
+ RUBY
32
+
33
+ parser.create_token(string).should == [
34
+ ['hoststatus', 'hoststatus'],
35
+ [:OPEN, nil],
36
+ [:KEY, 'bar'], [:VALUE, 'baz'],
37
+ [:KEY, 'hello'], [:VALUE, 'world'],
38
+ [:KEY, 'foo'], [:VALUE, 'bar'],
39
+ [:KEY, 'foo'], [:VALUE, 'bar baz hello world'],
40
+ [:KEY, 'eek'], [:VALUE, 1],
41
+ [:CLOSE, nil],
42
+ ['info', 'info'],
43
+ [:OPEN, nil],
44
+ [:KEY, 'version'], [:VALUE, '3.2.0'],
45
+ [:CLOSE, nil],
46
+ ['programstatus', 'programstatus'],
47
+ [:OPEN, nil],
48
+ [:KEY, 'last_command_check'], [:VALUE, 1291408262],
49
+ [:KEY, 'global_service_event_handler'],
50
+ [:CLOSE, nil],
51
+ [false, false]
52
+ ]
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "#next_token" do
58
+ it "returns shifts the next element off the token list" do
59
+ parser.token = [:one, :two, :three]
60
+ parser.next_token
61
+ parser.next_token.should == :two
62
+ end
63
+ end
64
+
65
+ describe "#parse" do
66
+ context "with a valid string" do
67
+ it "returns a hash of status types" do
68
+ string = <<-RUBY
69
+ hoststatus {
70
+ bar=baz
71
+ hello = world
72
+ version = 1
73
+ }
74
+ info { version=3.2.0 }
75
+ RUBY
76
+
77
+ data = parser.parse(string)
78
+ data['info'].first['version'].should == '3.2.0'
79
+ data['hoststatus'].first['bar'].should == 'baz'
80
+ data['hoststatus'].first['version'].should == 1
81
+ end
82
+ end
83
+
84
+ context "with an invalid status type" do
85
+ it "will raise an exception" do
86
+ expect {
87
+ parser.parse('FooBar { info=test }')
88
+ }.to raise_error
89
+ end
90
+ end
91
+
92
+ context "with invalid status data" do
93
+ it "will raise an exception" do
94
+ expect {
95
+ parser.parse('info { =test }')
96
+ }.to raise_error
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,8 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'rubygems'
4
+ require 'rspec'
5
+ require 'rspec/autorun'
6
+
7
+ RSpec.configure do |config|
8
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nagios_parser
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Bernd Ahlers
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-16 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rake
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: racc
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: rspec
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ description: "\n The nagios_parser gem provides parsers for Nagios config\n and status files.\n "
64
+ email:
65
+ - bernd@tuneafish.de
66
+ executables: []
67
+
68
+ extensions: []
69
+
70
+ extra_rdoc_files: []
71
+
72
+ files:
73
+ - .gitignore
74
+ - Gemfile
75
+ - LICENSE
76
+ - README.md
77
+ - Rakefile
78
+ - lib/nagios_parser.rb
79
+ - lib/nagios_parser/object/parser.rb
80
+ - lib/nagios_parser/object/parser.y
81
+ - lib/nagios_parser/status/parser.rb
82
+ - lib/nagios_parser/status/parser.y
83
+ - lib/nagios_parser/version.rb
84
+ - nagios_parser.gemspec
85
+ - spec/nagios_parser/object/parser_spec.rb
86
+ - spec/nagios_parser/status/parser_spec.rb
87
+ - spec/spec_helper.rb
88
+ has_rdoc: true
89
+ homepage: http://rubygems.org/gems/nagios_parser
90
+ licenses: []
91
+
92
+ post_install_message:
93
+ rdoc_options: []
94
+
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ hash: 3
112
+ segments:
113
+ - 0
114
+ version: "0"
115
+ requirements: []
116
+
117
+ rubyforge_project:
118
+ rubygems_version: 1.3.7
119
+ signing_key:
120
+ specification_version: 3
121
+ summary: parser lib for parsing Nagios status and config files
122
+ test_files: []
123
+