mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Merge pull request #1440 from Dokploy/1120-rebuild-database
feat(databases): add database rebuild functionality
This commit is contained in:
116
apps/dokploy/components/dashboard/shared/rebuild-database.tsx
Normal file
116
apps/dokploy/components/dashboard/shared/rebuild-database.tsx
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
import {
|
||||||
|
AlertDialog,
|
||||||
|
AlertDialogAction,
|
||||||
|
AlertDialogCancel,
|
||||||
|
AlertDialogContent,
|
||||||
|
AlertDialogDescription,
|
||||||
|
AlertDialogFooter,
|
||||||
|
AlertDialogHeader,
|
||||||
|
AlertDialogTitle,
|
||||||
|
AlertDialogTrigger,
|
||||||
|
} from "@/components/ui/alert-dialog";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { api } from "@/utils/api";
|
||||||
|
import { DatabaseIcon, AlertTriangle } from "lucide-react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
id: string;
|
||||||
|
type: "postgres" | "mysql" | "mariadb" | "mongo" | "redis";
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RebuildDatabase = ({ id, type }: Props) => {
|
||||||
|
const utils = api.useUtils();
|
||||||
|
|
||||||
|
const mutationMap = {
|
||||||
|
postgres: () => api.postgres.rebuild.useMutation(),
|
||||||
|
mysql: () => api.mysql.rebuild.useMutation(),
|
||||||
|
mariadb: () => api.mariadb.rebuild.useMutation(),
|
||||||
|
mongo: () => api.mongo.rebuild.useMutation(),
|
||||||
|
redis: () => api.redis.rebuild.useMutation(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const { mutateAsync, isLoading } = mutationMap[type]();
|
||||||
|
|
||||||
|
const handleRebuild = async () => {
|
||||||
|
try {
|
||||||
|
await mutateAsync({
|
||||||
|
postgresId: type === "postgres" ? id : "",
|
||||||
|
mysqlId: type === "mysql" ? id : "",
|
||||||
|
mariadbId: type === "mariadb" ? id : "",
|
||||||
|
mongoId: type === "mongo" ? id : "",
|
||||||
|
redisId: type === "redis" ? id : "",
|
||||||
|
});
|
||||||
|
toast.success("Database rebuilt successfully");
|
||||||
|
await utils.invalidate();
|
||||||
|
} catch (error) {
|
||||||
|
toast.error("Error rebuilding database", {
|
||||||
|
description: error instanceof Error ? error.message : "Unknown error",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="bg-background border-destructive/50">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="text-xl flex items-center gap-2">
|
||||||
|
<AlertTriangle className="h-5 w-5 text-destructive" />
|
||||||
|
Danger Zone
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<h3 className="text-base font-semibold">Rebuild Database</h3>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
This action will completely reset your database to its initial
|
||||||
|
state. All data, tables, and configurations will be removed.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<AlertDialog>
|
||||||
|
<AlertDialogTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="w-full border-destructive/50 hover:bg-destructive/10 hover:text-destructive text-destructive"
|
||||||
|
>
|
||||||
|
<DatabaseIcon className="mr-2 h-4 w-4" />
|
||||||
|
Rebuild Database
|
||||||
|
</Button>
|
||||||
|
</AlertDialogTrigger>
|
||||||
|
<AlertDialogContent>
|
||||||
|
<AlertDialogHeader>
|
||||||
|
<AlertDialogTitle className="flex items-center gap-2">
|
||||||
|
<AlertTriangle className="h-5 w-5 text-destructive" />
|
||||||
|
Are you absolutely sure?
|
||||||
|
</AlertDialogTitle>
|
||||||
|
<AlertDialogDescription className="space-y-2">
|
||||||
|
<p>This action will:</p>
|
||||||
|
<ul className="list-disc list-inside space-y-1">
|
||||||
|
<li>Stop the current database service</li>
|
||||||
|
<li>Delete all existing data and volumes</li>
|
||||||
|
<li>Reset to the default configuration</li>
|
||||||
|
<li>Restart the service with a clean state</li>
|
||||||
|
</ul>
|
||||||
|
<p className="font-medium text-destructive mt-4">
|
||||||
|
This action cannot be undone.
|
||||||
|
</p>
|
||||||
|
</AlertDialogDescription>
|
||||||
|
</AlertDialogHeader>
|
||||||
|
<AlertDialogFooter>
|
||||||
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||||
|
<AlertDialogAction
|
||||||
|
onClick={handleRebuild}
|
||||||
|
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
||||||
|
disabled={isLoading}
|
||||||
|
>
|
||||||
|
{isLoading ? "Rebuilding..." : "Yes, rebuild database"}
|
||||||
|
</AlertDialogAction>
|
||||||
|
</AlertDialogFooter>
|
||||||
|
</AlertDialogContent>
|
||||||
|
</AlertDialog>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
|
||||||
|
import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
|
||||||
|
import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
|
||||||
|
import { RebuildDatabase } from "./rebuild-database";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
id: string;
|
||||||
|
type: "postgres" | "mysql" | "mariadb" | "mongo" | "redis";
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ShowDatabaseAdvancedSettings = ({ id, type }: Props) => {
|
||||||
|
return (
|
||||||
|
<div className="flex w-full flex-col gap-5">
|
||||||
|
<ShowCustomCommand id={id} type={type} />
|
||||||
|
<ShowVolumes id={id} type={type} />
|
||||||
|
<ShowResources id={id} type={type} />
|
||||||
|
<RebuildDatabase id={id} type={type} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
|
|
||||||
import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
|
|
||||||
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
|
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
|
||||||
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
|
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
|
||||||
import { DeleteService } from "@/components/dashboard/compose/delete-service";
|
import { DeleteService } from "@/components/dashboard/compose/delete-service";
|
||||||
@@ -10,7 +8,7 @@ import { ShowInternalMariadbCredentials } from "@/components/dashboard/mariadb/g
|
|||||||
import { UpdateMariadb } from "@/components/dashboard/mariadb/update-mariadb";
|
import { UpdateMariadb } from "@/components/dashboard/mariadb/update-mariadb";
|
||||||
import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring";
|
import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring";
|
||||||
import { ContainerPaidMonitoring } from "@/components/dashboard/monitoring/paid/container/show-paid-container-monitoring";
|
import { ContainerPaidMonitoring } from "@/components/dashboard/monitoring/paid/container/show-paid-container-monitoring";
|
||||||
import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
|
import { ShowDatabaseAdvancedSettings } from "@/components/dashboard/shared/show-database-advanced-settings";
|
||||||
import { MariadbIcon } from "@/components/icons/data-tools-icons";
|
import { MariadbIcon } from "@/components/icons/data-tools-icons";
|
||||||
import { ProjectLayout } from "@/components/layouts/project-layout";
|
import { ProjectLayout } from "@/components/layouts/project-layout";
|
||||||
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
||||||
@@ -278,11 +276,10 @@ const Mariadb = (
|
|||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="advanced">
|
<TabsContent value="advanced">
|
||||||
<div className="flex flex-col gap-4 pt-2.5">
|
<div className="flex flex-col gap-4 pt-2.5">
|
||||||
<div className="flex w-full flex-col gap-5">
|
<ShowDatabaseAdvancedSettings
|
||||||
<ShowCustomCommand id={mariadbId} type="mariadb" />
|
id={mariadbId}
|
||||||
<ShowVolumes id={mariadbId} type="mariadb" />
|
type="mariadb"
|
||||||
<ShowResources id={mariadbId} type="mariadb" />
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
|
|
||||||
import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
|
|
||||||
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
|
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
|
||||||
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
|
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
|
||||||
import { DeleteService } from "@/components/dashboard/compose/delete-service";
|
import { DeleteService } from "@/components/dashboard/compose/delete-service";
|
||||||
@@ -10,7 +8,7 @@ import { ShowInternalMongoCredentials } from "@/components/dashboard/mongo/gener
|
|||||||
import { UpdateMongo } from "@/components/dashboard/mongo/update-mongo";
|
import { UpdateMongo } from "@/components/dashboard/mongo/update-mongo";
|
||||||
import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring";
|
import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring";
|
||||||
import { ContainerPaidMonitoring } from "@/components/dashboard/monitoring/paid/container/show-paid-container-monitoring";
|
import { ContainerPaidMonitoring } from "@/components/dashboard/monitoring/paid/container/show-paid-container-monitoring";
|
||||||
import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
|
import { ShowDatabaseAdvancedSettings } from "@/components/dashboard/shared/show-database-advanced-settings";
|
||||||
import { MongodbIcon } from "@/components/icons/data-tools-icons";
|
import { MongodbIcon } from "@/components/icons/data-tools-icons";
|
||||||
import { ProjectLayout } from "@/components/layouts/project-layout";
|
import { ProjectLayout } from "@/components/layouts/project-layout";
|
||||||
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
||||||
@@ -279,11 +277,7 @@ const Mongo = (
|
|||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="advanced">
|
<TabsContent value="advanced">
|
||||||
<div className="flex flex-col gap-4 pt-2.5">
|
<div className="flex flex-col gap-4 pt-2.5">
|
||||||
<div className="flex w-full flex-col gap-5 ">
|
<ShowDatabaseAdvancedSettings id={mongoId} type="mongo" />
|
||||||
<ShowCustomCommand id={mongoId} type="mongo" />
|
|
||||||
<ShowVolumes id={mongoId} type="mongo" />
|
|
||||||
<ShowResources id={mongoId} type="mongo" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
|
|
||||||
import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
|
|
||||||
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
|
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
|
||||||
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
|
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
|
||||||
import { DeleteService } from "@/components/dashboard/compose/delete-service";
|
import { DeleteService } from "@/components/dashboard/compose/delete-service";
|
||||||
@@ -10,7 +8,7 @@ import { ShowExternalMysqlCredentials } from "@/components/dashboard/mysql/gener
|
|||||||
import { ShowGeneralMysql } from "@/components/dashboard/mysql/general/show-general-mysql";
|
import { ShowGeneralMysql } from "@/components/dashboard/mysql/general/show-general-mysql";
|
||||||
import { ShowInternalMysqlCredentials } from "@/components/dashboard/mysql/general/show-internal-mysql-credentials";
|
import { ShowInternalMysqlCredentials } from "@/components/dashboard/mysql/general/show-internal-mysql-credentials";
|
||||||
import { UpdateMysql } from "@/components/dashboard/mysql/update-mysql";
|
import { UpdateMysql } from "@/components/dashboard/mysql/update-mysql";
|
||||||
import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
|
import { ShowDatabaseAdvancedSettings } from "@/components/dashboard/shared/show-database-advanced-settings";
|
||||||
import { MysqlIcon } from "@/components/icons/data-tools-icons";
|
import { MysqlIcon } from "@/components/icons/data-tools-icons";
|
||||||
import { ProjectLayout } from "@/components/layouts/project-layout";
|
import { ProjectLayout } from "@/components/layouts/project-layout";
|
||||||
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
||||||
@@ -236,33 +234,9 @@ const MySql = (
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{/* {monitoring?.enabledFeatures && (
|
|
||||||
<div className="flex flex-row border w-fit p-4 rounded-lg items-center gap-2">
|
|
||||||
<Label className="text-muted-foreground">
|
|
||||||
Change Monitoring
|
|
||||||
</Label>
|
|
||||||
<Switch
|
|
||||||
checked={toggleMonitoring}
|
|
||||||
onCheckedChange={setToggleMonitoring}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{toggleMonitoring ? (
|
|
||||||
<ContainerPaidMonitoring
|
|
||||||
appName={data?.appName || ""}
|
|
||||||
baseUrl={`http://${monitoring?.serverIp}:${monitoring?.metricsConfig?.server?.port}`}
|
|
||||||
token={
|
|
||||||
monitoring?.metricsConfig?.server?.token || ""
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div> */}
|
|
||||||
<ContainerFreeMonitoring
|
<ContainerFreeMonitoring
|
||||||
appName={data?.appName || ""}
|
appName={data?.appName || ""}
|
||||||
/>
|
/>
|
||||||
{/* </div> */}
|
|
||||||
{/* )} */}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -283,11 +257,10 @@ const MySql = (
|
|||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="advanced">
|
<TabsContent value="advanced">
|
||||||
<div className="flex flex-col gap-4 pt-2.5">
|
<div className="flex flex-col gap-4 pt-2.5">
|
||||||
<div className="flex w-full flex-col gap-5">
|
<ShowDatabaseAdvancedSettings
|
||||||
<ShowCustomCommand id={mysqlId} type="mysql" />
|
id={mysqlId}
|
||||||
<ShowVolumes id={mysqlId} type="mysql" />
|
type="mysql"
|
||||||
<ShowResources id={mysqlId} type="mysql" />
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
|
|
||||||
import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
|
|
||||||
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
|
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
|
||||||
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
|
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
|
||||||
import { DeleteService } from "@/components/dashboard/compose/delete-service";
|
import { DeleteService } from "@/components/dashboard/compose/delete-service";
|
||||||
import { ShowBackups } from "@/components/dashboard/database/backups/show-backups";
|
import { ShowBackups } from "@/components/dashboard/database/backups/show-backups";
|
||||||
import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring";
|
import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring";
|
||||||
import { ContainerPaidMonitoring } from "@/components/dashboard/monitoring/paid/container/show-paid-container-monitoring";
|
import { ContainerPaidMonitoring } from "@/components/dashboard/monitoring/paid/container/show-paid-container-monitoring";
|
||||||
import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
|
|
||||||
import { ShowExternalPostgresCredentials } from "@/components/dashboard/postgres/general/show-external-postgres-credentials";
|
import { ShowExternalPostgresCredentials } from "@/components/dashboard/postgres/general/show-external-postgres-credentials";
|
||||||
import { ShowGeneralPostgres } from "@/components/dashboard/postgres/general/show-general-postgres";
|
import { ShowGeneralPostgres } from "@/components/dashboard/postgres/general/show-general-postgres";
|
||||||
import { ShowInternalPostgresCredentials } from "@/components/dashboard/postgres/general/show-internal-postgres-credentials";
|
import { ShowInternalPostgresCredentials } from "@/components/dashboard/postgres/general/show-internal-postgres-credentials";
|
||||||
@@ -15,6 +12,7 @@ import { PostgresqlIcon } from "@/components/icons/data-tools-icons";
|
|||||||
import { ProjectLayout } from "@/components/layouts/project-layout";
|
import { ProjectLayout } from "@/components/layouts/project-layout";
|
||||||
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
||||||
import { StatusTooltip } from "@/components/shared/status-tooltip";
|
import { StatusTooltip } from "@/components/shared/status-tooltip";
|
||||||
|
import { ShowDatabaseAdvancedSettings } from "@/components/dashboard/shared/show-database-advanced-settings";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
@@ -235,33 +233,9 @@ const Postgresql = (
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{/* {monitoring?.enabledFeatures && (
|
|
||||||
<div className="flex flex-row border w-fit p-4 rounded-lg items-center gap-2">
|
|
||||||
<Label className="text-muted-foreground">
|
|
||||||
Change Monitoring
|
|
||||||
</Label>
|
|
||||||
<Switch
|
|
||||||
checked={toggleMonitoring}
|
|
||||||
onCheckedChange={setToggleMonitoring}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{toggleMonitoring ? (
|
|
||||||
<ContainerPaidMonitoring
|
|
||||||
appName={data?.appName || ""}
|
|
||||||
baseUrl={`http://${monitoring?.serverIp}:${monitoring?.metricsConfig?.server?.port}`}
|
|
||||||
token={
|
|
||||||
monitoring?.metricsConfig?.server?.token || ""
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div> */}
|
|
||||||
<ContainerFreeMonitoring
|
<ContainerFreeMonitoring
|
||||||
appName={data?.appName || ""}
|
appName={data?.appName || ""}
|
||||||
/>
|
/>
|
||||||
{/* </div> */}
|
|
||||||
{/* )} */}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -282,11 +256,10 @@ const Postgresql = (
|
|||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="advanced">
|
<TabsContent value="advanced">
|
||||||
<div className="flex flex-col gap-4 pt-2.5">
|
<div className="flex flex-col gap-4 pt-2.5">
|
||||||
<div className="flex w-full flex-col gap-5 ">
|
<ShowDatabaseAdvancedSettings
|
||||||
<ShowCustomCommand id={postgresId} type="postgres" />
|
id={postgresId}
|
||||||
<ShowVolumes id={postgresId} type="postgres" />
|
type="postgres"
|
||||||
<ShowResources id={postgresId} type="postgres" />
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
|
|
||||||
import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
|
|
||||||
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
|
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
|
||||||
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
|
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
|
||||||
import { DeleteService } from "@/components/dashboard/compose/delete-service";
|
import { DeleteService } from "@/components/dashboard/compose/delete-service";
|
||||||
import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring";
|
import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring";
|
||||||
import { ContainerPaidMonitoring } from "@/components/dashboard/monitoring/paid/container/show-paid-container-monitoring";
|
import { ContainerPaidMonitoring } from "@/components/dashboard/monitoring/paid/container/show-paid-container-monitoring";
|
||||||
import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
|
|
||||||
import { ShowExternalRedisCredentials } from "@/components/dashboard/redis/general/show-external-redis-credentials";
|
import { ShowExternalRedisCredentials } from "@/components/dashboard/redis/general/show-external-redis-credentials";
|
||||||
import { ShowGeneralRedis } from "@/components/dashboard/redis/general/show-general-redis";
|
import { ShowGeneralRedis } from "@/components/dashboard/redis/general/show-general-redis";
|
||||||
import { ShowInternalRedisCredentials } from "@/components/dashboard/redis/general/show-internal-redis-credentials";
|
import { ShowInternalRedisCredentials } from "@/components/dashboard/redis/general/show-internal-redis-credentials";
|
||||||
import { UpdateRedis } from "@/components/dashboard/redis/update-redis";
|
import { UpdateRedis } from "@/components/dashboard/redis/update-redis";
|
||||||
|
import { ShowDatabaseAdvancedSettings } from "@/components/dashboard/shared/show-database-advanced-settings";
|
||||||
import { RedisIcon } from "@/components/icons/data-tools-icons";
|
import { RedisIcon } from "@/components/icons/data-tools-icons";
|
||||||
import { ProjectLayout } from "@/components/layouts/project-layout";
|
import { ProjectLayout } from "@/components/layouts/project-layout";
|
||||||
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
||||||
@@ -272,11 +270,7 @@ const Redis = (
|
|||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="advanced">
|
<TabsContent value="advanced">
|
||||||
<div className="flex flex-col gap-4 pt-2.5">
|
<div className="flex flex-col gap-4 pt-2.5">
|
||||||
<div className="flex w-full flex-col gap-5 ">
|
<ShowDatabaseAdvancedSettings id={redisId} type="redis" />
|
||||||
<ShowCustomCommand id={redisId} type="redis" />
|
|
||||||
<ShowVolumes id={redisId} type="redis" />
|
|
||||||
<ShowResources id={redisId} type="redis" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
apiSaveEnvironmentVariablesMariaDB,
|
apiSaveEnvironmentVariablesMariaDB,
|
||||||
apiSaveExternalPortMariaDB,
|
apiSaveExternalPortMariaDB,
|
||||||
apiUpdateMariaDB,
|
apiUpdateMariaDB,
|
||||||
|
apiRebuildMariadb,
|
||||||
mariadb as mariadbTable,
|
mariadb as mariadbTable,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
import { cancelJobs } from "@/server/utils/backup";
|
import { cancelJobs } from "@/server/utils/backup";
|
||||||
@@ -34,7 +35,7 @@ import { observable } from "@trpc/server/observable";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "@/server/db";
|
import { db } from "@/server/db";
|
||||||
|
import { rebuildDatabase } from "@dokploy/server";
|
||||||
export const mariadbRouter = createTRPCRouter({
|
export const mariadbRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
.input(apiCreateMariaDB)
|
.input(apiCreateMariaDB)
|
||||||
@@ -369,4 +370,18 @@ export const mariadbRouter = createTRPCRouter({
|
|||||||
|
|
||||||
return updatedMariadb;
|
return updatedMariadb;
|
||||||
}),
|
}),
|
||||||
|
rebuild: protectedProcedure
|
||||||
|
.input(apiRebuildMariadb)
|
||||||
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
const mariadb = await findMariadbById(input.mariadbId);
|
||||||
|
if (mariadb.project.organizationId !== ctx.session.activeOrganizationId) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "UNAUTHORIZED",
|
||||||
|
message: "You are not authorized to rebuild this MariaDB database",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await rebuildDatabase(mariadb.mariadbId, "mariadb");
|
||||||
|
return true;
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
apiCreateMongo,
|
apiCreateMongo,
|
||||||
apiDeployMongo,
|
apiDeployMongo,
|
||||||
apiFindOneMongo,
|
apiFindOneMongo,
|
||||||
|
apiRebuildMongo,
|
||||||
apiResetMongo,
|
apiResetMongo,
|
||||||
apiSaveEnvironmentVariablesMongo,
|
apiSaveEnvironmentVariablesMongo,
|
||||||
apiSaveExternalPortMongo,
|
apiSaveExternalPortMongo,
|
||||||
@@ -34,7 +35,7 @@ import { observable } from "@trpc/server/observable";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "@/server/db";
|
import { db } from "@/server/db";
|
||||||
|
import { rebuildDatabase } from "@dokploy/server";
|
||||||
export const mongoRouter = createTRPCRouter({
|
export const mongoRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
.input(apiCreateMongo)
|
.input(apiCreateMongo)
|
||||||
@@ -383,4 +384,19 @@ export const mongoRouter = createTRPCRouter({
|
|||||||
|
|
||||||
return updatedMongo;
|
return updatedMongo;
|
||||||
}),
|
}),
|
||||||
|
rebuild: protectedProcedure
|
||||||
|
.input(apiRebuildMongo)
|
||||||
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
const mongo = await findMongoById(input.mongoId);
|
||||||
|
if (mongo.project.organizationId !== ctx.session.activeOrganizationId) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "UNAUTHORIZED",
|
||||||
|
message: "You are not authorized to rebuild this MongoDB database",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await rebuildDatabase(mongo.mongoId, "mongo");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
apiCreateMySql,
|
apiCreateMySql,
|
||||||
apiDeployMySql,
|
apiDeployMySql,
|
||||||
apiFindOneMySql,
|
apiFindOneMySql,
|
||||||
|
apiRebuildMysql,
|
||||||
apiResetMysql,
|
apiResetMysql,
|
||||||
apiSaveEnvironmentVariablesMySql,
|
apiSaveEnvironmentVariablesMySql,
|
||||||
apiSaveExternalPortMySql,
|
apiSaveExternalPortMySql,
|
||||||
@@ -24,6 +25,7 @@ import {
|
|||||||
findBackupsByDbId,
|
findBackupsByDbId,
|
||||||
findMySqlById,
|
findMySqlById,
|
||||||
findProjectById,
|
findProjectById,
|
||||||
|
rebuildDatabase,
|
||||||
removeMySqlById,
|
removeMySqlById,
|
||||||
removeService,
|
removeService,
|
||||||
startService,
|
startService,
|
||||||
@@ -379,4 +381,19 @@ export const mysqlRouter = createTRPCRouter({
|
|||||||
|
|
||||||
return updatedMysql;
|
return updatedMysql;
|
||||||
}),
|
}),
|
||||||
|
rebuild: protectedProcedure
|
||||||
|
.input(apiRebuildMysql)
|
||||||
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
const mysql = await findMySqlById(input.mysqlId);
|
||||||
|
if (mysql.project.organizationId !== ctx.session.activeOrganizationId) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "UNAUTHORIZED",
|
||||||
|
message: "You are not authorized to rebuild this MySQL database",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await rebuildDatabase(mysql.mysqlId, "mysql");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
apiCreatePostgres,
|
apiCreatePostgres,
|
||||||
apiDeployPostgres,
|
apiDeployPostgres,
|
||||||
apiFindOnePostgres,
|
apiFindOnePostgres,
|
||||||
|
apiRebuildPostgres,
|
||||||
apiResetPostgres,
|
apiResetPostgres,
|
||||||
apiSaveEnvironmentVariablesPostgres,
|
apiSaveEnvironmentVariablesPostgres,
|
||||||
apiSaveExternalPortPostgres,
|
apiSaveExternalPortPostgres,
|
||||||
@@ -21,6 +22,7 @@ import {
|
|||||||
findBackupsByDbId,
|
findBackupsByDbId,
|
||||||
findPostgresById,
|
findPostgresById,
|
||||||
findProjectById,
|
findProjectById,
|
||||||
|
rebuildDatabase,
|
||||||
removePostgresById,
|
removePostgresById,
|
||||||
removeService,
|
removeService,
|
||||||
startService,
|
startService,
|
||||||
@@ -34,7 +36,6 @@ import { observable } from "@trpc/server/observable";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "@/server/db";
|
import { db } from "@/server/db";
|
||||||
|
|
||||||
export const postgresRouter = createTRPCRouter({
|
export const postgresRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
.input(apiCreatePostgres)
|
.input(apiCreatePostgres)
|
||||||
@@ -401,4 +402,21 @@ export const postgresRouter = createTRPCRouter({
|
|||||||
|
|
||||||
return updatedPostgres;
|
return updatedPostgres;
|
||||||
}),
|
}),
|
||||||
|
rebuild: protectedProcedure
|
||||||
|
.input(apiRebuildPostgres)
|
||||||
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
const postgres = await findPostgresById(input.postgresId);
|
||||||
|
if (
|
||||||
|
postgres.project.organizationId !== ctx.session.activeOrganizationId
|
||||||
|
) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "UNAUTHORIZED",
|
||||||
|
message: "You are not authorized to rebuild this Postgres database",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await rebuildDatabase(postgres.postgresId, "postgres");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
apiSaveExternalPortRedis,
|
apiSaveExternalPortRedis,
|
||||||
apiUpdateRedis,
|
apiUpdateRedis,
|
||||||
redis as redisTable,
|
redis as redisTable,
|
||||||
|
apiRebuildRedis,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
|
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
@@ -34,7 +35,7 @@ import { observable } from "@trpc/server/observable";
|
|||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "@/server/db";
|
import { db } from "@/server/db";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
import { rebuildDatabase } from "@dokploy/server";
|
||||||
export const redisRouter = createTRPCRouter({
|
export const redisRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
.input(apiCreateRedis)
|
.input(apiCreateRedis)
|
||||||
@@ -363,4 +364,18 @@ export const redisRouter = createTRPCRouter({
|
|||||||
|
|
||||||
return updatedRedis;
|
return updatedRedis;
|
||||||
}),
|
}),
|
||||||
|
rebuild: protectedProcedure
|
||||||
|
.input(apiRebuildRedis)
|
||||||
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
const redis = await findRedisById(input.redisId);
|
||||||
|
if (redis.project.organizationId !== ctx.session.activeOrganizationId) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "UNAUTHORIZED",
|
||||||
|
message: "You are not authorized to rebuild this Redis database",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await rebuildDatabase(redis.redisId, "redis");
|
||||||
|
return true;
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -146,3 +146,9 @@ export const apiUpdateMariaDB = createSchema
|
|||||||
mariadbId: z.string().min(1),
|
mariadbId: z.string().min(1),
|
||||||
})
|
})
|
||||||
.omit({ serverId: true });
|
.omit({ serverId: true });
|
||||||
|
|
||||||
|
export const apiRebuildMariadb = createSchema
|
||||||
|
.pick({
|
||||||
|
mariadbId: true,
|
||||||
|
})
|
||||||
|
.required();
|
||||||
|
|||||||
@@ -141,3 +141,9 @@ export const apiResetMongo = createSchema
|
|||||||
appName: true,
|
appName: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
|
export const apiRebuildMongo = createSchema
|
||||||
|
.pick({
|
||||||
|
mongoId: true,
|
||||||
|
})
|
||||||
|
.required();
|
||||||
|
|||||||
@@ -144,3 +144,9 @@ export const apiUpdateMySql = createSchema
|
|||||||
mysqlId: z.string().min(1),
|
mysqlId: z.string().min(1),
|
||||||
})
|
})
|
||||||
.omit({ serverId: true });
|
.omit({ serverId: true });
|
||||||
|
|
||||||
|
export const apiRebuildMysql = createSchema
|
||||||
|
.pick({
|
||||||
|
mysqlId: true,
|
||||||
|
})
|
||||||
|
.required();
|
||||||
|
|||||||
@@ -140,3 +140,9 @@ export const apiUpdatePostgres = createSchema
|
|||||||
postgresId: z.string().min(1),
|
postgresId: z.string().min(1),
|
||||||
})
|
})
|
||||||
.omit({ serverId: true });
|
.omit({ serverId: true });
|
||||||
|
|
||||||
|
export const apiRebuildPostgres = createSchema
|
||||||
|
.pick({
|
||||||
|
postgresId: true,
|
||||||
|
})
|
||||||
|
.required();
|
||||||
|
|||||||
@@ -133,3 +133,9 @@ export const apiUpdateRedis = createSchema
|
|||||||
redisId: z.string().min(1),
|
redisId: z.string().min(1),
|
||||||
})
|
})
|
||||||
.omit({ serverId: true });
|
.omit({ serverId: true });
|
||||||
|
|
||||||
|
export const apiRebuildRedis = createSchema
|
||||||
|
.pick({
|
||||||
|
redisId: true,
|
||||||
|
})
|
||||||
|
.required();
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export * from "./services/github";
|
|||||||
export * from "./services/gitlab";
|
export * from "./services/gitlab";
|
||||||
export * from "./services/server";
|
export * from "./services/server";
|
||||||
export * from "./services/application";
|
export * from "./services/application";
|
||||||
|
export * from "./utils/databases/rebuild";
|
||||||
export * from "./setup/config-paths";
|
export * from "./setup/config-paths";
|
||||||
export * from "./setup/postgres-setup";
|
export * from "./setup/postgres-setup";
|
||||||
export * from "./setup/redis-setup";
|
export * from "./setup/redis-setup";
|
||||||
|
|||||||
99
packages/server/src/utils/databases/rebuild.ts
Normal file
99
packages/server/src/utils/databases/rebuild.ts
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import { deployPostgres } from "@dokploy/server/services/postgres";
|
||||||
|
import { execAsyncRemote } from "../process/execAsync";
|
||||||
|
import { execAsync } from "../process/execAsync";
|
||||||
|
import { deployMySql } from "@dokploy/server/services/mysql";
|
||||||
|
import { deployMariadb } from "@dokploy/server/services/mariadb";
|
||||||
|
import { deployMongo } from "@dokploy/server/services/mongo";
|
||||||
|
import { deployRedis } from "@dokploy/server/services/redis";
|
||||||
|
import { removeService } from "../docker/utils";
|
||||||
|
import { db } from "@dokploy/server/db";
|
||||||
|
import {
|
||||||
|
postgres,
|
||||||
|
mysql,
|
||||||
|
mariadb,
|
||||||
|
mongo,
|
||||||
|
redis,
|
||||||
|
} from "@dokploy/server/db/schema";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
|
||||||
|
type DatabaseType = "postgres" | "mysql" | "mariadb" | "mongo" | "redis";
|
||||||
|
|
||||||
|
export const rebuildDatabase = async (
|
||||||
|
databaseId: string,
|
||||||
|
type: DatabaseType,
|
||||||
|
) => {
|
||||||
|
const database = await findDatabaseById(databaseId, type);
|
||||||
|
|
||||||
|
if (!database) {
|
||||||
|
throw new Error("Database not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
await removeService(database.appName, database.serverId);
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 6000));
|
||||||
|
|
||||||
|
for (const mount of database.mounts) {
|
||||||
|
if (mount.type === "volume") {
|
||||||
|
const command = `docker volume rm ${mount?.volumeName} --force`;
|
||||||
|
if (database.serverId) {
|
||||||
|
await execAsyncRemote(database.serverId, command);
|
||||||
|
} else {
|
||||||
|
await execAsync(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "postgres") {
|
||||||
|
await deployPostgres(databaseId);
|
||||||
|
} else if (type === "mysql") {
|
||||||
|
await deployMySql(databaseId);
|
||||||
|
} else if (type === "mariadb") {
|
||||||
|
await deployMariadb(databaseId);
|
||||||
|
} else if (type === "mongo") {
|
||||||
|
await deployMongo(databaseId);
|
||||||
|
} else if (type === "redis") {
|
||||||
|
await deployRedis(databaseId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const findDatabaseById = async (databaseId: string, type: DatabaseType) => {
|
||||||
|
if (type === "postgres") {
|
||||||
|
return await db.query.postgres.findFirst({
|
||||||
|
where: eq(postgres.postgresId, databaseId),
|
||||||
|
with: {
|
||||||
|
mounts: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (type === "mysql") {
|
||||||
|
return await db.query.mysql.findFirst({
|
||||||
|
where: eq(mysql.mysqlId, databaseId),
|
||||||
|
with: {
|
||||||
|
mounts: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (type === "mariadb") {
|
||||||
|
return await db.query.mariadb.findFirst({
|
||||||
|
where: eq(mariadb.mariadbId, databaseId),
|
||||||
|
with: {
|
||||||
|
mounts: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (type === "mongo") {
|
||||||
|
return await db.query.mongo.findFirst({
|
||||||
|
where: eq(mongo.mongoId, databaseId),
|
||||||
|
with: {
|
||||||
|
mounts: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (type === "redis") {
|
||||||
|
return await db.query.redis.findFirst({
|
||||||
|
where: eq(redis.redisId, databaseId),
|
||||||
|
with: {
|
||||||
|
mounts: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user