{%- if slap_software_type == software_type -%}
{% import "caucase" as caucase with context %}
# KeDiFa instance profile
[buildout]
extends =
  {{ parameter_dict['common_profile'] }}
  {{ parameter_dict['monitor_template'] }}
  {{ parameter_dict['logrotate_base_instance'] }}

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

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

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

# 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
promise = ${:etc}/promise
plugin = ${:etc}/plugin

# 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
caddy-csr_id = ${:etc}/caddy-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 '{{ parameter_dict['openssl'] }} req -new -sha256 \
      -newkey rsa:2048 -nodes -keyout ${:key} \
      -subj "/O=${:organization}/OU=${:organizational_unit}" \
      -reqexts SAN \
      -config <(cat {{ 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}
stop-on-error = True

{{ caucase.updater(
     prefix='caucase-updater',
     buildout_bin_directory=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:wrapper-path}',
     template_csr='${kedifa-csr:template-csr}',
     openssl=parameter_dict['openssl'] ~ '/bin/openssl',
)}}

[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 =
  {{ 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:caddy-csr_id}/certificate.pem
key = ${directory:caddy-csr_id}/key.pem

stop-on-error = True
update-command = ${:command}
command =
  if ! [ -f ${:key} ] && ! [ -f ${:certificate} ] ; then
    openssl req -new -newkey rsa:2048 -sha256 -subj \
      "/O=${kedifa-csr:organization}/OU=${kedifa-csr:organizational_unit}/CN={{ instance_parameter['ipv6-random'] }}" \
      -days 5 -nodes -x509 -keyout ${:key} -out ${:certificate}
  fi

[expose-csr_id-configuration]
ip = {{ instance_parameter['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
template = inline:
  https://:${expose-csr_id-configuration:port}/ {
    bind ${expose-csr_id-configuration:ip}
    tls ${expose-csr_id-configuration:certificate} ${expose-csr_id-configuration:key}
    log ${expose-csr_id-configuration:error-log}
  }

rendered = ${directory:caddy-csr_id}/Caddyfile

[promise-expose-csr_id-ip-port]
<= promise-plugin-base
module = check_port_listening
name = expose-csr_id-ip-port-listening.py
config-hostname = ${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 = {{ parameter_dict['caddy'] }}
  -conf ${expose-csr_id-template:rendered}
  -log ${expose-csr_id-configuration:error-log}
  -http2=true
  -disable-http-challenge
  -disable-tls-alpn-challenge
  -root ${directory:csr_id}

wrapper-path = ${directory:service}/expose-csr_id
hash-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(instance_parameter['configuration']) }}
slap_software_type = {{ dumps(instance_parameter['slap-software-type']) }}
context =
    import json_module json
    raw common_profile {{ parameter_dict['common_profile'] }}
    key slap_software_type :slap_software_type
    key slapparameter_dict :slapparameter_dict
    section directory directory
    ${:extra-context}

[promise-plugin-base]
recipe = slapos.cookbook:promise.plugin
eggs =
  slapos.toolbox
content =
  from slapos.promise.plugin.${:module} import RunPromise
output = ${directory:plugin}/${:name}

[kedifa-config]
ip = {{ instance_parameter['ipv6-random'] }}
port = {{ instance_parameter['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}/kedfia.log

[kedifa-reloader]
recipe = slapos.cookbook:wrapper
command-line = kill -SIGHUP `cat ${kedifa-config:pidfile}`
wrapper-path = ${directory:etc-run}/kedifa-reloader

[promise-kedifa-http-reply]
<= promise-plugin-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 = 30

[kedifa]
recipe = slapos.cookbook:wrapper
command-line = {{ 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-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} ] && {{ 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} ] && {{ 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
slave-kedifa-information = {{ json_module.dumps(slave_kedifa_information) }}
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}
{%- endif -%} {# if slap_software_type in software_type #}
