예제 #1
0
    def test_broken(self):
        config = NginxConfig(broken_config)
        config.full_parse()

        assert_that(config.tree, equal_to({}))
        # this would be has_length(1) but new parser cascades errors when error is 'expected "}"'
        assert_that(config.parser_errors, not_(empty()))
예제 #2
0
    def test_broken(self):
        config = NginxConfig(broken_config)
        config.full_parse()

        assert_that(
            config.tree,
            has_entries({
                'status':
                'failed',
                'errors':
                has_length(2),
                'config':
                contains(
                    has_entries({
                        'file':
                        '/amplify/test/fixtures/nginx/broken/nginx.conf',
                        'status':
                        'failed',
                        'errors':
                        contains(
                            has_entries({
                                'line':
                                9,
                                'error':
                                '"http" directive is not allowed here in /amplify/test/fixtures/nginx/broken/nginx.conf:9'
                            }),
                            has_entries({
                                'line':
                                11,
                                'error':
                                'unexpected end of file, expecting "}" in /amplify/test/fixtures/nginx/broken/nginx.conf:11'
                            }))
                    }))
            }))
예제 #3
0
    def test_parse_huge(self):
        config = NginxConfig(huge_config)
        config.full_parse()

        # error logs
        assert_that(config.error_logs, has_length(1))
        assert_that(config.error_logs, has_key('/var/log/nginx-error.log'))

        # access logs
        assert_that(config.access_logs, has_length(2))
        assert_that(config.access_logs, has_item('/var/log/default.log'))
        assert_that(config.access_logs, has_item('/var/log/pp.log'))
        assert_that(config.access_logs['/var/log/pp.log'], equal_to('main'))

        # log formats
        assert_that(config.log_formats, has_length(1))
        assert_that(config.log_formats, has_item('main'))
        assert_that(
            config.log_formats['main'],
            equal_to(
                '$remote_addr - $remote_user [$time_local] "$request" ' +
                '$status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"'
            )
        )

        # stub status url
        assert_that(config.stub_status_urls, has_length(2))
        assert_that(config.stub_status_urls[0], equal_to('127.0.0.1:80/nginx_status'))
예제 #4
0
    def test_parse_wildcard_dir(self):
        """
        Tests wild card directory handling.
        """
        config = NginxConfig(wildcard_directory_config)
        config.full_parse()

        assert_that(
            config.directory_map,
            has_entries({
                '/amplify/test/fixtures/nginx/wildcard_directory/data/www/test.domain.info/config/nginx/':
                has_entries({
                    'files':
                    has_key(
                        '/amplify/test/fixtures/nginx/wildcard_directory/data/www/test.domain.info/config/nginx/test.conf'
                    )
                }),
                '/amplify/test/fixtures/nginx/wildcard_directory/data/www/test.domain.other/config/nginx/':
                has_entries({
                    'files':
                    has_key(
                        '/amplify/test/fixtures/nginx/wildcard_directory/data/www/test.domain.other/config/nginx/foobar.conf'
                    )
                })
            }))
예제 #5
0
    def test_parse_huge(self):
        config = NginxConfig(huge_config)
        config.full_parse()

        # error logs
        assert_that(config.error_logs, has_length(1))
        assert_that(config.error_logs, has_key('/var/log/nginx-error.log'))

        # access logs
        assert_that(config.access_logs, has_length(2))
        assert_that(config.access_logs, has_item('/var/log/default.log'))
        assert_that(config.access_logs, has_item('/var/log/pp.log'))
        assert_that(config.access_logs['/var/log/pp.log'], equal_to('main'))

        # log formats
        assert_that(config.log_formats, has_length(1))
        assert_that(config.log_formats, has_item('main'))
        assert_that(
            config.log_formats['main'],
            equal_to(
                '$remote_addr - $remote_user [$time_local] "$request" ' +
                '$status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"'
            )
        )

        # stub status url
        assert_that(config.stub_status_urls, has_length(2))
        assert_that(config.stub_status_urls[0], equal_to('127.0.0.1:80/nginx_status'))
예제 #6
0
    def test_broken_includes(self):
        config = NginxConfig(huge_config)
        config.full_parse()

        assert_that(config.tree, has_entries({
            'status': 'failed',
            'errors': has_length(9),
            'config': contains(
                has_entries({
                    'file': '/amplify/test/fixtures/nginx/huge/nginx.conf',
                    'status': 'failed',
                    'errors': contains(
                        {'error': "[Errno 2] No such file or directory: '/amplify/test/fixtures/nginx/huge/mime.types2'", 'line': 13},
                        {'error': "[Errno 2] No such file or directory: '/amplify/test/fixtures/nginx/huge/dir.map'", 'line': 31},
                        {'error': "[Errno 2] No such file or directory: '/amplify/test/fixtures/nginx/huge/ec2-public-networks.conf'", 'line': 114},
                        {'error': "[Errno 2] No such file or directory: '/amplify/test/fixtures/nginx/huge/ec2-public-networks.conf'", 'line': 117},
                        {'error': "[Errno 2] No such file or directory: '/amplify/test/fixtures/nginx/huge/ec2-public-networks.conf'", 'line': 120},
                        {'error': "[Errno 2] No such file or directory: '/amplify/test/fixtures/nginx/huge/ec2-public-networks.conf'", 'line': 123},
                        {'error': "[Errno 2] No such file or directory: '/amplify/test/fixtures/nginx/huge/ec2-public-networks.conf'", 'line': 126},
                        {'error': "[Errno 2] No such file or directory: '/amplify/test/fixtures/nginx/huge/azure-public-networks.conf'", 'line': 129},
                        {'error': "[Errno 2] No such file or directory: '/amplify/test/fixtures/nginx/huge/gce-public-networks.conf'", 'line': 132},
                    )
                }),
                has_entries({
                    'file': '/amplify/test/fixtures/nginx/huge/mime.types',
                    'status': 'ok'
                })
            )
        }))

        # despite there being 8 errors, there are only 5 missing includes
        assert_that(config.parser_errors, has_length(5))
예제 #7
0
    def test_json(self):
        config = NginxConfig(json_config)
        config.full_parse()

        assert_that(config.log_formats, has_key('json'))
        assert_that(
            config.log_formats['json'],
            equal_to('{ "time_iso8601": "$time_iso8601", "browser": [{"modern_browser": "$modern_browser", '
                     '"ancient_browser": "$ancient_browser", "msie": "$msie"}], "core": [{"args": "$args", "arg": '
                     '{ "arg_example": "$arg_example"}, "body_bytes_sent": "$body_bytes_sent", "bytes_sent": '
                     '"$bytes_sent", "cookie": { "cookie_example": "$cookie_example" }, "connection": "$connection", '
                     '"connection_requests": "$connection_requests", "content_length": "$content_length", '
                     '"content_type": "$content_type", "document_root": "$document_root", "document_uri": '
                     '"$document_uri","host": "$host", "hostname": "$hostname", "http": { "http_example": '
                     '"$http_example" }, "https": "$https", "is_args": "$is_args", "limit_rate": "$limit_rate", '
                     '"msec": "$msec", "nginx_version": "$nginx_version", "pid": "$pid", "pipe": "$pipe", '
                     '"proxy_protocol_addr": "$proxy_protocol_addr", "query_string": "$query_string", "realpath_root": '
                     '"$realpath_root", "remote_addr": "$remote_addr", "remote_port": "$remote_port", "remote_user": '******'"$remote_user", "request": "$request", "request_body": "$request_body", "request_body_file": '
                     '"$request_body_file", "request_completion": "$request_completion", "request_filename": '
                     '"$request_filename", "request_length": "$request_length", "request_method": "$request_method", '
                     '"request_time": "$request_time", "request_uri": "$request_uri", "scheme": "$scheme", '
                     '"sent_http_": { "sent_http_example": "$sent_http_example" }, "server_addr": "$server_addr", '
                     '"server_name": "$server_name", "server_port": "$server_port", "server_protocol": '
                     '"$server_protocol", "status": "$status", "tcpinfo_rtt": "$tcpinfo_rtt", "tcpinfo_rttvar": '
                     '"$tcpinfo_rttvar", "tcpinfo_snd_cwnd": "$tcpinfo_snd_cwnd", "tcpinfo_rcv_space": '
                     '"$tcpinfo_rcv_space", "uri": "$uri" }]}')
        )
예제 #8
0
    def test_proxy_buffers_complex(self):
        config = NginxConfig(proxy_buffers_complex_config)
        config.full_parse()

        assert_that(config.subtree, has_item(
            has_entries({
                'directive': 'http',
                'block': has_items(
                    has_entries({'directive': 'proxy_buffering'}),
                    has_entries({'directive': 'proxy_buffers'}),
                    has_entries({
                        'directive': 'server',
                        'block': has_item(
                            has_entries({
                                'directive': 'location',
                                'args': ['/'],
                                'block': has_items(
                                    has_entries({'directive': 'proxy_pass'}),
                                    has_entries({'directive': 'proxy_buffering'}),
                                    has_entries({'directive': 'proxy_buffers'})
                                )
                            })
                        )
                    })
                )
            })
        ))

        assert_that(config.parser_errors, empty())
        assert_that(config.test_errors, empty())
예제 #9
0
    def test_json(self):
        config = NginxConfig(json_config)
        config.full_parse()

        assert_that(config.log_formats, has_key('json'))
        assert_that(
            config.log_formats['json'],
            equal_to('{ "time_iso8601": "$time_iso8601", "browser": [{"modern_browser": "$modern_browser", '
                     '"ancient_browser": "$ancient_browser", "msie": "$msie"}], "core": [{"args": "$args", "arg": '
                     '{ "arg_example": "$arg_example"}, "body_bytes_sent": "$body_bytes_sent", "bytes_sent": '
                     '"$bytes_sent", "cookie": { "cookie_example": "$cookie_example" }, "connection": "$connection", '
                     '"connection_requests": "$connection_requests", "content_length": "$content_length", '
                     '"content_type": "$content_type", "document_root": "$document_root", "document_uri": '
                     '"$document_uri","host": "$host", "hostname": "$hostname", "http": { "http_example": '
                     '"$http_example" }, "https": "$https", "is_args": "$is_args", "limit_rate": "$limit_rate", '
                     '"msec": "$msec", "nginx_version": "$nginx_version", "pid": "$pid", "pipe": "$pipe", '
                     '"proxy_protocol_addr": "$proxy_protocol_addr", "query_string": "$query_string", "realpath_root": '
                     '"$realpath_root", "remote_addr": "$remote_addr", "remote_port": "$remote_port", "remote_user": '******'"$remote_user", "request": "$request", "request_body": "$request_body", "request_body_file": '
                     '"$request_body_file", "request_completion": "$request_completion", "request_filename": '
                     '"$request_filename", "request_length": "$request_length", "request_method": "$request_method", '
                     '"request_time": "$request_time", "request_uri": "$request_uri", "scheme": "$scheme", '
                     '"sent_http_": { "sent_http_example": "$sent_http_example" }, "server_addr": "$server_addr", '
                     '"server_name": "$server_name", "server_port": "$server_port", "server_protocol": '
                     '"$server_protocol", "status": "$status", "tcpinfo_rtt": "$tcpinfo_rtt", "tcpinfo_rttvar": '
                     '"$tcpinfo_rttvar", "tcpinfo_snd_cwnd": "$tcpinfo_snd_cwnd", "tcpinfo_rcv_space": '
                     '"$tcpinfo_rcv_space", "uri": "$uri" }]}')
        )
예제 #10
0
    def test_parse_simple_exclude_combined(self):
        """Check that config.full_parse() obeys exclude_logs from app_config with combined ignore"""
        context.app_config['nginx']['exclude_logs'] = '/var/log/nginx/*.log'

        config = NginxConfig(simple_config)
        config.full_parse()

        del context.app_config['nginx']['exclude_logs']

        assert_that(config.error_logs, empty())
        assert_that(config.access_logs, empty())

        # log formats
        assert_that(config.log_formats, has_length(1))
        assert_that(config.log_formats, has_item('super_log_format'))
        assert_that(
            config.log_formats['super_log_format'],
            equal_to(
                '$remote_addr - $remote_user [$time_local] "$request" $status ' +
                '$body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" ' +
                'rt="$request_time" ua="$upstream_addr" us="$upstream_status" ' +
                'ut="$upstream_response_time" "$gzip_ratio"'
            )
        )

        # stub status urls
        assert_that(config.stub_status_urls, has_length(1))
        assert_that(config.stub_status_urls[0], equal_to('127.0.0.1:81/basic_status'))

        # status urls
        assert_that(config.plus_status_external_urls, has_length(1))
        assert_that(config.plus_status_external_urls[0], equal_to('127.0.0.1:81/plus_status'))

        assert_that(config.plus_status_internal_urls, has_length(1))
        assert_that(config.plus_status_internal_urls[0], equal_to('127.0.0.1:81/plus_status'))
예제 #11
0
    def test_parse_bad_access_and_error_log(self):
        """
        Test case for ignoring access_log and error_log edge cases.
        """
        config = NginxConfig(bad_log_directives_config)
        config.full_parse()

        # common structure
        assert_that(config.subtree, contains(
            has_entries({'directive': 'user'}),
            has_entries({'directive': 'worker_processes'}),
            has_entries({'directive': 'pid'}),
            has_entries({'directive': 'events'}),
            has_entries({'directive': 'http'})
        ))

        # http
        http = config.subtree[4]['block']
        assert_that(http, has_items(
            has_entries({'directive': 'access_log', 'args': ['']}),
            has_entries({'directive': 'error_log', 'args': ['/var/log/nginx/$host-error.log']})
        ))

        assert_that(config.access_logs, empty())
        assert_that(config.error_logs, empty())
예제 #12
0
    def test_regex_status_url(self):
        """
        Check that we could handle regex urls like

        location ~ /(nginx_status|status)
        location ~ ^/nginx_status$
        """
        config = NginxConfig(regex_status_config)
        config.full_parse()

        # check total amount of status urls
        assert_that(config.stub_status_urls, has_length(4))  # we have 4 valid locations in the regex_status/status.conf

        # check each location
        valid_urls_dict = {
            '1.1.1.1:80': [
                '1.1.1.1:80/nginx_status',
                '1.1.1.1:80/status',
            ],
            '1.1.1.1:81': ['1.1.1.1:81/nginx_status'],
            '1.1.1.1:82': [
                '1.1.1.1:82/status_weird_thing', '1.1.1.1:82/nginx_status_weird_thing',
                '1.1.1.1:82/status_weird_some', '1.1.1.1:82/nginx_status_weird_some'
            ],
            '1.1.1.1:84': ['1.1.1.1:84/valid_location'],
        }

        for url in config.stub_status_urls:
            address = url.split('/')[0]
            valid_urls = valid_urls_dict[address]
            assert_that(valid_urls, has_item(url))
예제 #13
0
    def test_regex_status_url(self):
        """
        Check that we could handle regex urls like

        location ~ /(nginx_status|status)
        location ~ ^/nginx_status$
        """
        config = NginxConfig(regex_status_config)
        config.full_parse()

        # check total amount of status urls
        assert_that(config.stub_status_urls, has_length(
            4))  # we have 4 valid locations in the regex_status/status.conf

        # check each location
        valid_urls_dict = {
            '1.1.1.1:80': [
                '1.1.1.1:80/nginx_status',
                '1.1.1.1:80/status',
            ],
            '1.1.1.1:81': ['1.1.1.1:81/nginx_status'],
            '1.1.1.1:82': [
                '1.1.1.1:82/status_weird_thing',
                '1.1.1.1:82/nginx_status_weird_thing',
                '1.1.1.1:82/status_weird_some',
                '1.1.1.1:82/nginx_status_weird_some'
            ],
            '1.1.1.1:84': ['1.1.1.1:84/valid_location'],
        }

        for url in config.stub_status_urls:
            address = url.split('/')[0]
            valid_urls = valid_urls_dict[address]
            assert_that(valid_urls, has_item(url))
예제 #14
0
    def test_parse_complex(self):
        config = NginxConfig(complex_config)
        config.full_parse()

        assert_that(config.error_logs, empty())
        assert_that(config.access_logs, empty())
        assert_that(config.log_formats, empty())
        assert_that(config.stub_status_urls, empty())
예제 #15
0
    def test_log_format_unicode_quote(self):
        config = NginxConfig(log_format_unicode_quote)
        config.full_parse()

        assert_that(config.log_formats, has_length(1))
        assert_that(config.log_formats, has_entries({
            'foo': 'site="$server_name" server="$host\xe2\x80\x9d uri="uri"'
        }))
예제 #16
0
    def test_parse_simple(self):
        config = NginxConfig(simple_config)
        config.full_parse()

        # error logs
        assert_that(config.error_logs, has_length(1))
        assert_that(config.error_logs, has_key('/var/log/nginx/error.log'))
        assert_that(config.error_logs.values(), only_contains(
            has_entries(
                log_level=instance_of(str),
                permissions=matches_regexp('[0-7]{4}'),
                readable=instance_of(bool)
            )
        ))

        # access logs
        assert_that(config.access_logs, has_length(2))
        assert_that(config.access_logs, has_item('/var/log/nginx/access.log'))
        assert_that(config.access_logs, has_item('/var/log/nginx/superaccess.log'))
        assert_that(config.access_logs['/var/log/nginx/access.log']['log_format'], equal_to('super_log_format'))
        assert_that(config.access_logs.values(), only_contains(
            has_entries(
                log_format=any_of(is_in(config.log_formats), none()),
                permissions=matches_regexp('[0-7]{4}'),
                readable=instance_of(bool)
            )
        ))

        # log formats
        assert_that(config.log_formats, has_length(1))
        assert_that(config.log_formats, has_item('super_log_format'))
        assert_that(
            config.log_formats['super_log_format'],
            equal_to(
                '$remote_addr - $remote_user [$time_local] "$request" $status ' +
                '$body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" ' +
                'rt="$request_time" ua="$upstream_addr" us="$upstream_status" ' +
                'ut="$upstream_response_time" "$gzip_ratio"'
            )
        )

        # stub status urls
        assert_that(config.stub_status_urls, has_length(1))
        assert_that(config.stub_status_urls[0], equal_to('127.0.0.1:81/basic_status'))

        # status urls
        assert_that(config.plus_status_external_urls, has_length(1))
        assert_that(config.plus_status_external_urls[0], equal_to('127.0.0.1:81/plus_status'))

        assert_that(config.plus_status_internal_urls, has_length(1))
        assert_that(config.plus_status_internal_urls[0], equal_to('127.0.0.1:81/plus_status'))

        # api urls
        assert_that(config.api_external_urls, has_length(1))
        assert_that(config.api_external_urls[0], equal_to('127.0.0.1:81/api'))

        assert_that(config.api_internal_urls, has_length(1))
        assert_that(config.api_internal_urls[0], equal_to('127.0.0.1:81/api'))
예제 #17
0
 def test_log_format_with_escape_parameter(self):
     """
     Tests that the optional "escape" parameter from log_format gets ignored
     """
     config = NginxConfig(log_format_escaped_json)
     config.full_parse()
     assert_that(config.log_formats, has_length(1))
     assert_that(config.log_formats, has_key('masked'))
     assert_that(config.log_formats['masked'], not_(starts_with('escape=')))
예제 #18
0
    def test_parse_simple_exclude_multiple(self):
        """Check that config.full_parse() obeys exclude_logs from app_config with multiple ignores"""
        context.app_config['nginx'][
            'exclude_logs'] = '/var/log/nginx/super*.log,error*'

        config = NginxConfig(simple_config)
        config.full_parse()

        del context.app_config['nginx']['exclude_logs']

        assert_that(config.error_logs, empty())

        assert_that(config.access_logs, has_length(1))
        assert_that(config.access_logs, has_item('/var/log/nginx/access.log'))
        assert_that(
            config.access_logs['/var/log/nginx/access.log']['log_format'],
            equal_to('super_log_format'))
        assert_that(
            config.access_logs.values(),
            only_contains(
                has_entries(log_format=any_of(is_in(config.log_formats),
                                              none()),
                            permissions=matches_regexp('[0-7]{4}'),
                            readable=instance_of(bool))))

        # log formats
        assert_that(config.log_formats, has_length(1))
        assert_that(config.log_formats, has_item('super_log_format'))
        assert_that(
            config.log_formats['super_log_format'],
            equal_to(
                '$remote_addr - $remote_user [$time_local] "$request" $status '
                +
                '$body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" '
                +
                'rt="$request_time" ua="$upstream_addr" us="$upstream_status" '
                + 'ut="$upstream_response_time" "$gzip_ratio"'))

        # stub status urls
        assert_that(config.stub_status_urls, has_length(2))
        assert_that(config.stub_status_urls,
                    has_item('http://127.0.0.1:81/basic_status'))
        assert_that(config.stub_status_urls,
                    has_item('https://127.0.0.1:443/basic_status'))

        # status urls
        assert_that(config.plus_status_external_urls, has_length(2))
        assert_that(config.plus_status_external_urls,
                    has_item('http://127.0.0.1:81/plus_status'))
        assert_that(config.plus_status_external_urls,
                    has_item('https://127.0.0.1:443/plus_status'))

        assert_that(config.plus_status_internal_urls, has_length(2))
        assert_that(config.plus_status_internal_urls,
                    has_item('http://127.0.0.1:81/plus_status'))
        assert_that(config.plus_status_internal_urls,
                    has_item('https://127.0.0.1:443/plus_status'))
예제 #19
0
    def test_status_urls(self):
        """
        Tests that statuses are found correctly
        """
        config = NginxConfig(status_urls)
        config.full_parse()

        assert_that(config, has_property('stub_status_urls', ['http://127.0.0.1:80/', 'http://127.0.0.1:80/nginx_status']))
        assert_that(config, has_property('plus_status_external_urls', ['http://www.example.com:80/status']))
        assert_that(config, has_property('plus_status_internal_urls', ['http://127.0.0.1:80/status']))
예제 #20
0
    def test_ssl(self):
        config = NginxConfig(ssl_simple_config)
        config.full_parse()
        config.run_ssl_analysis()

        ssl_certificates = config.ssl_certificates
        assert_that(ssl_certificates, has_length(1))

        # check contents
        assert_that(ssl_certificates.keys()[0], ends_with('certs.d/example.com.crt'))
        assert_that(ssl_certificates.values()[0], has_item('names'))
예제 #21
0
    def test_parse_tabbed_config(self):
        config = NginxConfig(tabs_config)
        config.full_parse()

        assert_that(config.log_formats, has_key('main'))
        assert_that(
            config.log_formats['main'],
            equal_to('"$time_local"\t"$remote_addr"\t"$http_host"\t"$request"\t'
                     '"$status"\t"$body_bytes_sent\t"$http_referer"\t'
                     '"$http_user_agent"\t"$http_x_forwarded_for"')
        )
예제 #22
0
    def test_parse_tabbed_config(self):
        config = NginxConfig(tabs_config)
        config.full_parse()

        assert_that(config.log_formats, has_key('main'))
        assert_that(
            config.log_formats['main'],
            equal_to(
                '"$time_local"\t"$remote_addr"\t"$http_host"\t"$request"\t'
                '"$status"\t"$body_bytes_sent\t"$http_referer"\t'
                '"$http_user_agent"\t"$http_x_forwarded_for"'))
예제 #23
0
    def test_proxy_buffers_simple(self):
        config = NginxConfig(proxy_buffers_simple_config)
        config.full_parse()

        assert_that(config.tree, has_key('http'))

        http_bucket = config.tree['http'][0]
        assert_that(http_bucket, has_key('proxy_buffering'))
        assert_that(http_bucket, has_key('proxy_buffers'))

        assert_that(config.parser_errors, empty())
        assert_that(config.test_errors, empty())
예제 #24
0
    def test_proxy_buffers_simple(self):
        config = NginxConfig(proxy_buffers_simple_config)
        config.full_parse()

        assert_that(config.tree, has_key('http'))

        http_bucket = config.tree['http'][0]
        assert_that(http_bucket, has_key('proxy_buffering'))
        assert_that(http_bucket, has_key('proxy_buffers'))

        assert_that(config.parser_errors, has_length(0))
        assert_that(config.test_errors, has_length(0))
예제 #25
0
    def test_fastcgi(self):
        config = NginxConfig(fastcgi_config)
        config.full_parse()

        assert_that(config.tree, has_key('http'))

        http_bucket = config.tree['http'][0]
        server_bucket = http_bucket['server'][0][0]  # fastcgi server tree
        location = server_bucket['location']['~ \\.php$'][0]  # fastcgi pass location tree

        assert_that(location, has_key('fastcgi_pass'))
        assert_that(location, has_key('fastcgi_param'))
        assert_that(location['fastcgi_param'], has_length(17))
예제 #26
0
    def test_fastcgi(self):
        config = NginxConfig(fastcgi_config)
        config.full_parse()

        assert_that(config.tree, has_key('http'))

        http_bucket = config.tree['http'][0]
        server_bucket = http_bucket['server'][0][0]  # fastcgi server tree
        location = server_bucket['location']['~ \\.php$'][0]  # fastcgi pass location tree

        assert_that(location, has_key('fastcgi_pass'))
        assert_that(location, has_key('fastcgi_param'))
        assert_that(location['fastcgi_param'], has_length(17))
예제 #27
0
    def test_parse_complex(self):
        config = NginxConfig(complex_config)
        config.full_parse()

        context.log.info(config.index)
        context.log.info(config.tree)
        context.log.info(config.files)
        context.log.info(config.checksum())

        assert_that(config.error_logs, empty())
        assert_that(config.access_logs, empty())
        assert_that(config.log_formats, empty())
        assert_that(config.stub_status_urls, empty())
예제 #28
0
    def test_parse_huge(self):
        config = NginxConfig(huge_config)
        config.full_parse()

        # error logs
        assert_that(config.error_logs, has_length(1))
        assert_that(config.error_logs, has_key('/var/log/nginx-error.log'))
        assert_that(config.error_logs.values(), only_contains(
            has_entries(
                log_level=is_in(ERROR_LOG_LEVELS),
                permissions=matches_regexp('[0-7]{4}'),
                readable=instance_of(bool)
            )
        ))

        # access logs
        assert_that(config.access_logs, has_length(6))
        assert_that(config.access_logs, has_item('/var/log/default.log'))
        assert_that(config.access_logs, has_item('/var/log/pp.log'))
        assert_that(config.access_logs['/var/log/pp.log']['log_format'], equal_to('main'))
        assert_that(config.access_logs.values(), only_contains(
            any_of(
                has_entries(
                    log_format=any_of(is_in(config.log_formats), none()),
                    permissions=matches_regexp('[0-7]{4}'),
                    readable=instance_of(bool)
                ),
                all_of(
                    has_length(1),
                    has_entries(
                        log_format=any_of(is_in(config.log_formats), none())
                    )
                )  # syslog will not have permissions or readable values
            )
        ))

        # log formats
        assert_that(config.log_formats, has_length(1))
        assert_that(config.log_formats, has_item('main'))
        assert_that(
            config.log_formats['main'],
            equal_to(
                '$remote_addr - $remote_user [$time_local] "$request" ' +
                '$status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"'
            )
        )

        # stub status url
        assert_that(config.stub_status_urls, has_length(2))
        assert_that(config.stub_status_urls[0], equal_to('http://127.0.0.1:80/nginx_status'))
예제 #29
0
    def test_parse_tabbed_config(self):
        config = NginxConfig(tabs_config)
        config.full_parse()

        # common structure
        assert_that(
            config.subtree,
            contains(has_entries({'directive': 'user'}),
                     has_entries({'directive': 'worker_processes'}),
                     has_entries({'directive': 'error_log'}),
                     has_entries({'directive': 'pid'}),
                     has_entries({'directive': 'events'}),
                     has_entries({'directive': 'http'})))

        http = config.subtree[5]['block']
        assert_that(
            http,
            contains(
                has_entries({'directive': 'charset'}),
                has_entries({'directive': 'log_format'}),
                has_entries({'directive': 'access_log'}),
                has_entries({'directive': 'proxy_cache_path'}),
                has_entries({'directive': 'sendfile'}),
                has_entries({'directive': 'keepalive_timeout'}),
                has_entries({'directive': 'gzip'}),
                has_entries({'directive': 'gzip_types'}),
                has_entries({'directive': 'root'}),
                has_entries({'directive': 'server'}),
                has_entries({'directive': 'server'}),
                has_entries({'directive': 'upstream'}),
                has_entries({'directive': 'server'}),
                has_entries({'directive': 'server'}),
            ))

        log_format_args = http[1]['args']
        assert_that(log_format_args[0], equal_to('main'))
        assert_that(
            log_format_args[1],
            equal_to(
                '"$time_local"\\t"$remote_addr"\\t"$http_host"\\t"$request"\\t'
                '"$status"\\t"$body_bytes_sent\\t"$http_referer"\\t'
                '"$http_user_agent"\\t"$http_x_forwarded_for"'))

        assert_that(
            config.log_formats['main'],
            equal_to(
                '"$time_local"\t"$remote_addr"\t"$http_host"\t"$request"\t'
                '"$status"\t"$body_bytes_sent\t"$http_referer"\t'
                '"$http_user_agent"\t"$http_x_forwarded_for"'))
예제 #30
0
    def test_exclude_ssl(self):
        config = NginxConfig(ssl_simple_config)

        # also check that existing certs get cleared on subsequent parse
        config.full_parse()
        config.run_ssl_analysis()

        ssl_certificates = config.ssl_certificates
        assert_that(ssl_certificates, has_length(1))

        config.full_parse(include_ssl_certs=False)
        config.run_ssl_analysis()

        ssl_certificates = config.ssl_certificates
        assert_that(ssl_certificates, has_length(0))
예제 #31
0
    def test_proxy_buffers_simple(self):
        config = NginxConfig(proxy_buffers_simple_config)
        config.full_parse()

        assert_that(config.subtree, has_item(
            has_entries({
                'directive': 'http',
                'block': has_items(
                    has_entries({'directive': 'proxy_buffering'}),
                    has_entries({'directive': 'proxy_buffers'})
                )
            })
        ))

        assert_that(config.parser_errors, empty())
        assert_that(config.test_errors, empty())
예제 #32
0
    def test_proxy_buffers_complex(self):
        config = NginxConfig(proxy_buffers_complex_config)
        config.full_parse()

        assert_that(config.tree, has_key('http'))

        http_bucket = config.tree['http'][0]
        assert_that(http_bucket, has_key('proxy_buffering'))
        assert_that(http_bucket, has_key('proxy_buffers'))

        location_bucket = config.tree['http'][0]['server'][0][0]['location']['/'][0]
        assert_that(location_bucket, has_key('proxy_buffering'))
        assert_that(location_bucket, has_key('proxy_buffers'))

        assert_that(config.parser_errors, has_length(0))
        assert_that(config.test_errors, has_length(0))
예제 #33
0
    def test_proxy_buffers_complex(self):
        config = NginxConfig(proxy_buffers_complex_config)
        config.full_parse()

        assert_that(config.tree, has_key('http'))

        http_bucket = config.tree['http'][0]
        assert_that(http_bucket, has_key('proxy_buffering'))
        assert_that(http_bucket, has_key('proxy_buffers'))

        location_bucket = config.tree['http'][0]['server'][0][0]['location']['/'][0]
        assert_that(location_bucket, has_key('proxy_buffering'))
        assert_that(location_bucket, has_key('proxy_buffers'))

        assert_that(config.parser_errors, has_length(0))
        assert_that(config.test_errors, has_length(0))
예제 #34
0
    def __getitem__(self, ident):
        # if the config does not exist, create it
        filename, prefix, bin_path = ident
        if ident not in self._configs:
            self._configs[ident] = NginxConfig(filename=filename, prefix=prefix, binary=bin_path)

        return self._configs[ident]
예제 #35
0
    def test_permissions_and_mtime_affect_checksum(self):
        """
        Check that changing permissions or mtime affect checksum
        """
        config = NginxConfig(simple_config)
        config.full_parse()
        old_checksum = config.checksum()

        os.system('touch %s' % (os.getcwd() + '/test/fixtures/nginx/simple/conf.d/'))
        config.full_parse()
        new_checksum = config.checksum()
        assert_that(new_checksum, not_(equal_to(old_checksum)))
예제 #36
0
    def test_parse_simple(self):
        config = NginxConfig(simple_config)
        config.full_parse()

        # error logs
        assert_that(config.error_logs, has_length(1))
        assert_that(config.error_logs, has_key('/var/log/nginx/error.log'))

        # access logs
        assert_that(config.access_logs, has_length(2))
        assert_that(config.access_logs, has_item('/var/log/nginx/access.log'))
        assert_that(config.access_logs,
                    has_item('/var/log/nginx/superaccess.log'))
        assert_that(config.access_logs['/var/log/nginx/access.log'],
                    equal_to('super_log_format'))

        # log formats
        assert_that(config.log_formats, has_length(1))
        assert_that(config.log_formats, has_item('super_log_format'))
        assert_that(
            config.log_formats['super_log_format'],
            equal_to(
                '$remote_addr - $remote_user [$time_local] "$request" $status '
                +
                '$body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" '
                +
                'rt="$request_time" ua="$upstream_addr" us="$upstream_status" '
                + 'ut="$upstream_response_time" "$gzip_ratio"'))

        # stub status urls
        assert_that(config.stub_status_urls, has_length(1))
        assert_that(config.stub_status_urls[0],
                    equal_to('127.0.0.1:81/basic_status'))

        # status urls
        assert_that(config.plus_status_external_urls, has_length(1))
        assert_that(config.plus_status_external_urls[0],
                    equal_to('127.0.0.1:81/plus_status'))

        assert_that(config.plus_status_internal_urls, has_length(1))
        assert_that(config.plus_status_internal_urls[0],
                    equal_to('127.0.0.1:81/plus_status'))
예제 #37
0
    def test_parse_complex(self):
        config = NginxConfig(complex_config)
        config.full_parse()

        context.log.info(config.index)
        context.log.info(config.tree)
        context.log.info(config.files)
        context.log.info(config.checksum())

        # error logs
        assert_that(config.error_logs, has_length(0))

        # access logs
        assert_that(config.access_logs, has_length(0))

        # log formats
        assert_that(config.log_formats, has_length(0))

        # stub status url
        assert_that(config.stub_status_urls, has_length(0))
예제 #38
0
    def test_parse_complex(self):
        config = NginxConfig(complex_config)
        config.full_parse()

        context.log.info(config.index)
        context.log.info(config.tree)
        context.log.info(config.files)
        context.log.info(config.checksum())

        # error logs
        assert_that(config.error_logs, has_length(0))

        # access logs
        assert_that(config.access_logs, has_length(0))

        # log formats
        assert_that(config.log_formats, has_length(0))

        # stub status url
        assert_that(config.stub_status_urls, has_length(0))
예제 #39
0
    def test_log_format_string_concat(self):
        config = NginxConfig(log_format_string_concat)
        config.full_parse()

        expected = (
            '$remote_addr - $remote_user [$time_local] "$request" '
            '$status $body_bytes_sent "$http_referer" '
            '"$http_user_agent" "$http_x_forwarded_for" '
            '"$host" sn="$server_name" '
            'rt=$request_time '
            'ua="$upstream_addr" us="$upstream_status" '
            'ut="$upstream_response_time" ul="$upstream_response_length" '
            'cs=$upstream_cache_status'
        )

        assert_that(config.log_formats, has_length(2))
        assert_that(config.log_formats, has_entries({
            'without_newlines': expected,
            'with_newlines': expected
        }))
예제 #40
0
    def test_parse_wildcard_dir(self):
        """
        Tests wild card directory handling.
        """
        config = NginxConfig(wildcard_directory_config)
        config.full_parse()

        assert_that(
            config.directory_map,
            has_key(
                '/amplify/test/fixtures/nginx/wildcard_directory/data/www/test.domain.info/config/nginx/'
            )
        )
        files = config.directory_map[
            '/amplify/test/fixtures/nginx/wildcard_directory/data/www/test.domain.info/config/nginx/'
        ]['files']
        assert_that(
            files,
            has_key('/amplify/test/fixtures/nginx/wildcard_directory/data/www/test.domain.info/config/nginx/test.conf')
        )
예제 #41
0
    def test_parse_simple_exclude_multiple(self):
        """Check that config.full_parse() obeys exclude_logs from app_config with multiple ignores"""
        context.app_config['nginx']['exclude_logs'] = '/var/log/nginx/super*.log,error*'

        config = NginxConfig(simple_config)
        config.full_parse()

        del context.app_config['nginx']['exclude_logs']

        # error logs
        assert_that(config.error_logs, has_length(0))

        # access logs
        assert_that(config.access_logs, has_length(1))
        assert_that(config.access_logs, has_item('/var/log/nginx/access.log'))
        assert_that(config.access_logs['/var/log/nginx/access.log'], equal_to('super_log_format'))

        # log formats
        assert_that(config.log_formats, has_length(1))
        assert_that(config.log_formats, has_item('super_log_format'))
        assert_that(
            config.log_formats['super_log_format'],
            equal_to(
                '$remote_addr - $remote_user [$time_local] "$request" $status ' +
                '$body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" ' +
                'rt="$request_time" ua="$upstream_addr" us="$upstream_status" ' +
                'ut="$upstream_response_time" "$gzip_ratio"'
            )
        )

        # stub status urls
        assert_that(config.stub_status_urls, has_length(1))
        assert_that(config.stub_status_urls[0], equal_to('127.0.0.1:81/basic_status'))

        # status urls
        assert_that(config.plus_status_external_urls, has_length(1))
        assert_that(config.plus_status_external_urls[0], equal_to('127.0.0.1:81/plus_status'))

        assert_that(config.plus_status_internal_urls, has_length(1))
        assert_that(config.plus_status_internal_urls[0], equal_to('127.0.0.1:81/plus_status'))
예제 #42
0
    def test_permissions_and_mtime_affect_checksum(self):
        """
        Check that changing permissions or mtime affect checksum
        """
        config = NginxConfig(simple_config)
        config.full_parse()
        old_checksum = config.checksum()

        os.system('touch %s' % (os.getcwd() + '/test/fixtures/nginx/simple/conf.d/'))
        config.full_parse()
        new_checksum = config.checksum()
        assert_that(new_checksum, not_(equal_to(old_checksum)))
예제 #43
0
    def test_parse_simple(self):
        config = NginxConfig(simple_config)
        config.full_parse()

        # error logs
        assert_that(config.error_logs, has_length(1))
        assert_that(config.error_logs, has_key('/var/log/nginx/error.log'))

        # access logs
        assert_that(config.access_logs, has_length(2))
        assert_that(config.access_logs, has_item('/var/log/nginx/access.log'))
        assert_that(config.access_logs, has_item('/var/log/nginx/superaccess.log'))
        assert_that(config.access_logs['/var/log/nginx/access.log'], equal_to('super_log_format'))

        # log formats
        assert_that(config.log_formats, has_length(1))
        assert_that(config.log_formats, has_item('super_log_format'))
        assert_that(
            config.log_formats['super_log_format'],
            equal_to(
                '$remote_addr - $remote_user [$time_local] "$request" $status ' +
                '$body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" ' +
                'rt="$request_time" ua="$upstream_addr" us="$upstream_status" ' +
                'ut="$upstream_response_time" "$gzip_ratio"'
            )
        )

        # stub status urls
        assert_that(config.stub_status_urls, has_length(1))
        assert_that(config.stub_status_urls[0], equal_to('127.0.0.1:81/basic_status'))

        # status urls
        assert_that(config.plus_status_external_urls, has_length(1))
        assert_that(config.plus_status_external_urls[0], equal_to('127.0.0.1:81/plus_status'))

        assert_that(config.plus_status_internal_urls, has_length(1))
        assert_that(config.plus_status_internal_urls[0], equal_to('127.0.0.1:81/plus_status'))
예제 #44
0
    def __init__(self, **kwargs):
        super(CommonNginxObject, self).__init__(**kwargs)

        # Have to override intervals here because new container sub objects.
        self.intervals = context.app_config['containers'].get('nginx', {}).get('poll_intervals', {'default': 10})

        self.root_uuid = self.data.get(
            'root_uuid') or context.objects.root_object.uuid if context.objects.root_object else None
        self.local_id_cache = self.data['local_id']  # Assigned by manager
        self.pid = self.data['pid']
        self.version = self.data['version']
        self.workers = self.data['workers']
        self.prefix = self.data['prefix']
        self.bin_path = self.data['bin_path']
        self.conf_path = self.data['conf_path']

        default_config = context.app_config['containers']['nginx']

        self.upload_config = self.data.get('upload_config') or default_config.get('upload_config', False)
        self.run_config_test = self.data.get('run_test') or default_config.get('run_test', False)
        self.upload_ssl = self.data.get('upload_ssl') or default_config.get('upload_ssl', False)
        self.filters = []

        # filters
        for raw_filter in self.data.get('filters') or []:
            self.filters.append(Filter(**raw_filter))

        self.config = NginxConfig(self.conf_path, prefix=self.prefix)
        self.config.full_parse()

        self.plus_status_external_url, self.plus_status_internal_url = self.get_alive_plus_status_urls()
        self.plus_status_enabled = True if (self.plus_status_external_url or self.plus_status_internal_url) else False

        self.stub_status_url = self.get_alive_stub_status_url()
        self.stub_status_enabled = True if self.stub_status_url else False

        self.processes = []
예제 #45
0
    def collect(self):
        try:
            config = NginxConfig(
                self.object.conf_path,
                binary=self.object.bin_path,
                prefix=self.object.prefix
            )

            # check if config is changed (changes are: new files/certs, new mtimes)
            config_files, config_dirs = config.collect_structure(include_ssl_certs=self.object.upload_ssl)
            if config_files == self.previous_files and config_dirs == self.previous_directories:
                return

            # parse config tree
            config.full_parse()

            # Send event for parsing nginx config.
            # Use config.parser.filename to account for default value defined in NginxConfigParser.
            self.object.eventd.event(
                level=INFO,
                message='nginx config parsed, read from %s' % config.filename,
            )
            for error in config.parser_errors:
                self.object.eventd.event(level=WARNING, message=error)

            # run ssl checks
            if self.object.upload_ssl:
                config.run_ssl_analysis()
            else:
                context.log.info('ssl analysis skipped due to users settings')

            # run upload
            checksum = config.checksum()
            if self.object.upload_config:
                self.upload(config, checksum)

            if self.previous_checksum:
                # config changed, so we need to restart the object
                self.object.need_restart = True
            else:
                # otherwise run test
                if self.object.run_config_test and config.total_size() < 20*1024*1024:  # 20 MB
                    run_time = config.run_test()

                    # send event for testing nginx config
                    if config.test_errors:
                        self.object.eventd.event(level=WARNING, message='nginx config test failed')
                    else:
                        self.object.eventd.event(level=INFO, message='nginx config tested ok')

                    for error in config.test_errors:
                        self.object.eventd.event(level=CRITICAL, message=error)

                    # stop -t if it took too long
                    if run_time > context.app_config['containers']['nginx']['max_test_duration']:
                        context.app_config['containers']['nginx']['run_test'] = False
                        context.app_config.mark_unchangeable('run_test')
                        self.object.eventd.event(
                            level=WARNING,
                            message='%s -t -c %s took %s seconds, disabled until agent restart' % (
                                config.binary, config.filename, run_time
                            )
                        )
                        self.object.run_config_test = False

            self.previous_checksum = checksum
            self.previous_files = copy.copy(config_files)
            self.previous_directories = copy.copy(config_dirs)
        except Exception as e:
            exception_name = e.__class__.__name__
            context.log.error('failed to collect due to %s' % exception_name)
            context.log.debug('additional info:', exc_info=True)

            self.object.eventd.event(
                level=INFO,
                message='nginx config parser failed, path %s' % self.object.conf_path,
                onetime=True
            )
예제 #46
0
    def __init__(self, **kwargs):
        super(NginxObject, self).__init__(**kwargs)

        self.root_uuid = self.data.get('root_uuid') or context.objects.root_object.uuid if context.objects.root_object else None
        self.local_id_cache = self.data['local_id']  # Assigned by manager
        self.pid = self.data['pid']
        self.version = self.data['version']
        self.workers = self.data['workers']
        self.prefix = self.data['prefix']
        self.bin_path = self.data['bin_path']
        self.conf_path = self.data['conf_path']

        default_config = context.app_config['containers'][self.type]

        self.upload_config = self.data.get('upload_config') or default_config.get('upload_config', False)
        self.run_config_test = self.data.get('run_test') or default_config.get('run_test', False)
        self.upload_ssl = self.data.get('upload_ssl') or default_config.get('upload_ssl', False)

        self.config = NginxConfig(self.conf_path, prefix=self.prefix)
        self.config.full_parse()

        self.plus_status_external_url, self.plus_status_internal_url = self.get_alive_plus_status_urls()
        self.plus_status_enabled = True if (self.plus_status_external_url or self.plus_status_internal_url) else False

        self.stub_status_url = self.get_alive_stub_status_url()
        self.stub_status_enabled = True if self.stub_status_url else False

        self.processes = []
        self.filters = []

        # filters
        for raw_filter in self.data.get('filters') or []:
            self.filters.append(Filter(**raw_filter))

        # meta
        meta_collector_class = NginxCommonMetaCollector
        if host.os_name() == 'linux':
            if host.linux_name() in ('ubuntu', 'debian'):
                meta_collector_class = NginxDebianMetaCollector
            elif host.linux_name() in ('centos',):
                meta_collector_class = NginxCentosMetaCollector

        self.collectors = [
            meta_collector_class(
                object=self, interval=self.intervals['meta']
            ),
            NginxMetricsCollector(
                object=self, interval=self.intervals['metrics']
            ),
            NginxConfigCollector(
                object=self, interval=self.intervals['configs'],
            )
        ]

        # access logs
        for log_filename, format_name in self.config.access_logs.iteritems():
            log_format = self.config.log_formats.get(format_name)
            try:
                self.collectors.append(
                    NginxAccessLogsCollector(
                        object=self,
                        interval=self.intervals['logs'],
                        filename=log_filename,
                        log_format=log_format,
                    )
                )

                # Send access log discovery event.
                self.eventd.event(level=INFO, message='nginx access log %s found' % log_filename)
            except IOError as e:
                exception_name = e.__class__.__name__
                context.log.error(
                    'failed to start reading log %s due to %s (maybe has no rights?)' %
                    (log_filename, exception_name)
                )
                context.log.debug('additional info:', exc_info=True)

        # error logs
        for log_filename, log_level in self.config.error_logs.iteritems():
            try:
                self.collectors.append(
                    NginxErrorLogsCollector(
                        object=self,
                        interval=self.intervals['logs'],
                        filename=log_filename,
                        level=log_level
                    )
                )

                # Send error log discovery event.
                self.eventd.event(level=INFO, message='nginx error log %s found' % log_filename)
            except IOError as e:
                exception_name = e.__class__.__name__
                context.log.error(
                    'failed to start reading log %s due to %s (maybe has no rights?)' %
                    (log_filename, exception_name)
                )
                context.log.debug('additional info:', exc_info=True)
예제 #47
0
class NginxObject(AbstractObject):
    type = 'nginx'

    def __init__(self, **kwargs):
        super(NginxObject, self).__init__(**kwargs)

        self.root_uuid = self.data.get('root_uuid') or context.objects.root_object.uuid if context.objects.root_object else None
        self.local_id_cache = self.data['local_id']  # Assigned by manager
        self.pid = self.data['pid']
        self.version = self.data['version']
        self.workers = self.data['workers']
        self.prefix = self.data['prefix']
        self.bin_path = self.data['bin_path']
        self.conf_path = self.data['conf_path']

        default_config = context.app_config['containers'][self.type]

        self.upload_config = self.data.get('upload_config') or default_config.get('upload_config', False)
        self.run_config_test = self.data.get('run_test') or default_config.get('run_test', False)
        self.upload_ssl = self.data.get('upload_ssl') or default_config.get('upload_ssl', False)

        self.config = NginxConfig(self.conf_path, prefix=self.prefix)
        self.config.full_parse()

        self.plus_status_external_url, self.plus_status_internal_url = self.get_alive_plus_status_urls()
        self.plus_status_enabled = True if (self.plus_status_external_url or self.plus_status_internal_url) else False

        self.stub_status_url = self.get_alive_stub_status_url()
        self.stub_status_enabled = True if self.stub_status_url else False

        self.processes = []
        self.filters = []

        # filters
        for raw_filter in self.data.get('filters') or []:
            self.filters.append(Filter(**raw_filter))

        # meta
        meta_collector_class = NginxCommonMetaCollector
        if host.os_name() == 'linux':
            if host.linux_name() in ('ubuntu', 'debian'):
                meta_collector_class = NginxDebianMetaCollector
            elif host.linux_name() in ('centos',):
                meta_collector_class = NginxCentosMetaCollector

        self.collectors = [
            meta_collector_class(
                object=self, interval=self.intervals['meta']
            ),
            NginxMetricsCollector(
                object=self, interval=self.intervals['metrics']
            ),
            NginxConfigCollector(
                object=self, interval=self.intervals['configs'],
            )
        ]

        # access logs
        for log_filename, format_name in self.config.access_logs.iteritems():
            log_format = self.config.log_formats.get(format_name)
            try:
                self.collectors.append(
                    NginxAccessLogsCollector(
                        object=self,
                        interval=self.intervals['logs'],
                        filename=log_filename,
                        log_format=log_format,
                    )
                )

                # Send access log discovery event.
                self.eventd.event(level=INFO, message='nginx access log %s found' % log_filename)
            except IOError as e:
                exception_name = e.__class__.__name__
                context.log.error(
                    'failed to start reading log %s due to %s (maybe has no rights?)' %
                    (log_filename, exception_name)
                )
                context.log.debug('additional info:', exc_info=True)

        # error logs
        for log_filename, log_level in self.config.error_logs.iteritems():
            try:
                self.collectors.append(
                    NginxErrorLogsCollector(
                        object=self,
                        interval=self.intervals['logs'],
                        filename=log_filename,
                        level=log_level
                    )
                )

                # Send error log discovery event.
                self.eventd.event(level=INFO, message='nginx error log %s found' % log_filename)
            except IOError as e:
                exception_name = e.__class__.__name__
                context.log.error(
                    'failed to start reading log %s due to %s (maybe has no rights?)' %
                    (log_filename, exception_name)
                )
                context.log.debug('additional info:', exc_info=True)

    @property
    def definition(self):
        return {'type': self.type, 'local_id': self.local_id, 'root_uuid': self.root_uuid}

    def get_alive_stub_status_url(self):
        """
        Tries to get alive stub_status url
        Records some events about it
        :return:
        """
        urls_to_check = self.config.stub_status_urls

        if 'stub_status' in context.app_config.get('nginx', {}):
            predefined_uri = context.app_config['nginx']['stub_status']
            urls_to_check.append(http.resolve_uri(predefined_uri))

        stub_status_url = self.__get_alive_status(urls_to_check)
        if stub_status_url:
            # Send stub detected event
            self.eventd.event(
                level=INFO,
                message='nginx stub_status detected, %s' % stub_status_url
            )
        else:
            self.eventd.event(
                level=INFO,
                message='nginx stub_status not found in nginx config'
            )
        return stub_status_url

    def get_alive_plus_status_urls(self):
        """
        Tries to get alive plus urls
        There are two types of plus status urls: internal and external
        - internal are for the agent and usually they have the localhost ip in address
        - external are for the browsers and usually they have a normal server name

        Returns a tuple of str or Nones - (external_url, internal_url)

        Even if external status url is not responding (cannot be accesible from the host)
        we should return it to show in our UI

        :return: (str or None, str or None)
        """
        internal_urls = self.config.plus_status_internal_urls
        external_urls = self.config.plus_status_external_urls

        if 'plus_status' in context.app_config.get('nginx', {}):
            predefined_uri = context.app_config['nginx']['plus_status']
            internal_urls.append(http.resolve_uri(predefined_uri))

        internal_status_url = self.__get_alive_status(internal_urls, json=True)
        if internal_status_url:
            self.eventd.event(
                level=INFO,
                message='nginx internal plus_status detected, %s' % internal_status_url
            )

        external_status_url = self.__get_alive_status(external_urls, json=True)
        if len(self.config.plus_status_external_urls) > 0:
            if not external_status_url:
                external_status_url = 'http://%s' % self.config.plus_status_external_urls[0]

            self.eventd.event(
                level=INFO,
                message='nginx external plus_status detected, %s' % external_status_url
            )

        return external_status_url, internal_status_url

    def __get_alive_status(self, url_list, json=False):
        """
        Tries to find alive status url
        Returns first alive url or None if all founded urls are not responding

        :param url_list: [] of urls
        :param json: bool - will try to encode json if True
        :return: None or str
        """
        for url in url_list:
            for proto in ('http://', 'https://'):
                full_url = '%s%s' % (proto, url) if not url.startswith('http') else url
                try:
                    status_response = context.http_client.get(full_url, timeout=0.5, json=json, log=False)
                    if status_response:
                        if json or 'Active connections' in status_response:
                            return full_url
                    else:
                        context.log.debug('bad response from stub/plus status url %s' % full_url)
                except:
                    context.log.debug('bad response from stub/plus status url %s' % full_url)
        return None
예제 #48
0
    def test_broken(self):
        config = NginxConfig(broken_config)
        config.full_parse()

        assert_that(config.tree, equal_to({}))
        assert_that(config.parser_errors, has_length(1))
예제 #49
0
    def test_broken_includes(self):
        config = NginxConfig(huge_config)
        config.full_parse()

        assert_that(config.tree, not_(equal_to({})))
        assert_that(config.parser_errors, has_length(5))  # 5 missing includes
예제 #50
0
if __name__ == '__main__':
    if not options.config:
        parser.print_help()
        sys.exit(1)

    if options.config.startswith('~'):
        filename = options.config.replace('~', os.path.expanduser('~'))
    elif not options.config.startswith('/'):
        filename = os.getcwd() + '/' + options.config
    else:
        filename = options.config

    start_time = time.time()

    cfg = NginxConfig(filename=filename)
    print_args = dict(indent=4, sort_keys=True) if options.pretty else dict()

    if not options.light:
        cfg.full_parse()

        print('\033[32mConfig tree for %s\033[0m' % filename)
        print(json.dumps(cfg.tree, **print_args))

        print('\n\033[32mConfig index for %s\033[0m' % filename)
        print(json.dumps(cfg.index, **print_args))

        print('\n\033[32mConfig files for %s\033[0m' % filename)
        print(json.dumps(cfg.files, **print_args))

        print('\n\033[32mStub/plus status %s\033[0m' % filename)