begin work on autodeployer
Some checks failed
/ build-deployer (push) Failing after 10s
/ diff-and-deploy (push) Successful in 33s

This commit is contained in:
Finn 2024-10-29 23:16:00 -07:00
parent 69dcc3e1af
commit ff115f79aa
7 changed files with 231 additions and 0 deletions

View file

@ -0,0 +1,22 @@
on:
push:
paths:
- containers/deployer/**
- .forgejo/workflows/build-deployer.yaml
jobs:
build-deployer:
runs-on: docker
container:
image: library/docker:dind
steps:
- run: apk add --no-cache nodejs git
- name: login to container registry
run: echo "${{ secrets.DEPLOY_SECRET }}" | docker login --username ${{ secrets.DEPLOY_USER }} --password-stdin git.janky.solutions
- name: build container image
uses: docker/build-push-action@v6
with:
file: Containerfile
context: "{{defaultContext}}:containers/deployer"
tags: git.janky.solutions/jankysolutions/infra/deployer:latest
platforms: linux/amd64
push: true

View file

@ -0,0 +1,37 @@
on:
push:
paths:
- k8s/**
- .forgejo/workflows/k8s-diff-and-deploy.yaml
jobs:
diff-and-deploy:
runs-on: ubuntu-latest
container:
image: git.devhack.net/devhack/containers/deployer:latest
steps:
- uses: actions/checkout@v4
- name: kubectl diff and deploy
run: |
set -euo pipefail
echo "${{ secrets.KUBERNETES_CLIENT_CONFIG }}" > ~/.kube/config
for component in k8s/*; do
if [ ! -d "${component}" ]; then
continue
fi
touch "${component}/secrets.yaml"
echo "👀 $ kubectl diff -k ${component}"
kubectl diff -k "${component}" || echo
# if [[ "${GITHUB_REF_NAME}" == "main" ]]; then
# echo "🚀 $ kubectl apply -k ${component}"
# if [[ "${component}" == "k8s/operators" ]]; then
# kubectl apply -k "${component}" --server-side
# else
# kubectl apply -k "${component}"
# fi
# echo
# fi
done

View file

@ -0,0 +1,3 @@
FROM library/alpine:3.20
RUN apk add --no-cache nodejs git bash helm kubectl
RUN mkdir -p ~/.kube

View file

@ -0,0 +1,62 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: forgejo-secret-sync
spec:
schedule: "0 0 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: secret-sync
image: library/python:3
command:
- bash
- -c
- pip install requests && python /code/forgejo-secret-sync.py
env:
- name: REPO_MAPPINGS
value: |
[
{"k8s_name": "infra-deployer", "owner": "JankySolutions", "repo": "infra"}
]
envFrom:
- secretRef:
name: forgejo-secret-sync
volumeMounts:
- name: code
mountPath: /code
- name: host-tls
mountPath: /var/lib/rancher/k3s/server/tls
restartPolicy: OnFailure
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: In
values: ["true"]
volumes:
- name: code
configMap:
name: forgejo-secret-sync
- name: host-tls
hostPath:
path: /var/lib/rancher/k3s/server/tls
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: forgejo-secret-sync
spec:
secretStoreRef:
kind: SecretStore
name: openbao
target:
name: forgejo-secret-sync
creationPolicy: Owner
dataFrom:
- extract:
key: forgejo/default/secret-sync

View file

@ -0,0 +1,86 @@
#!/usr/bin/env python3
import subprocess
import logging
import base64
import os
import requests
import json
logging.basicConfig(level=logging.DEBUG)
with open("/var/lib/rancher/k3s/server/tls/server-ca.crt") as f:
ca = base64.b64encode(f.read().encode()).decode()
forgejo_token = os.getenv("FORGEJO_TOKEN")
def run(cmd: list[str], stdin=None) -> str:
logging.debug("executing %s", cmd)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
out = p.communicate(stdin)
if p.returncode != 0:
logging.critical("{} exited with code {}", cmd, p.returncode)
os.exit(1)
return out[0]
def update_cert(k8s_name: str, owner: str, repo: str):
key = run(["openssl", "genrsa", "4096"])
req = run(
["openssl", "req", "-key", "/dev/stdin", "-new", "-nodes", "-subj", f"/CN={k8s_name}"], stdin=key
)
cert = run(
[
"openssl",
"x509",
"-req",
"-CA",
"/var/lib/rancher/k3s/server/tls/client-ca.nochain.crt",
"-CAkey",
"/var/lib/rancher/k3s/server/tls/client-ca.key",
"-CAcreateserial",
"-days",
"2",
],
stdin=req,
)
keyb64 = base64.b64encode(key).decode()
certb64 = base64.b64encode(cert).decode()
kubeconfig = f"""
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: {ca}
server: https://k8s-node-1:6443
name: default
contexts:
- context:
cluster: default
user: default
name: default
current-context: default
kind: Config
preferences: {"{}"}
users:
- name: default
user:
client-certificate-data: {certb64}
client-key-data: {keyb64}
"""
logging.info(f"updating secret for {owner}/{repo}")
requests.put(
f"https://git.janky.solutions/api/v1/repos/{owner}/{repo}/actions/secrets/KUBERNETES_CLIENT_CONFIG",
data=json.dumps(
{"data": kubeconfig},
),
headers={
"Authorization": f"token {forgejo_token}",
"Content-Type": "application/json",
},
).raise_for_status()
for entry in json.loads(os.getenv("REPO_MAPPINGS")):
update_cert(**entry)

View file

@ -5,8 +5,10 @@ resources:
- namespace.yaml - namespace.yaml
- config.yaml - config.yaml
- ingress.yaml - ingress.yaml
- forgejo-secret-sync.yaml
- services.yaml - services.yaml
- statefulset.yaml - statefulset.yaml
- secret-store.yaml
- secrets.yaml - secrets.yaml
- renovatebot.yaml - renovatebot.yaml
configMapGenerator: configMapGenerator:
@ -16,3 +18,6 @@ configMapGenerator:
- name: renovate-config - name: renovate-config
files: files:
- renovate/config.js - renovate/config.js
- name: forgejo-secret-sync
files:
- forgejo-secret-sync/forgejo-secret-sync.py

View file

@ -0,0 +1,16 @@
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: openbao
spec:
provider:
vault:
server: http://openbao.openbao:8200
path: static-secrets
version: v2
auth:
kubernetes:
mountPath: kubernetes
role: kubernetes-default
serviceAccountRef:
name: default