diff --git a/.dockerignore b/.dockerignore index fc06e3e..814e90a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -9,7 +9,6 @@ LICENSE .vscode Makefile helm-charts -.env .editorconfig .idea coverage* diff --git a/.env b/.env index 204f0dc..d5d71ca 100644 --- a/.env +++ b/.env @@ -1,3 +1,9 @@ VITE_DEPLOY_API_URL="https://api.cloud.cbh.kth.se/deploy/v2" VITE_ALERT_API_URL="https://alert.app.cloud.cbh.kth.se/" +VITE_KEYCLOAK_URL="https://iam.cloud.cbh.kth.se" +VITE_KEYCLOAK_REALM="cloud" +VITE_KEYCLOAK_CLIENT_ID="landing" +VITE_RANCHER_URL="https://mgmt.cloud.cbh.kth.se" +VITE_DNS_URL="https://dns.cloud.cbh.kth.se" +VITE_MAIA_URL="https://maia.app.cloud.cbh.kth.se/maia" GENERATE_SOURCEMAP=false diff --git a/Dockerfile b/Dockerfile index 656093d..b9e7f2b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,28 +1,52 @@ # Build with Bun -FROM docker.io/oven/bun:latest as build +FROM --platform=$BUILDPLATFORM docker.io/oven/bun:latest AS build ARG RELEASE_BRANCH ARG RELEASE_DATE ARG RELEASE_COMMIT +ENV NODE_ENV="production" + +WORKDIR /app + +COPY package*.json bun.lockb ./ + +RUN bun install + +COPY .env . +COPY --chmod=777 scripts/ ./ + +RUN ./docker-envs.ts .env.production && \ + ./nginx-entrypoint.ts && \ + rm .env + ENV VITE_RELEASE_BRANCH=${RELEASE_BRANCH} ENV VITE_RELEASE_DATE=${RELEASE_DATE} ENV VITE_RELEASE_COMMIT=${RELEASE_COMMIT} -ENV VITE_API_URL="https://api.cloud.cbh.kth.se" -ENV VITE_DEPLOY_API_URL="https://api.cloud.cbh.kth.se/deploy/v2" -ENV NODE_ENV="production" +COPY .eslintrc.json jsconfig.json index.html tsconfig*.json vite.config.ts ./ -WORKDIR /app -COPY . /app +COPY . . -RUN bun install RUN bun run build # Serve with NGINX -FROM nginx +FROM nginx:latest COPY --from=build /app/dist /usr/share/nginx/html RUN rm /etc/nginx/conf.d/default.conf COPY nginx/nginx.conf /etc/nginx/conf.d + +COPY --from=build --chmod=777 --link /app/entrypoint.sh . + +# Set default values, can be overriden +ENV DEPLOY_API_URL="https://api.cloud.cbh.kth.se/deploy/v2" +ENV ALERT_API_URL="https://alert.app.cloud.cbh.kth.se/" +ENV KEYCLOAK_URL="https://iam.cloud.cbh.kth.se" +ENV KEYCLOAK_REALM="cloud" +ENV KEYCLOAK_CLIENT_ID="landing" +ENV RANCHER_URL="https://mgmt.cloud.cbh.kth.se" +ENV DNS_URL="https://dns.cloud.cbh.kth.se" +ENV MAIA_URL="https://maia.app.cloud.cbh.kth.se/maia" + EXPOSE 3000 -CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file +ENTRYPOINT ["/entrypoint.sh"] diff --git a/bun.lockb b/bun.lockb index 8e46bd0..217371b 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index df5ff2f..272a347 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ }, "devDependencies": { "@faker-js/faker": "^8.4.1", + "@types/bun": "^1.1.17", "@types/react": "^18.3.3", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^18.3.0", diff --git a/scripts/docker-envs.ts b/scripts/docker-envs.ts new file mode 100755 index 0000000..8747736 --- /dev/null +++ b/scripts/docker-envs.ts @@ -0,0 +1,28 @@ +#!/usr/bin/env bun + +import fs from "fs"; +import path from "path"; + +// @ts-ignore +const viteEnv = import.meta.env; + +// Get the filename from command-line arguments +const args = process.argv.slice(2); +const outputFilename = args[0] || ".env.docker"; // Default to `.env.docker` if no argument is provided + +let envProductionContent = ""; + +// Process environment variables +for (const [key, _] of Object.entries(viteEnv)) { + if (key.startsWith("VITE_")) { + envProductionContent += `${key}={{__${key.slice("VITE_".length)}__}}\n`; + } +} + +// Resolve the output file path +const outputFilePath = path.resolve(outputFilename); + +// Write the content to the specified file +fs.writeFileSync(outputFilePath, envProductionContent, "utf-8"); + +console.log(`${outputFilename} file created successfully!`); diff --git a/scripts/nginx-entrypoint.ts b/scripts/nginx-entrypoint.ts new file mode 100755 index 0000000..7a3dcc3 --- /dev/null +++ b/scripts/nginx-entrypoint.ts @@ -0,0 +1,57 @@ +#!/usr/bin/env bun + +import fs from "fs"; +import path from "path"; + +const viteEnv = import.meta.env; + +let entrypointScript = `#!/bin/bash + +# Entrypoint script, replaces env variables in the dist files +set -eu + +exec "$@" + +# Function to update environment variables in files recursively +update_env_vars_placeholders() { + local directory="$1" + local old_var="$2" + local new_value="\${!3:-}" + + if [[ -z "$new_value" && -n "$3" ]]; then + echo "[WARN]: The value for $3 is not set." >&2 + fi + + # Find files in the given directory recursively + find "$directory" -type f -exec sed -i "s|{{$old_var}}|$new_value|g" {} + +}\n\n`; + +// Add the updates for all VITE_* env variables +for (const [key, _] of Object.entries(viteEnv)) { + if (key.startsWith("VITE_")) { + const env = key.slice("VITE_".length); + entrypointScript += `update_env_vars_placeholders "/usr/share/nginx/html" "__${env}__" "${env}"\n`; + } +} + +// Start Nginx +entrypointScript += `\n# Start Nginx\nnginx -g 'daemon off;'`; + +console.log(entrypointScript); + +// Get the filename from command-line arguments +const args = process.argv.slice(2); +const outputFilename = args[0] || "entrypoint.sh"; // Default to entrypoint.sh if no argument is provided + +// Define the output file path +const outputFilePath = path.resolve(outputFilename); + +// Write the entrypoint script to the specified file +fs.writeFileSync(outputFilePath, entrypointScript, "utf-8"); + +// Set the file permissions to 777 (executable for all users) +fs.chmodSync(outputFilePath, 0o777); + +console.log( + `${outputFilename} file created with executable permissions (777)!` +); diff --git a/src/keycloak.ts b/src/keycloak.ts index 260f9c2..3b88376 100644 --- a/src/keycloak.ts +++ b/src/keycloak.ts @@ -1,9 +1,9 @@ import Keycloak from "keycloak-js"; const config = { - url: "https://iam.cloud.cbh.kth.se", - realm: "cloud", - clientId: "landing", + url: import.meta.env.VITE_KEYCLOAK_URL, + realm: import.meta.env.VITE_KEYCLOAK_REALM, + clientId: import.meta.env.VITE_KEYCLOAK_CLIENT_ID, }; const keycloak = new Keycloak(config); diff --git a/src/layouts/dashboard/Menu.tsx b/src/layouts/dashboard/Menu.tsx index 7b9c846..01cb856 100644 --- a/src/layouts/dashboard/Menu.tsx +++ b/src/layouts/dashboard/Menu.tsx @@ -153,7 +153,7 @@ export default function Menu() { {t("menu-status")} - {t("menu-cloudstack")} - - {t("menu-rancher")} {t("menu-keycloak")} diff --git a/src/pages/admin/Admin.tsx b/src/pages/admin/Admin.tsx index 1faf3a4..b1cd0fe 100644 --- a/src/pages/admin/Admin.tsx +++ b/src/pages/admin/Admin.tsx @@ -853,7 +853,7 @@ export const Admin = () => { {t("admin-edit-permissions-in") + " "} diff --git a/src/pages/profile/Profile.tsx b/src/pages/profile/Profile.tsx index 43ee6ea..bcf5839 100644 --- a/src/pages/profile/Profile.tsx +++ b/src/pages/profile/Profile.tsx @@ -259,7 +259,7 @@ export function Profile() {