fix: Some nasty bug

fix: Automatic reconfiguration of all services and service proxies
This commit is contained in:
Andras Bacsai 2022-02-15 21:44:36 +01:00
parent 3ae7624361
commit 531c712ea5
11 changed files with 181 additions and 100 deletions

View File

@ -74,26 +74,12 @@ export async function makeLabelForStandaloneDatabase({ id, image, volume }) {
];
}
export async function makeLabelForPlausibleAnalytics({ id, images, volume }) {
const service = await db.prisma.service.findFirst({
where: { id },
include: { plausibleAnalytics: true }
});
delete service.destinationDockerId;
delete service.createdAt;
delete service.updatedAt;
export function makeLabelForServices(type) {
return [
'coolify.managed=true',
`coolify.version=${version}`,
`coolify.type=service-plausibleanalytics`,
`coolify.configuration=${base64Encode(
JSON.stringify({
version,
images,
volume,
...service
})
)}`
`coolify.type=service`,
`coolify.service.type=${type}`
];
}

View File

@ -114,27 +114,55 @@ export const supportedServiceTypesAndVersions = [
name: 'plausibleanalytics',
fancyName: 'Plausible Analytics',
baseImage: 'plausible/analytics',
versions: ['latest']
versions: ['latest'],
ports: {
main: 8000
}
},
{
name: 'nocodb',
fancyName: 'NocoDB',
baseImage: 'nocodb/nocodb',
versions: ['latest'],
ports: {
main: 8080
}
},
{
name: 'minio',
fancyName: 'MinIO',
baseImage: 'minio/minio',
versions: ['latest'],
ports: {
main: 9001
}
},
{ name: 'nocodb', fancyName: 'NocoDB', baseImage: 'nocodb/nocodb', versions: ['latest'] },
{ name: 'minio', fancyName: 'MinIO', baseImage: 'minio/minio', versions: ['latest'] },
{
name: 'vscodeserver',
fancyName: 'VSCode Server',
baseImage: 'codercom/code-server',
versions: ['latest']
versions: ['latest'],
ports: {
main: 8080
}
},
{
name: 'wordpress',
fancyName: 'Wordpress',
baseImage: 'wordpress',
versions: ['latest', 'php8.1', 'php8.0', 'php7.4', 'php7.3']
versions: ['latest', 'php8.1', 'php8.0', 'php7.4', 'php7.3'],
ports: {
main: 80
}
},
{
name: 'vaultwarden',
fancyName: 'Vaultwarden',
baseImage: 'vaultwarden/server',
versions: ['latest']
versions: ['latest'],
ports: {
main: 80
}
}
];

View File

@ -509,46 +509,60 @@ export async function configureNetworkCoolifyProxy(engine) {
export async function configureSimpleServiceProxyOn({ id, domain, port }) {
const haproxy = await haproxyInstance();
await checkHAProxy(haproxy);
let serverConfigured = false;
let backendAvailable: any = null;
try {
await haproxy.get(`v2/services/haproxy/configuration/backends/${domain}`).json();
const transactionId = await getNextTransactionId();
await haproxy
.delete(`v2/services/haproxy/configuration/backends/${domain}`, {
backendAvailable = await haproxy
.get(`v2/services/haproxy/configuration/backends/${domain}`)
.json();
const server: any = await haproxy
.get(`v2/services/haproxy/configuration/servers/${id}`, {
searchParams: {
transaction_id: transactionId
backend: domain
}
})
.json();
await completeTransaction(transactionId);
if (backendAvailable && server) {
// Very sophisticated way to check if the server is already configured in proxy
if (backendAvailable.data.forwardfor.enabled === 'enabled') {
if (backendAvailable.data.name === domain) {
if (server.data.check === 'enabled') {
if (server.data.address === id) {
if (server.data.port === port) {
serverConfigured = true;
}
}
}
}
}
}
} catch (error) {}
try {
const transactionId = await getNextTransactionId();
await haproxy.post('v2/services/haproxy/configuration/backends', {
searchParams: {
transaction_id: transactionId
},
json: {
'init-addr': 'last,libc,none',
forwardfor: { enabled: 'enabled' },
name: domain
}
});
await haproxy.post('v2/services/haproxy/configuration/servers', {
searchParams: {
transaction_id: transactionId,
backend: domain
},
json: {
address: id,
check: 'enabled',
name: id,
port: port
}
});
await completeTransaction(transactionId);
} catch (error) {
console.log(error);
}
if (serverConfigured) return;
const transactionId = await getNextTransactionId();
await haproxy.post('v2/services/haproxy/configuration/backends', {
searchParams: {
transaction_id: transactionId
},
json: {
'init-addr': 'last,libc,none',
forwardfor: { enabled: 'enabled' },
name: domain
}
});
await haproxy.post('v2/services/haproxy/configuration/servers', {
searchParams: {
transaction_id: transactionId,
backend: domain
},
json: {
address: id,
check: 'enabled',
name: id,
port: port
}
});
await completeTransaction(transactionId);
}
export async function configureSimpleServiceProxyOff({ domain }) {

View File

@ -1,14 +1,16 @@
import { getDomain } from '$lib/common';
import { getApplicationById, prisma } from '$lib/database';
import { getApplicationById, prisma, supportedServiceTypesAndVersions } from '$lib/database';
import { dockerInstance } from '$lib/docker';
import {
checkContainer,
configureCoolifyProxyOn,
configureProxyForApplication,
configureSimpleServiceProxyOn,
forceSSLOnApplication,
reloadHaproxy,
setWwwRedirection,
startCoolifyProxy
startCoolifyProxy,
startHttpProxy
} from '$lib/haproxy';
import * as db from '$lib/database';
@ -24,35 +26,70 @@ export default async function () {
(container) => container.Labels['coolify.managed']
);
for (const configuration of configurations) {
const parsedConfiguration = JSON.parse(
Buffer.from(configuration.Labels['coolify.configuration'], 'base64').toString()
);
if (
parsedConfiguration &&
configuration.Labels['coolify.type'] === 'standalone-application'
) {
const { fqdn, applicationId, port, pullmergeRequestId } = parsedConfiguration;
if (fqdn) {
const found = await getApplicationById({ id: applicationId });
if (found) {
const domain = getDomain(fqdn);
await configureProxyForApplication({
domain,
imageId: pullmergeRequestId
? `${applicationId}-${pullmergeRequestId}`
: applicationId,
applicationId,
port
});
const isHttps = fqdn.startsWith('https://');
if (isHttps) await forceSSLOnApplication({ domain });
await setWwwRedirection(fqdn);
if (configuration.Labels['coolify.configuration']) {
const parsedConfiguration = JSON.parse(
Buffer.from(configuration.Labels['coolify.configuration'], 'base64').toString()
);
if (
parsedConfiguration &&
configuration.Labels['coolify.type'] === 'standalone-application'
) {
const { fqdn, applicationId, port, pullmergeRequestId } = parsedConfiguration;
if (fqdn) {
const found = await getApplicationById({ id: applicationId });
if (found) {
const domain = getDomain(fqdn);
await configureProxyForApplication({
domain,
imageId: pullmergeRequestId
? `${applicationId}-${pullmergeRequestId}`
: applicationId,
applicationId,
port
});
const isHttps = fqdn.startsWith('https://');
if (isHttps) await forceSSLOnApplication({ domain });
await setWwwRedirection(fqdn);
}
}
}
}
}
for (const container of containers) {
const image = container.Image.split(':')[0];
const found = supportedServiceTypesAndVersions.find((a) => a.baseImage === image);
if (found) {
const type = found.name;
const mainPort = found.ports.main;
const id = container.Names[0].replace('/', '');
const service = await db.prisma.service.findUnique({
where: { id },
include: {
destinationDocker: true,
minio: true,
plausibleAnalytics: true,
vscodeserver: true,
wordpress: true
}
});
const { fqdn } = service;
const domain = getDomain(fqdn);
await configureSimpleServiceProxyOn({ id, domain, port: mainPort });
const publicPort = service[type]?.publicPort;
if (publicPort) {
const containerFound = await checkContainer(
destination.engine,
`haproxy-for-${publicPort}`
);
if (!containerFound) {
await startHttpProxy(destination, id, publicPort, 9000);
}
}
}
}
}
}
const services = await prisma.service.findMany({});
// Check Coolify FQDN and configure proxy if needed
const { fqdn } = await db.listSettings();
if (fqdn) {

View File

@ -102,17 +102,22 @@
}
}
async function forceRestartProxy() {
try {
restarting = true;
toast.push('Coolify Proxy restarting...');
await post(`/destinations/${id}/restart.json`, {
engine: destination.engine,
fqdn: settings.fqdn
});
} catch ({ error }) {
setTimeout(() => {
window.location.reload();
}, 5000);
const sure = confirm(
'Are you sure you want to restart the proxy? Everyting will be reconfigured in ~10 sec.'
);
if (sure) {
try {
restarting = true;
toast.push('Coolify Proxy restarting...');
await post(`/destinations/${id}/restart.json`, {
engine: destination.engine,
fqdn: settings.fqdn
});
} catch ({ error }) {
setTimeout(() => {
window.location.reload();
}, 5000);
}
}
}
</script>

View File

@ -15,6 +15,7 @@ import {
import getPort from 'get-port';
import { getDomain } from '$lib/components/common';
import { ErrorHandler } from '$lib/database';
import { makeLabelForServices } from '$lib/buildPacks/common';
export const post: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
@ -63,7 +64,8 @@ export const post: RequestHandler = async (event) => {
environment: config.environmentVariables,
networks: [network],
volumes: [config.volume],
restart: 'always'
restart: 'always',
labels: makeLabelForServices('minio')
}
},
networks: {

View File

@ -12,6 +12,7 @@ import {
} from '$lib/haproxy';
import { getDomain } from '$lib/components/common';
import { ErrorHandler } from '$lib/database';
import { makeLabelForServices } from '$lib/buildPacks/common';
export const post: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
@ -39,7 +40,8 @@ export const post: RequestHandler = async (event) => {
container_name: id,
image: `nocodb/nocodb:${version}`,
networks: [network],
restart: 'always'
restart: 'always',
labels: makeLabelForServices('nocodb')
}
},
networks: {

View File

@ -12,6 +12,7 @@ import {
} from '$lib/haproxy';
import { getDomain } from '$lib/components/common';
import { ErrorHandler } from '$lib/database';
import { makeLabelForServices } from '$lib/buildPacks/common';
export const post: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
@ -82,7 +83,6 @@ export const post: RequestHandler = async (event) => {
const network = destinationDockerId && destinationDocker.network;
const host = getEngine(destinationDocker.engine);
const engine = destinationDocker.engine;
// const labels = await makeLabelForPlausibleAnalytics({ id, })
const { workdir } = await createDirectories({ repository: type, buildId: id });
@ -138,7 +138,8 @@ COPY ./init-db.sh /docker-entrypoint-initdb.d/init-db.sh`;
environment: config.plausibleAnalytics.environmentVariables,
volumes: [config.postgresql.volume],
restart: 'always',
depends_on: [`${id}-postgresql`, `${id}-clickhouse`]
depends_on: [`${id}-postgresql`, `${id}-clickhouse`],
labels: makeLabelForServices('plausibleAnalytics')
},
[`${id}-postgresql`]: {
container_name: `${id}-postgresql`,

View File

@ -12,6 +12,7 @@ import {
} from '$lib/haproxy';
import { getDomain } from '$lib/components/common';
import { getServiceImage, ErrorHandler } from '$lib/database';
import { makeLabelForServices } from '$lib/buildPacks/common';
export const post: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
@ -46,7 +47,8 @@ export const post: RequestHandler = async (event) => {
image: config.image,
networks: [network],
volumes: [config.volume],
restart: 'always'
restart: 'always',
labels: makeLabelForServices('vaultWarden')
}
},
networks: {

View File

@ -12,6 +12,7 @@ import {
} from '$lib/haproxy';
import { getDomain } from '$lib/components/common';
import { ErrorHandler } from '$lib/database';
import { makeLabelForServices } from '$lib/buildPacks/common';
export const post: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
@ -54,7 +55,8 @@ export const post: RequestHandler = async (event) => {
environment: config.environmentVariables,
networks: [network],
volumes: [config.volume],
restart: 'always'
restart: 'always',
labels: makeLabelForServices('vscodeServer')
}
},
networks: {

View File

@ -12,6 +12,7 @@ import {
} from '$lib/haproxy';
import { getDomain } from '$lib/components/common';
import { ErrorHandler } from '$lib/database';
import { makeLabelForServices } from '$lib/buildPacks/common';
export const post: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
@ -78,7 +79,8 @@ export const post: RequestHandler = async (event) => {
environment: config.wordpress.environmentVariables,
networks: [network],
restart: 'always',
depends_on: [`${id}-mysql`]
depends_on: [`${id}-mysql`],
labels: makeLabelForServices('wordpress')
},
[`${id}-mysql`]: {
container_name: `${id}-mysql`,