From 15923edfd53980101ba73c517ea91e63fc3e47b1 Mon Sep 17 00:00:00 2001 From: Ben Li-Sauerwine Date: Thu, 9 Sep 2021 16:29:04 -0400 Subject: [PATCH 01/11] Adds ability to use delete-expunge operations to the JPA Starter Server. --- src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java | 9 +++++++++ .../ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java | 2 ++ src/main/resources/application.yaml | 1 + src/test/resources/application-integrationtest.yaml | 1 + 4 files changed, 13 insertions(+) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java index 4c69373..fd92001 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -29,6 +29,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; @@ -261,6 +262,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; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java index 8777e0a..4ec5912 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -36,6 +36,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"); @@ -81,6 +82,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()); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 7be4423..c4c393d 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -71,6 +71,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 diff --git a/src/test/resources/application-integrationtest.yaml b/src/test/resources/application-integrationtest.yaml index b19a14b..f311891 100644 --- a/src/test/resources/application-integrationtest.yaml +++ b/src/test/resources/application-integrationtest.yaml @@ -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 From e9e9f5d89ee2ffd4d914cfad544a56a08d627d4b Mon Sep 17 00:00:00 2001 From: Ben Li-Sauerwine Date: Tue, 14 Sep 2021 03:16:00 -0400 Subject: [PATCH 02/11] 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. --- Dockerfile | 4 + catalina.properties | 208 ++++++++++++++++++++++++++++++++++++++++++++ server.xml | 76 ++++++++++++++++ 3 files changed, 288 insertions(+) create mode 100644 catalina.properties create mode 100644 server.xml diff --git a/Dockerfile b/Dockerfile index 64a6478..5250ad5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,7 @@ FROM maven:3.6.3-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/ @@ -27,6 +28,9 @@ FROM tomcat:9.0.38-jdk11-openjdk-slim-buster 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/ +COPY catalina.properties /usr/local/tomcat/conf/catalina.properties +COPY server.xml /usr/local/tomcat/conf/server.xml + EXPOSE 8080 CMD ["catalina.sh", "run"] diff --git a/catalina.properties b/catalina.properties new file mode 100644 index 0000000..5277e74 --- /dev/null +++ b/catalina.properties @@ -0,0 +1,208 @@ +# 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 diff --git a/server.xml b/server.xml new file mode 100644 index 0000000..0723e96 --- /dev/null +++ b/server.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 9f65314537e5ab6f63fbceba2a5aa6a300541b3f Mon Sep 17 00:00:00 2001 From: Ben Li-Sauerwine Date: Tue, 14 Sep 2021 10:52:45 -0400 Subject: [PATCH 03/11] Adds ability to change HAPI FHIR JPA server's port with the environment variable server.port --- Dockerfile | 2 -- catalina.properties | 1 + server.xml | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5250ad5..1739d66 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,6 +31,4 @@ COPY --from=build-hapi /tmp/hapi-fhir-jpaserver-starter/target/*.war /usr/local/ COPY catalina.properties /usr/local/tomcat/conf/catalina.properties COPY server.xml /usr/local/tomcat/conf/server.xml -EXPOSE 8080 - CMD ["catalina.sh", "run"] diff --git a/catalina.properties b/catalina.properties index 5277e74..73ed499 100644 --- a/catalina.properties +++ b/catalina.properties @@ -206,3 +206,4 @@ tomcat.util.buf.StringCache.byte.enabled=true #tomcat.util.buf.StringCache.cacheSize=5000 org.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.Digester$EnvironmentPropertySource +server.port=8080 diff --git a/server.xml b/server.xml index 0723e96..86a0ae3 100644 --- a/server.xml +++ b/server.xml @@ -39,7 +39,7 @@ APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080 --> - Date: Mon, 27 Sep 2021 20:56:27 +0200 Subject: [PATCH 04/11] only push build images to DockerHub --- .github/workflows/build-images.yaml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/build-images.yaml b/.github/workflows/build-images.yaml index 89d492d..7aff28d 100644 --- a/.github/workflows/build-images.yaml +++ b/.github/workflows/build-images.yaml @@ -17,7 +17,6 @@ jobs: uses: crazy-max/ghaction-docker-meta@v1 with: images: | - ghcr.io/hapifhir/hapi docker.io/hapiproject/hapi tag-sha: false tag-match: "v(.*)" @@ -27,7 +26,6 @@ jobs: uses: crazy-max/ghaction-docker-meta@v1 with: images: | - ghcr.io/hapifhir/hapi docker.io/hapiproject/hapi tag-sha: false tag-match: "v(.*)" @@ -42,13 +40,6 @@ jobs: 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: From 73d01ab4084e32ae889c9485382b86861d8ccca4 Mon Sep 17 00:00:00 2001 From: chgl Date: Tue, 28 Sep 2021 21:02:44 +0200 Subject: [PATCH 05/11] bumped dependencies to latest --- Dockerfile | 7 +++---- pom.xml | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1739d66..5d3772e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -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 . @@ -13,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. @@ -23,7 +22,7 @@ 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/ diff --git a/pom.xml b/pom.xml index 80dc78f..94f096c 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0 + 5.5.1 hapi-fhir-jpaserver-starter From 79fddf8309db91795fafaf3c877d96833f3b5dff Mon Sep 17 00:00:00 2001 From: chgl Date: Tue, 28 Sep 2021 21:03:01 +0200 Subject: [PATCH 06/11] build ARM-compatible images --- .github/workflows/build-images.yaml | 43 +++++++++++++++++------------ 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build-images.yaml b/.github/workflows/build-images.yaml index 7aff28d..861519a 100644 --- a/.github/workflows/build-images.yaml +++ b/.github/workflows/build-images.yaml @@ -7,6 +7,10 @@ on: pull_request: branches: [master] +env: + IMAGES: docker.io/hapiproject/hapi + PLATFORMS: linux/amd64,linux/arm64/v8 + jobs: build: name: Build @@ -14,32 +18,37 @@ jobs: steps: - name: Docker meta id: docker_meta - uses: crazy-max/ghaction-docker-meta@v1 + uses: docker/metadata-action@v3 with: - images: | - 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: | - 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: Cache Docker layers uses: actions/cache@v2 with: @@ -47,6 +56,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 @@ -56,6 +66,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 @@ -63,10 +75,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 }} From eaffce0d42e5e783de02c597725bfd5b88bf385f Mon Sep 17 00:00:00 2001 From: chgl Date: Thu, 7 Oct 2021 00:38:42 +0200 Subject: [PATCH 07/11] simplified helm chart --- .github/ct/{ct.yaml => config.yaml} | 1 - .github/ct/lintconf.yaml | 40 ----- .github/workflows/build-images.yaml | 5 +- .github/workflows/chart-release.yaml | 9 +- .github/workflows/chart-test.yaml | 41 +++-- charts/README.md | 41 ----- charts/hapi-fhir-jpaserver/Chart.lock | 6 +- charts/hapi-fhir-jpaserver/Chart.yaml | 14 +- charts/hapi-fhir-jpaserver/README.md | 161 ++++++++---------- charts/hapi-fhir-jpaserver/README.md.gotmpl | 16 ++ charts/hapi-fhir-jpaserver/doc.yaml | 19 --- .../templates/_helpers.tpl | 32 +++- .../templates/deployment.yaml | 31 ++-- .../templates/externaldb-secret.yaml | 4 +- .../templates/ingress.yaml | 5 +- .../templates/networkpolicy.yaml | 27 +++ .../templates/tests/test-connection.yaml | 2 +- charts/hapi-fhir-jpaserver/values.yaml | 136 +++++++-------- 18 files changed, 285 insertions(+), 305 deletions(-) rename .github/ct/{ct.yaml => config.yaml} (91%) delete mode 100644 .github/ct/lintconf.yaml delete mode 100644 charts/README.md create mode 100644 charts/hapi-fhir-jpaserver/README.md.gotmpl delete mode 100644 charts/hapi-fhir-jpaserver/doc.yaml create mode 100644 charts/hapi-fhir-jpaserver/templates/networkpolicy.yaml diff --git a/.github/ct/ct.yaml b/.github/ct/config.yaml similarity index 91% rename from .github/ct/ct.yaml rename to .github/ct/config.yaml index ff1135d..484e994 100644 --- a/.github/ct/ct.yaml +++ b/.github/ct/config.yaml @@ -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 diff --git a/.github/ct/lintconf.yaml b/.github/ct/lintconf.yaml deleted file mode 100644 index 8e64eb2..0000000 --- a/.github/ct/lintconf.yaml +++ /dev/null @@ -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 diff --git a/.github/workflows/build-images.yaml b/.github/workflows/build-images.yaml index 861519a..dae0205 100644 --- a/.github/workflows/build-images.yaml +++ b/.github/workflows/build-images.yaml @@ -4,9 +4,12 @@ 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 diff --git a/.github/workflows/chart-release.yaml b/.github/workflows/chart-release.yaml index 7e122f5..5d30c2f 100644 --- a/.github/workflows/chart-release.yaml +++ b/.github/workflows/chart-release.yaml @@ -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 }}" diff --git a/.github/workflows/chart-test.yaml b/.github/workflows/chart-test.yaml index 31d8695..90bb32a 100644 --- a/.github/workflows/chart-test.yaml +++ b/.github/workflows/chart-test.yaml @@ -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' diff --git a/charts/README.md b/charts/README.md deleted file mode 100644 index 22e6ed8..0000000 --- a/charts/README.md +++ /dev/null @@ -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 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.) diff --git a/charts/hapi-fhir-jpaserver/Chart.lock b/charts/hapi-fhir-jpaserver/Chart.lock index 3229d8b..0db0f3a 100644 --- a/charts/hapi-fhir-jpaserver/Chart.lock +++ b/charts/hapi-fhir-jpaserver/Chart.lock @@ -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" diff --git a/charts/hapi-fhir-jpaserver/Chart.yaml b/charts/hapi-fhir-jpaserver/Chart.yaml index 486f828..0b83915 100644 --- a/charts/hapi-fhir-jpaserver/Chart.yaml +++ b/charts/hapi-fhir-jpaserver/Chart.yaml @@ -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 diff --git a/charts/hapi-fhir-jpaserver/README.md b/charts/hapi-fhir-jpaserver/README.md index a23e070..e1e5496 100644 --- a/charts/hapi-fhir-jpaserver/README.md +++ b/charts/hapi-fhir-jpaserver/README.md @@ -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 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: | +| 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: | `{}` | -| tolerations | tolerations for pods assignment see: | `[]` | -| affinity | affinity for pods assignment see: | `{}` | -| 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: | `"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) diff --git a/charts/hapi-fhir-jpaserver/README.md.gotmpl b/charts/hapi-fhir-jpaserver/README.md.gotmpl new file mode 100644 index 0000000..c599d14 --- /dev/null +++ b/charts/hapi-fhir-jpaserver/README.md.gotmpl @@ -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" . }} diff --git a/charts/hapi-fhir-jpaserver/doc.yaml b/charts/hapi-fhir-jpaserver/doc.yaml deleted file mode 100644 index 5a85b4a..0000000 --- a/charts/hapi-fhir-jpaserver/doc.yaml +++ /dev/null @@ -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 diff --git a/charts/hapi-fhir-jpaserver/templates/_helpers.tpl b/charts/hapi-fhir-jpaserver/templates/_helpers.tpl index d5e1c7a..178d840 100644 --- a/charts/hapi-fhir-jpaserver/templates/_helpers.tpl +++ b/charts/hapi-fhir-jpaserver/templates/_helpers.tpl @@ -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 -}} diff --git a/charts/hapi-fhir-jpaserver/templates/deployment.yaml b/charts/hapi-fhir-jpaserver/templates/deployment.yaml index 24ba02f..a58024c 100644 --- a/charts/hapi-fhir-jpaserver/templates/deployment.yaml +++ b/charts/hapi-fhir-jpaserver/templates/deployment.yaml @@ -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 diff --git a/charts/hapi-fhir-jpaserver/templates/externaldb-secret.yaml b/charts/hapi-fhir-jpaserver/templates/externaldb-secret.yaml index 408383a..e3a35d8 100644 --- a/charts/hapi-fhir-jpaserver/templates/externaldb-secret.yaml +++ b/charts/hapi-fhir-jpaserver/templates/externaldb-secret.yaml @@ -1,8 +1,8 @@ -{{- if and (not .Values.postgresql.enabled) (not .Values.externalDatabase.existingSecret) (not .Values.postgresql.existingSecret)}} +{{- if and (not .Values.postgresql.enabled) (not .Values.externalDatabase.existingSecret) (not .Values.postgresql.existingSecret) }} 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 diff --git a/charts/hapi-fhir-jpaserver/templates/ingress.yaml b/charts/hapi-fhir-jpaserver/templates/ingress.yaml index df4862b..6b7b354 100644 --- a/charts/hapi-fhir-jpaserver/templates/ingress.yaml +++ b/charts/hapi-fhir-jpaserver/templates/ingress.yaml @@ -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 }} diff --git a/charts/hapi-fhir-jpaserver/templates/networkpolicy.yaml b/charts/hapi-fhir-jpaserver/templates/networkpolicy.yaml new file mode 100644 index 0000000..d051950 --- /dev/null +++ b/charts/hapi-fhir-jpaserver/templates/networkpolicy.yaml @@ -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 }} diff --git a/charts/hapi-fhir-jpaserver/templates/tests/test-connection.yaml b/charts/hapi-fhir-jpaserver/templates/tests/test-connection.yaml index ba58956..eac503d 100644 --- a/charts/hapi-fhir-jpaserver/templates/tests/test-connection.yaml +++ b/charts/hapi-fhir-jpaserver/templates/tests/test-connection.yaml @@ -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: diff --git a/charts/hapi-fhir-jpaserver/values.yaml b/charts/hapi-fhir-jpaserver/values.yaml index 11f0a2a..5e3c63b 100644 --- a/charts/hapi-fhir-jpaserver/values.yaml +++ b/charts/hapi-fhir-jpaserver/values.yaml @@ -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: +# -- node selector for the pod nodeSelector: {} -# tolerations for pods assignment -# see: +# -- pod tolerations tolerations: [] -# affinity for pods assignment -# see: +# -- pod affinity affinity: {} -# see 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 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: 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: [] From ea3f10ec86774abfaedf220f46a7b515f9751d26 Mon Sep 17 00:00:00 2001 From: jkv Date: Wed, 10 Nov 2021 20:57:31 +0100 Subject: [PATCH 08/11] Added OpenAPI / Swagger option --- pom.xml | 6 ++++++ src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java | 9 +++++++++ .../ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 5 +++++ src/main/resources/application.yaml | 2 ++ 4 files changed, 22 insertions(+) diff --git a/pom.xml b/pom.xml index 94f096c..a7d67e5 100644 --- a/pom.xml +++ b/pom.xml @@ -112,6 +112,12 @@ hapi-fhir-jpaserver-mdm ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-server-openapi + ${project.version} + ca.uhn.hapi.fhir diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java index fd92001..87b4181 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -22,6 +22,7 @@ import java.util.Objects; public class AppProperties { private Boolean cql_enabled = false; + private Boolean openapi_enabled = false; private Boolean mdm_enabled = false; private Boolean allow_cascading_deletes = false; private Boolean allow_contains_searches = true; @@ -75,6 +76,14 @@ public class AppProperties { private Boolean use_apache_address_strategy = false; private Boolean use_apache_address_strategy_https = false; + 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; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java index dc16873..b58c41c 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -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); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index c4c393d..1c51699 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -36,6 +36,8 @@ spring: allow-bean-definition-overriding: true 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 From 16559ea17cf679812fabe8e2b2c2a05dc757e751 Mon Sep 17 00:00:00 2001 From: jkv Date: Thu, 18 Nov 2021 19:48:40 +0100 Subject: [PATCH 09/11] Upgraded to 5.6.0 Subscription tests fail ... --- pom.xml | 2 +- .../ca/uhn/fhir/jpa/starter/Application.java | 10 -------- .../fhir/jpa/starter/EnvironmentHelper.java | 8 ++++--- .../jpa/starter/FhirServerConfigCommon.java | 24 +++++++++---------- .../jpa/starter/FhirServerConfigDstu2.java | 8 ++++--- .../jpa/starter/FhirServerConfigDstu3.java | 12 ++++++---- .../fhir/jpa/starter/FhirServerConfigR4.java | 12 ++++++---- .../fhir/jpa/starter/FhirServerConfigR5.java | 12 ++++++---- src/main/resources/application.yaml | 5 ++-- 9 files changed, 46 insertions(+), 47 deletions(-) diff --git a/pom.xml b/pom.xml index a7d67e5..6b677e8 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.1 + 5.6.0 hapi-fhir-jpaserver-starter diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java index e823d5f..2cf60f5 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -29,16 +29,6 @@ public class Application extends SpringBootServletInitializer { public static void main(String[] args) { - /* - * https://github.com/hapifhir/hapi-fhir-jpaserver-starter/issues/246 - * This will be allowed for a short period until we know how MDM should be configured - * or don't have multiple equal bean instantiations. - * - * This will require changes in the main project as stated in the Github comment - * */ - System.setProperty("spring.main.allow-bean-definition-overriding","true"); - - System.setProperty("spring.batch.job.enabled", "false"); SpringApplication.run(Application.class, args); //Server is now accessible at eg. http://localhost:8080/fhir/metadata diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java index 75db0f8..96a958f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java @@ -14,6 +14,7 @@ import org.hibernate.search.engine.cfg.BackendSettings; import org.hibernate.search.mapper.orm.automaticindexing.session.AutomaticIndexingSynchronizationStrategyNames; import org.hibernate.search.mapper.orm.cfg.HibernateOrmMapperSettings; import org.hibernate.search.mapper.orm.schema.management.SchemaManagementStrategyName; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy; import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; import org.springframework.core.env.CompositePropertySource; @@ -25,7 +26,8 @@ import java.util.*; public class EnvironmentHelper { - public static Properties getHibernateProperties(ConfigurableEnvironment environment) { + public static Properties getHibernateProperties(ConfigurableEnvironment environment, + ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { Properties properties = new Properties(); Map jpaProps = getPropertiesStartingWith(environment, "spring.jpa.properties"); for (Map.Entry entry : jpaProps.entrySet()) { @@ -41,7 +43,7 @@ public class EnvironmentHelper { //properties.putIfAbsent(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory)); //hapi-fhir-jpaserver-base "sensible defaults" - Map hapiJpaPropertyMap = new HapiFhirLocalContainerEntityManagerFactoryBean().getJpaPropertyMap(); + Map hapiJpaPropertyMap = new HapiFhirLocalContainerEntityManagerFactoryBean(myConfigurableListableBeanFactory).getJpaPropertyMap(); hapiJpaPropertyMap.forEach(properties::putIfAbsent); //hapi-fhir-jpaserver-starter defaults @@ -73,7 +75,7 @@ public class EnvironmentHelper { ElasticsearchHibernatePropertiesBuilder builder = new ElasticsearchHibernatePropertiesBuilder(); IndexStatus requiredIndexStatus = environment.getProperty("elasticsearch.required_index_status", IndexStatus.class); builder.setRequiredIndexStatus(requireNonNullElse(requiredIndexStatus, IndexStatus.YELLOW)); - builder.setRestUrl(getElasticsearchServerUrl(environment)); + builder.setHosts(getElasticsearchServerUrl(environment)); builder.setUsername(getElasticsearchServerUsername(environment)); builder.setPassword(getElasticsearchServerPassword(environment)); builder.setProtocol(getElasticsearchServerProtocol(environment)); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java index 4ec5912..1e296d9 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -8,8 +8,9 @@ import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings.CrossPartitionReferenceMode; import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory; +import ca.uhn.fhir.jpa.subscription.match.deliver.email.EmailSenderImpl; import ca.uhn.fhir.jpa.subscription.match.deliver.email.IEmailSender; -import ca.uhn.fhir.jpa.subscription.match.deliver.email.JavaMailEmailSender; +import ca.uhn.fhir.rest.server.mail.MailConfig; import com.google.common.base.Strings; import org.hl7.fhir.dstu2.model.Subscription; import org.springframework.boot.env.YamlPropertySourceLoader; @@ -207,22 +208,21 @@ public class FhirServerConfigCommon { @Bean() public IEmailSender emailSender(AppProperties appProperties, Optional subscriptionDeliveryHandlerFactory) { if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) { - JavaMailEmailSender retVal = new JavaMailEmailSender(); + MailConfig mailConfig = new MailConfig(); AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail(); - retVal.setSmtpServerHostname(email.getHost()); - retVal.setSmtpServerPort(email.getPort()); - retVal.setSmtpServerUsername(email.getUsername()); - retVal.setSmtpServerPassword(email.getPassword()); - retVal.setAuth(email.getAuth()); - retVal.setStartTlsEnable(email.getStartTlsEnable()); - retVal.setStartTlsRequired(email.getStartTlsRequired()); - retVal.setQuitWait(email.getQuitWait()); + mailConfig.setSmtpHostname(email.getHost()); + mailConfig.setSmtpPort(email.getPort()); + mailConfig.setSmtpUsername(email.getUsername()); + mailConfig.setSmtpPassword(email.getPassword()); + mailConfig.setSmtpUseStartTLS(email.getStartTlsEnable()); + + IEmailSender emailSender = new EmailSenderImpl(mailConfig); if(subscriptionDeliveryHandlerFactory.isPresent()) - subscriptionDeliveryHandlerFactory.get().setEmailSender(retVal); + subscriptionDeliveryHandlerFactory.get().setEmailSender(emailSender); - return retVal; + return emailSender; } return null; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java index 6e26d41..25548bf 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java @@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU2Condition; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -58,8 +59,9 @@ public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 { @Override @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory); retVal.setPersistenceUnitName("HAPI_PU"); try { @@ -67,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)); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, myConfigurableListableBeanFactory)); return retVal; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java index 367c0ec..84822dd 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -10,6 +10,7 @@ import javax.annotation.PostConstruct; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -62,8 +63,9 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { @Override @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory); retVal.setPersistenceUnitName("HAPI_PU"); try { @@ -72,7 +74,8 @@ 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)); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, + myConfigurableListableBeanFactory)); return retVal; } @@ -96,8 +99,7 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { } String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - int elasticsearchPort = Integer.parseInt(elasticsearchUrl.substring(elasticsearchUrl.lastIndexOf(":")+1)); - return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchUsername, elasticsearchPassword); } else { return null; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java index a53b057..842256a 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -7,6 +7,7 @@ import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; import ca.uhn.fhir.jpa.starter.cql.StarterCqlR4Config; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.*; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.orm.jpa.JpaTransactionManager; @@ -58,8 +59,9 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 { @Override @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory); retVal.setPersistenceUnitName("HAPI_PU"); try { @@ -68,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)); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, + myConfigurableListableBeanFactory)); return retVal; } @@ -93,8 +96,7 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 { String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - int elasticsearchPort = Integer.parseInt(elasticsearchUrl.substring(elasticsearchUrl.lastIndexOf(":")+1)); - return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchUsername, elasticsearchPassword); } else { return null; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java index 2c6d72e..3cb6968 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -6,6 +6,7 @@ import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -59,8 +60,9 @@ public class FhirServerConfigR5 extends BaseJavaConfigR5 { @Override @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory); retVal.setPersistenceUnitName("HAPI_PU"); try { @@ -69,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)); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, + myConfigurableListableBeanFactory)); return retVal; } @@ -93,8 +96,7 @@ public class FhirServerConfigR5 extends BaseJavaConfigR5 { } String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - int elasticsearchPort = Integer.parseInt(elasticsearchUrl.substring(elasticsearchUrl.lastIndexOf(":")+1)); - return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchUsername, elasticsearchPassword); } else { return null; } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 1c51699..7dd9ece 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -10,6 +10,8 @@ spring: # database connection pool size hikari: maximum-pool-size: 10 + flyway: + check-location: false jpa: properties: hibernate.format_sql: false @@ -31,9 +33,6 @@ spring: batch: job: enabled: false - main: -# TODO 5.6.0 -> Prevent duplicate bean definitions in the Spring batch config in HAPI: see: - allow-bean-definition-overriding: true 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) From 96450874af60f9bbac1b00afb8da6ecb5fc39fdf Mon Sep 17 00:00:00 2001 From: jkv Date: Thu, 18 Nov 2021 20:17:30 +0100 Subject: [PATCH 10/11] Bumped version of Spring Boot in order to fix same issue as https://github.com/Haulmont/jmix-security/issues/90 --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index 6b677e8..338e9c9 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ 8 + 2.5.6 @@ -69,6 +70,7 @@ com.sun.mail javax.mail + 1.6.2 javax.activation From 0203a366685f1dea772148b1a8e2b8f9eea1823d Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Sat, 20 Nov 2021 16:07:26 +0100 Subject: [PATCH 11/11] Update application.yaml See https://github.com/hapifhir/hapi-fhir-jpaserver-starter/issues/292 --- src/main/resources/application.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 7dd9ece..bca1860 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -12,6 +12,7 @@ spring: maximum-pool-size: 10 flyway: check-location: false + baselineOnMigrate: true jpa: properties: hibernate.format_sql: false