mirror of
https://github.com/morten-olsen/homelab-operator.git
synced 2026-02-08 01:36:28 +01:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8591e4e2d3 |
@@ -33,14 +33,6 @@ spec:
|
|||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
resources:
|
resources:
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
{{- 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 }}
|
{{- with .Values.nodeSelector }}
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
{{- toYaml . | nindent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
|
|||||||
@@ -9,11 +9,8 @@ image:
|
|||||||
tag: main
|
tag: main
|
||||||
|
|
||||||
imagePullSecrets: []
|
imagePullSecrets: []
|
||||||
nameOverride: ''
|
nameOverride: ""
|
||||||
fullnameOverride: ''
|
fullnameOverride: ""
|
||||||
|
|
||||||
storage:
|
|
||||||
path: /data/volumes
|
|
||||||
|
|
||||||
serviceAccount:
|
serviceAccount:
|
||||||
# Specifies whether a service account should be created
|
# Specifies whether a service account should be created
|
||||||
@@ -22,7 +19,7 @@ serviceAccount:
|
|||||||
annotations: {}
|
annotations: {}
|
||||||
# The name of the service account to use.
|
# The name of the service account to use.
|
||||||
# If not set and create is true, a name is generated using the fullname template
|
# If not set and create is true, a name is generated using the fullname template
|
||||||
name: ''
|
name: ""
|
||||||
|
|
||||||
podAnnotations: {}
|
podAnnotations: {}
|
||||||
|
|
||||||
@@ -53,4 +50,4 @@ nodeSelector: {}
|
|||||||
|
|
||||||
tolerations: []
|
tolerations: []
|
||||||
|
|
||||||
affinity: {}
|
affinity: {}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#!/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}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -70,7 +70,7 @@ class AuthentikClientResource extends CustomResource<typeof authentikClientSpecS
|
|||||||
message: 'Server secret not found',
|
message: 'Server secret not found',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const url = serverSecretData.data.url;
|
const url = serverSecretData.data.external_url;
|
||||||
const appName = this.name;
|
const appName = this.name;
|
||||||
const clientSecretData = authentikClientSecretSchema.safeParse(decodeSecret(this.#clientSecretResource.data));
|
const clientSecretData = authentikClientSecretSchema.safeParse(decodeSecret(this.#clientSecretResource.data));
|
||||||
|
|
||||||
@@ -139,8 +139,8 @@ class AuthentikClientResource extends CustomResource<typeof authentikClientSpecS
|
|||||||
const authentikService = this.services.get(AuthentikService);
|
const authentikService = this.services.get(AuthentikService);
|
||||||
const authentikServer = authentikService.get({
|
const authentikServer = authentikService.get({
|
||||||
url: {
|
url: {
|
||||||
internal: `${serverSecretData.data.name}.${serverSecret.namespace}.svc.cluster.local`,
|
internal: serverSecretData.data.internal_url,
|
||||||
external: serverSecretData.data.url,
|
external: serverSecretData.data.external_url,
|
||||||
},
|
},
|
||||||
token: serverSecretData.data.token,
|
token: serverSecretData.data.token,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ const authentikClientSpecSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const authentikClientServerSecretSchema = z.object({
|
const authentikClientServerSecretSchema = z.object({
|
||||||
name: z.string(),
|
internal_url: z.string(),
|
||||||
url: z.string(),
|
external_url: z.string(),
|
||||||
token: z.string(),
|
token: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
import type { V1Secret } from '@kubernetes/client-node';
|
|
||||||
import deepEqual from 'deep-equal';
|
|
||||||
|
|
||||||
import {
|
|
||||||
CustomResource,
|
|
||||||
type CustomResourceOptions,
|
|
||||||
} from '../../services/custom-resources/custom-resources.custom-resource.ts';
|
|
||||||
import { ResourceService, type Resource } from '../../services/resources/resources.ts';
|
|
||||||
import type { ValueReference } from '../../services/value-reference/value-reference.instance.ts';
|
|
||||||
import { ValueReferenceService } from '../../services/value-reference/value-reference.ts';
|
|
||||||
import { decodeSecret, encodeSecret } from '../../utils/secrets.ts';
|
|
||||||
|
|
||||||
import type { authentikConnectionSpecSchema } from './authentik-connection.schemas.ts';
|
|
||||||
|
|
||||||
class AuthentikConnectionResource extends CustomResource<typeof authentikConnectionSpecSchema> {
|
|
||||||
#name: ValueReference;
|
|
||||||
#url: ValueReference;
|
|
||||||
#token: ValueReference;
|
|
||||||
#secret: Resource<V1Secret>;
|
|
||||||
|
|
||||||
constructor(options: CustomResourceOptions<typeof authentikConnectionSpecSchema>) {
|
|
||||||
super(options);
|
|
||||||
const valueReferenceService = this.services.get(ValueReferenceService);
|
|
||||||
const resourceService = this.services.get(ResourceService);
|
|
||||||
|
|
||||||
this.#name = valueReferenceService.get(this.namespace);
|
|
||||||
this.#url = valueReferenceService.get(this.namespace);
|
|
||||||
this.#token = valueReferenceService.get(this.namespace);
|
|
||||||
this.#secret = resourceService.get({
|
|
||||||
apiVersion: 'v1',
|
|
||||||
kind: 'Secret',
|
|
||||||
name: `${this.name}-authentik-server`,
|
|
||||||
namespace: this.namespace,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.#name.on('changed', this.queueReconcile);
|
|
||||||
this.#url.on('changed', this.queueReconcile);
|
|
||||||
this.#token.on('changed', this.queueReconcile);
|
|
||||||
this.#secret.on('changed', this.queueReconcile);
|
|
||||||
}
|
|
||||||
|
|
||||||
#updateResources = () => {
|
|
||||||
this.#name.ref = this.spec.name;
|
|
||||||
this.#url.ref = this.spec.url;
|
|
||||||
this.#token.ref = this.spec.token;
|
|
||||||
};
|
|
||||||
|
|
||||||
public reconcile = async () => {
|
|
||||||
this.#updateResources();
|
|
||||||
const name = this.#name.value;
|
|
||||||
const url = this.#url.value;
|
|
||||||
const token = this.#token.value;
|
|
||||||
if (!name) {
|
|
||||||
return await this.conditions.set('Ready', {
|
|
||||||
status: 'False',
|
|
||||||
reason: 'MissingName',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!url) {
|
|
||||||
return await this.conditions.set('Ready', {
|
|
||||||
status: 'False',
|
|
||||||
reason: 'MissingUrl',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!token) {
|
|
||||||
return await this.conditions.set('Ready', {
|
|
||||||
status: 'False',
|
|
||||||
reason: 'MissingToken',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const values = {
|
|
||||||
name,
|
|
||||||
url,
|
|
||||||
token,
|
|
||||||
};
|
|
||||||
const secretValue = decodeSecret(this.#secret.data);
|
|
||||||
if (!deepEqual(secretValue, values)) {
|
|
||||||
await this.#secret.patch({
|
|
||||||
data: encodeSecret(values),
|
|
||||||
});
|
|
||||||
return await this.conditions.set('Ready', {
|
|
||||||
status: 'False',
|
|
||||||
reason: 'UpdatingSecret',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.conditions.set('Ready', {
|
|
||||||
status: 'True',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export { AuthentikConnectionResource };
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import { valueReferenceInfoSchema } from '../../services/value-reference/value-reference.instance.ts';
|
|
||||||
|
|
||||||
const authentikConnectionSpecSchema = z.object({
|
|
||||||
name: valueReferenceInfoSchema,
|
|
||||||
url: valueReferenceInfoSchema,
|
|
||||||
token: valueReferenceInfoSchema,
|
|
||||||
});
|
|
||||||
|
|
||||||
export { authentikConnectionSpecSchema };
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import { createCustomResourceDefinition } from '../../services/custom-resources/custom-resources.ts';
|
|
||||||
import { GROUP } from '../../utils/consts.ts';
|
|
||||||
|
|
||||||
import { AuthentikConnectionResource } from './authentik-connection.resource.ts';
|
|
||||||
import { authentikConnectionSpecSchema } from './authentik-connection.schemas.ts';
|
|
||||||
|
|
||||||
const authentikConnectionDefinition = createCustomResourceDefinition({
|
|
||||||
group: GROUP,
|
|
||||||
version: 'v1',
|
|
||||||
kind: 'AuthentikConnection',
|
|
||||||
names: {
|
|
||||||
plural: 'authentikconnections',
|
|
||||||
singular: 'authentikconnection',
|
|
||||||
},
|
|
||||||
spec: authentikConnectionSpecSchema,
|
|
||||||
create: (options) => new AuthentikConnectionResource(options),
|
|
||||||
});
|
|
||||||
|
|
||||||
export { authentikConnectionDefinition };
|
|
||||||
@@ -1,13 +1,7 @@
|
|||||||
import { authentikClientDefinition } from './authentik-client/authentik-client.ts';
|
import { authentikClientDefinition } from './authentik-client/authentik-client.ts';
|
||||||
import { authentikConnectionDefinition } from './authentik-connection/authentik-connection.ts';
|
|
||||||
import { generateSecretDefinition } from './generate-secret/generate-secret.ts';
|
import { generateSecretDefinition } from './generate-secret/generate-secret.ts';
|
||||||
import { postgresDatabaseDefinition } from './postgres-database/postgres-database.ts';
|
import { postgresDatabaseDefinition } from './postgres-database/postgres-database.ts';
|
||||||
|
|
||||||
const customResources = [
|
const customResources = [postgresDatabaseDefinition, authentikClientDefinition, generateSecretDefinition];
|
||||||
postgresDatabaseDefinition,
|
|
||||||
authentikClientDefinition,
|
|
||||||
generateSecretDefinition,
|
|
||||||
authentikConnectionDefinition,
|
|
||||||
];
|
|
||||||
|
|
||||||
export { customResources };
|
export { customResources };
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ class GenerateSecretResource extends CustomResource<typeof generateSecretSpecSch
|
|||||||
const current = decodeSecret(this.#secretResource.data) || {};
|
const current = decodeSecret(this.#secretResource.data) || {};
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
...secrets,
|
|
||||||
...current,
|
...current,
|
||||||
|
...secrets,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isDeepSubset(current, expected)) {
|
if (!isDeepSubset(current, expected)) {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ const postgresDatabaseSecretSchema = z.object({
|
|||||||
port: z.string(),
|
port: z.string(),
|
||||||
user: z.string(),
|
user: z.string(),
|
||||||
password: z.string(),
|
password: z.string(),
|
||||||
database: z.string().optional(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const postgresDatabaseConnectionSecretSchema = z.object({
|
const postgresDatabaseConnectionSecretSchema = z.object({
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ class PostgresDatabaseResource extends CustomResource<typeof postgresDatabaseSpe
|
|||||||
port: serverSecretData.data.port,
|
port: serverSecretData.data.port,
|
||||||
user: this.#userName,
|
user: this.#userName,
|
||||||
database: this.#dbName,
|
database: this.#dbName,
|
||||||
...databaseSecretData.data,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isDeepSubset(databaseSecretData.data, expectedSecret)) {
|
if (!isDeepSubset(databaseSecretData.data, expectedSecret)) {
|
||||||
@@ -133,7 +132,7 @@ class PostgresDatabaseResource extends CustomResource<typeof postgresDatabaseSpe
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const secretData = postgresDatabaseConnectionSecretSchema.safeParse(decodeSecret(this.#databaseSecret.data));
|
const secretData = postgresDatabaseConnectionSecretSchema.safeParse(decodeSecret(this.#serverSecret.current?.data));
|
||||||
if (!secretData.success || !secretData.data) {
|
if (!secretData.success || !secretData.data) {
|
||||||
return {
|
return {
|
||||||
ready: false,
|
ready: false,
|
||||||
@@ -146,7 +145,6 @@ class PostgresDatabaseResource extends CustomResource<typeof postgresDatabaseSpe
|
|||||||
const database = postgresService.get({
|
const database = postgresService.get({
|
||||||
...connectionSecretData.data,
|
...connectionSecretData.data,
|
||||||
port: connectionSecretData.data.port ? Number(connectionSecretData.data.port) : 5432,
|
port: connectionSecretData.data.port ? Number(connectionSecretData.data.port) : 5432,
|
||||||
database: connectionSecretData.data.database,
|
|
||||||
});
|
});
|
||||||
await database.upsertRole({
|
await database.upsertRole({
|
||||||
name: secretData.data.user,
|
name: secretData.data.user,
|
||||||
@@ -168,8 +166,8 @@ class PostgresDatabaseResource extends CustomResource<typeof postgresDatabaseSpe
|
|||||||
}
|
}
|
||||||
this.#updateSecret();
|
this.#updateSecret();
|
||||||
await Promise.allSettled([
|
await Promise.allSettled([
|
||||||
this.reconcileSubresource(DATABASE_READY_CONDITION, this.#reconcileDatabase),
|
await this.reconcileSubresource(DATABASE_READY_CONDITION, this.#reconcileDatabase),
|
||||||
this.reconcileSubresource(SECRET_READY_CONDITION, this.#reconcileSecret),
|
await this.reconcileSubresource(SECRET_READY_CONDITION, this.#reconcileSecret),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const secretReady = this.conditions.get(SECRET_READY_CONDITION)?.status === 'True';
|
const secretReady = this.conditions.get(SECRET_READY_CONDITION)?.status === 'True';
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ type PostgresInstanceOptions = {
|
|||||||
port?: number;
|
port?: number;
|
||||||
user: string;
|
user: string;
|
||||||
password: string;
|
password: string;
|
||||||
database?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PostgresInstance {
|
class PostgresInstance {
|
||||||
@@ -24,7 +23,6 @@ class PostgresInstance {
|
|||||||
user: process.env.FORCE_PG_USER ?? options.user,
|
user: process.env.FORCE_PG_USER ?? options.user,
|
||||||
password: process.env.FORCE_PG_PASSWORD ?? options.password,
|
password: process.env.FORCE_PG_PASSWORD ?? options.password,
|
||||||
port: process.env.FORCE_PG_PORT ? parseInt(process.env.FORCE_PG_PORT) : options.port,
|
port: process.env.FORCE_PG_PORT ? parseInt(process.env.FORCE_PG_PORT) : options.port,
|
||||||
database: options.database,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
import { z } from 'zod';
|
|
||||||
import { V1Secret } from '@kubernetes/client-node';
|
|
||||||
import { EventEmitter } from 'eventemitter3';
|
|
||||||
import deepEqual from 'deep-equal';
|
|
||||||
|
|
||||||
import { ResourceReference, ResourceService } from '../resources/resources.ts';
|
|
||||||
import type { Services } from '../../utils/service.ts';
|
|
||||||
import { getWithNamespace } from '../../utils/naming.ts';
|
|
||||||
import { decodeSecret } from '../../utils/secrets.ts';
|
|
||||||
|
|
||||||
const valueReferenceInfoSchema = z.object({
|
|
||||||
value: z.string().optional(),
|
|
||||||
secretRef: z.string().optional(),
|
|
||||||
key: z.string().optional(),
|
|
||||||
});
|
|
||||||
|
|
||||||
type ValueReferenceInfo = z.infer<typeof valueReferenceInfoSchema>;
|
|
||||||
|
|
||||||
type ValueRefOptions = {
|
|
||||||
services: Services;
|
|
||||||
namespace: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ValueReferenceEvents = {
|
|
||||||
changed: () => void;
|
|
||||||
};
|
|
||||||
class ValueReference extends EventEmitter<ValueReferenceEvents> {
|
|
||||||
#options: ValueRefOptions;
|
|
||||||
#ref?: ValueReferenceInfo;
|
|
||||||
#resource: ResourceReference;
|
|
||||||
|
|
||||||
constructor(options: ValueRefOptions) {
|
|
||||||
super();
|
|
||||||
this.#options = options;
|
|
||||||
this.#resource = new ResourceReference<V1Secret>();
|
|
||||||
this.#resource.on('changed', this.#handleChange);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get ref() {
|
|
||||||
return this.#ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
public set ref(ref: ValueReferenceInfo | undefined) {
|
|
||||||
if (deepEqual(this.#ref, ref)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ref?.secretRef && ref.key) {
|
|
||||||
const { services, namespace } = this.#options;
|
|
||||||
const resourceService = services.get(ResourceService);
|
|
||||||
const refNames = getWithNamespace(ref.secretRef, namespace);
|
|
||||||
this.#resource.current = resourceService.get({
|
|
||||||
apiVersion: 'v1',
|
|
||||||
kind: 'Secret',
|
|
||||||
name: refNames.name,
|
|
||||||
namespace: refNames.namespace,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.#resource.current = undefined;
|
|
||||||
}
|
|
||||||
this.#ref = ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get value() {
|
|
||||||
console.log('get', this.#ref);
|
|
||||||
if (!this.#ref) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (this.#ref.value) {
|
|
||||||
return this.#ref.value;
|
|
||||||
}
|
|
||||||
if (this.#resource.current && this.#ref.key) {
|
|
||||||
const decoded = decodeSecret(this.#resource.current.data);
|
|
||||||
return decoded?.[this.#ref.key];
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
#handleChange = () => {
|
|
||||||
this.emit('changed');
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export { ValueReference, valueReferenceInfoSchema, type ValueReferenceInfo };
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import type { Services } from '../../utils/service.ts';
|
|
||||||
|
|
||||||
import { ValueReference } from './value-reference.instance.ts';
|
|
||||||
|
|
||||||
class ValueReferenceService {
|
|
||||||
#services: Services;
|
|
||||||
|
|
||||||
constructor(services: Services) {
|
|
||||||
this.#services = services;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get = (namespace: string) => {
|
|
||||||
return new ValueReference({
|
|
||||||
namespace,
|
|
||||||
services: this.#services,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export * from './value-reference.instance.ts';
|
|
||||||
export { ValueReferenceService };
|
|
||||||
@@ -7,6 +7,7 @@ import type { Services } from '../utils/service.ts';
|
|||||||
import { ResourceService, type Resource } from '../services/resources/resources.ts';
|
import { ResourceService, type Resource } from '../services/resources/resources.ts';
|
||||||
|
|
||||||
const PROVISIONER = 'reuse-local-path-provisioner';
|
const PROVISIONER = 'reuse-local-path-provisioner';
|
||||||
|
const LABEL_SELECTOR = `provisioner=${PROVISIONER}`;
|
||||||
|
|
||||||
class StorageProvider {
|
class StorageProvider {
|
||||||
#watcher: Watcher<V1PersistentVolumeClaim>;
|
#watcher: Watcher<V1PersistentVolumeClaim>;
|
||||||
@@ -16,36 +17,26 @@ class StorageProvider {
|
|||||||
this.#services = services;
|
this.#services = services;
|
||||||
const watchService = this.#services.get(WatcherService);
|
const watchService = this.#services.get(WatcherService);
|
||||||
this.#watcher = watchService.create({
|
this.#watcher = watchService.create({
|
||||||
path: '/api/v1/persistentvolumeclaims',
|
path: '/api/v1/persistantvolumeclaims',
|
||||||
transform: (manifest) => ({
|
list: (k8s) =>
|
||||||
apiVersion: 'v1',
|
k8s.api.listPersistentVolumeClaimForAllNamespaces({
|
||||||
kind: 'PersistentVolumeClaim',
|
labelSelector: LABEL_SELECTOR,
|
||||||
...manifest,
|
}),
|
||||||
}),
|
|
||||||
list: async (k8s) => {
|
|
||||||
const current = await k8s.api.listPersistentVolumeClaimForAllNamespaces();
|
|
||||||
return current;
|
|
||||||
},
|
|
||||||
verbs: ['add', 'update', 'delete'],
|
verbs: ['add', 'update', 'delete'],
|
||||||
|
selector: LABEL_SELECTOR,
|
||||||
});
|
});
|
||||||
this.#watcher.on('changed', this.#handleChange);
|
this.#watcher.on('changed', this.#handleChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
#handleChange = async (pvc: Resource<V1PersistentVolumeClaim>) => {
|
#handleChange = async (pvc: Resource<V1PersistentVolumeClaim>) => {
|
||||||
if (pvc.metadata?.annotations?.['volume.kubernetes.io/storage-provisioner'] !== PROVISIONER) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const target = `/data/volumes/${pvc.namespace}/${pvc.name}`;
|
const target = `/data/volumes/${pvc.namespace}/${pvc.name}`;
|
||||||
try {
|
await mkdir(target, { recursive: true });
|
||||||
await mkdir(target, { recursive: true });
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
const resourceService = this.#services.get(ResourceService);
|
const resourceService = this.#services.get(ResourceService);
|
||||||
const pv = resourceService.get<V1PersistentVolume>({
|
const pv = resourceService.get<V1PersistentVolume>({
|
||||||
apiVersion: 'v1',
|
apiVersion: 'v1',
|
||||||
kind: 'PersistentVolume',
|
kind: 'PersistantVolume',
|
||||||
name: `${pvc.namespace}-${pvc.name}`,
|
name: pvc.name,
|
||||||
|
namespace: pvc.namespace,
|
||||||
});
|
});
|
||||||
await pv.load();
|
await pv.load();
|
||||||
await pv.patch({
|
await pv.patch({
|
||||||
@@ -59,7 +50,7 @@ class StorageProvider {
|
|||||||
path: target,
|
path: target,
|
||||||
},
|
},
|
||||||
capacity: {
|
capacity: {
|
||||||
storage: pvc.spec?.resources?.requests?.storage ?? '1Gi',
|
storage: pvc.spec?.resources?.requests?.storage ?? '1GB',
|
||||||
},
|
},
|
||||||
persistentVolumeReclaimPolicy: 'Retain',
|
persistentVolumeReclaimPolicy: 'Retain',
|
||||||
accessModes: pvc.spec?.accessModes,
|
accessModes: pvc.spec?.accessModes,
|
||||||
|
|||||||
Reference in New Issue
Block a user