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

{{/*
Create fully qualified names.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "master-fullname" -}}
{{- $name := default .Chart.Name .Values.Master.Name -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{- define "webui-fullname" -}}
{{- $name := default .Chart.Name .Values.WebUi.Name -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{- define "worker-fullname" -}}
{{- $name := default .Chart.Name .Values.Worker.Name -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{- define "zeppelin-fullname" -}}
{{- $name := default .Chart.Name .Values.Zeppelin.Name -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Return the apiVersion of deployment.
*/}}
{{- define "deployment.apiVersion" -}}
{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}}
{{- print "extensions/v1beta1" -}}
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
{{- print "apps/v1" -}}
{{- end -}}
{{- end -}}
 # spark-master-deployment.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ template "master-fullname" . }}
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Master.Component }}"
spec:
  ports:
    - port: {{ .Values.Master.ServicePort }}
      targetPort: {{ .Values.Master.ContainerPort }}
  selector:
    component: "{{ .Release.Name }}-{{ .Values.Master.Component }}"
---
apiVersion: v1
kind: Service
metadata:
  name: {{ template "webui-fullname" . }}
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Master.Component }}"
spec:
  ports:
    - port: {{ .Values.WebUi.ServicePort }}
      targetPort: {{ .Values.WebUi.ContainerPort }}
  selector:
    component: "{{ .Release.Name }}-{{ .Values.Master.Component }}"
  type: {{ .Values.Master.ServiceType }}
---
apiVersion: {{ template "deployment.apiVersion" . }}
kind: Deployment
metadata:
  name: {{ template "master-fullname" . }}
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Master.Component }}"
spec:
  replicas: {{ default 1 .Values.Master.Replicas }}
  strategy:
    type: RollingUpdate
  selector:
    matchLabels:
      component: "{{ .Release.Name }}-{{ .Values.Master.Component }}"
  template:
    metadata:
      labels:
        heritage: {{ .Release.Service | quote }}
        release: {{ .Release.Name | quote }}
        chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
        component: "{{ .Release.Name }}-{{ .Values.Master.Component }}"
    spec:
      containers:
        - name: {{ template "master-fullname" . }}
          image: "{{ .Values.Master.Image }}:{{ .Values.Master.ImageTag }}"
          command: ["/bin/sh","-c"]
          args: ["echo $(hostname -i) {{ template "master-fullname" . }} >> /etc/hosts; {{ .Values.Spark.Path }}/bin/spark-class org.apache.spark.deploy.master.Master"]
          ports:
            - containerPort: {{ .Values.Master.ContainerPort }}
            - containerPort: {{ .Values.WebUi.ContainerPort }}
          resources:
            requests:
              cpu: "{{ .Values.Master.Cpu }}"
              memory: "{{ .Values.Master.Memory }}"
          env:
          - name: SPARK_DAEMON_MEMORY
            value: {{ default "1g" .Values.Master.DaemonMemory | quote }}
          - name: SPARK_MASTER_HOST
            value: {{ template "master-fullname" . }}
          - name: SPARK_MASTER_PORT
            value: {{ .Values.Master.ServicePort | quote }}
          - name: SPARK_MASTER_WEBUI_PORT
            value: {{ .Values.WebUi.ContainerPort | quote }}
 # spark-sql-test.yaml
apiVersion: v1
kind: Pod
metadata:
  name: "{{ .Release.Name }}-sql-test-{{ randAlphaNum 5 | lower }}"
  annotations:
    "helm.sh/hook": test-success
spec:
  containers:
    - name: {{ .Release.Name }}-sql-test
      image: {{ .Values.Master.Image }}:{{ .Values.Master.ImageTag }}
      command: ["{{ .Values.Spark.Path }}/bin/spark-sql", "--master",
                "spark://{{ .Release.Name }}-master:{{ .Values.Master.ServicePort }}", "-e",
                "show databases;"]
  restartPolicy: Never
 # spark-worker-deployment.yaml
apiVersion: {{ template "deployment.apiVersion" . }}
kind: Deployment
metadata:
  name: {{ template "worker-fullname" . }}
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Worker.Component }}"
spec:
{{- if not .Values.Worker.Autoscaling.Enabled }}
  replicas: {{ default 1 .Values.Worker.Replicas }}
{{- end }}
  strategy:
    type: RollingUpdate
  selector:
    matchLabels:
      component: "{{ .Release.Name }}-{{ .Values.Worker.Component }}"
  template:
    metadata:
      labels:
        heritage: {{ .Release.Service | quote }}
        release: {{ .Release.Name | quote }}
        chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
        component: "{{ .Release.Name }}-{{ .Values.Worker.Component }}"
    spec:
      containers:
        - name: {{ template "worker-fullname" . }}
          image: "{{ .Values.Worker.Image }}:{{ .Values.Worker.ImageTag }}"
          command: ["{{ .Values.Spark.Path }}/bin/spark-class", "org.apache.spark.deploy.worker.Worker", "spark://{{ template "master-fullname" . }}:{{ .Values.Master.ServicePort }}"]
          ports:
            - containerPort: {{ .Values.Worker.ContainerPort }}
          resources:
            requests:
              cpu: "{{ .Values.Worker.Cpu }}"
              memory: "{{ .Values.Worker.Memory }}"
          env:
          - name: SPARK_DAEMON_MEMORY
            value: {{ default "1g" .Values.Worker.DaemonMemory | quote }}
          - name: SPARK_WORKER_MEMORY
            value: {{ default "1g" .Values.Worker.ExecutorMemory | quote }}
          - name: SPARK_WORKER_WEBUI_PORT
            value: {{ .Values.WebUi.ContainerPort | quote }}
 # spark-worker-hpa.yaml
{{- if .Values.Worker.Autoscaling.Enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Worker.Component }}"
  name: {{ template "worker-fullname" . }}
spec:
  scaleTargetRef:
    apiVersion: {{ template "deployment.apiVersion" . }}
    kind: Deployment
    name: {{ template "worker-fullname" . }}
  minReplicas: {{ .Values.Worker.Replicas }}
  maxReplicas: {{ .Values.Worker.ReplicasMax }}
  metrics:
  - type: Resource
    resource:
      name: cpu
      targetAverageUtilization: {{ .Values.Worker.CpuTargetPercentage }}
{{- end }}
 # spark-zeppelin-config-pvc.yaml
{{ $persistence := .Values.Zeppelin.Persistence.Config }}
{{- if $persistence.Enabled }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: {{ template "zeppelin-fullname" . }}-config
spec:
  accessModes:
    - {{ $persistence.AccessMode | quote }}
  resources:
    requests:
      storage: {{ $persistence.Size | quote }}
{{- if $persistence.StorageClass }}
{{- if (eq "-" $persistence.StorageClass) }}
  storageClassName: ""
{{- else }}
  storageClassName: "{{ $persistence.StorageClass }}"
{{- end }}
{{- end }}
{{- end }} # spark-zeppelin-deployment.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ template "zeppelin-fullname" . }}
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Zeppelin.Component }}"
spec:
  ports:
    - name: http
      port: {{ .Values.Zeppelin.ServicePort }}
      targetPort: {{ .Values.Zeppelin.ContainerPort }}
  selector:
    component: "{{ .Release.Name }}-{{ .Values.Zeppelin.Component }}"
  type: {{ .Values.Zeppelin.ServiceType }}
---
apiVersion: {{ template "deployment.apiVersion" . }}
kind: Deployment
metadata:
  name: {{ template "zeppelin-fullname" . }}
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Zeppelin.Component }}"
spec:
  replicas: {{ default 1 .Values.Zeppelin.Replicas }}
  strategy:
    type: RollingUpdate
  selector:
    matchLabels:
      component: "{{ .Release.Name }}-{{ .Values.Zeppelin.Component }}"
  template:
    metadata:
      labels:
        heritage: {{ .Release.Service | quote }}
        release: {{ .Release.Name | quote }}
        chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
        component: "{{ .Release.Name }}-{{ .Values.Zeppelin.Component }}"
    spec:
      containers:
        - name: {{ template "zeppelin-fullname" . }}
          image: "{{ .Values.Zeppelin.Image }}:{{ .Values.Zeppelin.ImageTag }}"
          ports:
            - containerPort: {{ .Values.Zeppelin.ContainerPort }}
              name: http
          resources:
            requests:
              cpu: "{{ .Values.Zeppelin.Cpu }}"
          env:
            - name: SPARK_MASTER
              value: "spark://{{ template "master-fullname" . }}:{{ .Values.Master.ServicePort }}"
          volumeMounts:
          {{- if .Values.Zeppelin.Persistence.Config.Enabled }}
            - name: {{ template "master-fullname" . }}-config
              mountPath: /zeppelin/conf
          {{- end }}
          {{- if .Values.Zeppelin.Persistence.Notebook.Enabled }}
            - name: {{ template "master-fullname" . }}-notebook
              mountPath: /zeppelin/notebook
          {{- end }}
      volumes:
        {{- if .Values.Zeppelin.Persistence.Config.Enabled }}
        - name: {{ template "master-fullname" . }}-config
          persistentVolumeClaim:
            claimName: {{ template "zeppelin-fullname" . }}-config
        {{- end }}
        {{- if .Values.Zeppelin.Persistence.Notebook.Enabled }}
        - name: {{ template "master-fullname" . }}-notebook
          persistentVolumeClaim:
            claimName: {{ template "zeppelin-fullname" . }}-notebook
        {{- end }}
 # spark-zeppelin-ingress.yaml
{{- $ingress := .Values.Zeppelin.Ingress -}}
{{- $fullName := include "zeppelin-fullname" . -}}
{{- if $ingress.Enabled }}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{ template "zeppelin-fullname" . }}
{{- if $ingress.Annotations }}
  annotations:
{{ toYaml $ingress.Annotations | indent 4 }}
{{- end }}
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Zeppelin.Component }}"
spec:
{{- if $ingress.Tls }}
  tls:
  {{- range $ingress.Tls }}
  - hosts:
    {{- range .Hosts }}
    - {{ . }}
    {{- end }}
    secretName: {{ .SecretName | default (printf "%s-tls" $fullName) }}
{{- end }}
{{- end }}
  {{- if $ingress.Hosts }}
  rules:
  {{- range $ingress.Hosts }}
  - host: {{ . }}
    http:
      paths:
      - path: {{ $ingress.Path }}
        backend:
          serviceName: {{ $fullName }}
          servicePort: http
  {{- end }}
{{- else }}
  backend:
    serviceName: {{ template "zeppelin-fullname" . }}
    servicePort: http
{{- end }}
{{- end }}
 # spark-zeppelin-notebook-pvc.yaml
{{ $persistence := .Values.Zeppelin.Persistence.Notebook }}
{{- if $persistence.Enabled }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: {{ template "zeppelin-fullname" . }}-notebook
spec:
  accessModes:
    - {{ $persistence.AccessMode | quote }}
  resources:
    requests:
      storage: {{ $persistence.Size | quote }}
{{- if $persistence.StorageClass }}
{{- if (eq "-" $persistence.StorageClass) }}
  storageClassName: ""
{{- else }}
  storageClassName: "{{ $persistence.StorageClass }}"
{{- end }}
{{- end }}
{{- end }}
# Default values for spark.
# This is a YAML-formatted file.
# Declare name/value pairs to be passed into your templates.
# name: value

Spark:
  Path: "/opt/spark"

Master:
  Name: master
  Image: "k8s.gcr.io/spark"
  ImageTag: "1.5.1_v3"
  Replicas: 1
  Component: "spark-master"
  Cpu: "100m"
  Memory: "512Mi"
  ServicePort: 7077
  ContainerPort: 7077
  # Set Master JVM memory. Default 1g
  # DaemonMemory: 1g
  ServiceType: LoadBalancer

WebUi:
  Name: webui
  ServicePort: 8080
  ContainerPort: 8080

Worker:
  Name: worker
  Image: "k8s.gcr.io/spark"
  ImageTag: "1.5.1_v3"
  Replicas: 3
  Component: "spark-worker"
  Cpu: "100m"
  Memory: "512Mi"
  ContainerPort: 8081
  # Set Worker JVM memory. Default 1g
  # DaemonMemory: 1g
  # Set how much total memory workers have to give executors
  # ExecutorMemory: 1g
  Autoscaling:
    Enabled: false
  ReplicasMax: 10
  CpuTargetPercentage: 50

Zeppelin:
  Name: zeppelin
  Image: "apache/zeppelin"
  ImageTag: "0.7.3"
  Replicas: 1
  Component: "zeppelin"
  Cpu: "100m"
  ServicePort: 8080
  ContainerPort: 8080
  ServiceType: LoadBalancer
  Ingress:
    Enabled: false
    Path: "/"
    Tls: []
  #    - Hosts:
  #    SecretName: zeppelin
  # Used to create an Ingress record.
  # Hosts:
  # - example.local
  # Annotations:
  #   kubernetes.io/ingress.class: nginx
  #   kubernetes.io/tls-acme: "true"
  # Tls:
  #   Enabled: true
  # Secrets must be manually created in the namespace.
  #   SecretName: example-tls
  #   Hosts:
  #   - example.local
  Persistence:
    Config:
      Enabled: false
      ## etcd data Persistent Volume Storage Class
      ## If defined, storageClassName: <storageClass>
      ## If set to "-", storageClassName: "", which disables dynamic provisioning
      ## If undefined (the default) or set to null, no storageClassName spec is
      ## set, choosing the default provisioner. (gp2 on AWS, standard on
      ## GKE, AWS & OpenStack)
      StorageClass: "-"
      ## Set default PVC size
      Size: 10G
      ## Set default PVC access mode: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes
      AccessMode: ReadWriteOnce
    Notebook:
      Enabled: false
      StorageClass: "-"
      Size: 10G
      AccessMode: ReadWriteOnce
