nagios_parser 1.0.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.
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
+