# _helpers.tpl
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "elasticsearch-exporter.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "elasticsearch-exporter.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "elasticsearch-exporter.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

 # cert-secret.yaml
{{- if and .Values.es.ssl.enabled (eq .Values.es.ssl.useExistingSecrets false) }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ template "elasticsearch-exporter.fullname" . }}-cert
  labels:
    chart: {{ template "elasticsearch-exporter.chart" . }}
    app: {{ template "elasticsearch-exporter.name" . }}
    release: "{{ .Release.Name }}"
    heritage: "{{ .Release.Service }}"
type: Opaque
data:
  ca.pem: {{ .Values.es.ssl.ca.pem | b64enc }}
  client.pem: {{ .Values.es.ssl.client.pem | b64enc }}
  client.key: {{ .Values.es.ssl.client.key | b64enc }}
{{- end }}
 # deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ template "elasticsearch-exporter.fullname" . }}
  labels:
    chart: {{ template "elasticsearch-exporter.chart" . }}
    app: {{ template "elasticsearch-exporter.name" . }}
    release: "{{ .Release.Name }}"
    heritage: "{{ .Release.Service }}"
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ template "elasticsearch-exporter.name" . }}
      release: "{{ .Release.Name }}"
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: {{ template "elasticsearch-exporter.name" . }}
        release: "{{ .Release.Name }}"
      {{- if .Values.podAnnotations }}
      annotations:
{{ toYaml .Values.podAnnotations | indent 8 }}
      {{- end }}
    spec:
      {{- if .Values.serviceAccount.create  }}
      serviceAccountName: {{ template "elasticsearch-exporter.fullname" . }}
      {{- else }}
      serviceAccountName: {{ .Values.serviceAccount.name }}
      {{- end }}
{{- if .Values.priorityClassName }}
      priorityClassName: "{{ .Values.priorityClassName }}"
{{- end }}
{{- if .Values.image.pullSecret }}
      imagePullSecrets:
        - name: {{ .Values.image.pullSecret }}
{{- end }}
      restartPolicy: {{ .Values.restartPolicy }}
      {{- if .Values.securityContext.enabled }}
      securityContext:
        runAsNonRoot: true
        runAsUser: {{ .Values.securityContext.runAsUser }}
      {{- end }}
      containers:
        - name: {{ .Chart.Name }}
          env:
            {{- range $key, $value := .Values.env }}
            - name: {{ $key }}
              value: "{{ $value }}"
            {{- end }}
            {{- range $key, $value := .Values.extraEnvSecrets }}
            - name: {{ $key }}
              valueFrom:
                secretKeyRef:
                  name: {{ required "Must specify secret!" $value.secret }}
                  key: {{ required "Must specify key!" $value.key }}
            {{- end }}
          {{- if .Values.envFromSecret }}
          envFrom:
          - secretRef:
              name: {{ .Values.envFromSecret }}
          {{- end }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          command: ["elasticsearch_exporter",
                    {{- with .Values.log.format }}
                    "--log.format={{ . }}",
                    {{- end }}
                    {{- with .Values.log.level }}
                    "--log.level={{ . }}",
                    {{- end }}
                    {{- if .Values.es.uri }}
                    "--es.uri={{ .Values.es.uri }}",
                    {{- end }}
                    {{- if .Values.es.all }}
                    "--es.all",
                    {{- end }}
                    {{- if .Values.es.indices }}
                    "--es.indices",
                    {{- end }}
                    {{- if .Values.es.indices_settings }}
                    "--es.indices_settings",
                    {{- end }}
                    {{- if .Values.es.shards }}
                    "--es.shards",
                    {{- end }}
                    {{- if .Values.es.snapshots }}
                    "--es.snapshots",
                    {{- end }}
                    {{- if .Values.es.cluster_settings }}
                    "--es.cluster_settings",
                    {{- end }}
                    "--es.timeout={{ .Values.es.timeout }}",
                    {{- if .Values.es.sslSkipVerify }}
                    "--es.ssl-skip-verify",
                    {{- end }}
                    {{- if .Values.es.ssl.enabled }}
                    "--es.ca={{.Values.es.ssl.ca.path }}",
                    {{- if .Values.es.ssl.client.enabled }}
                    "--es.client-cert={{ .Values.es.ssl.client.pemPath }}",
                    "--es.client-private-key={{ .Values.es.ssl.client.keyPath }}",
                    {{- end }}
                    {{- end }}
                    "--web.listen-address=:{{ .Values.service.httpPort }}",
                    "--web.telemetry-path={{ .Values.web.path }}"]
          securityContext:
            capabilities:
              drop:
                - SETPCAP
                - MKNOD
                - AUDIT_WRITE
                - CHOWN
                - NET_RAW
                - DAC_OVERRIDE
                - FOWNER
                - FSETID
                - KILL
                - SETGID
                - SETUID
                - NET_BIND_SERVICE
                - SYS_CHROOT
                - SETFCAP
            readOnlyRootFilesystem: true
          resources:
{{ toYaml .Values.resources | indent 12 }}
          ports:
            - containerPort: {{ .Values.service.httpPort }}
              name: http
          livenessProbe:
            httpGet:
              path: /healthz
              port: http
            initialDelaySeconds: 5
            timeoutSeconds: 5
            periodSeconds: 5
          readinessProbe:
            httpGet:
              path: /healthz
              port: http
            initialDelaySeconds: 1
            timeoutSeconds: 5
            periodSeconds: 5
          lifecycle:
            preStop:
              exec:
                command: ["/bin/bash", "-c", "sleep 20"]
          volumeMounts:
            {{- if and .Values.es.ssl.enabled (eq .Values.es.ssl.useExistingSecrets false) }}
            - mountPath: /ssl
              name: ssl
            {{- end }}
            {{- range .Values.secretMounts }}
            - name: {{ .name }}
              mountPath: {{ .path }}
              {{- if .subPath }}
              subPath: {{ .subPath }}
              {{- end }}
            {{- end }}
{{- if .Values.nodeSelector }}
      nodeSelector:
{{ toYaml .Values.nodeSelector | indent 8 }}
{{- end }}
{{- if .Values.tolerations }}
      tolerations:
{{ toYaml .Values.tolerations | indent 8 }}
{{- end }}
{{- if .Values.affinity }}
      affinity:
{{ toYaml .Values.affinity | indent 8 }}
{{- end }}
      volumes:
        {{- if and .Values.es.ssl.enabled (eq .Values.es.ssl.useExistingSecrets false) }}
        - name: ssl
          secret:
            secretName: {{ template "elasticsearch-exporter.fullname" . }}-cert
        {{- end }}
        {{- range .Values.secretMounts }}
        - name: {{ .name }}
          secret:
            secretName: {{ .secretName }}
        {{- end }}
 # podsecuritypolicies.yaml
{{- if .Values.podSecurityPolicies.enabled -}}
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: {{ template "elasticsearch-exporter.fullname" . }}
  labels:
    chart: {{ template "elasticsearch-exporter.chart" . }}
    app: {{ template "elasticsearch-exporter.name" . }}
    release: "{{ .Release.Name }}"
    heritage: "{{ .Release.Service }}"
spec:
  privileged: false
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
   - ALL
  volumes:
    - 'secret'
  hostNetwork: false
  hostIPC: false
  hostPID: false
  runAsUser:
    rule: 'MustRunAs'
    ranges:
      - min: 1
        max: 65535
  seLinux:
    rule: 'RunAsAny'
  supplementalGroups:
    rule: 'MustRunAs'
    ranges:
      - min: 1
        max: 65535
  fsGroup:
    rule: 'MustRunAs'
    ranges:
      - min: 1
        max: 65535
  readOnlyRootFilesystem: true
{{- end }}
 # prometheusrule.yaml
{{- if .Values.prometheusRule.enabled }}
---
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: {{ template "elasticsearch-exporter.fullname" . }}
{{- if .Values.prometheusRule.namespace }}
  namespace: {{ .Values.prometheusRule.namespace }}
{{- end }}
  labels:
    chart: {{ template "elasticsearch-exporter.chart" . }}
    app: {{ template "elasticsearch-exporter.name" . }}
    release: "{{ .Release.Name }}"
    heritage: "{{ .Release.Service }}"
{{- if .Values.prometheusRule.labels }}
{{- toYaml .Values.prometheusRule.labels | nindent 4 }}
{{- end }}
spec:
{{- with .Values.prometheusRule.rules }}
  groups:
    - name: {{ template "elasticsearch-exporter.name" $ }}
      rules: {{ tpl (toYaml .) $ | nindent 8 }}
{{- end }}
{{- end }}
 # role.yaml
{{- if .Values.podSecurityPolicies.enabled -}}
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: {{ template "elasticsearch-exporter.fullname" . }}
  labels:
    chart: {{ template "elasticsearch-exporter.chart" . }}
    app: {{ template "elasticsearch-exporter.name" . }}
    release: "{{ .Release.Name }}"
    heritage: "{{ .Release.Service }}"
rules:
- apiGroups: ['extensions']
  resources: ['podsecuritypolicies']
  verbs:     ['use']
  resourceNames:
  - {{ template "elasticsearch-exporter.fullname" . }}
{{- end }}
 # rolebinding.yaml
{{- if .Values.podSecurityPolicies.enabled }}
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: {{ template "elasticsearch-exporter.fullname" . }}
  labels:
    chart: {{ template "elasticsearch-exporter.chart" . }}
    app: {{ template "elasticsearch-exporter.name" . }}
    release: "{{ .Release.Name }}"
    heritage: "{{ .Release.Service }}"
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: {{ template "elasticsearch-exporter.fullname" . }}
subjects:
- kind: ServiceAccount
  {{- if .Values.serviceAccount.create  }}
  name: {{ template "elasticsearch-exporter.fullname" . }}
  {{- else }}
  name: {{ .Values.serviceAccount.name }}
  {{- end }}
  namespace: {{ .Release.Namespace }}
{{- end }}
 # service.yaml
kind: Service
apiVersion: v1
metadata:
  name: {{ template "elasticsearch-exporter.fullname" . }}
  labels:
    chart: {{ template "elasticsearch-exporter.chart" . }}
    app: {{ template "elasticsearch-exporter.name" . }}
    release: "{{ .Release.Name }}"
    heritage: "{{ .Release.Service }}"
{{- if .Values.service.labels }}
{{ toYaml .Values.service.labels | indent 4 }}
{{- end }}
{{- if .Values.service.annotations }}
  annotations:
{{ toYaml .Values.service.annotations | indent 4 }}
{{- end }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - name: {{ .Values.service.metricsPort.name }}
      port: {{ .Values.service.httpPort }}
      protocol: TCP
  selector:
    app: {{ template "elasticsearch-exporter.name" . }}
    release: "{{ .Release.Name }}"
 # serviceaccount.yaml
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
  name: {{ template "elasticsearch-exporter.fullname" . }}
  labels:
    chart: {{ template "elasticsearch-exporter.chart" . }}
    app: {{ template "elasticsearch-exporter.name" . }}
    release: "{{ .Release.Name }}"
    heritage: "{{ .Release.Service }}"
{{- end }}
 # servicemonitor.yaml
{{- if .Values.serviceMonitor.enabled }}
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: {{ template "elasticsearch-exporter.fullname" . }}
  {{- if .Values.serviceMonitor.namespace }}
  namespace: {{ .Values.serviceMonitor.namespace }}
  {{- end }}
  labels:
    chart: {{ template "elasticsearch-exporter.chart" . }}
    app: {{ template "elasticsearch-exporter.name" . }}
    release: "{{ .Release.Name }}"
    heritage: "{{ .Release.Service }}"
    {{- if .Values.serviceMonitor.labels }}
    {{- toYaml .Values.serviceMonitor.labels | nindent 4 }}
    {{- end }}
spec:
  endpoints:
  - interval: {{ .Values.serviceMonitor.interval }}
    {{- if .Values.serviceMonitor.scrapeTimeout }}
    scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }}
    {{- end }}
    honorLabels: true
    port: {{ .Values.service.metricsPort.name }}
    path: {{ .Values.web.path }}
    scheme: {{ .Values.serviceMonitor.scheme }}
    {{- if .Values.serviceMonitor.relabelings }}
    relabelings:
    {{- toYaml .Values.serviceMonitor.relabelings | nindent 4 }}
    {{- end }}
    {{- if .Values.serviceMonitor.metricRelabelings }}
    metricRelabelings:
    {{ toYaml .Values.serviceMonitor.metricRelabelings | nindent 4 }}
    {{- end }}
  jobLabel: "{{ .Release.Name }}"
  selector:
    matchLabels:
      app: {{ template "elasticsearch-exporter.name" . }}
      release: "{{ .Release.Name }}"
  namespaceSelector:
    matchNames:
      - {{ .Release.Namespace }}
{{- if .Values.serviceMonitor.targetLabels }}
  targetLabels:
{{- range .Values.serviceMonitor.targetLabels }}
    - {{ . }}
{{- end }}
{{- end }}
  sampleLimit: {{ .Values.serviceMonitor.sampleLimit }}
{{- end }}

## number of exporter instances
##
replicaCount: 1

## restart policy for all containers
##
restartPolicy: Always

image:
  repository: justwatch/elasticsearch_exporter
  tag: 1.1.0
  pullPolicy: IfNotPresent
  pullSecret: ""

## Set enabled to false if you don't want securityContext
## in your Deployment.
## The below values are the default for kubernetes.
## Openshift won't deploy with runAsUser: 1000 without additional permissions.
securityContext:
  enabled: true  # Should be set to false when running on OpenShift
  runAsUser: 1000

log:
  format: logfmt
  level: info

resources: {}
  # requests:
  #   cpu: 100m
  #   memory: 128Mi
  # limits:
  #   cpu: 100m
  #   memory: 128Mi

priorityClassName: ""

nodeSelector: {}

tolerations: {}

podAnnotations: {}

affinity: {}

service:
  type: ClusterIP
  httpPort: 9108
  metricsPort:
    name: http
  annotations: {}
  labels: {}

## Extra environment variables that will be passed into the exporter pod
## example:
## env:
##   KEY_1: value1
##   KEY_2: value2
env: {}

## The name of a secret in the same kubernetes namespace which contain values to be added to the environment
## This can be useful for auth tokens, etc
envFromSecret: ""

## A list of environment variables from secret refs that will be passed into the exporter pod
## example:
## This will set ${ES_PASSWORD} to the 'password' key from the 'my-secret' secret
## extraEnvSecrets:
##   ES_PASSWORD:
##     secret: my-secret
##     key: password
extraEnvSecrets: {}

# A list of secrets and their paths to mount inside the pod
# This is useful for mounting certificates for security
secretMounts: []
#  - name: elastic-certs
#    secretName: elastic-certs
#    path: /ssl

es:
  ## Address (host and port) of the Elasticsearch node we should connect to.
  ## This could be a local node (localhost:9200, for instance), or the address
  ## of a remote Elasticsearch server. When basic auth is needed,
  ## specify as: <proto>://<user>:<password>@<host>:<port>. e.g., http://admin:pass@localhost:9200.
  ##
  uri: http://localhost:9200

  ## If true, query stats for all nodes in the cluster, rather than just the
  ## node we connect to.
  ##
  all: true

  ## If true, query stats for all indices in the cluster.
  ##
  indices: true

  ## If true, query settings stats for all indices in the cluster.
  ##
  indices_settings: true

  ## If true, query stats for shards in the cluster.
  ##
  shards: true

  ## If true, query stats for snapshots in the cluster.
  ##
  snapshots: true

  ## If true, query stats for cluster settings.
  ##
  cluster_settings: false

  ## Timeout for trying to get stats from Elasticsearch. (ex: 20s)
  ##
  timeout: 30s

  ## Skip SSL verification when connecting to Elasticsearch
  ## (only available if image.tag >= 1.0.4rc1)
  ##
  sslSkipVerify: false


  ssl:
    ## If true, a secure connection to ES cluster is used
    ##
    enabled: false

    ## If true, certs from secretMounts will be need to be referenced instead of certs below
    ##
    useExistingSecrets: false

    ca:

      ## PEM that contains trusted CAs used for setting up secure Elasticsearch connection
      ##
      # pem:

      # Path of ca pem file which should match a secretMount path
      path: /ssl/ca.pem
    client:
      ## if true, client SSL certificate is used for authentication
      ##
      enabled: true

      ## PEM that contains the client cert to connect to Elasticsearch.
      ##
      # pem:

      # Path of client pem file which should match a secretMount path
      pemPath: /ssl/client.pem

      ## Private key for client auth when connecting to Elasticsearch
      ##
      # key:

      # Path of client key file which should match a secretMount path
      keyPath: /ssl/client.key
web:
  ## Path under which to expose metrics.
  ##
  path: /metrics

serviceMonitor:
  ## If true, a ServiceMonitor CRD is created for a prometheus operator
  ## https://github.com/coreos/prometheus-operator
  ##
  enabled: false
  #  namespace: monitoring
  labels: {}
  interval: 10s
  scrapeTimeout: 10s
  scheme: http
  relabelings: []
  targetLabels: []
  metricRelabelings: []
  sampleLimit: 0

prometheusRule:
  ## If true, a PrometheusRule CRD is created for a prometheus operator
  ## https://github.com/coreos/prometheus-operator
  ##
  ## The rules will be processed as Helm template, allowing to set variables in them.
  enabled: false
  #  namespace: monitoring
  labels: {}
  rules: []
    # - record: elasticsearch_filesystem_data_used_percent
    #   expr: |
    #     100 * (elasticsearch_filesystem_data_size_bytes{service="{{ template "elasticsearch-exporter.fullname" . }}"} - elasticsearch_filesystem_data_free_bytes{service="{{ template "elasticsearch-exporter.fullname" . }}"})
    #     / elasticsearch_filesystem_data_size_bytes{service="{{ template "elasticsearch-exporter.fullname" . }}"}
    # - record: elasticsearch_filesystem_data_free_percent
    #   expr: 100 - elasticsearch_filesystem_data_used_percent{service="{{ template "elasticsearch-exporter.fullname" . }}"}
    # - alert: ElasticsearchTooFewNodesRunning
    #   expr: elasticsearch_cluster_health_number_of_nodes{service="{{ template "elasticsearch-exporter.fullname" . }}"} < 3
    #   for: 5m
    #   labels:
    #     severity: critical
    #   annotations:
    #     description: There are only {{ "{{ $value }}" }} < 3 ElasticSearch nodes running
    #     summary: ElasticSearch running on less than 3 nodes
    # - alert: ElasticsearchHeapTooHigh
    #   expr: |
    #     elasticsearch_jvm_memory_used_bytes{service="{{ template "elasticsearch-exporter.fullname" . }}", area="heap"} / elasticsearch_jvm_memory_max_bytes{service="{{ template "elasticsearch-exporter.fullname" . }}", area="heap"}
    #     > 0.9
    #   for: 15m
    #   labels:
    #     severity: critical
    #   annotations:
    #     description: The heap usage is over 90% for 15m
    #     summary: ElasticSearch node {{ "{{ $labels.node }}" }} heap usage is high

# Create a service account
# To use a service account not handled by the chart, set the name here
# and set create to false
serviceAccount:
  create: false
  name: default

# Creates a PodSecurityPolicy and the role/rolebinding
# allowing the serviceaccount to use it
podSecurityPolicies:
  enabled: false
