Merge branch 'master' into nih-testing

* master:
  Update application.yaml
  Bumped version of Spring Boot in order to fix same issue as https://github.com/Haulmont/jmix-security/issues/90
  Upgraded to 5.6.0 Subscription tests fail ...
  Added OpenAPI / Swagger option
  simplified helm chart
  build ARM-compatible images
  bumped dependencies to latest
  only push build images to DockerHub
  Adds ability to change HAPI FHIR JPA server's port with the environment variable server.port
  Adds ability to control the number of executor threads through environment variables server.tomcat.max-threads and server.tomcat.min-spare-threads.  There is not a breaking change and does not affect the function of the JPA server unless these environment variables are set.
  Adds ability to use delete-expunge operations to the JPA Starter Server.

# Conflicts:
#	pom.xml
#	src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java
#	src/main/java/ca/uhn/fhir/jpa/starter/Application.java
#	src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java
#	src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java
#	src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java
#	src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java
#	src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java
#	src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java
This commit is contained in:
Michael Buckley
2021-12-09 14:53:03 -05:00
33 changed files with 680 additions and 366 deletions

View File

@@ -1,6 +1,5 @@
debug: true
remote: origin
lint-conf: .github/ct/lintconf.yaml
chart-yaml-schema: .github/ct/chart-schema.yaml
validate-maintainers: false
validate-chart-schema: true

View File

@@ -1,40 +0,0 @@
---
rules:
braces:
min-spaces-inside: 0
max-spaces-inside: 0
min-spaces-inside-empty: -1
max-spaces-inside-empty: -1
brackets:
min-spaces-inside: 0
max-spaces-inside: 0
min-spaces-inside-empty: -1
max-spaces-inside-empty: -1
colons:
max-spaces-before: 0
max-spaces-after: 1
commas:
max-spaces-before: 0
min-spaces-after: 1
max-spaces-after: 1
comments:
require-starting-space: true
min-spaces-from-content: 1
document-end: disable
document-start: disable
empty-lines:
max: 2
max-start: 0
max-end: 0
hyphens:
max-spaces-after: 1
indentation:
spaces: consistent
indent-sequences: whatever
check-multi-line-strings: false
key-duplicates: enable
line-length: disable
new-line-at-end-of-file: enable
trailing-spaces: enable
truthy:
level: warning

View File

@@ -4,8 +4,15 @@ on:
push:
tags:
- "image/v*"
paths-ignore:
- "charts/**"
pull_request:
branches: [master]
paths-ignore:
- "charts/**"
env:
IMAGES: docker.io/hapiproject/hapi
PLATFORMS: linux/amd64,linux/arm64/v8
jobs:
build:
@@ -14,41 +21,37 @@ jobs:
steps:
- name: Docker meta
id: docker_meta
uses: crazy-max/ghaction-docker-meta@v1
uses: docker/metadata-action@v3
with:
images: |
ghcr.io/hapifhir/hapi
docker.io/hapiproject/hapi
tag-sha: false
tag-match: "v(.*)"
# waiting for https://github.com/crazy-max/ghaction-docker-meta/issues/13 for a cleaner solution
images: ${{ env.IMAGES }}
tags: |
type=match,pattern=image-(.*),group=1,enable=${{github.event_name != 'pull_request'}}
type=sha
- name: Docker distroless meta
id: docker_distroless_meta
uses: crazy-max/ghaction-docker-meta@v1
uses: docker/metadata-action@v3
with:
images: |
ghcr.io/hapifhir/hapi
docker.io/hapiproject/hapi
tag-sha: false
tag-match: "v(.*)"
sep-tags: -distroless,
images: ${{ env.IMAGES }}
tags: |
type=match,pattern=image-(.*),group=1,enable=${{github.event_name != 'pull_request'}}
type=sha
flavor: |
suffix=-distroless,onlatest=true
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
if: github.event_name != 'pull_request'
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
if: github.event_name != 'pull_request'
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GHCR_TOKEN }}
- name: Cache Docker layers
uses: actions/cache@v2
with:
@@ -56,6 +59,7 @@ jobs:
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
@@ -65,6 +69,8 @@ jobs:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}
platforms: ${{ env.PLATFORMS }}
- name: Build and push distroless
id: docker_build_distroless
uses: docker/build-push-action@v2
@@ -72,10 +78,7 @@ jobs:
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.docker_distroless_meta.outputs.tags }}-distroless
tags: ${{ steps.docker_distroless_meta.outputs.tags }}
labels: ${{ steps.docker_distroless_meta.outputs.labels }}
platforms: ${{ env.PLATFORMS }}
target: release-distroless
- name: Print image digests
run: |
echo ${{ steps.docker_build.outputs.digest }}
echo ${{ steps.docker_build_distroless.outputs.digest }}

View File

@@ -15,21 +15,26 @@ jobs:
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Install Helm
uses: azure/setup-helm@v1
with:
version: v3.4.0
version: v3.7.0
- name: Add bitnami repo
run: helm repo add bitnami https://charts.bitnami.com/bitnami
- name: Update dependencies
run: find charts/ ! -path charts/ -maxdepth 1 -type d -exec helm dependency update {} \;
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.2.0
with:
config: .github/ct/ct.yaml
config: .github/ct/config.yaml
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

View File

@@ -10,18 +10,28 @@ on:
jobs:
lint:
runs-on: ubuntu-20.04
container: ghcr.io/chgl/kube-powertools:latest
container: quay.io/helmpack/chart-testing:v3.4.0
steps:
- name: Install helm-docs
working-directory: /tmp
env:
HELM_DOCS_URL: https://github.com/norwoodj/helm-docs/releases/download/v1.5.0/helm-docs_1.5.0_Linux_x86_64.tar.gz
run: |
curl -LSs $HELM_DOCS_URL | tar xz && \
mv ./helm-docs /usr/local/bin/helm-docs && \
chmod +x /usr/local/bin/helm-docs && \
helm-docs --version
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Update dependencies
run: find charts/ ! -path charts/ -maxdepth 1 -type d -exec helm dependency update {} \;
- name: Check if documentation is up-to-date
run: helm-docs && git diff --exit-code HEAD
- name: Run chart-testing (lint)
run: ct lint --config .github/ct/ct.yaml
- name: Run Powerlint
run: chart-powerlint.sh
run: ct lint --config .github/ct/config.yaml
test:
runs-on: ubuntu-20.04
@@ -32,24 +42,27 @@ jobs:
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Helm
uses: azure/setup-helm@v1
with:
version: v3.5.2
- uses: actions/setup-python@v2
with:
python-version: 3.9
version: v3.7.0
- name: Set up chart-testing
uses: helm/chart-testing-action@v2.0.1
uses: helm/chart-testing-action@v2.1.0
- name: Run chart-testing (list-changed)
id: list-changed
run: |
changed=$(ct list-changed)
changed=$(ct list-changed --config .github/ct/config.yaml)
if [[ -n "$changed" ]]; then
echo "::set-output name=changed::true"
fi
- name: Create k8s Kind Cluster
uses: helm/kind-action@v1.1.0
uses: helm/kind-action@v1.2.0
if: steps.list-changed.outputs.changed == 'true'
- name: Run chart-testing (install)
run: ct install --config .github/ct/ct.yaml
run: ct install --config .github/ct/config.yaml
if: steps.list-changed.outputs.changed == 'true'

View File

@@ -1,7 +1,8 @@
FROM maven:3.6.3-jdk-11-slim as build-hapi
FROM maven:3.8.2-jdk-11-slim as build-hapi
WORKDIR /tmp/hapi-fhir-jpaserver-starter
COPY pom.xml .
COPY server.xml .
RUN mvn -ntp dependency:go-offline
COPY src/ /tmp/hapi-fhir-jpaserver-starter/src/
@@ -12,9 +13,8 @@ RUN mvn package spring-boot:repackage -Pboot
RUN mkdir /app && \
cp /tmp/hapi-fhir-jpaserver-starter/target/ROOT.war /app/main.war
FROM gcr.io/distroless/java-debian10:11 AS release-distroless
FROM gcr.io/distroless/java-debian11:11 AS release-distroless
COPY --chown=nonroot:nonroot --from=build-distroless /app /app
EXPOSE 8080
# 65532 is the nonroot user's uid
# used here instead of the name to allow Kubernetes to easily detect that the container
# is running as a non-root (uid != 0) user.
@@ -22,11 +22,12 @@ USER 65532:65532
WORKDIR /app
CMD ["/app/main.war"]
FROM tomcat:9.0.38-jdk11-openjdk-slim-buster
FROM tomcat:9.0.53-jdk11-openjdk-slim-bullseye
RUN mkdir -p /data/hapi/lucenefiles && chmod 775 /data/hapi/lucenefiles
COPY --from=build-hapi /tmp/hapi-fhir-jpaserver-starter/target/*.war /usr/local/tomcat/webapps/
EXPOSE 8080
COPY catalina.properties /usr/local/tomcat/conf/catalina.properties
COPY server.xml /usr/local/tomcat/conf/server.xml
CMD ["catalina.sh", "run"]

209
catalina.properties Normal file
View File

@@ -0,0 +1,209 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# List of comma-separated packages that start with or equal this string
# will cause a security exception to be thrown when
# passed to checkPackageAccess unless the
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
package.access=sun.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.tomcat.
#
# List of comma-separated packages that start with or equal this string
# will cause a security exception to be thrown when
# passed to checkPackageDefinition unless the
# corresponding RuntimePermission ("defineClassInPackage."+package) has
# been granted.
#
# by default, no packages are restricted for definition, and none of
# the class loaders supplied with the JDK call checkPackageDefinition.
#
package.definition=sun.,java.,org.apache.catalina.,org.apache.coyote.,\
org.apache.jasper.,org.apache.naming.,org.apache.tomcat.
#
#
# List of comma-separated paths defining the contents of the "common"
# classloader. Prefixes should be used to define what is the repository type.
# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
# If left as blank,the JVM system loader will be used as Catalina's "common"
# loader.
# Examples:
# "foo": Add this folder as a class repository
# "foo/*.jar": Add all the JARs of the specified folder as class
# repositories
# "foo/bar.jar": Add bar.jar as a class repository
#
# Note: Values are enclosed in double quotes ("...") in case either the
# ${catalina.base} path or the ${catalina.home} path contains a comma.
# Because double quotes are used for quoting, the double quote character
# may not appear in a path.
common.loader="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
#
# List of comma-separated paths defining the contents of the "server"
# classloader. Prefixes should be used to define what is the repository type.
# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
# If left as blank, the "common" loader will be used as Catalina's "server"
# loader.
# Examples:
# "foo": Add this folder as a class repository
# "foo/*.jar": Add all the JARs of the specified folder as class
# repositories
# "foo/bar.jar": Add bar.jar as a class repository
#
# Note: Values may be enclosed in double quotes ("...") in case either the
# ${catalina.base} path or the ${catalina.home} path contains a comma.
# Because double quotes are used for quoting, the double quote character
# may not appear in a path.
server.loader=
#
# List of comma-separated paths defining the contents of the "shared"
# classloader. Prefixes should be used to define what is the repository type.
# Path may be relative to the CATALINA_BASE path or absolute. If left as blank,
# the "common" loader will be used as Catalina's "shared" loader.
# Examples:
# "foo": Add this folder as a class repository
# "foo/*.jar": Add all the JARs of the specified folder as class
# repositories
# "foo/bar.jar": Add bar.jar as a class repository
# Please note that for single jars, e.g. bar.jar, you need the URL form
# starting with file:.
#
# Note: Values may be enclosed in double quotes ("...") in case either the
# ${catalina.base} path or the ${catalina.home} path contains a comma.
# Because double quotes are used for quoting, the double quote character
# may not appear in a path.
shared.loader=
# Default list of JAR files that should not be scanned using the JarScanner
# functionality. This is typically used to scan JARs for configuration
# information. JARs that do not contain such information may be excluded from
# the scan to speed up the scanning process. This is the default list. JARs on
# this list are excluded from all scans. The list must be a comma separated list
# of JAR file names.
# The list of JARs to skip may be over-ridden at a Context level for individual
# scan types by configuring a JarScanner with a nested JarScanFilter.
# The JARs listed below include:
# - Tomcat Bootstrap JARs
# - Tomcat API JARs
# - Catalina JARs
# - Jasper JARs
# - Tomcat JARs
# - Common non-Tomcat JARs
# - Test JARs (JUnit, Cobertura and dependencies)
tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\
annotations-api.jar,\
ant-junit*.jar,\
ant-launcher.jar,\
ant.jar,\
asm-*.jar,\
aspectj*.jar,\
bootstrap.jar,\
catalina-ant.jar,\
catalina-ha.jar,\
catalina-ssi.jar,\
catalina-storeconfig.jar,\
catalina-tribes.jar,\
catalina.jar,\
cglib-*.jar,\
cobertura-*.jar,\
commons-beanutils*.jar,\
commons-codec*.jar,\
commons-collections*.jar,\
commons-daemon.jar,\
commons-dbcp*.jar,\
commons-digester*.jar,\
commons-fileupload*.jar,\
commons-httpclient*.jar,\
commons-io*.jar,\
commons-lang*.jar,\
commons-logging*.jar,\
commons-math*.jar,\
commons-pool*.jar,\
dom4j-*.jar,\
easymock-*.jar,\
ecj-*.jar,\
el-api.jar,\
geronimo-spec-jaxrpc*.jar,\
h2*.jar,\
hamcrest-*.jar,\
hibernate*.jar,\
httpclient*.jar,\
icu4j-*.jar,\
jasper-el.jar,\
jasper.jar,\
jaspic-api.jar,\
jaxb-*.jar,\
jaxen-*.jar,\
jdom-*.jar,\
jetty-*.jar,\
jmx-tools.jar,\
jmx.jar,\
jsp-api.jar,\
jstl.jar,\
jta*.jar,\
junit-*.jar,\
junit.jar,\
log4j*.jar,\
mail*.jar,\
objenesis-*.jar,\
oraclepki.jar,\
oro-*.jar,\
servlet-api-*.jar,\
servlet-api.jar,\
slf4j*.jar,\
taglibs-standard-spec-*.jar,\
tagsoup-*.jar,\
tomcat-api.jar,\
tomcat-coyote.jar,\
tomcat-dbcp.jar,\
tomcat-i18n-*.jar,\
tomcat-jdbc.jar,\
tomcat-jni.jar,\
tomcat-juli-adapters.jar,\
tomcat-juli.jar,\
tomcat-util-scan.jar,\
tomcat-util.jar,\
tomcat-websocket.jar,\
tools.jar,\
websocket-api.jar,\
wsdl4j*.jar,\
xercesImpl.jar,\
xml-apis.jar,\
xmlParserAPIs-*.jar,\
xmlParserAPIs.jar,\
xom-*.jar
# Default list of JAR files that should be scanned that overrides the default
# jarsToSkip list above. This is typically used to include a specific JAR that
# has been excluded by a broad file name pattern in the jarsToSkip list.
# The list of JARs to scan may be over-ridden at a Context level for individual
# scan types by configuring a JarScanner with a nested JarScanFilter.
tomcat.util.scan.StandardJarScanFilter.jarsToScan=\
log4j-taglib*.jar,\
log4j-web*.jar,\
log4javascript*.jar,\
slf4j-taglib*.jar
# String cache configuration.
tomcat.util.buf.StringCache.byte.enabled=true
#tomcat.util.buf.StringCache.char.enabled=true
#tomcat.util.buf.StringCache.trainThreshold=500000
#tomcat.util.buf.StringCache.cacheSize=5000
org.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.Digester$EnvironmentPropertySource
server.port=8080

View File

@@ -1,41 +0,0 @@
# Charts
> A collection of Helm charts
```sh
helm repo add hapifhir https://hapifhir.github.io/charts
helm repo update
```
## Development
1. Make changes to the charts
1. Mount the folder in the [kube-powertools](https://github.com/chgl/kube-powertools) container to easily run linters and checks
```sh
docker run --rm -it -v $PWD:/usr/src/app ghcr.io/chgl/kube-powertools:latest
```
1. Run chart-testing and the `chart-powerlint.sh` script to lint the chart
```sh
ct lint --config .github/ct/ct.yaml && chart-powerlint.sh
```
1. (Optional) View the results of the [polaris audit check](https://github.com/FairwindsOps/polaris) in your browser
```sh
$ docker run --rm -it -p 9090:8080 -v $PWD:/usr/src/app ghcr.io/chgl/kube-powertools:latest
bash-5.0: helm template charts/fhir-server/ | polaris dashboard --audit-path -
```
You can now open your browser at <http://localhost:9090> and see the results and recommendations.
1. Run `generate-docs.sh` to auto-generate an updated README
```sh
generate-docs.sh
```
1. Bump the version in the changed Chart.yaml according to SemVer (The `ct lint` step above will complain if you forget to update the version.)

View File

@@ -1,6 +1,6 @@
dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 10.3.16
digest: sha256:a45816f0855c6d4b1d66384ac36db99e0378f24663d02791006f815ff9d49245
generated: "2021-04-09T15:11:17.790703505Z"
version: 10.12.2
digest: sha256:38ee315eae1af3e3f6eb20e1dd8ffd60d4ab7ee0c51bf26941b56c8bcb376c11
generated: "2021-10-07T00:19:18.9743522+02:00"

View File

@@ -7,7 +7,17 @@ sources:
- https://github.com/hapifhir/hapi-fhir-jpaserver-starter
dependencies:
- name: postgresql
version: 10.3.16
version: 10.12.2
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled
version: 0.2.0
annotations:
artifacthub.io/license: Apache-2.0
artifacthub.io/prerelease: "true"
artifacthub.io/changes: |
# When using the list of objects option the valid supported kinds are
# added, changed, deprecated, removed, fixed, and security.
- kind: changed
description: |
updated HAPI FHIR starter image to 5.5.1
appVersion: v5.5.1
version: 0.6.0

View File

@@ -1,101 +1,74 @@
# hapi-fhir-jpaserver
# HAPI FHIR JPA Server Starter Helm Chart
[HAPI FHIR JPA Server](https://github.com/hapifhir/hapi-fhir-jpaserver-starter) - Helm chart for deploying the HAPI FHIR JPA starter server
![Version: 0.6.0](https://img.shields.io/badge/Version-0.6.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v5.5.1](https://img.shields.io/badge/AppVersion-v5.5.1-informational?style=flat-square)
## TL;DR;
This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment.
```console
$ helm repo add hapifhir https://hapifhir.github.io/hapi-fhir-jpaserver-starter
$ helm repo update
$ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver -n fhir
## Sample usage
```sh
helm repo add hapifhir https://hapifhir.github.io/hapi-fhir-jpaserver-starter/
helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver
```
## Introduction
## Values
This chart deploys the HAPI FHIR JPA starter server. on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| affinity | object | `{}` | pod affinity |
| deploymentAnnotations | object | `{}` | annotations applied to the server deployment |
| externalDatabase.database | string | `"fhir"` | database name |
| externalDatabase.existingSecret | string | `""` | name of an existing secret resource containing the DB password in the `existingSecretKey` key |
| externalDatabase.existingSecretKey | string | `"postgresql-password"` | name of the key inside the `existingSecret` |
| externalDatabase.host | string | `"localhost"` | external database host used with `postgresql.enabled=false` |
| externalDatabase.password | string | `""` | database password |
| externalDatabase.port | int | `5432` | database port number |
| externalDatabase.user | string | `"fhir"` | username for the external database |
| fullnameOverride | string | `""` | override the chart fullname |
| image.flavor | string | `"distroless"` | the flavor or variant of the image to use. appended to the image tag by `-`. |
| image.pullPolicy | string | `"IfNotPresent"` | |
| image.registry | string | `"docker.io"` | |
| image.repository | string | `"hapiproject/hapi"` | |
| image.tag | string | `""` | defaults to `Chart.appVersion` |
| imagePullSecrets | list | `[]` | image pull secrets to use when pulling the image |
| ingress.annotations | object | `{}` | provide any additional annotations which may be required. Evaluated as a template. |
| ingress.enabled | bool | `false` | whether to create an Ingress to expose the FHIR server HTTP endpoint |
| ingress.hosts[0].host | string | `"fhir-server.127.0.0.1.nip.io"` | |
| ingress.hosts[0].pathType | string | `"ImplementationSpecific"` | |
| ingress.hosts[0].paths[0] | string | `"/"` | |
| ingress.tls | list | `[]` | ingress TLS config |
| nameOverride | string | `""` | override the chart name |
| networkPolicy.allowedFrom | list | `[]` | Additional allowed NetworkPolicyPeer specs Evaluated as a template so you could do: Example: allowedFrom: - podSelector: matchLabels: app.kubernetes.io/name: {{ $.Release.Name }} |
| networkPolicy.enabled | bool | `false` | enable NetworkPolicy |
| networkPolicy.explicitNamespacesSelector | object | `{}` | a Kubernetes LabelSelector to explicitly select namespaces from which ingress traffic could be allowed |
| nodeSelector | object | `{}` | node selector for the pod |
| podAnnotations | object | `{}` | annotations applied to the server pod |
| podSecurityContext | object | `{}` | pod security context |
| postgresql.containerSecurityContext.allowPrivilegeEscalation | bool | `false` | |
| postgresql.containerSecurityContext.capabilities.drop[0] | string | `"ALL"` | |
| postgresql.enabled | bool | `true` | enable an included PostgreSQL DB. see <https://github.com/bitnami/charts/tree/master/bitnami/postgresql> for details if set to `false`, the values under `externalDatabase` are used |
| postgresql.existingSecret | string | `""` | Name of existing secret to use for PostgreSQL passwords. The secret has to contain the keys `postgresql-password` which is the password for `postgresqlUsername` when it is different of `postgres`, `postgresql-postgres-password` which will override `postgresqlPassword`, `postgresql-replication-password` which will override `replication.password` and `postgresql-ldap-password` which will be sed to authenticate on LDAP. The value is evaluated as a template. |
| postgresql.postgresqlDatabase | string | `"fhir"` | name of the database to create see: <https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-on-first-run> |
| readinessProbe.failureThreshold | int | `5` | |
| readinessProbe.initialDelaySeconds | int | `30` | |
| readinessProbe.periodSeconds | int | `20` | |
| readinessProbe.successThreshold | int | `1` | |
| readinessProbe.timeoutSeconds | int | `20` | |
| replicaCount | int | `1` | number of replicas to deploy |
| resources | object | `{}` | configure the FHIR server's resource requests and limits |
| securityContext.allowPrivilegeEscalation | bool | `false` | |
| securityContext.capabilities.drop[0] | string | `"ALL"` | |
| securityContext.readOnlyRootFilesystem | bool | `true` | |
| securityContext.runAsNonRoot | bool | `true` | |
| securityContext.runAsUser | int | `65532` | |
| service.port | int | `8080` | |
| service.type | string | `"ClusterIP"` | |
| startupProbe.failureThreshold | int | `10` | |
| startupProbe.initialDelaySeconds | int | `60` | |
| startupProbe.periodSeconds | int | `30` | |
| startupProbe.successThreshold | int | `1` | |
| startupProbe.timeoutSeconds | int | `30` | |
| tolerations | list | `[]` | pod tolerations |
## Prerequisites
- Kubernetes v1.18+
- Helm v3
## Installing the Chart
To install the chart with the release name `hapi-fhir-jpaserver`:
```console
$ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver -n fhir
```
The command deploys the HAPI FHIR JPA starter server. on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.
> **Tip**: List all releases using `helm list`
## Uninstalling the Chart
To uninstall/delete the `hapi-fhir-jpaserver`:
```console
$ helm delete hapi-fhir-jpaserver -n fhir
```
The command removes all the Kubernetes components associated with the chart and deletes the release.
## Configuration
The following table lists the configurable parameters of the `hapi-fhir-jpaserver` chart and their default values.
| Parameter | Description | Default |
| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| replicaCount | | `1` |
| imagePullSecrets | image pull secrets | `[]` |
| nameOverride | | `""` |
| fullnameOverride | | `""` |
| deploymentAnnotations | annotations applied to the server deployment | `{}` |
| podAnnotations | annotations applied to the server pod | `{}` |
| podSecurityContext | PodSecurityContext applied to the pod | `{}` |
| service.type | | `ClusterIP |
| | | # service port` |
| service.port | | `8080` |
| ingress.enabled | | `false |
| | | # provide any additional annotations which may be required. Evaluated as a template.` |
| ingress.annotations | | `{}` |
| ingress.tls | | `[]` |
| resources | resource requests and limits | `{}` |
| nodeSelector | choice for the user. This also increases chances charts run on environments with little resources, such as Minikube. If you do want to specify resources, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'resources:'. limits: cpu: 100m memory: 128Mi requests: cpu: 100m memory: 128Mi node labels for pods assignment see: <https://kubernetes.io/docs/user-guide/node-selection/> | `{}` |
| tolerations | tolerations for pods assignment see: <https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/> | `[]` |
| affinity | affinity for pods assignment see: <https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity> | `{}` |
| postgresql.enabled | if set to `false`, the values under `webApi.db` are used | `true |
| | | # update the default Postgres version to 13.2` |
| postgresql.image | | `{"tag":"13.2.0"}` |
| postgresql.postgresqlDatabase | see: <https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-on-first-run> | `"fhir"` |
| postgresql.existingSecret | The secret has to contain the keys `postgresql-password` which is the password for `postgresqlUsername` when it is different of `postgres`, `postgresql-postgres-password` which will override `postgresqlPassword`, `postgresql-replication-password` which will override `replication.password` and `postgresql-ldap-password` which will be sed to authenticate on LDAP. The value is evaluated as a template. | `""` |
| postgresql.replication.enabled | | `false |
| | | # number of read replicas` |
| postgresql.replication.readReplicas | | `2` |
| postgresql.replication.synchronousCommit | | `"on"` |
| postgresql.replication.numSynchronousReplicas | | `1` |
| postgresql.metrics.enabled | | `false` |
| postgresql.metrics.serviceMonitor.enabled | | `false |
| | | # the labels used for Prometheus autodiscover, e.g. could be `release: prometheus`` |
| postgresql.metrics.serviceMonitor.additionalLabels | | `{}` |
| externalDatabase.host | | `localhost |
| | | # non-root Username for FHIR Database` |
| externalDatabase.user | | `fhir` |
| externalDatabase.password | | `""` |
| externalDatabase.existingSecret | | `""` |
| externalDatabase.database | | `fhir` |
| externalDatabase.port | | `5432` |
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example:
```console
$ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver -n fhir --set replicaCount=1
```
Alternatively, a YAML file that specifies the values for the parameters can be provided while
installing the chart. For example:
```console
$ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver -n fhir --values values.yaml
```
----------------------------------------------
Autogenerated from chart metadata using [helm-docs v1.5.0](https://github.com/norwoodj/helm-docs/releases/v1.5.0)

View File

@@ -0,0 +1,16 @@
# HAPI FHIR JPA Server Starter Helm Chart
{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }}
This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment.
## Sample usage
```sh
helm repo add hapifhir https://hapifhir.github.io/hapi-fhir-jpaserver-starter/
helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver
```
{{ template "chart.valuesSection" . }}
{{ template "helm-docs.versionFooter" . }}

View File

@@ -1,19 +0,0 @@
project:
name: HAPI FHIR JPA Server
shortName: hapi-fhir-jpaserver
url: https://github.com/hapifhir/hapi-fhir-jpaserver-starter
description: Helm chart for deploying the HAPI FHIR JPA starter server
app: the HAPI FHIR JPA starter server.
repository:
url: https://hapifhir.github.io/hapi-fhir-jpaserver-starter
name: hapifhir
chart:
name: hapi-fhir-jpaserver
values: "-- generate from values file --"
valuesExample: "-- generate from values file --"
prerequisites:
- "Kubernetes v1.18+"
- "Helm v3"
release:
name: hapi-fhir-jpaserver
namespace: fhir

View File

@@ -30,6 +30,18 @@ Create chart name and version as used by the chart label.
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create image tag
*/}}
{{- define "hapi-fhir-jpaserver.imageTag" -}}
{{- $version := default .Chart.AppVersion .Values.image.tag -}}
{{- if .Values.image.flavor }}
{{- printf "%s-%s" $version .Values.image.flavor }}
{{- else }}
{{- printf "%s" $version }}
{{- end }}
{{- end }}
{{/*
Common labels
*/}}
@@ -60,7 +72,7 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
{{- end -}}
{{/*
Get the Postgresql credentials secret.
Get the Postgresql credentials secret name.
*/}}
{{- define "hapi-fhir-jpaserver.postgresql.secretName" -}}
{{- if and (.Values.postgresql.enabled) (not .Values.postgresql.existingSecret) -}}
@@ -71,11 +83,22 @@ Get the Postgresql credentials secret.
{{- if .Values.externalDatabase.existingSecret -}}
{{- printf "%s" .Values.externalDatabase.existingSecret -}}
{{- else -}}
{{ printf "%s-%s" .Release.Name "externaldb" }}
{{ printf "%s-%s" (include "hapi-fhir-jpaserver.fullname" .) "external-db" }}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Get the Postgresql credentials secret key.
*/}}
{{- define "hapi-fhir-jpaserver.postgresql.secretKey" -}}
{{- if (.Values.externalDatabase.existingSecret) -}}
{{- printf "%s" .Values.externalDatabase.existingSecretKey -}}
{{- else }}
{{- printf "postgresql-password" -}}
{{- end -}}
{{- end -}}
{{/*
Add environment variables to configure database values
*/}}
@@ -87,7 +110,7 @@ Add environment variables to configure database values
Add environment variables to configure database values
*/}}
{{- define "hapi-fhir-jpaserver.database.user" -}}
{{- ternary .Values.postgresql.postgresqlUsername .Values.externalDatabase.user .Values.postgresql.enabled | quote -}}
{{- ternary .Values.postgresql.postgresqlUsername .Values.externalDatabase.user .Values.postgresql.enabled -}}
{{- end -}}
{{/*
@@ -111,5 +134,6 @@ Create the JDBC URL from the host, port and database name.
{{- $host := (include "hapi-fhir-jpaserver.database.host" .) -}}
{{- $port := (include "hapi-fhir-jpaserver.database.port" .) -}}
{{- $name := (include "hapi-fhir-jpaserver.database.name" .) -}}
{{ printf "jdbc:postgresql://%s:%d/%s" $host (int $port) $name }}
{{- $appName := .Release.Name -}}
{{ printf "jdbc:postgresql://%s:%d/%s?ApplicationName=%s" $host (int $port) $name $appName }}
{{- end -}}

View File

@@ -28,10 +28,9 @@ spec:
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
{{- if .Values.postgresql.enabled }}
initContainers:
- name: wait-for-db
image: busybox:1.32
- name: wait-for-db-to-be-ready
image: "{{ .Values.postgresql.image.registry }}/{{ .Values.postgresql.image.repository }}:{{ .Values.postgresql.image.tag }}"
imagePullPolicy: IfNotPresent
securityContext:
allowPrivilegeEscalation: false
@@ -41,15 +40,27 @@ spec:
drop:
- ALL
runAsNonRoot: true
runAsUser: 11111
runAsGroup: 11111
command: ["sh", "-c", "while ! nc -z {{ .Release.Name }}-postgresql 5432 -w 5; do echo $(date) waiting for database; sleep 5; done;"]
{{- end }}
runAsUser: 1001
runAsGroup: 1001
env:
- name: PGHOST
value: "{{ include "hapi-fhir-jpaserver.database.host" . }}"
- name: PGPORT
value: "{{ include "hapi-fhir-jpaserver.database.port" . }}"
- name: PGUSER
value: "{{ include "hapi-fhir-jpaserver.database.user" . }}"
command: ["/bin/sh", "-c"]
args:
- |
until pg_isready; do
echo "Waiting for DB ${PGUSER}@${PGHOST}:${PGPORT} to be up";
sleep 15;
done;
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}"
image: {{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ include "hapi-fhir-jpaserver.imageTag" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
@@ -68,7 +79,7 @@ spec:
{{- end }}
startupProbe:
httpGet:
path: /fhir/Patient?_count=1
path: /fhir/metadata
port: http
{{- with .Values.startupProbe }}
initialDelaySeconds: {{ .initialDelaySeconds }}
@@ -88,7 +99,7 @@ spec:
valueFrom:
secretKeyRef:
name: {{ include "hapi-fhir-jpaserver.postgresql.secretName" . }}
key: postgresql-password
key: {{ include "hapi-fhir-jpaserver.postgresql.secretKey" . }}
- name: SPRING_DATASOURCE_DRIVERCLASSNAME
value: org.postgresql.Driver
- name: SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT

View File

@@ -2,7 +2,7 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ printf "%s-%s" .Release.Name "externaldb" }}
name: {{ include "hapi-fhir-jpaserver.fullname" . }}-external-db
labels:
{{- include "hapi-fhir-jpaserver.labels" . | nindent 4 }}
type: Opaque

View File

@@ -1,6 +1,5 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "hapi-fhir-jpaserver.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion }}
@@ -44,10 +43,10 @@ spec:
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
name: http
{{ else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
servicePort: http
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,27 @@
{{- if .Values.networkPolicy.enabled }}
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: {{ include "hapi-fhir-jpaserver.fullname" . }}
labels:
{{- include "hapi-fhir-jpaserver.labels" . | nindent 4 }}
spec:
podSelector:
matchLabels:
{{- include "hapi-fhir-jpaserver.selectorLabels" . | nindent 6 }}
ingress:
# Allow inbound connections from pods with the "hapi-fhir-jpaserver-client: true" label
- ports:
- port: http
from:
- podSelector:
matchLabels:
{{ include "hapi-fhir-jpaserver.fullname" . }}-client: "true"
{{- with .Values.networkPolicy.explicitNamespacesSelector }}
namespaceSelector:
{{ toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.networkPolicy.allowedFrom }}
{{ tpl (toYaml .) $ | nindent 8 }}
{{- end }}
{{- end }}

View File

@@ -4,6 +4,7 @@ metadata:
name: "{{ include "hapi-fhir-jpaserver.fullname" . }}-test-connection"
labels:
{{- include "hapi-fhir-jpaserver.labels" . | nindent 4 }}
{{ include "hapi-fhir-jpaserver.fullname" . }}-client: "true"
annotations:
"helm.sh/hook": test
spec:
@@ -11,7 +12,6 @@ spec:
containers:
- name: wget
image: busybox:1
imagePullPolicy: Always
command: ['wget', '-O', '-']
args: ['http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/Patient?_count=1']
securityContext:

View File

@@ -1,33 +1,37 @@
# Default values for hapi-fhir-jpaserver.
# This is a YAML-formatted file.
# number of replicas
# -- number of replicas to deploy
replicaCount: 1
image: # +doc-gen:ignore
registry: ghcr.io
repository: chgl/hapifhir/hapi-fhir-jpaserver-starter
tag: v5.3.0-distroless
image:
registry: docker.io
repository: hapiproject/hapi
# -- defaults to `Chart.appVersion`
tag: ""
# -- the flavor or variant of the image to use.
# appended to the image tag by `-`.
flavor: "distroless"
pullPolicy: IfNotPresent
# image pull secrets
# -- image pull secrets to use when pulling the image
imagePullSecrets: []
# -- override the chart name
nameOverride: ""
# -- override the chart fullname
fullnameOverride: ""
# annotations applied to the server deployment
# -- annotations applied to the server deployment
deploymentAnnotations: {}
# annotations applied to the server pod
# -- annotations applied to the server pod
podAnnotations: {}
# PodSecurityContext applied to the pod
# -- pod security context
podSecurityContext:
{}
# fsGroup: 2000
# ContainerSecurityContext applied to the container
securityContext: # +doc-gen:ignore
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
@@ -36,31 +40,30 @@ securityContext: # +doc-gen:ignore
runAsNonRoot: true
runAsUser: 65532
# service to expose the server
service:
# type of service to expose the server
type: ClusterIP
# service port
port: 8080
ingress:
# whether to create an Ingress to expose the FHIR server web interface
# -- whether to create an Ingress to expose the FHIR server HTTP endpoint
enabled: false
# provide any additional annotations which may be required. Evaluated as a template.
# -- provide any additional annotations which may be required. Evaluated as a template.
annotations:
{}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: fhir-server.127.0.0.1.xip.io
- host: fhir-server.127.0.0.1.nip.io
pathType: ImplementationSpecific
paths: ["/"]
# ingress TLS config
# -- ingress TLS config
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
# resource requests and limits
# -- configure the FHIR server's resource requests and limits
resources:
{}
# We usually recommend not to specify default resources and to leave this as a conscious
@@ -74,30 +77,24 @@ resources:
# cpu: 100m
# memory: 128Mi
# node labels for pods assignment
# see: <https://kubernetes.io/docs/user-guide/node-selection/>
# -- node selector for the pod
nodeSelector: {}
# tolerations for pods assignment
# see: <https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/>
# -- pod tolerations
tolerations: []
# affinity for pods assignment
# see: <https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity>
# -- pod affinity
affinity: {}
# see <https://github.com/bitnami/charts/tree/master/bitnami/postgresql> for details
postgresql:
# enable an included PostgreSQL DB.
# if set to `false`, the values under `webApi.db` are used
# -- enable an included PostgreSQL DB.
# see <https://github.com/bitnami/charts/tree/master/bitnami/postgresql> for details
# if set to `false`, the values under `externalDatabase` are used
enabled: true
# update the default Postgres version to 13.2
image: # +doc-gen:break
tag: 13.2.0
# name of the database to create
# -- name of the database to create
# see: <https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-on-first-run>
postgresqlDatabase: "fhir"
# Name of existing secret to use for PostgreSQL passwords.
# -- Name of existing secret to use for PostgreSQL passwords.
# The secret has to contain the keys `postgresql-password`
# which is the password for `postgresqlUsername` when it is
# different of `postgres`, `postgresql-postgres-password` which
@@ -105,55 +102,58 @@ postgresql:
# which will override `replication.password` and `postgresql-ldap-password`
# which will be sed to authenticate on LDAP. The value is evaluated as a template.
existingSecret: ""
replication:
# should be true for production use
enabled: false
# number of read replicas
readReplicas: 2
# set synchronous commit mode: on, off, remote_apply, remote_write and local
synchronousCommit: "on"
# from the number of `readReplicas` defined above, set the number of those that will have synchronous replication
numSynchronousReplicas: 1
metrics:
# should also be true for production use
enabled: false
serviceMonitor:
# create a Prometheus Operator ServiceMonitor resource
enabled: false
# the labels used for Prometheus autodiscover, e.g. could be `release: prometheus`
additionalLabels: {}
containerSecurityContext: # +doc-gen:ignore
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
# readiness probe
readinessProbe: # +doc-gen:ignore
readinessProbe:
failureThreshold: 5
initialDelaySeconds: 30
periodSeconds: 20
successThreshold: 1
timeoutSeconds: 20
# startup probe
startupProbe: # +doc-gen:ignore
startupProbe:
failureThreshold: 10
initialDelaySeconds: 60
periodSeconds: 30
successThreshold: 1
timeoutSeconds: 30
# only used if `postgresql.enabeld=false`
externalDatabase:
# Database host
# -- external database host used with `postgresql.enabled=false`
host: localhost
# non-root Username for FHIR Database
user: fhir
# Database password
password: ""
# Name of an existing secret resource containing the DB password in a 'postgresql-password' key
existingSecret: ""
# Database name
database: fhir
# Database port number
# -- database port number
port: 5432
# -- username for the external database
user: fhir
# -- database password
password: ""
# -- name of an existing secret resource containing the DB password in the `existingSecretKey` key
existingSecret: ""
# -- name of the key inside the `existingSecret`
existingSecretKey: "postgresql-password"
# -- database name
database: fhir
networkPolicy:
# -- enable NetworkPolicy
enabled: false
# -- a Kubernetes LabelSelector to explicitly select namespaces from which ingress traffic could be allowed
explicitNamespacesSelector:
{}
# matchLabels:
# team: one
# test: foo
# -- Additional allowed NetworkPolicyPeer specs
# Evaluated as a template so you could do:
#
# Example:
# allowedFrom:
# - podSelector:
# matchLabels:
# app.kubernetes.io/name: {{ $.Release.Name }}
allowedFrom: []

View File

@@ -14,13 +14,14 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>5.6.0-PRE7_NIH-SNAPSHOT</version>
<version>5.6.0</version>
</parent>
<artifactId>hapi-fhir-jpaserver-starter</artifactId>
<properties>
<java.version>8</java.version>
<spring_boot_version>2.5.6</spring_boot_version>
</properties>
<prerequisites>
@@ -118,6 +119,12 @@
<artifactId>hapi-fhir-jpaserver-mdm</artifactId>
<version>${project.version}</version>
</dependency>
<!-- This dependency includes the OpenAPI Server -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-server-openapi</artifactId>
<version>${project.version}</version>
</dependency>
<!-- This dependency is used for the "FHIR Tester" web app overlay -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>

76
server.xml Normal file
View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Note: A "Server" is not itself a "Container", so you may not
define subcomponents such as "Valves" at this level.
Documentation at /docs/config/server.html
-->
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<!--APR library loader. Documentation at /docs/apr.html -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources
Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- A "Service" is a collection of one or more "Connectors" that share
a single "Container" Note: A "Service" is not itself a "Container",
so you may not define subcomponents such as "Valves" at this level.
Documentation at /docs/config/service.html
-->
<Service name="Catalina">
<!-- A "Connector" represents an endpoint by which requests are received
and responses are returned. Documentation at :
Java HTTP Connector: /docs/config/http.html
Java AJP Connector: /docs/config/ajp.html
APR (HTTP/AJP) Connector: /docs/apr.html
Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
-->
<Connector port="${server.port}" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="${server.tomcat.max-threads}"
minSpareThreads="${server.tomcat.min-spare-threads}" />
<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
-->
<Engine name="Catalina" defaultHost="localhost">
<!-- Use the LockOutRealm to prevent attempts to guess user passwords
via a brute-force attack -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>

View File

@@ -19,6 +19,7 @@ import java.util.*;
public class AppProperties {
private Boolean cql_enabled = false;
private Boolean openapi_enabled = false;
private Boolean mdm_enabled = false;
private boolean advanced_lucene_indexing = false;
private Boolean allow_cascading_deletes = false;
@@ -27,6 +28,7 @@ public class AppProperties {
private Boolean allow_multiple_delete = false;
private Boolean allow_override_default_search_params = true;
private Boolean auto_create_placeholder_reference_targets = false;
private Boolean delete_expunge_enabled = false;
private Boolean enable_index_missing_fields = false;
private Boolean enable_index_contained_resource = false;
private Boolean enable_repository_validating_interceptor = false;
@@ -76,6 +78,14 @@ public class AppProperties {
private Integer bundle_batch_pool_max_size = 100;
private List<String> local_base_urls = new ArrayList<>();
public Boolean getOpenapi_enabled() {
return openapi_enabled;
}
public void setOpenapi_enabled(Boolean openapi_enabled) {
this.openapi_enabled = openapi_enabled;
}
public Boolean getUse_apache_address_strategy() {
return use_apache_address_strategy;
}
@@ -275,6 +285,14 @@ public class AppProperties {
this.default_page_size = default_page_size;
}
public Boolean getDelete_expunge_enabled() {
return delete_expunge_enabled;
}
public void setDelete_expunge_enabled(Boolean delete_expunge_enabled) {
this.delete_expunge_enabled = delete_expunge_enabled;
}
public Boolean getEnable_index_missing_fields() {
return enable_index_missing_fields;
}

View File

@@ -29,8 +29,6 @@ public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
System.setProperty("spring.batch.job.enabled", "false");
SpringApplication.run(Application.class, args);
//Server is now accessible at eg. http://localhost:8080/fhir/metadata

View File

@@ -28,6 +28,7 @@ import ca.uhn.fhir.mdm.provider.MdmProviderLoader;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.narrative.INarrativeGenerator;
import ca.uhn.fhir.narrative2.NullNarrativeGenerator;
import ca.uhn.fhir.rest.openapi.OpenApiInterceptor;
import ca.uhn.fhir.rest.server.ApacheProxyAddressStrategy;
import ca.uhn.fhir.rest.server.ETagSupportEnum;
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
@@ -357,6 +358,10 @@ public class BaseJpaRestfulServer extends RestfulServer {
daoConfig.setDeferIndexingForCodesystemsOfSize(appProperties.getDefer_indexing_for_codesystems_of_size());
if (appProperties.getOpenapi_enabled()) {
registerInterceptor(new OpenApiInterceptor());
}
// Bulk Export
if (appProperties.getBulk_export_enabled()) {
registerProvider(bulkDataExportProvider);

View File

@@ -26,7 +26,8 @@ import java.util.*;
public class EnvironmentHelper {
public static Properties getHibernateProperties(ConfigurableEnvironment environment, ConfigurableListableBeanFactory theBeanFactory) {
public static Properties getHibernateProperties(ConfigurableEnvironment environment,
ConfigurableListableBeanFactory myConfigurableListableBeanFactory) {
Properties properties = new Properties();
Map<String, Object> jpaProps = getPropertiesStartingWith(environment, "spring.jpa.properties");
for (Map.Entry<String, Object> entry : jpaProps.entrySet()) {
@@ -42,7 +43,7 @@ public class EnvironmentHelper {
//properties.putIfAbsent(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory));
//hapi-fhir-jpaserver-base "sensible defaults"
Map<String, Object> hapiJpaPropertyMap = new HapiFhirLocalContainerEntityManagerFactoryBean(theBeanFactory).getJpaPropertyMap();
Map<String, Object> hapiJpaPropertyMap = new HapiFhirLocalContainerEntityManagerFactoryBean(myConfigurableListableBeanFactory).getJpaPropertyMap();
hapiJpaPropertyMap.forEach(properties::putIfAbsent);
//hapi-fhir-jpaserver-starter defaults

View File

@@ -43,6 +43,7 @@ public class FhirServerConfigCommon {
ourLog.info("Server configured to " + (appProperties.getAllow_contains_searches() ? "allow" : "deny") + " contains searches");
ourLog.info("Server configured to " + (appProperties.getAllow_multiple_delete() ? "allow" : "deny") + " multiple deletes");
ourLog.info("Server configured to " + (appProperties.getAllow_external_references() ? "allow" : "deny") + " external references");
ourLog.info("Server configured to " + (appProperties.getDelete_expunge_enabled() ? "enable" : "disable") + " delete expunges");
ourLog.info("Server configured to " + (appProperties.getExpunge_enabled() ? "enable" : "disable") + " expunges");
ourLog.info("Server configured to " + (appProperties.getAllow_override_default_search_params() ? "allow" : "deny") + " overriding default search params");
ourLog.info("Server configured to " + (appProperties.getAuto_create_placeholder_reference_targets() ? "allow" : "disable") + " auto-creating placeholder references");
@@ -88,6 +89,7 @@ public class FhirServerConfigCommon {
retVal.setAllowContainsSearches(appProperties.getAllow_contains_searches());
retVal.setAllowMultipleDelete(appProperties.getAllow_multiple_delete());
retVal.setAllowExternalReferences(appProperties.getAllow_external_references());
retVal.setDeleteExpungeEnabled(appProperties.getDelete_expunge_enabled());
retVal.setExpungeEnabled(appProperties.getExpunge_enabled());
if(appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null)
retVal.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom());
@@ -214,19 +216,21 @@ public class FhirServerConfigCommon {
@Bean()
public IEmailSender emailSender(AppProperties appProperties, Optional<SubscriptionDeliveryHandlerFactory> subscriptionDeliveryHandlerFactory) {
if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) {
AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail();
MailConfig mailConfig = new MailConfig();
AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail();
mailConfig.setSmtpHostname(email.getHost());
mailConfig.setSmtpUseStartTLS(email.getStartTlsRequired());
mailConfig.setSmtpPort(email.getPort());
mailConfig.setSmtpUsername(email.getUsername());
mailConfig.setSmtpPassword(email.getPassword());
EmailSenderImpl emailSender = new EmailSenderImpl(mailConfig);
mailConfig.setSmtpUseStartTLS(email.getStartTlsEnable());
if(subscriptionDeliveryHandlerFactory.isPresent()) {
IEmailSender emailSender = new EmailSenderImpl(mailConfig);
if(subscriptionDeliveryHandlerFactory.isPresent())
subscriptionDeliveryHandlerFactory.get().setEmailSender(emailSender);
}
return emailSender;
}
return null;

View File

@@ -59,8 +59,9 @@ public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 {
@Override
@Bean()
public LocalContainerEntityManagerFactoryBean entityManagerFactory(ConfigurableListableBeanFactory theBeanFactory) {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(theBeanFactory);
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
ConfigurableListableBeanFactory myConfigurableListableBeanFactory) {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory);
retVal.setPersistenceUnitName("HAPI_PU");
try {
@@ -68,7 +69,7 @@ public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 {
} catch (Exception e) {
throw new ConfigurationException("Could not set the data source due to a configuration issue", e);
}
retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, theBeanFactory));
retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, myConfigurableListableBeanFactory));
return retVal;
}

View File

@@ -63,8 +63,9 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 {
@Override
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(ConfigurableListableBeanFactory theBeanFactory) {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(theBeanFactory);
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
ConfigurableListableBeanFactory myConfigurableListableBeanFactory) {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory);
retVal.setPersistenceUnitName("HAPI_PU");
try {
@@ -73,7 +74,9 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 {
throw new ConfigurationException("Could not set the data source due to a configuration issue", e);
}
retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, theBeanFactory));
retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment,
myConfigurableListableBeanFactory));
return retVal;
}

View File

@@ -59,8 +59,9 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 {
@Override
@Bean()
public LocalContainerEntityManagerFactoryBean entityManagerFactory(ConfigurableListableBeanFactory theBeanFactory) {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(theBeanFactory);
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
ConfigurableListableBeanFactory myConfigurableListableBeanFactory) {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory);
retVal.setPersistenceUnitName("HAPI_PU");
try {
@@ -69,7 +70,8 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 {
throw new ConfigurationException("Could not set the data source due to a configuration issue", e);
}
retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, theBeanFactory));
retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment,
myConfigurableListableBeanFactory));
return retVal;
}

View File

@@ -60,8 +60,9 @@ public class FhirServerConfigR5 extends BaseJavaConfigR5 {
@Override
@Bean()
public LocalContainerEntityManagerFactoryBean entityManagerFactory(ConfigurableListableBeanFactory theBeanFactory) {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(theBeanFactory);
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
ConfigurableListableBeanFactory myConfigurableListableBeanFactory) {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory);
retVal.setPersistenceUnitName("HAPI_PU");
try {
@@ -70,7 +71,8 @@ public class FhirServerConfigR5 extends BaseJavaConfigR5 {
throw new ConfigurationException("Could not set the data source due to a configuration issue", e);
}
retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, theBeanFactory));
retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment,
myConfigurableListableBeanFactory));
return retVal;
}

View File

@@ -12,6 +12,9 @@ spring:
# database connection pool size
hikari:
maximum-pool-size: 10
flyway:
check-location: false
baselineOnMigrate: true
jpa:
properties:
hibernate.format_sql: false
@@ -35,6 +38,8 @@ spring:
enabled: false
hapi:
fhir:
### This enables the swagger-ui at /fhir/swagger-ui/index.html as well as the /fhir/api-docs (see https://hapifhir.io/hapi-fhir/docs/server_plain/openapi.html)
openapi_enabled: true
### This is the FHIR version. Choose between, DSTU2, DSTU3, R4 or R5
fhir_version: R4
### enable to use the ApacheProxyAddressStrategy which uses X-Forwarded-* headers
@@ -70,6 +75,7 @@ hapi:
# default_encoding: JSON
# default_pretty_print: true
# default_page_size: 20
# delete_expunge_enabled: true
# enable_repository_validating_interceptor: false
# enable_index_missing_fields: false
# enable_index_contained_resource: false

View File

@@ -25,6 +25,7 @@ hapi:
# default_encoding: JSON
# default_pretty_print: true
# default_page_size: 20
# delete_expunge_enabled: true
# enable_index_missing_fields: false
# enforce_referential_integrity_on_delete: false
# enforce_referential_integrity_on_write: false