feat: add commands for managing deployments and resources
- Implemented `down` command to delete managed resources, with an option to delete ingress and PVCs. - Added `exec` command to execute commands inside deployment pods. - Created `logs` command to show deployment logs with an option to follow the output. - Introduced `start` command to start deployments without rebuilding images. - Developed `stop` command to scale managed deployments to zero. refactor: enhance resource management and Kubernetes interactions - Refactored resource handling in `lib/apply.ts` to support sorting and applying resources. - Improved logging functionality with a new logger in `lib/logger.ts`. - Enhanced build process in `lib/build.ts` to support remote builds and syncing with Git repositories. - Added functions to manage deployments and pods in `lib/shared.ts`. chore: update dependencies and TypeScript configuration - Updated package.json to include `listr2` for task management. - Modified tsconfig.json to exclude build artifacts and fixtures.
This commit is contained in:
+119
@@ -0,0 +1,119 @@
|
||||
import { PatchStrategy } from "@kubernetes/client-node";
|
||||
import type { KubernetesObject } from "@kubernetes/client-node";
|
||||
import { LABELS } from "../const";
|
||||
import { objectApi } from "./k8s";
|
||||
|
||||
const FIELD_MANAGER = "kuber";
|
||||
|
||||
const ResourceOrder = {
|
||||
Namespace: 0,
|
||||
PersistentVolumeClaim: 1,
|
||||
Secret: 2,
|
||||
Service: 3,
|
||||
Deployment: 4,
|
||||
Ingress: 5,
|
||||
} as const;
|
||||
|
||||
const ManagedResources = [
|
||||
{ apiVersion: "v1", kind: "PersistentVolumeClaim" },
|
||||
{ apiVersion: "v1", kind: "Secret" },
|
||||
{ apiVersion: "v1", kind: "Service" },
|
||||
{ apiVersion: "apps/v1", kind: "Deployment" },
|
||||
{ apiVersion: "networking.k8s.io/v1", kind: "Ingress" },
|
||||
] as const;
|
||||
|
||||
const ManagedBySelector = `app.kubernetes.io/managed-by=${LABELS["app.kubernetes.io/managed-by"]}`;
|
||||
|
||||
function getResourceOrder(resource: KubernetesObject): number {
|
||||
return ResourceOrder[resource.kind as keyof typeof ResourceOrder] ?? 999;
|
||||
}
|
||||
|
||||
export function sortResources<T extends KubernetesObject>(resources: T[]): T[] {
|
||||
return [...resources].sort(
|
||||
(left, right) => getResourceOrder(left) - getResourceOrder(right),
|
||||
);
|
||||
}
|
||||
|
||||
export function getResourceKey(resource: KubernetesObject): string {
|
||||
return `${resource.kind}:${resource.metadata?.namespace ?? ""}:${resource.metadata?.name ?? ""}`;
|
||||
}
|
||||
|
||||
export async function applyResource<T extends KubernetesObject>(
|
||||
resource: T,
|
||||
): Promise<T> {
|
||||
return objectApi.patch(
|
||||
resource,
|
||||
undefined,
|
||||
undefined,
|
||||
FIELD_MANAGER,
|
||||
true,
|
||||
PatchStrategy.ServerSideApply,
|
||||
);
|
||||
}
|
||||
|
||||
export async function applyResources<T extends KubernetesObject>(
|
||||
resources: T[],
|
||||
): Promise<T[]> {
|
||||
const applied: T[] = [];
|
||||
|
||||
for (const resource of sortResources(resources)) {
|
||||
applied.push(await applyResource(resource));
|
||||
}
|
||||
|
||||
return applied;
|
||||
}
|
||||
|
||||
export async function deleteResource(resource: KubernetesObject): Promise<void> {
|
||||
await objectApi.delete(resource);
|
||||
}
|
||||
|
||||
export async function deleteResources(resources: KubernetesObject[]): Promise<void> {
|
||||
for (const resource of sortResources(resources).reverse()) {
|
||||
await deleteResource(resource);
|
||||
}
|
||||
}
|
||||
|
||||
export async function listManagedResources(
|
||||
namespace: string,
|
||||
): Promise<KubernetesObject[]> {
|
||||
const resources = await Promise.all(
|
||||
ManagedResources.map(async ({ apiVersion, kind }) => {
|
||||
const list = await objectApi.list(
|
||||
apiVersion,
|
||||
kind,
|
||||
namespace,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
ManagedBySelector,
|
||||
);
|
||||
|
||||
return list.items.map((item) => ({
|
||||
...item,
|
||||
apiVersion: item.apiVersion ?? apiVersion,
|
||||
kind: item.kind ?? kind,
|
||||
metadata: {
|
||||
...item.metadata,
|
||||
namespace: item.metadata?.namespace ?? namespace,
|
||||
},
|
||||
}));
|
||||
}),
|
||||
);
|
||||
|
||||
return resources.flat();
|
||||
}
|
||||
|
||||
export async function getStaleResources(
|
||||
namespace: string,
|
||||
desiredResources: KubernetesObject[],
|
||||
): Promise<KubernetesObject[]> {
|
||||
const desired = new Set(
|
||||
desiredResources
|
||||
.filter((resource) => resource.kind !== "Namespace")
|
||||
.map(getResourceKey),
|
||||
);
|
||||
|
||||
const existing = await listManagedResources(namespace);
|
||||
return existing.filter((resource) => !desired.has(getResourceKey(resource)));
|
||||
}
|
||||
Reference in New Issue
Block a user