diff --git a/CHANGELOG.md b/CHANGELOG.md index 6212f1afc..70aa9da14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ - Jenkins master and agent maintenance. Add Rhel9 variant and make it default ([#1361](https://github.com/opendevstack/ods-core/pull/1361)) - Update tailor to 1.4.0 ([#1373](https://github.com/opendevstack/ods-core/pull/1373)) - Update Jenkins java version to jdk 21 ([#1374](https://github.com/opendevstack/ods-core/pull/1374)) -- Add new configuration for the ODS API Service ([1375](https://github.com/opendevstack/ods-core/pull/1375)) +- Add new configuration for the ODS API Service ([1375](https://github.com/opendevstack/ods-core/pull/1375)) ([1377](https://github.com/opendevstack/ods-core/pull/1377)) ### Fixed diff --git a/Makefile b/Makefile index 3e6466d92..b6b74e6ae 100644 --- a/Makefile +++ b/Makefile @@ -19,9 +19,6 @@ ifeq ($(INSECURE), $(filter $(INSECURE), true yes)) endif # ODS API Service configuration files -env ?= dev -ENV ?= $(env) -env := $(ENV) ODS_CONFIGURATION_DIR := ../ods-configuration ODS_CONFIGURATION_FULL_PATH := $(abspath $(ODS_CONFIGURATION_DIR)) ODS_API_SERVICE_DATABASE_REPO := $(ODS_API_SERVICE_DIR:-.../ods-api-service) @@ -190,19 +187,85 @@ start-opentelemetry-collector-build: ocp-scripts/start-and-follow-build.sh --namespace $(ODS_NAMESPACE) --build-config opentelemetry-collector .PHONY: start-opentelemetry-collector-build +#################### # ODS API SERVICE +#################### ## Install or update Ods API Service. -install-ods-api-service: start-ods-api-service-build apply-ods-api-service-chart configure-ods-api-service +check-configuration-defined: +ifndef env + $(error "Environment variable 'env' is not defined. Please set it to the desired environment (e.g., dev, staging, prod) before running this target.") +endif + + @if [ ! -d "../ods-api-service" ]; then \ + echo "Error: ods-api-service directory not found at ../ods-api-service"; \ + exit 1; \ + fi + @if [ ! -d "$(ODS_CONFIGURATION_FULL_PATH)" ]; then \ + echo "Error: ods-configuration directory not found at $(ODS_CONFIGURATION_FULL_PATH)"; \ + exit 1; \ + fi + @if [ ! -f "$(ODS_CONFIGURATION_FULL_PATH)/ods-core.values.yaml" ]; then \ + echo "Error: File not found: $(ODS_CONFIGURATION_FULL_PATH)/ods-core.values.yaml"; \ + exit 1; \ + fi + @if [ ! -f "$(ODS_CONFIGURATION_FULL_PATH)/ods-core.secrets.enc.yaml" ]; then \ + echo "Error: File not found: $(ODS_CONFIGURATION_FULL_PATH)/ods-core.secrets.enc.yaml"; \ + exit 1; \ + fi + @if [ ! -f "$(ODS_CONFIGURATION_FULL_PATH)/ods-api-service/values.yaml" ]; then \ + echo "Error: File not found: $(ODS_CONFIGURATION_FULL_PATH)/ods-api-service/values.yaml"; \ + exit 1; \ + fi + @if [ ! -f "$(ODS_CONFIGURATION_FULL_PATH)/ods-api-service/secrets.enc.yaml" ]; then \ + echo "Error: File not found: $(ODS_CONFIGURATION_FULL_PATH)/ods-api-service/secrets.enc.yaml"; \ + exit 1; \ + fi + @if [ ! -f "$(ODS_CONFIGURATION_FULL_PATH)/ods-api-service/$(env)/values.$(env).yaml" ]; then \ + echo "Error: File not found: $(ODS_CONFIGURATION_FULL_PATH)/ods-api-service/$(env)/values.$(env).yaml"; \ + exit 1; \ + fi + @if [ ! -f "$(ODS_CONFIGURATION_FULL_PATH)/ods-api-service/$(env)/secrets.$(env).enc.yaml" ]; then \ + echo "Error: File not found: $(ODS_CONFIGURATION_FULL_PATH)/ods-api-service/$(env)/secrets.$(env).enc.yaml"; \ + exit 1; \ + fi + @echo "All validation checks passed!" + +.PHONY: check-configuration-defined + +install-ods-api-service: \ + check-configuration-defined \ + start-ods-api-service-build \ + start-ods-api-service-database-build \ + apply-ods-api-service-database-chart \ + configure-ods-api-service-database-backup \ + ods-api-service-db-migration \ + apply-ods-api-service-chart .PHONY: ods-api-service ## Start build of BuildConfig "Ods API Service". start-ods-api-service-build: - cd ods-api-service/build-config && oc process -f template.yaml -p ODS_NAMESPACE=$(ODS_NAMESPACE) -p ODS_IMAGE_TAG=$(ODS_IMAGE_TAG) -p BITBUCKET_URL=$(BITBUCKET_URL) -p ODS_BITBUCKET_PROJECT=$(ODS_BITBUCKET_PROJECT) -p ODS_GIT_REF=$(ODS_GIT_REF) -p ODS_API_SERVICE_VERSION=$(ODS_API_SERVICE_VERSION) | oc apply --namespace $(ODS_NAMESPACE) -f - - ocp-scripts/start-and-follow-build.sh --namespace $(ODS_NAMESPACE) --build-config ods-api-service && ocp-scripts/start-and-follow-build.sh --namespace $(ODS_NAMESPACE) --build-config ods-api-service-postgresql + cd ods-api-service/build-config && oc process -f template-ods-api-service.yaml \ + -p ODS_NAMESPACE=$(ODS_NAMESPACE) \ + -p ODS_IMAGE_TAG=$(ODS_IMAGE_TAG) \ + -p BITBUCKET_URL=$(BITBUCKET_URL) \ + -p ODS_BITBUCKET_PROJECT=$(ODS_BITBUCKET_PROJECT) \ + -p ODS_GIT_REF=$(ODS_GIT_REF) \ + -p ODS_API_SERVICE_VERSION=$(ODS_API_SERVICE_VERSION) | oc apply --namespace $(ODS_NAMESPACE) -f - + ocp-scripts/start-and-follow-build.sh --namespace $(ODS_NAMESPACE) --build-config ods-api-service .PHONY: start-ods-api-service-build +## Start build of BuildConfig "Ods API Service Database". +start-ods-api-service-database-build: + cd ods-api-service-database/build-config && oc process -f template-postgresql.yaml \ + -p ODS_NAMESPACE=$(ODS_NAMESPACE) \ + -p BITBUCKET_URL=$(BITBUCKET_URL) \ + -p ODS_BITBUCKET_PROJECT=$(ODS_BITBUCKET_PROJECT) \ + -p ODS_GIT_REF=$(ODS_GIT_REF) \ + -p ODS_DATABASE_VERSION=$(ODS_DATABASE_VERSION) | oc apply --namespace $(ODS_NAMESPACE) -f - + ocp-scripts/start-and-follow-build.sh --namespace $(ODS_NAMESPACE) --build-config ods-api-service-postgresql +.PHONY: start-ods-api-service-database-build ## Apply OpenShift resources related to the Ods API Service. -apply-ods-api-service-chart: +apply-ods-api-service-chart: check-configuration-defined cd ods-api-service/chart && \ helm secrets upgrade --install --namespace $(ODS_NAMESPACE) \ -f $(ODS_CONFIGURATION_FULL_PATH)/ods-core.values.yaml \ @@ -220,17 +283,62 @@ apply-ods-api-service-chart: --set global.registry=$(DOCKER_REGISTRY) \ --set global.componentId=ods-api-service \ --set imageNamespace=$(ODS_NAMESPACE) \ - --set imageTag=$(ODS_IMAGE_TAG) \ + --set imageTag=$(ODS_API_SERVICE_VERSION) \ --set global.imageNamespace=$(ODS_NAMESPACE) \ - --set global.imageTag=$(ODS_IMAGE_TAG) \ + --set global.imageTag=$(ODS_API_SERVICE_VERSION) \ --set ODS_OPENSHIFT_APP_DOMAIN=$(OPENSHIFT_APPS_BASEDOMAIN) \ ods-api-service . .PHONY: apply-ods-api-service-chart +## Apply OpenShift resources related to the Ods API Service Database. +apply-ods-api-service-database-chart: check-configuration-defined + cd ods-api-service-database/chart && \ + helm secrets upgrade --install --namespace $(ODS_NAMESPACE) \ + -f $(ODS_CONFIGURATION_FULL_PATH)/ods-core.values.yaml \ + -f $(ODS_CONFIGURATION_FULL_PATH)/ods-core.secrets.enc.yaml \ + -f $(ODS_CONFIGURATION_FULL_PATH)/ods-api-service/values.yaml \ + -f $(ODS_CONFIGURATION_FULL_PATH)/ods-api-service/secrets.enc.yaml \ + -f $(ODS_CONFIGURATION_FULL_PATH)/ods-api-service/$(env)/values.$(env).yaml \ + -f $(ODS_CONFIGURATION_FULL_PATH)/ods-api-service/$(env)/secrets.$(env).enc.yaml \ + --set projectId=$(ODS_NAMESPACE) \ + --set appSelector=app=ods-api-service \ + --set registry=$(DOCKER_REGISTRY) \ + --set componentId=ods-api-service \ + --set global.projectId=$(ODS_NAMESPACE) \ + --set global.appSelector=app=ods-api-service \ + --set global.registry=$(DOCKER_REGISTRY) \ + --set global.componentId=ods-api-service \ + --set imageNamespace=$(ODS_NAMESPACE) \ + --set imageTag=$(ODS_DATABASE_VERSION) \ + --set global.imageNamespace=$(ODS_NAMESPACE) \ + --set global.imageTag=$(ODS_DATABASE_VERSION) \ + --set ODS_OPENSHIFT_APP_DOMAIN=$(OPENSHIFT_APPS_BASEDOMAIN) \ + ods-api-service-postgresql . +.PHONY: apply-ods-api-service-database-chart + +## Run database migration for ODS API Service. This will port-forward the PostgreSQL service to localhost and run the migration command, then stop the port-forwarding. +ods-api-service-db-migration: + @cd ../ods-api-service && { \ + make db-port-forward NAMESPACE=$(ODS_NAMESPACE) & \ + PF_PID=$$!; \ + export ODS_API_SERVICE_DB_HOST=localhost \ + ODS_API_SERVICE_DB_PORT=5432 \ + ODS_API_SERVICE_DB_NAME=$(ODS_API_SERVICE_DB_NAME) \ + ODS_API_SERVICE_DB_USER=$(ODS_API_SERVICE_DB_USER) \ + ODS_API_SERVICE_DB_PASSWORD=$(ODS_API_SERVICE_DB_PASSWORD); \ + make db-migrate; \ + MIGRATE_RC=$$?; \ + echo "Database migration completed. Stopping port-forwarding..."; \ + kill $$PF_PID 2>/dev/null || true; \ + wait $$PF_PID 2>/dev/null || true; \ + exit $$MIGRATE_RC; \ + } +.PHONY: ods-api-service-db-migration + ## Configure ODS API Service (sets up PostgreSQL superuser for backup operations). -configure-ods-api-service: - cd ods-api-service && ./configure.sh --namespace $(ODS_NAMESPACE) -.PHONY: configure-ods-api-service +configure-ods-api-service-database-backup: + cd ods-api-service-database && ./configure.sh --namespace $(ODS_NAMESPACE) +.PHONY: configure-ods-api-service-database-backup # BACKUP ## Create a backup of the current state. diff --git a/ods-api-service-database/build-config/template-postgresql.yaml b/ods-api-service-database/build-config/template-postgresql.yaml new file mode 100644 index 000000000..cd0efe006 --- /dev/null +++ b/ods-api-service-database/build-config/template-postgresql.yaml @@ -0,0 +1,79 @@ +--- +apiVersion: template.openshift.io/v1 +kind: Template +metadata: + name: ods-api-service-database + annotations: + description: "Template for ODS API Service Database BuildConfig and ImageStream" +parameters: + - name: ODS_NAMESPACE + description: "ODS namespace" + required: true + - name: BITBUCKET_URL + description: "Bitbucket URL" + required: true + - name: ODS_BITBUCKET_PROJECT + description: "ODS Bitbucket project key" + required: true + - name: ODS_GIT_REF + description: "Git reference (branch or tag)" + required: true + - name: ODS_DATABASE_VERSION + description: "Database image tag" + required: true +objects: + # ImageStream for the ODS API Service PostgreSQL database + - apiVersion: image.openshift.io/v1 + kind: ImageStream + metadata: + name: ods-api-service-postgresql + namespace: ${ODS_NAMESPACE} + labels: + app: ods-api-service + component: postgresql + spec: + lookupPolicy: + local: false + + # BuildConfig for ODS API Service PostgreSQL database + # Uses Dockerfile.database (base: public.ecr.aws/docker/library/postgres:18-alpine + oc CLI) + - apiVersion: build.openshift.io/v1 + kind: BuildConfig + metadata: + name: ods-api-service-postgresql + namespace: ${ODS_NAMESPACE} + labels: + app: ods-api-service + component: postgresql + spec: + nodeSelector: null + output: + to: + kind: ImageStreamTag + name: ods-api-service-postgresql:${ODS_DATABASE_VERSION} + resources: + limits: + cpu: '1' + memory: 2Gi + requests: + cpu: 200m + memory: 1Gi + successfulBuildsHistoryLimit: 5 + failedBuildsHistoryLimit: 5 + strategy: + type: Docker + dockerStrategy: + dockerfilePath: Dockerfile.database + forcePull: true + noCache: true + postCommit: {} + source: + type: Git + binary: null + git: + uri: ${BITBUCKET_URL}/scm/${ODS_BITBUCKET_PROJECT}/ods-core.git + ref: ${ODS_GIT_REF} + contextDir: ods-api-service-database/docker + sourceSecret: + name: cd-user-token + runPolicy: Serial diff --git a/ods-api-service-database/chart/Chart.yaml b/ods-api-service-database/chart/Chart.yaml new file mode 100644 index 000000000..17a9504a5 --- /dev/null +++ b/ods-api-service-database/chart/Chart.yaml @@ -0,0 +1,10 @@ +apiVersion: v2 +name: ods-api-service-postgresql +description: A Helm chart for deploying ODS API Service on OpenShift +type: application +version: 0.1.0 +appVersion: "0.0.1" +maintainers: + - name: ODS Team +keywords: + - postgresql \ No newline at end of file diff --git a/ods-api-service/chart/templates/postgresql/cronjob-backup.yaml b/ods-api-service-database/chart/templates/postgresql/cronjob-backup.yaml similarity index 94% rename from ods-api-service/chart/templates/postgresql/cronjob-backup.yaml rename to ods-api-service-database/chart/templates/postgresql/cronjob-backup.yaml index 5f212a590..83ba69cdf 100644 --- a/ods-api-service/chart/templates/postgresql/cronjob-backup.yaml +++ b/ods-api-service-database/chart/templates/postgresql/cronjob-backup.yaml @@ -1,7 +1,7 @@ apiVersion: batch/v1 kind: CronJob metadata: - name: {{ include "chart.fullname" . }}-postgresql-backup + name: {{ include "chart.fullname" . }}-backup labels: {{- include "chart.labels" . | nindent 4 }} app.kubernetes.io/component: postgresql-backup @@ -22,7 +22,7 @@ spec: serviceAccountName: ods-edit containers: - name: postgresql-backup - image: {{ .Values.postgresql.internalRegistry }}/{{ .Values.postgresql.odsNamespace }}/{{ include "chart.fullname" . }}-postgresql:{{ .Values.postgresql.odsImageTag }} + image: {{ .Values.postgresql.internalRegistry }}/{{ .Values.postgresql.odsNamespace }}/{{ include "chart.fullname" . }}:{{ .Values.postgresql.odsImageTag }} imagePullPolicy: Always resources: limits: @@ -37,7 +37,7 @@ spec: - name: PGPASSWORD valueFrom: secretKeyRef: - name: {{ include "chart.fullname" . }}-postgresql + name: {{ include "chart.fullname" . }} key: ODS_API_SERVICE_DB_SUPERUSER_PASSWORD command: - /bin/bash @@ -47,14 +47,14 @@ spec: set -e # Compute snapshot name - SNAP_NAME="{{ include "chart.fullname" . }}-postgresql-snapshot-$(date +%Y-%m-%d-%H-%M-%S)" - DB_HOST="{{ include "chart.fullname" . }}-postgresql" + SNAP_NAME="{{ include "chart.fullname" . }}-snapshot-$(date +%Y-%m-%d-%H-%M-%S)" + DB_HOST="{{ include "chart.fullname" . }}" DB_USER="{{ .Values.postgresql.superuserName }}" DB_NAME="{{ .Values.postgresql.databaseName }}" ODS_NAMESPACE="{{ .Values.postgresql.odsNamespace }}" STORAGE_CLASS="{{ .Values.postgresql.backup.snapshotStorageClass }}" APP_NAME="{{ include "chart.fullname" . }}" - PVC_NAME="postgresql-data-{{ include "chart.fullname" . }}-postgresql-0" + PVC_NAME="postgresql-data-{{ include "chart.fullname" . }}-0" echo "Starting PostgreSQL backup process..." diff --git a/ods-api-service/chart/templates/postgresql/secret.yaml b/ods-api-service-database/chart/templates/postgresql/secret.yaml similarity index 89% rename from ods-api-service/chart/templates/postgresql/secret.yaml rename to ods-api-service-database/chart/templates/postgresql/secret.yaml index b7fe1b0b9..93e1d80f1 100644 --- a/ods-api-service/chart/templates/postgresql/secret.yaml +++ b/ods-api-service-database/chart/templates/postgresql/secret.yaml @@ -4,7 +4,7 @@ metadata: labels: {{- include "chart.labels" . | nindent 4 }} app.kubernetes.io/component: postgresql - name: {{ include "chart.fullname" . }}-postgresql + name: {{ include "chart.fullname" . }} type: Opaque data: ODS_API_SERVICE_DB_NAME: {{ .Values.postgresql.databaseNameB64 }} diff --git a/ods-api-service/chart/templates/postgresql/service.yaml b/ods-api-service-database/chart/templates/postgresql/service.yaml similarity index 79% rename from ods-api-service/chart/templates/postgresql/service.yaml rename to ods-api-service-database/chart/templates/postgresql/service.yaml index 7f95f6fdd..e6360ed80 100644 --- a/ods-api-service/chart/templates/postgresql/service.yaml +++ b/ods-api-service-database/chart/templates/postgresql/service.yaml @@ -6,7 +6,7 @@ metadata: labels: {{- include "chart.labels" . | nindent 4 }} app.kubernetes.io/component: postgresql - name: {{ include "chart.fullname" . }}-postgresql + name: {{ include "chart.fullname" . }} spec: ports: - name: postgresql @@ -14,6 +14,6 @@ spec: protocol: TCP targetPort: 5432 selector: - app: {{ include "chart.fullname" . }}-postgresql + app: {{ include "chart.fullname" . }} sessionAffinity: None type: ClusterIP diff --git a/ods-api-service/chart/templates/postgresql/statefulset.yaml b/ods-api-service-database/chart/templates/postgresql/statefulset.yaml similarity index 82% rename from ods-api-service/chart/templates/postgresql/statefulset.yaml rename to ods-api-service-database/chart/templates/postgresql/statefulset.yaml index 5a6b118bf..69c2a31b9 100644 --- a/ods-api-service/chart/templates/postgresql/statefulset.yaml +++ b/ods-api-service-database/chart/templates/postgresql/statefulset.yaml @@ -1,24 +1,24 @@ apiVersion: apps/v1 kind: StatefulSet metadata: - name: {{ include "chart.fullname" . }}-postgresql + name: {{ include "chart.fullname" . }} labels: {{- include "chart.labels" . | nindent 4 }} app.kubernetes.io/component: postgresql spec: - serviceName: {{ include "chart.fullname" . }}-postgresql + serviceName: {{ include "chart.fullname" . }} replicas: 1 selector: matchLabels: - app: {{ include "chart.fullname" . }}-postgresql + app: {{ include "chart.fullname" . }} template: metadata: labels: - app: {{ include "chart.fullname" . }}-postgresql + app: {{ include "chart.fullname" . }} spec: containers: - name: postgresql - image: {{ .Values.postgresql.internalRegistry }}/{{ .Values.postgresql.odsNamespace }}/{{ include "chart.fullname" . }}-postgresql:{{ .Values.postgresql.odsImageTag }} + image: {{ .Values.postgresql.internalRegistry }}/{{ .Values.postgresql.odsNamespace }}/ods-api-service-postgresql:{{ .Values.postgresql.odsImageTag }} imagePullPolicy: Always ports: - name: postgresql @@ -28,22 +28,22 @@ spec: - name: POSTGRES_USER valueFrom: secretKeyRef: - name: {{ include "chart.fullname" . }}-postgresql + name: {{ include "chart.fullname" . }} key: ODS_API_SERVICE_DB_USER - name: PGUSER valueFrom: secretKeyRef: - name: {{ include "chart.fullname" . }}-postgresql + name: {{ include "chart.fullname" . }} key: ODS_API_SERVICE_DB_USER - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: - name: {{ include "chart.fullname" . }}-postgresql + name: {{ include "chart.fullname" . }} key: ODS_API_SERVICE_DB_PASSWORD - name: POSTGRES_DB valueFrom: secretKeyRef: - name: {{ include "chart.fullname" . }}-postgresql + name: {{ include "chart.fullname" . }} key: ODS_API_SERVICE_DB_NAME - name: PGDATA value: /var/lib/postgresql/data/pgdata @@ -103,7 +103,7 @@ spec: volume.beta.kubernetes.io/storage-provisioner: {{ .Values.postgresql.storageProvisioner }} helm.sh/resource-policy: keep labels: - app: {{ include "chart.fullname" . }}-postgresql + app: {{ include "chart.fullname" . }} spec: accessModes: - ReadWriteOnce diff --git a/ods-api-service-database/chart/templates/tpl/_helpers.tpl b/ods-api-service-database/chart/templates/tpl/_helpers.tpl new file mode 100644 index 000000000..e939379db --- /dev/null +++ b/ods-api-service-database/chart/templates/tpl/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "chart.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "chart.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "chart.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "chart.labels" -}} +helm.sh/chart: {{ include "chart.chart" . }} +{{ include "chart.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "chart.selectorLabels" -}} +app: {{ printf "%s-%s" .Values.projectId .Values.componentId | trimPrefix "-" }} +app.kubernetes.io/name: {{ include "chart.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "chart.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "chart.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/ods-api-service-database/chart/values.yaml.template b/ods-api-service-database/chart/values.yaml.template new file mode 100644 index 000000000..3b072ba8b --- /dev/null +++ b/ods-api-service-database/chart/values.yaml.template @@ -0,0 +1,42 @@ +## Default values for chart. +## This is a YAML-formatted file. Intendation matters! +## Comments are prefixed with two hashes (##), examples are commented with one hash (#) +## Declare variables to be passed into your templates. + +## PostgreSQL database configuration +postgresql: + ## Internal OpenShift registry and namespace where the built image is stored. + ## The image is built via the BuildConfig using Dockerfile.database (base: public.ecr.aws/docker/library/postgres:18-alpine) + internalRegistry: $ODS_API_SERVICE_DB_INTERNAL_REGISTRY + odsNamespace: $ODS_NAMESPACE + odsImageTag: $ODS_IMAGE_TAG + ## Plain-text database details (used in backup scripts and connection strings) + databaseName: $ODS_API_SERVICE_DB_NAME + databaseUser: $ODS_API_SERVICE_DB_USER + ## Name of the PostgreSQL superuser (default 'postgres' in official image) + superuserName: $ODS_API_SERVICE_DB_SUPER_NAME + ## Base64-encoded credentials stored in the Secret + databaseNameB64: $ODS_API_SERVICE_DB_NAME_B64 + databaseUserB64: $ODS_API_SERVICE_DB_USER_B64 + databasePasswordB64: $ODS_API_SERVICE_DB_PASSWORD_B64 + superuserPasswordB64: $ODS_API_SERVICE_DB_SUPER_PASSWORD_B64 + ## Resource limits/requests for the PostgreSQL container + cpuLimit: $ODS_API_SERVICE_DB_CPU_LIMIT + cpuRequest: $ODS_API_SERVICE_DB_CPU_REQUEST + memLimit: $ODS_API_SERVICE_DB_MEMORY_LIMIT + memRequest: $ODS_API_SERVICE_DB_MEMORY_REQUEST + ## PVC storage for database data + pvcDatabaseCapacity: $ODS_API_SERVICE_DB_CAPACITY + storageClassName: $ODS_API_SERVICE_DB_STORAGE_CLASS + storageProvisioner: $ODS_API_SERVICE_DB_STORAGE_PROVISIONER + ## Backup configuration + backup: + ## The backup job uses the same built image as the DB container (includes psql + oc CLI) + ## Snapshots are created in the namespace defined by postgresql.odsNamespace + ## Cron schedule for the backup job (default: daily at 02:00) + schedule: $ODS_API_SERVICE_DB_BACKUP_SCHEDULE + ## VolumeSnapshotClass used for storage snapshots + snapshotStorageClass: $ODS_API_SERVICE_DB_BACKUP_SNAPSHOT_CLASS + successHistoryLimit: $ODS_API_SERVICE_DB_BACKUP_SUCCESS_HISTORY_LIMIT + failedHistoryLimit: $ODS_API_SERVICE_DB_BACKUP_FAILED_HISTORY_LIMIT + diff --git a/ods-api-service/configure.sh b/ods-api-service-database/configure.sh similarity index 100% rename from ods-api-service/configure.sh rename to ods-api-service-database/configure.sh diff --git a/ods-api-service/docker/Dockerfile.database b/ods-api-service-database/docker/Dockerfile.database similarity index 100% rename from ods-api-service/docker/Dockerfile.database rename to ods-api-service-database/docker/Dockerfile.database diff --git a/ods-api-service/build-config/template.yaml b/ods-api-service/build-config/template-ods-api-service.yaml similarity index 58% rename from ods-api-service/build-config/template.yaml rename to ods-api-service/build-config/template-ods-api-service.yaml index fdab76966..d67587e59 100644 --- a/ods-api-service/build-config/template.yaml +++ b/ods-api-service/build-config/template-ods-api-service.yaml @@ -23,7 +23,7 @@ parameters: required: true - name: ODS_API_SERVICE_VERSION description: "API Service version" - required: false + required: true value: "latest" objects: # ImageStream for the ODS API Service @@ -53,7 +53,7 @@ objects: output: to: kind: ImageStreamTag - name: ods-api-service:${ODS_IMAGE_TAG} + name: ods-api-service:${ODS_API_SERVICE_VERSION} resources: limits: cpu: '1' @@ -77,6 +77,7 @@ objects: postCommit: {} source: type: Git + binary: null git: uri: ${BITBUCKET_URL}/scm/${ODS_BITBUCKET_PROJECT}/ods-core.git ref: ${ODS_GIT_REF} @@ -85,57 +86,3 @@ objects: name: cd-user-token runPolicy: Serial - # ImageStream for the ODS API Service PostgreSQL database - - apiVersion: image.openshift.io/v1 - kind: ImageStream - metadata: - name: ods-api-service-postgresql - namespace: ${ODS_NAMESPACE} - labels: - app: ods-api-service - component: postgresql - spec: - lookupPolicy: - local: false - - # BuildConfig for ODS API Service PostgreSQL database - # Uses Dockerfile.database (base: public.ecr.aws/docker/library/postgres:18-alpine + oc CLI) - - apiVersion: build.openshift.io/v1 - kind: BuildConfig - metadata: - name: ods-api-service-postgresql - namespace: ${ODS_NAMESPACE} - labels: - app: ods-api-service - component: postgresql - spec: - nodeSelector: null - output: - to: - kind: ImageStreamTag - name: ods-api-service-postgresql:${ODS_IMAGE_TAG} - resources: - limits: - cpu: '1' - memory: 2Gi - requests: - cpu: 200m - memory: 1Gi - successfulBuildsHistoryLimit: 5 - failedBuildsHistoryLimit: 5 - strategy: - type: Docker - dockerStrategy: - dockerfilePath: Dockerfile.database - forcePull: true - noCache: true - postCommit: {} - source: - type: Git - git: - uri: ${BITBUCKET_URL}/scm/${ODS_BITBUCKET_PROJECT}/ods-core.git - ref: ${ODS_GIT_REF} - contextDir: ods-api-service/docker - sourceSecret: - name: cd-user-token - runPolicy: Serial diff --git a/ods-api-service/chart/templates/core/deployment.yaml b/ods-api-service/chart/templates/core/deployment.yaml index c396aa18f..eae3c865d 100644 --- a/ods-api-service/chart/templates/core/deployment.yaml +++ b/ods-api-service/chart/templates/core/deployment.yaml @@ -16,6 +16,13 @@ spec: {{- include "chart.selectorLabels" . | nindent 6 }} template: metadata: + annotations: + checksum/configmap-application: {{ include (print $.Template.BasePath "/core/configmaps-application.yaml") . | sha256sum }} + checksum/configmap-services: {{ include (print $.Template.BasePath "/core/configmaps-services.yaml") . | sha256sum }} + checksum/configmap-external-services: {{ include (print $.Template.BasePath "/core/configmaps-external-services.yaml") . | sha256sum }} + checksum/secret-application: {{ include (print $.Template.BasePath "/core/secrets-application.yaml") . | sha256sum }} + checksum/secret-services: {{ include (print $.Template.BasePath "/core/secrets-services.yaml") . | sha256sum }} + checksum/secret-external-services: {{ include (print $.Template.BasePath "/core/secrets-external-services.yaml") . | sha256sum }} labels: {{- include "chart.selectorLabels" . | nindent 8 }} spec: diff --git a/ods-api-service/chart/templates/core/ingress.yaml b/ods-api-service/chart/templates/core/ingress.yaml index 0dba0fd22..523b3be1a 100644 --- a/ods-api-service/chart/templates/core/ingress.yaml +++ b/ods-api-service/chart/templates/core/ingress.yaml @@ -51,7 +51,7 @@ spec: {{- end }} {{- else }} rules: - - host: {{ .Values.componentId }}-{{ .Values.imageNamespace }}{{ .Values.ODS_OPENSHIFT_APP_DOMAIN }} + - host: {{ .Values.componentId }}-{{ .Values.imageNamespace }}{{ or .Values.global.ODS_OPENSHIFT_APP_DOMAIN .Values.ODS_OPENSHIFT_APP_DOMAIN }} http: paths: - path: / diff --git a/ods-api-service/chart/templates/tpl/_application_yaml.tpl b/ods-api-service/chart/templates/tpl/_application_yaml.tpl index f302ce18f..d1bbefacd 100644 --- a/ods-api-service/chart/templates/tpl/_application_yaml.tpl +++ b/ods-api-service/chart/templates/tpl/_application_yaml.tpl @@ -19,7 +19,7 @@ spring: jwk-set-uri: ${OAUTH2_JWK_SET_URI:} issuer-uri: ${OAUTH2_ISSUER:} audiences: - - ${OAUTH2_AUDIENCE:} + - ${OAUTH2_AUDIENCE:} datasource: url: ${ODS_API_SERVICE_DB_DATASOURCE_URL} username: ${ODS_API_SERVICE_DB_USER:opendevstack} @@ -179,6 +179,21 @@ externalservices: instances: {} {{- end }} + marketplace: +{{- if gt (len .Values.externalServices.marketplace.instances) 0 }} + default-instance: ${MARKETPLACE_DEFAULT_INSTANCE:{{ .Values.externalServices.marketplace.defaultInstance }}} + instances: +{{- range $name, $instance := .Values.externalServices.marketplace.instances }} + {{ $name }}: + projectComponentsBaseUrl: ${MARKETPLACE_{{ $name | upper | replace "-" "_" }}_PROJECT_COMPONENT_BASE_URL:} + provisionerActionsBaseUrl: ${MARKETPLACE_{{ $name | upper | replace "-" "_" }}_PROVISIONER_ACTIONS_BASE_URL:} + oboScope: ${MARKETPLACE_{{ $name | upper | replace "-" "_" }}_OBO_SCOPE:} + trust-all-certificates: ${MARKETPLACE_{{ $name | upper | replace "-" "_" }}_TRUST_ALL:false} +{{- end }} +{{- else }} + instances: {} +{{- end }} + services: project: ldap: diff --git a/ods-api-service/chart/templates/tpl/_env_application.tpl b/ods-api-service/chart/templates/tpl/_env_application.tpl index 6b6977c41..14e40b716 100644 --- a/ods-api-service/chart/templates/tpl/_env_application.tpl +++ b/ods-api-service/chart/templates/tpl/_env_application.tpl @@ -7,4 +7,8 @@ ODS_API_SERVICE_DB_DATASOURCE_URL: "jdbc:postgresql://{{ include "chart.fullname ODS_API_SERVICE_DB_NAME: {{ .Values.postgresql.databaseNameB64 }} ODS_API_SERVICE_DB_USER: {{ .Values.postgresql.databaseUserB64 }} ODS_API_SERVICE_DB_PASSWORD: {{ .Values.postgresql.databasePasswordB64 }} +AZURE_TENANT_ID: {{ .Values.spring.security.obo.azureTenant | b64enc | quote }} +OBO_TOKEN_URL: {{ .Values.spring.security.obo.tokenUrl | b64enc | quote }} +OBO_CLIENT_ID: {{ .Values.spring.security.obo.clientId | b64enc | quote }} +OBO_CLIENT_SECRET: {{ .Values.spring.security.obo.clientSecret | b64enc | quote }} {{- end }} diff --git a/ods-api-service/chart/templates/tpl/_env_external_services.tpl b/ods-api-service/chart/templates/tpl/_env_external_services.tpl index 884aa734a..38610c5cb 100644 --- a/ods-api-service/chart/templates/tpl/_env_external_services.tpl +++ b/ods-api-service/chart/templates/tpl/_env_external_services.tpl @@ -69,6 +69,15 @@ WEBHOOK_PROXY_{{ $name | upper | replace "-" "_" }}_TRUST_ALL: {{ default false WEBHOOK_PROXY_{{ $name | upper | replace "-" "_" }}_JENKINSFILE_PATH: {{ $cluster.defaultJenkinsfilePath | quote }} {{- end }} {{- end }} + +## Mkt configuration +MARKETPLACE_DEFAULT_INSTANCE: {{ .Values.externalServices.marketplace.defaultInstance | quote }} +{{- range $name, $instance := .Values.externalServices.marketplace.instances }} +MARKETPLACE_{{ $name | upper | replace "-" "_" }}_PROJECT_COMPONENT_BASE_URL: {{ $instance.projectComponentsBaseUrl | quote }} +MARKETPLACE_{{ $name | upper | replace "-" "_" }}_PROVISIONER_ACTIONS_BASE_URL: {{ $instance.provisionerActionsBaseUrl | quote }} +MARKETPLACE_{{ $name | upper | replace "-" "_" }}_OBO_SCOPE: {{ $instance.oboScope | quote }} +MARKETPLACE_{{ $name | upper | replace "-" "_" }}_TRUST_ALL: {{ $instance.trustAllCertificates | quote }} +{{- end }} {{- end }} {{- define "chart.externalServicesSecretData" }} @@ -128,4 +137,4 @@ JIRA_{{ $name | upper | replace "-" "_" }}_PASSWORD: {{ $instance.password | b64 JENKINS_{{ $env.name | upper | replace "-" "_" }}_API_TOKEN: {{ $env.apiToken | b64enc | quote }} {{- end }} {{- end }} -{{- end }} \ No newline at end of file +{{- end }} diff --git a/ods-api-service/chart/values.yaml.template b/ods-api-service/chart/values.yaml.template index 2c0278be4..e39c588a0 100644 --- a/ods-api-service/chart/values.yaml.template +++ b/ods-api-service/chart/values.yaml.template @@ -266,6 +266,15 @@ externalServices: # connectionTimeout: 30000 # readTimeout: 30000 # trustAllCertificates: false + # Marketplace configuration + marketplace: + # Name of the default marketplace instance key (must match a key under instances) + defaultInstance: "" + instances: {} + # Example: + # dev: + # projectComponentsBaseUrl: "https://component-catalog.example.com/v1" + # provisionerActionsBaseUrl: "https://component-provisioner.example.com/v1" # API Configuration Secrets apis: projectUsers: @@ -277,42 +286,7 @@ apis: expirationHours: $PROJECT_USERS_JWT_EXPIRATION_HOURS # Environment-specific configuration (loaded based on active profile) envConfig: {} -## PostgreSQL database configuration -postgresql: - ## Internal OpenShift registry and namespace where the built image is stored. - ## The image is built via the BuildConfig using Dockerfile.database (base: public.ecr.aws/docker/library/postgres:18-alpine) - internalRegistry: $ODS_API_SERVICE_DB_INTERNAL_REGISTRY - odsNamespace: $ODS_NAMESPACE - odsImageTag: $ODS_IMAGE_TAG - ## Plain-text database details (used in backup scripts and connection strings) - databaseName: $ODS_API_SERVICE_DB_NAME - databaseUser: $ODS_API_SERVICE_DB_USER - ## Name of the PostgreSQL superuser (default 'postgres' in official image) - superuserName: $ODS_API_SERVICE_DB_SUPER_NAME - ## Base64-encoded credentials stored in the Secret - databaseNameB64: $ODS_API_SERVICE_DB_NAME_B64 - databaseUserB64: $ODS_API_SERVICE_DB_USER_B64 - databasePasswordB64: $ODS_API_SERVICE_DB_PASSWORD_B64 - superuserPasswordB64: $ODS_API_SERVICE_DB_SUPER_PASSWORD_B64 - ## Resource limits/requests for the PostgreSQL container - cpuLimit: $ODS_API_SERVICE_DB_CPU_LIMIT - cpuRequest: $ODS_API_SERVICE_DB_CPU_REQUEST - memLimit: $ODS_API_SERVICE_DB_MEMORY_LIMIT - memRequest: $ODS_API_SERVICE_DB_MEMORY_REQUEST - ## PVC storage for database data - pvcDatabaseCapacity: $ODS_API_SERVICE_DB_CAPACITY - storageClassName: $ODS_API_SERVICE_DB_STORAGE_CLASS - storageProvisioner: $ODS_API_SERVICE_DB_STORAGE_PROVISIONER - ## Backup configuration - backup: - ## The backup job uses the same built image as the DB container (includes psql + oc CLI) - ## Snapshots are created in the namespace defined by postgresql.odsNamespace - ## Cron schedule for the backup job (default: daily at 02:00) - schedule: $ODS_API_SERVICE_DB_BACKUP_SCHEDULE - ## VolumeSnapshotClass used for storage snapshots - snapshotStorageClass: $ODS_API_SERVICE_DB_BACKUP_SNAPSHOT_CLASS - successHistoryLimit: $ODS_API_SERVICE_DB_BACKUP_SUCCESS_HISTORY_LIMIT - failedHistoryLimit: $ODS_API_SERVICE_DB_BACKUP_FAILED_HISTORY_LIMIT + resources: limits: cpu: 500m diff --git a/scripts/decrypt-helm-secrets.sh b/scripts/decrypt-helm-secrets.sh index d8ba6290a..0d16143ef 100755 --- a/scripts/decrypt-helm-secrets.sh +++ b/scripts/decrypt-helm-secrets.sh @@ -106,7 +106,7 @@ decrypt_secrets_in_folder() { echo " (Use -y flag to auto-remove)" fi fi - done < <(find "$folder" -maxdepth 1 -type f -name "*secrets*.enc.yaml" 2>/dev/null) + done < <(find "$folder" -maxdepth 2 -type f -name "*secrets*.enc.yaml" 2>/dev/null) if [ $decrypted_count -eq 0 ]; then echo " ⚠ No encrypted secrets files found" @@ -126,7 +126,7 @@ if [ "$ENV" = "all" ]; then while IFS= read -r -d '' env_folder; do env_name=$(basename "$env_folder") decrypt_secrets_in_folder "$env_folder" "environment: $env_name" - done < <(find "$FOLDER" -maxdepth 1 -type d ! -name ".*" -print0 | grep -zv "^$FOLDER$") + done < <(find "$FOLDER" -maxdepth 2 -type d ! -name ".*" -print0 | grep -zv "^$FOLDER$") elif [ -n "$ENV" ]; then # Decrypt specific environment folder @@ -135,7 +135,7 @@ elif [ -n "$ENV" ]; then echo "❌ Environment folder not found: $env_folder" echo "" echo "Available environments:" - find "$FOLDER" -maxdepth 1 -type d ! -name ".*" ! -path "$FOLDER" -exec basename {} \; + find "$FOLDER" -maxdepth 2 -type d ! -name ".*" ! -path "$FOLDER" -exec basename {} \; exit 1 fi decrypt_secrets_in_folder "$env_folder" "environment: $ENV" diff --git a/scripts/encrypt-helm-secrets.sh b/scripts/encrypt-helm-secrets.sh index 687c9de2d..98054c8a1 100755 --- a/scripts/encrypt-helm-secrets.sh +++ b/scripts/encrypt-helm-secrets.sh @@ -113,7 +113,7 @@ encrypt_secrets_in_folder() { echo " (Use -y flag to auto-remove)" fi fi - done < <(find "$folder" -maxdepth 1 -type f \( -name "*secrets*.dec.yaml" -o -name "*secrets*.yaml" \) ! -name "*.enc.yaml" 2>/dev/null) + done < <(find "$folder" -maxdepth 2 -type f \( -name "*secrets*.dec.yaml" -o -name "*secrets*.yaml" \) ! -name "*.enc.yaml" 2>/dev/null) if [ $encrypted_count -eq 0 ]; then echo " ⚠ No secrets files found" @@ -133,7 +133,7 @@ if [ "$ENV" = "all" ]; then while IFS= read -r -d '' env_folder; do env_name=$(basename "$env_folder") encrypt_secrets_in_folder "$env_folder" "environment: $env_name" - done < <(find "$FOLDER" -maxdepth 1 -type d ! -name ".*" -print0 | grep -zv "^$FOLDER$") + done < <(find "$FOLDER" -maxdepth 2 -type d ! -name ".*" -print0 | grep -zv "^$FOLDER$") elif [ -n "$ENV" ]; then # Encrypt specific environment folder @@ -142,7 +142,7 @@ elif [ -n "$ENV" ]; then echo "❌ Environment folder not found: $env_folder" echo "" echo "Available environments:" - find "$FOLDER" -maxdepth 1 -type d ! -name ".*" ! -path "$FOLDER" -exec basename {} \; + find "$FOLDER" -maxdepth 2 -type d ! -name ".*" ! -path "$FOLDER" -exec basename {} \; exit 1 fi encrypt_secrets_in_folder "$env_folder" "environment: $ENV"