From fb047b1267e63d8788e44fd7f3de80559c4c1f47 Mon Sep 17 00:00:00 2001 From: Christian Adams Date: Thu, 12 Mar 2020 17:45:52 -0400 Subject: [PATCH] Add unit tests for reconfiguring rsyslog & for test endpoint --- awx/conf/views.py | 3 +- .../tests/functional/api/test_settings.py | 5 + awx/main/tests/unit/api/test_logger_test.py | 94 +++++++++++++++++++ awx/main/utils/external_logging.py | 14 ++- tools/docker-compose/supervisor.conf | 4 - 5 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 awx/main/tests/unit/api/test_logger_test.py diff --git a/awx/conf/views.py b/awx/conf/views.py index 4b1f070d98..1f82009291 100644 --- a/awx/conf/views.py +++ b/awx/conf/views.py @@ -8,6 +8,7 @@ import sys import socket import os from urllib.parse import urlparse +from socket import SHUT_RDWR # Django from django.conf import settings @@ -194,7 +195,7 @@ class SettingLoggingTest(GenericAPIView): try: s.settimeout(.5) s.connect((hostname, int(port))) - s.shutdown(2) + s.shutdown(SHUT_RDWR) s.close() return Response(status=status.HTTP_202_ACCEPTED) except Exception as e: diff --git a/awx/main/tests/functional/api/test_settings.py b/awx/main/tests/functional/api/test_settings.py index 5c6cb16022..9bcd813aad 100644 --- a/awx/main/tests/functional/api/test_settings.py +++ b/awx/main/tests/functional/api/test_settings.py @@ -292,6 +292,11 @@ def test_logging_aggregrator_connection_test_with_masked_password(mocker, patch, create_settings = kwargs['custom_settings'] assert getattr(create_settings, 'LOG_AGGREGATOR_PASSWORD') == 'password123' + # Update these tests ^^ + # Test the `/api/v2/settings/logging/test` functionality + def test_logging_test(): + pass + @pytest.mark.django_db def test_logging_aggregrator_connection_test_invalid(mocker, get, post, admin): diff --git a/awx/main/tests/unit/api/test_logger_test.py b/awx/main/tests/unit/api/test_logger_test.py new file mode 100644 index 0000000000..616b2e4c25 --- /dev/null +++ b/awx/main/tests/unit/api/test_logger_test.py @@ -0,0 +1,94 @@ +import pytest + +from awx.main.utils.external_logging import construct_rsyslog_conf_template +from awx.conf import settings_registry + + +''' +# Example User Data +data_logstash = { + "LOG_AGGREGATOR_TYPE": "logstash", + "LOG_AGGREGATOR_HOST": "localhost", + "LOG_AGGREGATOR_PORT": 8080, + "LOG_AGGREGATOR_PROTOCOL": "tcp", + "LOG_AGGREGATOR_USERNAME": "logger", + "LOG_AGGREGATOR_PASSWORD": "mcstash" +} + +data_netcat = { + "LOG_AGGREGATOR_TYPE": "other", + "LOG_AGGREGATOR_HOST": "localhost", + "LOG_AGGREGATOR_PORT": 9000, + "LOG_AGGREGATOR_PROTOCOL": "udp", +} + +data_loggly = { + "LOG_AGGREGATOR_TYPE": "loggly", + "LOG_AGGREGATOR_HOST": "http://logs-01.loggly.com/inputs/1fd38090-2af1-4e1e-8d80-492899da0f71/tag/http/", + "LOG_AGGREGATOR_PORT": 8080, + "LOG_AGGREGATOR_PROTOCOL": "https" +} +''' + + +# Test reconfigure logging settings function +# name this whatever you want +@pytest.mark.parametrize( + 'enabled, type, host, port, protocol, expected_config', [ + (True, 'loggly', 'http://logs-01.loggly.com/inputs/1fd38090-2af1-4e1e-8d80-492899da0f71/tag/http/', None, 'https', + '$IncludeConfig /etc/rsyslog.conf\ninput(type="imuxsock" Socket="/var/run/rsyslog/rsyslog.sock" unlink="on")\ntemplate(name="awx" type="string" string="%msg%")\nmodule(load="omhttp")\naction(type="omhttp" server="logs-01.loggly.com" serverport="80" usehttps="off" skipverifyhost="off" action.resumeRetryCount="-1" template="awx" errorfile="/var/log/tower/external.err" healthchecktimeout="20000" restpath="inputs/1fd38090-2af1-4e1e-8d80-492899da0f71/tag/http/")'), + (True, 'other', 'localhost', 9000, 'udp', + '$IncludeConfig /etc/rsyslog.conf\ninput(type="imuxsock" Socket="/var/run/rsyslog/rsyslog.sock" unlink="on")\ntemplate(name="awx" type="string" string="%msg%")\naction(type="omfwd" target="localhost" port="9000" protocol="udp" action.resumeRetryCount="-1" template="awx")'), + (True, 'other', 'localhost', 9000, 'tcp', + '$IncludeConfig /etc/rsyslog.conf\ninput(type="imuxsock" Socket="/var/run/rsyslog/rsyslog.sock" unlink="on")\ntemplate(name="awx" type="string" string="%msg%")\naction(type="omfwd" target="localhost" port="9000" protocol="tcp" action.resumeRetryCount="-1" template="awx")'), + (False, 'loggly', 'http://logs-01.loggly.com/inputs/1fd38090-2af1-4e1e-8d80-492899da0f71/tag/http/', 8080, 'https', + '$IncludeConfig /etc/rsyslog.conf'), + (True, 'splunk', 'https://yoursplunk:8088/services/collector/event', None, None, + '''$IncludeConfig /etc/rsyslog.conf +input(type="imuxsock" Socket="/var/run/rsyslog/rsyslog.sock" unlink="on") +template(name="awx" type="string" string="%msg%") +module(load="omhttp") +action(type="omhttp" server="yoursplunk" serverport="8088" usehttps="on" skipverifyhost="off" action.resumeRetryCount="-1" template="awx" errorfile="/var/log/tower/external.err" healthchecktimeout="20000" restpath="services/collector/event")'''), + (True, 'splunk', 'https://yoursplunk/services/collector/event', 8088, None, + '''$IncludeConfig /etc/rsyslog.conf +input(type="imuxsock" Socket="/var/run/rsyslog/rsyslog.sock" unlink="on") +template(name="awx" type="string" string="%msg%") +module(load="omhttp") +action(type="omhttp" server="yoursplunk" serverport="8088" usehttps="on" skipverifyhost="off" action.resumeRetryCount="-1" template="awx" errorfile="/var/log/tower/external.err" healthchecktimeout="20000" restpath="services/collector/event")'''), + (True, 'splunk', 'https://yoursplunk/services/collector/event', 8088, 'https', + '''$IncludeConfig /etc/rsyslog.conf +input(type="imuxsock" Socket="/var/run/rsyslog/rsyslog.sock" unlink="on") +template(name="awx" type="string" string="%msg%") +module(load="omhttp") +action(type="omhttp" server="yoursplunk" serverport="8088" usehttps="on" skipverifyhost="off" action.resumeRetryCount="-1" template="awx" errorfile="/var/log/tower/external.err" healthchecktimeout="20000" restpath="services/collector/event")'''), + ] +) +def test_rsyslog_conf_template(enabled, type, host, port, protocol, expected_config): + + # Mock settings object + class MockSettings: + pass + mock_settings = MockSettings() + + # Pre-populate settings obj with defaults + for key in settings_registry.get_registered_settings(category_slug='logging'): + value = settings_registry.get_setting_field(key).get_default() + setattr(mock_settings, key, value) + + + # Set test settings + setattr(mock_settings, 'LOGGING_SOCK', '/var/run/rsyslog/rsyslog.sock') + setattr(mock_settings, 'LOG_AGGREGATOR_ENABLED', enabled) + setattr(mock_settings, 'LOG_AGGREGATOR_TYPE', type) + setattr(mock_settings, 'LOG_AGGREGATOR_HOST', host) + if port: + setattr(mock_settings, 'LOG_AGGREGATOR_PORT', port) + if protocol: + setattr(mock_settings, 'LOG_AGGREGATOR_PROTOCOL', protocol) + + # create rsyslog conf template + tmpl = construct_rsyslog_conf_template(mock_settings) + + # check validity of created template + assert tmpl in expected_config + diff --git a/awx/main/utils/external_logging.py b/awx/main/utils/external_logging.py index 4468634903..e54c50cbf9 100644 --- a/awx/main/utils/external_logging.py +++ b/awx/main/utils/external_logging.py @@ -5,14 +5,14 @@ from django.conf import settings from awx.main.utils.reload import supervisor_service_command -def reconfigure_rsyslog(): +def construct_rsyslog_conf_template(settings=settings): tmpl = '' parts = ['$IncludeConfig /etc/rsyslog.conf'] if settings.LOG_AGGREGATOR_ENABLED: host = getattr(settings, 'LOG_AGGREGATOR_HOST', '') port = getattr(settings, 'LOG_AGGREGATOR_PORT', '') protocol = getattr(settings, 'LOG_AGGREGATOR_PROTOCOL', '') - + import pdb; pdb.set_trace() if protocol.startswith('http'): scheme = 'https' # urlparse requires '//' to be provided if scheme is not specified @@ -23,12 +23,13 @@ def reconfigure_rsyslog(): host = parsed.hostname try: - port = parsed.port + if parsed.port: + port = parsed.port except ValueError: port = settings.LOG_AGGREGATOR_PORT parts.extend([ - 'input(type="imuxsock" Socket="/var/run/rsyslog/rsyslog.sock" unlink="on")', + 'input(type="imuxsock" Socket="' + settings.LOGGING_SOCK + '" unlink="on")', 'template(name="awx" type="string" string="%msg%")', ]) if protocol.startswith('http'): @@ -63,8 +64,11 @@ def reconfigure_rsyslog(): parts.append( f'action(type="omfwd" target="{host}" port="{port}" protocol="{protocol}" action.resumeRetryCount="-1" template="awx")' # noqa ) - tmpl = '\n'.join(parts) + return tmpl + +def reconfigure_rsyslog(): + tmpl = get_rsyslog_conf_template() with open('/var/lib/awx/rsyslog/rsyslog.conf', 'w') as f: f.write(tmpl + '\n') supervisor_service_command(command='restart', service='awx-rsyslogd') diff --git a/tools/docker-compose/supervisor.conf b/tools/docker-compose/supervisor.conf index 0b7fd029f8..a28a230da1 100644 --- a/tools/docker-compose/supervisor.conf +++ b/tools/docker-compose/supervisor.conf @@ -72,11 +72,7 @@ stdout_logfile=/dev/fd/1 stdout_logfile_maxbytes=0 [program:awx-rsyslogd] -<<<<<<< HEAD command = rsyslogd -n -i /var/run/rsyslog/rsyslog.pid -f /var/lib/awx/rsyslog/rsyslog.conf -======= -command = rsyslogd -n -i /var/run/tower/sockets/rsyslog.pid -f /var/lib/awx/rsyslog/rsyslog.conf ->>>>>>> 3a8bd7c40... Fix Logging settings "Test" button functionality autostart = true autorestart = true stopwaitsecs = 1