Compare commits

...

11 commits

Author SHA1 Message Date
2892c7afea Remove blocking helm annotation 2021-01-13 10:25:59 +01:00
cb83fa9c30 Fix duplicate values section 2021-01-13 10:24:02 +01:00
f8e5b96886 Mount volume in job too 2021-01-13 07:47:31 +01:00
cf233cacad Add persistence 2021-01-13 07:38:54 +01:00
550a71b599 Add missing Job policy 2021-01-12 21:01:35 +01:00
44f8aee7e2 Move Install phase into Job 2021-01-12 20:54:31 +01:00
b14cad0db2 Make database configurable 2021-01-12 19:08:05 +01:00
bfc6a915d7 Make helm chart runnable
Setup script checks haveibeenpwned for weak passwords, and does not let
us continue the setup process.
2021-01-12 13:26:52 +01:00
3c0b6d682a Ingress always requires a path 2021-01-12 13:17:51 +01:00
ccc9bbe0c8 Use securityContexts 2021-01-12 13:10:25 +01:00
1b39b9db29 Initial Mediawiki version 2021-01-12 13:00:01 +01:00
11 changed files with 514 additions and 0 deletions

View file

@ -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/

View file

@ -0,0 +1,9 @@
apiVersion: v2
name: mediawiki
description: A wiki with semantic extensions
type: application
version: 0.0.0
appVersion: 3.15.1

View file

@ -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 }}{{ . }}
{{- 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 "mediawiki.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 "mediawiki.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mediawiki.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 "mediawiki.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 }}

View file

@ -0,0 +1,131 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "mediawiki.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 "mediawiki.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 "mediawiki.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "mediawiki.labels" -}}
helm.sh/chart: {{ include "mediawiki.chart" . }}
{{ include "mediawiki.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "mediawiki.selectorLabels" -}}
app.kubernetes.io/name: {{ include "mediawiki.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Common environment values
*/}}
{{- define "mediawiki.env" -}}
- name: WG_SERVER
value: {{ .Values.wiki.server | quote }}
- name: MEDIAWIKI_ADMIN_USER
value: "admin"
- name: MEDIAWIKI_ADMIN_PASS
value: "hardcodedexamplepasswordthatwillbereplacedlater" # FIXME
- name: ALLOW_PUBLIC_EDIT
value: "true" # FIXME
- name: WG_SECRET_KEY
value: {{ .Values.wiki.secretKey }}
- name: WG_DB_TYPE
value: {{ .Values.database.type }}
- name: WG_DB_SERVER
value: {{ .Values.database.server }}
- name: WG_DB_PORT
value: {{ .Values.database.port | quote }}
- name: WG_DB_NAME
value: {{ .Values.database.name }}
- name: WG_DB_USER
{{- if .Values.database.secretName }}
valueFrom:
secretKeyRef:
name: {{ .Values.database.secretName }}
key: username
{{- else }}
value: {{ .Values.database.username }}
{{- end }}
- name: WG_DB_PASSWORD
{{- if .Values.database.secretName }}
valueFrom:
secretKeyRef:
name: {{ .Values.database.secretName }}
key: password
{{- else }}
value: {{ .Values.database.password }}
{{- end }}
#WG_SITENAME="Test Wiki"
#WG_SCRIPT_PATH=""
#WG_SERVER="https://wiki.example.com"
#SEMANTIC_URL="wiki.example.com"
#WG_ENABLE_UPLOADS="false"
#WG_ENABLE_EMAIL="false"
#WG_UPLOAD_PATH="/uploads"
#WG_META_NAMESPACE="Meta"
#WG_LANGUAGE_CODE="en"
#MEDIAWIKI_ADMIN_USER="admin"
#MEDIAWIKI_ADMIN_PASS="password"
#WG_DB_TYPE="sqlite"
#WG_DB_SERVER=""
#WG_DB_NAME="my_wiki"
#WG_DB_PASSWORD="password"
#WG_DB_PREFIX=""
#WG_DB_MWSCHEMA=""
#WG_DATABASE_DIR="/var/www/data"
#WG_SECRET_KEY="0000000000000000000000000000000000000000000000000000000000000000"
#WG_EMERGENCY_CONTACT="admin@example.com"
#WG_PASSWORD_SENDER="wiki@example.com"
#ALLOW_PUBLIC_REGISTRATION="false"
#ALLOW_PUBLIC_EDIT="false"
#ALLOW_PUBLIC_READ="true"
#DISABLE_ICONS="false"
#DEBUG="false"
{{- end }}

View file

@ -0,0 +1,99 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mediawiki.fullname" . }}
labels:
{{- include "mediawiki.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "mediawiki.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "mediawiki.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}-web
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
{{- include "mediawiki.env" . | nindent 12 }}
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
volumeMounts:
- name: data-volume
mountPath: /var/www/data
- name: localstore-volume
mountPath: /var/www/localstore
{{- with .Values.extraVolumeMounts }}
{{- tpl . $ | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
- name: {{ .Chart.Name }}-cron
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ['crontab-foreground']
env:
{{- include "mediawiki.env" . | nindent 12 }}
volumeMounts:
- name: data-volume
mountPath: /var/www/data
- name: localstore-volume
mountPath: /var/www/localstore
{{- with .Values.extraVolumeMounts }}
{{- tpl . $ | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumes:
- name: localstore-volume
{{- if .Values.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ default (include "mediawiki.fullname" .) .Values.persistence.existingClaim }}
{{- else }}
emptyDir: {}
{{- end }}
- name: data-volume
emptyDir: {}
{{- with .Values.extraVolumes }}
{{- tpl . $ | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

View file

@ -0,0 +1,41 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "mediawiki.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- 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 "mediawiki.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- 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: {{ . }}
backend:
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,52 @@
{{- if and .Values.wiki.install (ne "sqlite" .Values.database.type) }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "mediawiki.fullname" . }}-setup
labels:
{{- include "mediawiki.labels" . | nindent 4 }}
spec:
template:
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
restartPolicy: OnFailure
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: setup
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ['db-setup.sh']
env:
{{- include "mediawiki.env" . | nindent 12 }}
volumeMounts:
- name: data-volume
mountPath: /var/www/data
- name: localstore-volume
mountPath: /var/www/localstore
volumes:
- name: localstore-volume
{{- if .Values.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ default (include "mediawiki.fullname" .) .Values.persistence.existingClaim }}
{{- else }}
emptyDir: {}
{{- end }}
- name: data-volume
emptyDir: {}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{ end }}

View file

@ -0,0 +1,21 @@
{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) -}}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: {{ include "mediawiki.fullname" . }}
labels:
{{- include "mediawiki.labels" . | nindent 4 }}
{{- if .Values.persistence.annotations }}
annotations:
{{ toYaml .Values.persistence.annotations | indent 4 }}
{{- end }}
spec:
accessModes:
- {{ .Values.persistence.accessMode | quote }}
resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- if .Values.persistence.storageClass }}
storageClassName: {{ .Values.persistence.storageClass | quote }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "mediawiki.fullname" . }}
labels:
{{- include "mediawiki.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "mediawiki.selectorLabels" . | nindent 4 }}

View file

@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "mediawiki.fullname" . }}-test-connection"
labels:
{{- include "mediawiki.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "mediawiki.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never

View file

@ -0,0 +1,86 @@
# Default values for mediawiki.
replicaCount: 1
image:
repository: zombi/mediawiki
pullPolicy: IfNotPresent
tag: "latest"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
wiki:
# Install decides if a job should be started to install the database schema once.
install: false
server: "https://wiki.example.org"
secretKey: "1166f2af9b8c1e1401f38a11d95628629bef0b75b90d09b296390041d19c3b2c"
persistence:
enabled: false
#existingClaim: ""
accessMode: ReadWriteOnce
size: 5Gi
storageClass: ""
annotations: {}
database:
type: postgres
server: postgres.example.org
port: 5432
name: mediawiki
username: mediawiki # unused if secretName is set
password: mediawiki # unused if secretName is set
#secretName: database-secret
podAnnotations: {}
podSecurityContext:
fsGroup: 33 # www-data
securityContext: {}
# runAsNonRoot: true
# runAsUser: 33 # www-data
# allowPrivilegeEscalation: false
# capabilities:
# drop:
# - all
# add:
# - NET_BIND_SERVICE # For listening on port 80
# # readOnlyRootFilesystem: true
service:
type: ClusterIP
port: 80
ingress:
enabled: false
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: chart-example.local
paths: ['/']
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
extraVolumeMounts: {}
extraVolumes: {}
resources: {}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}