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

{{/*
The name of the ServiceAccount used.
*/}}
{{- define "instana-agent.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
    {{ default (include "instana-agent.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
    {{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}

{{/*
The name of the PodSecurityPolicy used.
*/}}
{{- define "instana-agent.podSecurityPolicyName" -}}
{{- if .Values.podSecurityPolicy.enable -}}
{{ default (include "instana-agent.fullname" .) .Values.podSecurityPolicy.name }}
{{- end -}}
{{- end -}}

{{/*
Add Helm metadata to resource labels.
*/}}
{{- define "instana-agent.commonLabels" -}}
app.kubernetes.io/name: {{ include "instana-agent.name" . }}
{{ if .Values.templating -}}
app.kubernetes.io/version: {{ .Chart.Version }}
{{- else -}}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
helm.sh/chart: {{ include "instana-agent.chart" . }}
{{- end -}}
{{- end -}}

{{/*
Add Helm metadata to selector labels specifically for deployments/daemonsets/statefulsets.
*/}}
{{- define "instana-agent.selectorLabels" -}}
app.kubernetes.io/name: {{ include "instana-agent.name" . }}
{{- if not .Values.templating }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
{{- end -}}
 # agentsecret.yaml
{{- if or .Values.agent.key .Values.agent.downloadKey }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ template "instana-agent.fullname" . }}
  namespace: {{ .Release.Namespace }}
  labels:
    {{- include "instana-agent.commonLabels" . | nindent 4 }}
type: Opaque
data:
{{- if .Values.templating }}
  key: {{ .Values.agent.key }}
{{- else }}
  key: {{ .Values.agent.key | b64enc | quote }}
{{- end }}
{{- if .Values.agent.downloadKey }}
  downloadKey: {{ .Values.agent.downloadKey | b64enc | quote }}
{{- end }}
{{- end }}
 # clusterrole.yaml
{{- if .Values.rbac.create -}}
kind: ClusterRole
{{- if .Values.agent.supportOpenshift }}
apiVersion: v1
{{- else }}
apiVersion: rbac.authorization.k8s.io/v1
{{- end }}
metadata:
  name: {{ template "instana-agent.fullname" . }}
  labels:
    {{- include "instana-agent.commonLabels" . | nindent 4 }}
rules:
- nonResourceURLs:
    - "/version"
    - "/healthz"
  verbs: ["get"]
- apiGroups: ["batch"]
  resources:
    - "jobs"
    - "cronjobs"
  verbs: ["get", "list", "watch"]
- apiGroups: ["extensions"]
  resources:
    - "deployments"
    - "replicasets"
    - "ingresses"
  verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
  resources:
    - "deployments"
    - "replicasets"
    - "daemonsets"
    - "statefulsets"
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources:
    - "namespaces"
    - "events"
    - "services"
    - "endpoints"
    - "nodes"
    - "pods"
    - "replicationcontrollers"
    - "componentstatuses"
    - "resourcequotas"
    - "persistentvolumes"
    - "persistentvolumeclaims"
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources:
    - "endpoints"
  verbs: ["create", "update", "patch"]
- apiGroups: ["networking.k8s.io"]
  resources:
    - "ingresses"
  verbs: ["get", "list", "watch"]
{{- if .Values.agent.supportOpenshift }}
- apiGroups: ["apps.openshift.io"]
  resources:
    - "deploymentconfigs"
  verbs: ["get", "list", "watch"]
{{- end -}}
{{- if .Values.podSecurityPolicy.enable}}
- apiGroups: ["policy"]
  resources: ["podsecuritypolicies"]
  verbs:     ["use"]
  resourceNames:
  - {{ template "instana-agent.podSecurityPolicyName" . }}
{{- end -}}
{{- end -}}
 # clusterrolebinding.yaml
{{- if .Values.rbac.create -}}
kind: ClusterRoleBinding
{{- if .Values.agent.supportOpenshift }}
apiVersion: v1
{{- else }}
apiVersion: rbac.authorization.k8s.io/v1
{{- end }}
metadata:
  name: {{ template "instana-agent.fullname" . }}
  labels:
    {{- include "instana-agent.commonLabels" . | nindent 4 }}
subjects:
- kind: ServiceAccount
  name: {{ template "instana-agent.serviceAccountName" . }}
  namespace: {{ .Release.Namespace }}
roleRef:
  kind: ClusterRole
  name: {{ template "instana-agent.fullname" . }}
  {{- if not .Values.agent.supportOpenshift }}
  apiGroup: rbac.authorization.k8s.io
  {{- end -}}
{{- end -}}
 # configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ template "instana-agent.fullname" . }}
  namespace: {{ .Release.Namespace }}
  labels:
    {{- include "instana-agent.commonLabels" . | nindent 4 }}
data:
  configuration.yaml: |
    # Manual a-priori configuration. Configuration will be only used when the sensor
    # is actually installed by the agent.
    # The commented out example values represent example configuration and are not
    # necessarily defaults. Defaults are usually 'absent' or mentioned separately.
    # Changes are hot reloaded unless otherwise mentioned.

    # It is possible to create files called 'configuration-abc.yaml' which are
    # merged with this file in file system order. So 'configuration-cde.yaml' comes
    # after 'configuration-abc.yaml'. Only nested structures are merged, values are
    # overwritten by subsequent configurations.

    # Secrets
    # To filter sensitive data from collection by the agent, all sensors respect
    # the following secrets configuration. If a key collected by a sensor matches
    # an entry from the list, the value is redacted.
    #com.instana.secrets:
    #  matcher: 'contains-ignore-case' # 'contains-ignore-case', 'contains', 'regex'
    #  list:
    #    - 'key'
    #    - 'password'
    #    - 'secret'

    # Host
    #com.instana.plugin.host:
    #  tags:
    #    - 'dev'
    #    - 'app1'

    # Hardware & Zone
    #com.instana.plugin.generic.hardware:
    #  enabled: true # disabled by default
    #  availability-zone: 'zone'
  {{- if .Values.agent.configuration_yaml -}}
  {{ .Values.agent.configuration_yaml | nindent 4 }}
  {{- end }}
  {{- if .Values.agent.additionalBackends }}
  {{- $proxyHost := .Values.agent.proxyHost }}
  {{- $proxyPort := .Values.agent.proxyPort }}
  {{- $proxyUser := .Values.agent.proxyUser }}
  {{- $proxyPassword := .Values.agent.proxyPassword }}
  {{- $proxyUseDNS := .Values.agent.proxyUseDNS }}
  {{- range $index,$backend := .Values.agent.additionalBackends }}
  {{ $backendIndex :=add $index 2 -}}
  additional-backend-{{$backendIndex}}: |
    host={{ .endpointHost }}
    port={{ default 443 .endpointPort }}
    key={{ .key }}
    protocol=HTTP/2
  {{- if $proxyHost }}
    proxy.type=HTTP
    proxy.host={{ $proxyHost }}
    proxy.port={{ $proxyPort }}
  {{- if $proxyUser }}
    proxy.user={{ $proxyUser }}
    proxy.password={{ $proxyPassword }}
  {{- end }}
  {{- if $proxyUseDNS }}
    proxyUseDNS=true
  {{- end }}
  {{- end }}
  {{- end }}
  {{- end }}
 # daemonset.yaml
{{- if .Values.agent.key -}}
{{- if or .Values.zone.name .Values.cluster.name -}}
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: {{ template "instana-agent.fullname" . }}
  namespace: {{ .Release.Namespace }}
  labels:
    {{- include "instana-agent.commonLabels" . | nindent 4 }}
spec:
  selector:
    matchLabels:
      {{- include "instana-agent.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "instana-agent.commonLabels" . | nindent 8 }}
      {{- if .Values.agent.pod.annotations }}
      annotations:
        {{- toYaml .Values.agent.pod.annotations | nindent 8 }}
      {{- end }}
    spec:
      {{- if .Values.agent.pod.nodeSelector }}
      nodeSelector:
      {{- range $key, $value := .Values.agent.pod.nodeSelector }}
        {{ $key }}: {{ $value | quote }}
      {{- end }}
      {{- end }}
      serviceAccountName: {{ template "instana-agent.serviceAccountName" . }}
      hostIPC: true
      hostNetwork: true
      hostPID: true
      {{- if .Values.agent.pod.priorityClassName }}
      priorityClassName: {{ .Values.agent.pod.priorityClassName | quote }}
      {{- end }}
      dnsPolicy: ClusterFirstWithHostNet
      containers:
        - name: instana-agent
          image: "{{ .Values.agent.image.name }}:{{ .Values.agent.image.tag }}"
          imagePullPolicy: {{ .Values.agent.image.pullPolicy }}
          env:
            - name: INSTANA_AGENT_LEADER_ELECTOR_PORT
              value: {{ .Values.leaderElector.port | quote }}
            - name: INSTANA_ZONE
              value: {{ .Values.zone.name | quote }}
              {{- if .Values.cluster.name }}
            - name: INSTANA_KUBERNETES_CLUSTER_NAME
              value: {{ .Values.cluster.name | quote }}
              {{- end }}
            - name: INSTANA_AGENT_ENDPOINT
              value: {{ .Values.agent.endpointHost | quote }}
            - name: INSTANA_AGENT_ENDPOINT_PORT
              value: {{ .Values.agent.endpointPort | quote }}
            - name: INSTANA_AGENT_KEY
              valueFrom:
                secretKeyRef:
                  name: {{ template "instana-agent.fullname" . }}
                  key: key
            {{- if .Values.agent.mode }}
            - name: INSTANA_AGENT_MODE
              value: {{ .Values.agent.mode | quote }}
            {{- end }}
            {{- if .Values.agent.downloadKey }}
            - name: INSTANA_DOWNLOAD_KEY
              valueFrom:
                secretKeyRef:
                  name: {{ template "instana-agent.fullname" . }}
                  key: downloadKey
            {{- end }}
            {{- if .Values.agent.proxyHost }}
            - name: INSTANA_AGENT_PROXY_HOST
              value: {{ .Values.agent.proxyHost | quote }}
            {{- end }}
            {{- if .Values.agent.proxyPort }}
            - name: INSTANA_AGENT_PROXY_PORT
              value: {{ .Values.agent.proxyPort | quote }}
            {{- end }}
            {{- if .Values.agent.proxyProtocol }}
            - name: INSTANA_AGENT_PROXY_PROTOCOL
              value: {{ .Values.agent.proxyProtocol | quote }}
            {{- end }}
            {{- if .Values.agent.proxyUser }}
            - name: INSTANA_AGENT_PROXY_USER
              value: {{ .Values.agent.proxyUser | quote }}
            {{- end }}
            {{- if .Values.agent.proxyPassword }}
            - name: INSTANA_AGENT_PROXY_PASSWORD
              value: {{ .Values.agent.proxyPassword | quote }}
            {{- end }}
            {{- if .Values.agent.proxyUseDNS }}
            - name: INSTANA_AGENT_PROXY_USE_DNS
              value: {{ .Values.agent.proxyUseDNS | quote }}
            {{- end }}
            {{- if .Values.agent.listenAddress }}
            - name: INSTANA_AGENT_HTTP_LISTEN
              value: {{ .Values.agent.listenAddress | quote }}
            {{- end }}
            {{- if .Values.agent.redactKubernetesSecrets }}
            - name: INSTANA_KUBERNETES_REDACT_SECRETS
              value: {{ .Values.agent.redactKubernetesSecrets | quote }}
            {{- end }}
            - name: JAVA_OPTS
              # Approximately 1/3 of container memory requests to allow for direct-buffer memory usage and JVM overhead
              value: "-Xmx{{ div (default 512 .Values.agent.pod.requests.memory) 3 }}M -XX:+ExitOnOutOfMemoryError"
            - name: INSTANA_AGENT_POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
            {{- range $key, $value := .Values.agent.env }}
            - name: {{ $key }}
              value: {{ $value | quote }}
            {{- end }}
          securityContext:
            privileged: true
          volumeMounts:
            - name: dev
              mountPath: /dev
            - name: run
              mountPath: /run
            - name: var-run
              mountPath: /var/run
            - name: sys
              mountPath: /sys
            - name: var-log
              mountPath: /var/log
            - name: var-lib
              mountPath: /var/lib/containers/storage
            - name: machine-id
              mountPath: /etc/machine-id
            - name: configuration
              subPath: configuration.yaml
              mountPath: /root/configuration.yaml
            {{- if .Values.agent.host.repository }}
            - name: repo
              mountPath: /opt/instana/agent/data/repo
            {{- end }}
            {{- if .Values.agent.additionalBackends }}
            {{- range $index,$backend := .Values.agent.additionalBackends }}
            {{ $backendIndex :=add $index 2 -}}
            - name: additional-backend-{{$backendIndex}}
              subPath: additional-backend-{{$backendIndex}}
              mountPath: /opt/instana/agent/etc/instana/com.instana.agent.main.sender.Backend-{{$backendIndex}}.cfg
            {{- end }}
            {{- end }}
          livenessProbe:
            httpGet:
              path: /status
              port: 42699
            initialDelaySeconds: 300
            timeoutSeconds: 3
          resources:
            requests:
              memory: "{{ default 512 .Values.agent.pod.requests.memory }}Mi"
              cpu: {{ default 0.5 .Values.agent.pod.requests.cpu }}
            limits:
              memory: "{{ default 512 .Values.agent.pod.limits.memory }}Mi"
              cpu: {{ default 1.5 .Values.agent.pod.limits.cpu }}
          ports:
            - containerPort: 42699
        - name: instana-agent-leader-elector
          image: "{{ .Values.leaderElector.image.name }}:{{ .Values.leaderElector.image.tag }}"
          env:
            - name: INSTANA_AGENT_POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
          command:
            - "/busybox/sh"
            - "-c"
            - "sleep 12 && /app/server --election=instana --http=localhost:{{ .Values.leaderElector.port }} --id=$(INSTANA_AGENT_POD_NAME)"
          resources:
            requests:
              cpu: 0.1
              memory: 64Mi
          livenessProbe:
            httpGet: # Leader elector liveness is tied to agent, published on localhost:42699
              path: /com.instana.agent.coordination.sidecar/health
              port: 42699
            initialDelaySeconds: 300
            timeoutSeconds: 3
          ports:
            - containerPort: {{ .Values.leaderElector.port }}
      {{- if .Values.agent.pod.tolerations }}
      tolerations:
        {{- toYaml .Values.agent.pod.tolerations | nindent 8 }}
      {{- end }}
      volumes:
        - name: dev
          hostPath:
            path: /dev
        - name: run
          hostPath:
            path: /run
        - name: var-run
          hostPath:
            path: /var/run
        - name: sys
          hostPath:
            path: /sys
        - name: var-log
          hostPath:
            path: /var/log
        - name: var-lib
          hostPath:
            path: /var/lib/containers/storage
        - name: machine-id
          hostPath:
            path: /etc/machine-id
        - name: configuration
          configMap:
            name: {{ template "instana-agent.fullname" . }}
        {{- if .Values.agent.host.repository }}
        - name: repo
          hostPath:
            path: {{ .Values.agent.host.repository }}
        {{- end }}
        {{- if .Values.agent.additionalBackends }}
        {{- $fullname := include "instana-agent.fullname" . -}}
        {{- range $index,$backend := .Values.agent.additionalBackends }}
        {{ $backendIndex :=add $index 2 -}}
        - name: additional-backend-{{$backendIndex}}
          configMap:
            name: {{ $fullname }}
        {{- end }}
        {{- end }}
{{- end -}}
{{- end -}}
 # namespace.yaml
{{- if .Values.templating }}
apiVersion: v1
kind: Namespace
metadata:
  name: {{ .Release.Namespace }}
  labels:
    {{- include "instana-agent.commonLabels" . | nindent 4 }}
{{- end }}
 # podsecuritypolicy.yaml
{{- if .Values.rbac.create -}}
{{- if (and .Values.podSecurityPolicy.enable (not .Values.podSecurityPolicy.name)) -}}
kind: PodSecurityPolicy
apiVersion: policy/v1beta1
metadata:
  name: {{ template "instana-agent.podSecurityPolicyName" . }}
  namespace: {{ .Release.Namespace }}
  labels:
    {{- include "instana-agent.commonLabels" . | nindent 4 }}
spec:
  privileged: true
  allowPrivilegeEscalation: true
  volumes:
    - configMap
    - downwardAPI
    - emptyDir
    - persistentVolumeClaim
    - secret
    - projected
    - hostPath
  allowedHostPaths:
    - pathPrefix: "/dev"
      readOnly: false
    - pathPrefix:  "/run"
      readOnly: false
    - pathPrefix: "/var/run"
      readOnly: false
    - pathPrefix: "/sys"
      readOnly: false
    - pathPrefix: "/var/log"
      readOnly: false
    - pathPrefix: "/etc/machine-id"
      readOnly: false
    - pathPrefix: "/var/lib/containers/storage"
      readOnly: false
    {{- if .Values.agent.host.repository }}
    - pathPrefix: {{ .Values.agent.host.repository }}
      readOnly: false
    {{- end }}
  hostNetwork: true
  hostPorts:
    - min: 0
      max: 65535
  hostIPC: true
  hostPID: true
  runAsUser:
    rule: "RunAsAny"
  seLinux:
    rule: "RunAsAny"
  supplementalGroups:
    rule: "RunAsAny"
  fsGroup:
    rule: "RunAsAny"
{{- end -}}
{{- end -}}
 # serviceaccount.yaml
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
  name: {{ template "instana-agent.serviceAccountName" . }}
  namespace: {{ .Release.Namespace }}
  labels:
    {{- include "instana-agent.commonLabels" . | nindent 4 }}
{{- end -}}

# name is the value which will be used as the base resource name for various resources associated with the agent.
# name: instana-agent

agent:
  # agent.key is the secret token which your agent uses to authenticate to Instana's servers.
  key: null
  # agent.mode is used to set agent mode and it can be APM, INFRASTRUCTURE or AWS
  # mode: APM
  # agent.downloadKey is optional, if used it doesn't have to match agent.key
  # downloadKey: null
  # agent.listenAddress is the IP address the agent HTTP server will listen to.
  # listenAddress: *

  # agent.endpointHost is the hostname of the Instana server your agents will connect to.
  endpointHost: ingress-red-saas.instana.io
  # agent.endpointPort is the port number (as a String) of the Instana server your agents will connect to.
  endpointPort: 443

  # These are additional backends the Instana agent will report to besides
  # the one configured via the `agent.endpointHost`, `agent.endpointPort` and `agent.key` setting
  additionalBackends: []
    # - endpointHost: ingress.instana.io
    #   endpointPort: 443
    #   key: <agent_key>

  image:
    # agent.image.name is the name of the container image of the Instana agent.
    name: instana/agent
    # agent.image.tag is the tag name of the agent container image.
    tag: latest
    # agent.image.pullPolicy specifies when to pull the image container.
    pullPolicy: Always

  pod:
    # agent.pod.annotations are additional annotations to be added to the agent pods.
    annotations: {}

    # agent.pod.tolerations are tolerations to influence agent pod assignment.
    #   https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
    tolerations: []

    # agent.pod.priorityClassName is the name of an existing PriorityClass that should be set on the agent pods
    #   https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
    priorityClassName: null

    requests:
      # agent.pod.requests.memory is the requested memory allocation in MiB for the agent pods.
      memory: 512
      # agent.pod.requests.cpu are the requested CPU units allocation for the agent pods.
      cpu: 0.5
    limits:
      # agent.pod.limits.memory set the memory allocation limits in MiB for the agent pods.
      memory: 512
      # agent.pod.limits.cpu sets the CPU units allocation limits for the agent pods.
      cpu: 1.5

  # agent.proxyHost sets the INSTANA_AGENT_PROXY_HOST environment variable.
  # proxyHost: null
  # agent.proxyPort sets the INSTANA_AGENT_PROXY_PORT environment variable.
  # proxyPort: 80
  # agent.proxyProtocol sets the INSTANA_AGENT_PROXY_PROTOCOL environment variable.
  # proxyProtocol: HTTP
  # agent.proxyUser sets the INSTANA_AGENT_PROXY_USER environment variable.
  # proxyUser: null
  # agent.proxyPassword sets the INSTANA_AGENT_PROXY_PASSWORD environment variable.
  # proxyPassword: null
  # agent.proxyUseDNS sets the INSTANA_AGENT_PROXY_USE_DNS environment variable.
  # proxyUseDNS: false

  # use this to set additional environment variables for the instana agent
  # for example:
  # env:
  #   INSTANA_AGENT_TAGS: dev
  env: {}

  configuration_yaml: |
    # Place agent configuration here

  # agent.redactKubernetesSecrets sets the INSTANA_KUBERNETES_REDACT_SECRETS environment variable.
  # redactKubernetesSecrets: null

  # agent.host.repository sets a host path to be mounted as the agent maven repository (for debugging or development purposes)
  host:
    repository: null

  # agent.supportOpenshift specifies whether the cluster role should include openshift permissions
  # supportOpenshift: true

cluster:
  # cluster.name represents the name that will be assigned to this cluster in Instana
  name: null

leaderElector:
  image:
    # leaderElector.image.name is the name of the container image of the leader elector.
    name: instana/leader-elector
    # leaderElector.image.tag is the tag name of the agent container image.
    tag: 0.5.4
  port: 42655

rbac:
  # Specifies whether RBAC resources should be created
  create: true

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: instana-agent

podSecurityPolicy:
  # Specifies whether a PodSecurityPolicy should be authorized for the Instana Agent pods.
  # Requires `rbac.create` to be `true` as well.
  enable: false
  # The name of an existing PodSecurityPolicy you would like to authorize for the Instana Agent pods.
  # If not set and `enable` is true, a PodSecurityPolicy will be created with a name generated using the fullname template.
  name: null

zone:
  # zone.name is the custom zone that detected technologies will be assigned to
  name: null
