"use client";
import { Suspense, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { IconCloud, IconServer } from "@tabler/icons-react";
import { Button } from "@kandev/ui/button";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@kandev/ui/card";
import { Input } from "@kandev/ui/input";
import { Label } from "@kandev/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@kandev/ui/select";
import { Separator } from "@kandev/ui/separator";
import { createExecutorAction } from "@/app/actions/executors";
import { getWebSocketClient } from "@/lib/ws/connection";
import { useAppStore } from "@/components/state-provider";
import type { Executor } from "@/lib/types/http";
const EXECUTOR_TYPES = ["local_docker", "remote_docker"] as const;
type ExecutorType = (typeof EXECUTOR_TYPES)[number];
export default function ExecutorCreatePage() {
return (
Loading...}>
);
}
type RemoteDockerFieldsProps = {
dockerTlsVerify: string;
onDockerTlsVerifyChange: (value: string) => void;
dockerCertPath: string;
onDockerCertPathChange: (value: string) => void;
gitToken: string;
onGitTokenChange: (value: string) => void;
};
function RemoteDockerFields({
dockerTlsVerify,
onDockerTlsVerifyChange,
dockerCertPath,
onDockerCertPathChange,
gitToken,
onGitTokenChange,
}: RemoteDockerFieldsProps) {
return (
<>
>
);
}
type ExecutorFormCardProps = {
type: ExecutorType;
name: string;
dockerHost: string;
dockerTlsVerify: string;
dockerCertPath: string;
gitToken: string;
onTypeChange: (value: ExecutorType) => void;
onNameChange: (value: string) => void;
onDockerHostChange: (value: string) => void;
onDockerTlsVerifyChange: (value: string) => void;
onDockerCertPathChange: (value: string) => void;
onGitTokenChange: (value: string) => void;
};
function ExecutorFormCard({
type,
name,
dockerHost,
dockerTlsVerify,
dockerCertPath,
gitToken,
onTypeChange,
onNameChange,
onDockerHostChange,
onDockerTlsVerifyChange,
onDockerCertPathChange,
onGitTokenChange,
}: ExecutorFormCardProps) {
const isRemoteDocker = type === "remote_docker";
return (
{isRemoteDocker ? : }
{isRemoteDocker ? "Remote Docker Executor" : "Local Docker Executor"}
{isRemoteDocker
? "Connects to a remote Docker host. The repository will be cloned inside the container."
: "Uses the local Docker daemon on this machine."}
onNameChange(event.target.value)}
/>
{isRemoteDocker && (
)}
);
}
function buildExecutorConfig(
type: ExecutorType,
dockerHost: string,
dockerTlsVerify: string,
dockerCertPath: string,
gitToken: string,
): Record {
const config: Record = { docker_host: dockerHost };
if (type === "remote_docker") {
if (dockerTlsVerify) config.docker_tls_verify = dockerTlsVerify;
if (dockerCertPath) config.docker_cert_path = dockerCertPath;
if (gitToken) config.git_token = gitToken;
}
return config;
}
function ExecutorCreatePageContent() {
const router = useRouter();
const searchParams = useSearchParams();
const initialType = searchParams.get("type");
const [type, setType] = useState(() => {
if (EXECUTOR_TYPES.includes(initialType as ExecutorType)) return initialType as ExecutorType;
return "local_docker";
});
const [name, setName] = useState(() =>
initialType === "remote_docker" ? "Remote Docker" : "Local Docker",
);
const [dockerHost, setDockerHost] = useState(() =>
initialType === "remote_docker" ? "tcp://" : "unix:///var/run/docker.sock",
);
const [dockerTlsVerify, setDockerTlsVerify] = useState("");
const [dockerCertPath, setDockerCertPath] = useState("");
const [gitToken, setGitToken] = useState("");
const [isCreating, setIsCreating] = useState(false);
const executors = useAppStore((state) => state.executors.items);
const setExecutors = useAppStore((state) => state.setExecutors);
const handleTypeChange = (value: ExecutorType) => {
setType(value);
if (value === "local_docker") {
setName("Local Docker");
setDockerHost("unix:///var/run/docker.sock");
} else if (value === "remote_docker") {
setName("Remote Docker");
setDockerHost("tcp://");
}
};
const handleCreate = async () => {
setIsCreating(true);
try {
const config = buildExecutorConfig(
type,
dockerHost,
dockerTlsVerify,
dockerCertPath,
gitToken,
);
const payload = { name, type, status: "active", config };
const client = getWebSocketClient();
const created = client
? await client.request("executor.create", payload)
: await createExecutorAction(payload);
setExecutors([...executors.filter((item: Executor) => item.id !== created.id), created]);
router.push("/settings/executors");
} finally {
setIsCreating(false);
}
};
return (
Create Executor
Choose an executor type to run environments on your infrastructure.
);
}