mirror of
https://github.com/inspec/inspec
synced 2024-11-24 05:33:17 +00:00
Merge pull request #1888 from chef/dr/nginx_parser
add the Nginx parser
This commit is contained in:
commit
87b3c1ad40
2 changed files with 158 additions and 0 deletions
74
lib/utils/nginx_parser.rb
Normal file
74
lib/utils/nginx_parser.rb
Normal file
|
@ -0,0 +1,74 @@
|
|||
# encoding: utf-8
|
||||
# author: Dominik Richter
|
||||
# author: Christoph Hartmann
|
||||
|
||||
require 'parslet'
|
||||
|
||||
class NginxParser < Parslet::Parser
|
||||
root :outermost
|
||||
# only designed for rabbitmq config files for now:
|
||||
rule(:outermost) { filler? >> exp.repeat }
|
||||
|
||||
rule(:filler?) { one_filler.repeat }
|
||||
rule(:one_filler) { match('\s+') | match["\n"] | comment }
|
||||
rule(:space) { match('\s+') }
|
||||
rule(:comment) { str('#') >> (match["\n\r"].absent? >> any).repeat }
|
||||
|
||||
rule(:exp) {
|
||||
section | assignment
|
||||
}
|
||||
rule(:assignment) {
|
||||
(identifier >> values.maybe.as(:args)).as(:assignment) >> str(';') >> filler?
|
||||
}
|
||||
|
||||
rule(:identifier) {
|
||||
(match('[a-zA-Z]') >> match('[a-zA-Z0-9_]').repeat).as(:identifier) >> space >> space.repeat
|
||||
}
|
||||
|
||||
rule(:value) {
|
||||
((match('[#;{]').absent? >> any) >> (
|
||||
str('\\') >> any | match('[#;{]|\s').absent? >> any
|
||||
).repeat).as(:value) >> space.repeat
|
||||
}
|
||||
rule(:values) {
|
||||
value.repeat >> space.maybe
|
||||
}
|
||||
|
||||
rule(:section) {
|
||||
identifier.as(:section) >> values.maybe.as(:args) >> str('{') >> filler? >> exp.repeat.as(:expressions) >> str('}') >> filler?
|
||||
}
|
||||
end
|
||||
|
||||
class NginxTransform < Parslet::Transform
|
||||
Group = Struct.new(:id, :args, :body)
|
||||
Exp = Struct.new(:key, :vals)
|
||||
|
||||
def self.assemble_binary(seq)
|
||||
b = ErlangBitstream.new
|
||||
seq.each { |i| b.add(i) }
|
||||
b.value
|
||||
end
|
||||
|
||||
rule(section: { identifier: simple(:x) }, args: subtree(:y), expressions: subtree(:z)) { Group.new(x.to_s, y, z) }
|
||||
rule(assignment: { identifier: simple(:x), args: subtree(:y) }) { Exp.new(x.to_s, y) }
|
||||
rule(value: simple(:x)) { x.to_s }
|
||||
end
|
||||
|
||||
class NginxConfig
|
||||
def self.parse(content)
|
||||
lex = NginxParser.new.parse(content)
|
||||
tree = NginxTransform.new.apply(lex)
|
||||
gtree = NginxTransform::Group.new(nil, '', tree)
|
||||
read_nginx_group(gtree)
|
||||
end
|
||||
|
||||
def self.read_nginx_group(t)
|
||||
agg_conf = Hash.new([])
|
||||
agg_conf['_'] = t.args unless t.args == ''
|
||||
|
||||
groups, conf = t.body.partition { |i| i.is_a? NginxTransform::Group }
|
||||
conf.each { |x| agg_conf[x.key] += [x.vals.join(' ')] }
|
||||
groups.each { |x| agg_conf[x.id] += [read_nginx_group(x)] }
|
||||
agg_conf
|
||||
end
|
||||
end
|
84
test/unit/utils/nginx_parser_test.rb
Normal file
84
test/unit/utils/nginx_parser_test.rb
Normal file
|
@ -0,0 +1,84 @@
|
|||
# encoding: utf-8
|
||||
# author: Dominik Richter
|
||||
# author: Christoph Hartmann
|
||||
|
||||
require 'helper'
|
||||
require 'utils/nginx_parser'
|
||||
|
||||
describe NginxParser do
|
||||
def parse(c)
|
||||
NginxParser.new.parse(c)
|
||||
end
|
||||
|
||||
def parsestr(c)
|
||||
parse(c).to_s
|
||||
end
|
||||
|
||||
def parse_file(f)
|
||||
parse(File.read(f))
|
||||
end
|
||||
|
||||
it 'parses an empty nginx file' do
|
||||
_(parsestr('')).must_equal ''
|
||||
end
|
||||
|
||||
it 'parses a file with a comment' do
|
||||
_(parsestr("# some nice comment")).must_equal "# some nice comment"
|
||||
end
|
||||
|
||||
it 'parses a simple assignment' do
|
||||
_(parsestr("assignment a;")).must_equal "[{:assignment=>{:identifier=>\"assignment\"@0, :args=>[{:value=>\"a\"@11}]}}]"
|
||||
end
|
||||
|
||||
it 'parses an empty group' do
|
||||
_(parsestr("group {}")).must_equal "[{:section=>{:identifier=>\"group\"@0}, :args=>\"\", :expressions=>[]}]"
|
||||
end
|
||||
|
||||
it 'parses a group with parameters' do
|
||||
_(parsestr("group a b {}")).must_equal "[{:section=>{:identifier=>\"group\"@0}, :args=>[{:value=>\"a\"@6}, {:value=>\"b\"@8}], :expressions=>[]}]"
|
||||
end
|
||||
|
||||
it 'parses a group with a body' do
|
||||
_(parsestr("group {\na b;\n}")).must_equal "[{:section=>{:identifier=>\"group\"@0}, :args=>\"\", :expressions=>[{:assignment=>{:identifier=>\"a\"@8, :args=>[{:value=>\"b\"@10}]}}]}]"
|
||||
end
|
||||
|
||||
it 'parses a group with arguments and a body' do
|
||||
_(parsestr("group c {\na b;\n}")).must_equal "[{:section=>{:identifier=>\"group\"@0}, :args=>[{:value=>\"c\"@6}], :expressions=>[{:assignment=>{:identifier=>\"a\"@10, :args=>[{:value=>\"b\"@12}]}}]}]"
|
||||
end
|
||||
|
||||
it 'parses nested groups' do
|
||||
_(parsestr("f {g {h {\n# comment\n}}}")).must_equal "[{:section=>{:identifier=>\"f\"@0}, :args=>\"\", :expressions=>[{:section=>{:identifier=>\"g\"@3}, :args=>\"\", :expressions=>[{:section=>{:identifier=>\"h\"@6}, :args=>\"\", :expressions=>[]}]}]}]"
|
||||
end
|
||||
end
|
||||
|
||||
describe NginxTransform do
|
||||
def parse(c)
|
||||
NginxTransform.new.apply(NginxParser.new.parse(c))
|
||||
end
|
||||
|
||||
it 'transforms and empty file' do
|
||||
_(parse('')).must_equal ''
|
||||
end
|
||||
|
||||
it 'transforms an assignment' do
|
||||
_(parse('a b;')).must_equal [NginxTransform::Exp.new('a', ['b'])]
|
||||
end
|
||||
|
||||
it 'transforms an empty group' do
|
||||
_(parse('group {}')).must_equal [NginxTransform::Group.new('group','',[])]
|
||||
end
|
||||
|
||||
it 'transforms a simple group' do
|
||||
_(parse("group a {\na b;\n}")).must_equal [NginxTransform::Group.new('group',['a'],[NginxTransform::Exp.new('a', ['b'])])]
|
||||
end
|
||||
|
||||
it 'transforms a deeply nested group' do
|
||||
_(parse("f { g { h {\na b;\n}}}")).must_equal [
|
||||
NginxTransform::Group.new('f', '', [
|
||||
NginxTransform::Group.new('g', '', [
|
||||
NginxTransform::Group.new('h', '', [NginxTransform::Exp.new('a', ['b'])])
|
||||
])
|
||||
])
|
||||
]
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue