fixes
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: 1.0.3
|
||||
type: appwrite
|
||||
name: Appwrite
|
||||
documentation: https://appwrite.io/docs
|
||||
description: Secure Backend Server for Web, Mobile & Flutter Developers.
|
||||
@@ -1035,6 +1036,7 @@
|
||||
The default value is 15 minutes.
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: latest
|
||||
type: weblate
|
||||
name: Weblate
|
||||
description: ''
|
||||
services:
|
||||
@@ -1087,7 +1089,7 @@
|
||||
label: Weblate Admin Password
|
||||
defaultValue: $$generate_password
|
||||
description: ''
|
||||
showOnUI: true
|
||||
showOnConfiguration: true
|
||||
- id: $$config_postgres_user
|
||||
main: $$id-postgresql
|
||||
name: POSTGRES_USER
|
||||
@@ -1100,7 +1102,7 @@
|
||||
label: PostgreSQL Password
|
||||
defaultValue: $$generate_password
|
||||
description: ''
|
||||
showOnUI: true
|
||||
showOnConfiguration: true
|
||||
- id: $$config_postgres_db
|
||||
main: $$id-postgresql
|
||||
name: POSTGRES_DB
|
||||
@@ -1109,6 +1111,7 @@
|
||||
description: ''
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: 2022.10.14-1a5b0965
|
||||
type: searxng
|
||||
name: SearXNG
|
||||
description: ''
|
||||
services:
|
||||
@@ -1181,6 +1184,7 @@
|
||||
description: ''
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: v2.0.6
|
||||
type: glitchtip
|
||||
name: GlitchTip
|
||||
description: ''
|
||||
services:
|
||||
@@ -1344,6 +1348,7 @@
|
||||
description: ''
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: v2.13.0
|
||||
type: hasura
|
||||
name: Hasura
|
||||
description: 'Instant realtime GraphQL APIs on any Postgres application, existing or new.'
|
||||
services:
|
||||
@@ -1388,7 +1393,7 @@
|
||||
label: Hasura Admin Password
|
||||
defaultValue: $$generate_password
|
||||
description: ''
|
||||
showOnUI: true
|
||||
showOnConfiguration: true
|
||||
- id: $$config_postgres_user
|
||||
name: POSTGRES_USER
|
||||
label: PostgreSQL User
|
||||
@@ -1406,6 +1411,7 @@
|
||||
description: ''
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: postgresql-v1.38.0
|
||||
type: umami
|
||||
name: Umami
|
||||
description: >-
|
||||
Umami is a simple, easy to use, self-hosted web analytics solution. The goal
|
||||
@@ -1606,9 +1612,10 @@
|
||||
label: Initial Admin Password
|
||||
defaultValue: $$generate_password
|
||||
description: ''
|
||||
showOnUI: true
|
||||
showOnConfiguration: true
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: v0.29.1
|
||||
type: meilisearch
|
||||
name: MeiliSearch
|
||||
description: >-
|
||||
MeiliSearch is a lightning Fast, Ultra Relevant, and Typo-Tolerant Search
|
||||
@@ -1634,9 +1641,10 @@
|
||||
label: Master Key
|
||||
defaultValue: $$generate_hex(64)
|
||||
description: ''
|
||||
showOnUI: true
|
||||
showOnConfiguration: true
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: latest
|
||||
type: ghost
|
||||
name: Ghost
|
||||
description: >-
|
||||
Ghost is a free and open source blogging platform written in JavaScript and
|
||||
@@ -1749,8 +1757,9 @@
|
||||
description: ''
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: php8.1
|
||||
name: WordPress
|
||||
description: WordPress is a content management system based on PHP.
|
||||
type: wordpress
|
||||
name: WordPress (with MySQL)
|
||||
description: WordPress is a content management system based on PHP with new MySQL database.
|
||||
services:
|
||||
$$id:
|
||||
name: WordPress
|
||||
@@ -1789,53 +1798,138 @@
|
||||
label: WordPress DB Host
|
||||
defaultValue: $$id-mysql
|
||||
description: ''
|
||||
readonly: true
|
||||
- id: $$config_wordpress_db_user
|
||||
name: WORDPRESS_DB_USER
|
||||
label: WordPress DB User
|
||||
defaultValue: $$config_mysql_user
|
||||
description: ''
|
||||
readonly: true
|
||||
- id: $$secret_wordpress_db_password
|
||||
name: WORDPRESS_DB_PASSWORD
|
||||
label: WordPress DB Password
|
||||
defaultValue: $$secret_mysql_password
|
||||
description: ''
|
||||
readonly: true
|
||||
- id: $$config_wordpress_db_name
|
||||
name: WORDPRESS_DB_NAME
|
||||
label: WordPress DB Name
|
||||
defaultValue: $$config_mysql_database
|
||||
description: ''
|
||||
readonly: true
|
||||
- id: $$config_wordpress_config_extra
|
||||
name: WORDPRESS_CONFIG_EXTRA
|
||||
label: WordPress Config Extra
|
||||
defaultValue: ''
|
||||
description: ''
|
||||
type: 'textarea'
|
||||
placeholder: |
|
||||
define('WP_DEBUG', true);
|
||||
define('WP_DEBUG_LOG', true);
|
||||
define('WP_DEBUG_DISPLAY', false);
|
||||
@ini_set('display_errors', 0);
|
||||
- id: $$secret_mysql_root_password
|
||||
name: MYSQL_ROOT_PASSWORD
|
||||
label: MySQL Root Password
|
||||
defaultValue: $$generate_password
|
||||
description: ''
|
||||
readonly: true
|
||||
- id: $$config_mysql_root_user
|
||||
name: MYSQL_ROOT_USER
|
||||
label: MySQL Root User
|
||||
defaultValue: $$generate_username
|
||||
description: ''
|
||||
readonly: true
|
||||
- id: $$config_mysql_database
|
||||
name: MYSQL_DATABASE
|
||||
label: MySQL Database
|
||||
defaultValue: wordpress
|
||||
description: ''
|
||||
readonly: true
|
||||
- id: $$config_mysql_user
|
||||
name: MYSQL_USER
|
||||
label: MySQL User
|
||||
defaultValue: $$generate_username
|
||||
description: ''
|
||||
readonly: true
|
||||
- id: $$secret_mysql_password
|
||||
name: MYSQL_PASSWORD
|
||||
label: MySQL Password
|
||||
defaultValue: $$generate_password
|
||||
description: ''
|
||||
readonly: true
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: php8.1
|
||||
type: wordpress-only
|
||||
name: WordPress (without MySQL)
|
||||
description: WordPress is a content management system based on PHP without MySQL.
|
||||
services:
|
||||
$$id:
|
||||
name: WordPress
|
||||
documentation: 'Taken from https://docs.docker.com/compose/wordpress/'
|
||||
image: 'wordpress:$$core_version'
|
||||
volumes:
|
||||
- '$$id-wordpress-data:/var/www/html'
|
||||
environment:
|
||||
- WORDPRESS_DB_HOST=$$config_wordpress_db_host
|
||||
- WORDPRESS_DB_PORT=$$config_wordpress_db_port
|
||||
- WORDPRESS_DB_USER=$$config_wordpress_db_user
|
||||
- WORDPRESS_DB_PASSWORD=$$secret_wordpress_db_password
|
||||
- WORDPRESS_DB_NAME=$$config_wordpress_db_name
|
||||
- WORDPRESS_CONFIG_EXTRA=$$config_wordpress_config_extra
|
||||
ports:
|
||||
- '80'
|
||||
variables:
|
||||
- id: $$config_wordpress_db_host
|
||||
name: WORDPRESS_DB_HOST
|
||||
label: Database Host
|
||||
defaultValue: ''
|
||||
description: ''
|
||||
placeholder: 'db.coollabs.io'
|
||||
required: true
|
||||
- id: $$config_wordpress_db_port
|
||||
name: WORDPRESS_DB_PORT
|
||||
label: Database Port
|
||||
defaultValue: ''
|
||||
description: ''
|
||||
placeholder: '3306'
|
||||
required: true
|
||||
- id: $$config_wordpress_db_user
|
||||
name: WORDPRESS_DB_USER
|
||||
label: Database User
|
||||
defaultValue: ''
|
||||
description: ''
|
||||
placeholder: 'wordpress'
|
||||
required: true
|
||||
- id: $$secret_wordpress_db_password
|
||||
name: WORDPRESS_DB_PASSWORD
|
||||
label: Database Password
|
||||
defaultValue: ''
|
||||
description: ''
|
||||
placeholder: 'supers3cr3tpassw0rd!'
|
||||
required: true
|
||||
showOnConfiguration: true
|
||||
- id: $$config_wordpress_db_name
|
||||
name: WORDPRESS_DB_NAME
|
||||
label: Database Name
|
||||
defaultValue: ''
|
||||
description: ''
|
||||
placeholder: 'wordpress'
|
||||
required: true
|
||||
- id: $$config_wordpress_config_extra
|
||||
name: WORDPRESS_CONFIG_EXTRA
|
||||
label: Extra Config
|
||||
defaultValue: ''
|
||||
description: ''
|
||||
type: 'textarea'
|
||||
placeholder: |
|
||||
define('WP_DEBUG', true);
|
||||
define('WP_DEBUG_LOG', true);
|
||||
define('WP_DEBUG_DISPLAY', false);
|
||||
@ini_set('display_errors', 0);
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: 4.7.1
|
||||
type: vscodeserver
|
||||
name: VSCode Server
|
||||
description: >-
|
||||
vscode-server by Coder is VS Code running on a remote server, accessible
|
||||
@@ -1861,9 +1955,10 @@
|
||||
label: Password
|
||||
defaultValue: $$generate_password
|
||||
description: ''
|
||||
showOnUI: true
|
||||
showOnConfiguration: true
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: RELEASE.2022-10-15T19-57-03Z
|
||||
type: minio
|
||||
name: MinIO
|
||||
description: ' MinIO is a cloud storage server compatible with Amazon S3'
|
||||
services:
|
||||
@@ -1915,9 +2010,10 @@
|
||||
label: Root User Password
|
||||
defaultValue: $$generate_password
|
||||
description: ''
|
||||
showOnUI: true
|
||||
showOnConfiguration: true
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: 0.21.1
|
||||
type: fider
|
||||
name: Fider
|
||||
description: Fider is a platform to collect and organize customer feedback.
|
||||
services:
|
||||
@@ -2032,6 +2128,7 @@
|
||||
description: ''
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: 0.198.1
|
||||
type: n8nio
|
||||
name: n8n.io
|
||||
description: n8n is a free and open node based Workflow Automation Tool.
|
||||
services:
|
||||
@@ -2056,6 +2153,7 @@
|
||||
description: ''
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: stable
|
||||
type: plausibleanalytics
|
||||
name: Plausible Analytics
|
||||
description: Plausible is a lightweight and open-source website analytics tool.
|
||||
services:
|
||||
@@ -2157,7 +2255,7 @@
|
||||
label: Admin User Password
|
||||
defaultValue: $$generate_password
|
||||
description: This is the admin password. Please change it.
|
||||
showOnUI: true
|
||||
showOnConfiguration: true
|
||||
- id: $$secret_secret_key_base
|
||||
name: SECRET_KEY_BASE
|
||||
label: Secret Key Base
|
||||
@@ -2185,7 +2283,7 @@
|
||||
label: PostgreSQL Password
|
||||
defaultValue: $$generate_password
|
||||
description: ''
|
||||
showOnUI: true
|
||||
showOnConfiguration: true
|
||||
- id: $$config_postgresql_database
|
||||
main: $$id-postgresql
|
||||
name: POSTGRESQL_DATABASE
|
||||
@@ -2199,6 +2297,7 @@
|
||||
description: This is the default script name.
|
||||
- templateVersion: 1.0.0
|
||||
defaultVersion: 0.98.1
|
||||
type: nocodb
|
||||
name: NocoDB
|
||||
description: >-
|
||||
The Open Source Airtable Alternative - Turns any MySQL, PostgreSQL, SQL
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
-- RedefineTables
|
||||
PRAGMA foreign_keys=OFF;
|
||||
CREATE TABLE "new_Wordpress" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"extraConfig" TEXT,
|
||||
"tablePrefix" TEXT,
|
||||
"ownMysql" BOOLEAN NOT NULL DEFAULT false,
|
||||
"mysqlHost" TEXT,
|
||||
"mysqlPort" INTEGER,
|
||||
"mysqlUser" TEXT,
|
||||
"mysqlPassword" TEXT,
|
||||
"mysqlRootUser" TEXT,
|
||||
"mysqlRootUserPassword" TEXT,
|
||||
"mysqlDatabase" TEXT,
|
||||
"mysqlPublicPort" INTEGER,
|
||||
"ftpEnabled" BOOLEAN NOT NULL DEFAULT false,
|
||||
"ftpUser" TEXT,
|
||||
"ftpPassword" TEXT,
|
||||
"ftpPublicPort" INTEGER,
|
||||
"ftpHostKey" TEXT,
|
||||
"ftpHostKeyPrivate" TEXT,
|
||||
"serviceId" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "Wordpress_serviceId_fkey" FOREIGN KEY ("serviceId") REFERENCES "Service" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
INSERT INTO "new_Wordpress" ("createdAt", "extraConfig", "ftpEnabled", "ftpHostKey", "ftpHostKeyPrivate", "ftpPassword", "ftpPublicPort", "ftpUser", "id", "mysqlDatabase", "mysqlHost", "mysqlPassword", "mysqlPort", "mysqlPublicPort", "mysqlRootUser", "mysqlRootUserPassword", "mysqlUser", "ownMysql", "serviceId", "tablePrefix", "updatedAt") SELECT "createdAt", "extraConfig", "ftpEnabled", "ftpHostKey", "ftpHostKeyPrivate", "ftpPassword", "ftpPublicPort", "ftpUser", "id", "mysqlDatabase", "mysqlHost", "mysqlPassword", "mysqlPort", "mysqlPublicPort", "mysqlRootUser", "mysqlRootUserPassword", "mysqlUser", "ownMysql", "serviceId", "tablePrefix", "updatedAt" FROM "Wordpress";
|
||||
DROP TABLE "Wordpress";
|
||||
ALTER TABLE "new_Wordpress" RENAME TO "Wordpress";
|
||||
CREATE UNIQUE INDEX "Wordpress_serviceId_key" ON "Wordpress"("serviceId");
|
||||
PRAGMA foreign_key_check;
|
||||
PRAGMA foreign_keys=ON;
|
||||
@@ -480,10 +480,10 @@ model Wordpress {
|
||||
ownMysql Boolean @default(false)
|
||||
mysqlHost String?
|
||||
mysqlPort Int?
|
||||
mysqlUser String
|
||||
mysqlPassword String
|
||||
mysqlRootUser String
|
||||
mysqlRootUserPassword String
|
||||
mysqlUser String?
|
||||
mysqlPassword String?
|
||||
mysqlRootUser String?
|
||||
mysqlRootUserPassword String?
|
||||
mysqlDatabase String?
|
||||
mysqlPublicPort Int?
|
||||
ftpEnabled Boolean @default(false)
|
||||
|
||||
@@ -8,6 +8,7 @@ const template = yaml.load(templateYml)
|
||||
const newTemplate = {
|
||||
"templateVersion": "1.0.0",
|
||||
"defaultVersion": "latest",
|
||||
"type": "",
|
||||
"name": "",
|
||||
"description": "",
|
||||
"services": {
|
||||
@@ -18,6 +19,7 @@ const newTemplate = {
|
||||
const version = template.caproverOneClickApp.variables.find(v => v.id === '$$cap_APP_VERSION' || v.id === '$$cap_version').defaultValue || 'latest'
|
||||
|
||||
newTemplate.name = template.caproverOneClickApp.displayName
|
||||
newTemplate.type = template.caproverOneClickApp.displayName.replaceAll(' ', '').toLowerCase()
|
||||
newTemplate.documentation = template.caproverOneClickApp.documentation
|
||||
newTemplate.description = template.caproverOneClickApp.description
|
||||
newTemplate.defaultVersion = version
|
||||
|
||||
@@ -7,19 +7,32 @@ const templates = await fs.readFile('../devTemplates.yaml', 'utf8');
|
||||
const devTemplates = yaml.load(templates);
|
||||
for (const template of devTemplates) {
|
||||
let image = template.services['$$id'].image.replaceAll(':$$core_version', '');
|
||||
const name = template.name
|
||||
if (!image.includes('/')) {
|
||||
image = `library/${image}`;
|
||||
}
|
||||
repositories.push({ image, name: name.toLowerCase().replaceAll(' ', '') });
|
||||
repositories.push({ image, name: template.type });
|
||||
}
|
||||
const services = []
|
||||
|
||||
const numberOfTags = 30;
|
||||
// const semverRegex = new RegExp(/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/g)
|
||||
const semverRegex = new RegExp(/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/g)
|
||||
for (const repository of repositories) {
|
||||
console.log('Querying', repository.name, 'at', repository.image);
|
||||
let semverRegex = new RegExp(/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/g)
|
||||
if (repository.name.startsWith('wordpress')) {
|
||||
semverRegex = new RegExp(/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)-php(0|[1-9]\d*)$/g)
|
||||
}
|
||||
if (repository.name.startsWith('minio')) {
|
||||
semverRegex = new RegExp(/^RELEASE.*$/g)
|
||||
}
|
||||
if (repository.name.startsWith('fider')) {
|
||||
semverRegex = new RegExp(/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)-([0-9]+)$/g)
|
||||
}
|
||||
if (repository.name.startsWith('searxng')) {
|
||||
semverRegex = new RegExp(/^\d{4}[\.\-](0?[1-9]|[12][0-9]|3[01])[\.\-](0?[1-9]|1[012]).*$/)
|
||||
}
|
||||
if (repository.name.startsWith('umami')) {
|
||||
semverRegex = new RegExp(/^postgresql-v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)-([0-9]+)$/g)
|
||||
}
|
||||
if (repository.image.includes('ghcr.io')) {
|
||||
const { execaCommand } = await import('execa');
|
||||
const { stdout } = await execaCommand(`docker run --rm quay.io/skopeo/stable list-tags docker://${repository.image}`);
|
||||
|
||||
@@ -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 } } })
|
||||
}
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user