diff --git a/clusters/dev/apps/bff-cli/values.yaml b/clusters/dev/apps/bff-cli/values.yaml
index 20f16ed..a3102e5 100644
--- a/clusters/dev/apps/bff-cli/values.yaml
+++ b/clusters/dev/apps/bff-cli/values.yaml
@@ -48,7 +48,6 @@ bff-cli-service:
CORE_ZONE_LABEL: "Core"
GREEN_ZONE_LABEL: "Greenroom"
- # TODO: fill when these services are deployed on OVH
AUDIT_TRAIL_SERVICE: ""
HPC_SERVICE: ""
KG_SERVICE: ""
@@ -59,7 +58,6 @@ bff-cli-service:
# Guacamole CLI auth
CLI_PUBLIC_KEY_PATH: "/var/run/secrets/guacamole/jwt-key.pub"
- # TODO: replace with OVH pod CIDR when JupyterHub is deployed
JUPYTER_IP_LOWER: "10.0.0.0"
JUPYTER_IP_UPPER: "10.255.255.255"
diff --git a/clusters/dev/apps/kong-postgresql/application.yaml b/clusters/dev/apps/kong-postgresql/application.yaml
index 3c60a00..e3ba652 100644
--- a/clusters/dev/apps/kong-postgresql/application.yaml
+++ b/clusters/dev/apps/kong-postgresql/application.yaml
@@ -15,10 +15,6 @@ spec:
helm:
valueFiles:
- ../../registry.yaml
- # TODO: versions.yaml has pg_cron tag for main utility postgres only.
- # Proper fix: add postgresql-standard key to versions.yaml with standard
- # bitnami tag, then reference it here. For now, using chart default.
- # - ../../versions.yaml
- values.yaml
destination:
server: https://kubernetes.default.svc
diff --git a/clusters/prod/apps/approval/Chart.yaml b/clusters/prod/apps/approval/Chart.yaml
new file mode 100644
index 0000000..9fdb260
--- /dev/null
+++ b/clusters/prod/apps/approval/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: approval
+version: 0.1.0
+dependencies:
+ - name: approval-service
+ version: "0.3.1"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/approval/application.yaml b/clusters/prod/apps/approval/application.yaml
new file mode 100644
index 0000000..d9a391d
--- /dev/null
+++ b/clusters/prod/apps/approval/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: approval
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/approval
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/approval/templates/external-secret.yaml b/clusters/prod/apps/approval/templates/external-secret.yaml
new file mode 100644
index 0000000..972dd07
--- /dev/null
+++ b/clusters/prod/apps/approval/templates/external-secret.yaml
@@ -0,0 +1,25 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: approval-credentials
+ namespace: utility
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: approval-credentials
+ data:
+ - secretKey: db-uri
+ remoteRef:
+ key: secret/data/approval
+ property: db-uri
+ - secretKey: rds-password
+ remoteRef:
+ key: secret/data/postgresql
+ property: approval-user-password
+ - secretKey: redis-password
+ remoteRef:
+ key: secret/data/redis
+ property: password
diff --git a/clusters/prod/apps/approval/values.yaml b/clusters/prod/apps/approval/values.yaml
new file mode 100644
index 0000000..15d4031
--- /dev/null
+++ b/clusters/prod/apps/approval/values.yaml
@@ -0,0 +1,88 @@
+approval-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/approval
+ pullPolicy: IfNotPresent
+ # tag from versions.yaml via valueFile merge
+
+ fullnameOverride: approval
+ replicaCount: 1
+
+ container:
+ port: 8000
+
+ service:
+ type: ClusterIP
+ port: 8000
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ appConfig:
+ env: prod
+ config_center_enabled: "false"
+ config_center_base_url: "http://common.utility:5062/"
+
+ extraEnv:
+ CORE_ZONE_LABEL: "Core"
+ GREENROOM_ZONE_LABEL: "Greenroom"
+ META_SERVICE: "http://metadata.utility:5066"
+ RDS_SCHEMA_DEFAULT: "pilot_approval"
+ AUTH_SERVICE: "http://auth.utility:5061"
+ DATAOPS_SERVICE: "http://dataops.utility:5063"
+ EMAIL_SERVICE: "http://notification.utility:5065"
+ METADATA_SERVICE: "http://metadata.utility:5066"
+ PROJECT_SERVICE: "http://project.utility:5064"
+ NOTIFICATION_SERVICE: "http://notification.utility:5065"
+ REDIS_DB: "0"
+ REDIS_HOST: "redis-master.redis"
+ REDIS_PORT: "6379"
+ RDS_DB: "approval"
+ RDS_HOST: "postgres.utility"
+ RDS_USER: "approval_user"
+ RDS_PORT: "5432"
+
+ extraEnvYaml:
+ - name: DB_URI
+ valueFrom:
+ secretKeyRef:
+ name: approval-credentials
+ key: db-uri
+ - name: RDS_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: approval-credentials
+ key: rds-password
+ - name: REDIS_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: approval-credentials
+ key: redis-password
+
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 500m
+ memory: 500Mi
+
+ readinessProbe:
+ tcpSocket:
+ port: 8000
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ failureThreshold: 3
+
+ livenessProbe:
+ httpGet:
+ path: /v1/health
+ port: 8000
+ periodSeconds: 10
+ timeoutSeconds: 3
+ failureThreshold: 3
+
+ updateStrategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 0
diff --git a/clusters/prod/apps/auth/Chart.yaml b/clusters/prod/apps/auth/Chart.yaml
new file mode 100644
index 0000000..16c3780
--- /dev/null
+++ b/clusters/prod/apps/auth/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: auth
+version: 0.1.0
+dependencies:
+ - name: auth-service
+ version: "1.0.9"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/auth/application.yaml b/clusters/prod/apps/auth/application.yaml
new file mode 100644
index 0000000..b3c8e67
--- /dev/null
+++ b/clusters/prod/apps/auth/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: auth
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "7"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/auth
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/auth/templates/external-secret.yaml b/clusters/prod/apps/auth/templates/external-secret.yaml
new file mode 100644
index 0000000..0ff8471
--- /dev/null
+++ b/clusters/prod/apps/auth/templates/external-secret.yaml
@@ -0,0 +1,29 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: auth-credentials
+ namespace: utility
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: auth-credentials
+ data:
+ - secretKey: auth-user-password
+ remoteRef:
+ key: secret/data/postgresql
+ property: auth-user-password
+ - secretKey: redis-password
+ remoteRef:
+ key: secret/data/redis
+ property: password
+ - secretKey: keycloak-client-secret
+ remoteRef:
+ key: secret/data/auth
+ property: keycloak-client-secret
+ - secretKey: freeipa-password
+ remoteRef:
+ key: secret/data/auth
+ property: freeipa-password
diff --git a/clusters/prod/apps/auth/values.yaml b/clusters/prod/apps/auth/values.yaml
new file mode 100644
index 0000000..4b6a0c3
--- /dev/null
+++ b/clusters/prod/apps/auth/values.yaml
@@ -0,0 +1,103 @@
+auth-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/auth
+ pullPolicy: IfNotPresent
+
+ fullnameOverride: auth
+ replicaCount: 3
+
+ container:
+ port: 5061
+
+ service:
+ type: ClusterIP
+ port: 5061
+ targetPort: 5061
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ appConfig:
+ env: prod
+ WORKERS: 2
+ RDS_HOST: postgres.utility
+ RDS_USER: auth_user
+ RDS_DBNAME: auth
+ RDS_SCHEMA_PREFIX: pilot
+ LDAP_PREFIX: hdc
+ LDAP_COMMON_NAME_PREFIX: hdc
+ AD_USER_GROUP: hdc-users
+ IDENTITY_BACKEND: keycloak
+ KEYCLOAK_SERVER_URL: "https://iam.hdc.ebrains.eu/"
+ KEYCLOAK_CLIENT_ID: kong
+ KEYCLOAK_REALM: hdc
+ KEYCLOAK_ID: hdc
+ REDIS_HOST: redis-master.redis
+ REDIS_PORT: "6379"
+ FREEIPA_URL: "ldap.hdc.ebrains.eu"
+ ENABLE_ACTIVE_DIRECTORY: "false"
+ DOMAIN_NAME: "https://portal.hdc.ebrains.eu"
+ START_PATH: hdc
+ GUIDE_PATH: ""
+ EMAIL_SUPPORT: support@hdc.ebrains.eu
+ EMAIL_ADMIN: admin@hdc.ebrains.eu
+ EMAIL_HELPDESK: helpdesk@hdc.ebrains.eu
+ PLATFORM_NAME: HDC
+ PROJECT_NAME: HDC
+ OPEN_TELEMETRY_ENABLED: "false"
+ config_center_enabled: "false"
+
+ resources:
+ limits:
+ cpu: 500m
+ memory: 500Mi
+ requests:
+ cpu: 25m
+ memory: 10Mi
+
+ extraEnvYaml:
+ - name: RDS_PWD
+ valueFrom:
+ secretKeyRef:
+ name: auth-credentials
+ key: auth-user-password
+ - name: REDIS_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: auth-credentials
+ key: redis-password
+ - name: KEYCLOAK_SECRET
+ valueFrom:
+ secretKeyRef:
+ name: auth-credentials
+ key: keycloak-client-secret
+ - name: FREEIPA_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: auth-credentials
+ key: freeipa-password
+
+ extraEnv:
+ REDIS_DB: "0"
+ RDS_PRE_PING: "true"
+
+ readinessProbe:
+ tcpSocket:
+ port: 5061
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ failureThreshold: 3
+
+ livenessProbe:
+ httpGet:
+ path: /v1/health
+ port: 5061
+ periodSeconds: 30
+ timeoutSeconds: 5
+ failureThreshold: 3
+
+ updateStrategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 0
diff --git a/clusters/prod/apps/dataops/Chart.yaml b/clusters/prod/apps/dataops/Chart.yaml
new file mode 100644
index 0000000..865bd27
--- /dev/null
+++ b/clusters/prod/apps/dataops/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: dataops
+version: 0.1.0
+dependencies:
+ - name: dataops-service
+ version: "0.2.1"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/dataops/application.yaml b/clusters/prod/apps/dataops/application.yaml
new file mode 100644
index 0000000..236e675
--- /dev/null
+++ b/clusters/prod/apps/dataops/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: dataops
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/dataops
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/dataops/templates/external-secret.yaml b/clusters/prod/apps/dataops/templates/external-secret.yaml
new file mode 100644
index 0000000..14c942e
--- /dev/null
+++ b/clusters/prod/apps/dataops/templates/external-secret.yaml
@@ -0,0 +1,21 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: dataops-credentials
+ namespace: utility
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: dataops-credentials
+ data:
+ - secretKey: rds-password
+ remoteRef:
+ key: secret/data/postgresql
+ property: dataops-user-password
+ - secretKey: redis-password
+ remoteRef:
+ key: secret/data/redis
+ property: password
diff --git a/clusters/prod/apps/dataops/values.yaml b/clusters/prod/apps/dataops/values.yaml
new file mode 100644
index 0000000..f1b93bd
--- /dev/null
+++ b/clusters/prod/apps/dataops/values.yaml
@@ -0,0 +1,84 @@
+dataops-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/dataops
+ pullPolicy: IfNotPresent
+ # tag comes from versions.yaml via valueFile merge
+
+ fullnameOverride: dataops
+ replicaCount: 1
+
+ container:
+ port: 5063
+
+ service:
+ type: ClusterIP
+ port: 5063
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ appConfig:
+ env: prod
+ config_center_enabled: "false"
+ config_center_base_url: ""
+
+ extraEnv:
+ HOST: "0.0.0.0"
+ RDS_HOST: "postgres.utility"
+ RDS_PORT: "5432"
+ RDS_NAME: "dataops"
+ RDS_USERNAME: "dataops_user"
+ RDS_SCHEMA: "public"
+ RDS_ECHO_SQL_QUERIES: "false"
+ REDIS_HOST: "redis-master.redis"
+ REDIS_PORT: "6379"
+ REDIS_DB: "0"
+ WORKERS: "2"
+ LINEAGE_SERVICE: "http://lineage.utility:5064"
+ QUEUE_SERVICE: "http://queue-producer.greenroom:6060"
+ METADATA_SERVICE: "http://metadata.utility:5066"
+ AUTH_SERVICE: "http://auth.utility:5061"
+ MINIO_HOST: "http://minio.minio"
+ MINIO_PORT: "9000"
+ RSA_PUBLIC_KEY: "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFvQkNRQUpRbnpDK1UwN2h3NGliYWNLaWNMbWtTOFR0Mmp6MkFIcVFhWG1sOWUzeCsrZzh5TCtOaDNJSDAzLzdUV2xnbEFSNWRDcEU2cS9LaVpKS1dxU3RCcnlmOHk1UEhaUTJua1YxWXViajRPSThzMklKRFgyNU9XaUNvZFFDRkNwTkNyY1ZmSGpjbnJvRy9icGJoTTBBZ0RFc054UDlpd3NrZ2h3RVFGTDVuc1JWWkpyUEJ0T0dNRWJ4N0xNY3kyeFI2YmlySWFYTmNWSUlyd1g4MVB5bzZENlZRRzlkNkJSUmwvWlVDNGZ5SzZpNGxKUVJvUUV0SW0xNm9PNUFsUGpzYloxd0NXVStlazJJek9aNGRrRnhtUWlwdUpsbjI5TE1jZGdCMlFGZFRNcXBQTXlxWXc3ZmplWmhOL3FoZDFKbUVEeUZOVHVKcEt5Ymd2Y2VnNXdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0t"
+
+ extraEnvYaml:
+ - name: RDS_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: dataops-credentials
+ key: rds-password
+ - name: REDIS_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: dataops-credentials
+ key: redis-password
+
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 500m
+ memory: 500Mi
+
+ readinessProbe:
+ tcpSocket:
+ port: 5063
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ failureThreshold: 3
+
+ livenessProbe:
+ httpGet:
+ path: /v1/health
+ port: 5063
+ periodSeconds: 30
+ timeoutSeconds: 5
+ failureThreshold: 3
+
+ updateStrategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 0
diff --git a/clusters/prod/apps/dataset/Chart.yaml b/clusters/prod/apps/dataset/Chart.yaml
new file mode 100644
index 0000000..c2f28f6
--- /dev/null
+++ b/clusters/prod/apps/dataset/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: dataset
+version: 0.1.0
+dependencies:
+ - name: base-chart-hdc
+ version: "1.0.1"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/dataset/application.yaml b/clusters/prod/apps/dataset/application.yaml
new file mode 100644
index 0000000..3368266
--- /dev/null
+++ b/clusters/prod/apps/dataset/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: dataset
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/dataset
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/dataset/templates/external-secret.yaml b/clusters/prod/apps/dataset/templates/external-secret.yaml
new file mode 100644
index 0000000..1fe8b3e
--- /dev/null
+++ b/clusters/prod/apps/dataset/templates/external-secret.yaml
@@ -0,0 +1,36 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: dataset-credentials
+ namespace: utility
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: dataset-credentials
+ data:
+ # PostgreSQL credentials
+ - secretKey: db-username
+ remoteRef:
+ key: secret/data/postgresql
+ property: dataset-user
+ - secretKey: db-password
+ remoteRef:
+ key: secret/data/postgresql
+ property: dataset-user-password
+ # MinIO credentials
+ - secretKey: minio-access-key
+ remoteRef:
+ key: secret/data/minio
+ property: access_key
+ - secretKey: minio-secret-key
+ remoteRef:
+ key: secret/data/minio
+ property: secret_key
+ # Redis
+ - secretKey: redis-password
+ remoteRef:
+ key: secret/data/redis
+ property: password
diff --git a/clusters/prod/apps/dataset/values.yaml b/clusters/prod/apps/dataset/values.yaml
new file mode 100644
index 0000000..3bed0b8
--- /dev/null
+++ b/clusters/prod/apps/dataset/values.yaml
@@ -0,0 +1,143 @@
+base-chart-hdc:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/dataset
+ tag: "2.3.41"
+ tagPrefix: "dataset"
+ pullPolicy: IfNotPresent
+ initContainers:
+ enabled: true
+ image:
+ tagPrefix: alembic
+ fullnameOverride: dataset
+ labels:
+ app: dataset
+ instance: dataset-service
+ replicaCount: 1
+ container:
+ name: dataset
+ ports:
+ - name: http
+ containerPort: 5081
+ protocol: TCP
+ service:
+ type: ClusterIP
+ ports:
+ - port: 5081
+ targetPort: 5081
+ protocol: TCP
+ name: http
+ imagePullSecrets:
+ - name: docker-registry-secret
+ appConfig:
+ env: prod
+ config_center_enabled: false
+ extraEnv:
+ # Telemetry
+ OPEN_TELEMETRY_ENABLED: "true"
+ ENABLE_PROMETHEUS_METRICS: "false"
+ # Dataset config
+ DATASET_FILE_FOLDER: "data"
+ DATASET_SCHEMA_FOLDER: "schema"
+ DATASET_CODE_REGEX: "^[a-z0-9]{3,32}$"
+ ROOT_PATH: "/data/core-storage"
+ CORE_ZONE_LABEL: "Core"
+ GREEN_ZONE_LABEL: "Greenroom"
+ # MinIO
+ MINIO_OPENID_CLIENT: "react-app"
+ MINIO_ENDPOINT: "minio.minio:9000"
+ MINIO_HTTPS: "False"
+ S3_GATEWAY: "True"
+ S3_INTERNAL: "minio.minio:9000"
+ S3_INTERNAL_HTTPS: "False"
+ S3_HOST: "minio.minio"
+ S3_PORT: "9000"
+ S3_HTTPS_ENABLED: "false"
+ S3_GATEWAY_ENABLED: "true"
+ S3_BUCKET_ENCRYPTION_ENABLED: "false"
+ S3_PUBLIC: "object.hdc.ebrains.eu"
+ S3_PUBLIC_HTTPS: "TRUE"
+ # Keycloak
+ KEYCLOAK_URL: "http://keycloak.keycloak/auth/realms/hdc/protocol/openid-connect/token"
+ # Services
+ METADATA_SERVICE: "http://metadata.utility:5066"
+ PROJECT_SERVICE: "http://project.utility:5064"
+ QUEUE_SERVICE: "http://queue-producer.greenroom:6060"
+ # Kafka
+ KAFKA_URL: "kafka-headless.utility:9092"
+ # Queue
+ gm_queue_endpoint: "message-bus-greenroom.greenroom"
+ # Database
+ RDS_HOST: "postgres.utility"
+ RDS_PORT: "5432"
+ RDS_DBNAME: "dataset"
+ RDS_SCHEMA_DEFAULT: "dataset"
+ OPSDB_UTILITY_HOST: "postgres.utility"
+ OPSDB_UTILITY_PORT: "5432"
+ RUN_MIGRATIONS_ON_BUILD: "false"
+ ALEMBIC_CONFIG: "migrations/alembic.ini"
+ # Redis
+ REDIS_HOST: "redis-master.redis"
+ REDIS_PORT: "6379"
+ REDIS_DB: "0"
+ DATA_OPS_UTIL: "http://dataops.utility:5063"
+ # Misc
+ DOWNLOAD_TOKEN_EXPIRE_AT: "5"
+ MAX_PREVIEW_SIZE: "500000"
+ ESSENTIALS_NAME: "essential.schema.json"
+ ESSENTIALS_TPL_NAME: "Essential"
+ extraEnvYaml:
+ - name: OPSDB_UTILITY_USERNAME
+ valueFrom:
+ secretKeyRef:
+ name: dataset-credentials
+ key: db-username
+ - name: OPSDB_UTILITY_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: dataset-credentials
+ key: db-password
+ - name: MINIO_USERNAME
+ valueFrom:
+ secretKeyRef:
+ name: dataset-credentials
+ key: minio-access-key
+ - name: MINIO_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: dataset-credentials
+ key: minio-secret-key
+ - name: S3_ACCESS_KEY
+ valueFrom:
+ secretKeyRef:
+ name: dataset-credentials
+ key: minio-access-key
+ - name: S3_SECRET_KEY
+ valueFrom:
+ secretKeyRef:
+ name: dataset-credentials
+ key: minio-secret-key
+ - name: REDIS_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: dataset-credentials
+ key: redis-password
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 500m
+ memory: 500Mi
+ readinessProbe:
+ tcpSocket:
+ port: 5081
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ failureThreshold: 3
+ livenessProbe:
+ httpGet:
+ path: /v1/health
+ port: 5081
+ periodSeconds: 10
+ failureThreshold: 3
+ timeoutSeconds: 3
diff --git a/clusters/prod/apps/download-core/Chart.yaml b/clusters/prod/apps/download-core/Chart.yaml
new file mode 100644
index 0000000..66a3566
--- /dev/null
+++ b/clusters/prod/apps/download-core/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: download-core
+version: 0.1.0
+dependencies:
+ - name: download-service
+ version: "1.0.6"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/download-core/application.yaml b/clusters/prod/apps/download-core/application.yaml
new file mode 100644
index 0000000..82c5c8b
--- /dev/null
+++ b/clusters/prod/apps/download-core/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: download-core
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/download-core
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: core
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/download-core/templates/external-secret.yaml b/clusters/prod/apps/download-core/templates/external-secret.yaml
new file mode 100644
index 0000000..38d9986
--- /dev/null
+++ b/clusters/prod/apps/download-core/templates/external-secret.yaml
@@ -0,0 +1,29 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: download-credentials
+ namespace: core
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: download-credentials
+ data:
+ - secretKey: download-key
+ remoteRef:
+ key: secret/data/download
+ property: download-key
+ - secretKey: redis-password
+ remoteRef:
+ key: secret/data/redis
+ property: password
+ - secretKey: minio-access-key
+ remoteRef:
+ key: secret/data/minio
+ property: access_key
+ - secretKey: minio-secret-key
+ remoteRef:
+ key: secret/data/minio
+ property: secret_key
diff --git a/clusters/prod/apps/download-core/values.yaml b/clusters/prod/apps/download-core/values.yaml
new file mode 100644
index 0000000..7182a5a
--- /dev/null
+++ b/clusters/prod/apps/download-core/values.yaml
@@ -0,0 +1,94 @@
+download-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/download
+ pullPolicy: IfNotPresent
+
+
+ fullnameOverride: download
+ replicaCount: 1
+
+ container:
+ port: 5077
+
+ service:
+ type: ClusterIP
+ port: 5077
+ targetPort: 5077
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ appConfig:
+ port: 5077
+ env: prod
+ config_center_enabled: false
+ ROOT_PATH: "/data/core-storage"
+ OPEN_TELEMETRY_ENABLED: "False"
+
+ extraEnv:
+ HOST: "0.0.0.0"
+ namespace: "core"
+ S3_INTERNAL: "minio.minio:9000"
+ S3_INTERNAL_HTTPS: "FALSE"
+ S3_PUBLIC: "object.hdc.ebrains.eu"
+ S3_PUBLIC_HTTPS: "TRUE"
+
+ extraEnvYaml:
+ - name: DOWNLOAD_KEY
+ valueFrom:
+ secretKeyRef:
+ name: download-credentials
+ key: download-key
+ - name: REDIS_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: download-credentials
+ key: redis-password
+ - name: S3_ACCESS_KEY
+ valueFrom:
+ secretKeyRef:
+ name: download-credentials
+ key: minio-access-key
+ - name: S3_SECRET_KEY
+ valueFrom:
+ secretKeyRef:
+ name: download-credentials
+ key: minio-secret-key
+
+ extraVolumeMounts:
+ - name: download-storage
+ mountPath: /data/core-storage
+ readOnly: false
+
+ extraVolumes:
+ - name: download-storage
+ persistentVolumeClaim:
+ claimName: core-storage
+
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 500m
+ memory: 500Mi
+
+ readinessProbe:
+ tcpSocket:
+ port: 5077
+ initialDelaySeconds: 5
+ periodSeconds: 10
+
+ livenessProbe:
+ httpGet:
+ path: /v1/health
+ port: 5077
+ periodSeconds: 10
+ timeoutSeconds: 3
+ failureThreshold: 3
+
+ updateStrategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 0
diff --git a/clusters/prod/apps/download-greenroom/Chart.yaml b/clusters/prod/apps/download-greenroom/Chart.yaml
new file mode 100644
index 0000000..3c017df
--- /dev/null
+++ b/clusters/prod/apps/download-greenroom/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: download-greenroom
+version: 0.1.0
+dependencies:
+ - name: download-service
+ version: "1.0.6"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/download-greenroom/application.yaml b/clusters/prod/apps/download-greenroom/application.yaml
new file mode 100644
index 0000000..6a579dc
--- /dev/null
+++ b/clusters/prod/apps/download-greenroom/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: download-greenroom
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/download-greenroom
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: greenroom
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/download-greenroom/templates/external-secret.yaml b/clusters/prod/apps/download-greenroom/templates/external-secret.yaml
new file mode 100644
index 0000000..6f2e804
--- /dev/null
+++ b/clusters/prod/apps/download-greenroom/templates/external-secret.yaml
@@ -0,0 +1,29 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: download-credentials
+ namespace: greenroom
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: download-credentials
+ data:
+ - secretKey: download-key
+ remoteRef:
+ key: secret/data/download
+ property: download-key
+ - secretKey: redis-password
+ remoteRef:
+ key: secret/data/redis
+ property: password
+ - secretKey: minio-access-key
+ remoteRef:
+ key: secret/data/minio
+ property: access_key
+ - secretKey: minio-secret-key
+ remoteRef:
+ key: secret/data/minio
+ property: secret_key
diff --git a/clusters/prod/apps/download-greenroom/values.yaml b/clusters/prod/apps/download-greenroom/values.yaml
new file mode 100644
index 0000000..88b4a7d
--- /dev/null
+++ b/clusters/prod/apps/download-greenroom/values.yaml
@@ -0,0 +1,94 @@
+download-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/download
+ pullPolicy: IfNotPresent
+
+
+ fullnameOverride: download
+ replicaCount: 1
+
+ container:
+ port: 5077
+
+ service:
+ type: ClusterIP
+ port: 5077
+ targetPort: 5077
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ appConfig:
+ port: 5077
+ env: prod
+ config_center_enabled: false
+ ROOT_PATH: "/data/greenroom-storage"
+ OPEN_TELEMETRY_ENABLED: "False"
+
+ extraEnv:
+ HOST: "0.0.0.0"
+ namespace: "greenroom"
+ S3_INTERNAL: "minio.minio:9000"
+ S3_INTERNAL_HTTPS: "FALSE"
+ S3_PUBLIC: "object.hdc.ebrains.eu"
+ S3_PUBLIC_HTTPS: "TRUE"
+
+ extraEnvYaml:
+ - name: DOWNLOAD_KEY
+ valueFrom:
+ secretKeyRef:
+ name: download-credentials
+ key: download-key
+ - name: REDIS_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: download-credentials
+ key: redis-password
+ - name: S3_ACCESS_KEY
+ valueFrom:
+ secretKeyRef:
+ name: download-credentials
+ key: minio-access-key
+ - name: S3_SECRET_KEY
+ valueFrom:
+ secretKeyRef:
+ name: download-credentials
+ key: minio-secret-key
+
+ extraVolumeMounts:
+ - name: download-storage
+ mountPath: /data/greenroom-storage
+ readOnly: false
+
+ extraVolumes:
+ - name: download-storage
+ persistentVolumeClaim:
+ claimName: greenroom-storage
+
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 500m
+ memory: 500Mi
+
+ readinessProbe:
+ tcpSocket:
+ port: 5077
+ initialDelaySeconds: 5
+ periodSeconds: 10
+
+ livenessProbe:
+ httpGet:
+ path: /v1/health
+ port: 5077
+ periodSeconds: 10
+ timeoutSeconds: 3
+ failureThreshold: 3
+
+ updateStrategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 0
diff --git a/clusters/prod/apps/keycloak/Chart.yaml b/clusters/prod/apps/keycloak/Chart.yaml
new file mode 100644
index 0000000..d8cb845
--- /dev/null
+++ b/clusters/prod/apps/keycloak/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: keycloak
+version: 0.1.0
+dependencies:
+ - name: keycloak
+ version: "13.2.0"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/keycloak/application.yaml b/clusters/prod/apps/keycloak/application.yaml
new file mode 100644
index 0000000..e270e5b
--- /dev/null
+++ b/clusters/prod/apps/keycloak/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: keycloak
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "6"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/keycloak
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: keycloak
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/keycloak/templates/external-secret.yaml b/clusters/prod/apps/keycloak/templates/external-secret.yaml
new file mode 100644
index 0000000..497b48a
--- /dev/null
+++ b/clusters/prod/apps/keycloak/templates/external-secret.yaml
@@ -0,0 +1,53 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: keycloak-credentials
+ namespace: keycloak
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: keycloak-credentials
+ data:
+ - secretKey: admin-password
+ remoteRef:
+ key: secret/data/keycloak
+ property: admin-password
+---
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: keycloak-db-credentials
+ namespace: keycloak
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: keycloak-db-credentials
+ data:
+ - secretKey: password
+ remoteRef:
+ key: secret/data/keycloak
+ property: keycloak-user-password
+---
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: github-access-token
+ namespace: keycloak
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: github-access-token
+ data:
+ - secretKey: GITHUB_TOKEN
+ remoteRef:
+ key: secret/data/keycloak
+ property: github-token
diff --git a/clusters/prod/apps/keycloak/templates/keycloak-antd-pvc.yaml b/clusters/prod/apps/keycloak/templates/keycloak-antd-pvc.yaml
new file mode 100644
index 0000000..6ef116a
--- /dev/null
+++ b/clusters/prod/apps/keycloak/templates/keycloak-antd-pvc.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: keycloak-antd
+ namespace: keycloak
+spec:
+ accessModes:
+ - ReadWriteOnce
+ storageClassName: csi-cinder-high-speed
+ resources:
+ requests:
+ storage: 1Gi
diff --git a/clusters/prod/apps/keycloak/templates/theme-configmap.yaml b/clusters/prod/apps/keycloak/templates/theme-configmap.yaml
new file mode 100644
index 0000000..39cd43f
--- /dev/null
+++ b/clusters/prod/apps/keycloak/templates/theme-configmap.yaml
@@ -0,0 +1,33 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: keycloak-antd-theme
+ namespace: keycloak
+data:
+ login.ftl: |
+{{ .Files.Get "theme/login/login.ftl" | indent 4 }}
+ template.ftl: |
+{{ .Files.Get "theme/login/template.ftl" | indent 4 }}
+ theme.properties: |
+{{ .Files.Get "theme/login/theme.properties" | indent 4 }}
+ login.css: |
+{{ .Files.Get "theme/login/resources/css/login.css" | indent 4 }}
+ jquery.min.js: |
+{{ .Files.Get "theme/login/resources/js/jquery.min.js" | indent 4 }}
+ login.js: |
+{{ .Files.Get "theme/login/resources/js/login.js" | indent 4 }}
+binaryData:
+ error.png: {{ .Files.Get "theme/login/resources/img/error.png" | b64enc | quote }}
+ favicon.ico: {{ .Files.Get "theme/login/resources/img/favicon.ico" | b64enc | quote }}
+ feedback-error-arrow-down.png: {{ .Files.Get "theme/login/resources/img/feedback-error-arrow-down.png" | b64enc | quote }}
+ feedback-error-sign.png: {{ .Files.Get "theme/login/resources/img/feedback-error-sign.png" | b64enc | quote }}
+ feedback-success-arrow-down.png: {{ .Files.Get "theme/login/resources/img/feedback-success-arrow-down.png" | b64enc | quote }}
+ feedback-success-sign.png: {{ .Files.Get "theme/login/resources/img/feedback-success-sign.png" | b64enc | quote }}
+ feedback-warning-arrow-down.png: {{ .Files.Get "theme/login/resources/img/feedback-warning-arrow-down.png" | b64enc | quote }}
+ feedback-warning-sign.png: {{ .Files.Get "theme/login/resources/img/feedback-warning-sign.png" | b64enc | quote }}
+ HDC-logo.png: {{ .Files.Get "theme/login/resources/img/HDC-logo.png" | b64enc | quote }}
+ keycloak-bg.png: {{ .Files.Get "theme/login/resources/img/keycloak-bg.png" | b64enc | quote }}
+ keycloak-logo.png: {{ .Files.Get "theme/login/resources/img/keycloak-logo.png" | b64enc | quote }}
+ keycloak-logo-text.png: {{ .Files.Get "theme/login/resources/img/keycloak-logo-text.png" | b64enc | quote }}
+ lock.png: {{ .Files.Get "theme/login/resources/img/lock.png" | b64enc | quote }}
+ user.png: {{ .Files.Get "theme/login/resources/img/user.png" | b64enc | quote }}
diff --git a/clusters/prod/apps/keycloak/theme/login/login.ftl b/clusters/prod/apps/keycloak/theme/login/login.ftl
new file mode 100644
index 0000000..5e5e8b3
--- /dev/null
+++ b/clusters/prod/apps/keycloak/theme/login/login.ftl
@@ -0,0 +1,74 @@
+<#import "template.ftl" as layout>
+<@layout.registrationLayout displayInfo=social.displayInfo displayWide=(realm.password && social.providers??); section>
+ <#if section = "header">
+ <#-- ${msg("doLogIn")} -->
+
+ <#elseif section = "form">
+
+
+ <#elseif section = "info" >
+ <#if realm.password && realm.registrationAllowed && !registrationDisabled??>
+
+ #if>
+ #if>
+
+@layout.registrationLayout>
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/css/login.css b/clusters/prod/apps/keycloak/theme/login/resources/css/login.css
new file mode 100644
index 0000000..c92a780
--- /dev/null
+++ b/clusters/prod/apps/keycloak/theme/login/resources/css/login.css
@@ -0,0 +1,687 @@
+.login-pf body {
+ background: none;
+ background-color: #f0f2f5;
+ background-size: cover;
+ height: 100%;
+}
+
+.label-icon{
+ width:15px; margin-top:-5px;
+}
+
+.label-text{
+ margin-left: 8px;
+}
+
+.forget-password{
+ margin-bottom: 8px;
+}
+
+.login-pf-page-header{
+ display: none;
+}
+
+.login-pf-page{
+ padding-top: 117px;
+}
+
+/* .card-pf{
+ position: absolute ;
+ margin: auto ;
+} */
+
+.form-div{
+ padding-top: 30px;
+}
+
+.btn {
+ line-height: 1.5715;
+ position: relative;
+ display: inline-block;
+ font-weight: 400;
+ white-space: nowrap;
+ text-align: center;
+ background-image: none;
+ border: 1px solid transparent;
+ -webkit-box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
+ box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
+ cursor: pointer;
+ -webkit-transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+ transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -ms-touch-action: manipulation;
+ touch-action: manipulation;
+ height: 32px;
+ padding: 4px 15px;
+ font-size: 14px;
+ border-radius: 2px;
+ color: rgba(0, 0, 0, 0.65);
+ background-color: #fff;
+ border-color: #d9d9d9;
+ }
+
+ .btn-primary {
+ color: #fff;
+ background-color: #5bab58;
+ border-color: #5bab58;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12);
+ -webkit-box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
+ box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
+ }
+
+ .alert {
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ color: rgba(0, 0, 0, 0.65);
+ font-size: 14px;
+ font-variant: tabular-nums;
+ line-height: 1.5715;
+ list-style: none;
+ -webkit-font-feature-settings: 'tnum';
+ font-feature-settings: 'tnum';
+ position: relative;
+ padding: 8px 15px 8px 15px;
+ word-wrap: break-word;
+ border-radius: 2px;
+ }
+.alert-error {
+ background-color: #fff2f0;
+ border: 1px solid #ffccc7;
+}
+
+.alert-success{
+ background-color: #f6ffed;
+ border: 1px solid #b7eb8f;
+ color: #52c41a;
+}
+
+.alert-warning{
+ background-color: #fffbe6;
+ border: 1px solid #ffe58f;
+}
+
+.alert-info{
+ background-color: #e6f7ff;
+ border: 1px solid #91d5ff;
+}
+
+#kc-locale ul {
+ display: none;
+ position: absolute;
+ background-color: #fff;
+ list-style: none;
+ right: 0;
+ top: 20px;
+ min-width: 100px;
+ padding: 2px 0;
+ border: solid 1px #bbb;
+}
+
+#kc-locale:hover ul {
+ display: block;
+ margin: 0;
+}
+
+#kc-locale ul li a {
+ display: block;
+ padding: 5px 14px;
+ color: #000 !important;
+ text-decoration: none;
+ line-height: 20px;
+}
+
+#kc-locale ul li a:hover {
+ color: #4d5258;
+ background-color: #d4edfa;
+}
+
+#kc-locale-dropdown a {
+ color: #4d5258;
+ background: 0 0;
+ padding: 0 15px 0 0;
+ font-weight: 300;
+}
+
+#kc-locale-dropdown a:hover {
+ text-decoration: none;
+}
+
+a#kc-current-locale-link {
+ display: block;
+ padding: 0 5px;
+}
+
+/* a#kc-current-locale-link:hover {
+ background-color: rgba(0,0,0,0.2);
+} */
+
+a#kc-current-locale-link::after {
+ content: "\2c5";
+ margin-left: 4px;
+}
+
+.login-pf .container {
+ padding-top: 40px;
+}
+
+.login-pf a:hover {
+ color: #5bab58;
+}
+
+#kc-logo {
+ width: 100%;
+}
+
+#kc-logo-wrapper {
+ background-image: url(../img/keycloak-logo-2.png);
+ background-repeat: no-repeat;
+ height: 63px;
+ width: 300px;
+ margin: 62px auto 0;
+}
+
+div.kc-logo-text {
+ background-image: url(../img/keycloak-logo-text.png);
+ background-repeat: no-repeat;
+ height: 63px;
+ width: 300px;
+ margin: 0 auto;
+}
+
+div.kc-logo-text span {
+ display: none;
+}
+
+#kc-header {
+ color: #ededed;
+ overflow: visible;
+ white-space: nowrap;
+}
+
+#kc-header-wrapper {
+ display: none;
+ font-size: 29px;
+ text-transform: uppercase;
+ letter-spacing: 3px;
+ line-height: 1.2em;
+ padding: 62px 10px 20px;
+ white-space: normal;
+}
+
+#kc-content {
+ width: 100%;
+}
+
+#kc-attempted-username{
+ font-size: 20px;
+ font-family:inherit;
+ font-weight: normal;
+ padding-right:10px;
+}
+
+#kc-username{
+ text-align: center;
+}
+
+#kc-webauthn-settings-form{
+ padding-top:8px;
+}
+
+/* #kc-content-wrapper {
+ overflow-y: hidden;
+} */
+
+#kc-info {
+ padding-bottom: 200px;
+ margin-bottom: -200px;
+}
+
+#kc-info-wrapper {
+ font-size: 13px;
+}
+
+#kc-form-options span {
+ display: block;
+}
+
+#kc-form-options .checkbox {
+ margin-top: 0;
+ color: #72767b;
+}
+
+#kc-terms-text {
+ margin-bottom: 20px;
+}
+
+#kc-registration {
+ margin-bottom: 15px;
+}
+
+/* TOTP */
+
+.subtitle {
+ text-align: right;
+ margin-top: 30px;
+ color: #909090;
+}
+
+.required {
+ color: #CB2915;
+}
+
+ol#kc-totp-settings {
+ margin: 0;
+ padding-left: 20px;
+}
+
+ul#kc-totp-supported-apps {
+ margin-bottom: 10px;
+}
+
+#kc-totp-secret-qr-code {
+ max-width:150px;
+ max-height:150px;
+}
+
+#kc-totp-secret-key {
+ background-color: #fff;
+ color: #333333;
+ font-size: 16px;
+ padding: 10px 0;
+}
+
+/* OAuth */
+
+#kc-oauth h3 {
+ margin-top: 0;
+}
+
+#kc-oauth ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+#kc-oauth ul li {
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
+ font-size: 12px;
+ padding: 10px 0;
+}
+
+#kc-oauth ul li:first-of-type {
+ border-top: 0;
+}
+
+#kc-oauth .kc-role {
+ display: inline-block;
+ width: 50%;
+}
+
+/* Code */
+#kc-code textarea {
+ width: 100%;
+ height: 8em;
+}
+
+/* Social */
+
+#kc-social-providers ul {
+ padding: 0;
+}
+
+#kc-social-providers li {
+ display: block;
+}
+
+#kc-social-providers li:first-of-type {
+ margin-top: 0;
+}
+
+.kc-login-tooltip{
+ position:relative;
+ display: inline-block;
+}
+
+.kc-login-tooltip .kc-tooltip-text{
+ top:-3px;
+ left:160%;
+ background-color: black;
+ visibility: hidden;
+ color: #fff;
+
+ min-width:130px;
+ text-align: center;
+ border-radius: 2px;
+ box-shadow:0 1px 8px rgba(0,0,0,0.6);
+ padding: 5px;
+
+ position: absolute;
+ opacity:0;
+ transition:opacity 0.5s;
+}
+
+/* Show tooltip */
+.kc-login-tooltip:hover .kc-tooltip-text {
+ visibility: visible;
+ opacity:0.7;
+}
+
+/* Arrow for tooltip */
+.kc-login-tooltip .kc-tooltip-text::after {
+ content: " ";
+ position: absolute;
+ top: 15px;
+ right: 100%;
+ margin-top: -5px;
+ border-width: 5px;
+ border-style: solid;
+ border-color: transparent black transparent transparent;
+}
+
+.zocial,
+a.zocial {
+ width: 100%;
+ font-weight: normal;
+ font-size: 14px;
+ text-shadow: none;
+ border: 0;
+ background: #f5f5f5;
+ color: #72767b;
+ border-radius: 0;
+ white-space: normal;
+}
+.zocial:before {
+ border-right: 0;
+ margin-right: 0;
+}
+.zocial span:before {
+ padding: 7px 10px;
+ font-size: 14px;
+}
+.zocial:hover {
+ background: #ededed !important;
+}
+
+.zocial.facebook,
+.zocial.github,
+.zocial.google,
+.zocial.microsoft,
+.zocial.stackoverflow,
+.zocial.linkedin,
+.zocial.twitter {
+ background-image: none;
+ border: 0;
+
+ box-shadow: none;
+ text-shadow: none;
+}
+
+/* Copy of zocial windows classes to be used for microsoft's social provider button */
+.zocial.microsoft:before{ content: "\f15d"; }
+.zocial.stackoverflow:before{ color: inherit; }
+
+
+@media (min-width: 768px) {
+ #kc-container-wrapper {
+ position: absolute;
+ width: 100%;
+ }
+
+ .login-pf .container {
+ padding-right: 80px;
+ }
+
+ #kc-locale {
+ position: relative;
+ text-align: right;
+ z-index: 9999;
+ }
+}
+
+@media (max-width: 767px) {
+
+ .login-pf body {
+ background: white;
+ }
+
+ #kc-header {
+ padding-left: 15px;
+ padding-right: 15px;
+ float: none;
+ text-align: left;
+ }
+
+ #kc-header-wrapper {
+ font-size: 16px;
+ font-weight: bold;
+ padding: 20px 60px 0 0;
+ color: #72767b;
+ letter-spacing: 0;
+ }
+
+ div.kc-logo-text {
+ margin: 0;
+ width: 150px;
+ height: 32px;
+ background-size: 100%;
+ }
+
+ #kc-form {
+ float: none;
+ }
+
+ #kc-info-wrapper {
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
+ margin-top: 15px;
+ padding-top: 15px;
+ padding-left: 0px;
+ padding-right: 15px;
+ }
+
+ #kc-social-providers li {
+ display: block;
+ margin-right: 5px;
+ }
+
+ .login-pf .container {
+ padding-top: 15px;
+ padding-bottom: 15px;
+ }
+
+ #kc-locale {
+ position: absolute;
+ width: 200px;
+ top: 20px;
+ right: 20px;
+ text-align: right;
+ z-index: 9999;
+ }
+
+ #kc-logo-wrapper {
+ background-size: 100px 21px;
+ height: 21px;
+ width: 100px;
+ margin: 20px 0 0 20px;
+ }
+
+}
+
+@media (min-height: 646px) {
+ #kc-container-wrapper {
+ bottom: 12%;
+ }
+}
+
+@media (max-height: 645px) {
+ #kc-container-wrapper {
+ padding-top: 50px;
+ top: 20%;
+ }
+}
+
+.card-pf form.form-actions .btn {
+ float: right;
+ margin-left: 10px;
+}
+
+.login-pf-page .login-pf-brand {
+ margin-top: 20px;
+ max-width: 360px;
+ width: 40%;
+}
+
+.card-pf {
+ background: #fff;
+ margin: 0 auto;
+ padding: 0 20px;
+ max-width: 500px;
+ border-top: 0;
+ box-shadow: 0px 0px 15px rgba(90, 90, 90, 0.459);
+
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ padding: 0;
+ color: rgba(0, 0, 0, 0.65);
+ font-size: 14px;
+ font-variant: tabular-nums;
+ line-height: 1.5715;
+ list-style: none;
+ -webkit-font-feature-settings: 'tnum';
+ font-feature-settings: 'tnum';
+ position: relative;
+ background: #fff;
+ border-radius: 2px;
+ -webkit-transition: all 0.3s;
+ transition: all 0.3s;
+}
+
+/*tablet*/
+@media (max-width: 840px) {
+ .login-pf-page .card-pf{
+ max-width: none;
+ margin-left: 20px;
+ margin-right: 20px;
+ padding: 20px 20px 30px 20px;
+ }
+}
+@media (max-width: 767px) {
+ .login-pf-page .card-pf{
+ max-width: none;
+ margin-left: 0;
+ margin-right: 0;
+ padding-top: 0;
+ }
+ .card-pf.login-pf-accounts{
+ max-width: none;
+ }
+}
+
+.login-pf-page .login-pf-signup {
+ font-size: 15px;
+ color: #72767b;
+}
+#kc-content-wrapper .row {
+ margin-left: 0;
+ margin-right: 0;
+}
+
+@media (min-width: 768px) {
+
+ .login-pf-page .login-pf-social-section .login-pf-social-link:last-of-type {
+ margin-bottom: 0;
+ }
+}
+
+.login-pf-page .login-pf-social-link {
+ margin-bottom: 25px;
+}
+.login-pf-page .login-pf-social-link a {
+ padding: 2px 0;
+ background-color: #5bab58;
+ color: white;
+ padding-top: 5px;
+ padding-bottom: 5px;
+}
+
+.login-pf-page.login-pf-page-accounts {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.login-pf-page .btn-primary {
+ margin-top: 0;
+}
+
+.login-pf-page .list-view-pf .list-group-item {
+ border-bottom: 1px solid #ededed;
+}
+
+.login-pf-page .list-view-pf-description {
+ width: 100%;
+}
+
+.login-pf-page .card-pf{
+ margin-bottom: 10px;
+}
+
+#kc-form-login div.form-group:last-of-type,
+#kc-register-form div.form-group:last-of-type,
+#kc-update-profile-form div.form-group:last-of-type {
+ margin-bottom: 0px;
+}
+
+#kc-back {
+ margin-top: 5px;
+}
+
+form#kc-select-back-form div.login-pf-social-section {
+ padding-left: 0px;
+ border-left: 0px;
+}
+
+#kc-form{
+ display: flex;
+ flex-direction: column-reverse;
+}
+.login-pf-page .login-pf-social-section{
+ width: 100%!important;
+ max-width: 100%!important;
+}
+.login-pf-page .login-pf-social-section:last-of-type{
+ padding-left: 0px;
+ padding-right: 0px;
+ border-left: 0;
+}
+.login-pf-page .login-pf-social-section:first-of-type{
+ padding-left: 40px;
+ padding-right: 40px;
+}
+#kc-social-providers{
+ width: 100%!important;
+ padding-bottom: 40px;
+ border-bottom: 1px solid #d1d1d1;
+}
+#kc-form-wrapper{
+ padding-top: 40px;
+}
+#login-username-button{
+ position: absolute;
+ top: -10px;
+ z-index: 100;
+ padding: 0 20px;
+ background: white;
+ left: 50%;
+ transform: translate(-50%, 0);
+}
+#login-username-button:hover{
+ color: #5bab58;
+ cursor: pointer;
+}
+#kc-form-login{
+ display: none;
+}
\ No newline at end of file
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/HDC-logo.png b/clusters/prod/apps/keycloak/theme/login/resources/img/HDC-logo.png
new file mode 100644
index 0000000..f360463
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/HDC-logo.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/error.png b/clusters/prod/apps/keycloak/theme/login/resources/img/error.png
new file mode 100644
index 0000000..3c6b7e5
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/error.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/favicon.ico b/clusters/prod/apps/keycloak/theme/login/resources/img/favicon.ico
new file mode 100644
index 0000000..48188de
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/favicon.ico differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-error-arrow-down.png b/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-error-arrow-down.png
new file mode 100644
index 0000000..6f2d9d2
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-error-arrow-down.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-error-sign.png b/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-error-sign.png
new file mode 100644
index 0000000..0dd5004
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-error-sign.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-success-arrow-down.png b/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-success-arrow-down.png
new file mode 100644
index 0000000..03cc0c4
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-success-arrow-down.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-success-sign.png b/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-success-sign.png
new file mode 100644
index 0000000..640bd71
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-success-sign.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-warning-arrow-down.png b/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-warning-arrow-down.png
new file mode 100644
index 0000000..6f2d9d2
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-warning-arrow-down.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-warning-sign.png b/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-warning-sign.png
new file mode 100644
index 0000000..f9392a3
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/feedback-warning-sign.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/keycloak-bg.png b/clusters/prod/apps/keycloak/theme/login/resources/img/keycloak-bg.png
new file mode 100644
index 0000000..4004db4
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/keycloak-bg.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/keycloak-logo-text.png b/clusters/prod/apps/keycloak/theme/login/resources/img/keycloak-logo-text.png
new file mode 100644
index 0000000..63f3b9f
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/keycloak-logo-text.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/keycloak-logo.png b/clusters/prod/apps/keycloak/theme/login/resources/img/keycloak-logo.png
new file mode 100644
index 0000000..ffa5b0b
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/keycloak-logo.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/lock.png b/clusters/prod/apps/keycloak/theme/login/resources/img/lock.png
new file mode 100644
index 0000000..697845b
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/lock.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/img/user.png b/clusters/prod/apps/keycloak/theme/login/resources/img/user.png
new file mode 100644
index 0000000..c0f4d0a
Binary files /dev/null and b/clusters/prod/apps/keycloak/theme/login/resources/img/user.png differ
diff --git a/clusters/prod/apps/keycloak/theme/login/resources/js/jquery.min.js b/clusters/prod/apps/keycloak/theme/login/resources/js/jquery.min.js
new file mode 100644
index 0000000..2c69bc9
--- /dev/null
+++ b/clusters/prod/apps/keycloak/theme/login/resources/js/jquery.min.js
@@ -0,0 +1,2 @@
+/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML=" ",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML=" ";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML=" ",v.option=!!ce.lastChild;var ge={thead:[1,""],col:[2,""],tr:[2,""],td:[3,""],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var me=/<|?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0
+
+
+
+
+
+
+
+
+ <#if properties.meta?has_content>
+ <#list properties.meta?split(' ') as meta>
+
+ #list>
+ #if>
+ ${msg("loginTitle",(realm.displayName!''))}
+
+ <#if properties.styles?has_content>
+ <#list properties.styles?split(' ') as style>
+
+ #list>
+ #if>
+ <#if properties.scripts?has_content>
+ <#list properties.scripts?split(' ') as script>
+
+ #list>
+ #if>
+ <#if scripts??>
+ <#list scripts as script>
+
+ #list>
+ #if>
+
+
+
+
+
+
+#macro>
diff --git a/clusters/prod/apps/keycloak/theme/login/theme.properties b/clusters/prod/apps/keycloak/theme/login/theme.properties
new file mode 100644
index 0000000..36a1d41
--- /dev/null
+++ b/clusters/prod/apps/keycloak/theme/login/theme.properties
@@ -0,0 +1,95 @@
+parent=base
+import=common/keycloak
+
+styles=node_modules/patternfly/dist/css/patternfly.min.css node_modules/patternfly/dist/css/patternfly-additions.min.css lib/zocial/zocial.css css/login.css?v=3
+scripts=js/jquery.min.js js/login.js
+meta=viewport==width=device-width,initial-scale=1
+
+kcHtmlClass=login-pf
+kcLoginClass=login-pf-page
+
+kcLogoLink=http://www.keycloak.org
+
+kcLogoClass=login-pf-brand
+
+kcContainerClass=container-fluid
+kcContentClass=col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 col-lg-6 col-lg-offset-3
+kcContentWrapperClass=row
+
+kcHeaderClass=login-pf-page-header
+kcFeedbackAreaClass=col-md-12
+kcLocaleClass=col-xs-12 col-sm-1
+kcAlertIconClasserror=pficon pficon-error-circle-o
+
+kcFormAreaClass=col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2 col-lg-8 col-lg-offset-2
+kcFormCardClass=card-pf
+kcFormCardAccountClass=login-pf-accounts
+kcFormSocialAccountClass=login-pf-social-section
+kcFormSocialAccountContentClass=col-xs-12 col-sm-6
+kcFormSocialAccountListClass=login-pf-social list-unstyled login-pf-social-all
+kcFormSocialAccountDoubleListClass=login-pf-social-double-col
+kcFormSocialAccountListLinkClass=login-pf-social-link
+kcFormHeaderClass=login-pf-header
+
+kcFeedbackErrorIcon=pficon pficon-error-circle-o
+kcFeedbackWarningIcon=pficon pficon-warning-triangle-o
+kcFeedbackSuccessIcon=pficon pficon-ok
+kcFeedbackInfoIcon=pficon pficon-info
+
+kcResetFlowIcon=pficon pficon-arrow fa-2x
+kcWebAuthnKeyIcon=pficon pficon-key
+
+kcFormClass=form-horizontal
+kcFormGroupClass=form-group
+kcFormGroupErrorClass=has-error
+kcLabelClass=control-label
+kcLabelWrapperClass=col-xs-12 col-sm-12 col-md-12 col-lg-12
+kcInputClass=form-control
+kcInputWrapperClass=col-xs-12 col-sm-12 col-md-12 col-lg-12
+kcFormOptionsClass=col-xs-12 col-sm-12 col-md-12 col-lg-12
+kcFormButtonsClass=col-xs-12 col-sm-12 col-md-12 col-lg-12
+kcFormSettingClass=login-pf-settings
+kcTextareaClass=form-control
+kcSignUpClass=login-pf-signup
+
+
+kcInfoAreaClass=col-xs-12 col-sm-4 col-md-4 col-lg-5 details
+
+##### css classes for form buttons
+# main class used for all buttons
+kcButtonClass=btn
+# classes defining priority of the button - primary or default (there is typically only one priority button for the form)
+kcButtonPrimaryClass=btn-primary
+kcButtonDefaultClass=btn-default
+# classes defining size of the button
+kcButtonLargeClass=btn-lg
+kcButtonBlockClass=btn-block
+
+##### css classes for input
+kcInputLargeClass=input-lg
+
+##### css classes for form accessability
+kcSrOnlyClass=sr-only
+
+##### css classes for select-authenticator form
+kcSelectAuthListClass=list-group list-view-pf
+kcSelectAuthListItemClass=list-group-item list-view-pf-stacked
+kcSelectAuthListItemInfoClass=list-view-pf-main-info
+kcSelectAuthListItemLeftClass=list-view-pf-left
+kcSelectAuthListItemBodyClass=list-view-pf-body
+kcSelectAuthListItemDescriptionClass=list-view-pf-description
+kcSelectAuthListItemHeadingClass=list-group-item-heading
+kcSelectAuthListItemHelpTextClass=list-group-item-text
+
+##### css classes for the authenticators
+kcAuthenticatorDefaultClass=fa list-view-pf-icon-lg
+kcAuthenticatorPasswordClass=fa fa-unlock list-view-pf-icon-lg
+kcAuthenticatorOTPClass=fa fa-mobile list-view-pf-icon-lg
+kcAuthenticatorWebAuthnClass=fa fa-key list-view-pf-icon-lg
+kcAuthenticatorWebAuthnPasswordlessClass=fa fa-key list-view-pf-icon-lg
+
+##### css classes for the OTP Login Form
+kcSelectOTPListClass=card-pf card-pf-view card-pf-view-select card-pf-view-single-select
+kcSelectOTPListItemClass=card-pf-body card-pf-top-element
+kcAuthenticatorOtpCircleClass=fa fa-mobile card-pf-icon-circle
+kcSelectOTPItemHeadingClass=card-pf-title text-center
\ No newline at end of file
diff --git a/clusters/prod/apps/keycloak/values.yaml b/clusters/prod/apps/keycloak/values.yaml
new file mode 100644
index 0000000..8669c7a
--- /dev/null
+++ b/clusters/prod/apps/keycloak/values.yaml
@@ -0,0 +1,135 @@
+keycloak:
+ global:
+ imagePullSecrets:
+ - docker-registry-secret
+
+ image:
+ repository: hdc-services-external/bitnami/keycloak
+
+ auth:
+ existingSecret: keycloak-credentials
+ passwordSecretKey: "admin-password"
+ adminUser: user
+
+ service:
+ type: ClusterIP
+
+ postgresql:
+ enabled: false
+
+ externalDatabase:
+ host: "keycloak-postgresql.keycloak"
+ port: 5432
+ user: bn_keycloak
+ database: bitnami_keycloak
+ existingSecret: keycloak-db-credentials
+ existingSecretPasswordKey: password
+
+ extraEnvVars:
+ - name: KEYCLOAK_LOGLEVEL
+ value: INFO
+ - name: KEYCLOAK_PROXY_ADDRESS_FORWARDING
+ value: "true"
+ - name: JAVA_OPTS
+ value: >-
+ -Dkeycloak.profile.feature.scripts=enabled
+ -Dkeycloak.profile.feature.upload_scripts=enabled
+ -Dkeycloak.profile.feature.token_exchange=enabled
+ -Dkeycloak.adminUrl=https://iam.hdc.ebrains.eu
+ -Dkeycloak.frontendUrl=https://iam.hdc.ebrains.eu
+
+ extraVolumes:
+ - name: antd
+ persistentVolumeClaim:
+ claimName: keycloak-antd
+ - name: theme-cm
+ configMap:
+ name: keycloak-antd-theme
+
+ extraVolumeMounts:
+ - name: antd
+ mountPath: /opt/bitnami/keycloak/themes/keycloak-antd/
+
+ initContainers:
+ - name: download-plugins
+ image: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-external/alpine:3.21
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ # Root required to chown downloaded plugins to uid 1001 (keycloak)
+ runAsUser: 0
+ runAsGroup: 0
+ allowPrivilegeEscalation: false
+ resources:
+ requests:
+ cpu: 100m
+ memory: 64Mi
+ limits:
+ cpu: 200m
+ memory: 128Mi
+ volumeMounts:
+ - mountPath: /opt/bitnami/keycloak/themes/keycloak-antd/
+ name: antd
+ - mountPath: /tmp/theme
+ name: theme-cm
+ envFrom:
+ - secretRef:
+ name: github-access-token
+ command: ["/bin/sh", "-c"]
+ args:
+ - >
+ set -e;
+ THEME_DIR=/opt/bitnami/keycloak/themes/keycloak-antd;
+ echo "=== Installing theme files ===" &&
+ mkdir -p $THEME_DIR/login/resources/css \
+ $THEME_DIR/login/resources/js \
+ $THEME_DIR/login/resources/img &&
+ cp /tmp/theme/login.ftl $THEME_DIR/login/ &&
+ cp /tmp/theme/template.ftl $THEME_DIR/login/ &&
+ cp /tmp/theme/theme.properties $THEME_DIR/login/ &&
+ cp /tmp/theme/login.css $THEME_DIR/login/resources/css/ &&
+ cp /tmp/theme/jquery.min.js $THEME_DIR/login/resources/js/ &&
+ cp /tmp/theme/login.js $THEME_DIR/login/resources/js/ &&
+ cp /tmp/theme/error.png /tmp/theme/favicon.ico \
+ /tmp/theme/feedback-error-arrow-down.png /tmp/theme/feedback-error-sign.png \
+ /tmp/theme/feedback-success-arrow-down.png /tmp/theme/feedback-success-sign.png \
+ /tmp/theme/feedback-warning-arrow-down.png /tmp/theme/feedback-warning-sign.png \
+ /tmp/theme/HDC-logo.png /tmp/theme/keycloak-bg.png \
+ /tmp/theme/keycloak-logo.png /tmp/theme/keycloak-logo-text.png \
+ /tmp/theme/lock.png /tmp/theme/user.png \
+ $THEME_DIR/login/resources/img/ &&
+ echo "=== Downloading plugins ===" &&
+ apk add --no-cache wget ca-certificates &&
+ mkdir -p $THEME_DIR/plugins &&
+ rm -fv $THEME_DIR/plugins/keycloak-last-login-* $THEME_DIR/plugins/keycloak-auth-require-group-* &&
+ wget --header "Authorization: token $GITHUB_TOKEN"
+ https://maven.pkg.github.com/PilotDataPlatform/keycloak-extensions/org/indocresearch/pilot/keycloak-last-login/1.0.1/keycloak-last-login-1.0.1.jar
+ -P $THEME_DIR/plugins &&
+ wget --header "Authorization: token $GITHUB_TOKEN"
+ https://maven.pkg.github.com/PilotDataPlatform/keycloak-extensions/com/github/thomasdarimont/keycloak/keycloak-auth-require-group/1.0.0/keycloak-auth-require-group-1.0.0.jar
+ -P $THEME_DIR/plugins &&
+ chown -R 1001:1001 $THEME_DIR
+
+ initdbScripts:
+ move_plugins.sh: |
+ #!/bin/bash
+ echo "Checking plugins folder..."
+ ls -trl /opt/bitnami/keycloak/themes/keycloak-antd/plugins
+ echo "Copying plugins to providers..."
+ cp -r /opt/bitnami/keycloak/themes/keycloak-antd/plugins/* /opt/bitnami/keycloak/providers/
+ echo "Done!"
+ ls -trl /opt/bitnami/keycloak/providers
+
+ ingress:
+ enabled: true
+ ingressClassName: nginx
+ annotations:
+ cert-manager.io/cluster-issuer: letsencrypt-prod
+ nginx.ingress.kubernetes.io/proxy-buffer-size: "128k"
+ hostname: iam.hdc.ebrains.eu
+ pathType: Prefix
+ path: /
+ servicePort: http
+ tls: true
+
+ logging:
+ level: INFO
diff --git a/clusters/prod/apps/kg-integration/Chart.yaml b/clusters/prod/apps/kg-integration/Chart.yaml
new file mode 100644
index 0000000..c1ed776
--- /dev/null
+++ b/clusters/prod/apps/kg-integration/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: kg-integration
+version: 0.1.0
+dependencies:
+ - name: base-chart
+ version: "0.1.0"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/kg-integration/application.yaml b/clusters/prod/apps/kg-integration/application.yaml
new file mode 100644
index 0000000..3453fb7
--- /dev/null
+++ b/clusters/prod/apps/kg-integration/application.yaml
@@ -0,0 +1,27 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: kg-integration
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "9"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/kg-integration
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/kg-integration/templates/external-secret.yaml b/clusters/prod/apps/kg-integration/templates/external-secret.yaml
new file mode 100644
index 0000000..af6edd7
--- /dev/null
+++ b/clusters/prod/apps/kg-integration/templates/external-secret.yaml
@@ -0,0 +1,21 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: kg-integration-credentials
+ namespace: utility
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: kg-integration-credentials
+ data:
+ - secretKey: db-password
+ remoteRef:
+ key: secret/data/postgresql
+ property: kg-integration-user-password
+ - secretKey: account-secret
+ remoteRef:
+ key: secret/data/kg-integration
+ property: account-secret
diff --git a/clusters/prod/apps/kg-integration/values.yaml b/clusters/prod/apps/kg-integration/values.yaml
new file mode 100644
index 0000000..d7d5f9b
--- /dev/null
+++ b/clusters/prod/apps/kg-integration/values.yaml
@@ -0,0 +1,73 @@
+base-chart:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/kg-integration
+ tag: "1.3.34"
+ pullPolicy: IfNotPresent
+ fullnameOverride: kg-integration
+ replicaCount: 1
+ container:
+ port: 8000
+ service:
+ type: ClusterIP
+ port: 8000
+ imagePullSecrets:
+ - name: docker-registry-secret
+ appConfig:
+ env: prod
+ srv_namespace: service_kg
+ config_center_enabled: "false"
+ config_center_base_url: ""
+ port: "8000"
+ extraEnv:
+ HOST: "0.0.0.0"
+ PORT: "8000"
+ SRV_NAMESPACE: "utility"
+ # Database
+ RDS_SCHEMA_DEFAULT: "kg_integration"
+ RDS_DB: "kg_integration"
+ RDS_HOST: "postgres.utility"
+ RDS_USER: "kg_integration_user"
+ RDS_PORT: "5432"
+ KG_ENV: "prod"
+ KG_PREFIX: "collab-"
+ KG_SERVICE_ACCOUNT_ID: "hdcclient-kg"
+ # Collaboratory
+ COLLAB_ENV: "prod"
+ COLLAB_PREFIX: "hdc-"
+ # Keycloak
+ KEYCLOAK_URL: "http://keycloak.keycloak/auth/"
+ KEYCLOAK_REALM: "hdc"
+ KEYCLOAK_BROKER: "ebrains-keycloak"
+ # Deployed services
+ AUTH_SERVICE: "http://auth.utility:5061"
+ DATASET_SERVICE: "http://dataset.utility:5081"
+ PROJECT_SERVICE: "http://project.utility:5064"
+ # Kafka
+ KAFKA_URL: "kafka-headless.utility:9092"
+ # Telemetry
+ OPEN_TELEMETRY_ENABLED: "false"
+ extraEnvYaml:
+ - name: RDS_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: kg-integration-credentials
+ key: db-password
+ - name: KG_SERVICE_ACCOUNT_SECRET
+ valueFrom:
+ secretKeyRef:
+ name: kg-integration-credentials
+ key: account-secret
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 500m
+ memory: 500Mi
+ readinessProbe:
+ failureThreshold: 3
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ successThreshold: 1
+ tcpSocket:
+ port: 8000
diff --git a/clusters/prod/apps/kong-postgresql/Chart.yaml b/clusters/prod/apps/kong-postgresql/Chart.yaml
new file mode 100644
index 0000000..6336bd8
--- /dev/null
+++ b/clusters/prod/apps/kong-postgresql/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: kong-postgresql
+version: 0.1.0
+dependencies:
+ - name: postgresql
+ version: "15.5.17"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/kong-postgresql/application.yaml b/clusters/prod/apps/kong-postgresql/application.yaml
new file mode 100644
index 0000000..59bbe24
--- /dev/null
+++ b/clusters/prod/apps/kong-postgresql/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: kong-postgresql
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+ # NO finalizer — StatefulSet with PVC
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/kong-postgresql
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/kong-postgresql/templates/external-secret.yaml b/clusters/prod/apps/kong-postgresql/templates/external-secret.yaml
new file mode 100644
index 0000000..413ccf4
--- /dev/null
+++ b/clusters/prod/apps/kong-postgresql/templates/external-secret.yaml
@@ -0,0 +1,21 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: kong-postgresql-credentials
+ namespace: utility
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: kong-postgresql-credentials
+ data:
+ - secretKey: password
+ remoteRef:
+ key: secret/data/kong
+ property: postgresql-password
+ - secretKey: postgres-password
+ remoteRef:
+ key: secret/data/kong
+ property: postgres-password
diff --git a/clusters/prod/apps/kong-postgresql/values.yaml b/clusters/prod/apps/kong-postgresql/values.yaml
new file mode 100644
index 0000000..79c1854
--- /dev/null
+++ b/clusters/prod/apps/kong-postgresql/values.yaml
@@ -0,0 +1,40 @@
+postgresql:
+ fullnameOverride: kong-postgresql
+
+ global:
+ imagePullSecrets:
+ - docker-registry-secret
+ postgresql:
+ auth:
+ database: kong
+ username: kong
+ existingSecret: kong-postgresql-credentials
+ secretKeys:
+ adminPasswordKey: postgres-password
+ userPasswordKey: password
+
+ image:
+ repository: hdc-services-external/bitnami/postgresql
+
+ architecture: standalone
+
+ primary:
+ pgHbaConfiguration: |-
+ local all all trust
+ host all all 127.0.0.1/32 trust
+ host all all ::1/128 trust
+ host all all 0.0.0.0/0 md5
+ host all all ::/0 md5
+ extendedConfiguration: |-
+ password_encryption = md5
+ persistence:
+ size: 5Gi
+ storageClass: "csi-cinder-high-speed"
+
+ resources:
+ limits:
+ cpu: 500m
+ memory: 256Mi
+ requests:
+ cpu: 10m
+ memory: 64Mi
diff --git a/clusters/prod/apps/kong/Chart.yaml b/clusters/prod/apps/kong/Chart.yaml
new file mode 100644
index 0000000..0b6f2bc
--- /dev/null
+++ b/clusters/prod/apps/kong/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: kong
+version: 0.1.0
+dependencies:
+ - name: kong
+ version: "9.1.8"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/kong/application.yaml b/clusters/prod/apps/kong/application.yaml
new file mode 100644
index 0000000..ed853ea
--- /dev/null
+++ b/clusters/prod/apps/kong/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: kong
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "9"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/kong
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/kong/values.yaml b/clusters/prod/apps/kong/values.yaml
new file mode 100644
index 0000000..de87baf
--- /dev/null
+++ b/clusters/prod/apps/kong/values.yaml
@@ -0,0 +1,76 @@
+kong:
+ migration:
+ annotations:
+ helm.sh/hook: post-install, pre-upgrade
+ helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
+ # Chart bug: postgresql.external.database not mapped to KONG_PG_DATABASE
+ extraEnvVars:
+ - name: KONG_PG_DATABASE
+ value: "kong"
+
+ global:
+ imagePullSecrets:
+ - docker-registry-secret
+
+ image:
+ repository: hdc-services-external/kong-with-oidc
+ pullPolicy: IfNotPresent
+ debug: false
+
+ database: postgresql
+ replicaCount: 1
+
+ # Disable bundled PostgreSQL — using external kong-postgresql app (wave 8)
+ postgresql:
+ enabled: false
+ external:
+ host: kong-postgresql
+ port: 5432
+ user: kong
+ database: kong
+ existingSecret: kong-postgresql-credentials
+ existingSecretPasswordKey: password
+
+ ingress:
+ enabled: true
+ hostname: api.hdc.ebrains.eu
+ path: /
+ annotations:
+ cert-manager.io/cluster-issuer: letsencrypt-prod
+ kubernetes.io/ingress.class: nginx
+ nginx.ingress.kubernetes.io/affinity: cookie
+ nginx.ingress.kubernetes.io/proxy-body-size: 20m
+ nginx.ingress.kubernetes.io/proxy-buffer-size: 512k
+ nginx.ingress.kubernetes.io/proxy-buffering: "on"
+ nginx.ingress.kubernetes.io/proxy-buffers-number: "8"
+ nginx.ingress.kubernetes.io/proxy-connect-timeout: 180s
+ nginx.ingress.kubernetes.io/proxy-max-temp-file-size: "0"
+ nginx.ingress.kubernetes.io/proxy-read-timeout: 180s
+ nginx.ingress.kubernetes.io/proxy-send-timeout: 180s
+ tls: true
+
+ ingressController:
+ enabled: false
+
+ kong:
+ extraEnvVars:
+ - name: KONG_LOG_LEVEL
+ value: "info"
+ - name: KONG_PLUGINS
+ value: "bundled,oidc"
+ - name: KONG_LUA_SSL_TRUSTED_CERTIFICATE
+ value: "/etc/ssl/certs/ca-certificates.crt"
+ # Chart bug: postgresql.external.database not mapped to KONG_PG_DATABASE
+ - name: KONG_PG_DATABASE
+ value: "kong"
+
+ service:
+ exposeAdmin: true
+
+ resources:
+ requests:
+ memory: "256Mi"
+ cpu: "100m"
+ limits:
+ memory: "512Mi"
+ cpu: "500m"
diff --git a/clusters/prod/apps/metadata-event-handler/Chart.yaml b/clusters/prod/apps/metadata-event-handler/Chart.yaml
new file mode 100644
index 0000000..99519fb
--- /dev/null
+++ b/clusters/prod/apps/metadata-event-handler/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: metadata-event-handler
+version: 0.1.0
+dependencies:
+ - name: metadata-event-handler
+ version: "0.1.1"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/metadata-event-handler/application.yaml b/clusters/prod/apps/metadata-event-handler/application.yaml
new file mode 100644
index 0000000..a48961c
--- /dev/null
+++ b/clusters/prod/apps/metadata-event-handler/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: metadata-event-handler
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "9"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/metadata-event-handler
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/metadata-event-handler/values.yaml b/clusters/prod/apps/metadata-event-handler/values.yaml
new file mode 100644
index 0000000..e7d9904
--- /dev/null
+++ b/clusters/prod/apps/metadata-event-handler/values.yaml
@@ -0,0 +1,57 @@
+metadata-event-handler:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/metadata_event_handler
+ pullPolicy: IfNotPresent
+
+ fullnameOverride: metadata-event-handler
+ replicaCount: 1
+
+ container:
+ port: 5069
+
+ service:
+ type: ClusterIP
+ port: 5069
+ targetPort: 5069
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ # appConfig: only KAFKA_SERVICE and ELASTICSEARCH_SERVICE are rendered by the chart template
+ appConfig:
+ KAFKA_SERVICE: "kafka.utility:9092"
+ ELASTICSEARCH_SERVICE: "http://elasticsearch-master.utility:9200"
+
+ extraEnv:
+ KAFKA_TOPICS: '["metadata.items", "metadata.items.activity", "dataset.activity"]'
+ METADATA_SERVICE: "http://metadata.utility:5066"
+ PROJECT_SERVICE: "http://project.utility:5064"
+ APP_NAME: "metadata-event-handler"
+ VERSION: "1.0.0"
+ HOST: "0.0.0.0"
+ PORT: "5069"
+ WORKERS: "1"
+
+ resources:
+ limits:
+ cpu: "1"
+ memory: 100Mi
+ requests:
+ cpu: 10m
+ memory: 10Mi
+
+ livenessProbe:
+ failureThreshold: 3
+ httpGet:
+ path: /v1/health/
+ port: 5069
+ scheme: HTTP
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 3
+
+ updateStrategy:
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 33%
+ type: RollingUpdate
diff --git a/clusters/prod/apps/metadata/Chart.yaml b/clusters/prod/apps/metadata/Chart.yaml
new file mode 100644
index 0000000..dc72443
--- /dev/null
+++ b/clusters/prod/apps/metadata/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: metadata
+version: 0.1.0
+dependencies:
+ - name: metadata-service
+ version: "1.0.0"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/metadata/application.yaml b/clusters/prod/apps/metadata/application.yaml
new file mode 100644
index 0000000..d1a7ac0
--- /dev/null
+++ b/clusters/prod/apps/metadata/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: metadata
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/metadata
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/metadata/templates/external-secret.yaml b/clusters/prod/apps/metadata/templates/external-secret.yaml
new file mode 100644
index 0000000..46b7832
--- /dev/null
+++ b/clusters/prod/apps/metadata/templates/external-secret.yaml
@@ -0,0 +1,17 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: metadata-credentials
+ namespace: utility
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: metadata-credentials
+ data:
+ - secretKey: metadata-user-password
+ remoteRef:
+ key: secret/data/postgresql
+ property: metadata-user-password
diff --git a/clusters/prod/apps/metadata/values.yaml b/clusters/prod/apps/metadata/values.yaml
new file mode 100644
index 0000000..9c980fb
--- /dev/null
+++ b/clusters/prod/apps/metadata/values.yaml
@@ -0,0 +1,75 @@
+metadata-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/metadata
+ pullPolicy: IfNotPresent
+
+ fullnameOverride: metadata
+ replicaCount: 1
+
+ container:
+ port: 5066
+
+ service:
+ type: ClusterIP
+ port: 5066
+ targetPort: 5066
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ appConfig:
+ port: 5066
+ env: prod
+ srv_namespace: metadata
+ config_center_enabled: false
+ METADATA_SCHEMA: metadata
+ OPSDB_UTILITY_HOST: postgres.utility
+ OPSDB_UTILITY_PORT: "5432"
+ OPSDB_UTILITY_USERNAME: metadata_user
+ DCM_PROJECT_ID: generate_id
+ RUN_MIGRATIONS: "true"
+ AUTH_HOST: "http://auth.utility:5061"
+ KAFKA_URL: "kafka.utility:9092"
+ KAFKA_TOPIC: "metadata.items"
+
+ extraEnv:
+ RSA_PUBLIC_KEY: "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFvQkNRQUpRbnpDK1UwN2h3NGliYWNLaWNMbWtTOFR0Mmp6MkFIcVFhWG1sOWUzeCsrZzh5TCtOaDNJSDAzLzdUV2xnbEFSNWRDcEU2cS9LaVpKS1dxU3RCcnlmOHk1UEhaUTJua1YxWXViajRPSThzMklKRFgyNU9XaUNvZFFDRkNwTkNyY1ZmSGpjbnJvRy9icGJoTTBBZ0RFc054UDlpd3NrZ2h3RVFGTDVuc1JWWkpyUEJ0T0dNRWJ4N0xNY3kyeFI2YmlySWFYTmNWSUlyd1g4MVB5bzZENlZRRzlkNkJSUmwvWlVDNGZ5SzZpNGxKUVJvUUV0SW0xNm9PNUFsUGpzYloxd0NXVStlazJJek9aNGRrRnhtUWlwdUpsbjI5TE1jZGdCMlFGZFRNcXBQTXlxWXc3ZmplWmhOL3FoZDFKbUVEeUZOVHVKcEt5Ymd2Y2VnNXdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0t"
+
+ extraEnvYaml:
+ - name: OPSDB_UTILITY_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: metadata-credentials
+ key: metadata-user-password
+
+ resources:
+ limits:
+ cpu: "1"
+ memory: 500Mi
+ requests:
+ cpu: 10m
+ memory: 50Mi
+
+ readinessProbe:
+ failureThreshold: 3
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ successThreshold: 1
+ tcpSocket:
+ port: 5066
+
+ livenessProbe:
+ failureThreshold: 3
+ httpGet:
+ path: /v1/health
+ port: 5066
+ scheme: HTTP
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 3
+
+ updateStrategy:
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 33%
+ type: RollingUpdate
diff --git a/clusters/prod/apps/notification/Chart.yaml b/clusters/prod/apps/notification/Chart.yaml
new file mode 100644
index 0000000..8dd8fef
--- /dev/null
+++ b/clusters/prod/apps/notification/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: notification
+version: 0.1.0
+dependencies:
+ - name: notification-service
+ version: "0.3.2"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/notification/application.yaml b/clusters/prod/apps/notification/application.yaml
new file mode 100644
index 0000000..447ba05
--- /dev/null
+++ b/clusters/prod/apps/notification/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: notification
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/notification
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/notification/templates/external-secret.yaml b/clusters/prod/apps/notification/templates/external-secret.yaml
new file mode 100644
index 0000000..c960f52
--- /dev/null
+++ b/clusters/prod/apps/notification/templates/external-secret.yaml
@@ -0,0 +1,17 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: notification-credentials
+ namespace: utility
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: notification-credentials
+ data:
+ - secretKey: notification-user-password
+ remoteRef:
+ key: secret/data/postgresql
+ property: notification-user-password
diff --git a/clusters/prod/apps/notification/values.yaml b/clusters/prod/apps/notification/values.yaml
new file mode 100644
index 0000000..d938aac
--- /dev/null
+++ b/clusters/prod/apps/notification/values.yaml
@@ -0,0 +1,78 @@
+notification-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/notification
+ pullPolicy: IfNotPresent
+ # tag 2.2.10 from versions.yaml
+ # chart prefixes: notification-{tag} (main), alembic-{tag} (init)
+
+ fullnameOverride: notification
+ replicaCount: 1
+
+ container:
+ port: 5065
+
+ service:
+ type: ClusterIP
+ port: 5065
+ targetPort: 5065
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ # appConfig: only the 5 vars the chart template renders explicitly
+ appConfig:
+ port: 5065
+ env: prod
+ config_center_enabled: "false"
+ config_center_base_url: "http://common.utility:5062/"
+ srv_namespace: service_notification
+
+ # All other config via extraEnv (applied to BOTH init + main containers)
+ extraEnv:
+ # App
+ HOST: "0.0.0.0"
+ WORKERS: "2"
+ PLATFORM_NAME: PILOT
+ namespace: utility
+ OPEN_TELEMETRY_ENABLED: "false"
+ POSTFIX: TODO-PROD-SMTP-RELAY # TODO: replace with prod SMTP relay
+ SMTP_PORT: "25"
+ SMTP_USER: ""
+ SMTP_PASS: ""
+ EMAIL_ATTACHMENT_MAX_SIZE_BYTES: "2097152"
+ # Database
+ RDS_HOST: postgres.utility
+ RDS_PORT: "5432"
+ RDS_USER: notification_user
+ RDS_DB_NAME: notifications
+
+ # Secret env vars (applied to BOTH init + main containers)
+ extraEnvYaml:
+ - name: RDS_PWD
+ valueFrom:
+ secretKeyRef:
+ name: notification-credentials
+ key: notification-user-password
+
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 500m
+ memory: 500Mi
+
+ readinessProbe:
+ tcpSocket:
+ port: 5065
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ failureThreshold: 3
+
+ livenessProbe:
+ httpGet:
+ path: /v1/health
+ port: 5065
+ periodSeconds: 10
+ timeoutSeconds: 3
+ failureThreshold: 3
diff --git a/clusters/prod/apps/pipelinewatch/Chart.yaml b/clusters/prod/apps/pipelinewatch/Chart.yaml
new file mode 100644
index 0000000..f18fb1a
--- /dev/null
+++ b/clusters/prod/apps/pipelinewatch/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: pipelinewatch
+version: 0.1.0
+dependencies:
+ - name: pipelinewatch-service
+ version: "0.4.2"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/pipelinewatch/application.yaml b/clusters/prod/apps/pipelinewatch/application.yaml
new file mode 100644
index 0000000..3e3b943
--- /dev/null
+++ b/clusters/prod/apps/pipelinewatch/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: pipelinewatch
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/pipelinewatch
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: greenroom
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/pipelinewatch/templates/rbac.yaml b/clusters/prod/apps/pipelinewatch/templates/rbac.yaml
new file mode 100644
index 0000000..61cd432
--- /dev/null
+++ b/clusters/prod/apps/pipelinewatch/templates/rbac.yaml
@@ -0,0 +1,21 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: pipelinewatch-job-watcher
+rules:
+ - apiGroups: ["batch"]
+ resources: ["jobs"]
+ verbs: ["get", "list", "watch", "delete"]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: pipelinewatch-job-watcher
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: pipelinewatch-job-watcher
+subjects:
+ - kind: ServiceAccount
+ name: pipelinewatch
+ namespace: greenroom
diff --git a/clusters/prod/apps/pipelinewatch/values.yaml b/clusters/prod/apps/pipelinewatch/values.yaml
new file mode 100644
index 0000000..9606c3c
--- /dev/null
+++ b/clusters/prod/apps/pipelinewatch/values.yaml
@@ -0,0 +1,46 @@
+pipelinewatch-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/pipelinewatch
+ pullPolicy: IfNotPresent
+
+ fullnameOverride: pipelinewatch-k8s-job
+ replicaCount: 1
+
+ container:
+ port: 6063
+ command: /app/worker_k8s_job_watch.py
+
+ service:
+ type: ClusterIP
+ port: 6063
+ targetPort: 6063
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ serviceAccount:
+ create: true
+ name: pipelinewatch
+
+ appConfig:
+ env: prod
+ config_center_enabled: "false"
+
+ extraEnv:
+ GR_ZONE_LABEL: "Greenroom"
+ CORE_ZONE_LABEL: "Core"
+ METADATA_SERVICE: "http://metadata.utility:5066"
+ DATAOPS_SERVICE: "http://dataops.utility:5063"
+
+ volumes:
+ name: nfsvol
+ mountPath: /data/core-storage
+ claimName: greenroom-storage
+
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 1
+ memory: 1000Mi
diff --git a/clusters/prod/apps/project/Chart.yaml b/clusters/prod/apps/project/Chart.yaml
new file mode 100644
index 0000000..d3fff92
--- /dev/null
+++ b/clusters/prod/apps/project/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: project
+version: 0.1.0
+dependencies:
+ - name: project-service
+ version: "0.2.1"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/project/application.yaml b/clusters/prod/apps/project/application.yaml
new file mode 100644
index 0000000..b622b7a
--- /dev/null
+++ b/clusters/prod/apps/project/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: project
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/project
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/project/templates/external-secret.yaml b/clusters/prod/apps/project/templates/external-secret.yaml
new file mode 100644
index 0000000..faf5e08
--- /dev/null
+++ b/clusters/prod/apps/project/templates/external-secret.yaml
@@ -0,0 +1,25 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: project-credentials
+ namespace: utility
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: project-credentials
+ data:
+ - secretKey: project-user-password
+ remoteRef:
+ key: secret/data/postgresql
+ property: project-user-password
+ - secretKey: minio-access-key
+ remoteRef:
+ key: secret/data/minio
+ property: access_key
+ - secretKey: minio-secret-key
+ remoteRef:
+ key: secret/data/minio
+ property: secret_key
diff --git a/clusters/prod/apps/project/values.yaml b/clusters/prod/apps/project/values.yaml
new file mode 100644
index 0000000..31e42b4
--- /dev/null
+++ b/clusters/prod/apps/project/values.yaml
@@ -0,0 +1,102 @@
+project-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/project
+ pullPolicy: IfNotPresent
+
+ fullnameOverride: project
+ replicaCount: 1
+
+ container:
+ port: 5064
+
+ service:
+ type: ClusterIP
+ port: 5064
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ appConfig:
+ port: 5064
+ env: prod
+ srv_namespace: service_project
+ config_center_enabled: false
+ config_center_base_url: http://common.utility:5062/
+
+ extraEnv:
+ APP_NAME: "project"
+ HOST: "0.0.0.0"
+ PORT: "5064"
+ WORKERS: "1"
+ RDS_DB_HOST: postgres.utility
+ RDS_DB_PORT: "5432"
+ RDS_DB_USERNAME: project_user
+ RDS_DB_NAME: project
+ RDS_ECHO_SQL_QUERIES: "false"
+ DCM_PROJECT_ID: generate_id
+ RUN_MIGRATIONS: "true"
+ AUTH_SERVICE: "http://auth.utility:5061"
+ METADATA_SERVICE: "http://metadata.utility:5066"
+ S3_HOST: minio.minio
+ S3_PORT: "9000"
+ S3_HTTPS_ENABLED: "false"
+ S3_GATEWAY_ENABLED: "false"
+ S3_BUCKET_ENCRYPTION_ENABLED: "false"
+ S3_BUCKET_FOR_PROJECT_LOGOS: project-logos
+ S3_PREFIX_FOR_PROJECT_IMAGE_URLS: "https://object.hdc.ebrains.eu/project-logos"
+ OBJECT_STORAGE_PROVIDER: S3
+ OPEN_TELEMETRY_ENABLED: "false"
+ LOG_LEVEL_DEFAULT: "30"
+ LOG_LEVEL_STDOUT: "30"
+ LOG_LEVEL_STDERR: "40"
+ SERVICE_CLIENT_TIMEOUT: "5"
+ ICON_SIZE_LIMIT: "16777216"
+
+ extraEnvYaml:
+ - name: RDS_DB_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: project-credentials
+ key: project-user-password
+ - name: S3_ACCESS_KEY
+ valueFrom:
+ secretKeyRef:
+ name: project-credentials
+ key: minio-access-key
+ - name: S3_SECRET_KEY
+ valueFrom:
+ secretKeyRef:
+ name: project-credentials
+ key: minio-secret-key
+
+ resources:
+ limits:
+ cpu: "1"
+ memory: 500Mi
+ requests:
+ cpu: 10m
+ memory: 50Mi
+
+ readinessProbe:
+ failureThreshold: 3
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ successThreshold: 1
+ tcpSocket:
+ port: 5064
+
+ livenessProbe:
+ failureThreshold: 3
+ httpGet:
+ path: /v1/health/
+ port: 5064
+ scheme: HTTP
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 3
+
+ updateStrategy:
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 33%
+ type: RollingUpdate
diff --git a/clusters/prod/apps/queue-consumer/Chart.yaml b/clusters/prod/apps/queue-consumer/Chart.yaml
new file mode 100644
index 0000000..bc88288
--- /dev/null
+++ b/clusters/prod/apps/queue-consumer/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: queue-consumer
+version: 0.1.0
+dependencies:
+ - name: queue-service
+ version: "0.3.0" # synced from versions.yaml via make sync-versions
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/queue-consumer/application.yaml b/clusters/prod/apps/queue-consumer/application.yaml
new file mode 100644
index 0000000..93dbb4c
--- /dev/null
+++ b/clusters/prod/apps/queue-consumer/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: queue-consumer
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/queue-consumer
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ # no versions.yaml — image tag is in values.yaml (prefixed per sub-service)
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: greenroom
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/queue-consumer/templates/external-secret.yaml b/clusters/prod/apps/queue-consumer/templates/external-secret.yaml
new file mode 100644
index 0000000..4a26c84
--- /dev/null
+++ b/clusters/prod/apps/queue-consumer/templates/external-secret.yaml
@@ -0,0 +1,33 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: queue-consumer-credentials
+ namespace: greenroom
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: queue-consumer-credentials
+ data:
+ - secretKey: rabbitmq-username
+ remoteRef:
+ key: secret/data/rabbitmq
+ property: username
+ - secretKey: rabbitmq-password
+ remoteRef:
+ key: secret/data/rabbitmq
+ property: password
+ - secretKey: redis-password
+ remoteRef:
+ key: secret/data/redis
+ property: password
+ - secretKey: minio-access-key
+ remoteRef:
+ key: secret/data/minio
+ property: access_key
+ - secretKey: minio-secret-key
+ remoteRef:
+ key: secret/data/minio
+ property: secret_key
diff --git a/clusters/prod/apps/queue-consumer/templates/rbac.yaml b/clusters/prod/apps/queue-consumer/templates/rbac.yaml
new file mode 100644
index 0000000..365f768
--- /dev/null
+++ b/clusters/prod/apps/queue-consumer/templates/rbac.yaml
@@ -0,0 +1,23 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: queue-consumer-job-creator
+ namespace: greenroom
+rules:
+ - apiGroups: ["batch"]
+ resources: ["jobs"]
+ verbs: ["create"]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: queue-consumer-job-creator
+ namespace: greenroom
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: queue-consumer-job-creator
+subjects:
+ - kind: ServiceAccount
+ name: queue-consumer
+ namespace: greenroom
diff --git a/clusters/prod/apps/queue-consumer/values.yaml b/clusters/prod/apps/queue-consumer/values.yaml
new file mode 100644
index 0000000..147098d
--- /dev/null
+++ b/clusters/prod/apps/queue-consumer/values.yaml
@@ -0,0 +1,104 @@
+queue-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/queue/consumer
+ pullPolicy: IfNotPresent
+ tag: "consumer-2.2.16" # prefixed tag — NOT from versions.yaml
+ fullnameOverride: queue-consumer
+ replicaCount: 1
+ container:
+ port: 6060
+ service:
+ type: ClusterIP
+ port: 6060
+ targetPort: 6060
+ imagePullSecrets:
+ - name: docker-registry-secret
+ serviceAccount:
+ create: true
+ name: queue-consumer
+ appConfig:
+ env: prod
+ config_center_enabled: "false"
+ config_center_base_url: ""
+ extraEnv:
+ # -- Pipeline config --
+ bids_validate_pipeline: "bids_validate"
+ copy_pipeline: "data_transfer"
+ copy_pipeline_folder: "data_transfer_folder"
+ move_pipeline: "data_delete"
+ move_pipeline_folder: "data_delete_folder"
+ # -- Pipeline images (OVH registry) --
+ bids_validate_image: "n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/pipelines/bids-validator:bids-validator-2.2.15"
+ data_transfer_image: "n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/pipelines/filecopy:filecopy-2.2.16"
+ # -- Storage (pass-through to spawned Jobs — consumer doesn't touch FS itself) --
+ data_lake: "/data/core-storage"
+ claim_name: "greenroom-storage"
+ NFS_MOUNT: "nfsvol"
+ # -- Zone labels --
+ GREEN_ZONE_LABEL: "Greenroom"
+ CORE_ZONE_LABEL: "Core"
+ # -- Database (pass-through to spawned Jobs — consumer has NO DB driver) --
+ RDS_DBNAME: "approval"
+ RDS_HOST: "postgres.utility"
+ RDS_PORT: "5432"
+ # -- S3 / MinIO --
+ S3_HOST: "minio.minio"
+ S3_PORT: "9000"
+ S3_INTERNAL_HTTPS: "false"
+ # -- RabbitMQ --
+ gm_queue_endpoint: "message-bus-greenroom.greenroom"
+ # -- Queue config --
+ gr_queue: "gr_queue"
+ gr_exchange: "gr_exchange"
+ # -- Inter-service URLs --
+ DATAOPS_SERVICE: "http://dataops.utility:5063"
+ DATASET_SERVICE: "http://dataset.utility:5081"
+ QUEUE_SERVICE: "http://queue-producer.greenroom:6060"
+ METADATA_SERVICE: "http://metadata.utility:5066"
+ PROJECT_SERVICE: "http://project.utility:5064"
+ APPROVAL_SERVICE: "http://approval.utility:8000"
+ NOTIFICATION_SERVICE: "http://notification.utility:5065"
+ KAFKA_URL: "kafka.utility:9092"
+ REDIS_HOST: "redis-master.redis"
+ REDIS_PORT: "6379"
+ ATLAS_HOST: "atlas.utility"
+ ATLAS_PORT: "21000"
+ # Secrets — all pass-through to spawned Jobs (consumer itself uses none except RabbitMQ creds)
+ extraEnvYaml:
+ - name: gm_username
+ valueFrom:
+ secretKeyRef:
+ name: queue-consumer-credentials
+ key: rabbitmq-username
+ - name: gm_password
+ valueFrom:
+ secretKeyRef:
+ name: queue-consumer-credentials
+ key: rabbitmq-password
+ - name: REDIS_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: queue-consumer-credentials
+ key: redis-password
+ - name: S3_ACCESS_KEY
+ valueFrom:
+ secretKeyRef:
+ name: queue-consumer-credentials
+ key: minio-access-key
+ - name: S3_SECRET_KEY
+ valueFrom:
+ secretKeyRef:
+ name: queue-consumer-credentials
+ key: minio-secret-key
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 1
+ memory: 1000Mi
+ updateStrategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: "33%"
diff --git a/clusters/prod/apps/queue-producer/Chart.yaml b/clusters/prod/apps/queue-producer/Chart.yaml
new file mode 100644
index 0000000..fd222d1
--- /dev/null
+++ b/clusters/prod/apps/queue-producer/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: queue-producer
+version: 0.1.0
+dependencies:
+ - name: queue-service
+ version: "0.3.0" # synced from versions.yaml via make sync-versions
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/queue-producer/application.yaml b/clusters/prod/apps/queue-producer/application.yaml
new file mode 100644
index 0000000..96ce9dd
--- /dev/null
+++ b/clusters/prod/apps/queue-producer/application.yaml
@@ -0,0 +1,27 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: queue-producer
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/queue-producer
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: greenroom
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/queue-producer/templates/external-secret.yaml b/clusters/prod/apps/queue-producer/templates/external-secret.yaml
new file mode 100644
index 0000000..cb6cb15
--- /dev/null
+++ b/clusters/prod/apps/queue-producer/templates/external-secret.yaml
@@ -0,0 +1,21 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: queue-producer-credentials
+ namespace: greenroom
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: queue-producer-credentials
+ data:
+ - secretKey: rabbitmq-username
+ remoteRef:
+ key: secret/data/rabbitmq
+ property: username
+ - secretKey: rabbitmq-password
+ remoteRef:
+ key: secret/data/rabbitmq
+ property: password
diff --git a/clusters/prod/apps/queue-producer/values.yaml b/clusters/prod/apps/queue-producer/values.yaml
new file mode 100644
index 0000000..8d134e3
--- /dev/null
+++ b/clusters/prod/apps/queue-producer/values.yaml
@@ -0,0 +1,57 @@
+queue-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/queue/producer
+ pullPolicy: IfNotPresent
+ tag: "producer-2.2.16"
+ fullnameOverride: queue-producer
+ replicaCount: 1
+ container:
+ port: 6060
+ service:
+ type: ClusterIP
+ port: 6060
+ targetPort: 6060
+ imagePullSecrets:
+ - name: docker-registry-secret
+ appConfig:
+ env: prod
+ config_center_enabled: "false"
+ config_center_base_url: ""
+ extraEnv:
+ copy_pipeline: "data_transfer"
+ data_storage: "/core-data"
+ gr_queue: "gr_queue"
+ gr_exchange: "gr_exchange"
+ LOG_PATH: "/tmp/logs"
+ move_pipeline: "data_delete"
+ WORK_PATH: "/tmp/workdir"
+ # -- RabbitMQ --
+ gm_queue_endpoint: "message-bus-greenroom.greenroom"
+ extraEnvYaml:
+ - name: gm_username
+ valueFrom:
+ secretKeyRef:
+ name: queue-producer-credentials
+ key: rabbitmq-username
+ - name: gm_password
+ valueFrom:
+ secretKeyRef:
+ name: queue-producer-credentials
+ key: rabbitmq-password
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 1
+ memory: 1000Mi
+ readinessProbe:
+ tcpSocket:
+ port: 6060
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ updateStrategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: "33%"
diff --git a/clusters/prod/apps/queue-socketio/Chart.yaml b/clusters/prod/apps/queue-socketio/Chart.yaml
new file mode 100644
index 0000000..a4965b1
--- /dev/null
+++ b/clusters/prod/apps/queue-socketio/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: queue-socketio
+version: 0.1.0
+dependencies:
+ - name: queue-service
+ version: "0.4.1" # synced from versions.yaml (queue-service-socketio) via make sync-versions
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/queue-socketio/application.yaml b/clusters/prod/apps/queue-socketio/application.yaml
new file mode 100644
index 0000000..5589084
--- /dev/null
+++ b/clusters/prod/apps/queue-socketio/application.yaml
@@ -0,0 +1,27 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: queue-socketio
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/queue-socketio
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: greenroom
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/queue-socketio/templates/external-secret.yaml b/clusters/prod/apps/queue-socketio/templates/external-secret.yaml
new file mode 100644
index 0000000..f920b68
--- /dev/null
+++ b/clusters/prod/apps/queue-socketio/templates/external-secret.yaml
@@ -0,0 +1,21 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: queue-socketio-credentials
+ namespace: greenroom
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: queue-socketio-credentials
+ data:
+ - secretKey: rabbitmq-username
+ remoteRef:
+ key: secret/data/rabbitmq
+ property: username
+ - secretKey: rabbitmq-password
+ remoteRef:
+ key: secret/data/rabbitmq
+ property: password
diff --git a/clusters/prod/apps/queue-socketio/values.yaml b/clusters/prod/apps/queue-socketio/values.yaml
new file mode 100644
index 0000000..023d43e
--- /dev/null
+++ b/clusters/prod/apps/queue-socketio/values.yaml
@@ -0,0 +1,64 @@
+queue-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/queue/socketio
+ pullPolicy: IfNotPresent
+ tag: "socketio-2.2.16"
+ fullnameOverride: queue-socketio
+ replicaCount: 1
+ container:
+ port: 6062
+ service:
+ type: ClusterIP
+ port: 6062
+ targetPort: 6062
+ imagePullSecrets:
+ - name: docker-registry-secret
+ appConfig:
+ env: prod
+ config_center_enabled: "false"
+ config_center_base_url: ""
+ extraEnv:
+ # -- RabbitMQ --
+ gm_queue_endpoint: "message-bus-greenroom.greenroom"
+ extraEnvYaml:
+ - name: gm_username
+ valueFrom:
+ secretKeyRef:
+ name: queue-socketio-credentials
+ key: rabbitmq-username
+ - name: gm_password
+ valueFrom:
+ secretKeyRef:
+ name: queue-socketio-credentials
+ key: rabbitmq-password
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 1
+ memory: 1000Mi
+ readinessProbe:
+ tcpSocket:
+ port: 6062
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ updateStrategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: "33%"
+ ingress:
+ enabled: true
+ hostname: hdc.ebrains.eu
+ path: /socket.io/
+ pathType: ImplementationSpecific
+ annotations:
+ cert-manager.io/cluster-issuer: letsencrypt-prod
+ kubernetes.io/ingress.class: nginx
+ nginx.ingress.kubernetes.io/proxy-body-size: 25m
+ nginx.ingress.kubernetes.io/ssl-redirect: "true"
+ # WebSocket support
+ nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
+ nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
+ tls: true
diff --git a/clusters/prod/apps/search/Chart.yaml b/clusters/prod/apps/search/Chart.yaml
new file mode 100644
index 0000000..52abf81
--- /dev/null
+++ b/clusters/prod/apps/search/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: search
+version: 0.1.0
+dependencies:
+ - name: search-service
+ version: "0.2.2"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/search/application.yaml b/clusters/prod/apps/search/application.yaml
new file mode 100644
index 0000000..82c3578
--- /dev/null
+++ b/clusters/prod/apps/search/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: search
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/search
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/search/values.yaml b/clusters/prod/apps/search/values.yaml
new file mode 100644
index 0000000..7321ad1
--- /dev/null
+++ b/clusters/prod/apps/search/values.yaml
@@ -0,0 +1,47 @@
+search-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/search
+ pullPolicy: IfNotPresent
+
+ fullnameOverride: search
+ replicaCount: 1
+
+ container:
+ port: 5064
+
+ service:
+ type: ClusterIP
+ port: 5064
+ targetPort: 5064
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ appConfig:
+ env: prod
+ port: 5064
+ config_center_enabled: false
+ config_center_base_url: http://common.utility:5062/
+ srv_namespace: service_search
+
+ extraEnv:
+ HOST: "0.0.0.0"
+ PORT: "5064"
+ ELASTICSEARCH_URI: "http://elasticsearch-master.utility:9200"
+ WORKSERS: "2"
+
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 500m
+ memory: 500Mi
+
+ readinessProbe:
+ tcpSocket:
+ port: 5064
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ failureThreshold: 3
+ successThreshold: 1
diff --git a/clusters/prod/apps/upload-core/Chart.yaml b/clusters/prod/apps/upload-core/Chart.yaml
new file mode 100644
index 0000000..1f2c615
--- /dev/null
+++ b/clusters/prod/apps/upload-core/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: upload-core
+version: 0.1.0
+dependencies:
+ - name: upload-service
+ version: "0.3.1"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/upload-core/application.yaml b/clusters/prod/apps/upload-core/application.yaml
new file mode 100644
index 0000000..1c80377
--- /dev/null
+++ b/clusters/prod/apps/upload-core/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: upload-core
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/upload-core
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: core
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/upload-core/templates/external-secret.yaml b/clusters/prod/apps/upload-core/templates/external-secret.yaml
new file mode 100644
index 0000000..4254aca
--- /dev/null
+++ b/clusters/prod/apps/upload-core/templates/external-secret.yaml
@@ -0,0 +1,25 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: upload-credentials
+ namespace: core
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: upload-credentials
+ data:
+ - secretKey: redis-password
+ remoteRef:
+ key: secret/data/redis
+ property: password
+ - secretKey: minio-access-key
+ remoteRef:
+ key: secret/data/minio
+ property: access_key
+ - secretKey: minio-secret-key
+ remoteRef:
+ key: secret/data/minio
+ property: secret_key
diff --git a/clusters/prod/apps/upload-core/values.yaml b/clusters/prod/apps/upload-core/values.yaml
new file mode 100644
index 0000000..6425753
--- /dev/null
+++ b/clusters/prod/apps/upload-core/values.yaml
@@ -0,0 +1,96 @@
+upload-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/upload
+ pullPolicy: IfNotPresent
+
+
+ fullnameOverride: upload
+ replicaCount: 1
+
+ container:
+ port: 5079
+
+ service:
+ type: ClusterIP
+ port: 5079
+ targetPort: 5079
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ appConfig:
+ port: 5079
+ env: prod
+
+ extraEnv:
+ HOST: "0.0.0.0"
+ namespace: "core"
+ ROOT_PATH: "/data/core-storage"
+ CORE_ZONE_LABEL: "Core"
+ GREEN_ZONE_LABEL: "Greenroom"
+ DATAOPS_SERVICE: "http://dataops.utility:5063"
+ METADATA_SERVICE: "http://metadata.utility:5066"
+ PROJECT_SERVICE: "http://project.utility:5064"
+ S3_INTERNAL: "minio.minio:9000"
+ S3_INTERNAL_HTTPS: "False"
+ S3_PUBLIC: "object.hdc.ebrains.eu"
+ S3_PUBLIC_HTTPS: "True"
+ REDIS_HOST: "redis-master.redis"
+ REDIS_PORT: "6379"
+ REDIS_DB: "0"
+ KAFKA_URL: "kafka.utility:9092"
+ KAFKA_ACTIVITY_TOPIC: "metadata.items.activity"
+ OPEN_TELEMETRY_ENABLED: "False"
+ OPEN_TELEMETRY_HOST: "127.0.0.1"
+ OPEN_TELEMETRY_PORT: "6831"
+
+ extraEnvYaml:
+ - name: REDIS_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: upload-credentials
+ key: redis-password
+ - name: S3_ACCESS_KEY
+ valueFrom:
+ secretKeyRef:
+ name: upload-credentials
+ key: minio-access-key
+ - name: S3_SECRET_KEY
+ valueFrom:
+ secretKeyRef:
+ name: upload-credentials
+ key: minio-secret-key
+
+ # Single object, not array — chart template accesses .Values.volumes.mountPath directly
+ volumes:
+ name: upload-storage
+ mountPath: /data/core-storage
+ claimName: core-storage
+
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 500m
+ memory: 500Mi
+
+ readinessProbe:
+ tcpSocket:
+ port: 5079
+ initialDelaySeconds: 5
+ periodSeconds: 10
+
+ livenessProbe:
+ httpGet:
+ path: /v1/health
+ port: 5079
+ periodSeconds: 10
+ timeoutSeconds: 3
+ failureThreshold: 3
+
+ updateStrategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 0
diff --git a/clusters/prod/apps/upload-greenroom/Chart.yaml b/clusters/prod/apps/upload-greenroom/Chart.yaml
new file mode 100644
index 0000000..410f3b6
--- /dev/null
+++ b/clusters/prod/apps/upload-greenroom/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: upload-greenroom
+version: 0.1.0
+dependencies:
+ - name: upload-service
+ version: "0.3.1"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/upload-greenroom/application.yaml b/clusters/prod/apps/upload-greenroom/application.yaml
new file mode 100644
index 0000000..98d186e
--- /dev/null
+++ b/clusters/prod/apps/upload-greenroom/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: upload-greenroom
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/upload-greenroom
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: greenroom
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/upload-greenroom/templates/external-secret.yaml b/clusters/prod/apps/upload-greenroom/templates/external-secret.yaml
new file mode 100644
index 0000000..08e76ef
--- /dev/null
+++ b/clusters/prod/apps/upload-greenroom/templates/external-secret.yaml
@@ -0,0 +1,25 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: upload-credentials
+ namespace: greenroom
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: upload-credentials
+ data:
+ - secretKey: redis-password
+ remoteRef:
+ key: secret/data/redis
+ property: password
+ - secretKey: minio-access-key
+ remoteRef:
+ key: secret/data/minio
+ property: access_key
+ - secretKey: minio-secret-key
+ remoteRef:
+ key: secret/data/minio
+ property: secret_key
diff --git a/clusters/prod/apps/upload-greenroom/values.yaml b/clusters/prod/apps/upload-greenroom/values.yaml
new file mode 100644
index 0000000..67323ab
--- /dev/null
+++ b/clusters/prod/apps/upload-greenroom/values.yaml
@@ -0,0 +1,96 @@
+upload-service:
+ image:
+ repository: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/upload
+ pullPolicy: IfNotPresent
+
+
+ fullnameOverride: upload
+ replicaCount: 1
+
+ container:
+ port: 5079
+
+ service:
+ type: ClusterIP
+ port: 5079
+ targetPort: 5079
+
+ imagePullSecrets:
+ - name: docker-registry-secret
+
+ appConfig:
+ port: 5079
+ env: prod
+
+ extraEnv:
+ HOST: "0.0.0.0"
+ namespace: "greenroom"
+ ROOT_PATH: "/data/greenroom-storage"
+ CORE_ZONE_LABEL: "Core"
+ GREEN_ZONE_LABEL: "Greenroom"
+ DATAOPS_SERVICE: "http://dataops.utility:5063"
+ METADATA_SERVICE: "http://metadata.utility:5066"
+ PROJECT_SERVICE: "http://project.utility:5064"
+ S3_INTERNAL: "minio.minio:9000"
+ S3_INTERNAL_HTTPS: "False"
+ S3_PUBLIC: "object.hdc.ebrains.eu"
+ S3_PUBLIC_HTTPS: "True"
+ REDIS_HOST: "redis-master.redis"
+ REDIS_PORT: "6379"
+ REDIS_DB: "0"
+ KAFKA_URL: "kafka.utility:9092"
+ KAFKA_ACTIVITY_TOPIC: "metadata.items.activity"
+ OPEN_TELEMETRY_ENABLED: "False"
+ OPEN_TELEMETRY_HOST: "127.0.0.1"
+ OPEN_TELEMETRY_PORT: "6831"
+
+ extraEnvYaml:
+ - name: REDIS_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: upload-credentials
+ key: redis-password
+ - name: S3_ACCESS_KEY
+ valueFrom:
+ secretKeyRef:
+ name: upload-credentials
+ key: minio-access-key
+ - name: S3_SECRET_KEY
+ valueFrom:
+ secretKeyRef:
+ name: upload-credentials
+ key: minio-secret-key
+
+ # Single object, not array — chart template accesses .Values.volumes.mountPath directly
+ volumes:
+ name: upload-storage
+ mountPath: /data/greenroom-storage
+ claimName: greenroom-storage
+
+ resources:
+ requests:
+ cpu: 10m
+ memory: 50Mi
+ limits:
+ cpu: 500m
+ memory: 500Mi
+
+ readinessProbe:
+ tcpSocket:
+ port: 5079
+ initialDelaySeconds: 5
+ periodSeconds: 10
+
+ livenessProbe:
+ httpGet:
+ path: /v1/health
+ port: 5079
+ periodSeconds: 10
+ timeoutSeconds: 3
+ failureThreshold: 3
+
+ updateStrategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 0
diff --git a/clusters/prod/apps/xwiki/Chart.yaml b/clusters/prod/apps/xwiki/Chart.yaml
new file mode 100644
index 0000000..40b4c2a
--- /dev/null
+++ b/clusters/prod/apps/xwiki/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: xwiki
+version: 0.1.0
+dependencies:
+ - name: xwiki
+ version: "0.3.0"
+ repository: https://pilotdataplatform.github.io/helm-charts/
diff --git a/clusters/prod/apps/xwiki/application.yaml b/clusters/prod/apps/xwiki/application.yaml
new file mode 100644
index 0000000..93e5af3
--- /dev/null
+++ b/clusters/prod/apps/xwiki/application.yaml
@@ -0,0 +1,28 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: xwiki
+ namespace: argocd
+ annotations:
+ argocd.argoproj.io/sync-wave: "8"
+spec:
+ project: default
+ source:
+ repoURL: https://github.com/PilotDataPlatform/pilot-hdc-platform-gitops.git
+ targetRevision: main
+ path: clusters/prod/apps/xwiki
+ helm:
+ valueFiles:
+ - ../../registry.yaml
+ - ../../versions.yaml
+ - values.yaml
+ destination:
+ server: https://kubernetes.default.svc
+ namespace: utility
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - ServerSideApply=true
diff --git a/clusters/prod/apps/xwiki/templates/external-secret.yaml b/clusters/prod/apps/xwiki/templates/external-secret.yaml
new file mode 100644
index 0000000..6288be2
--- /dev/null
+++ b/clusters/prod/apps/xwiki/templates/external-secret.yaml
@@ -0,0 +1,42 @@
+# Database credentials — target name MUST be "xwiki-postgresql"
+# Both the PG sub-chart (via existingSecret) and the XWiki deployment
+# (hardcoded -postgresql) read from this Secret
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: xwiki-postgresql
+ namespace: utility
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: xwiki-postgresql
+ data:
+ - secretKey: postgresql-password
+ remoteRef:
+ key: secret/data/xwiki
+ property: postgresql-password
+---
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: xwiki-config
+ namespace: utility
+spec:
+ refreshInterval: 1h
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: vault
+ target:
+ name: xwiki-config
+ data:
+ - secretKey: xwiki.cfg
+ remoteRef:
+ key: secret/data/xwiki
+ property: xwiki-cfg
+ - secretKey: xwiki.properties
+ remoteRef:
+ key: secret/data/xwiki
+ property: xwiki-properties
diff --git a/clusters/prod/apps/xwiki/templates/pvc.yaml b/clusters/prod/apps/xwiki/templates/pvc.yaml
new file mode 100644
index 0000000..5a7e170
--- /dev/null
+++ b/clusters/prod/apps/xwiki/templates/pvc.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: xwiki-data
+ namespace: utility
+spec:
+ accessModes:
+ - ReadWriteMany
+ storageClassName: nfs-client
+ resources:
+ requests:
+ storage: 5Gi
diff --git a/clusters/prod/apps/xwiki/values.yaml b/clusters/prod/apps/xwiki/values.yaml
new file mode 100644
index 0000000..d537017
--- /dev/null
+++ b/clusters/prod/apps/xwiki/values.yaml
@@ -0,0 +1,80 @@
+xwiki:
+ replicaCount: 1
+
+ overrides:
+ image: true
+
+ image:
+ name: n47w5524.c1.de1.container-registry.ovh.net/hdc-services-image/xwiki
+ pullPolicy: IfNotPresent
+
+ mysql:
+ enabled: false
+
+ postgresql:
+ enabled: true
+ postgresqlUsername: xwiki
+ postgresqlDatabase: xwiki
+ existingSecret: xwiki-postgresql
+ image:
+ repository: hdc-services-external/bitnami/postgresql
+ tag: 11.3.0-debian-9-r38
+ volumePermissions:
+ image:
+ repository: hdc-services-external/bitnami/minideb
+ tag: stretch
+ persistence:
+ storageClass: nfs-client
+ size: 1Gi
+
+ service:
+ type: ClusterIP
+
+ ingress:
+ enabled: true
+ annotations:
+ cert-manager.io/cluster-issuer: letsencrypt-prod
+ nginx.ingress.kubernetes.io/affinity: cookie
+ nginx.ingress.kubernetes.io/proxy-body-size: 100m
+ nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600"
+ nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
+ nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
+ hostname: xwiki.hdc.ebrains.eu
+ path: /
+ pathType: Prefix
+ tls: true
+
+ # Chart-managed PVC (hardcoded name "xwiki", mounts at /opt/solr/server/solr)
+ # Can't disable — keep small and ignore
+ storageClass: nfs-client
+ storage: 1Gi
+
+ solr:
+ enabled: false
+
+ # Volume name "xwiki-conf" avoids collision with chart built-in volume "xwiki-data"
+ extraVolumes:
+ - name: xwiki-config
+ secret:
+ secretName: xwiki-config
+ - name: xwiki-conf
+ persistentVolumeClaim:
+ claimName: xwiki-data
+
+ extraVolumeMounts:
+ - name: xwiki-conf
+ mountPath: /usr/local/xwiki/data
+ - name: xwiki-config
+ mountPath: /usr/local/xwiki/data/xwiki.cfg
+ subPath: xwiki.cfg
+ - name: xwiki-config
+ mountPath: /usr/local/xwiki/data/xwiki.properties
+ subPath: xwiki.properties
+
+ resources:
+ requests:
+ cpu: "1"
+ memory: 2Gi
+ limits:
+ cpu: "2"
+ memory: 4Gi
diff --git a/docs/vault-secrets.md b/docs/vault-secrets.md
index 0aaeac1..3fb4332 100644
--- a/docs/vault-secrets.md
+++ b/docs/vault-secrets.md
@@ -31,7 +31,8 @@ vault kv patch secret/postgresql -user-password=$(openssl rand -hex 24)
vault kv put secret/keycloak \
admin-password=$(openssl rand -hex 24) \
postgres-password=$(openssl rand -hex 24) \
- keycloak-user-password=$(openssl rand -hex 24)
+ keycloak-user-password=$(openssl rand -hex 24) \
+ github-token=''
```
## Redis (`secret/redis`)
@@ -76,7 +77,8 @@ vault kv put secret/docker-registry/ovh \
```bash
vault kv put secret/auth \
- keycloak-client-secret=''
+ keycloak-client-secret='' \
+ freeipa-password=''
```
## Kong (`secret/kong`)
@@ -103,6 +105,17 @@ vault kv put secret/download \
download-key=$(openssl rand -hex 32)
```
+## XWiki (`secret/xwiki`)
+
+```bash
+vault kv put secret/xwiki \
+ postgresql-password=$(openssl rand -hex 24) \
+ xwiki-cfg='' \
+ xwiki-properties=''
+```
+
+The `xwiki-cfg` and `xwiki-properties` values are full file contents mounted into the container. Copy from the running dev instance or from backup.
+
## KG Integration (`secret/kg-integration`)
```bash