diff --git a/apps/api/devTemplates.yaml b/apps/api/devTemplates.yaml index d590e7cf5..84d457d02 100644 --- a/apps/api/devTemplates.yaml +++ b/apps/api/devTemplates.yaml @@ -1130,11 +1130,10 @@ - SETGID - SETUID - DAC_OVERRIDE - extras: - files: - - source: $$workdir/settings.yml - destination: /etc/searxng/settings.yml - content: |2- + files: + - source: $$workdir/settings.yml + destination: /etc/searxng/settings.yml + content: |2- # see https://docs.searxng.org/admin/engines/settings.html#use-default-settings use_default_settings: true @@ -1173,7 +1172,7 @@ - id: $$secret_secret_key name: SECRET_KEY label: Secret Key - defaultValue: $$generate_passphrase + defaultValue: $$generate_hex(64) description: '' - id: $$secret_redis_password name: REDIS_PASSWORD @@ -1439,11 +1438,10 @@ - POSTGRES_PASSWORD=$$secret_postgres_password - POSTGRES_DB=$$config_postgres_db ports: [] - extras: - files: - - source: $$workdir/schema.postgresql.sql - destination: /docker-entrypoint-initdb.d/schema.postgresql.sql - content: |2- + files: + - source: $$workdir/schema.postgresql.sql + destination: /docker-entrypoint-initdb.d/schema.postgresql.sql + content: |2- -- CreateTable CREATE TABLE "account" ( @@ -1586,7 +1584,7 @@ - id: $$secret_hash_salt name: HASH_SALT label: Hash Salt - defaultValue: $$generate_passphrase + defaultValue: $$generate_hex(64) description: '' - id: $$config_postgres_user name: POSTGRES_USER @@ -1634,7 +1632,7 @@ - id: $$secret_meili_master_key name: MEILI_MASTER_KEY label: Master Key - defaultValue: $$generate_passphrase + defaultValue: $$generate_hex(64) description: '' showOnUI: true - templateVersion: 1.0.0 @@ -1967,7 +1965,7 @@ - id: $$secret_jwt_secret name: JWT_SECRET label: JWT Secret - defaultValue: $$generate_passphrase + defaultValue: $$generate_hex(64) description: '' - id: $$config_email_noreply name: EMAIL_NOREPLY @@ -2057,12 +2055,6 @@ defaultVersion: stable name: Plausible Analytics description: Plausible is a lightweight and open-source website analytics tool. - labels: - - analytics - - plausible - - gdpr - - no-cookie - - privacy services: $$id: name: Plausible Analytics @@ -2106,27 +2098,26 @@ nofile: soft: 262144 hard: 262144 - extras: - files: - - source: $$workdir/clickhouse-config.xml - destination: /etc/clickhouse-server/users.d/logging.xml - content: >- + files: + - source: $$workdir/clickhouse-config.xml + destination: /etc/clickhouse-server/users.d/logging.xml + content: >- warningtrue - - source: $$workdir/clickhouse-user-config.xml - destination: /etc/clickhouse-server/config.d/logging.xml - content: >- + - source: $$workdir/clickhouse-user-config.xml + destination: /etc/clickhouse-server/config.d/logging.xml + content: >- 00 - - source: $$workdir/init.query - destination: /docker-entrypoint-initdb.d/init.query - content: CREATE DATABASE IF NOT EXISTS plausible; - - source: $$workdir/init-db.sh - destination: /docker-entrypoint-initdb.d/init-db.sh - content: >- + - source: $$workdir/init.query + destination: /docker-entrypoint-initdb.d/init.query + content: CREATE DATABASE IF NOT EXISTS plausible; + - source: $$workdir/init-db.sh + destination: /docker-entrypoint-initdb.d/init-db.sh + content: >- clickhouse client --queries-file /docker-entrypoint-initdb.d/init.query variables: @@ -2167,7 +2158,7 @@ - id: $$secret_secret_key_base name: SECRET_KEY_BASE label: Secret Key Base - defaultValue: $$generate_passphrase + defaultValue: $$generate_hex(64) description: '' - id: $$config_disable_auth name: DISABLE_AUTH @@ -2180,16 +2171,20 @@ defaultValue: 'true' description: '' - id: $$config_postgresql_username + main: $$id-postgresql name: POSTGRESQL_USERNAME label: PostgreSQL Username defaultValue: postgresql description: '' - id: $$secret_postgresql_password + main: $$id-postgresql name: POSTGRESQL_PASSWORD label: PostgreSQL Password defaultValue: $$generate_password description: '' + showOnUI: true - id: $$config_postgresql_database + main: $$id-postgresql name: POSTGRESQL_DATABASE label: PostgreSQL Database defaultValue: plausible diff --git a/apps/api/scripts/convert.mjs b/apps/api/scripts/convert.mjs index ca18ae41d..1ef0d7249 100644 --- a/apps/api/scripts/convert.mjs +++ b/apps/api/scripts/convert.mjs @@ -15,7 +15,6 @@ const newTemplate = { }, "variables": [] } -console.log(template.caproverOneClickApp.variables) const version = template.caproverOneClickApp.variables.find(v => v.id === '$$cap_APP_VERSION' || v.id === '$$cap_version').defaultValue || 'latest' newTemplate.name = template.caproverOneClickApp.displayName diff --git a/apps/api/src/lib/common.ts b/apps/api/src/lib/common.ts index e1de6c6f3..9f8212fb1 100644 --- a/apps/api/src/lib/common.ts +++ b/apps/api/src/lib/common.ts @@ -1099,6 +1099,7 @@ export const createDirectories = async ({ repository: string; buildId: string; }): Promise<{ workdir: string; repodir: string }> => { + repository = repository.replaceAll(' ','') const repodir = `/tmp/build-sources/${repository}/`; const workdir = `/tmp/build-sources/${repository}/${buildId}`; let workdirFound = false; diff --git a/apps/api/src/lib/services.ts b/apps/api/src/lib/services.ts index c576573ad..546cc1edd 100644 --- a/apps/api/src/lib/services.ts +++ b/apps/api/src/lib/services.ts @@ -7,138 +7,138 @@ export async function getTemplates() { } else { templates = JSON.parse(await (await fs.readFile('/app/template.json')).toString()) } - if (!isDev) { - templates.push({ - "templateVersion": "1.0.0", - "defaultVersion": "latest", - "name": "Test-Fake-Service", - "description": "", - "services": { - "$$id": { - "name": "Test-Fake-Service", - "depends_on": [ - "$$id-postgresql", - "$$id-redis" - ], - "image": "weblate/weblate:$$core_version", - "volumes": [ - "$$id-data:/app/data", - ], - "environment": [ - `POSTGRES_SECRET=$$secret_postgres_secret`, - `WEBLATE_SITE_DOMAIN=$$config_weblate_site_domain`, - `WEBLATE_ADMIN_PASSWORD=$$secret_weblate_admin_password`, - `POSTGRES_PASSWORD=$$secret_postgres_password`, - `POSTGRES_USER=$$config_postgres_user`, - `POSTGRES_DATABASE=$$config_postgres_db`, - `POSTGRES_HOST=$$id-postgresql`, - `POSTGRES_PORT=5432`, - `REDIS_HOST=$$id-redis`, - ], - "ports": [ - "8080" - ] - }, - "$$id-postgresql": { - "name": "PostgreSQL", - "depends_on": [], - "image": "postgres:14-alpine", - "volumes": [ - "$$id-postgresql-data:/var/lib/postgresql/data", - ], - "environment": [ - "POSTGRES_USER=$$config_postgres_user", - "POSTGRES_PASSWORD=$$secret_postgres_password", - "POSTGRES_DB=$$config_postgres_db", - ], - "ports": [] - }, - "$$id-redis": { - "name": "Redis", - "depends_on": [], - "image": "redis:7-alpine", - "volumes": [ - "$$id-redis-data:/data", - ], - "environment": [], - "ports": [], - } - }, - "variables": [ - { - "id": "$$config_weblate_site_domain", - "main": "$$id", - "name": "WEBLATE_SITE_DOMAIN", - "label": "Weblate Domain", - "defaultValue": "$$generate_domain", - "description": "", - }, - { - "id": "$$secret_weblate_admin_password", - "main": "$$id", - "name": "WEBLATE_ADMIN_PASSWORD", - "label": "Weblate Admin Password", - "defaultValue": "$$generate_password", - "description": "", - "extras": { - "isVisibleOnUI": true, - } - }, - { - "id": "$$secret_weblate_admin_password2", - "name": "WEBLATE_ADMIN_PASSWORD2", - "label": "Weblate Admin Password2", - "defaultValue": "$$generate_password", - "description": "", - }, - { - "id": "$$config_postgres_user", - "main": "$$id-postgresql", - "name": "POSTGRES_USER", - "label": "PostgreSQL User", - "defaultValue": "$$generate_username", - "description": "", - }, - { - "id": "$$secret_postgres_password", - "main": "$$id-postgresql", - "name": "POSTGRES_PASSWORD", - "label": "PostgreSQL Password", - "defaultValue": "$$generate_password(32)", - "description": "", - }, - { - "id": "$$secret_postgres_password_hex32", - "name": "POSTGRES_PASSWORD_hex32", - "label": "PostgreSQL Password hex32", - "defaultValue": "$$generate_hex(32)", - "description": "", - }, - { - "id": "$$config_postgres_something_hex32", - "name": "POSTGRES_SOMETHING_HEX32", - "label": "PostgreSQL Something hex32", - "defaultValue": "$$generate_hex(32)", - "description": "", - }, - { - "id": "$$config_postgres_db", - "main": "$$id-postgresql", - "name": "POSTGRES_DB", - "label": "PostgreSQL Database", - "defaultValue": "weblate", - "description": "", - }, - { - "id": "$$secret_postgres_secret", - "name": "POSTGRES_SECRET", - "label": "PostgreSQL Secret", - "defaultValue": "", - "description": "", - }, - ] - }) - } + // if (!isDev) { + // templates.push({ + // "templateVersion": "1.0.0", + // "defaultVersion": "latest", + // "name": "Test-Fake-Service", + // "description": "", + // "services": { + // "$$id": { + // "name": "Test-Fake-Service", + // "depends_on": [ + // "$$id-postgresql", + // "$$id-redis" + // ], + // "image": "weblate/weblate:$$core_version", + // "volumes": [ + // "$$id-data:/app/data", + // ], + // "environment": [ + // `POSTGRES_SECRET=$$secret_postgres_secret`, + // `WEBLATE_SITE_DOMAIN=$$config_weblate_site_domain`, + // `WEBLATE_ADMIN_PASSWORD=$$secret_weblate_admin_password`, + // `POSTGRES_PASSWORD=$$secret_postgres_password`, + // `POSTGRES_USER=$$config_postgres_user`, + // `POSTGRES_DATABASE=$$config_postgres_db`, + // `POSTGRES_HOST=$$id-postgresql`, + // `POSTGRES_PORT=5432`, + // `REDIS_HOST=$$id-redis`, + // ], + // "ports": [ + // "8080" + // ] + // }, + // "$$id-postgresql": { + // "name": "PostgreSQL", + // "depends_on": [], + // "image": "postgres:14-alpine", + // "volumes": [ + // "$$id-postgresql-data:/var/lib/postgresql/data", + // ], + // "environment": [ + // "POSTGRES_USER=$$config_postgres_user", + // "POSTGRES_PASSWORD=$$secret_postgres_password", + // "POSTGRES_DB=$$config_postgres_db", + // ], + // "ports": [] + // }, + // "$$id-redis": { + // "name": "Redis", + // "depends_on": [], + // "image": "redis:7-alpine", + // "volumes": [ + // "$$id-redis-data:/data", + // ], + // "environment": [], + // "ports": [], + // } + // }, + // "variables": [ + // { + // "id": "$$config_weblate_site_domain", + // "main": "$$id", + // "name": "WEBLATE_SITE_DOMAIN", + // "label": "Weblate Domain", + // "defaultValue": "$$generate_domain", + // "description": "", + // }, + // { + // "id": "$$secret_weblate_admin_password", + // "main": "$$id", + // "name": "WEBLATE_ADMIN_PASSWORD", + // "label": "Weblate Admin Password", + // "defaultValue": "$$generate_password", + // "description": "", + // "extras": { + // "isVisibleOnUI": true, + // } + // }, + // { + // "id": "$$secret_weblate_admin_password2", + // "name": "WEBLATE_ADMIN_PASSWORD2", + // "label": "Weblate Admin Password2", + // "defaultValue": "$$generate_password", + // "description": "", + // }, + // { + // "id": "$$config_postgres_user", + // "main": "$$id-postgresql", + // "name": "POSTGRES_USER", + // "label": "PostgreSQL User", + // "defaultValue": "$$generate_username", + // "description": "", + // }, + // { + // "id": "$$secret_postgres_password", + // "main": "$$id-postgresql", + // "name": "POSTGRES_PASSWORD", + // "label": "PostgreSQL Password", + // "defaultValue": "$$generate_password(32)", + // "description": "", + // }, + // { + // "id": "$$secret_postgres_password_hex32", + // "name": "POSTGRES_PASSWORD_hex32", + // "label": "PostgreSQL Password hex32", + // "defaultValue": "$$generate_hex(32)", + // "description": "", + // }, + // { + // "id": "$$config_postgres_something_hex32", + // "name": "POSTGRES_SOMETHING_HEX32", + // "label": "PostgreSQL Something hex32", + // "defaultValue": "$$generate_hex(32)", + // "description": "", + // }, + // { + // "id": "$$config_postgres_db", + // "main": "$$id-postgresql", + // "name": "POSTGRES_DB", + // "label": "PostgreSQL Database", + // "defaultValue": "weblate", + // "description": "", + // }, + // { + // "id": "$$secret_postgres_secret", + // "name": "POSTGRES_SECRET", + // "label": "PostgreSQL Secret", + // "defaultValue": "", + // "description": "", + // }, + // ] + // }) + // } return templates } export async function defaultServiceConfigurations({ id, teamId }) { diff --git a/apps/api/src/lib/services/handlers.ts b/apps/api/src/lib/services/handlers.ts index 674fd4691..f822f215f 100644 --- a/apps/api/src/lib/services/handlers.ts +++ b/apps/api/src/lib/services/handlers.ts @@ -701,18 +701,21 @@ export async function startService(request: FastifyRequest) { const config = {}; for (const service in template.services) { let newEnvironments = [] - for (const environment of template.services[service].environment) { - const [env, value] = environment.split("="); - if (!value.startsWith('$$secret') && value !== '') { - newEnvironments.push(`${env}=${value}`) + if (template.services[service]?.environment?.length > 0) { + for (const environment of template.services[service].environment) { + const [env, value] = environment.split("="); + if (!value.startsWith('$$secret') && value !== '') { + newEnvironments.push(`${env}=${value}`) + } } - } const secrets = await prisma.serviceSecret.findMany({ where: { serviceId: id } }) for (const secret of secrets) { const { name, value } = secret if (value) { - if (template.services[service].environment.find(env => env.startsWith(`${name}=`)) && !newEnvironments.find(env => env.startsWith(`${name}=`))) { + const foundEnv = !!template.services[service].environment?.find(env => env.startsWith(`${name}=`)) + const foundNewEnv = !!newEnvironments?.find(env => env.startsWith(`${name}=`)) + if (foundEnv && !foundNewEnv) { newEnvironments.push(`${name}=${decrypt(value)}`) } } @@ -736,7 +739,7 @@ export async function startService(request: FastifyRequest) { } // Generate files for builds - if (template.services[service]?.extras?.files?.length > 0) { + if (template.services[service]?.files?.length > 0) { if (!template.services[service].build) { template.services[service].build = { context: workdir, @@ -745,7 +748,7 @@ export async function startService(request: FastifyRequest) { } let Dockerfile = ` FROM ${template.services[service].image}` - for (const file of template.services[service].extras.files) { + for (const file of template.services[service].files) { const { source, destination, content } = file; await fs.writeFile(source, content); Dockerfile += ` @@ -754,6 +757,7 @@ export async function startService(request: FastifyRequest) { await fs.writeFile(`${workdir}/Dockerfile.${service}`, Dockerfile); } } + const { volumeMounts } = persistentVolumes(id, persistentStorage, config) const composeFile: ComposeFile = { version: '3.8', @@ -766,7 +770,6 @@ export async function startService(request: FastifyRequest) { volumes: volumeMounts } const composeFileDestination = `${workdir}/docker-compose.yaml`; - console.log(composeFileDestination) await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); await startServiceContainers(destinationDocker.id, composeFileDestination) return {} diff --git a/apps/api/src/routes/api/v1/services/handlers.ts b/apps/api/src/routes/api/v1/services/handlers.ts index ec5e82b23..ed265c487 100644 --- a/apps/api/src/routes/api/v1/services/handlers.ts +++ b/apps/api/src/routes/api/v1/services/handlers.ts @@ -258,9 +258,7 @@ export async function saveServiceType(request: FastifyRequest, const regex = /^\$\$.*\((\d+)\)$/g; const length = Number(regex.exec(defaultValue)?.[1]) || undefined if (variable.defaultValue.startsWith('$$generate_password')) { - console.log(variable) variable.value = generatePassword({ length }); - console.log(variable.value) } else if (variable.defaultValue.startsWith('$$generate_hex')) { variable.value = generatePassword({ length, isHex: true }); } else if (variable.defaultValue.startsWith('$$generate_username')) { @@ -268,6 +266,10 @@ export async function saveServiceType(request: FastifyRequest, } 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) { diff --git a/apps/ui/src/routes/applications/[id]/__layout.svelte b/apps/ui/src/routes/applications/[id]/__layout.svelte index 77849f39d..94977e5e0 100644 --- a/apps/ui/src/routes/applications/[id]/__layout.svelte +++ b/apps/ui/src/routes/applications/[id]/__layout.svelte @@ -415,7 +415,7 @@ {/if}