# This is a bash script that runs on each pod when it starts up, and handles issues in the environment
# like configuration processing.
apiVersion: v1
kind: ConfigMap
metadata:
  name: "{{ .Release.Name }}-init-script"
  labels:
    helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    app.kubernetes.io/instance: {{ .Release.Name | quote }}
    app.kubernetes.io/name: {{ template "neo4j.name" . }}
    app.kubernetes.io/component: init
data:
  init.sh: |-
    # Local hostname (graph-neo4j-core-0) converted to graph_neo4j_core_0
    # So that if a var is defined graph_neo4j_core_0_MYSETTING
    # its host-specific value will override whatever the default MYSETTING
    # is in the environment.
    # In this way we can give a single configmap to all 3 pods in a stateful
    # set, and still be able to do per-pod bespoke config.
    export override_prefix=$(hostname | sed s/-/_/g)
    # Ensure HOST is set, but take a default from the outer environment if present.
    export HOST=${HOST:-$(hostname -f)}

    declare -A NEO4J_SETTINGS

    # Populate NEO4J_SETTINGS with keys for all settings overriden as env vars
    for variable_name in $(compgen -e) ; do
      if [[ "${variable_name}" == "${override_prefix}"* ]]; then
        NEO4J_SETTINGS[${variable_name#"${override_prefix}_"}]=""
      fi
    done

    # HTTPS
    NEO4J_SETTINGS[dbms_connector_https_enabled]=true

    # Default settings values; either inherit from outward settings,
    # or, lacking any definition, take the local host
    NEO4J_SETTINGS[NEO4J_dbms_connector_bolt_advertised__address]=${NEO4J_dbms_connector_bolt_advertised__address:-$HOST:7687}
    NEO4J_SETTINGS[NEO4J_dbms_connector_http_advertised__address]=${NEO4J_dbms_connector_http_advertised__address:-$HOST:7474}
    NEO4J_SETTINGS[NEO4J_dbms_connector_https_advertised__address]=${NEO4J_dbms_connector_https_advertised__address:-$HOST:7473}

    # Important: note the label selector only does discovery against first 3 cores. This is intentional;
    # the list service API may return other hosts which aren't yet ready, and this will fail discovery
    # This setting is intentionally overridable for power users; discovery type of k8s is not.
    # See: https://github.com/neo4j-contrib/neo4j-helm/issues/80
    default_label_selector="neo4j.com/cluster={{ template "neo4j.fullname" . }},neo4j.com/role=CORE,neo4j.com/coreindex in (0, 1, 2)"
    NEO4J_SETTINGS[NEO4J_causal__clustering_kubernetes_label__selector]=${NEO4J_causal__clustering_kubernetes_label__selector:-$default_label_selector}

    neo4jAdminMemrec() {
      echo "Calling neo4j-admin memrec to suggest memory settings:"
      # Neo4j-admin memrec outputs configuration like this: dbms.memory.heap.max_size=9000m
      # with a lot of comments.  We strip the comments, then
      # process its output into a docker env var by following the Neo4j docker rules:
      # underscores doubled, dots -> _
      # So dbms.memory.heap.max_size=9000m => export NEO4J_dbms_memory_heap_max__size=9000m

      echo '' > /var/lib/neo4j/conf/memory-recommendations.sh
      for line in $( /var/lib/neo4j/bin/neo4j-admin memrec | grep -v '^Selecting\ JVM' | grep -v '^\#' ) ; do
          # print out the memory recommendation that is being applied
          echo "${line}"
          echo "export $( echo "${line}" | sed 's/_/__/g' | sed 's/\./_/g' | sed 's/^/NEO4J_/g' )" >> /var/lib/neo4j/conf/memory-recommendations.sh
      done

      . /var/lib/neo4j/conf/memory-recommendations.sh
    }

    {{- if .Values.dbms.memory.use_memrec }}
        neo4jAdminMemrec
    {{- else }}
      {{- if .Values.dbms.memory.heap.initial_size }}
      NEO4J_SETTINGS[NEO4J_dbms_memory_heap_initial__size]={{ .Values.dbms.memory.heap.initial_size }}
      {{- end }}

      {{- if .Values.dbms.memory.heap.max_size }}
      NEO4J_SETTINGS[NEO4J_dbms_memory_heap_max__size]={{ .Values.dbms.memory.heap.max_size }}
      {{- end }}

      {{- if .Values.dbms.memory.pagecache.size }}
      NEO4J_SETTINGS[NEO4J_dbms_memory_pagecache_size]={{ .Values.dbms.memory.pagecache.size }}
      {{- end }}

      {{- if .Values.dbms.memory.transaction.max_size }}
      NEO4J_SETTINGS[NEO4J_dbms_memory_transaction_max__size]={{ .Values.dbms.memory.transaction.max_size }}
      {{- end }}

      {{- if .Values.dbms.memory.transaction.global_max_size }}
      NEO4J_SETTINGS[NEO4J_dbms_memory_transaction_global__max__size]={{ .Values.dbms.memory.transaction.global_max_size }}
      {{- end }}

      {{- if .Values.dbms.memory.transaction.memory_allocation }}
      NEO4J_SETTINGS[NEO4J_dbms_tx__state_memory__allocation]={{ .Values.dbms.memory.transaction.memory_allocation }}
      {{- end }}
    {{- end }}

    echo "Configuration override prefix = $override_prefix"

    # Check to see if a particular env var has a host-specific override.  If it does,
    # return the override.  Otherwise return the default value.
    getSettingValue() {
      # Setting key: $1
      # Default value: $2
      # Return: modify $SETTING_VALUE
      export override_varname=$override_prefix"_"$1
      # echo "Checking for override $override_varname"
      if [ -z "${!override_varname}" ] ; then
          SETTING_VALUE=$2
      else
          SETTING_VALUE=${!override_varname}
      fi
    }

    # For each config item, set an env var to the appropriate
    # metadata value or default value.  This sets us up for envsubst
    for setting in "${!NEO4J_SETTINGS[@]}" ; do
      # echo setting $setting
      # echo default 
      getSettingValue $setting "${NEO4J_SETTINGS[$setting]}"
      # echo "Setting $setting to $SETTING_VALUE"

      # Set the variable named setting to the result.
      # See: https://stackoverflow.com/questions/9714902/how-to-use-a-variables-value-as-another-variables-name-in-bash
      export $setting="$SETTING_VALUE"
    done

    {{- if not .Values.core.standalone }}
    # This discovery mechanism only applies for clustered installs.
    # These settings are *not* overrideable, because they must match the addresses the
    # core members see to avoid akka rejections, and to facilitate basic cluster formation.
    # K8S discovery requires an LB service per pod, and a service account with permissions to query the discovery API
    export NEO4J_causal__clustering_discovery__type=K8S

    # See discovery-lb, this is the name of the port used to form.
    export NEO4J_causal__clustering_kubernetes_service__port__name="tcp-discovery"
    {{- end }}

    if [ "${AUTH_ENABLED:-}" == "true" ]; then
      export NEO4J_AUTH="neo4j/${NEO4J_SECRETS_PASSWORD}"
    else
      export NEO4J_AUTH="none"
    fi

    # Once passed through to auth, unset this so Neo4j doesn't misinterpret it as config.
    unset NEO4J_SECRETS_PASSWORD
