diff --git a/src/app/api/deploy/route.ts b/src/app/api/deploy/route.ts index 8639ff5..676d11f 100644 --- a/src/app/api/deploy/route.ts +++ b/src/app/api/deploy/route.ts @@ -1,7 +1,7 @@ import { NextRequest, NextResponse } from "next/server"; import testAuth from "../auth"; import { StatusCodes } from "http-status-codes"; -import { deployApp } from "@/core/deployment"; +import { deployApp, toggleDeployment } from "@/core/deployment"; import { Application, Port } from "@/lib/types"; export async function POST(req: NextRequest): Promise { @@ -15,14 +15,14 @@ export async function POST(req: NextRequest): Promise { if (auth) { return NextResponse.json( { message: auth }, - { status: StatusCodes.UNAUTHORIZED } + { status: StatusCodes.UNAUTHORIZED }, ); } if (!name || !app) { return NextResponse.json( { message: "Body missing name, appId, nodeId" }, - { status: StatusCodes.BAD_REQUEST } + { status: StatusCodes.BAD_REQUEST }, ); } @@ -33,3 +33,29 @@ export async function POST(req: NextRequest): Promise { deployId, }); } + +export async function PUT(req: NextRequest): Promise { + const auth = await testAuth(req); + const { deployId, action }: { deployId: string; action: "start" | "stop" } = + await req.json(); + + if (auth) { + return NextResponse.json( + { message: auth }, + { status: StatusCodes.UNAUTHORIZED }, + ); + } + + if (!deployId || !action) { + return NextResponse.json( + { message: "Body missing deployId or action" }, + { status: StatusCodes.BAD_REQUEST }, + ); + } + + await toggleDeployment(deployId, action); + + return NextResponse.json({ + message: "ok", + }); +} diff --git a/src/app/deployments/page.tsx b/src/app/deployments/page.tsx index 3142284..3fa6ede 100644 --- a/src/app/deployments/page.tsx +++ b/src/app/deployments/page.tsx @@ -10,8 +10,8 @@ import { } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; -import { Plus, Play, Pause } from "lucide-react"; -import { getDeployments } from "@/lib/dockship/deploy"; +import { Plus, Play, Pause, Square } from "lucide-react"; +import { getDeployments, toggleDeployment } from "@/lib/dockship/deploy"; import { getApps } from "@/lib/dockship/application"; import { cn } from "@/lib/utils"; import DeployAppDialog from "@/components/dialogs/DeployApp"; @@ -39,6 +39,14 @@ export default function DeploymentsPage() { return map; }, [apps]); + const changeDeploymentStatus = async ( + deployId: string, + action: "start" | "stop", + ) => { + console.log(`Toggling deployment ${deployId} with action ${action}`); + await toggleDeployment(deployId, action); + }; + return (
- {}} /> diff --git a/src/core/deployment.ts b/src/core/deployment.ts index 3677ab4..1f73d8a 100644 --- a/src/core/deployment.ts +++ b/src/core/deployment.ts @@ -164,3 +164,20 @@ export async function deployApp( fs.rmSync(deployPath, { recursive: true, force: true }); } } + +export async function toggleDeployment( + containerId: string, + action: "start" | "stop", +) { + const container = docker.getContainer(containerId); + + try { + if (action === "start") { + await container.start(); + } else { + await container.stop(); + } + } catch (err) { + console.error(`Failed to ${action} container ${containerId}:`, err); + } +} diff --git a/src/lib/dockship/deploy.ts b/src/lib/dockship/deploy.ts index 0a39828..0c2fb87 100644 --- a/src/lib/dockship/deploy.ts +++ b/src/lib/dockship/deploy.ts @@ -17,8 +17,8 @@ export async function getDeployments(): Promise { await axios.post(`http://${n.ip}:3000/api/get-deployments`, apps, { headers: { Authorization: `ApiKey ${n.key}` }, }) - ).data.deployments - ) + ).data.deployments, + ), ) ).flat(); } @@ -27,7 +27,7 @@ export async function deployApp( name: string, appId: string, nodeId: string, - ports: Port[] + ports: Port[], ): Promise { const nodes = await getNodes(); @@ -44,7 +44,7 @@ export async function deployApp( { name, app, ports }, { headers: { Authorization: `ApiKey ${node.key}` }, - } + }, ) ).data.deployId; @@ -54,3 +54,25 @@ export async function deployApp( return deployId; } + +export async function toggleDeployment( + deployId: string, + action: "start" | "stop", +) { + const nodes = await getNodes(); + + await Promise.all( + nodes.map( + async (node) => + await axios.put( + `http://${node.ip}:3000/api/deploy`, + { deployId, action }, + { + headers: { Authorization: `ApiKey ${node.key}` }, + }, + ), + ), + ); + + return "ok"; +}