diff --git a/charts/veritable-cloudagent/Chart.yaml b/charts/veritable-cloudagent/Chart.yaml index af07a6e73..d288ef3ac 100644 --- a/charts/veritable-cloudagent/Chart.yaml +++ b/charts/veritable-cloudagent/Chart.yaml @@ -26,4 +26,4 @@ maintainers: name: veritable-cloudagent sources: - https://github.com/digicatapult/veritable-cloudagent -version: 2.4.56 +version: 2.5.0 diff --git a/charts/veritable-cloudagent/README.md b/charts/veritable-cloudagent/README.md index 7dccd536b..2d30451b3 100644 --- a/charts/veritable-cloudagent/README.md +++ b/charts/veritable-cloudagent/README.md @@ -324,7 +324,7 @@ The command removes all the Kubernetes components associated with the chart and | `postgresql.enabled` | Switch to enable or disable the PostgreSQL helm chart | `true` | | `postgresql.auth.username` | Name for a custom user to create | `veritable-cloudgent` | | `postgresql.auth.password` | Password for the custom user to create | `""` | -| `postgresql.auth.database` | Name for a custom database to create | `wallet-id` | +| `postgresql.auth.database` | Name for a custom database to create | `did-web-server` | | `postgresql.auth.existingSecret` | Name of existing secret to use for PostgreSQL credentials | `""` | | `postgresql.architecture` | PostgreSQL architecture (`standalone` or `replication`) | `standalone` | | `postgresql.global.security.allowInsecureImages` | Allow usage of `bitnamilegacy` repository` | `true` | @@ -343,6 +343,45 @@ The command removes all the Kubernetes components associated with the chart and | `externalDatabase.existingSecretPasswordKey` | Name of an existing secret key containing the non-root credentials | `""` | | `externalDatabase.existingSecretPostgresPasswordKey` | Name of an existing secret key containing the admin credentials | `""` | +### Database Migration Init Container Parameters + +| Name | Description | Value | +| --------------------------- | ------------------------------------------- | -------------------- | +| `initDbMigrate.enabled` | Run database migration in an init container | `true` | +| `initDbMigrate.environment` | NODE_ENV value used during migration | `production` | +| `initDbMigrate.args` | Arguments supplied to npx knex (array) | `["migrate:latest"]` | + +### DID Web Server Parameters + +| Name | Description | Value | +| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------ | +| `didWebServer.enabled` | Enable DID Web Server feature. When false, no related resources/env vars are rendered | `false` | +| `didWebServer.containerPort` | Container port the DID Web Server listens on (maps to DID_WEB_PORT) | `8443` | +| `didWebServer.env.didWebDbName` | Override database name for DID Web Server (DID_WEB_DB_NAME) | `did-web-server` | +| `didWebServer.env.didWebDomain` | Domain portion (URL-encoded) for did:web identifiers (DID_WEB_DOMAIN) | `""` | +| `didWebServer.env.didWebServiceEndpoint` | Explicit service endpoint for DID doc generation; empty => use veritable-cloudagent.defineEndpoint helper (DID_WEB_SERVICE_ENDPOINT) | `""` | +| `didWebServer.env.useDevCert` | Use development self-signed certificate inside container (DID_WEB_USE_DEV_CERT) | `false` | +| `didWebServer.env.devCertPath` | Path to development certificate inside container (DID_WEB_DEV_CERT_PATH) | `""` | +| `didWebServer.env.devKeyPath` | Path to development key inside container (DID_WEB_DEV_KEY_PATH) | `""` | +| `didWebServer.service.enabled` | Create a Service for the DID Web Server | `true` | +| `didWebServer.service.type` | Kubernetes Service type | `ClusterIP` | +| `didWebServer.service.port` | Service port to expose DID Web Server | `80` | +| `didWebServer.service.targetPort` | Target container port for DID Web Server traffic | `8443` | +| `didWebServer.service.annotations` | Additional annotations for DID Web Server service | `{}` | +| `didWebServer.service.labels` | Additional labels for DID Web Server service | `{}` | +| `didWebServer.ingress.enabled` | Create an Ingress for the DID Web Server | `false` | +| `didWebServer.ingress.className` | IngressClass name | `""` | +| `didWebServer.ingress.hostname` | Hostname for DID Web Server ingress | `""` | +| `didWebServer.ingress.path` | Base path for DID Web Server ingress | `/.well-known/did.json` | +| `didWebServer.ingress.pathType` | Ingress pathType | `ImplementationSpecific` | +| `didWebServer.ingress.tls` | TLS configuration entries for DID Web Server ingress | `[]` | +| `didWebServer.ingress.annotations` | Additional annotations for DID Web Server ingress | `{}` | +| `didWebServer.ingress.extraHosts` | Additional hosts for DID Web Server ingress | `[]` | +| `didWebServer.ingress.extraPaths` | Additional paths for primary host | `[]` | +| `didWebServer.ingress.extraTls` | Additional TLS entries | `[]` | +| `didWebServer.ingress.extraRules` | Additional raw ingress rules | `[]` | +| `didWebServer.extraEnv` | Additional map of extra environment variables to inject (merged as simple key/value) | `{}` | + ## Configuration and installation details ### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) diff --git a/charts/veritable-cloudagent/templates/didwebserver-ingress.yaml b/charts/veritable-cloudagent/templates/didwebserver-ingress.yaml new file mode 100644 index 000000000..89f394103 --- /dev/null +++ b/charts/veritable-cloudagent/templates/didwebserver-ingress.yaml @@ -0,0 +1,73 @@ +{{- if and .Values.didWebServer.enabled .Values.didWebServer.ingress.enabled }} +--- +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ include "common.names.fullname" . }}-didweb + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: did-web-server + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.didWebServer.ingress.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.didWebServer.ingress.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.didWebServer.ingress.annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +spec: + {{- if .Values.didWebServer.ingress.className }} + ingressClassName: {{ .Values.didWebServer.ingress.className | quote }} + {{- end }} + rules: + {{- if .Values.didWebServer.ingress.hostname }} + - host: {{ .Values.didWebServer.ingress.hostname | quote }} + http: + paths: + {{- $svcName := printf "%s-didweb" (include "common.names.fullname" $) }} + - path: {{ .Values.didWebServer.ingress.path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ .Values.didWebServer.ingress.pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" $svcName "servicePort" "http" "context" $) | nindent 14 }} + {{- if .Values.didWebServer.ingress.extraPaths }} + {{- toYaml .Values.didWebServer.ingress.extraPaths | nindent 10 }} + {{- end }} + {{- end }} + {{- range .Values.didWebServer.ingress.extraHosts }} + - host: {{ .name | quote }} + http: + paths: + {{- $svcName := printf "%s-didweb" (include "common.names.fullname" $) }} + {{- if $.Values.didWebServer.ingress.extraPaths }} + {{- toYaml $.Values.didWebServer.ingress.extraPaths | nindent 10 }} + {{- end }} + {{- range .paths }} + - path: {{ .path }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ default "ImplementationSpecific" .pathType }} + {{- end }} + backend: {{- include "common.ingress.backend" (dict "serviceName" $svcName "servicePort" "http" "context" $) | nindent 14 }} + {{- end }} + {{- end }} + {{- if .Values.didWebServer.ingress.extraRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.didWebServer.ingress.extraRules "context" $) | nindent 4 }} + {{- end }} + {{- if or .Values.didWebServer.ingress.tls .Values.didWebServer.ingress.extraTls }} + tls: + {{- range .Values.didWebServer.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- if .Values.didWebServer.ingress.extraTls }} + {{- include "common.tplvalues.render" (dict "value" .Values.didWebServer.ingress.extraTls "context" $) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/veritable-cloudagent/templates/didwebserver-svc.yaml b/charts/veritable-cloudagent/templates/didwebserver-svc.yaml new file mode 100644 index 000000000..0aee2feb4 --- /dev/null +++ b/charts/veritable-cloudagent/templates/didwebserver-svc.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.didWebServer.enabled .Values.didWebServer.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "common.names.fullname" . }}-didweb + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: did-web-server + {{- if .Values.didWebServer.service.labels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.didWebServer.service.labels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.didWebServer.service.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.didWebServer.service.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.didWebServer.service.annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +spec: + type: {{ .Values.didWebServer.service.type }} + selector: {{- include "common.labels.matchLabels" . | nindent 4 }} + app.kubernetes.io/component: veritable-cloudagent + ports: + - name: http + port: {{ .Values.didWebServer.service.port }} + targetPort: {{ .Values.didWebServer.service.targetPort }} + protocol: TCP +{{- end }} \ No newline at end of file diff --git a/charts/veritable-cloudagent/templates/statefulset.yaml b/charts/veritable-cloudagent/templates/statefulset.yaml index c4c7e8634..f33d3485b 100644 --- a/charts/veritable-cloudagent/templates/statefulset.yaml +++ b/charts/veritable-cloudagent/templates/statefulset.yaml @@ -67,7 +67,7 @@ spec: {{- if .Values.terminationGracePeriodSeconds }} terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} {{- end }} - {{- if or .Values.initContainers .Values.ipfs.initConfig (and (not .Values.postgresql.enabled) .Values.externalDatabase.create) }} + {{- if or .Values.initContainers .Values.ipfs.initConfig .Values.initDbMigrate.enabled (and (not .Values.postgresql.enabled) .Values.externalDatabase.create) }} initContainers: {{- if and (not .Values.postgresql.enabled) .Values.externalDatabase.create }} - name: database-create @@ -154,6 +154,31 @@ spec: value: {{ .Values.ipfs.initConfig.bootNodeAddress }} {{- end}} {{- end }} + {{- if .Values.initDbMigrate.enabled }} + - name: database-migrate + image: {{ template "veritable-cloudagent.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ['npx','knex'] + {{- if .Values.initDbMigrate.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.initDbMigrate.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: NODE_ENV + value: {{ .Values.initDbMigrate.environment | quote }} + - name: POSTGRES_HOST + value: {{ template "veritable-cloudagent.databaseHost" . }} + - name: POSTGRES_PORT + value: {{ template "veritable-cloudagent.databasePort" . }} + - name: POSTGRES_USERNAME + value: {{ template "veritable-cloudagent.databaseUser" . }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "veritable-cloudagent.databaseSecretName" . }} + key: {{ include "veritable-cloudagent.databaseSecretPasswordKey" . }} + - name: DID_WEB_DB_NAME + value: {{ .Values.didWebServer.env.didWebDbName | default "did-web-server" | quote }} + {{- end }} {{- if .Values.initContainers }} {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} {{- end }} @@ -256,6 +281,33 @@ spec: - name: VERIFIED_DRPC_OPTIONS_PROOF_REQUEST_OPTIONS value: {{ .Values.verifiedDrpcOptionsProofRequestOptions | quote }} {{- end }} + {{- if .Values.didWebServer.enabled }} + # TODO: Race condition exists where DID document generation occurs before didWebServer + # is fully started and pod/ingress are ready. The application may exit when it cannot + # lookup the DID document at the specified DID_WEB_DOMAIN address during startup. + - name: DID_WEB_ENABLED + value: "true" + - name: DID_WEB_PORT + value: {{ .Values.didWebServer.containerPort | quote }} + - name: DID_WEB_DB_NAME + value: {{ .Values.didWebServer.env.didWebDbName | quote }} + - name: DID_WEB_DOMAIN + value: {{ .Values.didWebServer.env.didWebDomain | quote }} + - name: DID_WEB_SERVICE_ENDPOINT + value: {{ (default (include "veritable-cloudagent.defineEndpoint" .) .Values.didWebServer.env.didWebServiceEndpoint) | quote }} + - name: DID_WEB_USE_DEV_CERT + value: {{ ternary "true" "false" .Values.didWebServer.env.useDevCert | quote }} + - name: DID_WEB_DEV_CERT_PATH + value: {{ .Values.didWebServer.env.devCertPath | quote }} + - name: DID_WEB_DEV_KEY_PATH + value: {{ .Values.didWebServer.env.devKeyPath | quote }} + {{- if .Values.didWebServer.extraEnv }} + {{- range $k, $v := .Values.didWebServer.extraEnv }} + - name: {{ $k }} + value: {{ $v | quote }} + {{- end }} + {{- end }} + {{- end }} {{- if .Values.extraEnvVars }} {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} {{- end }} @@ -278,6 +330,10 @@ spec: containerPort: {{ .Values.containerPorts.ws }} - name: admin containerPort: {{ .Values.containerPorts.admin }} + {{- if .Values.didWebServer.enabled }} + - name: http-didweb + containerPort: {{ .Values.didWebServer.containerPort }} + {{- end }} {{- if not .Values.diagnosticMode.enabled }} {{- if .Values.customLivenessProbe }} livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} diff --git a/charts/veritable-cloudagent/values.yaml b/charts/veritable-cloudagent/values.yaml index b6962e481..46ccb126f 100644 --- a/charts/veritable-cloudagent/values.yaml +++ b/charts/veritable-cloudagent/values.yaml @@ -1030,7 +1030,7 @@ postgresql: auth: username: veritable-cloudgent password: "" - database: wallet-id + database: "did-web-server" existingSecret: "" architecture: standalone image: @@ -1067,3 +1067,73 @@ externalDatabase: existingSecret: "" existingSecretPasswordKey: "" existingSecretPostgresPasswordKey: "" + +## @section Database Migration Init Container Parameters +## Run database migrations (Knex) for DID Web tables before the main container starts. +## @param initDbMigrate.enabled Run database migration in an init container +## @param initDbMigrate.environment NODE_ENV value used during migration +## @param initDbMigrate.args Arguments supplied to npx knex (array) +initDbMigrate: + enabled: true + environment: production + args: + - "migrate:latest" + +## @section DID Web Server Parameters +## didWebServer optional HTTP(S) server exposing did:web documents +## @param didWebServer.enabled Enable DID Web Server feature. When false, no related resources/env vars are rendered +## @param didWebServer.containerPort Container port the DID Web Server listens on (maps to DID_WEB_PORT) +## @param didWebServer.env.didWebDbName Override database name for DID Web Server (DID_WEB_DB_NAME) +## @param didWebServer.env.didWebDomain Domain portion (URL-encoded) for did:web identifiers (DID_WEB_DOMAIN) +## @param didWebServer.env.didWebServiceEndpoint Explicit service endpoint for DID doc generation; empty => use veritable-cloudagent.defineEndpoint helper (DID_WEB_SERVICE_ENDPOINT) +## @param didWebServer.env.useDevCert Use development self-signed certificate inside container (DID_WEB_USE_DEV_CERT) +## @param didWebServer.env.devCertPath Path to development certificate inside container (DID_WEB_DEV_CERT_PATH) +## @param didWebServer.env.devKeyPath Path to development key inside container (DID_WEB_DEV_KEY_PATH) +## @param didWebServer.service.enabled Create a Service for the DID Web Server +## @param didWebServer.service.type Kubernetes Service type +## @param didWebServer.service.port Service port to expose DID Web Server +## @param didWebServer.service.targetPort Target container port for DID Web Server traffic +## @param didWebServer.service.annotations Additional annotations for DID Web Server service +## @param didWebServer.service.labels Additional labels for DID Web Server service +## @param didWebServer.ingress.enabled Create an Ingress for the DID Web Server +## @param didWebServer.ingress.className IngressClass name +## @param didWebServer.ingress.hostname Hostname for DID Web Server ingress +## @param didWebServer.ingress.path Base path for DID Web Server ingress +## @param didWebServer.ingress.pathType Ingress pathType +## @param didWebServer.ingress.tls TLS configuration entries for DID Web Server ingress +## @param didWebServer.ingress.annotations Additional annotations for DID Web Server ingress +## @param didWebServer.ingress.extraHosts Additional hosts for DID Web Server ingress +## @param didWebServer.ingress.extraPaths Additional paths for primary host +## @param didWebServer.ingress.extraTls Additional TLS entries +## @param didWebServer.ingress.extraRules Additional raw ingress rules +## @param didWebServer.extraEnv Additional map of extra environment variables to inject (merged as simple key/value) +didWebServer: + enabled: false + containerPort: 8443 + env: + didWebDbName: "did-web-server" + didWebDomain: "" # URL-encoded domain (e.g. localhost%3A8443) + didWebServiceEndpoint: "" # e.g. http://:5002 + useDevCert: false + devCertPath: "" # e.g. alice.pem (dev only) + devKeyPath: "" # e.g. alice-key.pem (dev only) + service: + enabled: true + type: ClusterIP + port: 80 + targetPort: 8443 + annotations: {} + labels: {} + ingress: + enabled: false + className: "" + hostname: "" + path: /.well-known/did.json + pathType: ImplementationSpecific + tls: [] + annotations: {} + extraHosts: [] + extraPaths: [] + extraTls: [] + extraRules: [] + extraEnv: {}