This commit is contained in:
daniel 2026-09-11 13:11:54 -04:00 committed by GitHub
commit 4d2f06d2b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 287 additions and 0 deletions

View File

@ -0,0 +1,259 @@
import { buildLibsql } from "@dokploy/server/utils/databases/libsql";
import { buildMariadb } from "@dokploy/server/utils/databases/mariadb";
import { buildMongo } from "@dokploy/server/utils/databases/mongo";
import { buildMysql } from "@dokploy/server/utils/databases/mysql";
import { buildPostgres } from "@dokploy/server/utils/databases/postgres";
import { buildRedis } from "@dokploy/server/utils/databases/redis";
import { beforeEach, describe, expect, it, vi } from "vitest";
const {
inspectMock,
updateMock,
getServiceMock,
createServiceMock,
getRemoteDockerMock,
resolveServiceNetworksMock,
} = vi.hoisted(() => {
const inspect = vi.fn();
const update = vi.fn();
const getService = vi.fn(() => ({ inspect, update }));
const createService = vi.fn(async () => undefined);
const getRemoteDocker = vi.fn(async () => ({
getService,
createService,
}));
const resolveServiceNetworks = vi.fn(async () => [
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
return {
inspectMock: inspect,
updateMock: update,
getServiceMock: getService,
createServiceMock: createService,
getRemoteDockerMock: getRemoteDocker,
resolveServiceNetworksMock: resolveServiceNetworks,
};
});
vi.mock("@dokploy/server/utils/servers/remote-docker", () => ({
getRemoteDocker: getRemoteDockerMock,
}));
vi.mock("@dokploy/server/services/network", () => ({
resolveServiceNetworks: resolveServiceNetworksMock,
}));
vi.mock("@dokploy/server/utils/vault", () => ({
withResolvedVaultRefs: vi.fn(async (arg) => arg),
}));
const createBaseDb = (appName: string) => ({
appName,
databaseName: "testdb",
databaseUser: "testuser",
databasePassword: "testpassword",
dockerImage: "postgres:16",
externalPort: 5432,
memoryLimit: null,
memoryReservation: null,
cpuLimit: null,
cpuReservation: null,
command: null,
args: null,
mounts: [],
environment: {
project: { env: null },
env: null,
},
serverId: null,
networkIds: ["custom-overlay-id"],
detachDokployNetwork: false,
});
describe("database networks configuration", () => {
beforeEach(() => {
inspectMock.mockReset();
updateMock.mockReset();
getServiceMock.mockClear();
createServiceMock.mockClear();
getRemoteDockerMock.mockClear();
getRemoteDockerMock.mockResolvedValue({
getService: getServiceMock,
createService: createServiceMock,
});
getServiceMock.mockReturnValue({
inspect: inspectMock,
update: updateMock,
});
});
describe("buildPostgres", () => {
it("attaches networks at both root and TaskTemplate when creating service", async () => {
inspectMock.mockRejectedValue(new Error("service not found"));
const db = createBaseDb("postgres-test-1");
await buildPostgres(db as any);
expect(createServiceMock).toHaveBeenCalledTimes(1);
const [settings] = createServiceMock.mock.calls[0] as [any];
expect(settings.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
expect(settings.TaskTemplate.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
});
it("preserves root and TaskTemplate networks when updating service", async () => {
inspectMock.mockResolvedValue({
Version: { Index: "42" },
Spec: {
TaskTemplate: { ForceUpdate: 1 },
},
});
const db = createBaseDb("postgres-test-2");
await buildPostgres(db as any);
expect(updateMock).toHaveBeenCalledTimes(1);
const [updatePayload] = updateMock.mock.calls[0] as [any];
expect(updatePayload.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
expect(updatePayload.TaskTemplate.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
expect(updatePayload.TaskTemplate.ForceUpdate).toBe(2);
});
});
describe("buildMysql", () => {
it("attaches networks at both root and TaskTemplate when creating and updating service", async () => {
inspectMock.mockResolvedValue({
Version: { Index: "10" },
Spec: {
TaskTemplate: { ForceUpdate: 0 },
},
});
const db = createBaseDb("mysql-test-1");
await buildMysql(db as any);
expect(updateMock).toHaveBeenCalledTimes(1);
const [updatePayload] = updateMock.mock.calls[0] as [any];
expect(updatePayload.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
expect(updatePayload.TaskTemplate.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
});
});
describe("buildMariadb", () => {
it("attaches networks at both root and TaskTemplate when creating and updating service", async () => {
inspectMock.mockResolvedValue({
Version: { Index: "15" },
Spec: {
TaskTemplate: { ForceUpdate: 3 },
},
});
const db = createBaseDb("mariadb-test-1");
await buildMariadb(db as any);
expect(updateMock).toHaveBeenCalledTimes(1);
const [updatePayload] = updateMock.mock.calls[0] as [any];
expect(updatePayload.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
expect(updatePayload.TaskTemplate.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
});
});
describe("buildRedis", () => {
it("attaches networks at both root and TaskTemplate when creating and updating service", async () => {
inspectMock.mockResolvedValue({
Version: { Index: "20" },
Spec: {
TaskTemplate: { ForceUpdate: 5 },
},
});
const db = createBaseDb("redis-test-1");
await buildRedis(db as any);
expect(updateMock).toHaveBeenCalledTimes(1);
const [updatePayload] = updateMock.mock.calls[0] as [any];
expect(updatePayload.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
expect(updatePayload.TaskTemplate.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
});
});
describe("buildMongo", () => {
it("attaches networks at both root and TaskTemplate when creating and updating service", async () => {
inspectMock.mockResolvedValue({
Version: { Index: "25" },
Spec: {
TaskTemplate: { ForceUpdate: 2 },
},
});
const db = createBaseDb("mongo-test-1");
await buildMongo(db as any);
expect(updateMock).toHaveBeenCalledTimes(1);
const [updatePayload] = updateMock.mock.calls[0] as [any];
expect(updatePayload.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
expect(updatePayload.TaskTemplate.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
});
});
describe("buildLibsql", () => {
it("attaches networks at both root and TaskTemplate when creating and updating service", async () => {
inspectMock.mockResolvedValue({
Version: { Index: "30" },
Spec: {
TaskTemplate: { ForceUpdate: 1 },
},
});
const db = createBaseDb("libsql-test-1");
await buildLibsql(db as any);
expect(updateMock).toHaveBeenCalledTimes(1);
const [updatePayload] = updateMock.mock.calls[0] as [any];
expect(updatePayload.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
expect(updatePayload.TaskTemplate.Networks).toEqual([
{ Target: "dokploy-network" },
{ Target: "custom-overlay" },
]);
});
});
});

View File

@ -286,6 +286,7 @@ const rollbackApplication = async (
serveraddress: rollbackRegistry?.registryUrl || "",
},
Name: appName,
Networks: resolvedNetworks,
TaskTemplate: {
ContainerSpec: {
HealthCheck,
@ -328,8 +329,10 @@ const rollbackApplication = async (
await service.update({
version: Number.parseInt(inspect.Version.Index),
...settings,
Networks: resolvedNetworks,
TaskTemplate: {
...settings.TaskTemplate,
Networks: resolvedNetworks,
ForceUpdate: inspect.Spec.TaskTemplate.ForceUpdate + 1,
},
});

View File

@ -134,6 +134,7 @@ export const mechanizeDockerContainer = async (
const settings: CreateServiceOptions = {
authconfig: authConfig,
Name: appName,
Networks: resolvedNetworks,
TaskTemplate: {
ContainerSpec: {
HealthCheck,
@ -181,8 +182,10 @@ export const mechanizeDockerContainer = async (
await service.update({
version: Number.parseInt(inspect.Version.Index),
...settings,
Networks: resolvedNetworks,
TaskTemplate: {
...settings.TaskTemplate,
Networks: resolvedNetworks,
ForceUpdate: inspect.Spec.TaskTemplate.ForceUpdate + 1,
},
});

View File

@ -86,6 +86,7 @@ export const buildLibsql = async (rawLibsql: LibsqlNested) => {
const settings: CreateServiceOptions = {
Name: appName,
Networks: resolvedNetworks,
TaskTemplate: {
ContainerSpec: {
HealthCheck,
@ -156,6 +157,12 @@ export const buildLibsql = async (rawLibsql: LibsqlNested) => {
await service.update({
version: Number.parseInt(inspect.Version.Index),
...settings,
Networks: resolvedNetworks,
TaskTemplate: {
...settings.TaskTemplate,
Networks: resolvedNetworks,
ForceUpdate: (inspect.Spec.TaskTemplate?.ForceUpdate ?? 0) + 1,
},
});
} catch {
await docker.createService(settings);

View File

@ -73,6 +73,7 @@ export const buildMariadb = async (rawMariadb: MariadbNested) => {
const settings: CreateServiceOptions = {
Name: appName,
Networks: resolvedNetworks,
TaskTemplate: {
ContainerSpec: {
HealthCheck,
@ -127,8 +128,10 @@ export const buildMariadb = async (rawMariadb: MariadbNested) => {
await service.update({
version: Number.parseInt(inspect.Version.Index),
...settings,
Networks: resolvedNetworks,
TaskTemplate: {
...settings.TaskTemplate,
Networks: resolvedNetworks,
ForceUpdate: inspect.Spec.TaskTemplate.ForceUpdate + 1,
},
});

View File

@ -121,6 +121,7 @@ ${command ?? "wait $MONGOD_PID"}`;
const settings: CreateServiceOptions = {
Name: appName,
Networks: resolvedNetworks,
TaskTemplate: {
ContainerSpec: {
HealthCheck,
@ -184,8 +185,10 @@ ${command ?? "wait $MONGOD_PID"}`;
await service.update({
version: Number.parseInt(inspect.Version.Index),
...settings,
Networks: resolvedNetworks,
TaskTemplate: {
...settings.TaskTemplate,
Networks: resolvedNetworks,
ForceUpdate: inspect.Spec.TaskTemplate.ForceUpdate + 1,
},
});

View File

@ -79,6 +79,7 @@ export const buildMysql = async (rawMysql: MysqlNested) => {
const settings: CreateServiceOptions = {
Name: appName,
Networks: resolvedNetworks,
TaskTemplate: {
ContainerSpec: {
HealthCheck,
@ -133,8 +134,10 @@ export const buildMysql = async (rawMysql: MysqlNested) => {
await service.update({
version: Number.parseInt(inspect.Version.Index),
...settings,
Networks: resolvedNetworks,
TaskTemplate: {
...settings.TaskTemplate,
Networks: resolvedNetworks,
ForceUpdate: inspect.Spec.TaskTemplate.ForceUpdate + 1,
},
});

View File

@ -72,6 +72,7 @@ export const buildPostgres = async (rawPostgres: PostgresNested) => {
const settings: CreateServiceOptions = {
Name: appName,
Networks: resolvedNetworks,
TaskTemplate: {
ContainerSpec: {
HealthCheck,
@ -125,8 +126,10 @@ export const buildPostgres = async (rawPostgres: PostgresNested) => {
await service.update({
version: Number.parseInt(inspect.Version.Index),
...settings,
Networks: resolvedNetworks,
TaskTemplate: {
...settings.TaskTemplate,
Networks: resolvedNetworks,
ForceUpdate: inspect.Spec.TaskTemplate.ForceUpdate + 1,
},
});

View File

@ -70,6 +70,7 @@ export const buildRedis = async (rawRedis: RedisNested) => {
const settings: CreateServiceOptions = {
Name: appName,
Networks: resolvedNetworks,
TaskTemplate: {
ContainerSpec: {
HealthCheck,
@ -132,8 +133,10 @@ export const buildRedis = async (rawRedis: RedisNested) => {
await service.update({
version: Number.parseInt(inspect.Version.Index),
...settings,
Networks: resolvedNetworks,
TaskTemplate: {
...settings.TaskTemplate,
Networks: resolvedNetworks,
ForceUpdate: inspect.Spec.TaskTemplate.ForceUpdate + 1,
},
});