Remove deployment
This commit is contained in:
@@ -1,7 +1,11 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import testAuth from "../../../lib/server/auth";
|
import testAuth from "../../../lib/server/auth";
|
||||||
import { StatusCodes } from "http-status-codes";
|
import { StatusCodes } from "http-status-codes";
|
||||||
import { deployApp, toggleDeployment } from "@/core/deployment";
|
import {
|
||||||
|
deployApp,
|
||||||
|
removeDeployment,
|
||||||
|
toggleDeployment,
|
||||||
|
} from "@/core/deployment";
|
||||||
import { Application, Port } from "@/lib/types";
|
import { Application, Port } from "@/lib/types";
|
||||||
|
|
||||||
export async function POST(req: NextRequest): Promise<NextResponse> {
|
export async function POST(req: NextRequest): Promise<NextResponse> {
|
||||||
@@ -59,3 +63,28 @@ export async function PUT(req: NextRequest): Promise<NextResponse> {
|
|||||||
message: "ok",
|
message: "ok",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function DELETE(req: NextRequest): Promise<NextResponse> {
|
||||||
|
const deployId = req.nextUrl.searchParams.get("deployId");
|
||||||
|
const auth = await testAuth(req);
|
||||||
|
|
||||||
|
if (auth) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ message: auth },
|
||||||
|
{ status: StatusCodes.UNAUTHORIZED },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deployId) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ message: "Body missing deployId" },
|
||||||
|
{ status: StatusCodes.BAD_REQUEST },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await removeDeployment(deployId);
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
message: "ok",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,11 @@ import {
|
|||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Plus, Play, Pause, Square, RotateCcw } from "lucide-react";
|
import { Plus, Play, Pause, Square, RotateCcw } from "lucide-react";
|
||||||
import { getDeployments, toggleDeployment } from "@/lib/dockship/deploy";
|
import {
|
||||||
|
getDeployments,
|
||||||
|
removeDeployment,
|
||||||
|
toggleDeployment,
|
||||||
|
} from "@/lib/dockship/deploy";
|
||||||
import { getApps } from "@/lib/dockship/application";
|
import { getApps } from "@/lib/dockship/application";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import DeployAppDialog from "@/components/dialogs/DeployApp";
|
import DeployAppDialog from "@/components/dialogs/DeployApp";
|
||||||
@@ -53,6 +57,11 @@ export default function DeploymentsPage() {
|
|||||||
await toggleDeployment(deployId, action);
|
await toggleDeployment(deployId, action);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const remove = async (deployId: string) => {
|
||||||
|
console.log(`Removing deployment ${deployId}`);
|
||||||
|
await removeDeployment(deployId);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardLayout
|
<DashboardLayout
|
||||||
title="Deployments"
|
title="Deployments"
|
||||||
@@ -138,7 +147,7 @@ export default function DeploymentsPage() {
|
|||||||
<RotateCcw className="w-3 h-3" />
|
<RotateCcw className="w-3 h-3" />
|
||||||
</Button>
|
</Button>
|
||||||
</DeployAppDialog>
|
</DeployAppDialog>
|
||||||
<RemoveDialog remove={() => {}} />
|
<RemoveDialog remove={() => remove(dep.container)} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import pLimit from "p-limit";
|
|||||||
import { randomUUID } from "crypto";
|
import { randomUUID } from "crypto";
|
||||||
import { cloneRepo } from "./git";
|
import { cloneRepo } from "./git";
|
||||||
import tar from "tar-fs";
|
import tar from "tar-fs";
|
||||||
|
import { read, write } from "@/lib/server/file";
|
||||||
|
|
||||||
const docker = new Docker();
|
const docker = new Docker();
|
||||||
|
|
||||||
@@ -180,3 +181,21 @@ export async function toggleDeployment(
|
|||||||
console.error(`Failed to ${action} container ${containerId}:`, err);
|
console.error(`Failed to ${action} container ${containerId}:`, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function removeDeployment(deployId: string) {
|
||||||
|
const apps = await read(() => [] as Application[], "data", "apps.json");
|
||||||
|
const app = apps.find((a) => a.deployments.includes(deployId));
|
||||||
|
if (app) {
|
||||||
|
app.deployments = app.deployments.filter((id) => id !== deployId);
|
||||||
|
await write(apps, "data", "apps.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const container = docker.getContainer(deployId);
|
||||||
|
await container.stop();
|
||||||
|
await container.remove({ force: true });
|
||||||
|
await docker.pruneImages();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Failed to remove container ${deployId}:`, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -82,3 +82,21 @@ export async function toggleDeployment(
|
|||||||
|
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function removeDeployment(deployId: string) {
|
||||||
|
const nodes = await getNodes();
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
nodes.map(
|
||||||
|
async (node) =>
|
||||||
|
await axios.delete(
|
||||||
|
`http://${node.ip}:${process.env.PORT}/api/deploy?deployId=${deployId}`,
|
||||||
|
{
|
||||||
|
headers: { Authorization: `ApiKey ${node.key}` },
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user