This commit is contained in:
Morten Olsen
2025-07-28 22:27:40 +02:00
parent b35782a7d8
commit 48f1bde404
25 changed files with 3341 additions and 235 deletions

View File

@@ -1,9 +1,11 @@
import type { Static, TSchema } from "@sinclair/typebox";
import type { Services } from "../utils/service.ts";
import { K8sService } from "../services/k8s.ts";
import { CustomResourceRegistry } from "./custom-resource.registry.ts";
import { CustomResourceStatus, type CustomResourceStatusType } from "./custom-resource.status.ts";
import { ApiException, PatchStrategy, setHeaderOptions } from "@kubernetes/client-node";
import type { Static, TSchema } from '@sinclair/typebox';
import { ApiException, PatchStrategy, setHeaderOptions } from '@kubernetes/client-node';
import type { Services } from '../utils/service.ts';
import { K8sService } from '../services/k8s.ts';
import { CustomResourceRegistry } from './custom-resource.registry.ts';
import { CustomResourceStatus, type CustomResourceStatusType } from './custom-resource.status.ts';
type CustomResourceRequestOptions = {
type: 'ADDED' | 'DELETED' | 'MODIFIED';
@@ -22,7 +24,7 @@ type CustomResourceRequestMetadata = Record<string, string> & {
generation: number;
};
class CustomResourceRequest<TSpec extends TSchema>{
class CustomResourceRequest<TSpec extends TSchema> {
#options: CustomResourceRequestOptions;
constructor(options: CustomResourceRequestOptions) {
@@ -59,18 +61,19 @@ class CustomResourceRequest<TSpec extends TSchema>{
public isOwnerOf = (manifest: any) => {
const ownerRef = manifest?.metadata?.ownerReferences || [];
return ownerRef.some((ref: any) =>
ref.apiVersion === this.apiVersion &&
ref.kind === this.kind &&
ref.name === this.metadata.name &&
ref.uid === this.metadata.uid
return ownerRef.some(
(ref: any) =>
ref.apiVersion === this.apiVersion &&
ref.kind === this.kind &&
ref.name === this.metadata.name &&
ref.uid === this.metadata.uid,
);
}
};
public setStatus = async (status: CustomResourceStatusType) => {
const { manifest, services } = this.#options;
const { kind, metadata } = manifest;
const registry = services.get(CustomResourceRegistry);
const registry = services.get(CustomResourceRegistry);
const crd = registry.getByKind(kind);
if (!crd) {
throw new Error(`Custom resource ${kind} not found`);
@@ -80,17 +83,20 @@ class CustomResourceRequest<TSpec extends TSchema>{
const { namespace = 'default', name } = metadata;
const response = await k8sService.customObjectsApi.patchNamespacedCustomObjectStatus({
group: crd.group,
version: crd.version,
namespace,
plural: crd.names.plural,
name,
body: { status },
fieldValidation: 'Strict',
}, setHeaderOptions('Content-Type', PatchStrategy.MergePatch))
const response = await k8sService.customObjectsApi.patchNamespacedCustomObjectStatus(
{
group: crd.group,
version: crd.version,
namespace,
plural: crd.names.plural,
name,
body: { status },
fieldValidation: 'Strict',
},
setHeaderOptions('Content-Type', PatchStrategy.MergePatch),
);
return response;
}
};
public getCurrent = async () => {
const { manifest, services } = this.#options;
@@ -101,19 +107,19 @@ class CustomResourceRequest<TSpec extends TSchema>{
throw new Error(`Custom resource ${manifest.kind} not found`);
}
try {
const resource = await k8sService.customObjectsApi.getNamespacedCustomObject({
group: crd.group,
version: crd.version,
plural: crd.names.plural,
namespace: manifest.metadata.namespace,
name: manifest.metadata.name,
});
return resource as {
apiVersion: string;
kind: string;
metadata: CustomResourceRequestMetadata;
spec: Static<TSpec>;
status: CustomResourceStatusType;
const resource = await k8sService.customObjectsApi.getNamespacedCustomObject({
group: crd.group,
version: crd.version,
plural: crd.names.plural,
namespace: manifest.metadata.namespace,
name: manifest.metadata.name,
});
return resource as {
apiVersion: string;
kind: string;
metadata: CustomResourceRequestMetadata;
spec: Static<TSpec>;
status: CustomResourceStatusType;
};
} catch (error) {
if (error instanceof ApiException && error.code === 404) {
@@ -121,10 +127,10 @@ class CustomResourceRequest<TSpec extends TSchema>{
}
throw error;
}
}
};
public getStatus = async () => {
const resource = await this.getCurrent()
const resource = await this.getCurrent();
if (!resource || !resource.status) {
return new CustomResourceStatus({
status: {
@@ -140,8 +146,7 @@ class CustomResourceRequest<TSpec extends TSchema>{
generation: resource.metadata.generation,
save: this.setStatus,
});
}
};
}
export { CustomResourceRequest };
export { CustomResourceRequest };