{% if slap_software_type in software_type %} [jinja2-template-base] recipe = slapos.recipe.template:jinja2 rendered = ${buildout:directory}/${:filename} extra-context = context = import json_module json raw common_profile {{ common_profile }} ${:extra-context} {% set popen = functools_module.partial(subprocess_module.Popen, stdout=subprocess_module.PIPE, stderr=subprocess_module.STDOUT, stdin=subprocess_module.PIPE) %} {% set part_list = [] %} {% set single_type_key = 'single-' %} {% if slap_software_type == "replicate" %} {% set frontend_type = slapparameter_dict.pop('-frontend-type', 'single-default') %} {% elif slap_software_type in ['default', 'RootSoftwareInstance'] %} {% set frontend_type = "%s%s" % (single_type_key, 'custom-personal') %} {% else %} {% set frontend_type = "%s%s" % (single_type_key, slap_software_type) %} {% endif %} {% set frontend_quantity = slapparameter_dict.pop('-frontend-quantity', '1') | int %} {% set slave_list_name = 'extra_slave_instance_list' %} {% set frontend_list = [] %} {% set frontend_section_list = [] %} {% set request_dict = {} %} {% set namebase = 'caddy-frontend' %} # XXX Dirty hack, not possible to define default value before {% set sla_computer_caddy_1_key = '-sla-1-computer_guid' %} {% if not sla_computer_caddy_1_key in slapparameter_dict %} {% do slapparameter_dict.__setitem__(sla_computer_caddy_1_key, '${slap-connection:computer-id}') %} {% endif %} # Here we request individually each frontend. # The presence of sla parameters is checked and added if found {% for i in range(1, frontend_quantity + 1) %} {% set frontend_name = "%s-%s" % (namebase, i) %} {% set request_section_title = 'request-%s' % frontend_name %} {% set sla_key = "-sla-%s-" % i %} {% set sla_key_length = sla_key | length %} {% set sla_dict = {} %} {% set config_key = "-frontend-config-%s-" % i %} {% set config_key_length = config_key | length %} {% set config_dict = {} %} {% for key in slapparameter_dict.keys() %} {% if key.startswith(sla_key) %} {% do sla_dict.__setitem__(key[sla_key_length:], slapparameter_dict.pop(key)) %} # We check for specific configuration regarding the frontend {% elif key.startswith(config_key) %} {% do config_dict.__setitem__(key[config_key_length:], slapparameter_dict.pop(key)) %} {% endif %} {% endfor %} {% do frontend_list.append(frontend_name) %} {% do frontend_section_list.append(request_section_title) %} {% do part_list.append(request_section_title) %} # Filling request dict for slave {% set state_key = "-frontend-%s-state" % i %} {% do request_dict.__setitem__(request_section_title, { 'config': config_dict, 'name': frontend_name, 'sla': sla_dict, 'state': slapparameter_dict.pop(state_key, None) }) %} {% endfor %} {% set authorized_slave_string_list = slapparameter_dict.pop('-frontend-authorized-slave-string', '').split() %} {% set authorized_slave_list = [] %} {% set rejected_slave_dict = {} %} {% set used_host_list = [] %} {% set unauthorized_message = 'slave not authorized' %} {% for slave in slave_instance_list %} {% set slave_error_list = [] %} {% set slave_server_alias_unclashed = [] %} {# BBB: apache_custom_https AND apache_custom_http #} {% set custom_domain = slave.get('custom_domain') %} {% if custom_domain and custom_domain in used_host_list %} {% do slave_error_list.append('custom_domain %r clashes' % (custom_domain,)) %} {% else %} {% do used_host_list.append(custom_domain) %} {% endif %} {% if slave.get('server-alias') %} {% for slave_alias in ('' ~ slave['server-alias']).split() %} {% if slave_alias.startswith('*.') %} {% set clean_slave_alias = slave_alias[2:] %} {% else %} {% set clean_slave_alias = slave_alias %} {% endif %} {% if not validators.domain(clean_slave_alias) %} {% do slave_error_list.append('server-alias \'%s\' not valid' % (slave_alias,)) %} {% else %} {% if slave_alias in slave_server_alias_unclashed or slave_alias == custom_domain %} {# optionally do something about reporting back that server-alias has been unclashed #} {% elif slave_alias in used_host_list %} {% do slave_error_list.append('server-alias \'%s\' clashes' % (slave_alias,)) %} {% else %} {% do slave_server_alias_unclashed.append(slave_alias) %} {% do used_host_list.append(slave_alias) %} {% endif %} {% endif %} {% endfor %} {% do slave.__setitem__('server-alias', ' '.join(slave_server_alias_unclashed)) %} {% endif %} {% for key in ['caddy_custom_http', 'caddy_custom_https', 'apache_custom_http', 'apache_custom_https'] %} {% if slave.get(key) %} {% if not slave.get('slave_reference') in authorized_slave_string_list %} {% if not unauthorized_message in slave_error_list %} {% do slave_error_list.append(unauthorized_message) %} {% endif %} {% elif subprocess_module.call([caddy_custom_http_validator, '' ~ slave[key]]) == 1 %} {% do slave_error_list.append('slave %s configuration invalid' % (key,)) %} {% endif %} {% endif %} {% endfor %} {# for key in ['caddy_custom_http', 'caddy_custom_https', 'apache_custom_http', 'apache_custom_https'] #} {% if slave.get('url') %} {% if subprocess_module.call([caddy_backend_url_validator, '' ~ slave['url']]) == 1 %} {% do slave_error_list.append('slave url %r invalid' % (slave['url'],)) %} {% endif %} {% endif %} {% if slave.get('https-url') %} {% if subprocess_module.call([caddy_backend_url_validator, '' ~ slave['https-url']]) == 1 %} {% do slave_error_list.append('slave https-url %r invalid' % (slave['https-url'],)) %} {% endif %} {% endif %} {% if slave.get('ssl_ca_crt') and not (slave.get('ssl_crt') and slave.get('ssl_key')) %} {% do slave_error_list.append('ssl_ca_crt is present, so ssl_crt and ssl_key are required') %} {% endif %} {% if slave.get('ssl_key') and slave.get('ssl_crt') %} {% set key_popen = popen([openssl, 'rsa', '-noout', '-modulus']) %} {% set crt_popen = popen([openssl, 'x509', '-noout', '-modulus']) %} {% set key_modulus = key_popen.communicate('' ~ slave['ssl_key'])[0] | trim %} {% set crt_modulus = crt_popen.communicate('' ~ slave['ssl_crt'])[0] | trim %} {% if not key_modulus or key_modulus != crt_modulus %} {% do slave_error_list.append('slave ssl_key and ssl_crt does not match') %} {% endif %} {% endif %} {% if slave.get('custom_domain') %} {% set slave_custom_domain = '' ~ slave['custom_domain'] %} {% if slave_custom_domain.startswith('*.') %} {% set clean_custom_domain = slave_custom_domain[2:] %} {% else %} {% set clean_custom_domain = slave_custom_domain %} {% endif %} {% if not validators.domain(clean_custom_domain) %} {% do slave_error_list.append('custom_domain %r invalid' % (slave['custom_domain'],)) %} {% endif %} {% endif %} {% if len(slave_error_list) == 0 %} {% do authorized_slave_list.append(slave) %} {% else %} {% do rejected_slave_dict.__setitem__(slave.get('slave_reference'), slave_error_list) %} {% endif %} {% endfor %} [monitor-instance-parameter] monitor-httpd-port = {{ slapparameter_dict.get('monitor-httpd-port', '8196') }} [replicate] <= slap-connection recipe = slapos.cookbook:requestoptional.serialised config-monitor-cors-domains = {{ slapparameter_dict.get('monitor-cors-domains', 'monitor.app.officejs.com') }} config-monitor-username = ${monitor-instance-parameter:username} config-monitor-password = ${monitor-htpasswd:passwd} {% set frontend_software_url_key = "-frontend-software-release-url" %} {% if slapparameter_dict.has_key(frontend_software_url_key) %} software-url = {{ slapparameter_dict.pop(frontend_software_url_key) }} {% else %} software-url = ${slap-connection:software-release-url} {% endif %} software-type = {{frontend_type}} return = private-ipv4 public-ipv4 slave-instance-information-list monitor-base-url {% for section, frontend_request in request_dict.iteritems() %} [{{section}}] <= replicate name = {{ frontend_request.get('name') }} {% if frontend_request.get('state') %} state = {{ frontend_request.get('state') }} {% endif%} {% set slave_configuration_dict = slapparameter_dict %} {% do slave_configuration_dict.update(frontend_request.get('config')) %} {% do slave_configuration_dict.__setitem__(slave_list_name, json_module.dumps(authorized_slave_list)) %} {% do slave_configuration_dict.__setitem__("frontend-name", frontend_request.get('name')) %} {%- for config_key, config_value in slave_configuration_dict.iteritems() %} config-{{ config_key }} = {{ dumps(config_value) }} {% endfor -%} {% if frontend_request.get('sla') %} {% for parameter, value in frontend_request.get('sla').iteritems() %} sla-{{ parameter }} = {{ value }} {% endfor %} {% endif %} {% endfor %} [publish-information] <= monitor-publish recipe = slapos.cookbook:publish domain = {{ slapparameter_dict.get('domain') }} slave-amount = {{ slave_instance_list | length }} accepted-slave-amount = {{ authorized_slave_list | length }} rejected-slave-amount = {{ rejected_slave_dict | length }} rejected-slave-dict = {{ dumps(json_module.dumps(rejected_slave_dict)) }} #---------------------------- #-- #-- Publish slave information [publish-slave-information] recipe = slapos.cookbook:softwaretype default = ${dynamic-publish-slave-information:rendered} RootSoftwareInstance = ${dynamic-publish-slave-information:rendered} replicate = ${dynamic-publish-slave-information:rendered} custom-personal = ${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] {% for frontend_section in frontend_section_list %} {{ frontend_section }} = {{ "${%s:connection-slave-instance-information-list}" % frontend_section }} {% endfor %} [active-slave-instance] {% set active_slave_instance_list = [] %} {% for slave_instance in slave_instance_list %} {# Provide a list of slave titles send by master, in order to filter out already destroyed slaves #} {# Note: This functionality is not yet covered by tests, please modify with care #} {% do active_slave_instance_list.append(slave_instance['slave_title']) %} {% endfor %} active-slave-instance-list = {{ json_module.dumps(active_slave_instance_list) }} [dynamic-publish-slave-information] < = jinja2-template-base template = {{ template_publish_slave_information }} filename = dynamic-publish-slave-information.cfg extensions = jinja2.ext.do extra-context = section slave_information slave-information section rejected_slave_information rejected-slave-information section active_slave_instance_dict active-slave-instance [monitor-conf-parameters] monitor-url-list += {% for frontend in frontend_section_list %} {{ ' ${' + frontend + ':connection-monitor-base-url}' }} {% endfor %} [buildout] extends = {{ common_profile }} {{ template_monitor }} parts = monitor-base publish-slave-information publish-information {% for part in part_list %} {{ ' %s' % part }} {% endfor %} # publish-information {% endif %}