Commit a48041d0 authored by Łukasz Nowak's avatar Łukasz Nowak Committed by Łukasz Nowak

caddy-frontend: Add error reporting to slave requester

Each slave rejected by the frontend will report back detailed information
to slave requester in key request-error-list being [json_list_of_found_errors]
parent 44b3fe29
...@@ -26,7 +26,7 @@ md5sum = 750e2b1c922bf14511a3bc8a42468b1b ...@@ -26,7 +26,7 @@ md5sum = 750e2b1c922bf14511a3bc8a42468b1b
[template-apache-replicate] [template-apache-replicate]
filename = instance-apache-replicate.cfg.in filename = instance-apache-replicate.cfg.in
md5sum = aaac56847a966ec4f155cba10570bb3c md5sum = 1576859772052bcb85ff2b5a7b786410
[template-slave-list] [template-slave-list]
filename = templates/apache-custom-slave-list.cfg.in filename = templates/apache-custom-slave-list.cfg.in
...@@ -38,7 +38,7 @@ md5sum = 54ae95597a126ae552c3a913ddf29e5e ...@@ -38,7 +38,7 @@ md5sum = 54ae95597a126ae552c3a913ddf29e5e
[template-replicate-publish-slave-information] [template-replicate-publish-slave-information]
filename = templates/replicate-publish-slave-information.cfg.in filename = templates/replicate-publish-slave-information.cfg.in
md5sum = 6a308c29b54d53cfd82ae23ba77a35dd md5sum = 01efde8febafcff6dde2ebb43e75a9e4
[template-caddy-frontend-configuration] [template-caddy-frontend-configuration]
filename = templates/Caddyfile.in filename = templates/Caddyfile.in
......
...@@ -194,6 +194,11 @@ replicate = ${dynamic-publish-slave-information:rendered} ...@@ -194,6 +194,11 @@ replicate = ${dynamic-publish-slave-information:rendered}
custom-personal = ${dynamic-publish-slave-information:rendered} custom-personal = ${dynamic-publish-slave-information:rendered}
custom-group = ${dynamic-publish-slave-information:rendered} custom-group = ${dynamic-publish-slave-information:rendered}
[rejected-slave-information]
{% for slave_id, rejected_list in rejected_slave_dict.iteritems() %}
{{ slave_id }} = {{ dumps(json_module.dumps(rejected_list)) }}
{% endfor %}
[slave-information] [slave-information]
{% for frontend_section in frontend_section_list %} {% for frontend_section in frontend_section_list %}
{{ frontend_section }} = {{ "${%s:connection-slave-instance-information-list}" % frontend_section }} {{ frontend_section }} = {{ "${%s:connection-slave-instance-information-list}" % frontend_section }}
...@@ -206,6 +211,7 @@ filename = dynamic-publish-slave-information.cfg ...@@ -206,6 +211,7 @@ filename = dynamic-publish-slave-information.cfg
extensions = jinja2.ext.do extensions = jinja2.ext.do
extra-context = extra-context =
section slave_information slave-information section slave_information slave-information
section rejected_slave_information rejected-slave-information
[monitor-conf-parameters] [monitor-conf-parameters]
monitor-url-list += monitor-url-list +=
......
...@@ -29,6 +29,10 @@ ...@@ -29,6 +29,10 @@
"url": { "url": {
"description": "Default URL provided", "description": "Default URL provided",
"type": "string" "type": "string"
},
"request-error-list": {
"description": "In case if slave has been rejected by master or has error in the request, the list contains information about each problem",
"type": "string"
} }
}, },
"type": "object" "type": "object"
......
...@@ -27,6 +27,13 @@ ...@@ -27,6 +27,13 @@
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
{% for slave_reference, rejected_info_list in rejected_slave_information.iteritems() %}
{% if slave_reference not in slave_information_dict %}
{% do slave_information_dict.__setitem__(slave_reference, {}) %}
{% endif %}
{% do slave_information_dict[slave_reference].__setitem__('request-error-list', rejected_info_list) %}
{% endfor %}
# Publish information for each slave # Publish information for each slave
{% for slave_reference, slave_information in slave_information_dict.iteritems() %} {% for slave_reference, slave_information in slave_information_dict.iteritems() %}
{% set publish_section_title = 'publish-%s' % slave_reference %} {% set publish_section_title = 'publish-%s' % slave_reference %}
...@@ -34,9 +41,12 @@ ...@@ -34,9 +41,12 @@
[{{ publish_section_title }}] [{{ publish_section_title }}]
recipe = slapos.cookbook:publish recipe = slapos.cookbook:publish
-slave-reference = {{ slave_reference }} -slave-reference = {{ slave_reference }}
log-access-url = {{ json_module.dumps(slave_information.pop('log-access-urls', 1000)) }} {% set log_access_url = slave_information.pop('log-access-urls', None) %}
{% if log_access_url %}
log-access-url = {{ dumps(json_module.dumps(log_access_url)) }}
{% endif %}
{% for key, value in slave_information.iteritems() %} {% for key, value in slave_information.iteritems() %}
{{ key }} = {{ value }} {{ key }} = {{ dumps(value) }}
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
...@@ -45,4 +55,4 @@ extends = {{ common_profile }} ...@@ -45,4 +55,4 @@ extends = {{ common_profile }}
parts = parts =
{% for part in part_list %} {% for part in part_list %}
{{ ' %s' % part }} {{ ' %s' % part }}
{% endfor %} {% endfor %}
\ No newline at end of file
...@@ -2069,7 +2069,11 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s { ...@@ -2069,7 +2069,11 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s {
def test_apache_custom_http_s_rejected(self): def test_apache_custom_http_s_rejected(self):
parameter_dict = self.slave_connection_parameter_dict_dict[ parameter_dict = self.slave_connection_parameter_dict_dict[
'apache_custom_http_s-rejected'] 'apache_custom_http_s-rejected']
self.assertEqual({}, parameter_dict) self.assertEqual(
{
'request-error-list': '["slave not authorised"]'
},
parameter_dict)
slave_configuration_file_list = glob.glob(os.path.join( slave_configuration_file_list = glob.glob(os.path.join(
self.instance_path, '*', 'etc', '*slave-conf.d', '*.conf')) self.instance_path, '*', 'etc', '*slave-conf.d', '*.conf'))
# no configuration file contains provided custom http # no configuration file contains provided custom http
...@@ -2143,7 +2147,11 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s { ...@@ -2143,7 +2147,11 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s {
def test_caddy_custom_http_s_rejected(self): def test_caddy_custom_http_s_rejected(self):
parameter_dict = self.slave_connection_parameter_dict_dict[ parameter_dict = self.slave_connection_parameter_dict_dict[
'caddy_custom_http_s-rejected'] 'caddy_custom_http_s-rejected']
self.assertEqual({}, parameter_dict) self.assertEqual(
{
'request-error-list': '["slave not authorised"]'
},
parameter_dict)
slave_configuration_file_list = glob.glob(os.path.join( slave_configuration_file_list = glob.glob(os.path.join(
self.instance_path, '*', 'etc', '*slave-conf.d', '*.conf')) self.instance_path, '*', 'etc', '*slave-conf.d', '*.conf'))
# no configuration file contains provided custom http # no configuration file contains provided custom http
...@@ -2680,14 +2688,22 @@ class TestMalformedBackenUrlSlave(SlaveHttpFrontendTestCase, ...@@ -2680,14 +2688,22 @@ class TestMalformedBackenUrlSlave(SlaveHttpFrontendTestCase,
parameter_dict = self.slave_connection_parameter_dict_dict[ parameter_dict = self.slave_connection_parameter_dict_dict[
'url'].copy() 'url'].copy()
self.assertEqual( self.assertEqual(
parameter_dict, {} parameter_dict,
{
'request-error-list': '["slave url \\"https://[fd46::c2ae]:!py!'
'u\'123123\'\\" invalid"]'
}
) )
def test_https_url(self): def test_https_url(self):
parameter_dict = self.slave_connection_parameter_dict_dict[ parameter_dict = self.slave_connection_parameter_dict_dict[
'https-url'].copy() 'https-url'].copy()
self.assertEqual( self.assertEqual(
parameter_dict, {} parameter_dict,
{
'request-error-list': '["slave https-url \\"https://[fd46::c2ae]:'
'!py!u\'123123\'\\" invalid"]'
}
) )
...@@ -3048,7 +3064,11 @@ https://www.google.com {}""", ...@@ -3048,7 +3064,11 @@ https://www.google.com {}""",
'custom_domain-unsafe'] 'custom_domain-unsafe']
self.assertEqual( self.assertEqual(
parameter_dict, parameter_dict,
{} {
'request-error-list':
'["custom_domain \'${section:option} afterspace\\\\nafternewline\' '
'invalid"]'
}
) )
def test_server_alias_unsafe(self): def test_server_alias_unsafe(self):
...@@ -3056,7 +3076,11 @@ https://www.google.com {}""", ...@@ -3056,7 +3076,11 @@ https://www.google.com {}""",
'server-alias-unsafe'] 'server-alias-unsafe']
self.assertEqual( self.assertEqual(
parameter_dict, parameter_dict,
{} {
'request-error-list':
'["server-alias \'${section:option}\' not valid", "server-alias '
'\'afterspace\' not valid"]'
}
) )
def test_virtualhostroot_http_port_unsafe(self): def test_virtualhostroot_http_port_unsafe(self):
...@@ -3239,7 +3263,7 @@ https://www.google.com {}""", ...@@ -3239,7 +3263,7 @@ https://www.google.com {}""",
'ssl_key-ssl_crt-unsafe'] 'ssl_key-ssl_crt-unsafe']
self.assertEqual( self.assertEqual(
parameter_dict, parameter_dict,
{} {'request-error-list': '["slave ssl_key and ssl_crt does not match"]'}
) )
def test_caddy_custom_http_s_reject(self): def test_caddy_custom_http_s_reject(self):
...@@ -3247,7 +3271,11 @@ https://www.google.com {}""", ...@@ -3247,7 +3271,11 @@ https://www.google.com {}""",
'caddy_custom_http_s-reject'] 'caddy_custom_http_s-reject']
self.assertEqual( self.assertEqual(
parameter_dict, parameter_dict,
{} {
'request-error-list':
'["slave caddy_custom_http configuration invalid", '
'"slave caddy_custom_https configuration invalid"]'
}
) )
...@@ -3299,16 +3327,28 @@ class TestDuplicateSiteKeyProtection(SlaveHttpFrontendTestCase, TestDataMixin): ...@@ -3299,16 +3327,28 @@ class TestDuplicateSiteKeyProtection(SlaveHttpFrontendTestCase, TestDataMixin):
'rejected-slave-amount': '3', 'rejected-slave-amount': '3',
'slave-amount': '4', 'slave-amount': '4',
'rejected-slave-dict': 'rejected-slave-dict':
'{"_site_4": ["custom_domain clashes", "server-alias ' '{"_site_4": ["custom_domain \'duplicate.example.com\' clashes", '
'\'duplicate.example.com\' clashes"], "_site_1": ' '"server-alias \'duplicate.example.com\' clashes"], "_site_1": '
'["custom_domain clashes"], "_site_3": ["server-alias ' '["custom_domain \'duplicate.example.com\' clashes"], "_site_3": '
'\'duplicate.example.com\' clashes"]}'} '["server-alias \'duplicate.example.com\' clashes"]}'
}
self.assertEqual( self.assertEqual(
expected_parameter_dict, expected_parameter_dict,
parameter_dict parameter_dict
) )
def test_site_1(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'site_1']
self.assertEqual(
parameter_dict,
{
'request-error-list':
'["custom_domain \'duplicate.example.com\' clashes"]'
}
)
def test_site_2(self): def test_site_2(self):
parameter_dict = self.slave_connection_parameter_dict_dict[ parameter_dict = self.slave_connection_parameter_dict_dict[
'site_2'] 'site_2']
...@@ -3324,3 +3364,26 @@ class TestDuplicateSiteKeyProtection(SlaveHttpFrontendTestCase, TestDataMixin): ...@@ -3324,3 +3364,26 @@ class TestDuplicateSiteKeyProtection(SlaveHttpFrontendTestCase, TestDataMixin):
'public-ipv4': LOCAL_IPV4, 'public-ipv4': LOCAL_IPV4,
} }
) )
def test_site_3(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'site_3']
self.assertEqual(
parameter_dict,
{
'request-error-list':
'["server-alias \'duplicate.example.com\' clashes"]'
}
)
def test_site_4(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'site_4']
self.assertEqual(
parameter_dict,
{
'request-error-list':
'["custom_domain \'duplicate.example.com\' clashes", "server-alias '
'\'duplicate.example.com\' clashes"]'
}
)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment