Loading deployment/Chart.yaml +4 −5 Changes for deployment/Chart.yaml: 4 added lines, 5 removed lines. Original line number Diff line number Diff line apiVersion: v2 name: portal description: Helm chart for the Portal frontend (Next.js) description: Helm chart for the OOP Portal (developer portal UI and its backend) type: application version: 0.1.0 appVersion: "1.0.0" version: 1.0.0 appVersion: "2.0.0" keywords: - frontend - oop - etsi - portal home: https://labs.etsi.org/rep/oop/code/dev-portal home: https://labs.etsi.org/rep/oop/code/portal maintainers: - name: OOP Team deployment/README.md +41 −70 Changes for deployment/README.md: 41 added lines, 70 removed lines. Original line number Diff line number Diff line # Portal Helm Chart Deploy the Portal frontend (Next.js) to Kubernetes. Deploys the OOP developer portal: one container in which the backend serves the web UI and its API (`/api/*`) on the same address, so the login cookies stay first-party. ## Prerequisites The portal needs, from the umbrella chart: - Helm 3 - Kubernetes cluster - Portal image (build from `portal-gui/` or use a registry) - **PostgreSQL**: database and role `portal`, an entry in `postgresql.databases`. An init container waits until the role can log in. - **Keycloak** (unless `global.auth.enabled=false`): the `oop-portal` client logs users in, and `oop-portal-provisioner` creates developers' API clients. Their secrets come from the `keycloak-credentials` Secret. - **OEG** and the **AI2 agent**, which the backend forwards `/api/oeg/*` and `/api/ai2/chat` to. ## Build the image ## Addresses From the repo root: Browsers reach the portal and Keycloak on public URLs built from `global.publicHost`, `global.scheme` and `global.nodePorts`, as the keycloak chart builds them. The backend's own calls to Keycloak use `global.keycloak.host`/`port` instead, since the public address may not be reachable from pods. ```bash docker build -t portal-gui:latest -f portal/portal-gui/Dockerfile portal/portal-gui ``` For **Kind**, load the image into the cluster: ```bash kind load docker-image portal-gui:latest ``` ## Install ```bash cd portal/deployment helm install portal . ``` If you set the keycloak chart's `hostname` or `realms.oop.portal.baseUrl`, set `keycloak.publicUrl` or `publicUrl` here to match. Override the image tag to use your built image: ## Configuration ```bash helm install portal . --set image.tag=latest ``` | Parameter | Description | Default | |-----------|-------------|---------| | `image.repository` | Image repository | `labs.etsi.org:5050/oop/code/portal` | | `image.tag` | Image tag, also reported as the app version | `2.0.0` | | `publicUrl` | Address browsers reach the portal on | `<scheme>://<public host>:<NodePort>` | | `oeg.url` | Where `/api/oeg/*` is forwarded to | `http://oeg:80` | | `oeg.publicUrl` | OEG address shown with developers' API clients | `""` (not shown) | | `ai2.chatUrl` | AI2 agent chat endpoint; empty turns the chat off | `http://ai2-ai-agent:9013/groq-mcp` | | `keycloak.publicUrl` | Keycloak's public URL (token issuer) | `<scheme>://<public host>:<global.nodePorts.keycloak>` | | `keycloak.existingSecret` | Secret with the client secrets | `keycloak-credentials` | | `keycloak.provisioner.enabled` | API clients feature | `true` | | `keycloak.provisioner.oegClientId` | The keycloak chart's `realms.oop.oeg.internalId` | `oeg-client` | | `database.name` / `database.user` | Database and role | `portal` | | `database.passwordKey` | Key of the role's password in `global.postgresql.secretName` | `portal-password` | | `service.type` | Service type | `ClusterIP` (`NodePort` in the umbrella chart) | | `service.nodePort` | NodePort | `global.nodePorts.portal` | Set the OEG service URL (used by the frontend as `OEG_SERVICE_URL`): The API products shown in the portal come from `global.apiProducts`, the same list Keycloak's roles are built from. ```bash helm install portal . \ --set image.tag=latest \ --set config.oegServiceUrl=http://oeg-service:8080 ``` API clients' registration tokens are encrypted with a key generated into the Secret `portal-credentials` on first install. It is kept on `helm uninstall`, like the database it belongs with. If the default NodePort is already in use, pick another (30000–32767): ## Troubleshooting ```bash helm install portal . --set service.nodePort=30081 kubectl get pods -n oop -l app.kubernetes.io/name=portal kubectl logs -f deployment/portal -n oop kubectl logs deployment/portal -n oop -c wait-for-database ``` ## Upgrade ```bash helm upgrade portal . --set image.tag=latest ``` ## Get the URL After install, Helm prints the URL. You can also run: ```bash kubectl get svc -l app.kubernetes.io/name=portal -o jsonpath='http://{.items[0].spec.clusterIP}:{.items[0].spec.ports[0].port}' ``` For **NodePort**, use the node IP and `nodePort` (see `kubectl get svc -l app.kubernetes.io/name=portal`). ## Uninstall ```bash helm uninstall portal ``` ## Main values | Value | Default | Description | |-------|---------|-------------| | `image.repository` | `portal-gui` | Image name | | `image.tag` | `1.0.0` | Image tag | | `config.oegServiceUrl` | `""` | OEG service base URL (env `OEG_SERVICE_URL`) | | `service.type` | `NodePort` | Service type | | `service.nodePort` | `30082` | NodePort (when type is NodePort) | | `replicaCount` | `1` | Number of replicas | See `values.yaml` for all options. deployment/templates/NOTES.txtdeleted 100644 → 0 +0 −16 Changes for deployment/templates/NOTES.txt: 0 added lines, 16 removed lines. Original line number Diff line number Diff line Portal frontend has been deployed. 1. Get the application URL by running these commands: {{- if contains "NodePort" .Values.service.type }} export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "portal.fullname" . }}) export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") echo http://$NODE_IP:$NODE_PORT {{- else if contains "LoadBalancer" .Values.service.type }} NOTE: It may take a few minutes for the LoadBalancer IP to be available. kubectl get --namespace {{ .Release.Namespace }} svc {{ include "portal.fullname" . }} -w {{- else if contains "ClusterIP" .Values.service.type }} kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "portal.fullname" . }} {{ .Values.service.port }}:{{ .Values.service.port }} echo "Visit http://127.0.0.1:{{ .Values.service.port }}" {{- end }} OEG_SERVICE_URL is set to: {{ .Values.config.oegServiceUrl }} deployment/templates/_helpers.tpl +84 −20 Changes for deployment/templates/_helpers.tpl: 84 added lines, 20 removed lines. Original line number Diff line number Diff line {{- define "portal.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} {{- define "portal.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} {{- $name := default .Chart.Name .Values.nameOverride }} {{- if contains $name .Release.Name }} {{- else if contains .Chart.Name .Release.Name }} {{- .Release.Name | trunc 63 | trimSuffix "-" }} {{- else }} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} {{- end }} {{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" }} {{- end }} {{- end }} {{- define "portal.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{- define "portal.labels" -}} helm.sh/chart: {{ include "portal.chart" . }} helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{ include "portal.selectorLabels" . }} app.kubernetes.io/version: {{ .Values.image.tag | quote }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} {{- end }} {{- define "portal.selectorLabels" -}} app.kubernetes.io/name: {{ include "portal.name" . }} app.kubernetes.io/name: {{ .Chart.Name }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/component: portal {{- end }} {{/* Settings shared across the platform live in the umbrella chart's `global` block. Each helper below takes this chart's own value when set, else the global one, else a built-in default, so the chart also installs on its own. */}} {{- define "portal.authEnabled" -}} {{- if dig "auth" "enabled" true (.Values.global | default dict) }}true{{ end -}} {{- end }} {{- define "portal.scheme" -}} {{- dig "scheme" "http" (.Values.global | default dict) -}} {{- end }} {{/* global.publicHost if set, else the first node's ExternalIP, else its InternalIP, as the keycloak chart does, so both build the same URLs. */}} {{- define "portal.publicHost" -}} {{- $host := dig "publicHost" "" (.Values.global | default dict) -}} {{- if not $host -}} {{- $nodes := lookup "v1" "Node" "" "" -}} {{- if and $nodes $nodes.items -}} {{- $addresses := (index $nodes.items 0).status.addresses -}} {{- range $addresses }}{{ if and (not $host) (eq .type "ExternalIP") }}{{ $host = .address }}{{ end }}{{ end -}} {{- range $addresses }}{{ if and (not $host) (eq .type "InternalIP") }}{{ $host = .address }}{{ end }}{{ end -}} {{- end -}} {{- end -}} {{- $host | default "localhost" -}} {{- end }} {{- define "portal.publicUrl" -}} {{- if .Values.publicUrl -}} {{- trimSuffix "/" .Values.publicUrl -}} {{- else -}} {{- $port := .Values.service.nodePort | default (dig "nodePorts" "portal" 30082 (.Values.global | default dict)) -}} {{- printf "%s://%s:%v" (include "portal.scheme" .) (include "portal.publicHost" .) $port -}} {{- end -}} {{- end }} {{/* Keycloak's public URL: the issuer of every token, and where browsers log in. */}} {{- define "portal.keycloak.publicUrl" -}} {{- if .Values.keycloak.publicUrl -}} {{- trimSuffix "/" .Values.keycloak.publicUrl -}} {{- else -}} {{- $port := dig "nodePorts" "keycloak" 30081 (.Values.global | default dict) -}} {{- printf "%s://%s:%v" (include "portal.scheme" .) (include "portal.publicHost" .) $port -}} {{- end -}} {{- end }} {{/* Keycloak inside the cluster, for the backend's own calls: the public URL may not be reachable from pods (on kind it is localhost). */}} {{- define "portal.keycloak.internalUrl" -}} {{- $kc := (.Values.global | default dict).keycloak | default dict -}} {{- printf "http://%s:%v" ($kc.host | default "keycloak") ($kc.port | default 8080) -}} {{- end }} {{- define "portal.db.host" -}} {{- dig "postgresql" "host" "postgres" (.Values.global | default dict) -}} {{- end }} {{- define "portal.db.port" -}} {{- dig "postgresql" "port" 5432 (.Values.global | default dict) -}} {{- end }} {{- define "portal.db.secretName" -}} {{- dig "postgresql" "secretName" "postgres-credentials" (.Values.global | default dict) -}} {{- end }} {{- define "portal.db.waitImage" -}} {{- dig "images" "postgres" "postgres:18.6-alpine" (.Values.global | default dict) -}} {{- end }} {{- define "portal.configMapName" -}} {{- include "portal.fullname" . }}-config {{- define "portal.secretName" -}} {{- include "portal.fullname" . }}-credentials {{- end }} deployment/templates/configmap.yaml +27 −3 Changes for deployment/templates/configmap.yaml: 27 added lines, 3 removed lines. Original line number Diff line number Diff line apiVersion: v1 kind: ConfigMap metadata: name: {{ include "portal.configMapName" . }} name: {{ include "portal.fullname" . }} namespace: {{ .Release.Namespace }} labels: {{- include "portal.labels" . | nindent 4 }} app.kubernetes.io/component: portal data: OEG_SERVICE_URL: {{ .Values.config.oegServiceUrl | quote }} APP_VERSION: {{ .Values.image.tag | quote }} POSTGRESQL_SETTINGS__CREATE_SCHEMA_ON_STARTUP: "true" OEG__BASE_URL: {{ .Values.oeg.url | quote }} OEG__PUBLIC_BASE_URL: {{ .Values.oeg.publicUrl | quote }} AI2__CHAT_URL: {{ .Values.ai2.chatUrl | quote }} API_PRODUCTS__FILE: /etc/portal/api-products.json {{- if include "portal.authEnabled" . }} {{- $issuer := printf "%s/realms/%s" (include "portal.keycloak.publicUrl" .) .Values.keycloak.realm }} {{- $internal := printf "%s/realms/%s" (include "portal.keycloak.internalUrl" .) .Values.keycloak.realm }} AUTH__SECURITY_MODE: jwt SESSION__HTTPS_ONLY: {{ eq (include "portal.scheme" .) "https" | quote }} OIDC__ISSUER: {{ $issuer | quote }} OIDC__CLIENT_ID: {{ .Values.keycloak.clientId | quote }} OIDC__REDIRECT_URI: {{ printf "%s/api/auth/callback" (include "portal.publicUrl" .) | quote }} # Backend-to-Keycloak calls go in-cluster; the issuer stays public. OIDC__JWKS_URI: {{ printf "%s/protocol/openid-connect/certs" $internal | quote }} OIDC__TOKEN_ENDPOINT: {{ printf "%s/protocol/openid-connect/token" $internal | quote }} OIDC__ADMIN_BASE_URL: {{ include "portal.keycloak.internalUrl" . | quote }} {{- if .Values.keycloak.provisioner.enabled }} PROVISIONING__CLIENT_ID: {{ .Values.keycloak.provisioner.clientId | quote }} PROVISIONING__OEG_CLIENT_UUID: {{ .Values.keycloak.provisioner.oegClientId | quote }} {{- end }} {{- else }} AUTH__SECURITY_MODE: none {{- end }} api-products.json: {{ dict "products" (dig "apiProducts" (list) (.Values.global | default dict)) | toJson | quote }} Loading
deployment/Chart.yaml +4 −5 Changes for deployment/Chart.yaml: 4 added lines, 5 removed lines. Original line number Diff line number Diff line apiVersion: v2 name: portal description: Helm chart for the Portal frontend (Next.js) description: Helm chart for the OOP Portal (developer portal UI and its backend) type: application version: 0.1.0 appVersion: "1.0.0" version: 1.0.0 appVersion: "2.0.0" keywords: - frontend - oop - etsi - portal home: https://labs.etsi.org/rep/oop/code/dev-portal home: https://labs.etsi.org/rep/oop/code/portal maintainers: - name: OOP Team
deployment/README.md +41 −70 Changes for deployment/README.md: 41 added lines, 70 removed lines. Original line number Diff line number Diff line # Portal Helm Chart Deploy the Portal frontend (Next.js) to Kubernetes. Deploys the OOP developer portal: one container in which the backend serves the web UI and its API (`/api/*`) on the same address, so the login cookies stay first-party. ## Prerequisites The portal needs, from the umbrella chart: - Helm 3 - Kubernetes cluster - Portal image (build from `portal-gui/` or use a registry) - **PostgreSQL**: database and role `portal`, an entry in `postgresql.databases`. An init container waits until the role can log in. - **Keycloak** (unless `global.auth.enabled=false`): the `oop-portal` client logs users in, and `oop-portal-provisioner` creates developers' API clients. Their secrets come from the `keycloak-credentials` Secret. - **OEG** and the **AI2 agent**, which the backend forwards `/api/oeg/*` and `/api/ai2/chat` to. ## Build the image ## Addresses From the repo root: Browsers reach the portal and Keycloak on public URLs built from `global.publicHost`, `global.scheme` and `global.nodePorts`, as the keycloak chart builds them. The backend's own calls to Keycloak use `global.keycloak.host`/`port` instead, since the public address may not be reachable from pods. ```bash docker build -t portal-gui:latest -f portal/portal-gui/Dockerfile portal/portal-gui ``` For **Kind**, load the image into the cluster: ```bash kind load docker-image portal-gui:latest ``` ## Install ```bash cd portal/deployment helm install portal . ``` If you set the keycloak chart's `hostname` or `realms.oop.portal.baseUrl`, set `keycloak.publicUrl` or `publicUrl` here to match. Override the image tag to use your built image: ## Configuration ```bash helm install portal . --set image.tag=latest ``` | Parameter | Description | Default | |-----------|-------------|---------| | `image.repository` | Image repository | `labs.etsi.org:5050/oop/code/portal` | | `image.tag` | Image tag, also reported as the app version | `2.0.0` | | `publicUrl` | Address browsers reach the portal on | `<scheme>://<public host>:<NodePort>` | | `oeg.url` | Where `/api/oeg/*` is forwarded to | `http://oeg:80` | | `oeg.publicUrl` | OEG address shown with developers' API clients | `""` (not shown) | | `ai2.chatUrl` | AI2 agent chat endpoint; empty turns the chat off | `http://ai2-ai-agent:9013/groq-mcp` | | `keycloak.publicUrl` | Keycloak's public URL (token issuer) | `<scheme>://<public host>:<global.nodePorts.keycloak>` | | `keycloak.existingSecret` | Secret with the client secrets | `keycloak-credentials` | | `keycloak.provisioner.enabled` | API clients feature | `true` | | `keycloak.provisioner.oegClientId` | The keycloak chart's `realms.oop.oeg.internalId` | `oeg-client` | | `database.name` / `database.user` | Database and role | `portal` | | `database.passwordKey` | Key of the role's password in `global.postgresql.secretName` | `portal-password` | | `service.type` | Service type | `ClusterIP` (`NodePort` in the umbrella chart) | | `service.nodePort` | NodePort | `global.nodePorts.portal` | Set the OEG service URL (used by the frontend as `OEG_SERVICE_URL`): The API products shown in the portal come from `global.apiProducts`, the same list Keycloak's roles are built from. ```bash helm install portal . \ --set image.tag=latest \ --set config.oegServiceUrl=http://oeg-service:8080 ``` API clients' registration tokens are encrypted with a key generated into the Secret `portal-credentials` on first install. It is kept on `helm uninstall`, like the database it belongs with. If the default NodePort is already in use, pick another (30000–32767): ## Troubleshooting ```bash helm install portal . --set service.nodePort=30081 kubectl get pods -n oop -l app.kubernetes.io/name=portal kubectl logs -f deployment/portal -n oop kubectl logs deployment/portal -n oop -c wait-for-database ``` ## Upgrade ```bash helm upgrade portal . --set image.tag=latest ``` ## Get the URL After install, Helm prints the URL. You can also run: ```bash kubectl get svc -l app.kubernetes.io/name=portal -o jsonpath='http://{.items[0].spec.clusterIP}:{.items[0].spec.ports[0].port}' ``` For **NodePort**, use the node IP and `nodePort` (see `kubectl get svc -l app.kubernetes.io/name=portal`). ## Uninstall ```bash helm uninstall portal ``` ## Main values | Value | Default | Description | |-------|---------|-------------| | `image.repository` | `portal-gui` | Image name | | `image.tag` | `1.0.0` | Image tag | | `config.oegServiceUrl` | `""` | OEG service base URL (env `OEG_SERVICE_URL`) | | `service.type` | `NodePort` | Service type | | `service.nodePort` | `30082` | NodePort (when type is NodePort) | | `replicaCount` | `1` | Number of replicas | See `values.yaml` for all options.
deployment/templates/NOTES.txtdeleted 100644 → 0 +0 −16 Changes for deployment/templates/NOTES.txt: 0 added lines, 16 removed lines. Original line number Diff line number Diff line Portal frontend has been deployed. 1. Get the application URL by running these commands: {{- if contains "NodePort" .Values.service.type }} export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "portal.fullname" . }}) export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") echo http://$NODE_IP:$NODE_PORT {{- else if contains "LoadBalancer" .Values.service.type }} NOTE: It may take a few minutes for the LoadBalancer IP to be available. kubectl get --namespace {{ .Release.Namespace }} svc {{ include "portal.fullname" . }} -w {{- else if contains "ClusterIP" .Values.service.type }} kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "portal.fullname" . }} {{ .Values.service.port }}:{{ .Values.service.port }} echo "Visit http://127.0.0.1:{{ .Values.service.port }}" {{- end }} OEG_SERVICE_URL is set to: {{ .Values.config.oegServiceUrl }}
deployment/templates/_helpers.tpl +84 −20 Changes for deployment/templates/_helpers.tpl: 84 added lines, 20 removed lines. Original line number Diff line number Diff line {{- define "portal.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} {{- define "portal.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} {{- $name := default .Chart.Name .Values.nameOverride }} {{- if contains $name .Release.Name }} {{- else if contains .Chart.Name .Release.Name }} {{- .Release.Name | trunc 63 | trimSuffix "-" }} {{- else }} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} {{- end }} {{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" }} {{- end }} {{- end }} {{- define "portal.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{- define "portal.labels" -}} helm.sh/chart: {{ include "portal.chart" . }} helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{ include "portal.selectorLabels" . }} app.kubernetes.io/version: {{ .Values.image.tag | quote }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} {{- end }} {{- define "portal.selectorLabels" -}} app.kubernetes.io/name: {{ include "portal.name" . }} app.kubernetes.io/name: {{ .Chart.Name }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/component: portal {{- end }} {{/* Settings shared across the platform live in the umbrella chart's `global` block. Each helper below takes this chart's own value when set, else the global one, else a built-in default, so the chart also installs on its own. */}} {{- define "portal.authEnabled" -}} {{- if dig "auth" "enabled" true (.Values.global | default dict) }}true{{ end -}} {{- end }} {{- define "portal.scheme" -}} {{- dig "scheme" "http" (.Values.global | default dict) -}} {{- end }} {{/* global.publicHost if set, else the first node's ExternalIP, else its InternalIP, as the keycloak chart does, so both build the same URLs. */}} {{- define "portal.publicHost" -}} {{- $host := dig "publicHost" "" (.Values.global | default dict) -}} {{- if not $host -}} {{- $nodes := lookup "v1" "Node" "" "" -}} {{- if and $nodes $nodes.items -}} {{- $addresses := (index $nodes.items 0).status.addresses -}} {{- range $addresses }}{{ if and (not $host) (eq .type "ExternalIP") }}{{ $host = .address }}{{ end }}{{ end -}} {{- range $addresses }}{{ if and (not $host) (eq .type "InternalIP") }}{{ $host = .address }}{{ end }}{{ end -}} {{- end -}} {{- end -}} {{- $host | default "localhost" -}} {{- end }} {{- define "portal.publicUrl" -}} {{- if .Values.publicUrl -}} {{- trimSuffix "/" .Values.publicUrl -}} {{- else -}} {{- $port := .Values.service.nodePort | default (dig "nodePorts" "portal" 30082 (.Values.global | default dict)) -}} {{- printf "%s://%s:%v" (include "portal.scheme" .) (include "portal.publicHost" .) $port -}} {{- end -}} {{- end }} {{/* Keycloak's public URL: the issuer of every token, and where browsers log in. */}} {{- define "portal.keycloak.publicUrl" -}} {{- if .Values.keycloak.publicUrl -}} {{- trimSuffix "/" .Values.keycloak.publicUrl -}} {{- else -}} {{- $port := dig "nodePorts" "keycloak" 30081 (.Values.global | default dict) -}} {{- printf "%s://%s:%v" (include "portal.scheme" .) (include "portal.publicHost" .) $port -}} {{- end -}} {{- end }} {{/* Keycloak inside the cluster, for the backend's own calls: the public URL may not be reachable from pods (on kind it is localhost). */}} {{- define "portal.keycloak.internalUrl" -}} {{- $kc := (.Values.global | default dict).keycloak | default dict -}} {{- printf "http://%s:%v" ($kc.host | default "keycloak") ($kc.port | default 8080) -}} {{- end }} {{- define "portal.db.host" -}} {{- dig "postgresql" "host" "postgres" (.Values.global | default dict) -}} {{- end }} {{- define "portal.db.port" -}} {{- dig "postgresql" "port" 5432 (.Values.global | default dict) -}} {{- end }} {{- define "portal.db.secretName" -}} {{- dig "postgresql" "secretName" "postgres-credentials" (.Values.global | default dict) -}} {{- end }} {{- define "portal.db.waitImage" -}} {{- dig "images" "postgres" "postgres:18.6-alpine" (.Values.global | default dict) -}} {{- end }} {{- define "portal.configMapName" -}} {{- include "portal.fullname" . }}-config {{- define "portal.secretName" -}} {{- include "portal.fullname" . }}-credentials {{- end }}
deployment/templates/configmap.yaml +27 −3 Changes for deployment/templates/configmap.yaml: 27 added lines, 3 removed lines. Original line number Diff line number Diff line apiVersion: v1 kind: ConfigMap metadata: name: {{ include "portal.configMapName" . }} name: {{ include "portal.fullname" . }} namespace: {{ .Release.Namespace }} labels: {{- include "portal.labels" . | nindent 4 }} app.kubernetes.io/component: portal data: OEG_SERVICE_URL: {{ .Values.config.oegServiceUrl | quote }} APP_VERSION: {{ .Values.image.tag | quote }} POSTGRESQL_SETTINGS__CREATE_SCHEMA_ON_STARTUP: "true" OEG__BASE_URL: {{ .Values.oeg.url | quote }} OEG__PUBLIC_BASE_URL: {{ .Values.oeg.publicUrl | quote }} AI2__CHAT_URL: {{ .Values.ai2.chatUrl | quote }} API_PRODUCTS__FILE: /etc/portal/api-products.json {{- if include "portal.authEnabled" . }} {{- $issuer := printf "%s/realms/%s" (include "portal.keycloak.publicUrl" .) .Values.keycloak.realm }} {{- $internal := printf "%s/realms/%s" (include "portal.keycloak.internalUrl" .) .Values.keycloak.realm }} AUTH__SECURITY_MODE: jwt SESSION__HTTPS_ONLY: {{ eq (include "portal.scheme" .) "https" | quote }} OIDC__ISSUER: {{ $issuer | quote }} OIDC__CLIENT_ID: {{ .Values.keycloak.clientId | quote }} OIDC__REDIRECT_URI: {{ printf "%s/api/auth/callback" (include "portal.publicUrl" .) | quote }} # Backend-to-Keycloak calls go in-cluster; the issuer stays public. OIDC__JWKS_URI: {{ printf "%s/protocol/openid-connect/certs" $internal | quote }} OIDC__TOKEN_ENDPOINT: {{ printf "%s/protocol/openid-connect/token" $internal | quote }} OIDC__ADMIN_BASE_URL: {{ include "portal.keycloak.internalUrl" . | quote }} {{- if .Values.keycloak.provisioner.enabled }} PROVISIONING__CLIENT_ID: {{ .Values.keycloak.provisioner.clientId | quote }} PROVISIONING__OEG_CLIENT_UUID: {{ .Values.keycloak.provisioner.oegClientId | quote }} {{- end }} {{- else }} AUTH__SECURITY_MODE: none {{- end }} api-products.json: {{ dict "products" (dig "apiProducts" (list) (.Values.global | default dict)) | toJson | quote }}