Compare commits

...

1 Commits

Author SHA1 Message Date
Morten Olsen
d971f11573 Added storage provisioner 2025-08-11 11:27:59 +02:00
5 changed files with 118 additions and 5 deletions

View File

@@ -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 }}

View File

@@ -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
View 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}`);
}
}

View File

@@ -5,6 +5,7 @@ import { Services } from './utils/service.ts';
import { CustomResourceService } from './services/custom-resources/custom-resources.ts';
import { WatcherService } from './services/watchers/watchers.ts';
import { customResources } from './custom-resouces/custom-resources.ts';
import { StorageProvider } from './storage-provider/storage-provider.ts';
process.on('uncaughtException', (error) => {
console.log('UNCAUGHT EXCEPTION');
@@ -29,6 +30,8 @@ process.on('unhandledRejection', (error) => {
const services = new Services();
const watcherService = services.get(WatcherService);
const storageProvider = services.get(StorageProvider);
await storageProvider.start();
await watcherService
.create({
path: '/apis/apiextensions.k8s.io/v1/customresourcedefinitions',
@@ -76,4 +79,4 @@ const customResourceService = services.get(CustomResourceService);
customResourceService.register(...customResources);
await customResourceService.install(true);
await customResourceService.watch();
// await customResourceService.watch();

View File

@@ -0,0 +1,84 @@
import { mkdir } from 'fs/promises';
import { V1PersistentVolume, type V1PersistentVolumeClaim } from '@kubernetes/client-node';
import { Watcher, WatcherService } from '../services/watchers/watchers.ts';
import type { Services } from '../utils/service.ts';
import { ResourceService, type Resource } from '../services/resources/resources.ts';
const PROVISIONER = 'reuse-local-path-provisioner';
class StorageProvider {
#watcher: Watcher<V1PersistentVolumeClaim>;
#services: Services;
constructor(services: Services) {
this.#services = services;
const watchService = this.#services.get(WatcherService);
this.#watcher = watchService.create({
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'],
});
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/${pvc.namespace}/${pvc.name}`;
console.log('TARGET: ', target);
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: 'PersistentVolume',
name: pvc.name,
namespace: pvc.namespace,
});
await pv.load();
await pv.patch({
metadata: {
labels: {
provisioner: PROVISIONER,
},
},
spec: {
hostPath: {
path: target,
},
capacity: {
storage: pvc.spec?.resources?.requests?.storage ?? '1Gi',
},
persistentVolumeReclaimPolicy: 'Retain',
accessModes: pvc.spec?.accessModes,
claimRef: {
uid: pvc.metadata?.uid,
resourceVersion: pvc.metadata?.resourceVersion,
apiVersion: pvc.apiVersion,
name: pvc.name,
namespace: pvc.namespace,
},
},
});
};
public start = async () => {
await this.#watcher.start();
};
}
export { StorageProvider };