{%- if instance_parameter_dict['slap-software-type'] == software_type -%}
{% import "caucase" as caucase with context %}
# KeDiFa instance profile
[buildout]
extends =
  {{ software_parameter_dict['profile_common'] }}
  {{ software_parameter_dict['profile_monitor'] }}
  {{ software_parameter_dict['profile_logrotate_base'] }}

parts =
  monitor-base
  directory
  kedifa
  logrotate-entry-kedifa
  promise-kedifa-http-reply
  slave-kedifa-information
  caucased
  caucased-promise
  caucase-updater
  expose-csr_id
  promise-expose-csr_id-ip-port
  promise-logrotate-setup

[monitor-instance-parameter]
# Note: Workaround for monitor stack, which uses monitor-httpd-port parameter
#       directly, and in our case it can come from the network, thus resulting
#       with need to strip !py!'u'
monitor-httpd-port = {{ instance_parameter_dict['configuration.monitor-httpd-port'] | int }}
password = {{ instance_parameter_dict['configuration.monitor-password'] | string }}

[caucased]
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg

{%  set caucase_host = '[' ~ instance_parameter_dict['ipv6-random'] ~ ']' %}
{%  set caucase_netloc = caucase_host ~ ':' ~ instance_parameter_dict['configuration.caucase_port'] -%}
{%  set caucase_url = 'http://' ~ caucase_netloc -%}
{{  caucase.caucased(
      prefix='caucased',
      buildout_bin_directory=software_parameter_dict['bin_directory'],
      caucased_path='${directory:service}/caucased',
      backup_dir='${directory:backup-caucased}',
      data_dir='${directory:caucased}',
      netloc=caucase_netloc,
      tmp='${directory:tmp}',
      service_auto_approve_count=0,
      user_auto_approve_count=1,
      key_len=2048
)}}

# Create all needed directories
[directory]
recipe = slapos.cookbook:mkdirectory

bin = ${buildout:directory}/bin/
etc = ${buildout:directory}/etc/
srv = ${buildout:directory}/srv/
var = ${buildout:directory}/var/
tmp = ${buildout:directory}/tmp/

backup = ${:srv}/backup
log = ${:var}/log
run = ${:var}/run
service = ${:etc}/service
etc-run = ${:etc}/run

# KeDiFa directories
kedifa = ${:srv}/kedifa
etc-kedifa = ${:etc}/kedifa

# CAUCASE directories
caucased = ${:srv}/caucased
backup-caucased = ${:backup}/caucased

# reservation
reservation = ${:srv}/reservation

# csr_id publication
csr_id = ${:srv}/csr_id
certificate-csr_id = ${:var}/certificate-csr_id
expose-csr_id-var = ${:var}/expose-csr_id

[kedifa-csr]
recipe = plone.recipe.command
organization = {{ slapparameter_dict['cluster-identification'] }}
organizational_unit = Kedifa Partition
command =
  if [ ! -f ${:template-csr} ] && [ ! -f ${:key} ]  ; then
    /bin/bash -c '{{ software_parameter_dict['openssl'] }} req -new -sha256 \
      -newkey rsa:2048 -nodes -keyout ${:key} \
      -subj "/O=${:organization}/OU=${:organizational_unit}" \
      -reqexts SAN \
      -config <(cat {{ software_parameter_dict['openssl_cnf'] }} \
      <(printf "\n[SAN]\nsubjectAltName=IP:${kedifa-config:ip}")) \
      -out ${:template-csr}'
  fi
update-command = ${:command}
template-csr = ${kedifa-config:template-csr}
key = ${kedifa-config:key}
{#- Can be stopped on error, as does not rely on self provided service #}
stop-on-error = True

{{ caucase.updater(
     prefix='caucase-updater',
     buildout_bin_directory=software_parameter_dict['bin_directory'],
     updater_path='${directory:service}/caucase-updater',
     url=caucase_url,
     data_dir='${directory:srv}/caucase-updater',
     crt_path='${kedifa-config:certificate}',
     ca_path='${kedifa-config:ca-certificate}',
     crl_path='${kedifa-config:crl}',
     key_path='${kedifa-csr:key}',
     on_renew='${kedifa-reloader:rendered}',
     template_csr='${kedifa-csr:template-csr}'
)}}

[store-csr_id]
recipe = plone.recipe.command

csr_id_path = ${directory:csr_id}/csr_id.txt
csr_work_path = ${directory:tmp}/${:_buildout_section_name_}

stop-on-error = False
update-command = ${:command}
command =
  {{ software_parameter_dict['bin_directory'] }}/caucase \
    --ca-url {{ caucase_url }} \
    --ca-crt ${kedifa-config:ca-certificate} \
    --crl ${kedifa-config:crl} \
    --mode service \
{#- XXX: Need to use caucase-updater-csr:csr, as there is no way to obatin csr_id from caucase-updater -#}
{#- XXX: nor directly path to the generated CSR #}
    --send-csr ${caucase-updater-csr:csr} > ${:csr_work_path} && \
  cut -d ' ' -f 1 ${:csr_work_path} > ${:csr_id_path}

[certificate-csr_id]
recipe = plone.recipe.command
certificate = ${directory:certificate-csr_id}/certificate.pem
key = ${directory:certificate-csr_id}/key.pem

{#- Can be stopped on error, as does not rely on self provided service #}
stop-on-error = True
update-command = ${:command}
command =
  if ! [ -f ${:key} ] && ! [ -f ${:certificate} ] ; then
    {{ software_parameter_dict['openssl'] }} req -new -newkey rsa:2048 -sha256 -subj \
      "/O=${kedifa-csr:organization}/OU=${kedifa-csr:organizational_unit}/CN={{ instance_parameter_dict['ipv6-random'] }}" \
      -days 5 -nodes -x509 -keyout ${:key} -out ${:certificate}
  fi

[expose-csr_id-configuration]
ip = {{ instance_parameter_dict['ipv6-random'] }}
port = 17000
key = ${certificate-csr_id:key}
certificate = ${certificate-csr_id:certificate}
error-log = ${directory:log}/expose-csr_id.log

[expose-csr_id-template]
recipe = slapos.recipe.template:jinja2
var = ${directory:expose-csr_id-var}
pid = ${directory:var}/nginx-expose-csr_id.pid
rendered = ${directory:etc}/nginx-expose-csr_id.conf
template = inline:
  daemon off;
  pid ${:pid};
  error_log ${expose-csr_id-configuration:error-log};
  events {
  }
  http {
    include {{ software_parameter_dict['nginx_mime'] }};
    server {
      server_name_in_redirect off;
      port_in_redirect off;
      error_log ${expose-csr_id-configuration:error-log};
      access_log /dev/null;
      listen [${expose-csr_id-configuration:ip}]:${expose-csr_id-configuration:port} ssl;
      ssl_certificate ${expose-csr_id-configuration:certificate};
      ssl_certificate_key ${expose-csr_id-configuration:key};
      default_type application/octet-stream;
      client_body_temp_path ${:var} 1 2;
      proxy_temp_path ${:var} 1 2;
      fastcgi_temp_path ${:var} 1 2;
      uwsgi_temp_path ${:var} 1 2;
      scgi_temp_path ${:var} 1 2;

      location / {
        alias ${directory:csr_id}/;
        autoindex off;
        sendfile on;
        sendfile_max_chunk 1m;
      }
    }
  }

[promise-expose-csr_id-ip-port]
<= monitor-promise-base
module = check_socket_listening
name = expose-csr_id-ip-port-listening.py
config-host = ${expose-csr_id-configuration:ip}
config-port = ${expose-csr_id-configuration:port}

[expose-csr_id]
depends = ${store-csr_id:command}
recipe = slapos.cookbook:wrapper
command-line = {{ software_parameter_dict['nginx'] }}
  -c ${expose-csr_id-template:rendered}

wrapper-path = ${directory:service}/expose-csr_id
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg

[get-csr_id-certificate]
recipe = collective.recipe.shelloutput
commands =
  certificate = cat ${certificate-csr_id:certificate}

[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
rendered = ${buildout:directory}/${:filename}
extra-context =
slapparameter_dict = {{ dumps(slapparameter_dict) }}
slap_software_type = {{ dumps(instance_parameter_dict['slap-software-type']) }}
context =
    import json_module json
    raw profile_common {{ software_parameter_dict['profile_common'] }}
    key slap_software_type :slap_software_type
    key slapparameter_dict :slapparameter_dict
    section directory directory
    ${:extra-context}

[kedifa-config]
ip = {{ instance_parameter_dict['ipv6-random'] }}
port = {{ instance_parameter_dict['configuration.kedifa_port'] }}
db = ${directory:kedifa}/kedifa.sqlite
certificate = ${directory:etc-kedifa}/certificate.pem
key = ${:certificate}
ca-certificate = ${directory:etc-kedifa}/ca-certificate.pem
crl = ${directory:etc-kedifa}/crl.pem
template-csr = ${directory:etc-kedifa}/template-csr.pem
pidfile = ${directory:run}/kedifa.pid
logfile = ${directory:log}/kedifa.log

[kedifa-reloader]
<= jinja2-template-base
template = {{ software_parameter_dict['template_wrapper'] }}
rendered = ${directory:etc-run}/kedifa-reloader
command =
  kill -HUP `cat ${kedifa-config:pidfile}`
mode = 0700
extra-context =
  key content :command

[promise-kedifa-http-reply]
<= monitor-promise-base
module = check_url_available
name = kedifa-http-reply.py
# Kedifa replies 400 on /, so use it to be sure that Kedifa replied
config-http_code = 400
config-url = https://[${kedifa-config:ip}]:${kedifa-config:port}
config-ca-cert-file = ${kedifa-config:ca-certificate}

[logrotate-entry-kedifa]
<= logrotate-entry-base
name = kedifa
log = ${kedifa-config:logfile}
rotate-num = {{ instance_parameter_dict['configuration.rotate-num'] | int }}
delaycompress =

[kedifa]
recipe = slapos.cookbook:wrapper
command-line = {{ software_parameter_dict['kedifa'] }}
  --ip ${kedifa-config:ip}
  --port ${kedifa-config:port}
  --db ${kedifa-config:db}
  --certificate ${kedifa-config:certificate}
  --ca-certificate ${kedifa-config:ca-certificate}
  --crl ${kedifa-config:crl}
  --pidfile ${kedifa-config:pidfile}
  --logfile ${kedifa-config:logfile}

wrapper-path = ${directory:service}/kedifa
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg

# Publish KeDiFa configuration for upload and download for each slave
{%- set slave_kedifa_information = {} -%}
{%- for slave in slapparameter_dict['slave-list'] -%}
{%-   set slave_reference = slave['slave_reference'] -%}
{%-   set slave_dict = {} -%}
{%-   do slave_dict.__setitem__('key-generate-auth-url', 'https://[${kedifa-config:ip}]:${kedifa-config:port}/${%s-auth-random:passwd}/generateauth' % (slave_reference,)) -%}
{%-   do slave_dict.__setitem__('key-upload-url', 'https://[${kedifa-config:ip}]:${kedifa-config:port}/${%s-auth-random:passwd}?auth=' % (slave_reference,)) -%}
{%-   do slave_dict.__setitem__('key-download-url', 'https://[${kedifa-config:ip}]:${kedifa-config:port}/${%s-auth-random:passwd}' % (slave_reference,)) -%}
{%-   do slave_dict.__setitem__('kedifa-caucase-url', caucase_url ) -%}
{%-   do slave_kedifa_information.__setitem__(slave_reference, slave_dict) %}
[{{ slave_reference }}-auth-random-generate]
recipe = plone.recipe.command
file = ${directory:reservation}/${:_buildout_section_name_}
command =
  [ ! -f ${:file} ] && {{ software_parameter_dict['curl'] }}/bin/curl -s -g -X POST https://[${kedifa-config:ip}]:${kedifa-config:port}/reserve-id --cert ${kedifa-config:certificate} --cacert ${kedifa-config:ca-certificate} > ${:file}.tmp && mv ${:file}.tmp ${:file}
update-command = ${:command}

[{{ slave_reference }}-auth-random]
recipe = collective.recipe.shelloutput
file = {{ '${' + slave_reference }}-auth-random-generate:file}
commands =
  passwd = cat ${:file} 2>/dev/null || echo "NotReadyYet"

{% endfor %}

[master-auth-random-generate]
recipe = plone.recipe.command
file = ${directory:reservation}/${:_buildout_section_name_}
command =
  [ ! -f ${:file} ] && {{ software_parameter_dict['curl'] }}/bin/curl -s -g -X POST https://[${kedifa-config:ip}]:${kedifa-config:port}/reserve-id --cert ${kedifa-config:certificate} --cacert ${kedifa-config:ca-certificate} > ${:file}.tmp && mv ${:file}.tmp ${:file}
update-command = ${:command}

[master-auth-random]
recipe = collective.recipe.shelloutput
file = ${master-auth-random-generate:file}
commands =
  passwd = cat ${:file} 2>/dev/null || echo "NotReadyYet"

[slave-kedifa-information]
recipe = slapos.cookbook:publish.serialised
{# sort_keys are important in order to avoid shuffling parameters on each run #}
slave-kedifa-information = {{ json_module.dumps(slave_kedifa_information, sort_keys=True) }}
caucase-url = {{ caucase_url }}
master-key-generate-auth-url = https://[${kedifa-config:ip}]:${kedifa-config:port}/${master-auth-random:passwd}/generateauth
master-key-upload-url = https://[${kedifa-config:ip}]:${kedifa-config:port}/${master-auth-random:passwd}?auth=
master-key-download-url = https://[${kedifa-config:ip}]:${kedifa-config:port}/${master-auth-random:passwd}
csr_id-url = https://[${expose-csr_id-configuration:ip}]:${expose-csr_id-configuration:port}/csr_id.txt
csr_id-certificate = ${get-csr_id-certificate:certificate}
monitor-base-url = ${monitor-instance-parameter:monitor-base-url}

[promise-logrotate-setup]
<= monitor-promise-base
module = check_command_execute
name = ${:_buildout_section_name_}.py
config-command =
  ${logrotate:wrapper-path} -d

{%- endif -%} {# if instance_parameter_dict['slap-software-type'] == software_type #}