🔨(CI) add Tilt
Tilt is a tool for local Kubernetes development. It makes it easy to see your changes as you make them, and it rebuilds and redeploys your app as you change it. It is a great tool for local development and testing of Kubernetes applications.
This commit is contained in:
@@ -25,7 +25,7 @@ COPY ./src/frontend/packages/eslint-config-impress/package.json ./packages/eslin
|
|||||||
RUN yarn --frozen-lockfile
|
RUN yarn --frozen-lockfile
|
||||||
|
|
||||||
### ---- Front-end builder image ----
|
### ---- Front-end builder image ----
|
||||||
FROM node:20 as frontend-builder
|
FROM node:20 as frontend-builder-1
|
||||||
|
|
||||||
WORKDIR /builder
|
WORKDIR /builder
|
||||||
|
|
||||||
@@ -34,6 +34,8 @@ COPY ./src/frontend .
|
|||||||
|
|
||||||
WORKDIR /builder/apps/impress
|
WORKDIR /builder/apps/impress
|
||||||
|
|
||||||
|
FROM frontend-builder-1 as frontend-builder-2
|
||||||
|
|
||||||
RUN yarn build
|
RUN yarn build
|
||||||
|
|
||||||
|
|
||||||
@@ -44,7 +46,7 @@ FROM nginxinc/nginx-unprivileged:1.25 as frontend-production
|
|||||||
ARG DOCKER_USER
|
ARG DOCKER_USER
|
||||||
USER ${DOCKER_USER}
|
USER ${DOCKER_USER}
|
||||||
|
|
||||||
COPY --from=frontend-builder \
|
COPY --from=frontend-builder-2 \
|
||||||
/builder/apps/impress/out \
|
/builder/apps/impress/out \
|
||||||
/usr/share/nginx/html
|
/usr/share/nginx/html
|
||||||
|
|
||||||
@@ -83,7 +85,7 @@ RUN yarn install --frozen-lockfile && \
|
|||||||
|
|
||||||
# ---- static link collector ----
|
# ---- static link collector ----
|
||||||
FROM base as link-collector
|
FROM base as link-collector
|
||||||
ARG PEOPLE_STATIC_ROOT=/data/static
|
ARG IMPRESS_STATIC_ROOT=/data/static
|
||||||
|
|
||||||
# Install libpangocairo & rdfind
|
# Install libpangocairo & rdfind
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
|
|||||||
71
Tiltfile
Normal file
71
Tiltfile
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
load('ext://uibutton', 'cmd_button', 'bool_input', 'location')
|
||||||
|
load('ext://namespace', 'namespace_create', 'namespace_inject')
|
||||||
|
namespace_create('impress')
|
||||||
|
|
||||||
|
docker_build(
|
||||||
|
'localhost:5001/impress-backend:latest',
|
||||||
|
context='.',
|
||||||
|
dockerfile='./Dockerfile',
|
||||||
|
only=['./src/backend', './src/mail', './docker'],
|
||||||
|
target = 'backend-development',
|
||||||
|
live_update=[
|
||||||
|
sync('./src/backend', '/app'),
|
||||||
|
run(
|
||||||
|
'pip install -r /app/requirements.txt',
|
||||||
|
trigger=['./api/requirements.txt']
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
docker_build(
|
||||||
|
'localhost:5001/impress-frontend:latest',
|
||||||
|
context='.',
|
||||||
|
dockerfile='./Dockerfile',
|
||||||
|
build_args={'ENV': 'dev'},
|
||||||
|
only=['./src/frontend', './src/mail', './docker'],
|
||||||
|
target = 'frontend-builder-1',
|
||||||
|
live_update=[
|
||||||
|
sync('./src/frontend', '/builder'),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
k8s_yaml(local('cd src/helm && helmfile -n impress -e dev template .'))
|
||||||
|
|
||||||
|
migration = '''
|
||||||
|
set -eu
|
||||||
|
# get k8s pod name from tilt resource name
|
||||||
|
POD_NAME="$(tilt get kubernetesdiscovery impress-backend -ojsonpath='{.status.pods[0].name}')"
|
||||||
|
kubectl -n impress exec "$POD_NAME" -- python manage.py makemigrations
|
||||||
|
'''
|
||||||
|
cmd_button('Make migration',
|
||||||
|
argv=['sh', '-c', migration],
|
||||||
|
resource='impress-backend',
|
||||||
|
icon_name='developer_board',
|
||||||
|
text='Run makemigration',
|
||||||
|
)
|
||||||
|
|
||||||
|
pod_migrate = '''
|
||||||
|
set -eu
|
||||||
|
# get k8s pod name from tilt resource name
|
||||||
|
POD_NAME="$(tilt get kubernetesdiscovery impress-backend -ojsonpath='{.status.pods[0].name}')"
|
||||||
|
kubectl -n impress exec "$POD_NAME" -- python manage.py migrate --no-input
|
||||||
|
'''
|
||||||
|
cmd_button('Migrate db',
|
||||||
|
argv=['sh', '-c', pod_migrate],
|
||||||
|
resource='impress-backend',
|
||||||
|
icon_name='developer_board',
|
||||||
|
text='Run database migration',
|
||||||
|
)
|
||||||
|
|
||||||
|
pod_add_admin = '''
|
||||||
|
set -eu
|
||||||
|
# get k8s pod name from tilt resource name
|
||||||
|
POD_NAME="$(tilt get kubernetesdiscovery impress-backend -ojsonpath='{.status.pods[0].name}')"
|
||||||
|
kubectl -n impress exec "$POD_NAME" -- python manage.py createsuperuser --email admin@example.com --password admin
|
||||||
|
'''
|
||||||
|
cmd_button('Add admin',
|
||||||
|
argv=['sh', '-c', pod_add_admin],
|
||||||
|
resource='impress-backend',
|
||||||
|
icon_name='developer_board',
|
||||||
|
text='Create superadmin',
|
||||||
|
)
|
||||||
1
src/frontend/apps/impress/.env.dev
Normal file
1
src/frontend/apps/impress/.env.dev
Normal file
@@ -0,0 +1 @@
|
|||||||
|
NEXT_PUBLIC_API_URL=https://impress.127.0.0.1.nip.io/api/v1.0/
|
||||||
@@ -4,6 +4,7 @@ image:
|
|||||||
tag: "latest"
|
tag: "latest"
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
|
replicas: 1
|
||||||
envVars:
|
envVars:
|
||||||
DJANGO_CSRF_TRUSTED_ORIGINS: https://impress.127.0.0.1.nip.io,http://impress.127.0.0.1.nip.io
|
DJANGO_CSRF_TRUSTED_ORIGINS: https://impress.127.0.0.1.nip.io,http://impress.127.0.0.1.nip.io
|
||||||
DJANGO_CONFIGURATION: Production
|
DJANGO_CONFIGURATION: Production
|
||||||
@@ -38,6 +39,15 @@ backend:
|
|||||||
REDIS_URL: redis://default:pass@redis-master:6379/1
|
REDIS_URL: redis://default:pass@redis-master:6379/1
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
|
envVars:
|
||||||
|
PORT: 8080
|
||||||
|
NEXT_PUBLIC_API_URL: https://impress.127.0.0.1.nip.io/api/v1.0/
|
||||||
|
|
||||||
|
replicas: 1
|
||||||
|
command:
|
||||||
|
- yarn
|
||||||
|
- dev
|
||||||
|
|
||||||
image:
|
image:
|
||||||
repository: localhost:5001/impress-frontend
|
repository: localhost:5001/impress-frontend
|
||||||
pullPolicy: Always
|
pullPolicy: Always
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ releases:
|
|||||||
values:
|
values:
|
||||||
- auth:
|
- auth:
|
||||||
password: pass
|
password: pass
|
||||||
|
architecture: standalone
|
||||||
|
|
||||||
- name: extra
|
- name: extra
|
||||||
installed: {{ ne .Environment.Name "dev" | toYaml }}
|
installed: {{ ne .Environment.Name "dev" | toYaml }}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ apiVersion: apps/v1
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ $fullName }}
|
name: {{ $fullName }}
|
||||||
|
namespace: {{ .Release.Namespace | quote }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||||
spec:
|
spec:
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ apiVersion: batch/v1
|
|||||||
kind: Job
|
kind: Job
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ $fullName }}-migrate
|
name: {{ $fullName }}-migrate
|
||||||
|
namespace: {{ .Release.Namespace | quote }}
|
||||||
{{- with .Values.backend.migrateJobAnnotations }}
|
{{- with .Values.backend.migrateJobAnnotations }}
|
||||||
annotations:
|
annotations:
|
||||||
{{- toYaml . | nindent 4 }}
|
{{- toYaml . | nindent 4 }}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ apiVersion: v1
|
|||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ $fullName }}
|
name: {{ $fullName }}
|
||||||
|
namespace: {{ .Release.Namespace | quote }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||||
annotations:
|
annotations:
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ apiVersion: apps/v1
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ $fullName }}
|
name: {{ $fullName }}
|
||||||
|
namespace: {{ .Release.Namespace | quote }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||||
spec:
|
spec:
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ apiVersion: v1
|
|||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ $fullName }}
|
name: {{ $fullName }}
|
||||||
|
namespace: {{ .Release.Namespace | quote }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||||
annotations:
|
annotations:
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ apiVersion: extensions/v1beta1
|
|||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ $fullName }}
|
name: {{ $fullName }}
|
||||||
|
namespace: {{ .Release.Namespace | quote }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "impress.labels" . | nindent 4 }}
|
{{- include "impress.labels" . | nindent 4 }}
|
||||||
{{- with .Values.ingress.annotations }}
|
{{- with .Values.ingress.annotations }}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ apiVersion: extensions/v1beta1
|
|||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ $fullName }}-admin
|
name: {{ $fullName }}-admin
|
||||||
|
namespace: {{ .Release.Namespace | quote }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "impress.labels" . | nindent 4 }}
|
{{- include "impress.labels" . | nindent 4 }}
|
||||||
{{- with .Values.ingressAdmin.annotations }}
|
{{- with .Values.ingressAdmin.annotations }}
|
||||||
|
|||||||
103
start-kind.sh
Normal file
103
start-kind.sh
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -o errexit
|
||||||
|
|
||||||
|
CURRENT_DIR=$(pwd)
|
||||||
|
|
||||||
|
echo "0. Create ca"
|
||||||
|
# 0. Create ca
|
||||||
|
mkcert -install
|
||||||
|
cd /tmp
|
||||||
|
mkcert "127.0.0.1.nip.io" "*.127.0.0.1.nip.io"
|
||||||
|
cd $CURRENT_DIR
|
||||||
|
|
||||||
|
echo "1. Create registry container unless it already exists"
|
||||||
|
# 1. Create registry container unless it already exists
|
||||||
|
reg_name='kind-registry'
|
||||||
|
reg_port='5001'
|
||||||
|
if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then
|
||||||
|
docker run \
|
||||||
|
-d --restart=always -p "127.0.0.1:${reg_port}:5000" --network bridge --name "${reg_name}" \
|
||||||
|
registry:2
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "2. Create kind cluster with containerd registry config dir enabled"
|
||||||
|
# 2. Create kind cluster with containerd registry config dir enabled
|
||||||
|
# TODO: kind will eventually enable this by default and this patch will
|
||||||
|
# be unnecessary.
|
||||||
|
#
|
||||||
|
# See:
|
||||||
|
# https://github.com/kubernetes-sigs/kind/issues/2875
|
||||||
|
# https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration
|
||||||
|
# See: https://github.com/containerd/containerd/blob/main/docs/hosts.md
|
||||||
|
cat <<EOF | kind create cluster --config=-
|
||||||
|
kind: Cluster
|
||||||
|
apiVersion: kind.x-k8s.io/v1alpha4
|
||||||
|
containerdConfigPatches:
|
||||||
|
- |-
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".registry]
|
||||||
|
config_path = "/etc/containerd/certs.d"
|
||||||
|
nodes:
|
||||||
|
- role: control-plane
|
||||||
|
image: kindest/node:v1.27.3
|
||||||
|
kubeadmConfigPatches:
|
||||||
|
- |
|
||||||
|
kind: InitConfiguration
|
||||||
|
nodeRegistration:
|
||||||
|
kubeletExtraArgs:
|
||||||
|
node-labels: "ingress-ready=true"
|
||||||
|
extraPortMappings:
|
||||||
|
- containerPort: 80
|
||||||
|
hostPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
- containerPort: 443
|
||||||
|
hostPort: 443
|
||||||
|
protocol: TCP
|
||||||
|
- role: worker
|
||||||
|
image: kindest/node:v1.27.3
|
||||||
|
- role: worker
|
||||||
|
image: kindest/node:v1.27.3
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "3. Add the registry config to the nodes"
|
||||||
|
# 3. Add the registry config to the nodes
|
||||||
|
#
|
||||||
|
# This is necessary because localhost resolves to loopback addresses that are
|
||||||
|
# network-namespace local.
|
||||||
|
# In other words: localhost in the container is not localhost on the host.
|
||||||
|
#
|
||||||
|
# We want a consistent name that works from both ends, so we tell containerd to
|
||||||
|
# alias localhost:${reg_port} to the registry container when pulling images
|
||||||
|
REGISTRY_DIR="/etc/containerd/certs.d/localhost:${reg_port}"
|
||||||
|
for node in $(kind get nodes); do
|
||||||
|
docker exec "${node}" mkdir -p "${REGISTRY_DIR}"
|
||||||
|
cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
|
||||||
|
[host."http://${reg_name}:5000"]
|
||||||
|
EOF
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "4. Connect the registry to the cluster network if not already connected"
|
||||||
|
# 4. Connect the registry to the cluster network if not already connected
|
||||||
|
# This allows kind to bootstrap the network but ensures they're on the same network
|
||||||
|
if [ "$(docker inspect -f='{{json .NetworkSettings.Networks.kind}}' "${reg_name}")" = 'null' ]; then
|
||||||
|
docker network connect "kind" "${reg_name}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "5. Document the local registry"
|
||||||
|
# 5. Document the local registry
|
||||||
|
# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry
|
||||||
|
cat <<EOF | kubectl apply -f -
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: local-registry-hosting
|
||||||
|
namespace: kube-public
|
||||||
|
data:
|
||||||
|
localRegistryHosting.v1: |
|
||||||
|
host: "localhost:${reg_port}"
|
||||||
|
help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "6. Install ingress-nginx"
|
||||||
|
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
|
||||||
|
kubectl -n ingress-nginx create secret tls mkcert --key /tmp/127.0.0.1.nip.io+1-key.pem --cert /tmp/127.0.0.1.nip.io+1.pem
|
||||||
|
kubectl -n ingress-nginx patch deployments.apps ingress-nginx-controller --type 'json' -p '[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value":"--default-ssl-certificate=ingress-nginx/mkcert"}]'
|
||||||
Reference in New Issue
Block a user