feat: add deploy databases to external server

This commit is contained in:
Mauricio Siu
2024-09-08 22:56:21 -06:00
parent 0a889c5db1
commit 6007427a6c
23 changed files with 4037 additions and 34 deletions

View File

@@ -35,6 +35,15 @@ import { useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { z } from "zod"; import { z } from "zod";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
type DbType = typeof mySchema._type.type; type DbType = typeof mySchema._type.type;
@@ -71,6 +80,9 @@ const baseDatabaseSchema = z.object({
databasePassword: z.string(), databasePassword: z.string(),
dockerImage: z.string(), dockerImage: z.string(),
description: z.string().nullable(), description: z.string().nullable(),
serverId: z.string().min(1, {
message: "Server is required",
}),
}); });
const mySchema = z.discriminatedUnion("type", [ const mySchema = z.discriminatedUnion("type", [
@@ -145,6 +157,7 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
const utils = api.useUtils(); const utils = api.useUtils();
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const slug = slugify(projectName); const slug = slugify(projectName);
const { data: servers } = api.server.all.useQuery();
const postgresMutation = api.postgres.create.useMutation(); const postgresMutation = api.postgres.create.useMutation();
const mongoMutation = api.mongo.create.useMutation(); const mongoMutation = api.mongo.create.useMutation();
const redisMutation = api.redis.create.useMutation(); const redisMutation = api.redis.create.useMutation();
@@ -183,6 +196,7 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
appName: data.appName, appName: data.appName,
dockerImage: defaultDockerImage, dockerImage: defaultDockerImage,
projectId, projectId,
serverId: data.serverId,
description: data.description, description: data.description,
}; };
@@ -191,8 +205,10 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
...commonParams, ...commonParams,
databasePassword: data.databasePassword, databasePassword: data.databasePassword,
databaseName: data.databaseName, databaseName: data.databaseName,
databaseUser: databaseUser:
data.databaseUser || databasesUserDefaultPlaceholder[data.type], data.databaseUser || databasesUserDefaultPlaceholder[data.type],
serverId: data.serverId,
}); });
} else if (data.type === "mongo") { } else if (data.type === "mongo") {
promise = mongoMutation.mutateAsync({ promise = mongoMutation.mutateAsync({
@@ -200,6 +216,7 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
databasePassword: data.databasePassword, databasePassword: data.databasePassword,
databaseUser: databaseUser:
data.databaseUser || databasesUserDefaultPlaceholder[data.type], data.databaseUser || databasesUserDefaultPlaceholder[data.type],
serverId: data.serverId,
}); });
} else if (data.type === "redis") { } else if (data.type === "redis") {
promise = redisMutation.mutateAsync({ promise = redisMutation.mutateAsync({
@@ -215,6 +232,7 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
databaseName: data.databaseName, databaseName: data.databaseName,
databaseUser: databaseUser:
data.databaseUser || databasesUserDefaultPlaceholder[data.type], data.databaseUser || databasesUserDefaultPlaceholder[data.type],
serverId: data.serverId,
}); });
} else if (data.type === "mysql") { } else if (data.type === "mysql") {
promise = mysqlMutation.mutateAsync({ promise = mysqlMutation.mutateAsync({
@@ -224,6 +242,7 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
databaseUser: databaseUser:
data.databaseUser || databasesUserDefaultPlaceholder[data.type], data.databaseUser || databasesUserDefaultPlaceholder[data.type],
databaseRootPassword: data.databaseRootPassword, databaseRootPassword: data.databaseRootPassword,
serverId: data.serverId,
}); });
} }
@@ -352,6 +371,39 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
</FormItem> </FormItem>
)} )}
/> />
<FormField
control={form.control}
name="serverId"
render={({ field }) => (
<FormItem>
<FormLabel>Select a Server</FormLabel>
<Select
onValueChange={field.onChange}
defaultValue={field.value}
>
<SelectTrigger>
<SelectValue placeholder="Select a Server" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{servers?.map((server) => (
<SelectItem
key={server.serverId}
value={server.serverId}
>
{server.name}
</SelectItem>
))}
<SelectLabel>
Servers ({servers?.length})
</SelectLabel>
</SelectGroup>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField <FormField
control={form.control} control={form.control}
name="appName" name="appName"

View File

@@ -0,0 +1,34 @@
ALTER TABLE "postgres" ADD COLUMN "serverId" text;--> statement-breakpoint
ALTER TABLE "mariadb" ADD COLUMN "serverId" text;--> statement-breakpoint
ALTER TABLE "mongo" ADD COLUMN "serverId" text;--> statement-breakpoint
ALTER TABLE "mysql" ADD COLUMN "serverId" text;--> statement-breakpoint
ALTER TABLE "redis" ADD COLUMN "serverId" text;--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "postgres" ADD CONSTRAINT "postgres_serverId_server_serverId_fk" FOREIGN KEY ("serverId") REFERENCES "public"."server"("serverId") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "mariadb" ADD CONSTRAINT "mariadb_serverId_server_serverId_fk" FOREIGN KEY ("serverId") REFERENCES "public"."server"("serverId") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "mongo" ADD CONSTRAINT "mongo_serverId_server_serverId_fk" FOREIGN KEY ("serverId") REFERENCES "public"."server"("serverId") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "mysql" ADD CONSTRAINT "mysql_serverId_server_serverId_fk" FOREIGN KEY ("serverId") REFERENCES "public"."server"("serverId") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "redis" ADD CONSTRAINT "redis_serverId_server_serverId_fk" FOREIGN KEY ("serverId") REFERENCES "public"."server"("serverId") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

File diff suppressed because it is too large Load Diff

View File

@@ -295,6 +295,13 @@
"when": 1725830160928, "when": 1725830160928,
"tag": "0041_mute_polaris", "tag": "0041_mute_polaris",
"breakpoints": true "breakpoints": true
},
{
"idx": 42,
"version": "6",
"when": 1725856996201,
"tag": "0042_wandering_inhumans",
"breakpoints": true
} }
] ]
} }

View File

@@ -15,7 +15,6 @@ import {
stopService, stopService,
} from "@/server/utils/docker/utils"; } from "@/server/utils/docker/utils";
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { createMount } from "../services/mount"; import { createMount } from "../services/mount";
import { import {
createMysql, createMysql,

View File

@@ -1,8 +1,4 @@
import { import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
cliProcedure,
createTRPCRouter,
protectedProcedure,
} from "@/server/api/trpc";
import { db } from "@/server/db"; import { db } from "@/server/db";
import { import {
applications, applications,
@@ -34,7 +30,6 @@ import {
checkProjectAccess, checkProjectAccess,
findUserByAuthId, findUserByAuthId,
} from "../services/user"; } from "../services/user";
import { findAdmin, findAdminByAuthId } from "../services/admin";
export const projectRouter = createTRPCRouter({ export const projectRouter = createTRPCRouter({
create: protectedProcedure create: protectedProcedure

View File

@@ -8,6 +8,7 @@ import { generatePassword } from "@/templates/utils";
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { eq, getTableColumns } from "drizzle-orm"; import { eq, getTableColumns } from "drizzle-orm";
import { validUniqueServerAppName } from "./project"; import { validUniqueServerAppName } from "./project";
import { executeCommand } from "@/server/utils/servers/command";
export type Mariadb = typeof mariadb.$inferSelect; export type Mariadb = typeof mariadb.$inferSelect;
@@ -56,6 +57,7 @@ export const findMariadbById = async (mariadbId: string) => {
with: { with: {
project: true, project: true,
mounts: true, mounts: true,
server: true,
backups: { backups: {
with: { with: {
destination: true, destination: true,
@@ -118,7 +120,15 @@ export const findMariadbByBackupId = async (backupId: string) => {
export const deployMariadb = async (mariadbId: string) => { export const deployMariadb = async (mariadbId: string) => {
const mariadb = await findMariadbById(mariadbId); const mariadb = await findMariadbById(mariadbId);
try { try {
await pullImage(mariadb.dockerImage); if (mariadb.serverId) {
await executeCommand(
mariadb.serverId,
`docker pull ${mariadb.dockerImage}`,
);
} else {
await pullImage(mariadb.dockerImage);
}
await buildMariadb(mariadb); await buildMariadb(mariadb);
await updateMariadbById(mariadbId, { await updateMariadbById(mariadbId, {
applicationStatus: "done", applicationStatus: "done",

View File

@@ -8,6 +8,7 @@ import { generatePassword } from "@/templates/utils";
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { eq, getTableColumns } from "drizzle-orm"; import { eq, getTableColumns } from "drizzle-orm";
import { validUniqueServerAppName } from "./project"; import { validUniqueServerAppName } from "./project";
import { executeCommand } from "@/server/utils/servers/command";
export type Mongo = typeof mongo.$inferSelect; export type Mongo = typeof mongo.$inferSelect;
@@ -52,6 +53,7 @@ export const findMongoById = async (mongoId: string) => {
with: { with: {
project: true, project: true,
mounts: true, mounts: true,
server: true,
backups: { backups: {
with: { with: {
destination: true, destination: true,
@@ -114,7 +116,12 @@ export const removeMongoById = async (mongoId: string) => {
export const deployMongo = async (mongoId: string) => { export const deployMongo = async (mongoId: string) => {
const mongo = await findMongoById(mongoId); const mongo = await findMongoById(mongoId);
try { try {
await pullImage(mongo.dockerImage); if (mongo.serverId) {
await executeCommand(mongo.serverId, `docker pull ${mongo.dockerImage}`);
} else {
await pullImage(mongo.dockerImage);
}
await buildMongo(mongo); await buildMongo(mongo);
await updateMongoById(mongoId, { await updateMongoById(mongoId, {
applicationStatus: "done", applicationStatus: "done",

View File

@@ -8,6 +8,7 @@ import { generatePassword } from "@/templates/utils";
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { eq, getTableColumns } from "drizzle-orm"; import { eq, getTableColumns } from "drizzle-orm";
import { validUniqueServerAppName } from "./project"; import { validUniqueServerAppName } from "./project";
import { executeCommand } from "@/server/utils/servers/command";
export type MySql = typeof mysql.$inferSelect; export type MySql = typeof mysql.$inferSelect;
@@ -57,6 +58,7 @@ export const findMySqlById = async (mysqlId: string) => {
with: { with: {
project: true, project: true,
mounts: true, mounts: true,
server: true,
backups: { backups: {
with: { with: {
destination: true, destination: true,
@@ -119,7 +121,12 @@ export const removeMySqlById = async (mysqlId: string) => {
export const deployMySql = async (mysqlId: string) => { export const deployMySql = async (mysqlId: string) => {
const mysql = await findMySqlById(mysqlId); const mysql = await findMySqlById(mysqlId);
try { try {
await pullImage(mysql.dockerImage); if (mysql.serverId) {
await executeCommand(mysql.serverId, `docker pull ${mysql.dockerImage}`);
} else {
await pullImage(mysql.dockerImage);
}
await buildMysql(mysql); await buildMysql(mysql);
await updateMySqlById(mysqlId, { await updateMySqlById(mysqlId, {
applicationStatus: "done", applicationStatus: "done",

View File

@@ -8,6 +8,7 @@ import { generatePassword } from "@/templates/utils";
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { eq, getTableColumns } from "drizzle-orm"; import { eq, getTableColumns } from "drizzle-orm";
import { validUniqueServerAppName } from "./project"; import { validUniqueServerAppName } from "./project";
import { executeCommand } from "@/server/utils/servers/command";
export type Postgres = typeof postgres.$inferSelect; export type Postgres = typeof postgres.$inferSelect;
@@ -45,13 +46,13 @@ export const createPostgres = async (input: typeof apiCreatePostgres._type) => {
return newPostgres; return newPostgres;
}; };
export const findPostgresById = async (postgresId: string) => { export const findPostgresById = async (postgresId: string) => {
const result = await db.query.postgres.findFirst({ const result = await db.query.postgres.findFirst({
where: eq(postgres.postgresId, postgresId), where: eq(postgres.postgresId, postgresId),
with: { with: {
project: true, project: true,
mounts: true, mounts: true,
server: true,
backups: { backups: {
with: { with: {
destination: true, destination: true,
@@ -114,7 +115,15 @@ export const removePostgresById = async (postgresId: string) => {
export const deployPostgres = async (postgresId: string) => { export const deployPostgres = async (postgresId: string) => {
const postgres = await findPostgresById(postgresId); const postgres = await findPostgresById(postgresId);
try { try {
await pullImage(postgres.dockerImage); if (postgres.serverId) {
await executeCommand(
postgres.serverId,
`docker pull ${postgres.dockerImage}`,
);
} else {
await pullImage(postgres.dockerImage);
}
await buildPostgres(postgres); await buildPostgres(postgres);
await updatePostgresById(postgresId, { await updatePostgresById(postgresId, {
applicationStatus: "done", applicationStatus: "done",

View File

@@ -8,6 +8,7 @@ import { generatePassword } from "@/templates/utils";
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { validUniqueServerAppName } from "./project"; import { validUniqueServerAppName } from "./project";
import { executeCommand } from "@/server/utils/servers/command";
export type Redis = typeof redis.$inferSelect; export type Redis = typeof redis.$inferSelect;
@@ -53,6 +54,7 @@ export const findRedisById = async (redisId: string) => {
with: { with: {
project: true, project: true,
mounts: true, mounts: true,
server: true,
}, },
}); });
if (!result) { if (!result) {
@@ -91,7 +93,12 @@ export const removeRedisById = async (redisId: string) => {
export const deployRedis = async (redisId: string) => { export const deployRedis = async (redisId: string) => {
const redis = await findRedisById(redisId); const redis = await findRedisById(redisId);
try { try {
await pullImage(redis.dockerImage); if (redis.serverId) {
await executeCommand(redis.serverId, `docker pull ${redis.dockerImage}`);
} else {
await pullImage(redis.dockerImage);
}
await buildRedis(redis); await buildRedis(redis);
await updateRedisById(redisId, { await updateRedisById(redisId, {
applicationStatus: "done", applicationStatus: "done",

View File

@@ -9,6 +9,7 @@ import { mounts } from "./mount";
import { projects } from "./project"; import { projects } from "./project";
import { applicationStatus } from "./shared"; import { applicationStatus } from "./shared";
import { generateAppName } from "./utils"; import { generateAppName } from "./utils";
import { server } from "./server";
export const mariadb = pgTable("mariadb", { export const mariadb = pgTable("mariadb", {
mariadbId: text("mariadbId") mariadbId: text("mariadbId")
@@ -44,6 +45,9 @@ export const mariadb = pgTable("mariadb", {
projectId: text("projectId") projectId: text("projectId")
.notNull() .notNull()
.references(() => projects.projectId, { onDelete: "cascade" }), .references(() => projects.projectId, { onDelete: "cascade" }),
serverId: text("serverId").references(() => server.serverId, {
onDelete: "cascade",
}),
}); });
export const mariadbRelations = relations(mariadb, ({ one, many }) => ({ export const mariadbRelations = relations(mariadb, ({ one, many }) => ({
@@ -53,6 +57,10 @@ export const mariadbRelations = relations(mariadb, ({ one, many }) => ({
}), }),
backups: many(backups), backups: many(backups),
mounts: many(mounts), mounts: many(mounts),
server: one(server, {
fields: [mariadb.serverId],
references: [server.serverId],
}),
})); }));
const createSchema = createInsertSchema(mariadb, { const createSchema = createInsertSchema(mariadb, {
@@ -88,6 +96,7 @@ export const apiCreateMariaDB = createSchema
databaseName: true, databaseName: true,
databaseUser: true, databaseUser: true,
databasePassword: true, databasePassword: true,
serverId: true,
}) })
.required(); .required();

View File

@@ -9,6 +9,7 @@ import { mounts } from "./mount";
import { projects } from "./project"; import { projects } from "./project";
import { applicationStatus } from "./shared"; import { applicationStatus } from "./shared";
import { generateAppName } from "./utils"; import { generateAppName } from "./utils";
import { server } from "./server";
export const mongo = pgTable("mongo", { export const mongo = pgTable("mongo", {
mongoId: text("mongoId") mongoId: text("mongoId")
@@ -40,6 +41,9 @@ export const mongo = pgTable("mongo", {
projectId: text("projectId") projectId: text("projectId")
.notNull() .notNull()
.references(() => projects.projectId, { onDelete: "cascade" }), .references(() => projects.projectId, { onDelete: "cascade" }),
serverId: text("serverId").references(() => server.serverId, {
onDelete: "cascade",
}),
}); });
export const mongoRelations = relations(mongo, ({ one, many }) => ({ export const mongoRelations = relations(mongo, ({ one, many }) => ({
@@ -49,6 +53,10 @@ export const mongoRelations = relations(mongo, ({ one, many }) => ({
}), }),
backups: many(backups), backups: many(backups),
mounts: many(mounts), mounts: many(mounts),
server: one(server, {
fields: [mongo.serverId],
references: [server.serverId],
}),
})); }));
const createSchema = createInsertSchema(mongo, { const createSchema = createInsertSchema(mongo, {
@@ -80,6 +88,7 @@ export const apiCreateMongo = createSchema
description: true, description: true,
databaseUser: true, databaseUser: true,
databasePassword: true, databasePassword: true,
serverId: true,
}) })
.required(); .required();

View File

@@ -1,4 +1,3 @@
import { generatePassword } from "@/templates/utils";
import { relations } from "drizzle-orm"; import { relations } from "drizzle-orm";
import { integer, pgTable, text } from "drizzle-orm/pg-core"; import { integer, pgTable, text } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod"; import { createInsertSchema } from "drizzle-zod";
@@ -9,6 +8,7 @@ import { mounts } from "./mount";
import { projects } from "./project"; import { projects } from "./project";
import { applicationStatus } from "./shared"; import { applicationStatus } from "./shared";
import { generateAppName } from "./utils"; import { generateAppName } from "./utils";
import { server } from "./server";
export const mysql = pgTable("mysql", { export const mysql = pgTable("mysql", {
mysqlId: text("mysqlId") mysqlId: text("mysqlId")
@@ -42,6 +42,9 @@ export const mysql = pgTable("mysql", {
projectId: text("projectId") projectId: text("projectId")
.notNull() .notNull()
.references(() => projects.projectId, { onDelete: "cascade" }), .references(() => projects.projectId, { onDelete: "cascade" }),
serverId: text("serverId").references(() => server.serverId, {
onDelete: "cascade",
}),
}); });
export const mysqlRelations = relations(mysql, ({ one, many }) => ({ export const mysqlRelations = relations(mysql, ({ one, many }) => ({
@@ -51,6 +54,10 @@ export const mysqlRelations = relations(mysql, ({ one, many }) => ({
}), }),
backups: many(backups), backups: many(backups),
mounts: many(mounts), mounts: many(mounts),
server: one(server, {
fields: [mysql.serverId],
references: [server.serverId],
}),
})); }));
const createSchema = createInsertSchema(mysql, { const createSchema = createInsertSchema(mysql, {
@@ -86,6 +93,7 @@ export const apiCreateMySql = createSchema
databaseUser: true, databaseUser: true,
databasePassword: true, databasePassword: true,
databaseRootPassword: true, databaseRootPassword: true,
serverId: true,
}) })
.required(); .required();

View File

@@ -9,6 +9,7 @@ import { mounts } from "./mount";
import { projects } from "./project"; import { projects } from "./project";
import { applicationStatus } from "./shared"; import { applicationStatus } from "./shared";
import { generateAppName } from "./utils"; import { generateAppName } from "./utils";
import { server } from "./server";
export const postgres = pgTable("postgres", { export const postgres = pgTable("postgres", {
postgresId: text("postgresId") postgresId: text("postgresId")
@@ -41,6 +42,9 @@ export const postgres = pgTable("postgres", {
projectId: text("projectId") projectId: text("projectId")
.notNull() .notNull()
.references(() => projects.projectId, { onDelete: "cascade" }), .references(() => projects.projectId, { onDelete: "cascade" }),
serverId: text("serverId").references(() => server.serverId, {
onDelete: "cascade",
}),
}); });
export const postgresRelations = relations(postgres, ({ one, many }) => ({ export const postgresRelations = relations(postgres, ({ one, many }) => ({
@@ -50,6 +54,10 @@ export const postgresRelations = relations(postgres, ({ one, many }) => ({
}), }),
backups: many(backups), backups: many(backups),
mounts: many(mounts), mounts: many(mounts),
server: one(server, {
fields: [postgres.serverId],
references: [server.serverId],
}),
})); }));
const createSchema = createInsertSchema(postgres, { const createSchema = createInsertSchema(postgres, {
@@ -82,6 +90,7 @@ export const apiCreatePostgres = createSchema
dockerImage: true, dockerImage: true,
projectId: true, projectId: true,
description: true, description: true,
serverId: true,
}) })
.required(); .required();

View File

@@ -1,4 +1,3 @@
import { generatePassword } from "@/templates/utils";
import { relations } from "drizzle-orm"; import { relations } from "drizzle-orm";
import { integer, pgTable, text } from "drizzle-orm/pg-core"; import { integer, pgTable, text } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod"; import { createInsertSchema } from "drizzle-zod";
@@ -8,6 +7,7 @@ import { mounts } from "./mount";
import { projects } from "./project"; import { projects } from "./project";
import { applicationStatus } from "./shared"; import { applicationStatus } from "./shared";
import { generateAppName } from "./utils"; import { generateAppName } from "./utils";
import { server } from "./server";
export const redis = pgTable("redis", { export const redis = pgTable("redis", {
redisId: text("redisId") redisId: text("redisId")
@@ -38,6 +38,9 @@ export const redis = pgTable("redis", {
projectId: text("projectId") projectId: text("projectId")
.notNull() .notNull()
.references(() => projects.projectId, { onDelete: "cascade" }), .references(() => projects.projectId, { onDelete: "cascade" }),
serverId: text("serverId").references(() => server.serverId, {
onDelete: "cascade",
}),
}); });
export const redisRelations = relations(redis, ({ one, many }) => ({ export const redisRelations = relations(redis, ({ one, many }) => ({
@@ -46,6 +49,10 @@ export const redisRelations = relations(redis, ({ one, many }) => ({
references: [projects.projectId], references: [projects.projectId],
}), }),
mounts: many(mounts), mounts: many(mounts),
server: one(server, {
fields: [redis.serverId],
references: [server.serverId],
}),
})); }));
const createSchema = createInsertSchema(redis, { const createSchema = createInsertSchema(redis, {
@@ -75,6 +82,7 @@ export const apiCreateRedis = createSchema
dockerImage: true, dockerImage: true,
projectId: true, projectId: true,
description: true, description: true,
serverId: true,
}) })
.required(); .required();

View File

@@ -7,7 +7,15 @@ import { admins } from "./admin";
import { generateAppName } from "./utils"; import { generateAppName } from "./utils";
import { deployments } from "./deployment"; import { deployments } from "./deployment";
import { sshKeys } from "./ssh-key"; import { sshKeys } from "./ssh-key";
import { applications, compose } from "."; import {
applications,
compose,
mariadb,
mongo,
mysql,
postgres,
redis,
} from ".";
export const server = pgTable("server", { export const server = pgTable("server", {
serverId: text("serverId") serverId: text("serverId")
@@ -46,6 +54,11 @@ export const serverRelations = relations(server, ({ one, many }) => ({
}), }),
applications: many(applications), applications: many(applications),
compose: many(compose), compose: many(compose),
redis: many(redis),
mariadb: many(mariadb),
mongo: many(mongo),
mysql: many(mysql),
postgres: many(postgres),
})); }));
const createSchema = createInsertSchema(server, { const createSchema = createInsertSchema(server, {

View File

@@ -130,20 +130,6 @@ export const mechanizeDockerContainer = async (
const image = getImageName(application); const image = getImageName(application);
const authConfig = getAuthConfig(application); const authConfig = getAuthConfig(application);
const docker = await getRemoteDocker(application.serverId); const docker = await getRemoteDocker(application.serverId);
// const server = await findServerById(application.serverId);
// if (!server.sshKeyId) return;
// const keys = await readSSHKey(server.sshKeyId);
// const docker = new Dockerode({
// host: server.ipAddress,
// port: server.port,
// username: server.username,
// protocol: "ssh",
// sshOptions: {
// privateKey: keys.privateKey,
// },
// });
// const results = await docker2.listContainers();
// console.log(results);
const settings: CreateServiceOptions = { const settings: CreateServiceOptions = {
authconfig: authConfig, authconfig: authConfig,

View File

@@ -1,6 +1,5 @@
import type { Mariadb } from "@/server/api/services/mariadb"; import type { Mariadb } from "@/server/api/services/mariadb";
import type { Mount } from "@/server/api/services/mount"; import type { Mount } from "@/server/api/services/mount";
import { docker } from "@/server/constants";
import type { CreateServiceOptions } from "dockerode"; import type { CreateServiceOptions } from "dockerode";
import { import {
calculateResources, calculateResources,
@@ -9,6 +8,7 @@ import {
generateVolumeMounts, generateVolumeMounts,
prepareEnvironmentVariables, prepareEnvironmentVariables,
} from "../docker/utils"; } from "../docker/utils";
import { getRemoteDocker } from "../servers/remote-docker";
type MariadbWithMounts = Mariadb & { type MariadbWithMounts = Mariadb & {
mounts: Mount[]; mounts: Mount[];
@@ -45,6 +45,8 @@ export const buildMariadb = async (mariadb: MariadbWithMounts) => {
const bindsMount = generateBindMounts(mounts); const bindsMount = generateBindMounts(mounts);
const filesMount = generateFileMounts(appName, mounts); const filesMount = generateFileMounts(appName, mounts);
const docker = await getRemoteDocker(mariadb.serverId);
const settings: CreateServiceOptions = { const settings: CreateServiceOptions = {
Name: appName, Name: appName,
TaskTemplate: { TaskTemplate: {

View File

@@ -1,7 +1,5 @@
import type { Mongo } from "@/server/api/services/mongo"; import type { Mongo } from "@/server/api/services/mongo";
import type { Mount } from "@/server/api/services/mount"; import type { Mount } from "@/server/api/services/mount";
import type { Postgres } from "@/server/api/services/postgres";
import { docker } from "@/server/constants";
import type { CreateServiceOptions } from "dockerode"; import type { CreateServiceOptions } from "dockerode";
import { import {
calculateResources, calculateResources,
@@ -10,6 +8,7 @@ import {
generateVolumeMounts, generateVolumeMounts,
prepareEnvironmentVariables, prepareEnvironmentVariables,
} from "../docker/utils"; } from "../docker/utils";
import { getRemoteDocker } from "../servers/remote-docker";
type MongoWithMounts = Mongo & { type MongoWithMounts = Mongo & {
mounts: Mount[]; mounts: Mount[];
@@ -45,6 +44,8 @@ export const buildMongo = async (mongo: MongoWithMounts) => {
const bindsMount = generateBindMounts(mounts); const bindsMount = generateBindMounts(mounts);
const filesMount = generateFileMounts(appName, mounts); const filesMount = generateFileMounts(appName, mounts);
const docker = await getRemoteDocker(mongo.serverId);
const settings: CreateServiceOptions = { const settings: CreateServiceOptions = {
Name: appName, Name: appName,
TaskTemplate: { TaskTemplate: {

View File

@@ -9,6 +9,7 @@ import {
generateVolumeMounts, generateVolumeMounts,
prepareEnvironmentVariables, prepareEnvironmentVariables,
} from "../docker/utils"; } from "../docker/utils";
import { getRemoteDocker } from "../servers/remote-docker";
type MysqlWithMounts = MySql & { type MysqlWithMounts = MySql & {
mounts: Mount[]; mounts: Mount[];
@@ -51,6 +52,8 @@ export const buildMysql = async (mysql: MysqlWithMounts) => {
const bindsMount = generateBindMounts(mounts); const bindsMount = generateBindMounts(mounts);
const filesMount = generateFileMounts(appName, mounts); const filesMount = generateFileMounts(appName, mounts);
const docker = await getRemoteDocker(mysql.serverId);
const settings: CreateServiceOptions = { const settings: CreateServiceOptions = {
Name: appName, Name: appName,
TaskTemplate: { TaskTemplate: {

View File

@@ -1,6 +1,5 @@
import type { Mount } from "@/server/api/services/mount"; import type { Mount } from "@/server/api/services/mount";
import type { Postgres } from "@/server/api/services/postgres"; import type { Postgres } from "@/server/api/services/postgres";
import { docker } from "@/server/constants";
import type { CreateServiceOptions } from "dockerode"; import type { CreateServiceOptions } from "dockerode";
import { import {
calculateResources, calculateResources,
@@ -9,6 +8,7 @@ import {
generateVolumeMounts, generateVolumeMounts,
prepareEnvironmentVariables, prepareEnvironmentVariables,
} from "../docker/utils"; } from "../docker/utils";
import { getRemoteDocker } from "../servers/remote-docker";
type PostgresWithMounts = Postgres & { type PostgresWithMounts = Postgres & {
mounts: Mount[]; mounts: Mount[];
@@ -45,6 +45,8 @@ export const buildPostgres = async (postgres: PostgresWithMounts) => {
const bindsMount = generateBindMounts(mounts); const bindsMount = generateBindMounts(mounts);
const filesMount = generateFileMounts(appName, mounts); const filesMount = generateFileMounts(appName, mounts);
const docker = await getRemoteDocker(postgres.serverId);
const settings: CreateServiceOptions = { const settings: CreateServiceOptions = {
Name: appName, Name: appName,
TaskTemplate: { TaskTemplate: {

View File

@@ -9,6 +9,7 @@ import {
generateVolumeMounts, generateVolumeMounts,
prepareEnvironmentVariables, prepareEnvironmentVariables,
} from "../docker/utils"; } from "../docker/utils";
import { getRemoteDocker } from "../servers/remote-docker";
type RedisWithMounts = Redis & { type RedisWithMounts = Redis & {
mounts: Mount[]; mounts: Mount[];
@@ -43,6 +44,8 @@ export const buildRedis = async (redis: RedisWithMounts) => {
const bindsMount = generateBindMounts(mounts); const bindsMount = generateBindMounts(mounts);
const filesMount = generateFileMounts(appName, mounts); const filesMount = generateFileMounts(appName, mounts);
const docker = await getRemoteDocker(redis.serverId);
const settings: CreateServiceOptions = { const settings: CreateServiceOptions = {
Name: appName, Name: appName,
TaskTemplate: { TaskTemplate: {