fix: no variables in template
feat: hostPort proxy conf from template
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import cuid from "cuid";
|
||||
import { decrypt, encrypt, fixType, generatePassword, prisma } from "./lib/common";
|
||||
import { decrypt, encrypt, fixType, generatePassword, generateToken, prisma } from "./lib/common";
|
||||
import { getTemplates } from "./lib/services";
|
||||
|
||||
export async function migrateApplicationPersistentStorage() {
|
||||
@@ -83,39 +83,42 @@ export async function migrateServicesToNewTemplate() {
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
|
||||
if (template.variables.length > 0) {
|
||||
if (template.variables) {
|
||||
if (template.variables.length > 0) {
|
||||
for (const variable of template.variables) {
|
||||
const { defaultValue } = variable;
|
||||
const regex = /^\$\$.*\((\d+)\)$/g;
|
||||
const length = Number(regex.exec(defaultValue)?.[1]) || undefined
|
||||
if (variable.defaultValue.startsWith('$$generate_password')) {
|
||||
variable.value = generatePassword({ length });
|
||||
} else if (variable.defaultValue.startsWith('$$generate_hex')) {
|
||||
variable.value = generatePassword({ length, isHex: true });
|
||||
} else if (variable.defaultValue.startsWith('$$generate_username')) {
|
||||
variable.value = cuid();
|
||||
} else if (variable.defaultValue.startsWith('$$generate_token')) {
|
||||
variable.value = generateToken()
|
||||
} else {
|
||||
variable.value = variable.defaultValue || '';
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const variable of template.variables) {
|
||||
const { defaultValue } = variable;
|
||||
const regex = /^\$\$.*\((\d+)\)$/g;
|
||||
const length = Number(regex.exec(defaultValue)?.[1]) || undefined
|
||||
if (variable.defaultValue.startsWith('$$generate_password')) {
|
||||
variable.value = generatePassword({ length });
|
||||
} else if (variable.defaultValue.startsWith('$$generate_hex')) {
|
||||
variable.value = generatePassword({ length, isHex: true });
|
||||
} else if (variable.defaultValue.startsWith('$$generate_username')) {
|
||||
variable.value = cuid();
|
||||
} else {
|
||||
variable.value = variable.defaultValue || '';
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const variable of template.variables) {
|
||||
if (variable.id.startsWith('$$secret_')) {
|
||||
const found = await prisma.serviceSecret.findFirst({ where: { name: variable.name, serviceId: id } })
|
||||
if (!found) {
|
||||
await prisma.serviceSecret.create({
|
||||
data: { name: variable.name, value: encrypt(variable.value) || '', service: { connect: { id } } }
|
||||
})
|
||||
}
|
||||
if (variable.id.startsWith('$$secret_')) {
|
||||
const found = await prisma.serviceSecret.findFirst({ where: { name: variable.name, serviceId: id } })
|
||||
if (!found) {
|
||||
await prisma.serviceSecret.create({
|
||||
data: { name: variable.name, value: encrypt(variable.value) || '', service: { connect: { id } } }
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
if (variable.id.startsWith('$$config_')) {
|
||||
const found = await prisma.serviceSetting.findFirst({ where: { name: variable.name, serviceId: id } })
|
||||
if (!found) {
|
||||
await prisma.serviceSetting.create({
|
||||
data: { name: variable.name, value: variable.value.toString(), variableName: variable.id, service: { connect: { id } } }
|
||||
})
|
||||
}
|
||||
if (variable.id.startsWith('$$config_')) {
|
||||
const found = await prisma.serviceSetting.findFirst({ where: { name: variable.name, serviceId: id } })
|
||||
if (!found) {
|
||||
await prisma.serviceSetting.create({
|
||||
data: { name: variable.name, value: variable.value.toString(), variableName: variable.id, service: { connect: { id } } }
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@ import { promises as dns } from 'dns';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import os from 'os';
|
||||
import sshConfig from 'ssh-config';
|
||||
|
||||
import jsonwebtoken from 'jsonwebtoken';
|
||||
import { checkContainer, removeContainer } from './docker';
|
||||
import { day } from './dayjs';
|
||||
import { saveBuildLog } from './buildPacks/common';
|
||||
@@ -722,6 +722,11 @@ export async function listSettings(): Promise<any> {
|
||||
return settings;
|
||||
}
|
||||
|
||||
export function generateToken() {
|
||||
return jsonwebtoken.sign({
|
||||
nbf: Math.floor(Date.now() / 1000) - 30,
|
||||
}, process.env['COOLIFY_SECRET_KEY'])
|
||||
}
|
||||
export function generatePassword({
|
||||
length = 24,
|
||||
symbols = false,
|
||||
@@ -1614,7 +1619,7 @@ export function persistentVolumes(id, persistentStorage, config) {
|
||||
for (const [key, value] of Object.entries(config)) {
|
||||
if (value.volumes) {
|
||||
for (const volume of value.volumes) {
|
||||
if (!volume.startsWith('/var/run/docker.sock')) {
|
||||
if (!volume.startsWith('/')) {
|
||||
volumeSet.add(volume);
|
||||
}
|
||||
}
|
||||
|
@@ -103,9 +103,19 @@ export async function startService(request: FastifyRequest<ServiceStartStop>, fa
|
||||
}
|
||||
}
|
||||
}
|
||||
let port = null
|
||||
if (template.services[s].ports?.length > 0) {
|
||||
port = template.services[s].ports[0]
|
||||
let ports = []
|
||||
if (template.services[s].proxy?.length > 0) {
|
||||
for (const proxy of template.services[s].proxy) {
|
||||
if (proxy.hostPort) {
|
||||
ports.push(`${proxy.hostPort}:${proxy.port}`)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (template.services[s].ports?.length === 1) {
|
||||
for (const port of template.services[s].ports) {
|
||||
ports.push(`${exposePort}:${exposePort}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
let image = template.services[s].image
|
||||
if (arm && template.services[s].imageArm) {
|
||||
@@ -118,7 +128,7 @@ export async function startService(request: FastifyRequest<ServiceStartStop>, fa
|
||||
entrypoint: template.services[s]?.entrypoint,
|
||||
image,
|
||||
expose: template.services[s].ports,
|
||||
...(exposePort && port ? { ports: [`${exposePort}:${port}`] } : {}),
|
||||
ports,
|
||||
volumes: Array.from(volumes),
|
||||
environment: newEnvironments,
|
||||
depends_on: template.services[s]?.depends_on,
|
||||
@@ -128,7 +138,6 @@ export async function startService(request: FastifyRequest<ServiceStartStop>, fa
|
||||
labels: makeLabelForServices(type),
|
||||
...defaultComposeConfiguration(network),
|
||||
}
|
||||
|
||||
// Generate files for builds
|
||||
if (template.services[s]?.files?.length > 0) {
|
||||
if (!config[s].build) {
|
||||
@@ -182,7 +191,6 @@ export async function startService(request: FastifyRequest<ServiceStartStop>, fa
|
||||
`docker container ls -a --filter 'name=${id}-' --format {{.ID}}|xargs -r -n 1 docker container rm -f`
|
||||
});
|
||||
} catch (error) { }
|
||||
|
||||
}
|
||||
return {}
|
||||
} catch ({ status, message }) {
|
||||
|
@@ -4,7 +4,7 @@ import yaml from 'js-yaml';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import cuid from 'cuid';
|
||||
|
||||
import { prisma, uniqueName, asyncExecShell, getServiceFromDB, getContainerUsage, isDomainConfigured, fixType, decrypt, encrypt, ComposeFile, getFreePublicPort, getDomain, errorHandler, generatePassword, isDev, stopTcpHttpProxy, executeDockerCmd, checkDomainsIsValidInDNS, checkExposedPort, listSettings } from '../../../../lib/common';
|
||||
import { prisma, uniqueName, asyncExecShell, getServiceFromDB, getContainerUsage, isDomainConfigured, fixType, decrypt, encrypt, ComposeFile, getFreePublicPort, getDomain, errorHandler, generatePassword, isDev, stopTcpHttpProxy, executeDockerCmd, checkDomainsIsValidInDNS, checkExposedPort, listSettings, generateToken } from '../../../../lib/common';
|
||||
import { day } from '../../../../lib/dayjs';
|
||||
import { checkContainer, } from '../../../../lib/docker';
|
||||
import { removeService } from '../../../../lib/services/common';
|
||||
@@ -159,13 +159,17 @@ export async function parseAndFindServiceTemplates(service: any, workdir?: strin
|
||||
files: value?.files,
|
||||
environment: [],
|
||||
fqdns: [],
|
||||
hostPorts: [],
|
||||
proxy: {}
|
||||
}
|
||||
if (value.environment?.length > 0) {
|
||||
for (const env of value.environment) {
|
||||
let [envKey, ...envValue] = env.split('=')
|
||||
envValue = envValue.join("=")
|
||||
const variable = foundTemplate.variables.find(v => v.name === envKey) || foundTemplate.variables.find(v => v.id === envValue)
|
||||
let variable = null
|
||||
if (foundTemplate?.variables) {
|
||||
variable = foundTemplate?.variables.find(v => v.name === envKey) || foundTemplate?.variables.find(v => v.id === envValue)
|
||||
}
|
||||
if (variable) {
|
||||
const id = variable.id.replaceAll('$$', '')
|
||||
const label = variable?.label
|
||||
@@ -191,7 +195,7 @@ export async function parseAndFindServiceTemplates(service: any, workdir?: strin
|
||||
if (value?.proxy && value.proxy.length > 0) {
|
||||
for (const proxyValue of value.proxy) {
|
||||
if (proxyValue.domain) {
|
||||
const variable = foundTemplate.variables.find(v => v.id === proxyValue.domain)
|
||||
const variable = foundTemplate?.variables.find(v => v.id === proxyValue.domain)
|
||||
if (variable) {
|
||||
const { id, name, label, description, defaultValue, required = false } = variable
|
||||
const found = await prisma.serviceSetting.findFirst({ where: { serviceId: service.id, variableName: proxyValue.domain } })
|
||||
@@ -199,7 +203,16 @@ export async function parseAndFindServiceTemplates(service: any, workdir?: strin
|
||||
{ id, name, value: found?.value || '', label, description, defaultValue, required }
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
if (proxyValue.hostPort) {
|
||||
const variable = foundTemplate?.variables.find(v => v.id === proxyValue.hostPort)
|
||||
if (variable) {
|
||||
const { id, name, label, description, defaultValue, required = false } = variable
|
||||
const found = await prisma.serviceSetting.findFirst({ where: { serviceId: service.id, variableName: proxyValue.hostPort } })
|
||||
parsedTemplate[realKey].hostPorts.push(
|
||||
{ id, name, value: found?.value || '', label, description, defaultValue, required }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,6 +238,8 @@ export async function parseAndFindServiceTemplates(service: any, workdir?: strin
|
||||
const regex = new RegExp(`\\$\\$config_${variableName.replace('$$config_', '')}`, 'gi')
|
||||
if (value === '$$generate_fqdn') {
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(regex, service.fqdn || '')
|
||||
} else if (value === '$$generate_fqdn_slash') {
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(regex, service.fqdn + '/')
|
||||
} else if (value === '$$generate_domain') {
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(regex, getDomain(service.fqdn))
|
||||
} else if (service.destinationDocker?.network && value === '$$generate_network') {
|
||||
@@ -297,42 +312,46 @@ export async function saveServiceType(request: FastifyRequest<SaveServiceType>,
|
||||
let foundTemplate = templates.find(t => fixType(t.type) === fixType(type))
|
||||
if (foundTemplate) {
|
||||
foundTemplate = JSON.parse(JSON.stringify(foundTemplate).replaceAll('$$id', id))
|
||||
if (foundTemplate.variables.length > 0) {
|
||||
if (foundTemplate.variables) {
|
||||
if (foundTemplate.variables.length > 0) {
|
||||
for (const variable of foundTemplate.variables) {
|
||||
const { defaultValue } = variable;
|
||||
const regex = /^\$\$.*\((\d+)\)$/g;
|
||||
const length = Number(regex.exec(defaultValue)?.[1]) || undefined
|
||||
if (variable.defaultValue.startsWith('$$generate_password')) {
|
||||
variable.value = generatePassword({ length });
|
||||
} else if (variable.defaultValue.startsWith('$$generate_hex')) {
|
||||
variable.value = generatePassword({ length, isHex: true });
|
||||
} else if (variable.defaultValue.startsWith('$$generate_username')) {
|
||||
variable.value = cuid();
|
||||
} else if (variable.defaultValue.startsWith('$$generate_token')) {
|
||||
variable.value = generateToken()
|
||||
} else {
|
||||
variable.value = variable.defaultValue || '';
|
||||
}
|
||||
const foundVariableSomewhereElse = foundTemplate.variables.find(v => v.defaultValue.includes(variable.id))
|
||||
if (foundVariableSomewhereElse) {
|
||||
foundVariableSomewhereElse.value = foundVariableSomewhereElse.value.replaceAll(variable.id, variable.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const variable of foundTemplate.variables) {
|
||||
const { defaultValue } = variable;
|
||||
const regex = /^\$\$.*\((\d+)\)$/g;
|
||||
const length = Number(regex.exec(defaultValue)?.[1]) || undefined
|
||||
if (variable.defaultValue.startsWith('$$generate_password')) {
|
||||
variable.value = generatePassword({ length });
|
||||
} else if (variable.defaultValue.startsWith('$$generate_hex')) {
|
||||
variable.value = generatePassword({ length, isHex: true });
|
||||
} else if (variable.defaultValue.startsWith('$$generate_username')) {
|
||||
variable.value = cuid();
|
||||
} else {
|
||||
variable.value = variable.defaultValue || '';
|
||||
}
|
||||
const foundVariableSomewhereElse = foundTemplate.variables.find(v => v.defaultValue.includes(variable.id))
|
||||
if (foundVariableSomewhereElse) {
|
||||
foundVariableSomewhereElse.value = foundVariableSomewhereElse.value.replaceAll(variable.id, variable.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const variable of foundTemplate.variables) {
|
||||
if (variable.id.startsWith('$$secret_')) {
|
||||
const found = await prisma.serviceSecret.findFirst({ where: { name: variable.name, serviceId: id } })
|
||||
if (!found) {
|
||||
await prisma.serviceSecret.create({
|
||||
data: { name: variable.name, value: encrypt(variable.value) || '', service: { connect: { id } } }
|
||||
})
|
||||
}
|
||||
if (variable.id.startsWith('$$secret_')) {
|
||||
const found = await prisma.serviceSecret.findFirst({ where: { name: variable.name, serviceId: id } })
|
||||
if (!found) {
|
||||
await prisma.serviceSecret.create({
|
||||
data: { name: variable.name, value: encrypt(variable.value) || '', service: { connect: { id } } }
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
if (variable.id.startsWith('$$config_')) {
|
||||
const found = await prisma.serviceSetting.findFirst({ where: { name: variable.name, serviceId: id } })
|
||||
if (!found) {
|
||||
await prisma.serviceSetting.create({
|
||||
data: { name: variable.name, value: variable.value.toString(), variableName: variable.id, service: { connect: { id } } }
|
||||
})
|
||||
}
|
||||
if (variable.id.startsWith('$$config_')) {
|
||||
const found = await prisma.serviceSetting.findFirst({ where: { name: variable.name, serviceId: id } })
|
||||
if (!found) {
|
||||
await prisma.serviceSetting.create({
|
||||
data: { name: variable.name, value: variable.value.toString(), variableName: variable.id, service: { connect: { id } } }
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -538,7 +557,7 @@ export async function saveService(request: FastifyRequest<SaveService>, reply: F
|
||||
}
|
||||
if (isNew) {
|
||||
if (!variableName) {
|
||||
variableName = foundTemplate.variables.find(v => v.name === name).id
|
||||
variableName = foundTemplate?.variables.find(v => v.name === name).id
|
||||
}
|
||||
await prisma.serviceSetting.create({ data: { name, value, variableName, service: { connect: { id } } } })
|
||||
}
|
||||
|
@@ -395,8 +395,8 @@ export async function proxyConfiguration(request: FastifyRequest<OnlyId>, remote
|
||||
}
|
||||
found = JSON.parse(JSON.stringify(found).replaceAll('$$id', id));
|
||||
for (const oneService of Object.keys(found.services)) {
|
||||
const isProxyConfiguration = found.services[oneService].proxy;
|
||||
if (isProxyConfiguration) {
|
||||
const isDomainConfiguration = found.services[oneService].proxy && found.services[oneService].proxy.filter(p => p.domain);
|
||||
if (isDomainConfiguration.length > 0) {
|
||||
const { proxy } = found.services[oneService];
|
||||
for (let configuration of proxy) {
|
||||
if (configuration.domain) {
|
||||
@@ -431,20 +431,24 @@ export async function proxyConfiguration(request: FastifyRequest<OnlyId>, remote
|
||||
}
|
||||
} else {
|
||||
if (found.services[oneService].ports && found.services[oneService].ports.length > 0) {
|
||||
let port = found.services[oneService].ports[0]
|
||||
const foundPortVariable = serviceSetting.find((a) => a.name.toLowerCase() === 'port')
|
||||
if (foundPortVariable) {
|
||||
port = foundPortVariable.value
|
||||
for (let [index, port] of found.services[oneService].ports.entries()) {
|
||||
if (port == 22) continue;
|
||||
if (index === 0) {
|
||||
const foundPortVariable = serviceSetting.find((a) => a.name.toLowerCase() === 'port')
|
||||
if (foundPortVariable) {
|
||||
port = foundPortVariable.value
|
||||
}
|
||||
}
|
||||
const domain = getDomain(fqdn);
|
||||
const nakedDomain = domain.replace(/^www\./, '');
|
||||
const isHttps = fqdn.startsWith('https://');
|
||||
const isWWW = fqdn.includes('www.');
|
||||
const pathPrefix = '/'
|
||||
const isCustomSSL = false
|
||||
const serviceId = `${oneService}-${port || 'default'}`
|
||||
traefik.http.routers = { ...traefik.http.routers, ...generateRouters(serviceId, domain, nakedDomain, pathPrefix, isHttps, isWWW, dualCerts, isCustomSSL) }
|
||||
traefik.http.services = { ...traefik.http.services, ...generateServices(serviceId, id, port) }
|
||||
}
|
||||
const domain = getDomain(fqdn);
|
||||
const nakedDomain = domain.replace(/^www\./, '');
|
||||
const isHttps = fqdn.startsWith('https://');
|
||||
const isWWW = fqdn.includes('www.');
|
||||
const pathPrefix = '/'
|
||||
const isCustomSSL = false
|
||||
const serviceId = `${oneService}-${port || 'default'}`
|
||||
traefik.http.routers = { ...traefik.http.routers, ...generateRouters(serviceId, domain, nakedDomain, pathPrefix, isHttps, isWWW, dualCerts, isCustomSSL) }
|
||||
traefik.http.services = { ...traefik.http.services, ...generateServices(serviceId, id, port) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user