Add helm chart with basic CI tasks
continuous-integration/drone/push Build is passing Details

master
Drew Bednar 1 year ago
parent ab06ee1ae2
commit 49646c1b1d

@ -6,6 +6,8 @@ repos:
- id: trailing-whitespace - id: trailing-whitespace
- id: end-of-file-fixer - id: end-of-file-fixer
- id: check-yaml - id: check-yaml
exclude:
^(charts/speech-collect/templates)
- id: check-added-large-files - id: check-added-large-files
- id: debug-statements - id: debug-statements
- repo: https://github.com/shellcheck-py/shellcheck-py - repo: https://github.com/shellcheck-py/shellcheck-py

@ -1,4 +1,4 @@
# speech_collect # Speech Collect
![build-status](https://drone.runcible.io/api/badges/androiddrew/speech-collect/status.svg) ![build-status](https://drone.runcible.io/api/badges/androiddrew/speech-collect/status.svg)

@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

@ -0,0 +1,6 @@
apiVersion: v2
name: speech-collect
description: A Helm chart to deploy the Speech-Collect web service
type: application
version: 0.1.0
appVersion: "0.1.0"

@ -0,0 +1,22 @@
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "speech-collect.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "speech-collect.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "speech-collect.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "speech-collect.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}

@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "speech-collect.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 "speech-collect.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 "speech-collect.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "speech-collect.labels" -}}
helm.sh/chart: {{ include "speech-collect.chart" . }}
{{ include "speech-collect.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "speech-collect.selectorLabels" -}}
app.kubernetes.io/name: {{ include "speech-collect.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "speech-collect.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "speech-collect.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

@ -0,0 +1,60 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Chart.Name }}-api
labels:
app: {{ .Chart.Name }}-api
{{- include "speech-collect.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.components.api.replicas }}
selector:
matchLabels:
app: {{ .Chart.Name }}-api
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
app: {{ .Chart.Name }}-api
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ .Values.serviceAccount.name }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}-api
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.components.api.port }}
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
{{- toYaml .Values.components.api.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: {{ .Chart.Name }}-api-service
labels:
{{- include "speech-collect.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: 80
targetPort: {{ .Values.components.api.port }}
protocol: TCP
selector:
app: {{ .Chart.Name }}-api

@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ $.Release.Name }}-{{ $.Chart.Name }}-configmap
data:
EXAMPLE_VALUE: "static"
{{- range $key, $val := .Values.configEnvVars }}
{{ $key }}: {{ $val | quote }}
{{- end }}

@ -0,0 +1,61 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "speech-collect.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "speech-collect.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

@ -0,0 +1,12 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.serviceAccount.name }}
labels:
{{- include "speech-collect.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

@ -0,0 +1,76 @@
image:
repository: registry.runcible.io/speech-collect
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
labels: {}
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: "speech-collect-sa"
podAnnotations: {}
podSecurityContext: {}
# fsGroup: 2000
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1337
service:
type: ClusterIP
port: 80
ingress:
enabled: false
className: "nginx"
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
nodeSelector: {}
tolerations: []
affinity: {}
components:
api:
replicas: 1
port: 8000
resources: {}
# If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
configEnvVars:
EXAMPLE_TWO: "value2"

@ -1,5 +1,10 @@
import os
from invoke import task from invoke import task
SPEECH_COLLECT_RESPOSITORY = os.environ.get("SPEECH_COLLECT_RESPOSITORY", "registry.runcible.io/speech-collect")
SPEECH_COLLECT_HELM_CHART_DIR = "./charts/speech-collect"
@task @task
def serve(c): def serve(c):
@ -35,3 +40,33 @@ def delint(c):
"""Applies automated linters to project""" """Applies automated linters to project"""
c.run("isort ./speech_collect ./tests ./tasks.py", pty=True) c.run("isort ./speech_collect ./tests ./tasks.py", pty=True)
c.run("black ./speech_collect ./tests ./tasks.py", pty=True) c.run("black ./speech_collect ./tests ./tasks.py", pty=True)
@task
def template_chart(c, values=None):
"""Templates the speech-collect Helm chart with an optional custom values.yaml"""
cmd = f"helm template {SPEECH_COLLECT_HELM_CHART_DIR}"
if values:
cmd += f" --values {values}"
c.run(cmd)
@task
def rebuild_chart(c):
"""Rebuilds the speech-collect helm chart"""
c.run(f"ls {SPEECH_COLLECT_HELM_CHART_DIR}")
c.run(f"rm -rf {SPEECH_COLLECT_HELM_CHART_DIR}/Chart.lock {SPEECH_COLLECT_HELM_CHART_DIR}/charts")
# c.run(f"helm dependency update --respository-config .charts/repositories.yaml {SPEECH_COLLECT_HELM_CHART_DIR}")
@task(pre=[rebuild_chart])
def package_chart(c, pre_release=None, destination="./build"):
"""Packages the speech-collect helm chart."""
# Helm requires a valid semantic version.
# See https://semver.org
chart_version = c.run(
f"helm show chart {SPEECH_COLLECT_HELM_CHART_DIR} | grep version | tail -1 | cut -d ':' -f2 | xargs"
).stdout.strip()
if pre_release is not None:
chart_version = chart_version + str(pre_release)
c.run(f"helm package {SPEECH_COLLECT_HELM_CHART_DIR} --version {chart_version} --destination {destination}")

Loading…
Cancel
Save