begin work on autodeployer
This commit is contained in:
parent
69dcc3e1af
commit
ff115f79aa
7 changed files with 231 additions and 0 deletions
22
.forgejo/workflows/build-deployer.yaml
Normal file
22
.forgejo/workflows/build-deployer.yaml
Normal 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
|
37
.forgejo/workflows/k8s-diff-and-deploy.yaml
Normal file
37
.forgejo/workflows/k8s-diff-and-deploy.yaml
Normal 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
|
3
containers/deployer/Containerfile
Normal file
3
containers/deployer/Containerfile
Normal file
|
@ -0,0 +1,3 @@
|
|||
FROM library/alpine:3.20
|
||||
RUN apk add --no-cache nodejs git bash helm kubectl
|
||||
RUN mkdir -p ~/.kube
|
62
k8s/forgejo/forgejo-secret-sync.yaml
Normal file
62
k8s/forgejo/forgejo-secret-sync.yaml
Normal 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
|
86
k8s/forgejo/forgejo-secret-sync/forgejo-secret-sync.py
Normal file
86
k8s/forgejo/forgejo-secret-sync/forgejo-secret-sync.py
Normal 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)
|
|
@ -5,8 +5,10 @@ resources:
|
|||
- namespace.yaml
|
||||
- config.yaml
|
||||
- ingress.yaml
|
||||
- forgejo-secret-sync.yaml
|
||||
- services.yaml
|
||||
- statefulset.yaml
|
||||
- secret-store.yaml
|
||||
- secrets.yaml
|
||||
- renovatebot.yaml
|
||||
configMapGenerator:
|
||||
|
@ -16,3 +18,6 @@ configMapGenerator:
|
|||
- name: renovate-config
|
||||
files:
|
||||
- renovate/config.js
|
||||
- name: forgejo-secret-sync
|
||||
files:
|
||||
- forgejo-secret-sync/forgejo-secret-sync.py
|
||||
|
|
16
k8s/forgejo/secret-store.yaml
Normal file
16
k8s/forgejo/secret-store.yaml
Normal 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
|
Loading…
Reference in a new issue