This commit is contained in:
Andras Bacsai 2022-10-26 10:12:17 +02:00
parent 54e0a9fc28
commit c34de3d0a3
8 changed files with 181 additions and 182 deletions

View File

@ -1130,11 +1130,10 @@
- SETGID - SETGID
- SETUID - SETUID
- DAC_OVERRIDE - DAC_OVERRIDE
extras: files:
files: - source: $$workdir/settings.yml
- source: $$workdir/settings.yml destination: /etc/searxng/settings.yml
destination: /etc/searxng/settings.yml content: |2-
content: |2-
# see https://docs.searxng.org/admin/engines/settings.html#use-default-settings # see https://docs.searxng.org/admin/engines/settings.html#use-default-settings
use_default_settings: true use_default_settings: true
@ -1173,7 +1172,7 @@
- id: $$secret_secret_key - id: $$secret_secret_key
name: SECRET_KEY name: SECRET_KEY
label: Secret Key label: Secret Key
defaultValue: $$generate_passphrase defaultValue: $$generate_hex(64)
description: '' description: ''
- id: $$secret_redis_password - id: $$secret_redis_password
name: REDIS_PASSWORD name: REDIS_PASSWORD
@ -1439,11 +1438,10 @@
- POSTGRES_PASSWORD=$$secret_postgres_password - POSTGRES_PASSWORD=$$secret_postgres_password
- POSTGRES_DB=$$config_postgres_db - POSTGRES_DB=$$config_postgres_db
ports: [] ports: []
extras: files:
files: - source: $$workdir/schema.postgresql.sql
- source: $$workdir/schema.postgresql.sql destination: /docker-entrypoint-initdb.d/schema.postgresql.sql
destination: /docker-entrypoint-initdb.d/schema.postgresql.sql content: |2-
content: |2-
-- CreateTable -- CreateTable
CREATE TABLE "account" ( CREATE TABLE "account" (
@ -1586,7 +1584,7 @@
- id: $$secret_hash_salt - id: $$secret_hash_salt
name: HASH_SALT name: HASH_SALT
label: Hash Salt label: Hash Salt
defaultValue: $$generate_passphrase defaultValue: $$generate_hex(64)
description: '' description: ''
- id: $$config_postgres_user - id: $$config_postgres_user
name: POSTGRES_USER name: POSTGRES_USER
@ -1634,7 +1632,7 @@
- id: $$secret_meili_master_key - id: $$secret_meili_master_key
name: MEILI_MASTER_KEY name: MEILI_MASTER_KEY
label: Master Key label: Master Key
defaultValue: $$generate_passphrase defaultValue: $$generate_hex(64)
description: '' description: ''
showOnUI: true showOnUI: true
- templateVersion: 1.0.0 - templateVersion: 1.0.0
@ -1967,7 +1965,7 @@
- id: $$secret_jwt_secret - id: $$secret_jwt_secret
name: JWT_SECRET name: JWT_SECRET
label: JWT Secret label: JWT Secret
defaultValue: $$generate_passphrase defaultValue: $$generate_hex(64)
description: '' description: ''
- id: $$config_email_noreply - id: $$config_email_noreply
name: EMAIL_NOREPLY name: EMAIL_NOREPLY
@ -2057,12 +2055,6 @@
defaultVersion: stable defaultVersion: stable
name: Plausible Analytics name: Plausible Analytics
description: Plausible is a lightweight and open-source website analytics tool. description: Plausible is a lightweight and open-source website analytics tool.
labels:
- analytics
- plausible
- gdpr
- no-cookie
- privacy
services: services:
$$id: $$id:
name: Plausible Analytics name: Plausible Analytics
@ -2106,27 +2098,26 @@
nofile: nofile:
soft: 262144 soft: 262144
hard: 262144 hard: 262144
extras: files:
files: - source: $$workdir/clickhouse-config.xml
- source: $$workdir/clickhouse-config.xml destination: /etc/clickhouse-server/users.d/logging.xml
destination: /etc/clickhouse-server/users.d/logging.xml content: >-
content: >-
<yandex><logger><level>warning</level><console>true</console></logger><query_thread_log <yandex><logger><level>warning</level><console>true</console></logger><query_thread_log
remove="remove"/><query_log remove="remove"/><text_log remove="remove"/><query_log remove="remove"/><text_log
remove="remove"/><trace_log remove="remove"/><metric_log remove="remove"/><trace_log remove="remove"/><metric_log
remove="remove"/><asynchronous_metric_log remove="remove"/><asynchronous_metric_log
remove="remove"/><session_log remove="remove"/><part_log remove="remove"/><session_log remove="remove"/><part_log
remove="remove"/></yandex> remove="remove"/></yandex>
- source: $$workdir/clickhouse-user-config.xml - source: $$workdir/clickhouse-user-config.xml
destination: /etc/clickhouse-server/config.d/logging.xml destination: /etc/clickhouse-server/config.d/logging.xml
content: >- content: >-
<yandex><profiles><default><log_queries>0</log_queries><log_query_threads>0</log_query_threads></default></profiles></yandex> <yandex><profiles><default><log_queries>0</log_queries><log_query_threads>0</log_query_threads></default></profiles></yandex>
- source: $$workdir/init.query - source: $$workdir/init.query
destination: /docker-entrypoint-initdb.d/init.query destination: /docker-entrypoint-initdb.d/init.query
content: CREATE DATABASE IF NOT EXISTS plausible; content: CREATE DATABASE IF NOT EXISTS plausible;
- source: $$workdir/init-db.sh - source: $$workdir/init-db.sh
destination: /docker-entrypoint-initdb.d/init-db.sh destination: /docker-entrypoint-initdb.d/init-db.sh
content: >- content: >-
clickhouse client --queries-file clickhouse client --queries-file
/docker-entrypoint-initdb.d/init.query /docker-entrypoint-initdb.d/init.query
variables: variables:
@ -2167,7 +2158,7 @@
- id: $$secret_secret_key_base - id: $$secret_secret_key_base
name: SECRET_KEY_BASE name: SECRET_KEY_BASE
label: Secret Key Base label: Secret Key Base
defaultValue: $$generate_passphrase defaultValue: $$generate_hex(64)
description: '' description: ''
- id: $$config_disable_auth - id: $$config_disable_auth
name: DISABLE_AUTH name: DISABLE_AUTH
@ -2180,16 +2171,20 @@
defaultValue: 'true' defaultValue: 'true'
description: '' description: ''
- id: $$config_postgresql_username - id: $$config_postgresql_username
main: $$id-postgresql
name: POSTGRESQL_USERNAME name: POSTGRESQL_USERNAME
label: PostgreSQL Username label: PostgreSQL Username
defaultValue: postgresql defaultValue: postgresql
description: '' description: ''
- id: $$secret_postgresql_password - id: $$secret_postgresql_password
main: $$id-postgresql
name: POSTGRESQL_PASSWORD name: POSTGRESQL_PASSWORD
label: PostgreSQL Password label: PostgreSQL Password
defaultValue: $$generate_password defaultValue: $$generate_password
description: '' description: ''
showOnUI: true
- id: $$config_postgresql_database - id: $$config_postgresql_database
main: $$id-postgresql
name: POSTGRESQL_DATABASE name: POSTGRESQL_DATABASE
label: PostgreSQL Database label: PostgreSQL Database
defaultValue: plausible defaultValue: plausible

View File

@ -15,7 +15,6 @@ const newTemplate = {
}, },
"variables": [] "variables": []
} }
console.log(template.caproverOneClickApp.variables)
const version = template.caproverOneClickApp.variables.find(v => v.id === '$$cap_APP_VERSION' || v.id === '$$cap_version').defaultValue || 'latest' const version = template.caproverOneClickApp.variables.find(v => v.id === '$$cap_APP_VERSION' || v.id === '$$cap_version').defaultValue || 'latest'
newTemplate.name = template.caproverOneClickApp.displayName newTemplate.name = template.caproverOneClickApp.displayName

View File

@ -1099,6 +1099,7 @@ export const createDirectories = async ({
repository: string; repository: string;
buildId: string; buildId: string;
}): Promise<{ workdir: string; repodir: string }> => { }): Promise<{ workdir: string; repodir: string }> => {
repository = repository.replaceAll(' ','')
const repodir = `/tmp/build-sources/${repository}/`; const repodir = `/tmp/build-sources/${repository}/`;
const workdir = `/tmp/build-sources/${repository}/${buildId}`; const workdir = `/tmp/build-sources/${repository}/${buildId}`;
let workdirFound = false; let workdirFound = false;

View File

@ -7,138 +7,138 @@ export async function getTemplates() {
} else { } else {
templates = JSON.parse(await (await fs.readFile('/app/template.json')).toString()) templates = JSON.parse(await (await fs.readFile('/app/template.json')).toString())
} }
if (!isDev) { // if (!isDev) {
templates.push({ // templates.push({
"templateVersion": "1.0.0", // "templateVersion": "1.0.0",
"defaultVersion": "latest", // "defaultVersion": "latest",
"name": "Test-Fake-Service", // "name": "Test-Fake-Service",
"description": "", // "description": "",
"services": { // "services": {
"$$id": { // "$$id": {
"name": "Test-Fake-Service", // "name": "Test-Fake-Service",
"depends_on": [ // "depends_on": [
"$$id-postgresql", // "$$id-postgresql",
"$$id-redis" // "$$id-redis"
], // ],
"image": "weblate/weblate:$$core_version", // "image": "weblate/weblate:$$core_version",
"volumes": [ // "volumes": [
"$$id-data:/app/data", // "$$id-data:/app/data",
], // ],
"environment": [ // "environment": [
`POSTGRES_SECRET=$$secret_postgres_secret`, // `POSTGRES_SECRET=$$secret_postgres_secret`,
`WEBLATE_SITE_DOMAIN=$$config_weblate_site_domain`, // `WEBLATE_SITE_DOMAIN=$$config_weblate_site_domain`,
`WEBLATE_ADMIN_PASSWORD=$$secret_weblate_admin_password`, // `WEBLATE_ADMIN_PASSWORD=$$secret_weblate_admin_password`,
`POSTGRES_PASSWORD=$$secret_postgres_password`, // `POSTGRES_PASSWORD=$$secret_postgres_password`,
`POSTGRES_USER=$$config_postgres_user`, // `POSTGRES_USER=$$config_postgres_user`,
`POSTGRES_DATABASE=$$config_postgres_db`, // `POSTGRES_DATABASE=$$config_postgres_db`,
`POSTGRES_HOST=$$id-postgresql`, // `POSTGRES_HOST=$$id-postgresql`,
`POSTGRES_PORT=5432`, // `POSTGRES_PORT=5432`,
`REDIS_HOST=$$id-redis`, // `REDIS_HOST=$$id-redis`,
], // ],
"ports": [ // "ports": [
"8080" // "8080"
] // ]
}, // },
"$$id-postgresql": { // "$$id-postgresql": {
"name": "PostgreSQL", // "name": "PostgreSQL",
"depends_on": [], // "depends_on": [],
"image": "postgres:14-alpine", // "image": "postgres:14-alpine",
"volumes": [ // "volumes": [
"$$id-postgresql-data:/var/lib/postgresql/data", // "$$id-postgresql-data:/var/lib/postgresql/data",
], // ],
"environment": [ // "environment": [
"POSTGRES_USER=$$config_postgres_user", // "POSTGRES_USER=$$config_postgres_user",
"POSTGRES_PASSWORD=$$secret_postgres_password", // "POSTGRES_PASSWORD=$$secret_postgres_password",
"POSTGRES_DB=$$config_postgres_db", // "POSTGRES_DB=$$config_postgres_db",
], // ],
"ports": [] // "ports": []
}, // },
"$$id-redis": { // "$$id-redis": {
"name": "Redis", // "name": "Redis",
"depends_on": [], // "depends_on": [],
"image": "redis:7-alpine", // "image": "redis:7-alpine",
"volumes": [ // "volumes": [
"$$id-redis-data:/data", // "$$id-redis-data:/data",
], // ],
"environment": [], // "environment": [],
"ports": [], // "ports": [],
} // }
}, // },
"variables": [ // "variables": [
{ // {
"id": "$$config_weblate_site_domain", // "id": "$$config_weblate_site_domain",
"main": "$$id", // "main": "$$id",
"name": "WEBLATE_SITE_DOMAIN", // "name": "WEBLATE_SITE_DOMAIN",
"label": "Weblate Domain", // "label": "Weblate Domain",
"defaultValue": "$$generate_domain", // "defaultValue": "$$generate_domain",
"description": "", // "description": "",
}, // },
{ // {
"id": "$$secret_weblate_admin_password", // "id": "$$secret_weblate_admin_password",
"main": "$$id", // "main": "$$id",
"name": "WEBLATE_ADMIN_PASSWORD", // "name": "WEBLATE_ADMIN_PASSWORD",
"label": "Weblate Admin Password", // "label": "Weblate Admin Password",
"defaultValue": "$$generate_password", // "defaultValue": "$$generate_password",
"description": "", // "description": "",
"extras": { // "extras": {
"isVisibleOnUI": true, // "isVisibleOnUI": true,
} // }
}, // },
{ // {
"id": "$$secret_weblate_admin_password2", // "id": "$$secret_weblate_admin_password2",
"name": "WEBLATE_ADMIN_PASSWORD2", // "name": "WEBLATE_ADMIN_PASSWORD2",
"label": "Weblate Admin Password2", // "label": "Weblate Admin Password2",
"defaultValue": "$$generate_password", // "defaultValue": "$$generate_password",
"description": "", // "description": "",
}, // },
{ // {
"id": "$$config_postgres_user", // "id": "$$config_postgres_user",
"main": "$$id-postgresql", // "main": "$$id-postgresql",
"name": "POSTGRES_USER", // "name": "POSTGRES_USER",
"label": "PostgreSQL User", // "label": "PostgreSQL User",
"defaultValue": "$$generate_username", // "defaultValue": "$$generate_username",
"description": "", // "description": "",
}, // },
{ // {
"id": "$$secret_postgres_password", // "id": "$$secret_postgres_password",
"main": "$$id-postgresql", // "main": "$$id-postgresql",
"name": "POSTGRES_PASSWORD", // "name": "POSTGRES_PASSWORD",
"label": "PostgreSQL Password", // "label": "PostgreSQL Password",
"defaultValue": "$$generate_password(32)", // "defaultValue": "$$generate_password(32)",
"description": "", // "description": "",
}, // },
{ // {
"id": "$$secret_postgres_password_hex32", // "id": "$$secret_postgres_password_hex32",
"name": "POSTGRES_PASSWORD_hex32", // "name": "POSTGRES_PASSWORD_hex32",
"label": "PostgreSQL Password hex32", // "label": "PostgreSQL Password hex32",
"defaultValue": "$$generate_hex(32)", // "defaultValue": "$$generate_hex(32)",
"description": "", // "description": "",
}, // },
{ // {
"id": "$$config_postgres_something_hex32", // "id": "$$config_postgres_something_hex32",
"name": "POSTGRES_SOMETHING_HEX32", // "name": "POSTGRES_SOMETHING_HEX32",
"label": "PostgreSQL Something hex32", // "label": "PostgreSQL Something hex32",
"defaultValue": "$$generate_hex(32)", // "defaultValue": "$$generate_hex(32)",
"description": "", // "description": "",
}, // },
{ // {
"id": "$$config_postgres_db", // "id": "$$config_postgres_db",
"main": "$$id-postgresql", // "main": "$$id-postgresql",
"name": "POSTGRES_DB", // "name": "POSTGRES_DB",
"label": "PostgreSQL Database", // "label": "PostgreSQL Database",
"defaultValue": "weblate", // "defaultValue": "weblate",
"description": "", // "description": "",
}, // },
{ // {
"id": "$$secret_postgres_secret", // "id": "$$secret_postgres_secret",
"name": "POSTGRES_SECRET", // "name": "POSTGRES_SECRET",
"label": "PostgreSQL Secret", // "label": "PostgreSQL Secret",
"defaultValue": "", // "defaultValue": "",
"description": "", // "description": "",
}, // },
] // ]
}) // })
} // }
return templates return templates
} }
export async function defaultServiceConfigurations({ id, teamId }) { export async function defaultServiceConfigurations({ id, teamId }) {

View File

@ -701,18 +701,21 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
const config = {}; const config = {};
for (const service in template.services) { for (const service in template.services) {
let newEnvironments = [] let newEnvironments = []
for (const environment of template.services[service].environment) { if (template.services[service]?.environment?.length > 0) {
const [env, value] = environment.split("="); for (const environment of template.services[service].environment) {
if (!value.startsWith('$$secret') && value !== '') { const [env, value] = environment.split("=");
newEnvironments.push(`${env}=${value}`) if (!value.startsWith('$$secret') && value !== '') {
newEnvironments.push(`${env}=${value}`)
}
} }
} }
const secrets = await prisma.serviceSecret.findMany({ where: { serviceId: id } }) const secrets = await prisma.serviceSecret.findMany({ where: { serviceId: id } })
for (const secret of secrets) { for (const secret of secrets) {
const { name, value } = secret const { name, value } = secret
if (value) { 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)}`) newEnvironments.push(`${name}=${decrypt(value)}`)
} }
} }
@ -736,7 +739,7 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
} }
// Generate files for builds // Generate files for builds
if (template.services[service]?.extras?.files?.length > 0) { if (template.services[service]?.files?.length > 0) {
if (!template.services[service].build) { if (!template.services[service].build) {
template.services[service].build = { template.services[service].build = {
context: workdir, context: workdir,
@ -745,7 +748,7 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
} }
let Dockerfile = ` let Dockerfile = `
FROM ${template.services[service].image}` 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; const { source, destination, content } = file;
await fs.writeFile(source, content); await fs.writeFile(source, content);
Dockerfile += ` Dockerfile += `
@ -754,6 +757,7 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
await fs.writeFile(`${workdir}/Dockerfile.${service}`, Dockerfile); await fs.writeFile(`${workdir}/Dockerfile.${service}`, Dockerfile);
} }
} }
const { volumeMounts } = persistentVolumes(id, persistentStorage, config) const { volumeMounts } = persistentVolumes(id, persistentStorage, config)
const composeFile: ComposeFile = { const composeFile: ComposeFile = {
version: '3.8', version: '3.8',
@ -766,7 +770,6 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
volumes: volumeMounts volumes: volumeMounts
} }
const composeFileDestination = `${workdir}/docker-compose.yaml`; const composeFileDestination = `${workdir}/docker-compose.yaml`;
console.log(composeFileDestination)
await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); await fs.writeFile(composeFileDestination, yaml.dump(composeFile));
await startServiceContainers(destinationDocker.id, composeFileDestination) await startServiceContainers(destinationDocker.id, composeFileDestination)
return {} return {}

View File

@ -258,9 +258,7 @@ export async function saveServiceType(request: FastifyRequest<SaveServiceType>,
const regex = /^\$\$.*\((\d+)\)$/g; const regex = /^\$\$.*\((\d+)\)$/g;
const length = Number(regex.exec(defaultValue)?.[1]) || undefined const length = Number(regex.exec(defaultValue)?.[1]) || undefined
if (variable.defaultValue.startsWith('$$generate_password')) { if (variable.defaultValue.startsWith('$$generate_password')) {
console.log(variable)
variable.value = generatePassword({ length }); variable.value = generatePassword({ length });
console.log(variable.value)
} else if (variable.defaultValue.startsWith('$$generate_hex')) { } else if (variable.defaultValue.startsWith('$$generate_hex')) {
variable.value = generatePassword({ length, isHex: true }); variable.value = generatePassword({ length, isHex: true });
} else if (variable.defaultValue.startsWith('$$generate_username')) { } else if (variable.defaultValue.startsWith('$$generate_username')) {
@ -268,6 +266,10 @@ export async function saveServiceType(request: FastifyRequest<SaveServiceType>,
} else { } else {
variable.value = variable.defaultValue || ''; 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) { for (const variable of foundTemplate.variables) {

View File

@ -415,7 +415,7 @@
</button> </button>
{/if} {/if}
<button <button
class="btn btn-sm gap-2" class="btn btn-sm btn-ghost gap-2"
class:btn-primary={$status.application.overallStatus !== 'degraded'} class:btn-primary={$status.application.overallStatus !== 'degraded'}
disabled={!$isDeploymentEnabled} disabled={!$isDeploymentEnabled}
on:click={() => handleDeploySubmit(false)} on:click={() => handleDeploySubmit(false)}

View File

@ -415,7 +415,6 @@
<Explainer explanation={variable.description} /> <Explainer explanation={variable.description} />
{/if}</label {/if}</label
> >
{#if variable.defaultValue === '$$generate_fqdn'} {#if variable.defaultValue === '$$generate_fqdn'}
<CopyPasswordField <CopyPasswordField
disabled disabled
@ -468,7 +467,7 @@
<option value="false"> false</option> <option value="false"> false</option>
</select> </select>
{/if} {/if}
{:else if variable.defaultValue === '$$generate_password' || variable.defaultValue === '$$generate_passphrase'} {:else if variable.defaultValue === '$$generate_password'}
<CopyPasswordField <CopyPasswordField
isPasswordField isPasswordField
readonly readonly