diff --git a/apps/api/src/lib/services/common.ts b/apps/api/src/lib/services/common.ts index f6174ca69..b627eb5bb 100644 --- a/apps/api/src/lib/services/common.ts +++ b/apps/api/src/lib/services/common.ts @@ -350,6 +350,13 @@ export async function configureServiceType({ } } }); + } else if (type === 'grafana') { + await prisma.service.update({ + where: { id }, + data: { + type + } + }); } else { await prisma.service.update({ where: { id }, diff --git a/apps/api/src/lib/services/handlers.ts b/apps/api/src/lib/services/handlers.ts index 30c994b0b..cc6646737 100644 --- a/apps/api/src/lib/services/handlers.ts +++ b/apps/api/src/lib/services/handlers.ts @@ -70,6 +70,9 @@ export async function startService(request: FastifyRequest) { if (type === 'taiga') { return await startTaigaService(request) } + if (type === 'grafana') { + return await startGrafanaService(request) + } throw `Service type ${type} not supported.` } catch (error) { throw { status: 500, message: error?.message || error } @@ -2641,6 +2644,61 @@ async function startTaigaService(request: FastifyRequest) { } } +async function startGrafanaService(request: FastifyRequest) { + try { + const { id } = request.params; + const teamId = request.user.teamId; + const service = await getServiceFromDB({ id, teamId }); + const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort, persistentStorage } = + service; + const network = destinationDockerId && destinationDocker.network; + const port = getServiceMainPort('grafana'); + + const { workdir } = await createDirectories({ repository: type, buildId: id }); + const image = getServiceImage(type); + + const config = { + grafana: { + image: `${image}:${version}`, + volumes: [`${id}-grafana:/var/lib/grafana`], + environmentVariables: {} + } + }; + if (serviceSecret.length > 0) { + serviceSecret.forEach((secret) => { + config.grafana.environmentVariables[secret.name] = secret.value; + }); + } + const { volumeMounts } = persistentVolumes(id, persistentStorage, config) + const composeFile: ComposeFile = { + version: '3.8', + services: { + [id]: { + container_name: id, + image: config.grafana.image, + volumes: config.grafana.volumes, + environment: config.grafana.environmentVariables, + ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), + labels: makeLabelForServices('grafana'), + ...defaultComposeConfiguration(network), + } + }, + networks: { + [network]: { + external: true + } + }, + volumes: volumeMounts + }; + const composeFileDestination = `${workdir}/docker-compose.yaml`; + await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); + await startServiceContainers(destinationDocker.id, composeFileDestination) + return {} + } catch ({ status, message }) { + return errorHandler({ status, message }) + } +} + export async function migrateAppwriteDB(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params diff --git a/apps/api/src/lib/services/supportedVersions.ts b/apps/api/src/lib/services/supportedVersions.ts index feaa584a4..9ad5ce783 100644 --- a/apps/api/src/lib/services/supportedVersions.ts +++ b/apps/api/src/lib/services/supportedVersions.ts @@ -233,4 +233,15 @@ export const supportedServiceTypesAndVersions = [ // main: 80 // } // }, + { + name: 'grafana', + fancyName: 'Grafana Dashboard', + baseImage: 'grafana/grafana', + images: [], + versions: ['latest', '9.1.3', '9.1.2', '9.0.8', '8.3.11', '8.4.11', '8.5.11'], + recommendedVersion: 'latest', + ports: { + main: 3000 + } + }, ]; \ No newline at end of file diff --git a/apps/ui/src/lib/components/svg/services/Grafana.svelte b/apps/ui/src/lib/components/svg/services/Grafana.svelte new file mode 100644 index 000000000..8701f58e7 --- /dev/null +++ b/apps/ui/src/lib/components/svg/services/Grafana.svelte @@ -0,0 +1,9 @@ + + +grafana logo diff --git a/apps/ui/src/lib/components/svg/services/ServiceIcons.svelte b/apps/ui/src/lib/components/svg/services/ServiceIcons.svelte index 4cc5426b2..6daf5bc97 100644 --- a/apps/ui/src/lib/components/svg/services/ServiceIcons.svelte +++ b/apps/ui/src/lib/components/svg/services/ServiceIcons.svelte @@ -42,4 +42,6 @@ {:else if type === 'weblate'} -{/if} +{:else if type === 'grafana'} + +{/if} \ No newline at end of file diff --git a/apps/ui/src/lib/components/svg/services/index.ts b/apps/ui/src/lib/components/svg/services/index.ts index 22f7702c9..4c62fd549 100644 --- a/apps/ui/src/lib/components/svg/services/index.ts +++ b/apps/ui/src/lib/components/svg/services/index.ts @@ -17,4 +17,5 @@ export { default as Appwrite } from './Appwrite.svelte'; export { default as Moodle } from './Moodle.svelte'; export { default as GlitchTip } from './GlitchTip.svelte'; export { default as Searxng } from './Searxng.svelte'; -export { default as Weblate } from './Weblate.svelte'; \ No newline at end of file +export { default as Weblate } from './Weblate.svelte'; +export { default as Grafana } from './Grafana.svelte'; \ No newline at end of file diff --git a/apps/ui/src/routes/services/[id]/_ServiceLinks.svelte b/apps/ui/src/routes/services/[id]/_ServiceLinks.svelte index d68a3eae0..e29df196f 100644 --- a/apps/ui/src/routes/services/[id]/_ServiceLinks.svelte +++ b/apps/ui/src/routes/services/[id]/_ServiceLinks.svelte @@ -75,4 +75,8 @@ +{:else if service.type === 'grafana'} + + + {/if} diff --git a/apps/ui/static/grafana.png b/apps/ui/static/grafana.png new file mode 100644 index 000000000..af2a31715 Binary files /dev/null and b/apps/ui/static/grafana.png differ