This commit is contained in:
Andras Bacsai
2022-10-28 11:54:03 +02:00
parent aa27aeafa1
commit dc626bd4f0
20 changed files with 422 additions and 97 deletions

View File

@@ -317,7 +317,9 @@ async function wordpress(service: any, template: any) {
]
await migrateSettings(settings, service, template);
await migrateSecrets(secrets, service);
if (ownMysql) {
await prisma.service.update({ where: { id: service.id }, data: { type: "wordpress-only" } })
}
// Remove old service data
// await prisma.service.update({ where: { id: service.id }, data: { wordpress: { delete: true } } })
}

View File

@@ -42,7 +42,7 @@ export function getAPIUrl() {
if (process.env.CODESANDBOX_HOST) {
return `https://${process.env.CODESANDBOX_HOST.replace(/\$PORT/, '3001')}`;
}
return isDev ? 'http://localhost:3001' : 'http://localhost:3000';
return isDev ? 'http://host.docker.internal:3001' : 'http://localhost:3000';
}
export function getUIUrl() {
@@ -1447,12 +1447,13 @@ export async function getServiceFromDB({
persistentStorage: true,
serviceSecret: true,
serviceSetting: true,
wordpress: true
}
});
if (!body) {
return null
}
body.type = fixType(body.type);
// body.type = fixType(body.type);
if (body?.serviceSecret.length > 0) {
body.serviceSecret = body.serviceSecret.map((s) => {
@@ -1460,6 +1461,9 @@ export async function getServiceFromDB({
return s;
});
}
if (body.wordpress) {
body.wordpress.ftpPassword = decrypt(body.wordpress.ftpPassword);
}
return { ...body, settings };
}

View File

@@ -42,11 +42,16 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
const template: any = await parseAndFindServiceTemplates(service, workdir, true)
const network = destinationDockerId && destinationDocker.network;
const config = {};
for (const service in template.services) {
const isWordpress = type === 'wordpress';
for (const s in template.services) {
if (isWordpress && service.wordpress.ownMysql && s.name === 'MySQL') {
console.log('skipping predefined mysql')
continue;
}
let newEnvironments = []
if (arm) {
if (template.services[service]?.environmentArm?.length > 0) {
for (const environment of template.services[service].environmentArm) {
if (template.services[s]?.environmentArm?.length > 0) {
for (const environment of template.services[s].environmentArm) {
const [env, value] = environment.split("=");
if (!value.startsWith('$$secret') && value !== '') {
newEnvironments.push(`${env}=${value}`)
@@ -54,8 +59,8 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
}
}
} else {
if (template.services[service]?.environment?.length > 0) {
for (const environment of template.services[service].environment) {
if (template.services[s]?.environment?.length > 0) {
for (const environment of template.services[s].environment) {
const [env, value] = environment.split("=");
if (!value.startsWith('$$secret') && value !== '') {
newEnvironments.push(`${env}=${value}`)
@@ -68,7 +73,7 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
for (const secret of secrets) {
const { name, value } = secret
if (value) {
const foundEnv = !!template.services[service].environment?.find(env => env.startsWith(`${name}=`))
const foundEnv = !!template.services[s].environment?.find(env => env.startsWith(`${name}=`))
const foundNewEnv = !!newEnvironments?.find(env => env.startsWith(`${name}=`))
if (foundEnv && !foundNewEnv) {
newEnvironments.push(`${name}=${decrypt(value)}`)
@@ -76,7 +81,7 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
}
}
const customVolumes = await prisma.servicePersistentStorage.findMany({ where: { serviceId: id } })
let volumes = arm ? template.services[service].volumesArm : template.services[service].volumes
let volumes = arm ? template.services[s].volumesArm : template.services[s].volumes
if (customVolumes.length > 0) {
for (const customVolume of customVolumes) {
const { volumeName, path, containerId } = customVolume
@@ -85,41 +90,58 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
}
}
}
config[service] = {
container_name: service,
build: template.services[service].build || undefined,
command: template.services[service].command,
entrypoint: template.services[service]?.entrypoint,
image: arm ? template.services[service].imageArm : template.services[service].image,
expose: template.services[service].ports,
if (isWordpress) {
const { wordpress: { mysqlHost, mysqlPort, mysqlUser, mysqlPassword, mysqlDatabase, ownMysql } } = service
console.log({ mysqlHost, mysqlPort, mysqlUser, mysqlPassword, mysqlDatabase, ownMysql })
if (ownMysql) {
let envsToRemove = ['WORDPRESS_DB_HOST', 'WORDPRESS_DB_USER', 'WORDPRESS_DB_PASSWORD', 'WORDPRESS_DB_NAME']
for (const env of newEnvironments) {
if (envsToRemove.includes(env.split('=')[0])) {
console.log('removing', env)
newEnvironments = newEnvironments.filter(e => e !== env)
}
}
newEnvironments.push(`WORDPRESS_DB_HOST=${mysqlHost}:${mysqlPort}`)
newEnvironments.push(`WORDPRESS_DB_USER=${mysqlUser}`)
newEnvironments.push(`WORDPRESS_DB_PASSWORD=${mysqlPassword}`)
newEnvironments.push(`WORDPRESS_DB_NAME=${mysqlDatabase}`)
}
}
config[s] = {
container_name: s,
build: template.services[s].build || undefined,
command: template.services[s].command,
entrypoint: template.services[s]?.entrypoint,
image: arm ? template.services[s].imageArm : template.services[s].image,
expose: template.services[s].ports,
...(exposePort ? { ports: [`${exposePort}:${exposePort}`] } : {}),
volumes,
environment: newEnvironments,
depends_on: template.services[service]?.depends_on,
ulimits: template.services[service]?.ulimits,
cap_drop: template.services[service]?.cap_drop,
cap_add: template.services[service]?.cap_add,
depends_on: template.services[s]?.depends_on,
ulimits: template.services[s]?.ulimits,
cap_drop: template.services[s]?.cap_drop,
cap_add: template.services[s]?.cap_add,
labels: makeLabelForServices(type),
...defaultComposeConfiguration(network),
}
// Generate files for builds
if (template.services[service]?.files?.length > 0) {
if (!template.services[service].build) {
template.services[service].build = {
if (template.services[s]?.files?.length > 0) {
if (!template.services[s].build) {
template.services[s].build = {
context: workdir,
dockerfile: `Dockerfile.${service}`
dockerfile: `Dockerfile.${s}`
}
}
let Dockerfile = `
FROM ${template.services[service].image}`
for (const file of template.services[service].files) {
FROM ${template.services[s].image}`
for (const file of template.services[s].files) {
const { source, destination, content } = file;
await fs.writeFile(source, content);
Dockerfile += `
COPY ./${path.basename(source)} ${destination}`
}
await fs.writeFile(`${workdir}/Dockerfile.${service}`, Dockerfile);
await fs.writeFile(`${workdir}/Dockerfile.${servsice}`, Dockerfile);
}
}
const { volumeMounts } = persistentVolumes(id, persistentStorage, config)

View File

@@ -113,7 +113,7 @@ export async function getServiceStatus(request: FastifyRequest<OnlyId>) {
}
export async function parseAndFindServiceTemplates(service: any, workdir?: string, isDeploy: boolean = false) {
const templates = await getTemplates()
const foundTemplate = templates.find(t => fixType(t.name) === service.type)
const foundTemplate = templates.find(t => fixType(t.type) === service.type)
let parsedTemplate = {}
if (foundTemplate) {
if (!isDeploy) {
@@ -130,16 +130,21 @@ export async function parseAndFindServiceTemplates(service: any, workdir?: strin
for (const env of value.environment) {
const [envKey, envValue] = env.split('=')
const variable = foundTemplate.variables.find(v => v.name === envKey) || foundTemplate.variables.find(v => v.id === envValue)
const id = variable.id.replaceAll('$$', '')
const label = variable?.label
const description = variable?.description
const defaultValue = variable?.defaultValue
const main = variable?.main || '$$id'
if (envValue.startsWith('$$config') || variable?.showOnUI) {
const type = variable?.type || 'input'
const placeholder = variable?.placeholder || ''
const readonly = variable?.readonly || false
const required = variable?.required || false
if (envValue.startsWith('$$config') || variable?.showOnConfiguration) {
if (envValue.startsWith('$$config_coolify')) {
continue
}
parsedTemplate[realKey].environment.push(
{ name: envKey, value: envValue, main, label, description, defaultValue }
{ id, name: envKey, value: envValue, main, label, description, defaultValue, type, placeholder, required, readonly }
)
}
}
@@ -203,6 +208,9 @@ export async function parseAndFindServiceTemplates(service: any, workdir?: strin
if (value) {
strParsedTemplate = strParsedTemplate.replaceAll(regexHashed, bcrypt.hashSync(value, 10) + "\"")
strParsedTemplate = strParsedTemplate.replaceAll(regex, value + "\"")
} else {
strParsedTemplate = strParsedTemplate.replaceAll(regexHashed, "\"")
strParsedTemplate = strParsedTemplate.replaceAll(regex, "\"")
}
}
}
@@ -249,7 +257,7 @@ export async function saveServiceType(request: FastifyRequest<SaveServiceType>,
const { id } = request.params;
const { type } = request.body;
const templates = await getTemplates()
let foundTemplate = templates.find(t => fixType(t.name) === fixType(type))
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) {
@@ -307,6 +315,10 @@ export async function saveServiceType(request: FastifyRequest<SaveServiceType>,
}
}
await prisma.service.update({ where: { id }, data: { type, version: foundTemplate.defaultVersion, templateVersion: foundTemplate.templateVersion } })
if (type.startsWith('wordpress')) {
await prisma.service.update({ where: { id }, data: { wordpress: { create: {} } } })
}
return reply.code(201).send()
} else {
throw { status: 404, message: 'Service type not found.' }
@@ -480,7 +492,7 @@ export async function saveService(request: FastifyRequest<SaveService>, reply: F
}
const templates = await getTemplates()
const service = await prisma.service.findUnique({ where: { id } })
const foundTemplate = templates.find(t => fixType(t.name) === fixType(service.type))
const foundTemplate = templates.find(t => fixType(t.type) === fixType(service.type))
for (const setting of serviceSetting) {
let { id: settingId, name, value, changed = false, isNew = false, variableName } = setting
if (changed) {
@@ -506,11 +518,19 @@ export async function saveService(request: FastifyRequest<SaveService>, reply: F
export async function getServiceSecrets(request: FastifyRequest<OnlyId>) {
try {
const { id } = request.params
const teamId = request.user.teamId;
const service = await getServiceFromDB({ id, teamId });
let secrets = await prisma.serviceSecret.findMany({
where: { serviceId: id },
orderBy: { createdAt: 'desc' }
});
const templates = await getTemplates()
const foundTemplate = templates.find(t => fixType(t.type) === service.type)
secrets = secrets.map((secret) => {
const foundVariable = foundTemplate?.variables.find(v => v.name === secret.name) || null
if (foundVariable) {
secret.readonly = foundVariable.readonly
}
secret.value = decrypt(secret.value);
return secret;
});

View File

@@ -381,7 +381,7 @@ export async function traefikConfiguration(request, reply) {
} = service;
if (destinationDockerId) {
const templates = await getTemplates();
let found = templates.find((a) => fixType(a.name) === fixType(type));
let found = templates.find((a) => a.type === type);
if (found) {
found = JSON.parse(JSON.stringify(found).replaceAll('$$id', id));
for (const oneService of Object.keys(found.services)) {
@@ -509,7 +509,7 @@ export async function traefikConfiguration(request, reply) {
}
} else {
traefik.http.routers[`${id}-${port || 'default'}`] = generateHttpRouter(`${id}-${port || 'default'}`, nakedDomain, pathPrefix)
traefik.http.routers[`${id}-${port || 'default'}-secure`] = generateProtocolRedirectRouter(`${id}-${port || 'default'}-secure`, nakedDomain, pathPrefix, 'https-to-http')
traefik.http.routers[`${id}-${port || 'default'}-secure`] = generateProtocolRedirectRouter(`${id}-${port || 'default'}`, nakedDomain, pathPrefix, 'https-to-http')
traefik.http.services[`${id}-${port || 'default'}`] = generateLoadBalancerService(id, port)
if (!dualCerts) {
@@ -873,7 +873,7 @@ export async function remoteTraefikConfiguration(request: FastifyRequest<OnlyId>
} = service;
if (destinationDockerId) {
const templates = await getTemplates();
let found = templates.find((a) => fixType(a.name) === fixType(type));
let found = templates.find((a) => a.type === type);
if (found) {
const port = found.ports.main;
const publicPort = service[type]?.publicPort;