mirror of https://github.com/yandex/gixy
Changed file reading logic. Parsers and auditor don't read files by itself, instead of this expect file descriptor or file content.
parent
625a25db46
commit
3c1437c816
|
@ -98,7 +98,7 @@ def main():
|
|||
_init_logger(args.debug)
|
||||
|
||||
path = os.path.expanduser(args.nginx_file)
|
||||
if not os.path.isfile(path):
|
||||
if path != '-' and not os.path.exists(path):
|
||||
sys.stderr.write('Please specify path to Nginx configuration.\n\n')
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
@ -150,7 +150,13 @@ def main():
|
|||
config.set_for(name, options)
|
||||
|
||||
with Gixy(config=config) as yoda:
|
||||
yoda.audit(path)
|
||||
if path == '-':
|
||||
with os.fdopen(sys.stdin.fileno(), 'r') as fdata:
|
||||
yoda.audit('<stdin>', fdata, is_stdin=True)
|
||||
else:
|
||||
with open(path, mode='r') as fdata:
|
||||
yoda.audit(path, fdata, is_stdin=False)
|
||||
|
||||
formatted = formatters()[config.output_format]().format(yoda)
|
||||
if args.output_file:
|
||||
with open(config.output_file, 'w') as f:
|
||||
|
|
|
@ -1,25 +1,32 @@
|
|||
import os
|
||||
import logging
|
||||
|
||||
import gixy
|
||||
from gixy.core.plugins_manager import PluginsManager
|
||||
from gixy.core.context import get_context, pop_context, push_context, purge_context
|
||||
from gixy.parser.nginx_parser import NginxParser
|
||||
from gixy.core.config import Config
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Manager(object):
|
||||
def __init__(self, config=None):
|
||||
self.root = None
|
||||
self.parser = None
|
||||
self.auditor = None
|
||||
self.config = config or Config()
|
||||
self.auditor = PluginsManager(config=self.config)
|
||||
self.stats = {gixy.severity.UNSPECIFIED: 0,
|
||||
gixy.severity.LOW: 0,
|
||||
gixy.severity.MEDIUM: 0,
|
||||
gixy.severity.HIGH: 0}
|
||||
|
||||
def audit(self, file_path):
|
||||
self.auditor = PluginsManager(config=self.config)
|
||||
self.parser = NginxParser(file_path, allow_includes=self.config.allow_includes)
|
||||
self.root = self.parser.parse(file_path)
|
||||
def audit(self, file_path, file_data, is_stdin=False):
|
||||
LOG.debug("Audit config file: {fname}".format(fname=file_path))
|
||||
parser = NginxParser(
|
||||
cwd=os.path.dirname(file_path) if not is_stdin else '',
|
||||
allow_includes=self.config.allow_includes)
|
||||
self.root = parser.parse(content=file_data.read(), path_info=file_path)
|
||||
|
||||
push_context(self.root)
|
||||
self._audit_recursive(self.root.children)
|
||||
|
||||
|
|
|
@ -12,26 +12,32 @@ LOG = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class NginxParser(object):
|
||||
def __init__(self, file_path, allow_includes=True):
|
||||
self.base_file_path = file_path
|
||||
self.cwd = os.path.dirname(file_path)
|
||||
def __init__(self, cwd='', allow_includes=True):
|
||||
self.cwd = cwd
|
||||
self.configs = {}
|
||||
self.is_dump = False
|
||||
self.allow_includes = allow_includes
|
||||
self.directives = {}
|
||||
self.parser = raw_parser.RawParser()
|
||||
self._init_directives()
|
||||
|
||||
def parse(self, file_path, root=None):
|
||||
LOG.debug("Parse file: {}".format(file_path))
|
||||
def parse_file(self, path, root=None):
|
||||
LOG.debug("Parse file: {}".format(path))
|
||||
content = open(path).read()
|
||||
return self.parse(content=content, root=root, path_info=path)
|
||||
|
||||
def parse(self, content, root=None, path_info=None):
|
||||
if not root:
|
||||
root = block.Root()
|
||||
|
||||
try:
|
||||
parser = raw_parser.RawParser()
|
||||
parsed = parser.parse(file_path)
|
||||
parsed = self.parser.parse(content)
|
||||
except ParseException as e:
|
||||
LOG.error('Failed to parse config "{file}": {error}'.format(file=file_path, error=str(e)))
|
||||
error_msg = 'char {char} (line:{line}, col:{col})'.format(char=e.loc, line=e.lineno, col=e.col)
|
||||
if path_info:
|
||||
LOG.error('Failed to parse config "{file}": {error}'.format(file=path_info, error=error_msg))
|
||||
else:
|
||||
LOG.error('Failed to parse config: {error}'.format(error=error_msg))
|
||||
return root
|
||||
|
||||
if len(parsed) and parsed[0].getName() == 'file_delimiter':
|
||||
|
@ -108,7 +114,7 @@ class NginxParser(object):
|
|||
for file_path in glob.iglob(path):
|
||||
include = block.IncludeBlock('include', [file_path])
|
||||
parent.append(include)
|
||||
self.parse(file_path, include)
|
||||
self.parse_file(file_path, include)
|
||||
|
||||
if not file_path:
|
||||
LOG.warning("File not found: {}".format(path))
|
||||
|
|
|
@ -3,7 +3,7 @@ from cached_property import cached_property
|
|||
|
||||
from pyparsing import (
|
||||
Literal, Suppress, White, Word, alphanums, Forward, Group, Optional, Combine,
|
||||
Keyword, OneOrMore, ZeroOrMore, Regex, QuotedString, nestedExpr)
|
||||
Keyword, OneOrMore, ZeroOrMore, Regex, QuotedString, nestedExpr, ParseResults)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -23,16 +23,15 @@ class RawParser(object):
|
|||
A class that parses nginx configuration with pyparsing
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._script = None
|
||||
|
||||
def parse(self, file_path):
|
||||
def parse(self, data):
|
||||
"""
|
||||
Returns the parsed tree.
|
||||
"""
|
||||
content = open(file_path).read()
|
||||
return self.script.parseString(content, parseAll=True)
|
||||
# return self.script.parseFile(file_path, parseAll=True)
|
||||
content = data.strip()
|
||||
if not content:
|
||||
return ParseResults()
|
||||
|
||||
return self.script.parseString(data, parseAll=True)
|
||||
|
||||
@cached_property
|
||||
def script(self):
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
from nose.tools import assert_equals, assert_is_instance, assert_is_not_none, assert_is_none, assert_true, assert_false
|
||||
import mock
|
||||
from six import StringIO
|
||||
from six.moves import builtins
|
||||
from gixy.parser.nginx_parser import NginxParser
|
||||
from gixy.directives.block import *
|
||||
|
||||
# TODO(buglloc): what about include block?
|
||||
|
||||
|
||||
def _get_parsed(config):
|
||||
with mock.patch('%s.open' % builtins.__name__) as mock_open:
|
||||
mock_open.return_value = StringIO(config)
|
||||
root = NginxParser('/foo/bar', allow_includes=False).parse('/foo/bar')
|
||||
return root.children[0]
|
||||
root = NginxParser(cwd='', allow_includes=False).parse(config)
|
||||
return root.children[0]
|
||||
|
||||
|
||||
def test_block():
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
from nose.tools import assert_equals, assert_is_instance, assert_false, assert_true
|
||||
import mock
|
||||
from six import StringIO
|
||||
from six.moves import builtins
|
||||
from gixy.parser.nginx_parser import NginxParser
|
||||
from gixy.directives.directive import *
|
||||
|
||||
|
||||
def _get_parsed(config):
|
||||
with mock.patch('%s.open' % builtins.__name__) as mock_open:
|
||||
mock_open.return_value = StringIO(config)
|
||||
return NginxParser('/foo/bar', allow_includes=False).parse('/foo/bar').children[0]
|
||||
root = NginxParser(cwd='', allow_includes=False).parse(config)
|
||||
return root.children[0]
|
||||
|
||||
|
||||
def test_directive():
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
from nose.tools import assert_is_instance, assert_equal
|
||||
import mock
|
||||
from six import StringIO
|
||||
from six.moves import builtins
|
||||
from gixy.parser.nginx_parser import NginxParser
|
||||
from gixy.directives.directive import *
|
||||
from gixy.directives.block import *
|
||||
|
||||
|
||||
def _parse(config):
|
||||
with mock.patch('%s.open' % builtins.__name__) as mock_open:
|
||||
mock_open.return_value = StringIO(config)
|
||||
return NginxParser('/foo/bar', allow_includes=False).parse('/foo/bar')
|
||||
return NginxParser(cwd='', allow_includes=False).parse(config)
|
||||
|
||||
|
||||
def test_directive():
|
||||
|
|
|
@ -497,8 +497,15 @@ add_header X-Blank-Comment blank;
|
|||
assert_config(config, expected)
|
||||
|
||||
|
||||
def test_empty_config():
|
||||
config = '''
|
||||
'''
|
||||
|
||||
expected = []
|
||||
|
||||
assert_config(config, expected)
|
||||
|
||||
|
||||
def assert_config(config, expected):
|
||||
with mock.patch('%s.open' % builtins.__name__) as mock_open:
|
||||
mock_open.return_value = StringIO(config)
|
||||
actual = RawParser().parse('/foo/bar')
|
||||
assert_equals(actual.asList(), expected)
|
||||
actual = RawParser().parse(config)
|
||||
assert_equals(actual.asList(), expected)
|
||||
|
|
|
@ -81,7 +81,7 @@ def yoda_provider(plugin, plugin_options=None):
|
|||
def check_configuration(plugin, config_path, test_config):
|
||||
plugin_options = parse_plugin_options(config_path)
|
||||
with yoda_provider(plugin, plugin_options) as yoda:
|
||||
yoda.audit(config_path)
|
||||
yoda.audit(config_path, open(config_path, mode='r'))
|
||||
results = RawFormatter().format(yoda)
|
||||
|
||||
assert_equals(len(results), 1, 'Should have one report')
|
||||
|
@ -102,7 +102,7 @@ def check_configuration(plugin, config_path, test_config):
|
|||
|
||||
def check_configuration_fp(plugin, config_path, test_config):
|
||||
with yoda_provider(plugin) as yoda:
|
||||
yoda.audit(config_path)
|
||||
yoda.audit(config_path, open(config_path, mode='r'))
|
||||
results = RawFormatter().format(yoda)
|
||||
|
||||
assert_equals(len(results), 0,
|
||||
|
|
Loading…
Reference in New Issue