mirror of
https://github.com/morten-olsen/homelab-operator.git
synced 2026-02-08 01:36:28 +01:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b49e273b89 | ||
|
|
47cf43b44e |
@@ -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 }}
|
||||
|
||||
@@ -9,8 +9,11 @@ image:
|
||||
tag: main
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
nameOverride: ''
|
||||
fullnameOverride: ''
|
||||
|
||||
storage:
|
||||
path: /data/volumes
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
@@ -19,7 +22,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: {}
|
||||
|
||||
@@ -50,4 +53,4 @@ nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
affinity: {}
|
||||
|
||||
15
scripts/list-manifests.ts
Executable file
15
scripts/list-manifests.ts
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
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();
|
||||
|
||||
for (const manifest of manifests.items) {
|
||||
for (const version of manifest.spec.versions) {
|
||||
console.log(`group: ${manifest.spec.group}, plural: ${manifest.spec.names.plural}, version: ${version.name}`);
|
||||
}
|
||||
}
|
||||
@@ -37,8 +37,8 @@ class GenerateSecretResource extends CustomResource<typeof generateSecretSpecSch
|
||||
const current = decodeSecret(this.#secretResource.data) || {};
|
||||
|
||||
const expected = {
|
||||
...current,
|
||||
...secrets,
|
||||
...current,
|
||||
};
|
||||
|
||||
if (!isDeepSubset(current, expected)) {
|
||||
|
||||
@@ -95,6 +95,7 @@ class PostgresDatabaseResource extends CustomResource<typeof postgresDatabaseSpe
|
||||
port: serverSecretData.data.port,
|
||||
user: this.#userName,
|
||||
database: this.#dbName,
|
||||
...databaseSecretData.data,
|
||||
};
|
||||
|
||||
if (!isDeepSubset(databaseSecretData.data, expectedSecret)) {
|
||||
@@ -132,7 +133,7 @@ class PostgresDatabaseResource extends CustomResource<typeof postgresDatabaseSpe
|
||||
};
|
||||
}
|
||||
|
||||
const secretData = postgresDatabaseConnectionSecretSchema.safeParse(decodeSecret(this.#serverSecret.current?.data));
|
||||
const secretData = postgresDatabaseConnectionSecretSchema.safeParse(decodeSecret(this.#databaseSecret.data));
|
||||
if (!secretData.success || !secretData.data) {
|
||||
return {
|
||||
ready: false,
|
||||
|
||||
@@ -7,7 +7,6 @@ import type { Services } from '../utils/service.ts';
|
||||
import { ResourceService, type Resource } from '../services/resources/resources.ts';
|
||||
|
||||
const PROVISIONER = 'reuse-local-path-provisioner';
|
||||
const LABEL_SELECTOR = `provisioner=${PROVISIONER}`;
|
||||
|
||||
class StorageProvider {
|
||||
#watcher: Watcher<V1PersistentVolumeClaim>;
|
||||
@@ -17,26 +16,36 @@ class StorageProvider {
|
||||
this.#services = services;
|
||||
const watchService = this.#services.get(WatcherService);
|
||||
this.#watcher = watchService.create({
|
||||
path: 'api/v1/persistantvolumeclaims',
|
||||
list: (k8s) =>
|
||||
k8s.api.listPersistentVolumeClaimForAllNamespaces({
|
||||
labelSelector: LABEL_SELECTOR,
|
||||
}),
|
||||
path: '/api/v1/persistentvolumeclaims',
|
||||
transform: (manifest) => ({
|
||||
apiVersion: 'v1',
|
||||
kind: 'PersistentVolumeClaim',
|
||||
...manifest,
|
||||
}),
|
||||
list: async (k8s) => {
|
||||
const current = await k8s.api.listPersistentVolumeClaimForAllNamespaces();
|
||||
return current;
|
||||
},
|
||||
verbs: ['add', 'update', 'delete'],
|
||||
selector: LABEL_SELECTOR,
|
||||
});
|
||||
this.#watcher.on('changed', this.#handleChange);
|
||||
}
|
||||
|
||||
#handleChange = async (pvc: Resource<V1PersistentVolumeClaim>) => {
|
||||
if (pvc.metadata?.annotations?.['volume.kubernetes.io/storage-provisioner'] !== PROVISIONER) {
|
||||
return;
|
||||
}
|
||||
const target = `/data/volumes/${pvc.namespace}/${pvc.name}`;
|
||||
await mkdir(target, { recursive: true });
|
||||
try {
|
||||
await mkdir(target, { recursive: true });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
const resourceService = this.#services.get(ResourceService);
|
||||
const pv = resourceService.get<V1PersistentVolume>({
|
||||
apiVersion: 'v1',
|
||||
kind: 'PersistantVolume',
|
||||
name: pvc.name,
|
||||
namespace: pvc.namespace,
|
||||
kind: 'PersistentVolume',
|
||||
name: `${pvc.namespace}-${pvc.name}`,
|
||||
});
|
||||
await pv.load();
|
||||
await pv.patch({
|
||||
@@ -50,7 +59,7 @@ class StorageProvider {
|
||||
path: target,
|
||||
},
|
||||
capacity: {
|
||||
storage: pvc.spec?.resources?.requests?.storage ?? '1GB',
|
||||
storage: pvc.spec?.resources?.requests?.storage ?? '1Gi',
|
||||
},
|
||||
persistentVolumeReclaimPolicy: 'Retain',
|
||||
accessModes: pvc.spec?.accessModes,
|
||||
|
||||
Reference in New Issue
Block a user