feat: add application and databases external servers

This commit is contained in:
Mauricio Siu
2024-09-09 15:58:58 -06:00
parent 5afe1645a0
commit 95f75fdccb
16 changed files with 385 additions and 233 deletions

View File

@@ -7,7 +7,7 @@ import {
CardTitle,
} from "@/components/ui/card";
import { api } from "@/utils/api";
import { AlertTriangle, Package } from "lucide-react";
import { Package } from "lucide-react";
import React from "react";
import { AddVolumes } from "./add-volumes";
import { DeleteVolume } from "./delete-volume";

View File

@@ -23,11 +23,7 @@ import {
type DeploymentJob,
cleanQueuesByApplication,
} from "@/server/queues/deployments-queue";
import {
enqueueDeploymentJob,
myQueue,
redisConfig,
} from "@/server/queues/queueSetup";
import { enqueueDeploymentJob, myQueue } from "@/server/queues/queueSetup";
import {
removeService,
startService,
@@ -39,7 +35,7 @@ import {
} from "@/server/utils/filesystem/directory";
import {
readConfig,
readConfigInServer,
readRemoteConfig,
removeTraefikConfig,
writeConfig,
} from "@/server/utils/traefik/application";
@@ -338,7 +334,7 @@ export const applicationRouter = createTRPCRouter({
const application = await findApplicationById(input.applicationId);
let traefikConfig = null;
if (application.serverId) {
traefikConfig = await readConfigInServer(
traefikConfig = await readRemoteConfig(
application.serverId,
application.appName,
);

View File

@@ -71,8 +71,10 @@ export const domainRouter = createTRPCRouter({
.mutation(async ({ input }) => {
const domain = await findDomainById(input.domainId);
const result = await removeDomainById(input.domainId);
if (domain.application) {
await removeDomain(domain.application.appName, domain.uniqueConfigKey);
if (domain.applicationId) {
const application = await findApplicationById(domain.applicationId);
await removeDomain(application, domain.uniqueConfigKey);
}
return result;

View File

@@ -1,5 +1,5 @@
import { readSSHKey } from "@/server/utils/filesystem/ssh";
import { execAsync } from "@/server/utils/process/execAsync";
import { execAsync, execAsyncRemote } from "@/server/utils/process/execAsync";
import { tail } from "lodash";
import { stderr, stdout } from "node:process";
import { Client } from "ssh2";
@@ -86,40 +86,14 @@ export const getContainersByAppNameMatch = async (
? `${cmd} --filter='label=com.docker.compose.project=${appName}'`
: `${cmd} | grep ${appName}`;
if (serverId) {
const server = await findServerById(serverId);
const { stdout, stderr } = await execAsyncRemote(serverId, command);
if (!server.sshKeyId) return;
const keys = await readSSHKey(server.sshKeyId);
const client = new Client();
result = await new Promise<string[]>((resolve, reject) => {
let output = "";
client
.on("ready", () => {
client.exec(command, (err, stream) => {
if (err) {
console.error("Execution error:", err);
reject(err);
return;
}
stream
.on("close", () => {
client.end();
resolve(output.trim().split("\n"));
})
.on("data", (data: string) => {
output += data.toString();
})
.stderr.on("data", (data) => {});
});
})
.connect({
host: server.ipAddress,
port: server.port,
username: server.username,
privateKey: keys.privateKey,
timeout: 99999,
});
});
if (stderr) {
return [];
}
if (!stdout) return [];
result = stdout.trim().split("\n");
} else {
const { stdout, stderr } = await execAsync(command);

View File

@@ -1,5 +1,4 @@
import { rmdir, stat, unlink } from "node:fs/promises";
import path, { join } from "node:path";
import path from "node:path";
import { APPLICATIONS_PATH, COMPOSE_PATH } from "@/server/constants";
import { db } from "@/server/db";
import {
@@ -7,10 +6,11 @@ import {
type apiCreateMount,
mounts,
} from "@/server/db/schema";
import { createFile } from "@/server/utils/docker/utils";
import { createFile, getCreateFileCommand } from "@/server/utils/docker/utils";
import { removeFileOrDirectory } from "@/server/utils/filesystem/directory";
import { TRPCError } from "@trpc/server";
import { type SQL, eq, sql } from "drizzle-orm";
import { execAsyncRemote } from "@/server/utils/process/execAsync";
export type Mount = typeof mounts.$inferSelect;
@@ -71,7 +71,19 @@ export const createFileMount = async (mountId: string) => {
try {
const mount = await findMountById(mountId);
const baseFilePath = await getBaseFilesPath(mountId);
await createFile(baseFilePath, mount.filePath || "", mount.content || "");
const serverId = await getServerId(mount);
if (serverId) {
const command = getCreateFileCommand(
baseFilePath,
mount.filePath || "",
mount.content || "",
);
await execAsyncRemote(serverId, command);
} else {
await createFile(baseFilePath, mount.filePath || "", mount.content || "");
}
} catch (error) {
console.log(`Error to create the file mount: ${error}`);
throw new TRPCError({
@@ -186,9 +198,16 @@ export const deleteFileMount = async (mountId: string) => {
const mount = await findMountById(mountId);
if (!mount.filePath) return;
const basePath = await getBaseFilesPath(mountId);
const fullPath = path.join(basePath, mount.filePath);
try {
await removeFileOrDirectory(fullPath);
const serverId = await getServerId(mount);
if (serverId) {
const command = `rm -rf ${fullPath}`;
await execAsyncRemote(serverId, command);
} else {
await removeFileOrDirectory(fullPath);
}
} catch (error) {}
};
@@ -219,3 +238,30 @@ export const getBaseFilesPath = async (mountId: string) => {
return directoryPath;
};
type MountNested = Awaited<ReturnType<typeof findMountById>>;
export const getServerId = async (mount: MountNested) => {
if (mount.serviceType === "application" && mount?.application?.serverId) {
return mount.application.serverId;
}
if (mount.serviceType === "postgres" && mount?.postgres?.serverId) {
return mount.postgres.serverId;
}
if (mount.serviceType === "mariadb" && mount?.mariadb?.serverId) {
return mount.mariadb.serverId;
}
if (mount.serviceType === "mongo" && mount?.mongo?.serverId) {
return mount.mongo.serverId;
}
if (mount.serviceType === "mysql" && mount?.mysql?.serverId) {
return mount.mysql.serverId;
}
if (mount.serviceType === "redis" && mount?.redis?.serverId) {
return mount.redis.serverId;
}
if (mount.serviceType === "compose" && mount?.compose?.serverId) {
return mount.compose.serverId;
}
return null;
};

View File

@@ -46,7 +46,7 @@ export const createRedirect = async (
const application = await findApplicationById(redirect.applicationId);
createRedirectMiddleware(application.appName, redirect);
createRedirectMiddleware(application, redirect);
});
return true;
@@ -77,7 +77,7 @@ export const removeRedirectById = async (redirectId: string) => {
const application = await findApplicationById(response.applicationId);
removeRedirectMiddleware(application.appName, response);
await removeRedirectMiddleware(application, response);
return response;
} catch (error) {
@@ -111,7 +111,7 @@ export const updateRedirectById = async (
}
const application = await findApplicationById(redirect.applicationId);
updateRedirectMiddleware(application.appName, redirect);
await updateRedirectMiddleware(application, redirect);
return redirect;
} catch (error) {

View File

@@ -44,7 +44,7 @@ export const createSecurity = async (
message: "Error to create the security",
});
}
await createSecurityMiddleware(application.appName, securityResponse);
await createSecurityMiddleware(application, securityResponse);
return true;
});
} catch (error) {
@@ -74,7 +74,7 @@ export const deleteSecurityById = async (securityId: string) => {
const application = await findApplicationById(result.applicationId);
removeSecurityMiddleware(application.appName, result);
await removeSecurityMiddleware(application, result);
return result;
} catch (error) {
throw new TRPCError({

View File

@@ -393,6 +393,24 @@ export const createFile = async (
}
};
export const getCreateFileCommand = (
outputPath: string,
filePath: string,
content: string,
) => {
const fullPath = path.join(outputPath, filePath);
if (fullPath.endsWith(path.sep) || filePath.endsWith("/")) {
return `mkdir -p ${fullPath};`;
}
const directory = path.dirname(fullPath);
return `
mkdir -p ${directory};
echo "${content}" > ${fullPath};
`;
};
export const getServiceContainer = async (appName: string) => {
try {
const filter = {

View File

@@ -1,3 +1,39 @@
import { exec } from "node:child_process";
import util from "node:util";
import { connectSSH } from "../servers/connection";
export const execAsync = util.promisify(exec);
export const execAsyncRemote = async (
serverId: string,
command: string,
): Promise<{ stdout: string; stderr: string }> => {
const client = await connectSSH(serverId);
return new Promise((resolve, reject) => {
client.exec(command, (err, stream) => {
if (err) {
client.end();
return reject(err);
}
let stdout = "";
let stderr = "";
stream
.on("data", (data: string) => {
stdout += data.toString();
})
.on("close", (code, signal) => {
client.end();
if (code === 0) {
resolve({ stdout, stderr });
} else {
reject(new Error(`Command exited with code ${code}`));
}
})
.stderr.on("data", (data) => {
stderr += data.toString();
});
});
});
};

View File

@@ -1,41 +1,10 @@
import { findServerById } from "@/server/api/services/server";
import { readSSHKey } from "../filesystem/ssh";
import { Client } from "ssh2";
import { execAsyncRemote } from "../process/execAsync";
export const executeCommand = async (serverId: string, command: string) => {
const server = await findServerById(serverId);
if (!server.sshKeyId) return;
const keys = await readSSHKey(server.sshKeyId);
const client = new Client();
return new Promise<void>((resolve, reject) => {
client
.on("ready", () => {
client.exec(command, (err, stream) => {
if (err) {
console.error("Execution error:", err);
reject(err);
return;
}
stream
.on("close", (code, signal) => {
client.end();
if (code === 0) {
resolve();
} else {
reject(new Error(`Command exited with code ${code}`));
}
})
.on("data", (data: string) => {})
.stderr.on("data", (data) => {});
});
})
.connect({
host: server.ipAddress,
port: server.port,
username: server.username,
privateKey: keys.privateKey,
timeout: 99999,
});
});
try {
await execAsyncRemote(serverId, command);
} catch (err) {
console.error("Execution error:", err);
throw err;
}
};

View File

@@ -0,0 +1,24 @@
import { findServerById } from "@/server/api/services/server";
import { Client } from "ssh2";
import { readSSHKey } from "../filesystem/ssh";
export const connectSSH = async (serverId: string) => {
const server = await findServerById(serverId);
if (!server.sshKeyId) throw new Error("No SSH key available for this server");
const keys = await readSSHKey(server.sshKeyId);
const client = new Client();
return new Promise<Client>((resolve, reject) => {
client
.on("ready", () => resolve(client))
.on("error", reject)
.connect({
host: server.ipAddress,
port: server.port,
username: server.username,
privateKey: keys.privateKey,
timeout: 99999,
});
});
};

View File

@@ -1,12 +1,10 @@
import fs, { writeFileSync } from "node:fs";
import path from "node:path";
import type { Domain } from "@/server/api/services/domain";
import { DYNAMIC_TRAEFIK_PATH, MAIN_TRAEFIK_PATH } from "@/server/constants";
import { DYNAMIC_TRAEFIK_PATH } from "@/server/constants";
import { dump, load } from "js-yaml";
import type { FileConfig, HttpLoadBalancerService } from "./file-types";
import { findServerById } from "@/server/api/services/server";
import { Client } from "ssh2";
import { readSSHKey } from "../filesystem/ssh";
import { execAsyncRemote } from "../process/execAsync";
export const createTraefikConfig = (appName: string) => {
const defaultPort = 3000;
@@ -58,6 +56,16 @@ export const removeTraefikConfig = async (appName: string) => {
} catch (error) {}
};
export const removeTraefikConfigRemote = async (
appName: string,
serverId: string,
) => {
try {
const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`);
await execAsyncRemote(serverId, `rm ${configPath}`);
} catch (error) {}
};
export const loadOrCreateConfig = (appName: string): FileConfig => {
const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`);
if (fs.existsSync(configPath)) {
@@ -74,56 +82,20 @@ export const loadOrCreateConfigRemote = async (
serverId: string,
appName: string,
) => {
const server = await findServerById(serverId);
if (!server.sshKeyId) return { http: { routers: {}, services: {} } };
const keys = await readSSHKey(server.sshKeyId);
const client = new Client();
let fileConfig: FileConfig;
const fileConfig: FileConfig = { http: { routers: {}, services: {} } };
const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`);
return new Promise<FileConfig>((resolve, reject) => {
client
.on("ready", () => {
client.exec(`cat ${configPath}`, (err, stream) => {
if (err) {
console.error("Execution error:", err);
return { http: { routers: {}, services: {} } };
}
stream
.on("close", (code, signal) => {
client.end();
if (code === 0) {
if (!fileConfig) {
fileConfig = { http: { routers: {}, services: {} } };
}
resolve(
(load(fileConfig) as FileConfig) || {
http: { routers: {}, services: {} },
},
);
} else {
console.log(fileConfig);
try {
const { stdout } = await execAsyncRemote(serverId, `cat ${configPath}`);
resolve({ http: { routers: {}, services: {} } });
if (!stdout) return fileConfig;
// reject(new Error(`Command exited with code ${code}`));
}
})
.on("data", (data: string) => {
console.log(data.toString());
fileConfig = data.toString() as unknown as FileConfig;
})
.stderr.on("data", (data) => {});
});
})
.connect({
host: server.ipAddress,
port: server.port,
username: server.username,
privateKey: keys.privateKey,
timeout: 99999,
});
});
const parsedConfig = (load(stdout) as FileConfig) || {
http: { routers: {}, services: {} },
};
return parsedConfig;
} catch (err) {
return fileConfig;
}
};
export const readConfig = (appName: string) => {
@@ -135,51 +107,15 @@ export const readConfig = (appName: string) => {
return null;
};
export const readConfigInServer = async (serverId: string, appName: string) => {
export const readRemoteConfig = async (serverId: string, appName: string) => {
const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`);
let content = "";
// if (fs.existsSync(configPath)) {
// const yamlStr = fs.readFileSync(configPath, "utf8");
// return yamlStr;
// }
const client = new Client();
const server = await findServerById(serverId);
if (!server.sshKeyId) return;
const keys = await readSSHKey(server.sshKeyId);
return new Promise<string>((resolve, reject) => {
client
.on("ready", () => {
const bashCommand = `
cat ${configPath}
`;
client.exec(bashCommand, (err, stream) => {
if (err) {
reject(err);
return;
}
stream
.on("close", () => {
client.end();
resolve(content);
})
.on("data", (data: string) => {
content = data.toString();
})
.stderr.on("data", (data) => {
reject(new Error(`stderr: ${data.toString()}`));
});
});
})
.connect({
host: server.ipAddress,
port: server.port,
username: server.username,
privateKey: keys.privateKey,
timeout: 99999,
});
});
try {
const { stdout } = await execAsyncRemote(serverId, `cat ${configPath}`);
if (!stdout) return null;
return stdout;
} catch (err) {
return null;
}
};
export const readMonitoringConfig = () => {
@@ -228,13 +164,26 @@ export const writeTraefikConfig = (
try {
const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`);
const yamlStr = dump(traefikConfig);
console.log(yamlStr);
fs.writeFileSync(configPath, yamlStr, "utf8");
} catch (e) {
console.error("Error saving the YAML config file:", e);
}
};
export const writeTraefikConfigRemote = async (
traefikConfig: FileConfig,
appName: string,
serverId: string,
) => {
try {
const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`);
const yamlStr = dump(traefikConfig);
await execAsyncRemote(serverId, `echo '${yamlStr}' > ${configPath}`);
} catch (e) {
console.error("Error saving the YAML config file:", e);
}
};
export const createServiceConfig = (
appName: string,
domain: Domain,

View File

@@ -5,13 +5,11 @@ import {
loadOrCreateConfig,
loadOrCreateConfigRemote,
removeTraefikConfig,
removeTraefikConfigRemote,
writeTraefikConfig,
writeTraefikConfigRemote,
} from "./application";
import type { FileConfig, HttpRouter } from "./file-types";
import { DYNAMIC_TRAEFIK_PATH } from "@/server/constants";
import path from "node:path";
import { dump } from "js-yaml";
import { executeCommand } from "../servers/command";
export const manageDomain = async (app: ApplicationNested, domain: Domain) => {
const { appName } = app;
@@ -49,23 +47,24 @@ export const manageDomain = async (app: ApplicationNested, domain: Domain) => {
config.http.services[serviceName] = createServiceConfig(appName, domain);
if (app.serverId) {
const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`);
const yamlStr = dump(config);
console.log(yamlStr);
const command = `
echo '${yamlStr}' > ${configPath}
`;
await executeCommand(app.serverId, command);
await writeTraefikConfigRemote(config, appName, app.serverId);
} else {
writeTraefikConfig(config, appName);
}
};
export const removeDomain = async (appName: string, uniqueKey: number) => {
const config: FileConfig = loadOrCreateConfig(appName);
export const removeDomain = async (
application: ApplicationNested,
uniqueKey: number,
) => {
const { appName, serverId } = application;
let config: FileConfig;
if (serverId) {
config = await loadOrCreateConfigRemote(serverId, appName);
} else {
config = loadOrCreateConfig(appName);
}
const routerKey = `${appName}-router-${uniqueKey}`;
const routerSecureKey = `${appName}-router-websecure-${uniqueKey}`;
@@ -86,9 +85,17 @@ export const removeDomain = async (appName: string, uniqueKey: number) => {
config?.http?.routers &&
Object.keys(config?.http?.routers).length === 0
) {
await removeTraefikConfig(appName);
if (serverId) {
await removeTraefikConfigRemote(appName, serverId);
} else {
await removeTraefikConfig(appName);
}
} else {
writeTraefikConfig(config, appName);
if (serverId) {
await writeTraefikConfigRemote(config, appName, serverId);
} else {
writeTraefikConfig(config, appName);
}
}
};

View File

@@ -4,6 +4,7 @@ import { DYNAMIC_TRAEFIK_PATH } from "@/server/constants";
import { dump, load } from "js-yaml";
import type { ApplicationNested } from "../builders";
import type { FileConfig } from "./file-types";
import { execAsyncRemote } from "../process/execAsync";
export const addMiddleware = (config: FileConfig, middlewareName: string) => {
if (config.http?.routers) {
@@ -72,6 +73,25 @@ export const loadMiddlewares = <T>() => {
return config;
};
export const loadRemoteMiddlewares = async (serverId: string) => {
const configPath = join(DYNAMIC_TRAEFIK_PATH, "middlewares.yml");
try {
const { stdout, stderr } = await execAsyncRemote(
serverId,
`cat ${configPath}`,
);
if (stderr) {
console.error(`Error: ${stderr}`);
throw new Error(`File not found: ${configPath}`);
}
const config = load(stdout) as FileConfig;
return config;
} catch (error) {
throw new Error(`File not found: ${configPath}`);
}
};
export const writeMiddleware = <T>(config: T) => {
const configPath = join(DYNAMIC_TRAEFIK_PATH, "middlewares.yml");
const newYamlContent = dump(config);

View File

@@ -1,15 +1,32 @@
import type { Redirect } from "@/server/api/services/redirect";
import { loadOrCreateConfig, writeTraefikConfig } from "./application";
import {
loadOrCreateConfig,
loadOrCreateConfigRemote,
writeTraefikConfig,
writeTraefikConfigRemote,
} from "./application";
import type { FileConfig } from "./file-types";
import {
addMiddleware,
deleteMiddleware,
loadMiddlewares,
loadRemoteMiddlewares,
writeMiddleware,
} from "./middleware";
import type { ApplicationNested } from "../builders";
export const updateRedirectMiddleware = (appName: string, data: Redirect) => {
const config = loadMiddlewares<FileConfig>();
export const updateRedirectMiddleware = async (
application: ApplicationNested,
data: Redirect,
) => {
const { appName, serverId } = application;
let config: FileConfig;
if (serverId) {
config = await loadRemoteMiddlewares(serverId);
} else {
config = loadMiddlewares<FileConfig>();
}
const middlewareName = `redirect-${appName}-${data.uniqueConfigKey}`;
if (config?.http?.middlewares?.[middlewareName]) {
@@ -22,10 +39,26 @@ export const updateRedirectMiddleware = (appName: string, data: Redirect) => {
};
}
writeMiddleware(config);
if (serverId) {
await writeTraefikConfigRemote(config, "middlewares", serverId);
} else {
writeMiddleware(config);
}
};
export const createRedirectMiddleware = (appName: string, data: Redirect) => {
const config = loadMiddlewares<FileConfig>();
export const createRedirectMiddleware = async (
application: ApplicationNested,
data: Redirect,
) => {
const { appName, serverId } = application;
let config: FileConfig;
if (serverId) {
config = await loadRemoteMiddlewares(serverId);
} else {
config = loadMiddlewares<FileConfig>();
}
const middlewareName = `redirect-${appName}-${data.uniqueConfigKey}`;
const newMiddleware = {
[middlewareName]: {
@@ -44,25 +77,56 @@ export const createRedirectMiddleware = (appName: string, data: Redirect) => {
};
}
const appConfig = loadOrCreateConfig(appName);
let appConfig: FileConfig;
if (serverId) {
appConfig = await loadOrCreateConfigRemote(serverId, appName);
} else {
appConfig = loadOrCreateConfig(appName);
}
addMiddleware(appConfig, middlewareName);
writeTraefikConfig(appConfig, appName);
writeMiddleware(config);
if (serverId) {
await writeTraefikConfigRemote(config, "middlewares", serverId);
await writeTraefikConfigRemote(appConfig, appName, serverId);
} else {
writeMiddleware(config);
writeTraefikConfig(appConfig, appName);
}
};
export const removeRedirectMiddleware = (appName: string, data: Redirect) => {
const config = loadMiddlewares<FileConfig>();
export const removeRedirectMiddleware = async (
application: ApplicationNested,
data: Redirect,
) => {
const { appName, serverId } = application;
let config: FileConfig;
if (serverId) {
config = await loadRemoteMiddlewares(serverId);
} else {
config = loadMiddlewares<FileConfig>();
}
const middlewareName = `redirect-${appName}-${data.uniqueConfigKey}`;
if (config?.http?.middlewares?.[middlewareName]) {
delete config.http.middlewares[middlewareName];
}
const appConfig = loadOrCreateConfig(appName);
let appConfig: FileConfig;
if (serverId) {
appConfig = await loadOrCreateConfigRemote(serverId, appName);
} else {
appConfig = loadOrCreateConfig(appName);
}
deleteMiddleware(appConfig, middlewareName);
writeTraefikConfig(appConfig, appName);
writeMiddleware(config);
if (serverId) {
await writeTraefikConfigRemote(config, "middlewares", serverId);
await writeTraefikConfigRemote(appConfig, appName, serverId);
} else {
writeTraefikConfig(appConfig, appName);
writeMiddleware(config);
}
};

View File

@@ -1,6 +1,11 @@
import type { Security } from "@/server/api/services/security";
import * as bcrypt from "bcrypt";
import { loadOrCreateConfig, writeTraefikConfig } from "./application";
import {
loadOrCreateConfig,
loadOrCreateConfigRemote,
writeTraefikConfig,
writeTraefikConfigRemote,
} from "./application";
import type {
BasicAuthMiddleware,
FileConfig,
@@ -10,14 +15,23 @@ import {
addMiddleware,
deleteMiddleware,
loadMiddlewares,
loadRemoteMiddlewares,
writeMiddleware,
} from "./middleware";
import type { ApplicationNested } from "../builders";
export const createSecurityMiddleware = async (
appName: string,
application: ApplicationNested,
data: Security,
) => {
const config = loadMiddlewares<FileConfig>();
const { appName, serverId } = application;
let config: FileConfig;
if (serverId) {
config = await loadRemoteMiddlewares(serverId);
} else {
config = loadMiddlewares<FileConfig>();
}
const middlewareName = `auth-${appName}`;
const user = `${data.username}:${await bcrypt.hash(data.password, 10)}`;
@@ -38,17 +52,42 @@ export const createSecurityMiddleware = async (
};
}
}
let appConfig: FileConfig;
const appConfig = loadOrCreateConfig(appName);
if (serverId) {
appConfig = await loadOrCreateConfigRemote(serverId, appName);
} else {
appConfig = loadOrCreateConfig(appName);
}
addMiddleware(appConfig, middlewareName);
writeTraefikConfig(appConfig, appName);
writeMiddleware(config);
if (serverId) {
await writeTraefikConfigRemote(config, "middlewares", serverId);
await writeTraefikConfigRemote(appConfig, appName, serverId);
} else {
writeTraefikConfig(appConfig, appName);
writeMiddleware(config);
}
};
export const removeSecurityMiddleware = (appName: string, data: Security) => {
const config = loadMiddlewares<FileConfig>();
const appConfig = loadOrCreateConfig(appName);
export const removeSecurityMiddleware = async (
application: ApplicationNested,
data: Security,
) => {
const { appName, serverId } = application;
let config: FileConfig;
if (serverId) {
config = await loadRemoteMiddlewares(serverId);
} else {
config = loadMiddlewares<FileConfig>();
}
let appConfig: FileConfig;
if (serverId) {
appConfig = await loadOrCreateConfigRemote(serverId, appName);
} else {
appConfig = loadOrCreateConfig(appName);
}
const middlewareName = `auth-${appName}`;
if (config.http?.middlewares) {
@@ -67,12 +106,20 @@ export const removeSecurityMiddleware = (appName: string, data: Security) => {
delete config.http.middlewares[middlewareName];
}
deleteMiddleware(appConfig, middlewareName);
writeTraefikConfig(appConfig, appName);
if (serverId) {
await writeTraefikConfigRemote(appConfig, appName, serverId);
} else {
writeTraefikConfig(appConfig, appName);
}
}
}
}
writeMiddleware(config);
if (serverId) {
await writeTraefikConfigRemote(config, "middlewares", serverId);
} else {
writeMiddleware(config);
}
};
const isBasicAuthMiddleware = (