# _helpers.tpl
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "telegraf.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 "telegraf.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 "telegraf.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
  CUSTOM TEMPLATES: This section contains templates that make up the different parts of the telegraf configuration file.
  - global_tags section
  - agent section
*/}}

{{- define "global_tags" -}}
{{- if . -}}
[global_tags]
  {{- range $key, $val := . }}
      {{ $key }} = {{ $val | quote }}
  {{- end }}
{{- end }}
{{- end -}}

{{- define "agent" -}}
[agent]
{{- range $key, $value := . -}}
  {{- $tp := typeOf $value }}
  {{- if eq $tp "string"}}
      {{ $key }} = {{ $value | quote }}
  {{- end }}
  {{- if eq $tp "float64"}}
      {{ $key }} = {{ $value | int64 }}
  {{- end }}
  {{- if eq $tp "int"}}
      {{ $key }} = {{ $value | int64 }}
  {{- end }}
  {{- if eq $tp "bool"}}
      {{ $key }} = {{ $value }}
  {{- end }}
{{- end }}
{{- end -}}

{{- define "outputs" -}}
{{- range $outputIdx, $configObject := . -}}
    {{- range $output, $config := . -}}

    [[outputs.{{- $output }}]]
    {{- if $config -}}
    {{- $tp := typeOf $config -}}
    {{- if eq $tp "map[string]interface {}" -}}
        {{- range $key, $value := $config -}}
          {{- $tp := typeOf $value -}}
          {{- if eq $tp "string" }}
      {{ $key }} = {{ $value | quote }}
          {{- end }}
          {{- if eq $tp "float64" }}
      {{ $key }} = {{ $value | int64 }}
          {{- end }}
          {{- if eq $tp "int" }}
      {{ $key }} = {{ $value | int64 }}
          {{- end }}
          {{- if eq $tp "bool" }}
      {{ $key }} = {{ $value }}
          {{- end }}
          {{- if eq $tp "[]interface {}" }}
      {{ $key }} = [
              {{- $numOut := len $value }}
              {{- $numOut := sub $numOut 1 }}
              {{- range $b, $val := $value }}
                {{- $i := int64 $b }}
                {{- $tp := typeOf $val }}
                {{- if eq $i $numOut }}
                  {{- if eq $tp "string" }}
        {{ $val | quote }}
                  {{- end }}
                  {{- if eq $tp "float64" }}
        {{ $val | int64 }}
                  {{- end }}
                {{- else }}
                  {{- if eq $tp "string" }}
        {{ $val | quote }},
                  {{- end}}
                  {{- if eq $tp "float64" }}
        {{ $val | int64 }},
                  {{- end }}
                {{- end }}
              {{- end }}
      ]
          {{- end }}
        {{- end }}
        {{- range $key, $value := $config -}}
          {{- $tp := typeOf $value -}}
          {{- if eq $tp "map[string]interface {}" }}
      [[outputs.{{ $output }}.{{ $key }}]]
            {{- range $k, $v := $value }}
              {{- $tps := typeOf $v }}
              {{- if eq $tps "string" }}
        {{ $k }} = {{ $v | quote }}
              {{- end }}
              {{- if eq $tps "float64" }}
        {{ $k }} = {{ $v | int64 }}.0
              {{- end }}
              {{- if eq $tps "int64" }}
        {{ $k }} = {{ $v | int64 }}
              {{- end }}
              {{- if eq $tps "bool" }}
        {{ $k }} = {{ $v }}
              {{- end }}
              {{- if eq $tps "[]interface {}"}}
        {{ $k }} = [
                {{- $numOut := len $value }}
                {{- $numOut := sub $numOut 1 }}
                {{- range $b, $val := $v }}
                  {{- $i := int64 $b }}
                  {{- if eq $i $numOut }}
            {{ $val | quote }}
                  {{- else }}
            {{ $val | quote }},
                  {{- end }}
                {{- end }}
        ]
              {{- end }}
              {{- if eq $tps "map[string]interface {}"}}
        [[outputs.{{ $output }}.{{ $key }}.{{ $k }}]]
                {{- range $foo, $bar := $v }}
            {{ $foo }} = {{ $bar | quote }}
                {{- end }}
              {{- end }}
            {{- end }}
          {{- end }}
          {{- end }}
    {{- end }}
    {{- end }}
    {{ end }}
{{- end }}
{{- end -}}

{{- define "inputs" -}}
{{- range $inputIdx, $configObject := . -}}
    {{- range $input, $config := . -}}

    [[inputs.{{- $input }}]]
    {{- if $config -}}
    {{- $tp := typeOf $config -}}
    {{- if eq $tp "map[string]interface {}" -}}
        {{- range $key, $value := $config -}}
          {{- $tp := typeOf $value -}}
          {{- if eq $tp "string" }}
      {{ $key }} = {{ $value | quote }}
          {{- end }}
          {{- if eq $tp "float64" }}
      {{ $key }} = {{ $value | int64 }}
          {{- end }}
          {{- if eq $tp "int" }}
      {{ $key }} = {{ $value | int64 }}
          {{- end }}
          {{- if eq $tp "bool" }}
      {{ $key }} = {{ $value }}
          {{- end }}
          {{- if eq $tp "[]interface {}" }}
      {{ $key }} = [
              {{- $numOut := len $value }}
              {{- $numOut := sub $numOut 1 }}
              {{- range $b, $val := $value }}
                {{- $i := int64 $b }}
                {{- $tp := typeOf $val }}
                {{- if eq $i $numOut }}
                  {{- if eq $tp "string" }}
        {{ $val | quote }}
                  {{- end }}
                  {{- if eq $tp "float64" }}
        {{ $val | int64 }}
                  {{- end }}
                {{- else }}
                  {{- if eq $tp "string" }}
        {{ $val | quote }},
                  {{- end}}
                  {{- if eq $tp "float64" }}
        {{ $val | int64 }},
                  {{- end }}
                {{- end }}
              {{- end }}
      ]
          {{- end }}
          {{- if eq $tp "map[string]interface {}" }}
      [[inputs.{{ $input }}.{{ $key }}]]
            {{- range $k, $v := $value }}
              {{- $tps := typeOf $v }}
              {{- if eq $tps "string" }}
        {{ $k }} = {{ $v }}
              {{- end }}
              {{- if eq $tps "[]interface {}"}}
        {{ $k }} = [
                {{- $numOut := len $value }}
                {{- $numOut := sub $numOut 1 }}
                {{- range $b, $val := $v }}
                  {{- $i := int64 $b }}
                  {{- if eq $i $numOut }}
            {{ $val | quote }}
                  {{- else }}
            {{ $val | quote }},
                  {{- end }}
                {{- end }}
        ]
              {{- end }}
              {{- if eq $tps "map[string]interface {}"}}
        [[inputs.{{ $input }}.{{ $key }}.{{ $k }}]]
                {{- range $foo, $bar := $v }}
            {{ $foo }} = {{ $bar | quote }}
                {{- end }}
              {{- end }}
            {{- end }}
          {{- end }}
          {{- end }}
    {{- end }}
    {{- end }}
    {{ end }}
{{- end }}
{{- end -}}

{{- define "processors" -}}
{{- range $processorIdx, $configObject := . -}}
    {{- range $processor, $config := . -}}

    [[processors.{{- $processor }}]]
    {{- if $config -}}
    {{- $tp := typeOf $config -}}
    {{- if eq $tp "map[string]interface {}" -}}
        {{- range $key, $value := $config -}}
          {{- $tp := typeOf $value -}}
          {{- if eq $tp "string" }}
      {{ $key }} = {{ $value | quote }}
          {{- end }}
          {{- if eq $tp "float64" }}
      {{ $key }} = {{ $value | int64 }}
          {{- end }}
          {{- if eq $tp "int" }}
      {{ $key }} = {{ $value | int64 }}
          {{- end }}
          {{- if eq $tp "bool" }}
      {{ $key }} = {{ $value }}
          {{- end }}
          {{- if eq $tp "[]interface {}" }}
      {{ $key }} = [
              {{- $numOut := len $value }}
              {{- $numOut := sub $numOut 1 }}
              {{- range $b, $val := $value }}
                {{- $i := int64 $b }}
                {{- $tp := typeOf $val }}
                {{- if eq $i $numOut }}
                  {{- if eq $tp "string" }}
        {{ $val | quote }}
                  {{- end }}
                  {{- if eq $tp "float64" }}
        {{ $val | int64 }}
                  {{- end }}
                {{- else }}
                  {{- if eq $tp "string" }}
        {{ $val | quote }},
                  {{- end}}
                  {{- if eq $tp "float64" }}
        {{ $val | int64 }},
                  {{- end }}
                {{- end }}
              {{- end }}
      ]
          {{- end }}
          {{- if eq $tp "map[string]interface {}" }}
      [[processors.{{ $processor }}.{{ $key }}]]
            {{- range $k, $v := $value }}
              {{- $tps := typeOf $v }}
              {{- if eq $tps "string" }}
        {{ $k }} = {{ $v | quote }}
              {{- end }}
              {{- if eq $tps "[]interface {}"}}
        {{ $k }} = [
                {{- $numOut := len $value }}
                {{- $numOut := sub $numOut 1 }}
                {{- range $b, $val := $v }}
                  {{- $i := int64 $b }}
                  {{- if eq $i $numOut }}
            {{ $val | quote }}
                  {{- else }}
            {{ $val | quote }},
                  {{- end }}
                {{- end }}
        ]
              {{- end }}
              {{- if eq $tps "map[string]interface {}"}}
        [processors.{{ $processor }}.{{ $key }}.{{ $k }}]
                {{- range $foo, $bar := $v }}
                {{- $tp := typeOf $bar -}}
                {{- if eq $tp "string" }}
            {{ $foo }} = {{ $bar | quote }}
                {{- end }}
                {{- if eq $tp "int" }}
            {{ $foo }} = {{ $bar }}
                {{- end }}
                {{- if eq $tp "float64" }}
            {{ $foo }} = {{ int64 $bar }}
                {{- end }}
                {{- end }}
              {{- end }}
            {{- end }}
          {{- end }}
          {{- end }}
    {{- end }}
    {{- end }}
    {{ end }}
{{- end }}
{{- end -}}

{{/*
Create the name of the service account to use
*/}}
{{- define "telegraf.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
    {{ default (include "telegraf.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
    {{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}
 # configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "telegraf.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "telegraf.name" . }}
    helm.sh/chart: {{ include "telegraf.chart" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
data:
  telegraf.conf: |+
    {{ template "global_tags" .Values.config.global_tags }}
    {{ template "agent" .Values.config.agent }}
    {{ template "processors" .Values.config.processors }}
    {{ template "outputs" .Values.config.outputs }}
    {{ template "inputs" .Values.config.inputs -}}
 # deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "telegraf.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "telegraf.name" . }}
    helm.sh/chart: {{ include "telegraf.chart" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ include "telegraf.name" . }}
      app.kubernetes.io/instance: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app.kubernetes.io/name: {{ include "telegraf.name" . }}
        app.kubernetes.io/instance: {{ .Release.Name }}
      annotations:
        checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
        {{- if .Values.podAnnotations }}
{{ toYaml .Values.podAnnotations | indent 8 }}
        {{- end }}
    spec:
      serviceAccountName: {{ template "telegraf.serviceAccountName" . }}
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repo }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ default "" .Values.image.pullPolicy | quote }}
        resources:
{{ toYaml .Values.resources | indent 10 }}
        env:
{{ toYaml .Values.env | indent 8 }}
        volumeMounts:
        - name: config
          mountPath: /etc/telegraf
        {{- range .Values.volumeMounts}}
        - name: {{ .name }}
          mountPath: {{ .mountPath }}
        {{- end }}
        {{- range $objectKey, $objectValue := .Values.config.outputs }}
        {{- range $key, $value := . -}}
        {{- $tp := typeOf $value -}}
        {{- if eq $key "health" }}
        livenessProbe:
          httpGet:
            path: /
            port: {{ trimPrefix "http://:" $value.service_address | int64 }}
        readinessProbe:
          httpGet:
            path: /
            port: {{ trimPrefix "http://:" $value.service_address | int64 }}
        {{- end }}
        {{- end }}
        {{- end }}
      {{- if .Values.imagePullSecrets }}
      imagePullSecrets:
{{ toYaml .Values.imagePullSecrets | indent 8 }}
      {{- end }}
      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      volumes:
      - name: config
        configMap:
          name: {{ include "telegraf.fullname" . }}
      {{- if .Values.volumeMounts }}
{{ toYaml .Values.volumeMounts | indent 6 }}
      {{- end}}
 # role.yaml
{{- if .Values.rbac.create }}
apiVersion: rbac.authorization.k8s.io/v1beta1
{{- if .Values.rbac.clusterWide }}
kind: ClusterRole
{{- else }}
kind: Role
{{- end }}
metadata:
  name: {{ template "telegraf.fullname" . }}
  namespace: {{ .Release.Namespace }}
rules:
{{ toYaml .Values.rbac.rules | indent 2 }}
{{- end }} # rolebinding.yaml
{{- if .Values.rbac.create }}
apiVersion: rbac.authorization.k8s.io/v1beta1
{{- if .Values.rbac.clusterWide }}
kind: ClusterRoleBinding
{{- else }}
kind: RoleBinding
{{- end }}
metadata:
  name: {{ template "telegraf.fullname" . }}
subjects:
  - kind: ServiceAccount
    name: {{ template "telegraf.fullname" . }}
    namespace: {{ .Release.Namespace }}
roleRef:
  apiGroup: rbac.authorization.k8s.io
  {{- if .Values.rbac.clusterWide }}
  kind: ClusterRole
  {{- else }}
  kind: Role
  {{- end }}
  name: {{ template "telegraf.fullname" . }}
{{- end }} # service.yaml
{{- if .Values.service.enabled -}}
apiVersion: v1
kind: Service
metadata:
  name: {{ include "telegraf.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "telegraf.name" . }}
    helm.sh/chart: {{ include "telegraf.chart" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
  {{- if .Values.service.annotations }}
  annotations:
{{ toYaml .Values.service.annotations | indent 4 }}
  {{- end }}
spec:
  type: {{ .Values.service.type }}
  ports:
  {{- range $objectKey, $objectValue := .Values.config.outputs }}
  {{- range $key, $value := . -}}
  {{- $tp := typeOf $value -}}
  {{- if eq $key "health" }}
  - port: {{ trimPrefix "http://:" $value.service_address | int64 }}
    targetPort: {{ trimPrefix "http://:" $value.service_address | int64 }}
    name: "health"
    {{- end }}
  {{- end }}
  {{- end }}
  {{- range $objectKey, $objectValue := .Values.config.inputs }}
  {{- range $key, $value := . -}}
    {{- $tp := typeOf $value -}}
    {{- if eq $key "http_listener" }}
  - port: {{ trimPrefix ":" $value.service_address | int64 }}
    targetPort: {{ trimPrefix ":" $value.service_address | int64 }}
    name: "http-listener"
    {{- end }}
    {{- if eq $key "statsd" }}
  - port: {{ trimPrefix ":" $value.service_address | int64 }}
    targetPort: {{ trimPrefix ":" $value.service_address | int64 }}
    protocol: "UDP"
    name: "statsd"
    {{- end }}
    {{- if eq $key "tcp-listener" }}
  - port: {{ trimPrefix ":" $value.service_address | int64 }}
    targetPort: {{ trimPrefix ":" $value.service_address | int64 }}
    name: "tcp_listener"
    {{- end }}
    {{- if eq $key "udp-listener" }}
  - port: {{ trimPrefix ":" $value.service_address | int64 }}
    targetPort: {{ trimPrefix ":" $value.service_address | int64 }}
    protocol: "UDP"
    name: "udp_listener"
    {{- end }}
    {{- if eq $key "webhooks" }}
  - port: {{ trimPrefix ":" $value.service_address | int64 }}
    targetPort: {{ trimPrefix ":" $value.service_address | int64 }}
    name: "webhooks"
    {{- end }}
  {{- end -}}
  {{- end }}
  {{- range $objectKey, $objectValue := .Values.config.outputs }}
  {{- range $key, $value := . -}}
    {{- $tp := typeOf $value -}}
    {{- if eq $key "prometheus_client" }}
  - port: {{ trimPrefix ":" $value.listen | int64 }}
    targetPort: {{ trimPrefix ":" $value.listen | int64 }}
    name: "prometheus-client"
    {{- end }}
  {{- end -}}
  {{- end }}
  selector:
    app.kubernetes.io/name: {{ include "telegraf.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
 # serviceaccount.yaml
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
  name: {{ template "telegraf.serviceAccountName" . }}
  labels:
    app: {{ template "telegraf.name" . }}
    chart: {{ template "telegraf.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
{{- end }}

## Default values.yaml for Telegraf
## This is a YAML-formatted file.
## ref: https://hub.docker.com/r/library/telegraf/tags/

replicaCount: 1

image:
  repo: "telegraf"
  tag: "1.12-alpine"
  pullPolicy: IfNotPresent

podAnnotations: {}

imagePullSecrets: []

env:
  - name: HOSTNAME
    value: "telegraf-polling-service"

## Configure resource requests and limits
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
resources: {}
  # requests:
  #   memory: 128Mi
  #   cpu: 100m
  # limits:
  #   memory: 128Mi
  #   cpu: 100m

## Node labels for pod assignment
## ref: https://kubernetes.io/docs/user-guide/node-selection/
nodeSelector: {}

service:
  enabled: true
  type: ClusterIP
  annotations: {}

rbac:
  # Specifies whether RBAC resources should be created
  create: true
  # Create only for the release namespace or cluster wide (Role vs ClusterRole)
  clusterWide: false
  # Rules for the created rule
  rules: []
# When using the prometheus input to scrape all pods you need extra rules set to the ClusterRole to be
# able to scan the pods for scraping labels. The following rules have been taken from:
# https://github.com/helm/charts/blob/master/stable/prometheus/templates/server-clusterrole.yaml#L8-L46
#    - apiGroups:
#        - ""
#      resources:
#        - nodes
#        - nodes/proxy
#        - nodes/metrics
#        - services
#        - endpoints
#        - pods
#        - ingresses
#        - configmaps
#      verbs:
#        - get
#        - list
#        - watch
#    - apiGroups:
#        - "extensions"
#      resources:
#        - ingresses/status
#        - ingresses
#      verbs:
#        - get
#        - list
#        - watch
#    - nonResourceURLs:
#        - "/metrics"
#      verbs:
#        - get

serviceAccount:
  # Specifies whether a ServiceAccount should be created
  create: true
  # The name of the ServiceAccount to use.
  # If not set and create is true, a name is generated using the fullname template
  name:

## Exposed telegraf configuration
## For full list of possible values see `/docs/all-config-values.yaml` and `/docs/all-config-values.toml`
## ref: https://docs.influxdata.com/telegraf/v1.1/administration/configuration/
config:
  agent:
    interval: "10s"
    round_interval: true
    metric_batch_size: 1000
    metric_buffer_limit: 10000
    collection_jitter: "0s"
    flush_interval: "10s"
    flush_jitter: "0s"
    precision: ""
    debug: false
    quiet: false
    logfile: ""
    hostname: "$HOSTNAME"
    omit_hostname: false
  processors:
    - enum:
        mapping:
          field: "status"
          dest: "status_code"
          value_mappings:
            healthy: 1
            problem: 2
            critical: 3
  outputs:
    - health:
        service_address: "http://:8888"
        compares:
          field: buffer_size
          lt: 5000.0
        contains:
          field: buffer_size
    - influxdb:
        urls:
          - "http://influxdb.monitoring.svc:8086"
        database: "telegraf"
  inputs:
    - statsd:
        service_address: ":8125"
        percentiles:
          - 50
          - 95
          - 99
        metric_separator: "_"
        allowed_pending_messages: 10000
        percentile_limit: 1000
