mirror of
https://github.com/morten-olsen/homelab-operator.git
synced 2026-02-08 01:36:28 +01:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d46998668 | ||
|
|
00d90bfa21 | ||
|
|
03e406322f | ||
|
|
5ee7a76443 | ||
|
|
683de402ff | ||
|
|
e8e939ad19 | ||
|
|
1b5b5145b0 | ||
|
|
cfd2d76873 | ||
|
|
9e5081ed9b | ||
|
|
3ab2b1969a | ||
|
|
a27b563113 | ||
|
|
295472a028 | ||
|
|
91298b3cf7 | ||
|
|
638c288a5c | ||
|
|
2be6bdca84 | ||
|
|
f362f4afc4 | ||
|
|
9fadbf75fb | ||
|
|
2add15d283 | ||
|
|
5426495be5 | ||
|
|
b8bb16ccbb | ||
|
|
d4b56007f1 | ||
|
|
130bfec468 | ||
|
|
ddb3c79657 | ||
|
|
47cf43b44e | ||
|
|
aa6d14738a | ||
|
|
9cdbaf7929 | ||
|
|
cfb90f7c9f | ||
|
|
757b2fcfac | ||
|
|
daf0ea21bb | ||
|
|
26b58a59c0 | ||
|
|
a25e0b9ffb | ||
|
|
5782d59f71 | ||
|
|
34bba171ef | ||
|
|
85d043aec3 | ||
|
|
523637d40f | ||
|
|
dd1e5a8124 |
2
.github/release-drafter-config.yml
vendored
2
.github/release-drafter-config.yml
vendored
@@ -1,5 +1,5 @@
|
||||
name-template: "$RESOLVED_VERSION 🌈"
|
||||
tag-template: "$RESOLVED_VERSION"
|
||||
tag-template: "v$RESOLVED_VERSION"
|
||||
categories:
|
||||
- title: "🚀 Features"
|
||||
labels:
|
||||
|
||||
56
.github/workflows/main.yml
vendored
56
.github/workflows/main.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Build and release
|
||||
name: Build, tag and release
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -71,55 +71,23 @@ jobs:
|
||||
environment: release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: release-drafter/release-drafter@v6
|
||||
- id: create-release
|
||||
uses: release-drafter/release-drafter@v6
|
||||
with:
|
||||
config-name: release-drafter-config.yml
|
||||
publish: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
release:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
attestations: write
|
||||
id-token: write
|
||||
pages: write
|
||||
name: Release
|
||||
if: github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
needs: update-release-draft
|
||||
environment: release
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
||||
- name: Upload Release Asset
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
registry: ${{ env.DOCKER_REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
||||
with:
|
||||
images: ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
id: push
|
||||
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
- name: Generate artifact attestation
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-name: ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME}}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
upload_url: ${{ steps.create-release.outputs.upload_url }}
|
||||
asset_path: ./operator.yaml
|
||||
asset_name: operator.yaml
|
||||
asset_content_type: application/yaml
|
||||
65
.github/workflows/publish-tag.yml
vendored
Normal file
65
.github/workflows/publish-tag.yml
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
name: Publish tag
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
env:
|
||||
environment: test
|
||||
release_channel: latest
|
||||
DO_NOT_TRACK: "1"
|
||||
NODE_VERSION: "23.x"
|
||||
DOCKER_REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
PNPM_VERSION: 10.6.0
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
jobs:
|
||||
release:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
attestations: write
|
||||
id-token: write
|
||||
pages: write
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
||||
with:
|
||||
registry: ${{ env.DOCKER_REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
||||
with:
|
||||
images: ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
id: push
|
||||
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
- name: Generate artifact attestation
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-name: ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME}}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -32,3 +32,7 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||
|
||||
# Finder (MacOS) folder config
|
||||
.DS_Store
|
||||
|
||||
/data/
|
||||
|
||||
/cloudflare.yaml
|
||||
|
||||
1
.python-version
Normal file
1
.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.13
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:23-alpine
|
||||
FROM node:23-slim
|
||||
RUN corepack enable
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm install --frozen-lockfile --prod
|
||||
|
||||
14
Makefile
Normal file
14
Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
.PHONY: dev-recreate dev-destroy server-install
|
||||
|
||||
dev-destroy:
|
||||
colima delete -f
|
||||
|
||||
dev-recreate: dev-destroy
|
||||
colima start --network-address --kubernetes -m 8 --k3s-arg="--disable helm-controller,local-storage,traefik --docker" # --mount ${PWD}/data:/data:w
|
||||
flux install --components="source-controller,helm-controller"
|
||||
|
||||
setup-flux:
|
||||
flux install --components="source-controller,helm-controller"
|
||||
|
||||
server-install:
|
||||
curl -sfL https://get.k3s.io | sh -s - --disable traefik,local-storage,helm-controller
|
||||
15
README.md
15
README.md
@@ -1,15 +0,0 @@
|
||||
# homelab-operator
|
||||
|
||||
To install dependencies:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
To run:
|
||||
|
||||
```bash
|
||||
bun run index.ts
|
||||
```
|
||||
|
||||
This project was created using `bun init` in bun v1.2.16. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: {{ include "homelab-operator.fullname" . }}
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["create", "get", "watch", "list"]
|
||||
- apiGroups: ["*"]
|
||||
resources: ["*"]
|
||||
verbs: ["get", "watch", "list", "patch"]
|
||||
- apiGroups: ["apiextensions.k8s.io"]
|
||||
resources: ["customresourcedefinitions"]
|
||||
verbs: ["get", "create", "replace"]
|
||||
3
charts/apps/audiobookshelf/Chart.yaml
Normal file
3
charts/apps/audiobookshelf/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
apiVersion: v2
|
||||
version: 1.0.0
|
||||
name: audiobookshelf
|
||||
13
charts/apps/audiobookshelf/templates/client.yaml
Normal file
13
charts/apps/audiobookshelf/templates/client.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: OidcClient
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.globals.environment }}'
|
||||
redirectUris:
|
||||
- path: /audiobookshelf/auth/openid/callback
|
||||
subdomain: '{{ .Values.subdomain }}'
|
||||
matchingMode: strict
|
||||
- path: /audiobookshelf/auth/openid/mobile-redirect
|
||||
subdomain: '{{ .Values.subdomain }}'
|
||||
matchingMode: strict
|
||||
52
charts/apps/audiobookshelf/templates/deployment.yaml
Normal file
52
charts/apps/audiobookshelf/templates/deployment.yaml
Normal file
@@ -0,0 +1,52 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: '{{ .Release.Name }}'
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
containers:
|
||||
- name: '{{ .Release.Name }}'
|
||||
image: '{{ .Values.image.repository }}:{{ .Values.image.tag }}'
|
||||
imagePullPolicy: '{{ .Values.image.pullPolicy }}'
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
volumeMounts:
|
||||
- mountPath: /config
|
||||
name: config
|
||||
- mountPath: /metadata
|
||||
name: metadata
|
||||
- mountPath: /audiobooks
|
||||
name: audiobooks
|
||||
- mountPath: /podcasts
|
||||
name: podcasts
|
||||
volumes:
|
||||
- name: config
|
||||
persistentVolumeClaim:
|
||||
claimName: '{{ .Release.Name }}-config'
|
||||
- name: metadata
|
||||
persistentVolumeClaim:
|
||||
claimName: '{{ .Release.Name }}-metadata'
|
||||
- name: audiobooks
|
||||
persistentVolumeClaim:
|
||||
claimName: books
|
||||
- name: podcasts
|
||||
persistentVolumeClaim:
|
||||
claimName: podcasts
|
||||
@@ -0,0 +1,11 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: ExternalHttpService
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.globals.environment }}'
|
||||
subdomain: '{{ .Values.subdomain }}'
|
||||
destination:
|
||||
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||
port:
|
||||
number: 80
|
||||
24
charts/apps/audiobookshelf/templates/pvc.yaml
Normal file
24
charts/apps/audiobookshelf/templates/pvc.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}-config'
|
||||
spec:
|
||||
accessModes:
|
||||
- 'ReadWriteOnce'
|
||||
resources:
|
||||
requests:
|
||||
storage: '1Gi'
|
||||
storageClassName: '{{ .Values.globals.environment }}'
|
||||
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}-metadata'
|
||||
spec:
|
||||
accessModes:
|
||||
- 'ReadWriteOnce'
|
||||
resources:
|
||||
requests:
|
||||
storage: '1Gi'
|
||||
storageClassName: '{{ .Values.globals.environment }}'
|
||||
15
charts/apps/audiobookshelf/templates/service.yaml
Normal file
15
charts/apps/audiobookshelf/templates/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: '{{ .Release.Name }}'
|
||||
7
charts/apps/audiobookshelf/values.yaml
Normal file
7
charts/apps/audiobookshelf/values.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
globals:
|
||||
environment: prod
|
||||
image:
|
||||
repository: ghcr.io/advplyr/audiobookshelf
|
||||
tag: 2.26.1
|
||||
pullPolicy: IfNotPresent
|
||||
subdomain: audiobookshelf
|
||||
3
charts/apps/bytestash/Chart.yaml
Normal file
3
charts/apps/bytestash/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
apiVersion: v2
|
||||
version: 1.0.0
|
||||
name: ByteStash
|
||||
13
charts/apps/bytestash/templates/_headless-service.yaml
Normal file
13
charts/apps/bytestash/templates/_headless-service.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}-headless'
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
clusterIP: None
|
||||
ports:
|
||||
- port: 5000
|
||||
name: http
|
||||
selector:
|
||||
app: '{{ .Release.Name }}'
|
||||
11
charts/apps/bytestash/templates/_http-service.yaml
Normal file
11
charts/apps/bytestash/templates/_http-service.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: HttpService
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.environment }}'
|
||||
subdomain: '{{ .Values.subdomain }}'
|
||||
destination:
|
||||
host: '{{ .Release.Name }}'
|
||||
port:
|
||||
number: 80
|
||||
10
charts/apps/bytestash/templates/client.yaml
Normal file
10
charts/apps/bytestash/templates/client.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: OidcClient
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.globals.environment }}'
|
||||
redirectUris:
|
||||
- path: /api/auth/oidc/callback
|
||||
subdomain: bytestash
|
||||
matchingMode: strict
|
||||
55
charts/apps/bytestash/templates/deployment.yaml
Normal file
55
charts/apps/bytestash/templates/deployment.yaml
Normal file
@@ -0,0 +1,55 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
serviceName: '{{ .Release.Name }}-headless'
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: '{{ .Release.Name }}'
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
containers:
|
||||
- name: '{{ .Release.Name }}'
|
||||
image: ghcr.io/jordan-dalby/bytestash:latest
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
name: http
|
||||
env:
|
||||
- name: ALLOW_NEW_ACCOUNTS
|
||||
value: 'true'
|
||||
- name: DISABLE_INTERNAL_ACCOUNTS
|
||||
value: 'true'
|
||||
- name: OIDC_ENABLED
|
||||
value: 'true'
|
||||
- name: OIDC_DISPLAY_NAME
|
||||
value: OIDC
|
||||
- name: OIDC_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-client'
|
||||
key: clientId
|
||||
- name: OIDC_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-client'
|
||||
key: clientSecret
|
||||
- name: OIDC_ISSUER_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-client'
|
||||
key: configuration
|
||||
|
||||
volumeMounts:
|
||||
- mountPath: /data/snippets
|
||||
name: data
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: '{{ .Release.Name }}-data'
|
||||
11
charts/apps/bytestash/templates/external-http-service.yaml
Normal file
11
charts/apps/bytestash/templates/external-http-service.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: ExternalHttpService
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.globals.environment }}'
|
||||
subdomain: '{{ .Values.subdomain }}'
|
||||
destination:
|
||||
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||
port:
|
||||
number: 80
|
||||
11
charts/apps/bytestash/templates/pvc.yaml
Normal file
11
charts/apps/bytestash/templates/pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}-data'
|
||||
spec:
|
||||
accessModes:
|
||||
- 'ReadWriteOnce'
|
||||
resources:
|
||||
requests:
|
||||
storage: '1Gi'
|
||||
storageClassName: '{{ .Values.globals.environment }}'
|
||||
15
charts/apps/bytestash/templates/service.yaml
Normal file
15
charts/apps/bytestash/templates/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 5000
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: '{{ .Release.Name }}'
|
||||
3
charts/apps/bytestash/values.yaml
Normal file
3
charts/apps/bytestash/values.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
globals:
|
||||
environment: prod
|
||||
subdomain: bytestash
|
||||
3
charts/apps/jellyfin/Chart.yaml
Normal file
3
charts/apps/jellyfin/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
apiVersion: v2
|
||||
version: 1.0.0
|
||||
name: Jellyfin
|
||||
1
charts/apps/jellyfin/notes.md
Normal file
1
charts/apps/jellyfin/notes.md
Normal file
@@ -0,0 +1 @@
|
||||
https://www.authelia.com/integration/openid-connect/clients/jellyfin/
|
||||
10
charts/apps/jellyfin/templates/client.yaml
Normal file
10
charts/apps/jellyfin/templates/client.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: OidcClient
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.environment }}'
|
||||
redirectUris:
|
||||
- path: /sso/OID/redirect/Authentik
|
||||
subdomain: '{{ .Values.globals.subdomain }}'
|
||||
matchingMode: strict
|
||||
11
charts/apps/jellyfin/templates/config-pvc.yaml
Normal file
11
charts/apps/jellyfin/templates/config-pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}-config'
|
||||
spec:
|
||||
accessModes:
|
||||
- 'ReadWriteOnce'
|
||||
resources:
|
||||
requests:
|
||||
storage: '1Gi'
|
||||
storageClassName: '{{ .Values.environment }}'
|
||||
52
charts/apps/jellyfin/templates/deployment.yaml
Normal file
52
charts/apps/jellyfin/templates/deployment.yaml
Normal file
@@ -0,0 +1,52 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: '{{ .Release.Name }}'
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
containers:
|
||||
- name: '{{ .Release.Name }}'
|
||||
image: '{{ .Values.image.repository }}:{{ .Values.image.tag }}'
|
||||
imagePullPolicy: '{{ .Values.image.pullPolicy }}'
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8096
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
volumeMounts:
|
||||
- mountPath: /config
|
||||
name: config
|
||||
- mountPath: /media/movies
|
||||
name: movies
|
||||
- mountPath: /media/tv-shows
|
||||
name: tvshows
|
||||
- mountPath: /media/music
|
||||
name: music
|
||||
volumes:
|
||||
- name: config
|
||||
persistentVolumeClaim:
|
||||
claimName: '{{ .Release.Name }}-config'
|
||||
- name: movies
|
||||
persistentVolumeClaim:
|
||||
claimName: movies
|
||||
- name: tvshows
|
||||
persistentVolumeClaim:
|
||||
claimName: tvshows
|
||||
- name: music
|
||||
persistentVolumeClaim:
|
||||
claimName: music
|
||||
11
charts/apps/jellyfin/templates/external-http-service.yaml
Normal file
11
charts/apps/jellyfin/templates/external-http-service.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: ExternalHttpService
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.globals.environment }}'
|
||||
subdomain: '{{ .Values.subdomain }}'
|
||||
destination:
|
||||
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||
port:
|
||||
number: 80
|
||||
15
charts/apps/jellyfin/templates/service.yaml
Normal file
15
charts/apps/jellyfin/templates/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8096
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: '{{ .Release.Name }}'
|
||||
7
charts/apps/jellyfin/values.yaml
Normal file
7
charts/apps/jellyfin/values.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
globals:
|
||||
environment: prod
|
||||
image:
|
||||
repository: docker.io/jellyfin/jellyfin
|
||||
tag: latest
|
||||
pullPolicy: IfNotPresent
|
||||
subdomain: jellyfin
|
||||
3
charts/apps/miniflux.disable/Chart.yaml
Normal file
3
charts/apps/miniflux.disable/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
apiVersion: v2
|
||||
version: 1.0.0
|
||||
name: ByteStash
|
||||
10
charts/apps/miniflux.disable/templates/client.yaml
Normal file
10
charts/apps/miniflux.disable/templates/client.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: OidcClient
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.globals.environment }}'
|
||||
redirectUris:
|
||||
- path: /api/auth/oidc/callback
|
||||
subdomain: bytestash
|
||||
matchingMode: strict
|
||||
55
charts/apps/miniflux.disable/templates/deployment.yaml
Normal file
55
charts/apps/miniflux.disable/templates/deployment.yaml
Normal file
@@ -0,0 +1,55 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
serviceName: '{{ .Release.Name }}-headless'
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: '{{ .Release.Name }}'
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
containers:
|
||||
- name: '{{ .Release.Name }}'
|
||||
image: ghcr.io/miniflux/miniflux:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
env:
|
||||
- name: ALLOW_NEW_ACCOUNTS
|
||||
value: 'true'
|
||||
- name: DISABLE_INTERNAL_ACCOUNTS
|
||||
value: 'true'
|
||||
- name: OIDC_ENABLED
|
||||
value: 'true'
|
||||
- name: OIDC_DISPLAY_NAME
|
||||
value: OIDC
|
||||
- name: OIDC_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-client'
|
||||
key: clientId
|
||||
- name: OIDC_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-client'
|
||||
key: clientSecret
|
||||
- name: OIDC_ISSUER_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-client'
|
||||
key: configuration
|
||||
|
||||
volumeMounts:
|
||||
- mountPath: /data/snippets
|
||||
name: data
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: '{{ .Release.Name }}-data'
|
||||
@@ -0,0 +1,11 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: ExternalHttpService
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.globals.environment }}'
|
||||
subdomain: '{{ .Values.subdomain }}'
|
||||
destination:
|
||||
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||
port:
|
||||
number: 80
|
||||
11
charts/apps/miniflux.disable/templates/pvc.yaml
Normal file
11
charts/apps/miniflux.disable/templates/pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}-data'
|
||||
spec:
|
||||
accessModes:
|
||||
- 'ReadWriteOnce'
|
||||
resources:
|
||||
requests:
|
||||
storage: '1Gi'
|
||||
storageClassName: '{{ .Values.globals.environment }}'
|
||||
15
charts/apps/miniflux.disable/templates/service.yaml
Normal file
15
charts/apps/miniflux.disable/templates/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: '{{ .Release.Name }}'
|
||||
3
charts/apps/miniflux.disable/values.yaml
Normal file
3
charts/apps/miniflux.disable/values.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
globals:
|
||||
environment: prod
|
||||
subdomain: miniflux
|
||||
3
charts/apps/n8n/Chart.yaml
Normal file
3
charts/apps/n8n/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
apiVersion: v2
|
||||
version: 1.0.0
|
||||
name: Jellyfin
|
||||
6
charts/apps/n8n/templates/database.yaml
Normal file
6
charts/apps/n8n/templates/database.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: PostgresDatabase
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.globals.environment }}'
|
||||
73
charts/apps/n8n/templates/deployment.yaml
Normal file
73
charts/apps/n8n/templates/deployment.yaml
Normal file
@@ -0,0 +1,73 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: '{{ .Release.Name }}'
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
containers:
|
||||
- name: '{{ .Release.Name }}'
|
||||
image: '{{ .Values.image.repository }}:{{ .Values.image.tag }}'
|
||||
imagePullPolicy: '{{ .Values.image.pullPolicy }}'
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 5678
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
volumeMounts:
|
||||
- mountPath: /home/node/.n8n
|
||||
name: data
|
||||
env:
|
||||
- name: TZ
|
||||
value: '{{ .Values.globals.timezone }}'
|
||||
- name: GENERIC_TIMEZONE
|
||||
value: '{{ .Values.globals.timezone }}'
|
||||
- name: N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS
|
||||
value: 'true'
|
||||
- name: N8N_RUNNERS_ENABLED
|
||||
value: 'true'
|
||||
- name: DB_TYPE
|
||||
value: postgresdb
|
||||
- name: DB_POSTGRESDB_DATABASE
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-pg-connection'
|
||||
key: database
|
||||
- name: DB_POSTGRESDB_HOST
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-pg-connection'
|
||||
key: host
|
||||
- name: DB_POSTGRESDB_PORT
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-pg-connection'
|
||||
key: port
|
||||
- name: DB_POSTGRESDB_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-pg-connection'
|
||||
key: user
|
||||
- name: DB_POSTGRESDB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-pg-connection'
|
||||
key: password
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: '{{ .Release.Name }}-data'
|
||||
11
charts/apps/n8n/templates/external-http-service.yaml
Normal file
11
charts/apps/n8n/templates/external-http-service.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: ExternalHttpService
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.globals.environment }}'
|
||||
subdomain: '{{ .Values.subdomain }}'
|
||||
destination:
|
||||
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||
port:
|
||||
number: 80
|
||||
11
charts/apps/n8n/templates/pvc.yaml
Normal file
11
charts/apps/n8n/templates/pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}-data'
|
||||
spec:
|
||||
accessModes:
|
||||
- 'ReadWriteOnce'
|
||||
resources:
|
||||
requests:
|
||||
storage: '1Gi'
|
||||
storageClassName: '{{ .Values.globals.environment }}'
|
||||
15
charts/apps/n8n/templates/service.yaml
Normal file
15
charts/apps/n8n/templates/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 5678
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: '{{ .Release.Name }}'
|
||||
8
charts/apps/n8n/values.yaml
Normal file
8
charts/apps/n8n/values.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
globals:
|
||||
environment: prod
|
||||
timezone: Europe/Amsterdam
|
||||
image:
|
||||
repository: docker.n8n.io/n8nio/n8n
|
||||
tag: latest
|
||||
pullPolicy: IfNotPresent
|
||||
subdomain: n8n
|
||||
3
charts/apps/ollama/Chart.yaml
Normal file
3
charts/apps/ollama/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
apiVersion: v2
|
||||
version: 1.0.0
|
||||
name: ollama
|
||||
10
charts/apps/ollama/templates/client.yaml
Normal file
10
charts/apps/ollama/templates/client.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: OidcClient
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.globals.environment }}'
|
||||
redirectUris:
|
||||
- path: /oauth/oidc/callback
|
||||
subdomain: '{{ .Values.subdomain }}'
|
||||
matchingMode: strict
|
||||
38
charts/apps/ollama/templates/deployment.yaml
Normal file
38
charts/apps/ollama/templates/deployment.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: '{{ .Release.Name }}'
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
containers:
|
||||
- name: '{{ .Release.Name }}'
|
||||
image: '{{ .Values.image.repository }}:{{ .Values.image.tag }}'
|
||||
imagePullPolicy: '{{ .Values.image.pullPolicy }}'
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 11434
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
volumeMounts:
|
||||
- mountPath: /root/.ollama
|
||||
name: data
|
||||
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: '{{ .Release.Name }}-data'
|
||||
11
charts/apps/ollama/templates/pvc.yaml
Normal file
11
charts/apps/ollama/templates/pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}-data'
|
||||
spec:
|
||||
accessModes:
|
||||
- 'ReadWriteOnce'
|
||||
resources:
|
||||
requests:
|
||||
storage: '1Gi'
|
||||
storageClassName: '{{ .Values.globals.environment }}'
|
||||
15
charts/apps/ollama/templates/service.yaml
Normal file
15
charts/apps/ollama/templates/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 11434
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: '{{ .Release.Name }}'
|
||||
7
charts/apps/ollama/values.yaml
Normal file
7
charts/apps/ollama/values.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
globals:
|
||||
environment: prod
|
||||
image:
|
||||
repository: ollama/ollama
|
||||
tag: 0.11.8
|
||||
pullPolicy: IfNotPresent
|
||||
subdomain: openwebui
|
||||
3
charts/apps/openwebui/Chart.yaml
Normal file
3
charts/apps/openwebui/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
apiVersion: v2
|
||||
version: 1.0.0
|
||||
name: openwebui
|
||||
10
charts/apps/openwebui/templates/client.yaml
Normal file
10
charts/apps/openwebui/templates/client.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: OidcClient
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.globals.environment }}'
|
||||
redirectUris:
|
||||
- path: /oauth/oidc/callback
|
||||
subdomain: '{{ .Values.subdomain }}'
|
||||
matchingMode: strict
|
||||
70
charts/apps/openwebui/templates/deployment.yaml
Normal file
70
charts/apps/openwebui/templates/deployment.yaml
Normal file
@@ -0,0 +1,70 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: '{{ .Release.Name }}'
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
containers:
|
||||
- name: '{{ .Release.Name }}'
|
||||
image: '{{ .Values.image.repository }}:{{ .Values.image.tag }}'
|
||||
imagePullPolicy: '{{ .Values.image.pullPolicy }}'
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
volumeMounts:
|
||||
- mountPath: /app/backend/data
|
||||
name: data
|
||||
env:
|
||||
- name: ENABLE_SIGNUP
|
||||
value: 'false'
|
||||
- name: WEBUI_URL # TODO: remove
|
||||
value: https://openwebui.olsen.cloud
|
||||
- name: ENABLE_OAUTH_PERSISTENT_CONFIG
|
||||
value: 'false'
|
||||
- name: ENABLE_OAUTH_SIGNUP
|
||||
value: 'true'
|
||||
- name: OAUTH_MERGE_ACCOUNTS_BY_EMAIL
|
||||
value: 'true'
|
||||
- name: OAUTH_PROVIDER_NAME
|
||||
value: authentik
|
||||
- name: OPENID_PROVIDER_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-client'
|
||||
key: configuration
|
||||
- name: OAUTH_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-client'
|
||||
key: clientId
|
||||
- name: OAUTH_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: '{{ .Release.Name }}-client'
|
||||
key: clientSecret
|
||||
- name: ENABLE_LOGIN_FORM
|
||||
value: 'false'
|
||||
- name: OPENID_REDIRECT
|
||||
value: https://openwebui.olsen.cloud/oauth/oidc/callback
|
||||
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: '{{ .Release.Name }}-data'
|
||||
11
charts/apps/openwebui/templates/external-http-service.yaml
Normal file
11
charts/apps/openwebui/templates/external-http-service.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: ExternalHttpService
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
spec:
|
||||
environment: '{{ .Values.globals.environment }}'
|
||||
subdomain: '{{ .Values.subdomain }}'
|
||||
destination:
|
||||
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||
port:
|
||||
number: 80
|
||||
11
charts/apps/openwebui/templates/pvc.yaml
Normal file
11
charts/apps/openwebui/templates/pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}-data'
|
||||
spec:
|
||||
accessModes:
|
||||
- 'ReadWriteOnce'
|
||||
resources:
|
||||
requests:
|
||||
storage: '1Gi'
|
||||
storageClassName: '{{ .Values.globals.environment }}'
|
||||
15
charts/apps/openwebui/templates/service.yaml
Normal file
15
charts/apps/openwebui/templates/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: '{{ .Release.Name }}'
|
||||
labels:
|
||||
app: '{{ .Release.Name }}'
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: '{{ .Release.Name }}'
|
||||
7
charts/apps/openwebui/values.yaml
Normal file
7
charts/apps/openwebui/values.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
globals:
|
||||
environment: prod
|
||||
image:
|
||||
repository: ghcr.io/open-webui/open-webui
|
||||
tag: main
|
||||
pullPolicy: IfNotPresent
|
||||
subdomain: openwebui
|
||||
0
charts/apps/values.yaml
Normal file
0
charts/apps/values.yaml
Normal file
12
charts/operator/templates/_storageclass.yaml
Normal file
12
charts/operator/templates/_storageclass.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
apiVersion: storage.k8s.io/v1
|
||||
kind: StorageClass
|
||||
metadata:
|
||||
name: {{ include "homelab-operator.fullname" . }}-local-path
|
||||
labels:
|
||||
{{- include "homelab-operator.labels" . | nindent 4 }}
|
||||
provisioner: reuse-local-path-provisioner
|
||||
parameters:
|
||||
# Add any provisioner-specific parameters here
|
||||
reclaimPolicy: {{ .Values.storage.reclaimPolicy | default "Retain" }}
|
||||
allowVolumeExpansion: {{ .Values.storage.allowVolumeExpansion | default false }}
|
||||
volumeBindingMode: {{ .Values.storage.volumeBindingMode | default "WaitForFirstConsumer" }}
|
||||
32
charts/operator/templates/clusterrole.yaml
Normal file
32
charts/operator/templates/clusterrole.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: {{ include "homelab-operator.fullname" . }}
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["create", "get", "watch", "list"]
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces"]
|
||||
verbs: ["get", "list", "watch", "create", "update", "patch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumes"]
|
||||
verbs: ["get", "list", "watch", "create", "delete", "patch", "update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumeclaims"]
|
||||
verbs: ["get", "list", "watch", "update", "patch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumeclaims/status"]
|
||||
verbs: ["update", "patch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["events"]
|
||||
verbs: ["create", "patch"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["storageclasses"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["*"]
|
||||
resources: ["*"]
|
||||
verbs: ["get", "watch", "list", "patch", "create", "update", "replace"]
|
||||
- apiGroups: ["apiextensions.k8s.io"]
|
||||
resources: ["customresourcedefinitions"]
|
||||
verbs: ["get", "create", "update", "replace", "patch"]
|
||||
@@ -33,6 +33,14 @@ spec:
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
volumeMounts:
|
||||
- name: data-volumes
|
||||
mountPath: {{ .Values.storage.path }}
|
||||
volumes:
|
||||
- name: data-volumes
|
||||
hostPath:
|
||||
path: {{ .Values.storage.path }}
|
||||
type: DirectoryOrCreate
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
@@ -6,11 +6,17 @@ image:
|
||||
repository: ghcr.io/morten-olsen/homelab-operator
|
||||
pullPolicy: IfNotPresent
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: ""
|
||||
tag: main
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
nameOverride: ''
|
||||
fullnameOverride: ''
|
||||
|
||||
storage:
|
||||
path: /data/volumes
|
||||
reclaimPolicy: Retain
|
||||
allowVolumeExpansion: false
|
||||
volumeBindingMode: WaitForFirstConsumer
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
@@ -19,7 +25,7 @@ serviceAccount:
|
||||
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: ""
|
||||
name: ''
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
3
charts/root/Chart.yaml
Normal file
3
charts/root/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
apiVersion: v2
|
||||
version: 1.0.0
|
||||
name: root
|
||||
33
charts/root/templates/apps.yaml
Normal file
33
charts/root/templates/apps.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: ApplicationSet
|
||||
metadata:
|
||||
name: homelab-apps
|
||||
namespace: '{{ .Values.env }}-argo'
|
||||
spec:
|
||||
generators:
|
||||
- git:
|
||||
repoURL: '{{ .Values.repo }}'
|
||||
revision: '{{ .Values.ref }}'
|
||||
directories:
|
||||
- path: charts/apps/*
|
||||
include: '.*'
|
||||
exclude: '.*.disabled'
|
||||
template:
|
||||
metadata:
|
||||
name: '{{`{{path.basename}}`}}'
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: '{{ .Values.repo }}'
|
||||
targetRevision: '{{ .Values.ref }}'
|
||||
path: charts/apps/{{`{{path.basename}}`}}
|
||||
helm:
|
||||
values: |
|
||||
globals: {{ .Values.globals | toYaml | nindent 14 }}
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: '{{ .Values.globals.env }}'
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
21
charts/root/templates/root.yaml
Normal file
21
charts/root/templates/root.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: homelab-root
|
||||
namespace: '{{ .Values.globals.env }}-argo'
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: '{{ .Values.repo }}'
|
||||
targetRevision: '{{ .Values.ref }}'
|
||||
path: charts/root
|
||||
helm:
|
||||
valueFiles:
|
||||
- values.yaml
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: '{{ .Values.globals.env }}-argo'
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
4
charts/root/values.yaml
Normal file
4
charts/root/values.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
globals:
|
||||
env: prod
|
||||
repo: https://github.com/morten-olsen/homelab-operator.git
|
||||
ref: HEAD
|
||||
3
charts/volumes/Chart.yaml
Normal file
3
charts/volumes/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
apiVersion: v2
|
||||
version: 1.0.0
|
||||
name: Resources
|
||||
28
charts/volumes/templates/books-pvc.yaml
Normal file
28
charts/volumes/templates/books-pvc.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: books
|
||||
labels:
|
||||
type: nfs
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: manual-books
|
||||
nfs:
|
||||
path: '{{ .Values.books.path }}'
|
||||
server: '{{ .Values.host }}'
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: books
|
||||
spec:
|
||||
storageClassName: manual-books
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
28
charts/volumes/templates/movies-pvc.yaml
Normal file
28
charts/volumes/templates/movies-pvc.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: movies
|
||||
labels:
|
||||
type: nfs
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: manual-movies
|
||||
nfs:
|
||||
path: '{{ .Values.movies.path }}'
|
||||
server: '{{ .Values.host }}'
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: movies
|
||||
spec:
|
||||
storageClassName: manual-movies
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
28
charts/volumes/templates/music-pvc.yaml
Normal file
28
charts/volumes/templates/music-pvc.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: music
|
||||
labels:
|
||||
type: nfs
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: manual-music
|
||||
nfs:
|
||||
path: '{{ .Values.music.path }}'
|
||||
server: '{{ .Values.host }}'
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: music
|
||||
spec:
|
||||
storageClassName: manual-music
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
28
charts/volumes/templates/podcasts-pvc.yaml
Normal file
28
charts/volumes/templates/podcasts-pvc.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: podcasts
|
||||
labels:
|
||||
type: nfs
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: manual-podcasts
|
||||
nfs:
|
||||
path: '{{ .Values.podcasts.path }}'
|
||||
server: '{{ .Values.host }}'
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: podcasts
|
||||
spec:
|
||||
storageClassName: manual-podcasts
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
28
charts/volumes/templates/tv-pvc.yaml
Normal file
28
charts/volumes/templates/tv-pvc.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: tvshows
|
||||
labels:
|
||||
type: nfs
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: manual-tvshows
|
||||
nfs:
|
||||
path: '{{ .Values.tvshows.path }}'
|
||||
server: '{{ .Values.host }}'
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: tvshows
|
||||
spec:
|
||||
storageClassName: manual-tvshows
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
11
charts/volumes/values.yaml
Normal file
11
charts/volumes/values.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
host: 192.168.20.106
|
||||
movies:
|
||||
path: /mnt/HDD/Movies
|
||||
tvshows:
|
||||
path: /mnt/HDD/TV-Shows
|
||||
music:
|
||||
path: /mnt/HDD/Music2
|
||||
books:
|
||||
path: /mnt/HDD/Books
|
||||
podcasts:
|
||||
path: /mnt/HDD/Podcasts
|
||||
@@ -1,12 +0,0 @@
|
||||
name: homelab
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:17
|
||||
ports:
|
||||
- 5432:5432
|
||||
environment:
|
||||
POSTGRES_USER: $POSTGRES_USER
|
||||
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
|
||||
POSTGRES_DB: ${POSTGRES_DB:-postgres}
|
||||
volumes:
|
||||
- $PWD/.data/local/postgres:/var/lib/postgresql/data
|
||||
@@ -46,6 +46,6 @@ export default tseslint.config(
|
||||
},
|
||||
...compat.extends('plugin:prettier/recommended'),
|
||||
{
|
||||
ignores: ['**/node_modules/', '**/dist/', '**/.turbo/', '**/generated/'],
|
||||
ignores: ['**/node_modules/', '**/dist/', '**/.turbo/', '**/generated/', '**/clients/*.types.ts'],
|
||||
},
|
||||
);
|
||||
|
||||
22
istio-test.yaml
Normal file
22
istio-test.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
apiVersion: networking.istio.io/v1beta1
|
||||
kind: ServiceEntry
|
||||
metadata:
|
||||
name: dev-authentik-override
|
||||
namespace: dev
|
||||
spec:
|
||||
hosts:
|
||||
- authentik.mortenolsen.nett
|
||||
ports:
|
||||
- number: 443
|
||||
name: https
|
||||
protocol: HTTPS
|
||||
- number: 80
|
||||
name: http
|
||||
protocol: HTTP
|
||||
location: MESH_EXTERNAL
|
||||
resolution: STATIC
|
||||
endpoints:
|
||||
- address: 1.1.1.1
|
||||
ports:
|
||||
https: 443
|
||||
http: 80
|
||||
9
manifests/client.yaml
Normal file
9
manifests/client.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: OidcClient
|
||||
metadata:
|
||||
name: test-client
|
||||
spec:
|
||||
environment: dev
|
||||
redirectUris:
|
||||
- url: https://localhost:3000/api/v1/authentik/oauth2/callback
|
||||
matchingMode: strict
|
||||
14
manifests/environment.yaml
Normal file
14
manifests/environment.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: dev
|
||||
---
|
||||
apiVersion: homelab.mortenolsen.pro/v1
|
||||
kind: Environment
|
||||
metadata:
|
||||
name: prod
|
||||
spec:
|
||||
domain: olsen.cloud
|
||||
networkIp: 192.168.20.180
|
||||
tls:
|
||||
issuer: lets-encrypt-prod
|
||||
39
manifests/example-pvc.yaml
Normal file
39
manifests/example-pvc.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: example-pvc
|
||||
namespace: default
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
storageClassName: homelab-operator-local-path
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: example-pod
|
||||
namespace: default
|
||||
spec:
|
||||
containers:
|
||||
- name: example-container
|
||||
image: alpine
|
||||
command: ["/bin/sh", "-c", "sleep infinity"]
|
||||
volumeMounts:
|
||||
- name: example-volume
|
||||
mountPath: /data
|
||||
resources:
|
||||
limits:
|
||||
memory: 100Mi
|
||||
cpu: "0.1"
|
||||
requests:
|
||||
memory: 50Mi
|
||||
cpu: "0.05"
|
||||
volumes:
|
||||
- name: example-volume
|
||||
persistentVolumeClaim:
|
||||
claimName: example-pvc
|
||||
14
manifests/test-service.yaml
Normal file
14
manifests/test-service.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: ServiceEntry
|
||||
metadata:
|
||||
name: test-example-com
|
||||
namespace: dev
|
||||
spec:
|
||||
hosts:
|
||||
- authentik.one.dev.olsen.cloud
|
||||
# (the address field is optional if you use 'resolution: DNS')
|
||||
ports:
|
||||
- number: 80
|
||||
name: https
|
||||
protocol: HTTPS
|
||||
resolution: DNS
|
||||
35
operator.yaml
Normal file
35
operator.yaml
Normal file
@@ -0,0 +1,35 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: homelab
|
||||
|
||||
---
|
||||
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: GitRepository
|
||||
metadata:
|
||||
name: homelab
|
||||
namespace: homelab
|
||||
spec:
|
||||
interval: 60m
|
||||
url: https://github.com/morten-olsen/homelab-operator
|
||||
ref:
|
||||
branch: main
|
||||
|
||||
---
|
||||
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: operator
|
||||
namespace: homelab
|
||||
spec:
|
||||
releaseName: operator
|
||||
interval: 60m
|
||||
chart:
|
||||
spec:
|
||||
chart: charts/operator
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: homelab
|
||||
namespace: homelab
|
||||
31
package.json
31
package.json
@@ -4,15 +4,14 @@
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest",
|
||||
"nodemon": "^3.1.10",
|
||||
"@eslint/eslintrc": "3.3.1",
|
||||
"@eslint/js": "9.32.0",
|
||||
"@pnpm/find-workspace-packages": "6.0.9",
|
||||
"@types/deep-equal": "^1.0.4",
|
||||
"eslint": "9.32.0",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"eslint-plugin-prettier": "5.5.3",
|
||||
"json-schema-to-typescript": "^15.0.4",
|
||||
"prettier": "3.6.2",
|
||||
"typescript": "5.8.3",
|
||||
"typescript-eslint": "8.38.0"
|
||||
@@ -21,17 +20,37 @@
|
||||
"typescript": "^5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@goauthentik/api": "2025.6.3-1751754396",
|
||||
"@kubernetes/client-node": "^1.3.0",
|
||||
"@sinclair/typebox": "^0.34.38",
|
||||
"cloudflare": "^4.5.0",
|
||||
"cron": "^4.3.3",
|
||||
"debounce": "^2.2.0",
|
||||
"deep-equal": "^2.2.3",
|
||||
"dotenv": "^17.2.1",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"execa": "^9.6.0",
|
||||
"knex": "^3.1.0",
|
||||
"p-queue": "^8.1.0",
|
||||
"p-retry": "^6.2.1",
|
||||
"pg": "^8.16.3",
|
||||
"sqlite3": "^5.1.7"
|
||||
"sqlite3": "^5.1.7",
|
||||
"yaml": "^2.8.0",
|
||||
"zod": "^4.0.14"
|
||||
},
|
||||
"imports": {
|
||||
"#services/*": "./src/services/*",
|
||||
"#resources/*": "./src/resources/*",
|
||||
"#bootstrap/*": "./src/bootstrap/*",
|
||||
"#utils/*": "./src/utils/*"
|
||||
},
|
||||
"packageManager": "pnpm@10.6.0",
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"sqlite3"
|
||||
]
|
||||
],
|
||||
"patchedDependencies": {
|
||||
"@kubernetes/client-node": "patches/@kubernetes__client-node.patch"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo 'No tests'",
|
||||
|
||||
14
patches/@kubernetes__client-node.patch
Normal file
14
patches/@kubernetes__client-node.patch
Normal file
@@ -0,0 +1,14 @@
|
||||
diff --git a/dist/gen/models/ObjectSerializer.js b/dist/gen/models/ObjectSerializer.js
|
||||
index 1d798b6a2d7c059165d1df9fbb77b89a8317ebca..c8bacfdc95be0f0146c6505f89a9372e013afea4 100644
|
||||
--- a/dist/gen/models/ObjectSerializer.js
|
||||
+++ b/dist/gen/models/ObjectSerializer.js
|
||||
@@ -2216,6 +2216,9 @@ export class ObjectSerializer {
|
||||
return transformedData;
|
||||
}
|
||||
else if (type === "Date") {
|
||||
+ if (typeof data === "string") {
|
||||
+ return data;
|
||||
+ }
|
||||
if (format == "date") {
|
||||
let month = data.getMonth() + 1;
|
||||
month = month < 10 ? "0" + month.toString() : month.toString();
|
||||
1638
pnpm-lock.yaml
generated
1638
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,8 +0,0 @@
|
||||
apiVersion: 'homelab.mortenolsen.pro/v1';
|
||||
kind: 'PostgresDatabase';
|
||||
name: 'test2';
|
||||
namespace: 'playground';
|
||||
foo: 'bar';
|
||||
foo: 'bar';
|
||||
{
|
||||
}
|
||||
9
pyproject.toml
Normal file
9
pyproject.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[project]
|
||||
name = "homelab-operator"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"kubediagrams>=0.5.0",
|
||||
]
|
||||
49
scripts/update-manifests.ts
Executable file
49
scripts/update-manifests.ts
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env node
|
||||
import { mkdir, writeFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
|
||||
import { compile } from 'json-schema-to-typescript';
|
||||
|
||||
import { K8sService } from '../src/services/k8s/k8s.ts';
|
||||
import { Services } from '../src/utils/service.ts';
|
||||
|
||||
const services = new Services();
|
||||
const k8s = services.get(K8sService);
|
||||
|
||||
const manifests = await k8s.extensionsApi.listCustomResourceDefinition();
|
||||
const root = join(import.meta.dirname, '..', 'src', '__generated__', 'resources');
|
||||
|
||||
await mkdir(root, { recursive: true });
|
||||
|
||||
const firstUpsercase = (input: string) => {
|
||||
const [first, ...rest] = input.split('');
|
||||
return [first.toUpperCase(), ...rest].join('');
|
||||
};
|
||||
|
||||
for (const manifest of manifests.items) {
|
||||
for (const version of manifest.spec.versions) {
|
||||
try {
|
||||
const schema = version.schema?.openAPIV3Schema;
|
||||
if (!schema) {
|
||||
continue;
|
||||
}
|
||||
const cleanedSchema = JSON.parse(JSON.stringify(schema));
|
||||
const kind = manifest.spec.names.kind;
|
||||
const typeName = `K8S${kind}${firstUpsercase(version.name)}`;
|
||||
const jsonLocation = join(root, `${typeName}.json`);
|
||||
await writeFile(jsonLocation, JSON.stringify(schema, null, 2));
|
||||
const file = await compile(cleanedSchema, typeName, {
|
||||
declareExternallyReferenced: true,
|
||||
additionalProperties: false,
|
||||
$refOptions: {
|
||||
continueOnError: true,
|
||||
},
|
||||
});
|
||||
const fileLocation = join(root, `${typeName}.ts`);
|
||||
await writeFile(fileLocation, file, 'utf8');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
console.error(`${manifest.metadata?.name} ${version.name} failed`);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
skaffold.yaml
Normal file
25
skaffold.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
apiVersion: skaffold/v4beta7
|
||||
kind: Config
|
||||
metadata:
|
||||
name: homelab-operator
|
||||
|
||||
build:
|
||||
cluster: {}
|
||||
artifacts:
|
||||
- image: homelaboperator
|
||||
context: .
|
||||
docker:
|
||||
dockerfile: Dockerfile
|
||||
|
||||
manifests:
|
||||
helm:
|
||||
releases:
|
||||
- name: homelab-operator
|
||||
chartPath: charts/operator
|
||||
setValueTemplates:
|
||||
image.repository: '{{.IMAGE_REPO_homelaboperator}}'
|
||||
image.tag: '{{.IMAGE_TAG_homelaboperator}}'
|
||||
|
||||
deploy:
|
||||
# Use kubectl to apply the manifests.
|
||||
kubectl: {}
|
||||
31
src/__generated__/resources/K8SAddonV1.json
generated
Normal file
31
src/__generated__/resources/K8SAddonV1.json
generated
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"description": "Addon is used to track application of a manifest file on disk. It mostly exists so that the wrangler DesiredSet\nApply controller has an object to track as the owner, and ensure that all created resources are tracked when the\nmanifest is modified or removed.",
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to.\nCannot be updated.\nIn CamelCase.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object"
|
||||
},
|
||||
"spec": {
|
||||
"description": "Spec provides information about the on-disk manifest backing this resource.",
|
||||
"properties": {
|
||||
"checksum": {
|
||||
"description": "Checksum is the SHA256 checksum of the most recently successfully applied manifest file.",
|
||||
"type": "string"
|
||||
},
|
||||
"source": {
|
||||
"description": "Source is the Path on disk to the manifest file that this Addon tracks.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
43
src/__generated__/resources/K8SAddonV1.ts
generated
Normal file
43
src/__generated__/resources/K8SAddonV1.ts
generated
Normal file
@@ -0,0 +1,43 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* This file was automatically generated by json-schema-to-typescript.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
||||
* and run json-schema-to-typescript to regenerate this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Addon is used to track application of a manifest file on disk. It mostly exists so that the wrangler DesiredSet
|
||||
* Apply controller has an object to track as the owner, and ensure that all created resources are tracked when the
|
||||
* manifest is modified or removed.
|
||||
*/
|
||||
export interface K8SAddonV1 {
|
||||
/**
|
||||
* APIVersion defines the versioned schema of this representation of an object.
|
||||
* Servers should convert recognized schemas to the latest internal value, and
|
||||
* may reject unrecognized values.
|
||||
* More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
*/
|
||||
apiVersion?: string;
|
||||
/**
|
||||
* Kind is a string value representing the REST resource this object represents.
|
||||
* Servers may infer this from the endpoint the client submits requests to.
|
||||
* Cannot be updated.
|
||||
* In CamelCase.
|
||||
* More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
*/
|
||||
kind?: string;
|
||||
metadata?: {};
|
||||
/**
|
||||
* Spec provides information about the on-disk manifest backing this resource.
|
||||
*/
|
||||
spec?: {
|
||||
/**
|
||||
* Checksum is the SHA256 checksum of the most recently successfully applied manifest file.
|
||||
*/
|
||||
checksum?: string;
|
||||
/**
|
||||
* Source is the Path on disk to the manifest file that this Addon tracks.
|
||||
*/
|
||||
source?: string;
|
||||
};
|
||||
}
|
||||
376
src/__generated__/resources/K8SAppProjectV1alpha1.json
generated
Normal file
376
src/__generated__/resources/K8SAppProjectV1alpha1.json
generated
Normal file
@@ -0,0 +1,376 @@
|
||||
{
|
||||
"description": "AppProject provides a logical grouping of applications, providing controls for:\n* where the apps may deploy to (cluster whitelist)\n* what may be deployed (repository whitelist, resource whitelist/blacklist)\n* who can access these applications (roles, OIDC group claims bindings)\n* and what they can do (RBAC policies)\n* automation access to these roles (JWT tokens)",
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to.\nCannot be updated.\nIn CamelCase.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object"
|
||||
},
|
||||
"spec": {
|
||||
"description": "AppProjectSpec is the specification of an AppProject",
|
||||
"properties": {
|
||||
"clusterResourceBlacklist": {
|
||||
"description": "ClusterResourceBlacklist contains list of blacklisted cluster level resources",
|
||||
"items": {
|
||||
"description": "GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying\nconcepts during lookup stages without having partially valid types",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"group",
|
||||
"kind"
|
||||
],
|
||||
"properties": {
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"clusterResourceWhitelist": {
|
||||
"description": "ClusterResourceWhitelist contains list of whitelisted cluster level resources",
|
||||
"items": {
|
||||
"description": "GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying\nconcepts during lookup stages without having partially valid types",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"group",
|
||||
"kind"
|
||||
],
|
||||
"properties": {
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"description": {
|
||||
"description": "Description contains optional project description",
|
||||
"type": "string"
|
||||
},
|
||||
"destinationServiceAccounts": {
|
||||
"description": "DestinationServiceAccounts holds information about the service accounts to be impersonated for the application sync operation for each destination.",
|
||||
"items": {
|
||||
"description": "ApplicationDestinationServiceAccount holds information about the service account to be impersonated for the application sync operation.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"defaultServiceAccount",
|
||||
"server"
|
||||
],
|
||||
"properties": {
|
||||
"defaultServiceAccount": {
|
||||
"description": "DefaultServiceAccount to be used for impersonation during the sync operation",
|
||||
"type": "string"
|
||||
},
|
||||
"namespace": {
|
||||
"description": "Namespace specifies the target namespace for the application's resources.",
|
||||
"type": "string"
|
||||
},
|
||||
"server": {
|
||||
"description": "Server specifies the URL of the target cluster's Kubernetes control plane API.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"destinations": {
|
||||
"description": "Destinations contains list of destinations available for deployment",
|
||||
"items": {
|
||||
"description": "ApplicationDestination holds information about the application's destination",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "Name is an alternate way of specifying the target cluster by its symbolic name. This must be set if Server is not set.",
|
||||
"type": "string"
|
||||
},
|
||||
"namespace": {
|
||||
"description": "Namespace specifies the target namespace for the application's resources.\nThe namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace",
|
||||
"type": "string"
|
||||
},
|
||||
"server": {
|
||||
"description": "Server specifies the URL of the target cluster's Kubernetes control plane API. This must be set if Name is not set.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"namespaceResourceBlacklist": {
|
||||
"description": "NamespaceResourceBlacklist contains list of blacklisted namespace level resources",
|
||||
"items": {
|
||||
"description": "GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying\nconcepts during lookup stages without having partially valid types",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"group",
|
||||
"kind"
|
||||
],
|
||||
"properties": {
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"namespaceResourceWhitelist": {
|
||||
"description": "NamespaceResourceWhitelist contains list of whitelisted namespace level resources",
|
||||
"items": {
|
||||
"description": "GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying\nconcepts during lookup stages without having partially valid types",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"group",
|
||||
"kind"
|
||||
],
|
||||
"properties": {
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"orphanedResources": {
|
||||
"description": "OrphanedResources specifies if controller should monitor orphaned resources of apps in this project",
|
||||
"properties": {
|
||||
"ignore": {
|
||||
"description": "Ignore contains a list of resources that are to be excluded from orphaned resources monitoring",
|
||||
"items": {
|
||||
"description": "OrphanedResourceKey is a reference to a resource to be ignored from",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"warn": {
|
||||
"description": "Warn indicates if warning condition should be created for apps which have orphaned resources",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"permitOnlyProjectScopedClusters": {
|
||||
"description": "PermitOnlyProjectScopedClusters determines whether destinations can only reference clusters which are project-scoped",
|
||||
"type": "boolean"
|
||||
},
|
||||
"roles": {
|
||||
"description": "Roles are user defined RBAC roles associated with this project",
|
||||
"items": {
|
||||
"description": "ProjectRole represents a role that has access to a project",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"description": {
|
||||
"description": "Description is a description of the role",
|
||||
"type": "string"
|
||||
},
|
||||
"groups": {
|
||||
"description": "Groups are a list of OIDC group claims bound to this role",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"jwtTokens": {
|
||||
"description": "JWTTokens are a list of generated JWT tokens bound to this role",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "JWTToken holds the issuedAt and expiresAt values of a token",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"iat"
|
||||
],
|
||||
"properties": {
|
||||
"exp": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"iat": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"description": "Name is a name for this role",
|
||||
"type": "string"
|
||||
},
|
||||
"policies": {
|
||||
"description": "Policies Stores a list of casbin formatted strings that define access policies for the role in the project",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"signatureKeys": {
|
||||
"description": "SignatureKeys contains a list of PGP key IDs that commits in Git must be signed with in order to be allowed for sync",
|
||||
"items": {
|
||||
"description": "SignatureKey is the specification of a key required to verify commit signatures with",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"keyID"
|
||||
],
|
||||
"properties": {
|
||||
"keyID": {
|
||||
"description": "The ID of the key in hexadecimal notation",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"sourceNamespaces": {
|
||||
"description": "SourceNamespaces defines the namespaces application resources are allowed to be created in",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"sourceRepos": {
|
||||
"description": "SourceRepos contains list of repository URLs which can be used for deployment",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"syncWindows": {
|
||||
"description": "SyncWindows controls when syncs can be run for apps in this project",
|
||||
"items": {
|
||||
"description": "SyncWindow contains the kind, time, duration and attributes that are used to assign the syncWindows to apps",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"andOperator": {
|
||||
"description": "UseAndOperator use AND operator for matching applications, namespaces and clusters instead of the default OR operator",
|
||||
"type": "boolean"
|
||||
},
|
||||
"applications": {
|
||||
"description": "Applications contains a list of applications that the window will apply to",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"clusters": {
|
||||
"description": "Clusters contains a list of clusters that the window will apply to",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"duration": {
|
||||
"description": "Duration is the amount of time the sync window will be open",
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"description": "Kind defines if the window allows or blocks syncs",
|
||||
"type": "string"
|
||||
},
|
||||
"manualSync": {
|
||||
"description": "ManualSync enables manual syncs when they would otherwise be blocked",
|
||||
"type": "boolean"
|
||||
},
|
||||
"namespaces": {
|
||||
"description": "Namespaces contains a list of namespaces that the window will apply to",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"schedule": {
|
||||
"description": "Schedule is the time the window will begin, specified in cron format",
|
||||
"type": "string"
|
||||
},
|
||||
"timeZone": {
|
||||
"description": "TimeZone of the sync that will be applied to the schedule",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"status": {
|
||||
"description": "AppProjectStatus contains status information for AppProject CRs",
|
||||
"properties": {
|
||||
"jwtTokensByRole": {
|
||||
"additionalProperties": {
|
||||
"description": "JWTTokens represents a list of JWT tokens",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "JWTToken holds the issuedAt and expiresAt values of a token",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"iat"
|
||||
],
|
||||
"properties": {
|
||||
"exp": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"iat": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "JWTTokensByRole contains a list of JWT tokens issued for a given role",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"metadata",
|
||||
"spec"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
233
src/__generated__/resources/K8SAppProjectV1alpha1.ts
generated
Normal file
233
src/__generated__/resources/K8SAppProjectV1alpha1.ts
generated
Normal file
@@ -0,0 +1,233 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* This file was automatically generated by json-schema-to-typescript.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
||||
* and run json-schema-to-typescript to regenerate this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* AppProject provides a logical grouping of applications, providing controls for:
|
||||
* * where the apps may deploy to (cluster whitelist)
|
||||
* * what may be deployed (repository whitelist, resource whitelist/blacklist)
|
||||
* * who can access these applications (roles, OIDC group claims bindings)
|
||||
* * and what they can do (RBAC policies)
|
||||
* * automation access to these roles (JWT tokens)
|
||||
*/
|
||||
export interface K8SAppProjectV1Alpha1 {
|
||||
/**
|
||||
* APIVersion defines the versioned schema of this representation of an object.
|
||||
* Servers should convert recognized schemas to the latest internal value, and
|
||||
* may reject unrecognized values.
|
||||
* More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
*/
|
||||
apiVersion?: string;
|
||||
/**
|
||||
* Kind is a string value representing the REST resource this object represents.
|
||||
* Servers may infer this from the endpoint the client submits requests to.
|
||||
* Cannot be updated.
|
||||
* In CamelCase.
|
||||
* More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
*/
|
||||
kind?: string;
|
||||
metadata: {};
|
||||
/**
|
||||
* AppProjectSpec is the specification of an AppProject
|
||||
*/
|
||||
spec: {
|
||||
/**
|
||||
* ClusterResourceBlacklist contains list of blacklisted cluster level resources
|
||||
*/
|
||||
clusterResourceBlacklist?: {
|
||||
group: string;
|
||||
kind: string;
|
||||
}[];
|
||||
/**
|
||||
* ClusterResourceWhitelist contains list of whitelisted cluster level resources
|
||||
*/
|
||||
clusterResourceWhitelist?: {
|
||||
group: string;
|
||||
kind: string;
|
||||
}[];
|
||||
/**
|
||||
* Description contains optional project description
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* DestinationServiceAccounts holds information about the service accounts to be impersonated for the application sync operation for each destination.
|
||||
*/
|
||||
destinationServiceAccounts?: {
|
||||
/**
|
||||
* DefaultServiceAccount to be used for impersonation during the sync operation
|
||||
*/
|
||||
defaultServiceAccount: string;
|
||||
/**
|
||||
* Namespace specifies the target namespace for the application's resources.
|
||||
*/
|
||||
namespace?: string;
|
||||
/**
|
||||
* Server specifies the URL of the target cluster's Kubernetes control plane API.
|
||||
*/
|
||||
server: string;
|
||||
}[];
|
||||
/**
|
||||
* Destinations contains list of destinations available for deployment
|
||||
*/
|
||||
destinations?: {
|
||||
/**
|
||||
* Name is an alternate way of specifying the target cluster by its symbolic name. This must be set if Server is not set.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* Namespace specifies the target namespace for the application's resources.
|
||||
* The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace
|
||||
*/
|
||||
namespace?: string;
|
||||
/**
|
||||
* Server specifies the URL of the target cluster's Kubernetes control plane API. This must be set if Name is not set.
|
||||
*/
|
||||
server?: string;
|
||||
}[];
|
||||
/**
|
||||
* NamespaceResourceBlacklist contains list of blacklisted namespace level resources
|
||||
*/
|
||||
namespaceResourceBlacklist?: {
|
||||
group: string;
|
||||
kind: string;
|
||||
}[];
|
||||
/**
|
||||
* NamespaceResourceWhitelist contains list of whitelisted namespace level resources
|
||||
*/
|
||||
namespaceResourceWhitelist?: {
|
||||
group: string;
|
||||
kind: string;
|
||||
}[];
|
||||
/**
|
||||
* OrphanedResources specifies if controller should monitor orphaned resources of apps in this project
|
||||
*/
|
||||
orphanedResources?: {
|
||||
/**
|
||||
* Ignore contains a list of resources that are to be excluded from orphaned resources monitoring
|
||||
*/
|
||||
ignore?: {
|
||||
group?: string;
|
||||
kind?: string;
|
||||
name?: string;
|
||||
}[];
|
||||
/**
|
||||
* Warn indicates if warning condition should be created for apps which have orphaned resources
|
||||
*/
|
||||
warn?: boolean;
|
||||
};
|
||||
/**
|
||||
* PermitOnlyProjectScopedClusters determines whether destinations can only reference clusters which are project-scoped
|
||||
*/
|
||||
permitOnlyProjectScopedClusters?: boolean;
|
||||
/**
|
||||
* Roles are user defined RBAC roles associated with this project
|
||||
*/
|
||||
roles?: {
|
||||
/**
|
||||
* Description is a description of the role
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* Groups are a list of OIDC group claims bound to this role
|
||||
*/
|
||||
groups?: string[];
|
||||
/**
|
||||
* JWTTokens are a list of generated JWT tokens bound to this role
|
||||
*/
|
||||
jwtTokens?: {
|
||||
exp?: number;
|
||||
iat: number;
|
||||
id?: string;
|
||||
}[];
|
||||
/**
|
||||
* Name is a name for this role
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Policies Stores a list of casbin formatted strings that define access policies for the role in the project
|
||||
*/
|
||||
policies?: string[];
|
||||
}[];
|
||||
/**
|
||||
* SignatureKeys contains a list of PGP key IDs that commits in Git must be signed with in order to be allowed for sync
|
||||
*/
|
||||
signatureKeys?: {
|
||||
/**
|
||||
* The ID of the key in hexadecimal notation
|
||||
*/
|
||||
keyID: string;
|
||||
}[];
|
||||
/**
|
||||
* SourceNamespaces defines the namespaces application resources are allowed to be created in
|
||||
*/
|
||||
sourceNamespaces?: string[];
|
||||
/**
|
||||
* SourceRepos contains list of repository URLs which can be used for deployment
|
||||
*/
|
||||
sourceRepos?: string[];
|
||||
/**
|
||||
* SyncWindows controls when syncs can be run for apps in this project
|
||||
*/
|
||||
syncWindows?: {
|
||||
/**
|
||||
* UseAndOperator use AND operator for matching applications, namespaces and clusters instead of the default OR operator
|
||||
*/
|
||||
andOperator?: boolean;
|
||||
/**
|
||||
* Applications contains a list of applications that the window will apply to
|
||||
*/
|
||||
applications?: string[];
|
||||
/**
|
||||
* Clusters contains a list of clusters that the window will apply to
|
||||
*/
|
||||
clusters?: string[];
|
||||
/**
|
||||
* Duration is the amount of time the sync window will be open
|
||||
*/
|
||||
duration?: string;
|
||||
/**
|
||||
* Kind defines if the window allows or blocks syncs
|
||||
*/
|
||||
kind?: string;
|
||||
/**
|
||||
* ManualSync enables manual syncs when they would otherwise be blocked
|
||||
*/
|
||||
manualSync?: boolean;
|
||||
/**
|
||||
* Namespaces contains a list of namespaces that the window will apply to
|
||||
*/
|
||||
namespaces?: string[];
|
||||
/**
|
||||
* Schedule is the time the window will begin, specified in cron format
|
||||
*/
|
||||
schedule?: string;
|
||||
/**
|
||||
* TimeZone of the sync that will be applied to the schedule
|
||||
*/
|
||||
timeZone?: string;
|
||||
}[];
|
||||
};
|
||||
/**
|
||||
* AppProjectStatus contains status information for AppProject CRs
|
||||
*/
|
||||
status?: {
|
||||
/**
|
||||
* JWTTokensByRole contains a list of JWT tokens issued for a given role
|
||||
*/
|
||||
jwtTokensByRole?: {
|
||||
/**
|
||||
* JWTTokens represents a list of JWT tokens
|
||||
*/
|
||||
[k: string]: {
|
||||
items?: {
|
||||
exp?: number;
|
||||
iat: number;
|
||||
id?: string;
|
||||
}[];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
26928
src/__generated__/resources/K8SApplicationSetV1alpha1.json
generated
Normal file
26928
src/__generated__/resources/K8SApplicationSetV1alpha1.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user