├── .github └── workflows │ ├── build-and-deploy-image.yml │ ├── ci.yml │ ├── cloud-config-versions.yml │ ├── codeql.yml │ ├── create-sha-docker-tag.yml │ ├── deploy.yml │ ├── generate-docker-tags.yml │ ├── generate-jvm-tag.yml │ └── release.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle.kts ├── examples ├── aws │ ├── paramstore │ │ ├── compose.yml │ │ ├── config │ │ │ └── application.yml │ │ └── populate-paramstore.sh │ ├── s3 │ │ ├── application.yml │ │ ├── compose.yml │ │ ├── config │ │ │ ├── foo-db.yml │ │ │ ├── foo-dev.yml │ │ │ ├── foo-development-db.yml │ │ │ ├── foo-development.yml │ │ │ └── foo.yml │ │ └── populate-s3.sh │ └── secretsmanager │ │ ├── application.yml │ │ ├── compose.yml │ │ └── populate-secretsmanager.sh ├── cloud-bus │ ├── kafka │ │ ├── compose.yml │ │ └── config │ │ │ └── application.yml │ └── rabbit │ │ ├── compose.yml │ │ └── config │ │ └── application.yml ├── git │ ├── compose.yml │ └── config │ │ └── application.yml ├── healthcheck │ └── compose.yml ├── jdbc │ ├── mariadb │ │ ├── compose.yml │ │ ├── config │ │ │ └── application.yml │ │ └── init-db.sql │ └── postgres │ │ ├── compose.yml │ │ ├── config │ │ └── application.yml │ │ └── init-db.sql ├── native │ ├── compose.yml │ ├── config │ │ └── application.yml │ └── native-files │ │ ├── aggregating.yml │ │ ├── application-dev.yml │ │ ├── application.yaml │ │ ├── application.yml │ │ ├── bar.properties │ │ ├── books.xml │ │ ├── configserver.yml │ │ ├── eureka.yml │ │ ├── foo-db.properties │ │ ├── foo-dev.yml │ │ ├── foo-development-db.properties │ │ ├── foo-development.properties │ │ ├── foo.properties │ │ ├── logtest.yml │ │ ├── processor.yml │ │ ├── samplebackendservice-development.properties │ │ ├── samplebackendservice.properties │ │ ├── samplefrontendservice.properties │ │ ├── stores.yml │ │ ├── subdir │ │ └── test.txt │ │ ├── test.json │ │ ├── text-resource.txt │ │ └── zuul.properties ├── prometheus │ ├── compose.yml │ └── config │ │ └── application.yml ├── redis │ ├── compose.yml │ ├── config │ │ └── application.yml │ └── populate-redis.sh ├── security │ ├── compose.yml │ └── config │ │ └── application.yml └── vault │ ├── compose.yml │ ├── config │ └── application.yml │ └── populate-vault.sh ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── project.toml └── src ├── main ├── kotlin │ └── org │ │ └── freshlegacycode │ │ └── cloud │ │ └── config │ │ └── server │ │ └── ConfigServerApplication.kt └── resources │ └── application.yaml └── test ├── kotlin └── org │ └── freshlegacycode │ └── cloud │ └── config │ └── server │ ├── AwsParamStoreBackendTest.kt │ ├── AwsS3BackendTest.kt │ ├── AwsSecretsManagerBackendTest.kt │ ├── CloudBusKafkaRemoteGitBackendTest.kt │ ├── CloudBusRabbitRemoteGitBackendTest.kt │ ├── ConfigServerApplicationTests.kt │ ├── FileSystemBackendTest.kt │ ├── JdbcBackendMariaDbTest.kt │ ├── JdbcBackendPostgresTest.kt │ ├── JdbcBackendTest.kt │ ├── PrometheusActuatorTest.kt │ ├── RedisBackendTest.kt │ ├── RemoteGitRepoBackendTest.kt │ ├── SecurityEncryptTest.kt │ └── VaultBackendTest.kt └── resources └── junit-platform.properties /.github/workflows/build-and-deploy-image.yml: -------------------------------------------------------------------------------- 1 | name: Build and deploy OCI image to registry 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | image-jvm-type: 7 | description: JVM type for output image 8 | type: string 9 | default: jre 10 | image-jvm-version: 11 | description: JVM version for output image 12 | type: string 13 | default: 17 14 | image-name: 15 | description: The output image name 16 | type: string 17 | required: true 18 | java-build-distribution: 19 | description: Java distribution to use for build 20 | type: string 21 | default: temurin 22 | java-build-version: 23 | description: Java version to build with 24 | type: string 25 | default: 17 26 | registry: 27 | description: The registry to deploy to 28 | type: string 29 | required: true 30 | tags: 31 | description: Comma separated list of docker tags to create 32 | type: string 33 | 34 | jobs: 35 | generate-jvm-tag: 36 | uses: ./.github/workflows/generate-jvm-tag.yml 37 | with: 38 | jvm-type: ${{ inputs.jvm-type }} 39 | jvm-version: ${{ inputs.jvm-version }} 40 | 41 | build-and-push: 42 | name: Build and deploy Java ${{ needs.generate-jvm-tag.outputs.jvm-tag }} OCI image to registry 43 | needs: generate-jvm-tag 44 | runs-on: ubuntu-latest 45 | steps: 46 | - name: Checkout 47 | uses: actions/checkout@v4 48 | 49 | - name: Set up JDK ${{ inputs.java-build-version }} 50 | uses: actions/setup-java@v4 51 | with: 52 | distribution: ${{ inputs.java-build-distribution }} 53 | java-version: ${{ inputs.java-build-version }} 54 | 55 | - name: Setup Gradle 56 | uses: gradle/actions/setup-gradle@v3 57 | 58 | - name: Add tags environment variable 59 | if: inputs.tags != '' 60 | run: echo "TAGS=-PdockerTags=${{ inputs.tags }}" >> $GITHUB_ENV 61 | 62 | - name: Setup Docker Hub credentials 63 | if: inputs.registry == 'docker.io' 64 | run: | 65 | echo "DOCKER_USERNAME=${{ secrets.DOCKERHUB_USERNAME }}" >> $GITHUB_ENV 66 | echo "DOCKER_PASSWORD=${{ secrets.DOCKERHUB_TOKEN }}" >> $GITHUB_ENV 67 | 68 | - name: Setup GitHub Container Registry credentials 69 | if: inputs.registry == 'ghcr.io' 70 | run: | 71 | echo "DOCKER_USERNAME=${{ github.actor }}" >> $GITHUB_ENV 72 | echo "DOCKER_PASSWORD=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV 73 | 74 | - name: Build and deploy OCI image 75 | run: > 76 | ./gradlew bootBuildImage 77 | -PjvmType=${{ inputs.image-jvm-type }} 78 | -PjdkVersion=${{ inputs.image-jvm-version }} 79 | -PdockerUsername=${{ env.DOCKER_USERNAME }} 80 | -PdockerPassword=${{ env.DOCKER_PASSWORD }} 81 | $TAGS 82 | --imageName=${{ inputs.registry }}/${{ inputs.image-name }} 83 | --publishImage 84 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Build and test 2 | 3 | on: 4 | pull_request: 5 | workflow_dispatch: 6 | 7 | env: 8 | DISTRIBUTION: temurin 9 | JVM_TYPE: jre 10 | JVM_VERSION: 17 11 | REGISTRY: ghcr.io 12 | 13 | jobs: 14 | build-vars: 15 | name: Create build variables 16 | runs-on: ubuntu-latest 17 | outputs: 18 | distribution: ${{ steps.build-vars.outputs.distribution }} 19 | jvm-type: ${{ steps.build-vars.outputs.jvm-type }} 20 | jvm-version: ${{ steps.build-vars.outputs.jvm-version }} 21 | registry: ${{ steps.build-vars.outputs.registry }} 22 | steps: 23 | - id: build-vars 24 | name: Create build variables 25 | run: | 26 | echo "distribution=$DISTRIBUTION" >> $GITHUB_OUTPUT 27 | echo "jvm-type=$JVM_TYPE" >> $GITHUB_OUTPUT 28 | echo "jvm-version=$JVM_VERSION" >> $GITHUB_OUTPUT 29 | echo "registry=$REGISTRY" >> $GITHUB_OUTPUT 30 | 31 | sha-tag: 32 | name: Create sha docker tag 33 | uses: ./.github/workflows/create-sha-docker-tag.yml 34 | needs: build-vars 35 | with: 36 | jvm-type: ${{ needs.build-vars.outputs.jvm-type }} 37 | jvm-version: ${{ needs.build-vars.outputs.jvm-version }} 38 | 39 | build-and-deploy: 40 | name: Build and deploy OCI image 41 | uses: ./.github/workflows/build-and-deploy-image.yml 42 | needs: 43 | - build-vars 44 | - sha-tag 45 | with: 46 | image-name: ${{ github.repository }}:${{ needs.sha-tag.outputs.tag }} 47 | registry: ${{ needs.build-vars.outputs.registry }} 48 | 49 | integration-test: 50 | name: Verify OCI image with ${{ matrix.backend }} 51 | needs: 52 | - build-vars 53 | - build-and-deploy 54 | - sha-tag 55 | runs-on: ubuntu-latest 56 | strategy: 57 | fail-fast: false 58 | matrix: 59 | backend: [ 60 | aws-param-store, 61 | aws-s3, 62 | aws-secrets-manager, 63 | cloud-bus-kafka, 64 | cloud-bus-rabbitmq, 65 | git, 66 | mariadb, 67 | native, 68 | postgres, 69 | prometheus, 70 | redis, 71 | security, 72 | vault 73 | ] 74 | steps: 75 | - name: Checkout 76 | uses: actions/checkout@v4 77 | 78 | - name: Set up JDK ${{ needs.build-vars.outputs.jvm-version }} 79 | uses: actions/setup-java@v4 80 | with: 81 | distribution: ${{ needs.build-vars.outputs.distribution }} 82 | java-version: ${{ needs.build-vars.outputs.jvm-version }} 83 | 84 | - name: Setup Gradle 85 | uses: gradle/actions/setup-gradle@v3 86 | 87 | - name: Test with ${{ matrix.backend }} 88 | run: > 89 | ./gradlew test -i 90 | -PtestFilter=${{ matrix.backend }} 91 | -PimageRegistry=${{ needs.build-vars.outputs.registry }} 92 | -PjdkVersion=${{ needs.build-vars.outputs.jvm-version }} 93 | -PimageTag=${{ needs.sha-tag.outputs.tag }} 94 | -------------------------------------------------------------------------------- /.github/workflows/cloud-config-versions.yml: -------------------------------------------------------------------------------- 1 | name: Find build and latest versions of cloud config 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | distribution: 7 | description: JVM distribution to run 8 | type: string 9 | default: temurin 10 | java-version: 11 | description: JVM version to run 12 | type: string 13 | default: 17 14 | outputs: 15 | build: 16 | description: Current build version of cloud config 17 | value: ${{ jobs.cloud-config-versions.outputs.build }} 18 | latest: 19 | description: Latest version of cloud config 20 | value: ${{ jobs.cloud-config-versions.outputs.latest }} 21 | 22 | jobs: 23 | cloud-config-versions: 24 | name: Create Cloud Config Versions 25 | runs-on: ubuntu-latest 26 | outputs: 27 | build: ${{ steps.vars.outputs.build }} 28 | latest: ${{ steps.vars.outputs.latest }} 29 | steps: 30 | - name: Checkout 31 | uses: actions/checkout@v4 32 | 33 | - name: Set up JDK ${{ inputs.java-version }} 34 | uses: actions/setup-java@v4 35 | with: 36 | distribution: ${{ inputs.distribution }} 37 | java-version: ${{ inputs.java-version }} 38 | 39 | - name: Setup Gradle 40 | uses: gradle/actions/setup-gradle@v3 41 | 42 | - name: Set cloud config versions 43 | id: vars 44 | run: | 45 | echo "latest=`curl -s https://search.maven.org/solrsearch/select\?q\=g:%22org.springframework.cloud%22%20AND%20a:%22spring-cloud-config-server%22 | jq -r '.response.docs[0].latestVersion'`" >> $GITHUB_OUTPUT 46 | echo "build=`./gradlew dependencyInsight --dependency org.springframework.cloud:spring-cloud-config-server | grep 'org.springframework.cloud:spring-cloud-config-server:' | tail -1 | cut -d ':' -f 3-`" >> $GITHUB_OUTPUT 47 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "main", "develop" ] 17 | pull_request: 18 | branches: [ "main", "develop" ] 19 | schedule: 20 | - cron: '25 22 * * 6' 21 | 22 | jobs: 23 | analyze: 24 | name: Analyze (${{ matrix.language }}) 25 | # Runner size impacts CodeQL analysis time. To learn more, please see: 26 | # - https://gh.io/recommended-hardware-resources-for-running-codeql 27 | # - https://gh.io/supported-runners-and-hardware-resources 28 | # - https://gh.io/using-larger-runners (GitHub.com only) 29 | # Consider using larger runners or machines with greater resources for possible analysis time improvements. 30 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} 31 | timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} 32 | permissions: 33 | # required for all workflows 34 | security-events: write 35 | 36 | # only required for workflows in private repositories 37 | actions: read 38 | contents: read 39 | 40 | strategy: 41 | fail-fast: false 42 | matrix: 43 | include: 44 | - language: java-kotlin 45 | build-mode: autobuild 46 | # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' 47 | # Use `c-cpp` to analyze code written in C, C++ or both 48 | # Use 'java-kotlin' to analyze code written in Java, Kotlin or both 49 | # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both 50 | # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, 51 | # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. 52 | # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how 53 | # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages 54 | steps: 55 | - name: Checkout repository 56 | uses: actions/checkout@v4 57 | 58 | - name: Set up JDK 17 59 | uses: actions/setup-java@v4 60 | with: 61 | distribution: temurin 62 | java-version: 17 63 | 64 | - name: Setup Gradle 65 | uses: gradle/actions/setup-gradle@v3 66 | 67 | # Initializes the CodeQL tools for scanning. 68 | - name: Initialize CodeQL 69 | uses: github/codeql-action/init@v3 70 | with: 71 | languages: ${{ matrix.language }} 72 | build-mode: ${{ matrix.build-mode }} 73 | # If you wish to specify custom queries, you can do so here or in a config file. 74 | # By default, queries listed here will override any specified in a config file. 75 | # Prefix the list here with "+" to use these queries and those in the config file. 76 | 77 | # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 78 | # queries: security-extended,security-and-quality 79 | 80 | # If the analyze step fails for one of the languages you are analyzing with 81 | # "We were unable to automatically build your code", modify the matrix above 82 | # to set the build mode to "manual" for that language. Then modify this step 83 | # to build your code. 84 | # ℹ️ Command-line programs to run using the OS shell. 85 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 86 | - if: matrix.build-mode == 'manual' 87 | run: | 88 | echo 'If you are using a "manual" build mode for one or more of the' \ 89 | 'languages you are analyzing, replace this with the commands to build' \ 90 | 'your code, for example:' 91 | echo ' make bootstrap' 92 | echo ' make release' 93 | exit 1 94 | 95 | - name: Perform CodeQL Analysis 96 | uses: github/codeql-action/analyze@v3 97 | with: 98 | category: "/language:${{matrix.language}}" 99 | -------------------------------------------------------------------------------- /.github/workflows/create-sha-docker-tag.yml: -------------------------------------------------------------------------------- 1 | name: Create sha docker tag 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | jvm-type: 7 | description: JVM type for output image 8 | type: string 9 | default: jre 10 | jvm-version: 11 | description: JVM version for output image 12 | type: string 13 | default: 17 14 | outputs: 15 | tag: 16 | description: Docker tag with sha of commit 17 | value: ${{ jobs.create-sha-docker-tag.outputs.tag }} 18 | 19 | jobs: 20 | jvm-tag: 21 | uses: ./.github/workflows/generate-jvm-tag.yml 22 | with: 23 | jvm-type: ${{ inputs.jvm-type }} 24 | jvm-version: ${{ inputs.jvm-version }} 25 | 26 | create-sha-docker-tag: 27 | name: Create sha docker tag 28 | needs: jvm-tag 29 | runs-on: ubuntu-latest 30 | outputs: 31 | tag: ${{ steps.vars.outputs.tag }} 32 | steps: 33 | - name: Build sha docker tag 34 | id: vars 35 | run: echo "tag=`echo $GITHUB_SHA | cut -c1-7`-${{ needs.jvm-tag.outputs.jvm-tag }}" >> $GITHUB_OUTPUT 36 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Build and deploy to registry 2 | 3 | on: 4 | release: 5 | types: 6 | - published 7 | workflow_dispatch: 8 | inputs: 9 | registry: 10 | description: Registry to deploy artifacts (docker.io, ghcr.io) 11 | required: true 12 | 13 | env: 14 | REGISTRY: docker.io 15 | 16 | jobs: 17 | build-vars: 18 | name: Create build variables 19 | runs-on: ubuntu-latest 20 | outputs: 21 | registry: ${{ inputs.registry || steps.build-vars.outputs.registry }} 22 | steps: 23 | - id: build-vars 24 | name: Create build variables 25 | run: echo "registry=$REGISTRY" >> $GITHUB_OUTPUT 26 | 27 | cloud-config-versions: 28 | name: Find build and latest versions of cloud config 29 | uses: ./.github/workflows/cloud-config-versions.yml 30 | 31 | build-and-deploy-to-registry: 32 | name: Create OCI images and deploy to ${{ inputs.registry }} 33 | uses: ./.github/workflows/release.yml 34 | needs: 35 | - build-vars 36 | - cloud-config-versions 37 | strategy: 38 | matrix: 39 | jvmType: [jre, jdk] 40 | jvmVersion: [17, 21] 41 | with: 42 | build-version: ${{ needs.cloud-config-versions.outputs.build }} 43 | latest-version: ${{ needs.cloud-config-versions.outputs.latest }} 44 | jvm-version: ${{ matrix.jvmVersion }} 45 | jvm-type: ${{ matrix.jvmType }} 46 | registry: ${{ needs.build-vars.outputs.registry }} 47 | secrets: inherit 48 | 49 | update-docker-hub-description: 50 | name: Update Docker Hub README 51 | needs: 52 | - build-vars 53 | - build-and-deploy-to-registry 54 | if: needs.build-vars.outputs.registry == 'docker.io' 55 | runs-on: ubuntu-latest 56 | steps: 57 | - name: Checkout 58 | uses: actions/checkout@v4 59 | 60 | - name: Docker Hub Description 61 | uses: peter-evans/dockerhub-description@v4 62 | with: 63 | username: ${{ secrets.DOCKERHUB_USERNAME }} 64 | password: ${{ secrets.DOCKERHUB_TOKEN }} 65 | repository: hyness/spring-cloud-config-server 66 | -------------------------------------------------------------------------------- /.github/workflows/generate-docker-tags.yml: -------------------------------------------------------------------------------- 1 | name: Generate release build tags 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | build-version: 7 | description: Version of docker image 8 | type: string 9 | required: true 10 | latest-version: 11 | description: Latest version of docker image 12 | type: string 13 | required: true 14 | image-name: 15 | description: The output image name 16 | type: string 17 | default: ${{ inputs.registry }}/${{ github.repository }} 18 | jvm-type: 19 | description: JVM type for output image 20 | type: string 21 | default: ${{ inputs.jvm-type-default }} 22 | jvm-type-default: 23 | description: Default JVM type for output image 24 | type: string 25 | default: jre 26 | jvm-version: 27 | description: JVM version for output image 28 | type: string 29 | default: ${{ inputs.jvm-version-default }} 30 | jvm-version-default: 31 | description: Default JVM version for output image 32 | type: string 33 | default: 17 34 | registry: 35 | description: Docker registry to deploy image 36 | type: string 37 | default: ghcr.io 38 | outputs: 39 | tags: 40 | description: A list of docker tags to create 41 | value: ${{ jobs.docker-tags.outputs.tags }} 42 | 43 | jobs: 44 | jvm-tag: 45 | uses: ./.github/workflows/generate-jvm-tag.yml 46 | with: 47 | jvm-type: ${{ inputs.jvm-type }} 48 | jvm-version: ${{ inputs.jvm-version }} 49 | 50 | jvm-tag-default: 51 | uses: ./.github/workflows/generate-jvm-tag.yml 52 | with: 53 | jvm-type: ${{ inputs.jvm-type-default }} 54 | jvm-version: ${{ inputs.jvm-version-default }} 55 | 56 | docker-tags: 57 | name: Generate release build tags 58 | needs: 59 | - jvm-tag 60 | - jvm-tag-default 61 | runs-on: ubuntu-latest 62 | outputs: 63 | tags: ${{ steps.write-tags.outputs.tags }} 64 | env: 65 | IS_JVM_DEFAULT: ${{ needs.jvm-tag.outputs.jvm-tag == needs.jvm-tag-default.outputs.jvm-tag }} 66 | steps: 67 | - name: Checkout 68 | uses: actions/checkout@v4 69 | 70 | - name: Remove prefix, if necessary 71 | run: | 72 | echo "BUILD_VERSION=`echo "${{ inputs.build-version }} | sed 's/.* -> //'`" >> $GITHUB_ENV 73 | 74 | - name: Determine if latest version 75 | run: | 76 | echo "IS_LATEST_VERSION=${{ env.BUILD_VERSION == inputs.latest-version }}" >> $GITHUB_ENV 77 | 78 | - name: Create docker tags 79 | uses: docker/metadata-action@v5 80 | with: 81 | images: ${{ inputs.image-name }} 82 | flavor: latest=false 83 | sep-tags: ',' 84 | tags: | 85 | type=raw,value=latest,enable=${{ env.IS_LATEST_VERSION && env.IS_JVM_DEFAULT }} 86 | type=semver,pattern={{version}},value=${{ env.BUILD_VERSION }},enable=${{ env.IS_JVM_DEFAULT }} 87 | type=semver,pattern={{major}}.{{minor}},value=${{ env.BUILD_VERSION }},enable=${{ env.IS_JVM_DEFAULT }} 88 | 89 | type=raw,value=${{ needs.jvm-tag.outputs.jvm-tag }} 90 | type=semver,pattern={{major}}.{{minor}},suffix=-${{ needs.jvm-tag.outputs.jvm-tag }},value=${{ env.BUILD_VERSION }} 91 | type=semver,pattern={{version}},suffix=-{{sha}}-${{ needs.jvm-tag.outputs.jvm-tag }},value=${{ env.BUILD_VERSION }} 92 | 93 | - name: Write output 94 | id: write-tags 95 | run: echo "tags=$DOCKER_METADATA_OUTPUT_TAGS" >> $GITHUB_OUTPUT 96 | -------------------------------------------------------------------------------- /.github/workflows/generate-jvm-tag.yml: -------------------------------------------------------------------------------- 1 | name: Generate a jvm tag 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | jvm-type: 7 | description: JVM type for output image 8 | type: string 9 | required: true 10 | jvm-version: 11 | description: JVM version for output image 12 | type: string 13 | required: true 14 | outputs: 15 | jvm-tag: 16 | description: JVM tag used in docker tags 17 | value: ${{ jobs.generate-jvm-tag.outputs.jvm-tag }} 18 | 19 | jobs: 20 | generate-jvm-tag: 21 | name: Generate a jvm tag 22 | runs-on: ubuntu-latest 23 | outputs: 24 | jvm-tag: ${{ steps.write-tag.outputs.jvm-tag }} 25 | steps: 26 | - name: Write output 27 | id: write-tag 28 | run: echo "jvm-tag=${{ format('{0}{1}', inputs.jvm-type, inputs.jvm-version) }}" >> $GITHUB_OUTPUT 29 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release build 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | build-version: 7 | description: Version of docker image 8 | type: string 9 | required: true 10 | latest-version: 11 | description: Latest version of docker image 12 | type: string 13 | required: true 14 | jvm-type: 15 | description: JVM type for output image 16 | type: string 17 | default: jre 18 | jvm-version: 19 | description: JVM version for output image 20 | type: string 21 | default: 17 22 | image-name: 23 | description: The output image name 24 | type: string 25 | default: ${{ github.repository }} 26 | registry: 27 | description: The registry to deploy to 28 | type: string 29 | required: true 30 | 31 | jobs: 32 | docker-tags: 33 | uses: ./.github/workflows/generate-docker-tags.yml 34 | with: 35 | build-version: ${{ inputs.build-version }} 36 | latest-version: ${{ inputs.latest-version }} 37 | jvm-version: ${{ inputs.jvm-version }} 38 | jvm-type: ${{ inputs.jvm-type }} 39 | 40 | jvm-tag: 41 | uses: ./.github/workflows/generate-jvm-tag.yml 42 | with: 43 | jvm-type: ${{ inputs.jvm-type }} 44 | jvm-version: ${{ inputs.jvm-version }} 45 | 46 | sha-tag: 47 | uses: ./.github/workflows/create-sha-docker-tag.yml 48 | with: 49 | jvm-type: ${{ inputs.jvm-type }} 50 | jvm-version: ${{ inputs.jvm-version }} 51 | 52 | build-and-deploy: 53 | name: Build and deploy Java ${{ needs.jvm-tag.outputs.jvm-tag }} OCI image to registry 54 | uses: ./.github/workflows/build-and-deploy-image.yml 55 | needs: 56 | - docker-tags 57 | - jvm-tag 58 | - sha-tag 59 | with: 60 | image-name: ${{ inputs.image-name }}:${{ needs.sha-tag.outputs.tag }} 61 | image-jvm-version: ${{ inputs.jvm-version }} 62 | image-jvm-type: ${{ inputs.jvm-type }} 63 | registry: ${{ inputs.registry }} 64 | tags: ${{ needs.docker-tags.outputs.tags }} 65 | secrets: inherit 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.github 3 | !.travis-ci.yml 4 | build 5 | target 6 | out 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring Cloud Config Server 2 | A docker image of [Spring Cloud Config Server](https://docs.spring.io/spring-cloud-config/reference/). 3 | 4 | ![CI Build](https://github.com/hyness/spring-cloud-config-server/actions/workflows/ci.yml/badge.svg) 5 | ![Docker Image Version (latest semver)](https://img.shields.io/docker/v/hyness/spring-cloud-config-server?sort=semver) 6 | [![Docker Stars](https://img.shields.io/docker/stars/hyness/spring-cloud-config-server.svg?style=flat)](https://hub.docker.com/r/hyness/spring-cloud-config-server/) 7 | [![Docker Pulls](https://img.shields.io/docker/pulls/hyness/spring-cloud-config-server.svg?style=flat)](https://hub.docker.com/r/hyness/spring-cloud-config-server) 8 | [![Image Size](https://img.shields.io/docker/image-size/hyness/spring-cloud-config-server.svg?style=flat)](https://hub.docker.com/r/hyness/spring-cloud-config-server) 9 | [![License](https://img.shields.io/github/license/hyness/spring-cloud-config-server)](https://www.apache.org/licenses/LICENSE-2.0.html) 10 | 11 | ### Supported tags 12 | * `4.2.2-jre17`, `4.2-jre17`, `jre17`, `4.2.2`, `4.2`, `latest` 13 | * `4.2.2-jdk17`, `4.2-jdk17`, `jdk17` 14 | * `4.2.2-jre21`, `4.2-jre21`, `jre21` 15 | * `4.2.2-jdk21`, `4.2-jdk21`, `jdk21` 16 | 17 | ### Usage 18 | ``` 19 | docker run -it --name=spring-cloud-config-server \ 20 | -p 8888:8888 \ 21 | -v :/config \ 22 | hyness/spring-cloud-config-server 23 | ``` 24 | 25 | #### Parameters 26 | * `-p 8888` Server port 27 | * `-v /config` Mounted configuration 28 | 29 | #### Environment Variables 30 | * `JAVA_OPTS` Specify VM Options or System Properties 31 | 32 | ### Configuring Spring Cloud Config Server 33 | Spring Cloud Config Server is a normal Spring Boot application, it can be configured through all the ways a 34 | Spring Boot application can be configured. You may use environment variables or you can mount configuration in 35 | the provided volume. The configuration file must be named **application** and may be a properties or yaml file. 36 | See the [Spring Boot documentation](http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config) 37 | for further information on how to use and configure Spring Boot. 38 | 39 | #### Configuration examples 40 | 41 | #### Using a mounted config directory 42 | ``` 43 | docker run -it -p 8888:8888 \ 44 | -v /path/to/config/dir:/config \ 45 | hyness/spring-cloud-config-server 46 | ``` 47 | 48 | #### Using a mounted application.yml 49 | ``` 50 | docker run -it -p 8888:8888 \ 51 | -v /path/to/application.yml:/config/application.yml \ 52 | hyness/spring-cloud-config-server 53 | ``` 54 | #### Configure through environment variables without a configuration file 55 | ``` 56 | docker run -it -p 8888:8888 \ 57 | -e SPRING_CLOUD_CONFIG_SERVER_GIT_URI=https://github.com/spring-cloud-samples/config-repo \ 58 | hyness/spring-cloud-config-server 59 | ``` 60 | #### Configure through system properties without a configuration file 61 | ``` 62 | docker run -it -p 8888:8888 \ 63 | -e JAVA_OPTS=-Dspring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo \ 64 | hyness/spring-cloud-config-server 65 | ``` 66 | #### Configure through command line arguments without a configuration file 67 | ``` 68 | docker run -it -p 8888:8888 \ 69 | hyness/spring-cloud-config-server \ 70 | --spring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo 71 | ``` 72 | #### Verify Samples Above 73 | ``` 74 | $ curl http://localhost:8888/foo/development 75 | ``` 76 | 77 | ### Required Backend Configuration 78 | Spring Cloud Config Server **requires** that you configure a backend to serve your configuration files 79 | 80 | #### Git 81 | #### Remote https git repo example 82 | ``` 83 | docker run -it -p 8888:8888 \ 84 | -e SPRING_CLOUD_CONFIG_SERVER_GIT_URI=https://github.com/spring-cloud-samples/config-repo \ 85 | hyness/spring-cloud-config-server 86 | ``` 87 | #### Remote ssh git repo example 88 | ``` 89 | docker run -it -p 8888:8888 \ 90 | -v /path/to/home/dir/with/ssh/keys:/home/cnb/.ssh \ 91 | -e SPRING_CLOUD_CONFIG_SERVER_GIT_URI=git@github.com:spring-cloud-samples/config-repo \ 92 | hyness/spring-cloud-config-server 93 | ``` 94 | #### Local git repo example 95 | ``` 96 | docker run -it -p 8888:8888 \ 97 | -v /path/to/config/files/dir:/config \ 98 | -e SPRING_CLOUD_CONFIG_SERVER_GIT_URI=file:/config/my-local-git-repo \ 99 | hyness/spring-cloud-config-server 100 | ``` 101 | #### Filesystem 102 | ``` 103 | docker run -it -p 8888:8888 \ 104 | -v /path/to/config/files/dir:/config \ 105 | -e SPRING_PROFILES_ACTIVE=native \ 106 | hyness/spring-cloud-config-server 107 | ``` 108 | #### Vault 109 | ``` 110 | docker run -it -p 8888:8888 \ 111 | -e SPRING_PROFILES_ACTIVE=vault \ 112 | -e SPRING_CLOUD_CONFIG_SERVER_VAULT_HOST=localhost \ 113 | -e SPRING_CLOUD_CONFIG_SERVER_VAULT_TOKEN=00000000-0000-0000-0000-000000000000 \ 114 | hyness/spring-cloud-config-server 115 | ``` 116 | #### AWS Parameter Store 117 | ``` 118 | docker run -it -p 8888:8888 \ 119 | -e SPRING_PROFILES_ACTIVE=awsparamstore \ 120 | -e SPRING_CLOUD_CONFIG_SERVER_AWSPARAMSTORE_REGION=us-east-1 \ 121 | hyness/spring-cloud-config-server 122 | ``` 123 | #### AWS S3 124 | ``` 125 | docker run -it -p 8888:8888 \ 126 | -e SPRING_PROFILES_ACTIVE=awss3 \ 127 | -e SPRING_CLOUD_CONFIG_SERVER_AWSS3_REGION=us-east-1 \ 128 | -e SPRING_CLOUD_CONFIG_SERVER_AWSS3_BUCKET=sample-bucket \ 129 | hyness/spring-cloud-config-server 130 | ``` 131 | #### AWS Secrets Manager 132 | ``` 133 | docker run -it -p 8888:8888 \ 134 | -e SPRING_PROFILES_ACTIVE=awssecretsmanager \ 135 | -e SPRING_CLOUD_CONFIG_SERVER_AWSSECRETSMANAGER_REGION=us-east-1 \ 136 | hyness/spring-cloud-config-server 137 | ``` 138 | #### Redis 139 | ``` 140 | docker run -it -p 8888:8888 \ 141 | -e SPRING_PROFILES_ACTIVE=redis \ 142 | -e SPRING_DATA_REDIS_HOST=localhost 143 | -e SPRING_DATA_REDIS_PORT=6379 144 | hyness/spring-cloud-config-server 145 | ``` 146 | #### JDBC 147 | ``` 148 | docker run -it -p 8888:8888 \ 149 | -e SPRING_PROFILES_ACTIVE=jdbc \ 150 | -e SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/database_name \ 151 | -e SPRING_DATASOURCE_USERNAME=myuser \ 152 | -e SPRING_DATASOURCE_PASSWORD=mypassword \ 153 | hyness/spring-cloud-config-server 154 | ``` 155 | #### Supported Databases 156 | * Firebird 157 | * MariaDB 158 | * MS-SQL 159 | * Postgres 160 | 161 | [See the docker-compose examples](https://github.com/hyness/spring-cloud-config-server/tree/main/examples) for more details 162 | 163 | ### Additional Features 164 | 165 | #### Push notifications with Spring Cloud Bus 166 | 167 | Spring Cloud Bus links the nodes of a distributed system with a lightweight message broker. It allows clusters of 168 | applications configured with **RefreshScope** to automatically reload configuration without restarting. 169 | 170 | [See the Spring Cloud Conifg](https://docs.spring.io/spring-cloud-config/docs/2.2.6.RELEASE/reference/html/#_push_notifications_and_spring_cloud_bus) and 171 | [Spring Cloud Bus](https://cloud.spring.io/spring-cloud-bus/reference/html) documentation for more details 172 | 173 | #### Supported Message Brokers 174 | #### Kafka 175 | ``` 176 | docker run -it -p 8888:8888 \ 177 | -e SPRING_PROFILES_ACTIVE=cloud-bus-kafka \ 178 | -e SPRING_CLOUD_CONFIG_SERVER_GIT_URI=https://github.com/spring-cloud-samples/config-repo \ 179 | -e SPRING_KAFKA_BOOTSTRAP-SERVERS=localhost:9092 \ 180 | hyness/spring-cloud-config-server 181 | ``` 182 | 183 | #### RabbitMQ 184 | ``` 185 | docker run -it -p 8888:8888 \ 186 | -e SPRING_PROFILES_ACTIVE=cloud-bus-rabbit \ 187 | -e SPRING_CLOUD_CONFIG_SERVER_GIT_URI=https://github.com/spring-cloud-samples/config-repo \ 188 | -e SPRING_RABBITMQ_HOST=localhost \ 189 | hyness/spring-cloud-config-server 190 | ``` 191 | 192 | ### Actuator 193 | The [Spring Boot actuator](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#production-ready) is 194 | enabled by default. [See the Spring Boot documentation](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#actuator-properties) 195 | for configuration options. The actuator can be disabled entirely by including the `no-actuator` profile 196 | 197 | #### Prometheus Metrics 198 | To enable support for an additional prometheus metrics endpoint, enable the `prometheus` endpoint, as well as [ensuring the 199 | endpoint is exposed](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#actuator.endpoints.exposing). 200 | ```` 201 | docker run -it -p 8888:8888 \ 202 | -v /path/to/config/files/dir:/config \ 203 | -e SPRING_CLOUD_CONFIG_SERVER_GIT_URI=file:/config/my-local-git-repo \ 204 | -e MANAGEMENT_ENDPOINT_PROMETHEUS_ENABLED=true \ 205 | -e MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE=health,prometheus \ 206 | hyness/spring-cloud-config-server 207 | ```` 208 | 209 | ### Spring Security 210 | Spring Security can be enabled through the `security` profile for use with any backend of your choosing. 211 | 212 | #### Basic / Form Security (with remote git backend) 213 | ``` 214 | docker run -it -p 8888:8888 \ 215 | -e SPRING_PROFILES_ACTIVE=security \ 216 | -e SPRING_SECURITY_USER_NAME=myuser \ 217 | -e SPRING_SECURITY_USER_PASSWORD=mypassword \ 218 | -e SPRING_CLOUD_CONFIG_SERVER_GIT_URI=https://github.com/spring-cloud-samples/config-repo \ 219 | hyness/spring-cloud-config-server 220 | ``` 221 | 222 | ### Docker Healthcheck 223 | Starting with 4.1.x, this docker image includes an internal health checker for use with docker or docker compose 224 | using [Tiny Health Checker](https://github.com/dmikusa/tiny-health-checker). 225 | 226 | #### Example configuration 227 | ```yaml 228 | healthcheck: 229 | test: ["CMD", "health-check"] 230 | start_interval: 30s 231 | interval: 5s 232 | retries: 10 233 | ``` 234 | 235 | See [the full example](./examples/healthcheck/compose.yml) for more details 236 | 237 | ### Thank You 238 | 239 | #### Project Contributors 240 | Thank you to all the contributors who have helped make this project better through code contributions and bug reports. 241 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES as SPRING_BOOT_BOM 2 | 3 | plugins { 4 | alias(libs.plugins.spring.boot) 5 | alias(libs.plugins.kotlin.jvm) 6 | alias(libs.plugins.kotlin.plugin.spring) 7 | } 8 | 9 | val jdkVersion: String by project 10 | val jvmType: String by project 11 | val dockerUsername: String by project 12 | val dockerPassword: String by project 13 | val dockerTags: String? by project 14 | val imageRegistry: String? by project 15 | val imageName: String? by project 16 | val imageTag: String? by project 17 | val testFilter: String? by project 18 | 19 | tasks { 20 | version = versionCatalogs.firstNotNullOf { 21 | it.findVersion("spring.cloud.config").orElse(null) 22 | } 23 | 24 | compileKotlin { 25 | compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") 26 | } 27 | 28 | test { 29 | systemProperties["registry"] = imageRegistry 30 | systemProperties["name"] = imageName 31 | systemProperties["tag"] = imageTag 32 | useJUnitPlatform { 33 | testFilter?.let { includeTags(it) } 34 | } 35 | } 36 | 37 | bootJar { 38 | manifest.attributes( 39 | "Implementation-Title" to project.name, 40 | "Implementation-Version" to project.version 41 | ) 42 | } 43 | 44 | bootBuildImage { 45 | applicationDirectory = "/opt/spring-cloud-config-server" 46 | buildpacks = listOf( 47 | "paketo-buildpacks/ca-certificates", 48 | "paketo-buildpacks/bellsoft-liberica", 49 | "paketo-buildpacks/syft", 50 | "paketo-buildpacks/executable-jar", 51 | "paketo-buildpacks/dist-zip", 52 | "paketo-buildpacks/spring-boot", 53 | "paketo-buildpacks/environment-variables", 54 | "gcr.io/paketo-buildpacks/health-checker:1.17.0" 55 | ) 56 | docker.publishRegistry { 57 | username = dockerUsername 58 | password = dockerPassword 59 | } 60 | environment = mapOf( 61 | "BP_JVM_TYPE" to jvmType, 62 | "BP_JVM_VERSION" to jdkVersion, 63 | "BPE_DELIM_JAVA_TOOL_OPTIONS" to " ", 64 | "BPE_APPEND_JAVA_TOOL_OPTIONS" to "-Dspring.config.additional-location=optional:file:/config/", 65 | "BP_HEALTH_CHECKER_ENABLED" to "true", 66 | "BPE_THC_PATH" to "/actuator/health", 67 | "BPE_THC_PORT" to "8888" 68 | ) 69 | imageName = "hyness/spring-cloud-config-server" 70 | tags = dockerTags?.split(',') 71 | } 72 | } 73 | 74 | repositories { 75 | mavenCentral() 76 | } 77 | 78 | dependencies { 79 | implementation(platform(SPRING_BOOT_BOM)) 80 | implementation(platform(libs.spring.cloud)) 81 | implementation(libs.bundles.spring.cloud.config) 82 | implementation(libs.bundles.spring.cloud.bus) 83 | implementation(libs.spring.boot.actuator) 84 | implementation(libs.spring.data.redis) 85 | implementation(libs.spring.boot.security) 86 | implementation(libs.spring.jdbc) 87 | implementation(libs.spring.vault) 88 | implementation(libs.bundles.kotlin) 89 | implementation(libs.bundles.aws) 90 | runtimeOnly(libs.bundles.jdbc.drivers) 91 | runtimeOnly(libs.micrometer.prometheus) 92 | testImplementation(libs.spring.boot.test) 93 | testImplementation(libs.spring.boot.testcontainers) 94 | testImplementation(libs.testcontainers.junit5) 95 | testImplementation(libs.kotlin.logging) 96 | testImplementation(libs.awaitility.kotlin) 97 | } 98 | 99 | configurations.all { 100 | resolutionStrategy.eachDependency { 101 | if (requested.name.startsWith("spring-cloud-function-")) { 102 | useVersion("4.2.2") 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /examples/aws/paramstore/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing AWS S3 2 | 3 | networks: 4 | aws: 5 | 6 | services: 7 | # Configured through environment variables 8 | config-server-env: 9 | depends_on: 10 | localstack: 11 | condition: service_healthy 12 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 13 | networks: 14 | - aws 15 | ports: 16 | - "8888" 17 | environment: 18 | AWS_ACCESS_KEY_ID: test 19 | AWS_SECRET_ACCESS_KEY: test 20 | SPRING_PROFILES_ACTIVE: awsparamstore 21 | SPRING_CLOUD_CONFIG_SERVER_AWSPARAMSTORE_ENDPOINT: http://localhost.localstack.cloud:4566 22 | SPRING_CLOUD_CONFIG_SERVER_AWSPARAMSTORE_REGION: us-east-1 23 | 24 | # Configured through mounted config file 25 | config-server-dir: 26 | depends_on: 27 | localstack: 28 | condition: service_healthy 29 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 30 | networks: 31 | - aws 32 | ports: 33 | - "8888" 34 | environment: 35 | AWS_ACCESS_KEY_ID: test 36 | AWS_SECRET_ACCESS_KEY: test 37 | volumes: 38 | - ./config:/config 39 | 40 | # Configured through system properties 41 | config-server-props: 42 | depends_on: 43 | localstack: 44 | condition: service_healthy 45 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 46 | networks: 47 | - aws 48 | ports: 49 | - "8888" 50 | environment: 51 | AWS_ACCESS_KEY_ID: test 52 | AWS_SECRET_ACCESS_KEY: test 53 | JAVA_OPTS: > 54 | -Dspring.profiles.active=awsparamstore 55 | -Dspring.cloud.config.server.awsparamstore.endpoint=http://localhost.localstack.cloud:4566 56 | -Dspring.cloud.config.server.awsparamstore.region=us-east-1 57 | 58 | 59 | # Configured through command line arguments 60 | config-server-args: 61 | depends_on: 62 | localstack: 63 | condition: service_healthy 64 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 65 | networks: 66 | - aws 67 | ports: 68 | - "8888" 69 | environment: 70 | AWS_ACCESS_KEY_ID: test 71 | AWS_SECRET_ACCESS_KEY: test 72 | command: 73 | - --spring.profiles.active=awsparamstore 74 | - --spring.cloud.config.server.awsparamstore.endpoint=http://localhost.localstack.cloud:4566 75 | - --spring.cloud.config.server.awsparamstore.region=us-east-1 76 | 77 | localstack: 78 | image: localstack/localstack:stable 79 | networks: 80 | aws: 81 | aliases: 82 | - localhost.localstack.cloud 83 | ports: 84 | - "4566:4566" 85 | - "4571:4571" 86 | environment: 87 | AWS_ACCESS_KEY_ID: test 88 | AWS_SECRET_ACCESS_KEY: test 89 | SERVICES: ssm 90 | DEBUG: 1 91 | USE_SINGLE_REGION: 1 92 | healthcheck: 93 | test: ["CMD-SHELL", "awslocal ssm list-documents"] 94 | volumes: 95 | - ./populate-paramstore.sh:/data/populate-paramstore.sh 96 | -------------------------------------------------------------------------------- /examples/aws/paramstore/config/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | server: 5 | awsparamstore: 6 | endpoint: http://localhost.localstack.cloud:4566 7 | region: us-east-1 8 | profiles: 9 | active: awsparamstore -------------------------------------------------------------------------------- /examples/aws/paramstore/populate-paramstore.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | awslocal ssm put-parameter --name /config/application-default/foo --value "default" --type String 3 | awslocal ssm put-parameter --name /config/application-development/bar --value "default" --type String 4 | awslocal ssm put-parameter --name /config/foo-development/foo --value "bar" --type String 5 | awslocal ssm put-parameter --name /config/foo-development/bar --value "foo" --type String 6 | -------------------------------------------------------------------------------- /examples/aws/s3/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | server: 5 | awss3: 6 | endpoint: http://localhost.localstack.cloud:4566 7 | region: us-east-1 8 | bucket: sample-bucket 9 | profiles: 10 | active: awss3 -------------------------------------------------------------------------------- /examples/aws/s3/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing AWS S3 2 | 3 | networks: 4 | aws: 5 | 6 | services: 7 | # Configured through environment variables 8 | config-server-env: 9 | depends_on: 10 | localstack: 11 | condition: service_healthy 12 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 13 | networks: 14 | - aws 15 | ports: 16 | - "8888" 17 | environment: 18 | AWS_ACCESS_KEY_ID: test 19 | AWS_SECRET_ACCESS_KEY: test 20 | SPRING_PROFILES_ACTIVE: awss3 21 | SPRING_CLOUD_CONFIG_SERVER_AWSS3_ENDPOINT: http://localhost.localstack.cloud:4566 22 | SPRING_CLOUD_CONFIG_SERVER_AWSS3_REGION: us-east-1 23 | SPRING_CLOUD_CONFIG_SERVER_AWSS3_BUCKET: sample-bucket 24 | 25 | # Configured through mounted config file 26 | config-server-dir: 27 | depends_on: 28 | localstack: 29 | condition: service_healthy 30 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 31 | networks: 32 | - aws 33 | ports: 34 | - "8888" 35 | environment: 36 | AWS_ACCESS_KEY_ID: test 37 | AWS_SECRET_ACCESS_KEY: test 38 | volumes: 39 | - ./application.yml:/config/application.yml 40 | 41 | # Configured through system properties 42 | config-server-props: 43 | depends_on: 44 | localstack: 45 | condition: service_healthy 46 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 47 | networks: 48 | - aws 49 | ports: 50 | - "8888" 51 | environment: 52 | AWS_ACCESS_KEY_ID: test 53 | AWS_SECRET_ACCESS_KEY: test 54 | JAVA_OPTS: > 55 | -Dspring.profiles.active=awss3 56 | -Dspring.cloud.config.server.awss3.endpoint=http://localhost.localstack.cloud:4566 57 | -Dspring.cloud.config.server.awss3.region=us-east-1 58 | -Dspring.cloud.config.server.awss3.bucket=sample-bucket 59 | 60 | # Configured through command line arguments 61 | config-server-args: 62 | depends_on: 63 | localstack: 64 | condition: service_healthy 65 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 66 | networks: 67 | - aws 68 | ports: 69 | - "8888" 70 | environment: 71 | AWS_ACCESS_KEY_ID: test 72 | AWS_SECRET_ACCESS_KEY: test 73 | command: 74 | - --spring.profiles.active=awss3 75 | - --spring.cloud.config.server.awss3.endpoint=http://localhost.localstack.cloud:4566 76 | - --spring.cloud.config.server.awss3.region=us-east-1 77 | - --spring.cloud.config.server.awss3.bucket=sample-bucket 78 | 79 | localstack: 80 | image: localstack/localstack:stable 81 | networks: 82 | aws: 83 | aliases: 84 | - localhost.localstack.cloud 85 | - sample-bucket.localhost.localstack.cloud 86 | ports: 87 | - "4566:4566" 88 | - "4571:4571" 89 | environment: 90 | AWS_ACCESS_KEY_ID: test 91 | AWS_SECRET_ACCESS_KEY: test 92 | DEBUG: 1 93 | SERVICES: s3 94 | USE_SINGLE_REGION: 1 95 | healthcheck: 96 | test: ["CMD-SHELL", "awslocal s3api create-bucket --bucket test"] 97 | volumes: 98 | - ./config:/data/config 99 | - ./populate-s3.sh:/data/populate-s3.sh 100 | -------------------------------------------------------------------------------- /examples/aws/s3/config/foo-db.yml: -------------------------------------------------------------------------------- 1 | foo.db: mycooldb 2 | -------------------------------------------------------------------------------- /examples/aws/s3/config/foo-dev.yml: -------------------------------------------------------------------------------- 1 | bar: spam 2 | foo: from foo development 3 | democonfigclient.message: hello from dev profile 4 | -------------------------------------------------------------------------------- /examples/aws/s3/config/foo-development-db.yml: -------------------------------------------------------------------------------- 1 | combined: true 2 | -------------------------------------------------------------------------------- /examples/aws/s3/config/foo-development.yml: -------------------------------------------------------------------------------- 1 | bar: spam 2 | foo: from foo development 3 | -------------------------------------------------------------------------------- /examples/aws/s3/config/foo.yml: -------------------------------------------------------------------------------- 1 | foo: from foo props 2 | democonfigclient.message: hello spring io 3 | -------------------------------------------------------------------------------- /examples/aws/s3/populate-s3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | awslocal s3api create-bucket --bucket sample-bucket --region us-east-1 3 | awslocal s3api put-bucket-acl --bucket sample-bucket --acl public-read 4 | awslocal s3api get-bucket-acl --bucket sample-bucket 5 | awslocal s3 cp /data/config/foo.yml s3://sample-bucket/ 6 | awslocal s3 cp /data/config/foo-db.yml s3://sample-bucket/ 7 | awslocal s3 cp /data/config/foo-dev.yml s3://sample-bucket/ 8 | awslocal s3 cp /data/config/foo-development.yml s3://sample-bucket/ 9 | awslocal s3 cp /data/config/foo-development-db.yml s3://sample-bucket/ 10 | awslocal s3 ls s3://sample-bucket/ -------------------------------------------------------------------------------- /examples/aws/secretsmanager/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | server: 5 | aws-secretsmanager: 6 | endpoint: http://localhost.localstack.cloud:4566 7 | region: us-east-1 8 | profiles: 9 | active: awssecretsmanager -------------------------------------------------------------------------------- /examples/aws/secretsmanager/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing AWS S3 2 | 3 | networks: 4 | aws: 5 | 6 | services: 7 | # Configured through environment variables 8 | config-server-env: 9 | depends_on: 10 | localstack: 11 | condition: service_healthy 12 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 13 | networks: 14 | - aws 15 | ports: 16 | - "8888" 17 | environment: 18 | AWS_ACCESS_KEY_ID: test 19 | AWS_SECRET_ACCESS_KEY: test 20 | SPRING_PROFILES_ACTIVE: awssecretsmanager 21 | SPRING_CLOUD_CONFIG_SERVER_AWSSECRETSMANAGER_ENDPOINT: http://localhost.localstack.cloud:4566 22 | SPRING_CLOUD_CONFIG_SERVER_AWSSECRETSMANAGER_REGION: us-east-1 23 | 24 | # Configured through mounted config file 25 | config-server-dir: 26 | depends_on: 27 | localstack: 28 | condition: service_healthy 29 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 30 | networks: 31 | - aws 32 | ports: 33 | - "8888" 34 | environment: 35 | AWS_ACCESS_KEY_ID: test 36 | AWS_SECRET_ACCESS_KEY: test 37 | volumes: 38 | - ./application.yml:/config/application.yml 39 | 40 | # Configured through system properties 41 | config-server-props: 42 | depends_on: 43 | localstack: 44 | condition: service_healthy 45 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 46 | networks: 47 | - aws 48 | ports: 49 | - "8888" 50 | environment: 51 | AWS_ACCESS_KEY_ID: test 52 | AWS_SECRET_ACCESS_KEY: test 53 | JAVA_OPTS: > 54 | -Dspring.profiles.active=awssecretsmanager 55 | -Dspring.cloud.config.server.aws-secretsmanager.endpoint=http://localhost.localstack.cloud:4566 56 | -Dspring.cloud.config.server.aws-secretsmanager.region=us-east-1 57 | 58 | 59 | # Configured through command line arguments 60 | config-server-args: 61 | depends_on: 62 | localstack: 63 | condition: service_healthy 64 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 65 | networks: 66 | - aws 67 | ports: 68 | - "8888" 69 | environment: 70 | AWS_ACCESS_KEY_ID: test 71 | AWS_SECRET_ACCESS_KEY: test 72 | command: 73 | - --spring.profiles.active=awssecretsmanager 74 | - --spring.cloud.config.server.aws-secretsmanager.endpoint=http://localhost.localstack.cloud:4566 75 | - --spring.cloud.config.server.aws-secretsmanager.region=us-east-1 76 | 77 | localstack: 78 | image: localstack/localstack:stable 79 | networks: 80 | aws: 81 | aliases: 82 | - localhost.localstack.cloud 83 | ports: 84 | - "4566:4566" 85 | - "4571:4571" 86 | environment: 87 | AWS_ACCESS_KEY_ID: test 88 | AWS_SECRET_ACCESS_KEY: test 89 | DEBUG: 1 90 | SERVICES: secretsmanager 91 | USE_SINGLE_REGION: 1 92 | healthcheck: 93 | test: ["CMD-SHELL", "awslocal secretsmanager list-secrets"] 94 | volumes: 95 | - ./populate-secretsmanager.sh:/data/populate-secretsmanager.sh 96 | -------------------------------------------------------------------------------- /examples/aws/secretsmanager/populate-secretsmanager.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | awslocal secretsmanager create-secret --name /secret/application-default/ --secret-string '{"foo": "default"}' 3 | awslocal secretsmanager create-secret --name /secret/application-development/ --secret-string '{"bar": "default"}' 4 | awslocal secretsmanager create-secret --name /secret/foo-development/ --secret-string '{"foo": "bar", "bar": "foo"}' 5 | -------------------------------------------------------------------------------- /examples/cloud-bus/kafka/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing Spring Cloud Bus Kafka 2 | 3 | services: 4 | # Configured through environment variables 5 | config-server-env: 6 | depends_on: 7 | - kafka 8 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 9 | networks: 10 | - app-tier 11 | ports: 12 | - "8888" 13 | environment: 14 | MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: "*" 15 | SPRING_PROFILES_ACTIVE: cloud-bus-kafka 16 | SPRING_CLOUD_CONFIG_SERVER_GIT_URI: https://github.com/spring-cloud-samples/config-repo 17 | SPRING_KAFKA_BOOTSTRAP-SERVERS: kafka:9092 18 | 19 | # Configured through mounted config volume 20 | config-server-dir: 21 | depends_on: 22 | - kafka 23 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 24 | networks: 25 | - app-tier 26 | ports: 27 | - "8888" 28 | volumes: 29 | - ./config:/config 30 | 31 | # Configured through system properties 32 | config-server-props: 33 | depends_on: 34 | - kafka 35 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 36 | networks: 37 | - app-tier 38 | ports: 39 | - "8888" 40 | environment: 41 | JAVA_OPTS: > 42 | -Dmanagement.endpoints.web.exposure.include=* 43 | -Dspring.profiles.active=cloud-bus-kafka 44 | -Dspring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo 45 | -Dspring.kafka.bootstrap-servers=kafka:9092 46 | 47 | # Configured through command line arguments 48 | config-server-args: 49 | depends_on: 50 | - kafka 51 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 52 | networks: 53 | - app-tier 54 | command: 55 | - --management.endpoints.web.exposure.include=* 56 | - --spring.profiles.active=cloud-bus-kafka 57 | - --spring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo 58 | - --spring.kafka.bootstrap-servers=kafka:9092 59 | ports: 60 | - "8888" 61 | 62 | kafka: 63 | image: bitnami/kafka:3.6 64 | networks: 65 | - app-tier 66 | ports: 67 | - "9092" 68 | environment: 69 | KAFKA_CFG_NODE_ID: 0 70 | KAFKA_CFG_PROCESS_ROLES: controller,broker 71 | KAFKA_CFG_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093 72 | KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT 73 | KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 0@kafka:9093 74 | KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER 75 | 76 | networks: 77 | app-tier: 78 | driver: bridge -------------------------------------------------------------------------------- /examples/cloud-bus/kafka/config/application.yml: -------------------------------------------------------------------------------- 1 | management: 2 | endpoints: 3 | web: 4 | exposure: 5 | include: "*" 6 | spring: 7 | cloud: 8 | config: 9 | server: 10 | git: 11 | uri: https://github.com/spring-cloud-samples/config-repo 12 | kafka: 13 | bootstrap-servers: kafka:9092 14 | profiles: 15 | active: cloud-bus-kafka 16 | -------------------------------------------------------------------------------- /examples/cloud-bus/rabbit/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing Spring Cloud Bus Kafka 2 | 3 | services: 4 | # Configured through environment variables 5 | config-server-env: 6 | depends_on: 7 | - rabbitmq 8 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 9 | ports: 10 | - "8888" 11 | environment: 12 | MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: "*" 13 | SPRING_PROFILES_ACTIVE: cloud-bus-rabbit 14 | SPRING_CLOUD_CONFIG_SERVER_GIT_URI: https://github.com/spring-cloud-samples/config-repo 15 | SPRING_RABBITMQ_HOST: rabbitmq 16 | 17 | # Configured through mounted config volume 18 | config-server-dir: 19 | depends_on: 20 | - rabbitmq 21 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 22 | ports: 23 | - "8888" 24 | volumes: 25 | - ./config:/config 26 | 27 | # Configured through system properties 28 | config-server-props: 29 | depends_on: 30 | - rabbitmq 31 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 32 | ports: 33 | - "8888" 34 | environment: 35 | JAVA_OPTS: > 36 | -Dmanagement.endpoints.web.exposure.include=* 37 | -Dspring.profiles.active=cloud-bus-rabbit 38 | -Dspring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo 39 | -Dspring.rabbitmq.host=rabbitmq 40 | 41 | # Configured through command line arguments 42 | config-server-args: 43 | depends_on: 44 | - rabbitmq 45 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 46 | command: 47 | - --management.endpoints.web.exposure.include=* 48 | - --spring.profiles.active=cloud-bus-rabbit 49 | - --spring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo 50 | - --spring.rabbitmq.host=rabbitmq 51 | ports: 52 | - "8888" 53 | 54 | rabbitmq: 55 | image: rabbitmq 56 | ports: 57 | - "5672" -------------------------------------------------------------------------------- /examples/cloud-bus/rabbit/config/application.yml: -------------------------------------------------------------------------------- 1 | management: 2 | endpoints: 3 | web: 4 | exposure: 5 | include: "*" 6 | spring: 7 | cloud: 8 | config: 9 | server: 10 | git: 11 | uri: https://github.com/spring-cloud-samples/config-repo 12 | rabbitmq: 13 | host: rabbitmq 14 | profiles: 15 | active: cloud-bus-rabbit 16 | -------------------------------------------------------------------------------- /examples/git/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing a remote git repo 2 | 3 | services: 4 | # Configured through environment variables 5 | config-server-env: 6 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 7 | ports: 8 | - "8888" 9 | environment: 10 | SPRING_CLOUD_CONFIG_SERVER_GIT_URI: https://github.com/spring-cloud-samples/config-repo 11 | volumes: 12 | - ./config:/config 13 | 14 | # Configured through mounted config volume 15 | config-server-dir: 16 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 17 | ports: 18 | - "8888" 19 | volumes: 20 | - ./config:/config 21 | 22 | # Configured through system properties 23 | config-server-props: 24 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 25 | ports: 26 | - "8888" 27 | environment: 28 | JAVA_OPTS: -Dspring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo 29 | 30 | # Configured through command line arguments 31 | config-server-args: 32 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 33 | command: --spring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo 34 | ports: 35 | - "8888" 36 | -------------------------------------------------------------------------------- /examples/git/config/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | server: 5 | git: 6 | uri: https://github.com/spring-cloud-samples/config-repo -------------------------------------------------------------------------------- /examples/healthcheck/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing a remote git repo 2 | 3 | services: 4 | # Configured through environment variables 5 | config-server-env: 6 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 7 | ports: 8 | - "8888" 9 | environment: 10 | SPRING_CLOUD_CONFIG_SERVER_GIT_URI: https://github.com/spring-cloud-samples/config-repo 11 | volumes: 12 | - ./config:/config 13 | healthcheck: 14 | test: ["CMD", "health-check"] 15 | start_interval: 30s 16 | interval: 5s 17 | retries: 10 -------------------------------------------------------------------------------- /examples/jdbc/mariadb/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing MySQL 2 | 3 | services: 4 | # Configured through environment variables 5 | config-server-env: 6 | depends_on: 7 | - mariadb 8 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 9 | ports: 10 | - "8888" 11 | environment: 12 | SPRING_PROFILES_ACTIVE: jdbc 13 | SPRING_CLOUD_CONFIG_SERVER_JDBC_SQL: SELECT `KEY`, VALUE from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=? 14 | SPRING_DATASOURCE_URL: jdbc:mariadb://mariadb:3306/cloud_config 15 | SPRING_DATASOURCE_USERNAME: root 16 | 17 | # Configured through mounted config volume 18 | config-server-dir: 19 | depends_on: 20 | - mariadb 21 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 22 | ports: 23 | - "8888" 24 | volumes: 25 | - ./config:/config 26 | 27 | # Configured through system properties 28 | config-server-props: 29 | depends_on: 30 | - mariadb 31 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 32 | ports: 33 | - "8888" 34 | environment: 35 | JAVA_OPTS: > 36 | -Dspring.profiles.active=jdbc 37 | -Dspring.datasource.url=jdbc:mariadb://mariadb:3306/cloud_config 38 | -Dspring.datasource.username=root 39 | -Dspring.cloud.config.server.jdbc.sql="SELECT `KEY`, VALUE from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=?" 40 | 41 | # Configured through command line arguments 42 | config-server-args: 43 | depends_on: 44 | - mariadb 45 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 46 | command: 47 | - --spring.profiles.active=jdbc 48 | - --spring.cloud.config.server.jdbc.sql=SELECT `KEY`, VALUE from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=? 49 | - --spring.datasource.url=jdbc:mariadb://mariadb:3306/cloud_config 50 | - --spring.datasource.username=root 51 | ports: 52 | - "8888" 53 | 54 | mariadb: 55 | image: mariadb 56 | ports: 57 | - "3306:3306" 58 | environment: 59 | MYSQL_DATABASE: cloud_config 60 | MYSQL_ALLOW_EMPTY_PASSWORD: "yes" 61 | volumes: 62 | - ./init-db.sql:/docker-entrypoint-initdb.d/init-db.sql -------------------------------------------------------------------------------- /examples/jdbc/mariadb/config/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | server: 5 | jdbc: 6 | sql: SELECT `key`, value from PROPERTIES where application=? and profile=? and label=? 7 | datasource: 8 | url: jdbc:mariadb://mariadb:3306/cloud_config 9 | username: root 10 | profiles: 11 | active: jdbc 12 | -------------------------------------------------------------------------------- /examples/jdbc/mariadb/init-db.sql: -------------------------------------------------------------------------------- 1 | create table PROPERTIES( 2 | application varchar(256), 3 | profile varchar(256), 4 | label varchar(256), 5 | `key` varchar(256), 6 | value varchar(256) 7 | ); 8 | 9 | insert into PROPERTIES values ('jdbc-app', 'dev', 'latest', 'sample key', 'a value'); -------------------------------------------------------------------------------- /examples/jdbc/postgres/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing Postgres 2 | 3 | services: 4 | # Configured through environment variables 5 | config-server-env: 6 | depends_on: 7 | - postgres 8 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 9 | ports: 10 | - "8888" 11 | environment: 12 | SPRING_PROFILES_ACTIVE: jdbc 13 | SPRING_CLOUD_CONFIG_SERVER_JDBC_SQL: "SELECT key, value from PROPERTIES where application=? and profile=? and label=?" 14 | SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/cloud_config 15 | SPRING_DATASOURCE_USERNAME: root 16 | SPRING_DATASOURCE_PASSWORD: password 17 | 18 | # Configured through mounted config volume 19 | config-server-dir: 20 | depends_on: 21 | - postgres 22 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 23 | ports: 24 | - "8888" 25 | volumes: 26 | - ./config:/config 27 | 28 | # Configured through system properties 29 | config-server-props: 30 | depends_on: 31 | - postgres 32 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 33 | ports: 34 | - "8888" 35 | environment: 36 | JAVA_OPTS: > 37 | -Dspring.profiles.active=jdbc 38 | -Dspring.cloud.config.server.jdbc.sql="SELECT key, value from PROPERTIES where application=? and profile=? and label=?" 39 | -Dspring.datasource.url=jdbc:postgresql://postgres:5432/cloud_config 40 | -Dspring.datasource.username=root 41 | -Dspring.datasource.password=password 42 | 43 | # Configured through command line arguments 44 | config-server-args: 45 | depends_on: 46 | - postgres 47 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 48 | command: 49 | - --spring.profiles.active=jdbc 50 | - --spring.datasource.url=jdbc:postgresql://postgres:5432/cloud_config 51 | - --spring.datasource.username=root 52 | - --spring.datasource.password=password 53 | - --spring.cloud.config.server.jdbc.sql=SELECT key, value from PROPERTIES where application=? and profile=? and label=? 54 | ports: 55 | - "8888" 56 | 57 | postgres: 58 | image: postgres 59 | ports: 60 | - "5432:5432" 61 | environment: 62 | POSTGRES_USER: root 63 | POSTGRES_PASSWORD: password 64 | POSTGRES_DB: cloud_config 65 | volumes: 66 | - .:/docker-entrypoint-initdb.d 67 | -------------------------------------------------------------------------------- /examples/jdbc/postgres/config/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | server: 5 | jdbc: 6 | sql: SELECT key, value from PROPERTIES where application=? and profile=? and label=? 7 | datasource: 8 | url: jdbc:postgresql://postgres:5432/cloud_config 9 | username: root 10 | password: password 11 | profiles: 12 | active: jdbc 13 | -------------------------------------------------------------------------------- /examples/jdbc/postgres/init-db.sql: -------------------------------------------------------------------------------- 1 | create table properties( 2 | application varchar(256), 3 | profile varchar(256), 4 | label varchar(256), 5 | key varchar(256), 6 | value varchar(256) 7 | ); 8 | 9 | insert into PROPERTIES values ('jdbc-app', 'dev', 'latest', 'sample key', 'a value'); -------------------------------------------------------------------------------- /examples/native/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing a native file system 2 | 3 | services: 4 | # Configured through environment variables 5 | config-server-env: 6 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 7 | ports: 8 | - "8888" 9 | environment: 10 | SPRING_PROFILES_ACTIVE: native 11 | SPRING_CLOUD_CONFIG_SERVER_NATIVE_SEARCHLOCATIONS: /native-files 12 | volumes: 13 | - ./native-files:/native-files 14 | 15 | # Configured through mounted config file 16 | config-server-dir: 17 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 18 | ports: 19 | - "8888" 20 | volumes: 21 | - ./config:/config 22 | - ./native-files:/native-files 23 | 24 | # Configured through system properties 25 | config-server-props: 26 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 27 | ports: 28 | - "8888" 29 | environment: 30 | JAVA_OPTS: -Dspring.profiles.active=native -Dspring.cloud.config.server.native.searchLocations=/native-files 31 | volumes: 32 | - ./native-files:/native-files 33 | 34 | # Configured through command line arguments 35 | config-server-args: 36 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 37 | ports: 38 | - "8888" 39 | command: --spring.profiles.active=native --spring.cloud.config.server.native.searchLocations=/native-files 40 | volumes: 41 | - ./native-files:/native-files 42 | -------------------------------------------------------------------------------- /examples/native/config/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | server: 5 | native: 6 | searchLocations: /native-files 7 | profiles: 8 | active: native -------------------------------------------------------------------------------- /examples/native/native-files/aggregating.yml: -------------------------------------------------------------------------------- 1 | ingredients.threshold: 1000 2 | -------------------------------------------------------------------------------- /examples/native/native-files/application-dev.yml: -------------------------------------------------------------------------------- 1 | my.prop: from application-dev.yml 2 | -------------------------------------------------------------------------------- /examples/native/native-files/application.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyness/spring-cloud-config-server/e06c625f71067b6ad2e9075645a540f30d9aeb11/examples/native/native-files/application.yaml -------------------------------------------------------------------------------- /examples/native/native-files/application.yml: -------------------------------------------------------------------------------- 1 | info: 2 | description: Spring Cloud Samples 3 | url: https://github.com/spring-cloud-samples 4 | eureka: 5 | client: 6 | serviceUrl: 7 | defaultZone: http://localhost:8761/eureka/ 8 | 9 | foo: baz 10 | 11 | --- 12 | spring: 13 | config: 14 | activate-on: 15 | profile: cloud 16 | cloud: 17 | config: 18 | uri: ${vcap.services.${PREFIX:}configserver.credentials.uri:http://user:password@${PREFIX:}configserver.${application.domain:cfapps.io}} 19 | oauth2: 20 | client: 21 | tokenUri: ${vcap.services.${PREFIX:}sso.credentials.tokenUri:} 22 | authorizationUri: ${vcap.services.${PREFIX:}sso.credentials.authorizationUri:} 23 | clientId: ${vcap.services.${PREFIX:}sso.credentials.clientId:} 24 | clientSecret: ${vcap.services.${PREFIX:}sso.credentials.clientSecret:} 25 | resource: 26 | tokenInfoUri: ${vcap.services.${OAUTH2_RESOURCE_SERVICEID:${oauth2.resource.serviceId:sso}}.credentials.tokenInfoUri:} 27 | serviceId: ${PREFIX:}resource 28 | application: 29 | domain: ${APPLICATION_DOMAIN:cfapps.io} 30 | endpoints: 31 | restart: enabled 32 | eureka: 33 | password: password 34 | instance: 35 | hostname: ${vcap.application.uris[0]:localhost} 36 | nonSecurePort: 80 37 | client: 38 | serviceUrl: 39 | defaultZone: ${vcap.services.${PREFIX:}eureka.credentials.uri:http://user:${eureka.password:}@${PREFIX:}eureka.${application.domain:cfapps.io}}/eureka/ 40 | hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000 41 | ribbon: 42 | ConnectTimeout: 3000 43 | ReadTimeout: 60000 44 | 45 | --- 46 | spring: 47 | config: 48 | activate-on: 49 | profile: docker 50 | cloud: 51 | config: 52 | uri: http://${CONFIGSERVER_1_PORT_8888_TCP_ADDR:localhost}:8888 53 | endpoints: 54 | restart: enabled 55 | eureka: 56 | instance: 57 | nonSecurePort: 80 58 | preferIpAddress: true 59 | client: 60 | serviceUrl: 61 | defaultZone: http://${EUREKA_1_PORT_8761_TCP_ADDR:localhost}:8761/eureka/ 62 | 63 | -------------------------------------------------------------------------------- /examples/native/native-files/bar.properties: -------------------------------------------------------------------------------- 1 | foo: bar2 2 | -------------------------------------------------------------------------------- /examples/native/native-files/books.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Gambardella, Matthew 5 | XML Developer's Guide 6 | Computer 7 | 44.95 8 | 2000-10-01 9 | An in-depth look at creating applications 10 | with XML. 11 | 12 | 13 | Ralls, Kim 14 | Midnight Rain 15 | Fantasy 16 | 5.95 17 | 2000-12-16 18 | A former architect battles corporate zombies, 19 | an evil sorceress, and her own childhood to become queen 20 | of the world. 21 | 22 | 23 | Corets, Eva 24 | Maeve Ascendant 25 | Fantasy 26 | 5.95 27 | 2000-11-17 28 | After the collapse of a nanotechnology 29 | society in England, the young survivors lay the 30 | foundation for a new society. 31 | 32 | 33 | Corets, Eva 34 | Oberon's Legacy 35 | Fantasy 36 | 5.95 37 | 2001-03-10 38 | In post-apocalypse England, the mysterious 39 | agent known only as Oberon helps to create a new life 40 | for the inhabitants of London. Sequel to Maeve 41 | Ascendant. 42 | 43 | 44 | Corets, Eva 45 | The Sundered Grail 46 | Fantasy 47 | 5.95 48 | 2001-09-10 49 | The two daughters of Maeve, half-sisters, 50 | battle one another for control of England. Sequel to 51 | Oberon's Legacy. 52 | 53 | 54 | Randall, Cynthia 55 | Lover Birds 56 | Romance 57 | 4.95 58 | 2000-09-02 59 | When Carla meets Paul at an ornithology 60 | conference, tempers fly as feathers get ruffled. 61 | 62 | 63 | Thurman, Paula 64 | Splish Splash 65 | Romance 66 | 4.95 67 | 2000-11-02 68 | A deep sea diver finds true love twenty 69 | thousand leagues beneath the sea. 70 | 71 | 72 | Knorr, Stefan 73 | Creepy Crawlies 74 | Horror 75 | 4.95 76 | 2000-12-06 77 | An anthology of horror stories about roaches, 78 | centipedes, scorpions and other insects. 79 | 80 | 81 | Kress, Peter 82 | Paradox Lost 83 | Science Fiction 84 | 6.95 85 | 2000-11-02 86 | After an inadvertant trip through a Heisenberg 87 | Uncertainty Device, James Salway discovers the problems 88 | of being quantum. 89 | 90 | 91 | O'Brien, Tim 92 | Microsoft .NET: The Programming Bible 93 | Computer 94 | 36.95 95 | 2000-12-09 96 | Microsoft's .NET initiative is explored in 97 | detail in this deep programmer's reference. 98 | 99 | 100 | O'Brien, Tim 101 | MSXML3: A Comprehensive Guide 102 | Computer 103 | 36.95 104 | 2000-12-01 105 | The Microsoft MSXML3 parser is covered in 106 | detail, with attention to XML DOM interfaces, XSLT processing, 107 | SAX and more. 108 | 109 | 110 | Galos, Mike 111 | Visual Studio 7: A Comprehensive Guide 112 | Computer 113 | 49.95 114 | 2001-04-16 115 | Microsoft Visual Studio 7 is explored in depth, 116 | looking at how Visual Basic, Visual C++, C#, and ASP+ are 117 | integrated into a comprehensive development 118 | environment. 119 | 120 | 121 | -------------------------------------------------------------------------------- /examples/native/native-files/configserver.yml: -------------------------------------------------------------------------------- 1 | info.description: configserver 2 | --- 3 | spring: 4 | profiles: cloud 5 | service: 6 | definition: 7 | metadata: 8 | uri: http://${spring.application.name}.${application.domain:cfapps.io} 9 | -------------------------------------------------------------------------------- /examples/native/native-files/eureka.yml: -------------------------------------------------------------------------------- 1 | --- 2 | spring: 3 | profiles: cloudpeers 4 | eureka: 5 | client: 6 | serviceUrl: 7 | defaultZone: ${vcap.services.${PREFIX:}othereureka.credentials.uri:http://${PREFIX:}othereureka.${application.domain:cfapps.io}}/eureka/ 8 | 9 | --- 10 | spring: 11 | profiles: docker 12 | eureka: 13 | client: 14 | serviceUrl: 15 | defaultZone: http://localhost:8761/eureka/ 16 | -------------------------------------------------------------------------------- /examples/native/native-files/foo-db.properties: -------------------------------------------------------------------------------- 1 | foo.db: mycooldb 2 | -------------------------------------------------------------------------------- /examples/native/native-files/foo-dev.yml: -------------------------------------------------------------------------------- 1 | bar: spam 2 | foo: from foo development 3 | democonfigclient.message: hello from dev profile 4 | -------------------------------------------------------------------------------- /examples/native/native-files/foo-development-db.properties: -------------------------------------------------------------------------------- 1 | combined: true 2 | -------------------------------------------------------------------------------- /examples/native/native-files/foo-development.properties: -------------------------------------------------------------------------------- 1 | bar: spam 2 | foo: from foo development 3 | -------------------------------------------------------------------------------- /examples/native/native-files/foo.properties: -------------------------------------------------------------------------------- 1 | foo: from foo props 2 | democonfigclient.message: hello spring io 3 | -------------------------------------------------------------------------------- /examples/native/native-files/logtest.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | com.example: 4 | foo: DEBUG 5 | bar: DEBUG 6 | -------------------------------------------------------------------------------- /examples/native/native-files/processor.yml: -------------------------------------------------------------------------------- 1 | --- 2 | spring: 3 | profiles: cloud 4 | data: 5 | mongodb: 6 | uri: ${vcap.services.${PREFIX:}mongodb.credentials.uri} 7 | demo: 8 | baseUri: http://${eureka.instance.hostname} -------------------------------------------------------------------------------- /examples/native/native-files/samplebackendservice-development.properties: -------------------------------------------------------------------------------- 1 | bar: spam -------------------------------------------------------------------------------- /examples/native/native-files/samplebackendservice.properties: -------------------------------------------------------------------------------- 1 | foo: live from phoenix again 2 | -------------------------------------------------------------------------------- /examples/native/native-files/samplefrontendservice.properties: -------------------------------------------------------------------------------- 1 | foo: bar2 2 | logging.level.org.springframework.web: DEBUG 3 | -------------------------------------------------------------------------------- /examples/native/native-files/stores.yml: -------------------------------------------------------------------------------- 1 | foo: '{cipher}{key:test}AQCST0WVyBi2M5w1KWyzV6DNGXKBgk5Yd9QnbVv4rSj+7HhgsJh5gQTI/CZvV/wHZqYtYrGxJJ3TCdXc/gBP4dbkBDdOEJOq+u7UUqNTOd2693FgOp5CeoMREUOmLp9r0CtF4TZLdjZfs4kxiBPVPd5fEaz9ULIgtgLSdS2oUEg6UXr3LA/M7P8YchkEPYUyf+VxGUDe587XPffHMU4zmvhmoTSen9BAc5BuGK+FZ3GFe12MDEPkNQ0uY002FitEfmgON65Xh3eJtNxCbUXJTj+oDc0icePqOgnG0gc17MymZdcJCIhP+cCiS6LzS57vhP+xGZvBBBHnw00ZVzHX73UfKkC9GLsnEVVQO5Xf2COR/rGZqvLJNKgvSHcbf03PrhQ=' 2 | --- 3 | spring: 4 | profiles: cloud 5 | data: 6 | mongodb: 7 | uri: ${vcap.services.${PREFIX:}mongodb.credentials.uri} 8 | -------------------------------------------------------------------------------- /examples/native/native-files/subdir/test.txt: -------------------------------------------------------------------------------- 1 | This is text served from a subdirectory 2 | -------------------------------------------------------------------------------- /examples/native/native-files/test.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "_id": "56f051673a6f1037be9a3ccb", 4 | "index": 0, 5 | "guid": "2b403b4b-8b4f-4bf4-8fc0-c957e9c92596", 6 | "isActive": true, 7 | "balance": "$2,210.39", 8 | "picture": "http://placehold.it/32x32", 9 | "age": 25, 10 | "eyeColor": "blue", 11 | "name": { 12 | "first": "Audra", 13 | "last": "Mendez" 14 | }, 15 | "company": "NEXGENE", 16 | "email": "audra.mendez@nexgene.io", 17 | "phone": "+1 (812) 461-2870", 18 | "address": "715 Ebony Court, Logan, New Hampshire, 9176", 19 | "about": "Sit deserunt nulla nulla incididunt et dolor anim eiusmod exercitation. Dolore dolor elit laborum aliquip esse amet id. Est ipsum sit voluptate duis cillum ut tempor ipsum pariatur adipisicing sunt. Consequat officia ut tempor id et reprehenderit et veniam ullamco anim qui sint aliquip tempor. Cillum laborum veniam ullamco enim consectetur veniam quis dolor nostrud officia.", 20 | "registered": "Tuesday, February 18, 2014 6:54 PM", 21 | "latitude": "-54.035224", 22 | "longitude": "-18.578621", 23 | "tags": [ 24 | 7, 25 | "irure" 26 | ], 27 | "range": [ 28 | 0, 29 | 1, 30 | 2, 31 | 3, 32 | 4, 33 | 5, 34 | 6, 35 | 7, 36 | 8, 37 | 9 38 | ], 39 | "friends": [ 40 | 3, 41 | { 42 | "id": 1, 43 | "name": "Hillary Hutchinson" 44 | } 45 | ], 46 | "greeting": "Hello, Audra! You have 9 unread messages.", 47 | "favoriteFruit": "apple" 48 | }, 49 | { 50 | "_id": "56f0516768d43b3ea3b7561f", 51 | "index": 1, 52 | "guid": "cbc8e72f-511b-406b-b3c8-d44a5ea78f2f", 53 | "isActive": true, 54 | "balance": "$3,096.58", 55 | "picture": "http://placehold.it/32x32", 56 | "age": 26, 57 | "eyeColor": "blue", 58 | "name": { 59 | "first": "Merle", 60 | "last": "Wooten" 61 | }, 62 | "company": "EDECINE", 63 | "email": "merle.wooten@edecine.ca", 64 | "phone": "+1 (842) 447-2285", 65 | "address": "142 Hendrix Street, Bartley, Arizona, 5777", 66 | "about": "Ea sunt veniam labore qui ad. Sint nisi aliqua laborum dolor do voluptate cupidatat eu. Enim deserunt anim excepteur enim labore et nostrud elit consectetur excepteur nostrud aliquip dolor adipisicing. Irure aliquip incididunt proident culpa.", 67 | "registered": "Thursday, April 10, 2014 4:58 AM", 68 | "latitude": "-8.395754", 69 | "longitude": "75.771414", 70 | "tags": [ 71 | 7, 72 | "irure" 73 | ], 74 | "range": [ 75 | 0, 76 | 1, 77 | 2, 78 | 3, 79 | 4, 80 | 5, 81 | 6, 82 | 7, 83 | 8, 84 | 9 85 | ], 86 | "friends": [ 87 | 3, 88 | { 89 | "id": 1, 90 | "name": "Hillary Hutchinson" 91 | } 92 | ], 93 | "greeting": "Hello, Merle! You have 5 unread messages.", 94 | "favoriteFruit": "strawberry" 95 | }, 96 | { 97 | "_id": "56f05167d299eab579202f1e", 98 | "index": 2, 99 | "guid": "46f24b5b-f8e3-486b-8b3a-0b0784f513d9", 100 | "isActive": true, 101 | "balance": "$3,437.48", 102 | "picture": "http://placehold.it/32x32", 103 | "age": 39, 104 | "eyeColor": "green", 105 | "name": { 106 | "first": "Lupe", 107 | "last": "Lewis" 108 | }, 109 | "company": "HOMELUX", 110 | "email": "lupe.lewis@homelux.me", 111 | "phone": "+1 (877) 548-3554", 112 | "address": "146 Terrace Place, Derwood, Pennsylvania, 2599", 113 | "about": "Aute sint id aliqua ipsum consectetur exercitation nisi. Minim ex laborum eu do. Sunt laborum enim deserunt culpa aliqua eu consectetur.", 114 | "registered": "Sunday, April 12, 2015 2:47 PM", 115 | "latitude": "-45.907896", 116 | "longitude": "-128.202572", 117 | "tags": [ 118 | 7, 119 | "irure" 120 | ], 121 | "range": [ 122 | 0, 123 | 1, 124 | 2, 125 | 3, 126 | 4, 127 | 5, 128 | 6, 129 | 7, 130 | 8, 131 | 9 132 | ], 133 | "friends": [ 134 | 3, 135 | { 136 | "id": 1, 137 | "name": "Hillary Hutchinson" 138 | } 139 | ], 140 | "greeting": "Hello, Lupe! You have 5 unread messages.", 141 | "favoriteFruit": "strawberry" 142 | }, 143 | { 144 | "_id": "56f05167aaf3df75213406b1", 145 | "index": 3, 146 | "guid": "c9f2570b-76c5-4326-809e-fb7797e0d1cc", 147 | "isActive": false, 148 | "balance": "$1,543.14", 149 | "picture": "http://placehold.it/32x32", 150 | "age": 34, 151 | "eyeColor": "blue", 152 | "name": { 153 | "first": "Swanson", 154 | "last": "Mccarthy" 155 | }, 156 | "company": "MITROC", 157 | "email": "swanson.mccarthy@mitroc.co.uk", 158 | "phone": "+1 (954) 466-3219", 159 | "address": "420 Merit Court, Frystown, Oregon, 4940", 160 | "about": "Culpa incididunt adipisicing nostrud velit in veniam officia. Consequat voluptate mollit tempor eu velit aliqua commodo nulla nisi irure. Velit non incididunt amet proident deserunt officia velit cillum. Non exercitation veniam commodo deserunt Lorem velit incididunt ullamco dolor eu est consectetur. Commodo aliqua in minim minim eu. Labore sunt non aute tempor elit ut tempor deserunt.", 161 | "registered": "Thursday, November 19, 2015 5:44 PM", 162 | "latitude": "29.438056", 163 | "longitude": "-5.197729", 164 | "tags": [ 165 | 7, 166 | "irure" 167 | ], 168 | "range": [ 169 | 0, 170 | 1, 171 | 2, 172 | 3, 173 | 4, 174 | 5, 175 | 6, 176 | 7, 177 | 8, 178 | 9 179 | ], 180 | "friends": [ 181 | 3, 182 | { 183 | "id": 1, 184 | "name": "Hillary Hutchinson" 185 | } 186 | ], 187 | "greeting": "Hello, Swanson! You have 10 unread messages.", 188 | "favoriteFruit": "banana" 189 | }, 190 | { 191 | "_id": "56f051675b6417531450dd6f", 192 | "index": 4, 193 | "guid": "40b284d8-00a3-4778-8215-4781e3ed5df3", 194 | "isActive": true, 195 | "balance": "$2,520.39", 196 | "picture": "http://placehold.it/32x32", 197 | "age": 24, 198 | "eyeColor": "blue", 199 | "name": { 200 | "first": "Casey", 201 | "last": "Dotson" 202 | }, 203 | "company": "IMKAN", 204 | "email": "casey.dotson@imkan.biz", 205 | "phone": "+1 (853) 506-2464", 206 | "address": "881 Sedgwick Street, Goodville, Hawaii, 7857", 207 | "about": "Officia exercitation aliqua anim deserunt sint. Elit incididunt laboris deserunt dolor sit veniam Lorem. Laboris anim non ad sint pariatur veniam cupidatat. Enim in quis reprehenderit ex amet laboris ea tempor. Labore laboris voluptate ipsum tempor sunt esse velit ex nisi. Minim sit pariatur Lorem elit occaecat.", 208 | "registered": "Saturday, August 15, 2015 8:30 PM", 209 | "latitude": "-58.150569", 210 | "longitude": "164.512045", 211 | "tags": [ 212 | 7, 213 | "irure" 214 | ], 215 | "range": [ 216 | 0, 217 | 1, 218 | 2, 219 | 3, 220 | 4, 221 | 5, 222 | 6, 223 | 7, 224 | 8, 225 | 9 226 | ], 227 | "friends": [ 228 | 3, 229 | { 230 | "id": 1, 231 | "name": "Hillary Hutchinson" 232 | } 233 | ], 234 | "greeting": "Hello, Casey! You have 10 unread messages.", 235 | "favoriteFruit": "apple" 236 | } 237 | ] 238 | -------------------------------------------------------------------------------- /examples/native/native-files/text-resource.txt: -------------------------------------------------------------------------------- 1 | Hello Toronto 2 | -------------------------------------------------------------------------------- /examples/native/native-files/zuul.properties: -------------------------------------------------------------------------------- 1 | zuul.route.samplebackendservice=/hello 2 | zuul.route.samplefrontendservice=/ 3 | zuul.route.hystrixdashboard=/hystrix-dashboard 4 | -------------------------------------------------------------------------------- /examples/prometheus/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing a remote git repo 2 | 3 | services: 4 | # Configured through environment variables 5 | config-server-env: 6 | image: ${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest} 7 | ports: 8 | - "8888" 9 | environment: 10 | MANAGEMENT_ENDPOINT_PROMETHEUS_ENABLED: "true" 11 | MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: health,prometheus 12 | SPRING_CLOUD_CONFIG_SERVER_GIT_URI: https://github.com/spring-cloud-samples/config-repo 13 | 14 | # Configured through mounted config volume 15 | config-server-dir: 16 | image: ${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest} 17 | ports: 18 | - "8888" 19 | volumes: 20 | - ./config:/config 21 | 22 | # Configured through system properties 23 | config-server-props: 24 | image: ${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest} 25 | ports: 26 | - "8888" 27 | environment: 28 | JAVA_OPTS: > 29 | -Dmanagement.endpoint.prometheus.enabled=true 30 | -Dmanagement.endpoints.web.exposure.include=health,prometheus 31 | -Dspring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo 32 | 33 | # Configured through command line arguments 34 | config-server-args: 35 | image: ${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest} 36 | ports: 37 | - "8888" 38 | command: 39 | - --management.endpoint.prometheus.enabled=true 40 | - --management.endpoints.web.exposure.include=health,prometheus 41 | - --spring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo 42 | -------------------------------------------------------------------------------- /examples/prometheus/config/application.yml: -------------------------------------------------------------------------------- 1 | management: 2 | endpoints: 3 | web: 4 | exposure: 5 | include: health,prometheus 6 | spring: 7 | cloud: 8 | config: 9 | server: 10 | git: 11 | default-label: main 12 | uri: https://github.com/spring-cloud-samples/config-repo -------------------------------------------------------------------------------- /examples/redis/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing a redis backed repo 2 | 3 | services: 4 | # Configured through environment variables 5 | config-server-env: 6 | depends_on: 7 | - redis 8 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 9 | ports: 10 | - "8888" 11 | environment: 12 | SPRING_PROFILES_ACTIVE: redis 13 | SPRING_DATA_REDIS_HOST: redis 14 | 15 | # Configured through mounted config volume 16 | config-server-dir: 17 | depends_on: 18 | - redis 19 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 20 | ports: 21 | - "8888" 22 | volumes: 23 | - ./config:/config 24 | 25 | # Configured through system properties 26 | config-server-props: 27 | depends_on: 28 | - redis 29 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 30 | ports: 31 | - "8888" 32 | environment: 33 | JAVA_OPTS: > 34 | -Dspring.profiles.active=redis 35 | -Dspring.data.redis.host=redis 36 | 37 | # Configured through command line arguments 38 | config-server-args: 39 | depends_on: 40 | - redis 41 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 42 | ports: 43 | - "8888" 44 | command: 45 | - --spring.profiles.active=redis 46 | - --spring.data.redis.host=redis 47 | 48 | redis: 49 | image: redis:alpine 50 | ports: 51 | - "6379:6379" 52 | volumes: 53 | - ./populate-redis.sh:/data/populate-redis.sh 54 | -------------------------------------------------------------------------------- /examples/redis/config/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | data: 3 | redis: 4 | host: redis 5 | profiles: 6 | active: redis 7 | -------------------------------------------------------------------------------- /examples/redis/populate-redis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo 'HMSET redis-app-development server.port "8100" redis.topic.name "test" test.property1 "property1"' | redis-cli 3 | -------------------------------------------------------------------------------- /examples/security/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing security with a remote git repo 2 | 3 | services: 4 | # Configured through environment variables 5 | config-server-env: 6 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 7 | ports: 8 | - "8888" 9 | environment: 10 | ENCRYPT_KEY: vprxxl5blpycu3kt8602 11 | SPRING_CLOUD_CONFIG_SERVER_GIT_URI: https://github.com/spring-cloud-samples/config-repo 12 | SPRING_PROFILES_ACTIVE: git,security 13 | SPRING_SECURITY_USER_NAME: user 14 | SPRING_SECURITY_USER_PASSWORD: password 15 | volumes: 16 | - ./config:/config 17 | 18 | # Configured through mounted config volume 19 | config-server-dir: 20 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 21 | ports: 22 | - "8888" 23 | volumes: 24 | - ./config:/config 25 | 26 | # Configured through system properties 27 | config-server-props: 28 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 29 | ports: 30 | - "8888" 31 | environment: 32 | JAVA_OPTS: > 33 | -Dencrypt.key=vprxxl5blpycu3kt8602 34 | -Dspring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo 35 | -Dspring.profiles.active=git,security 36 | -Dspring_security.user.name=user 37 | -Dspring.security.user.password=password 38 | 39 | # Configured through command line arguments 40 | config-server-args: 41 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 42 | ports: 43 | - "8888" 44 | command: 45 | - --encrypt.key=vprxxl5blpycu3kt8602 46 | - --spring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo 47 | - --spring.profiles.active=git,security 48 | - --spring_security.user.name=user 49 | - --spring.security.user.password=password 50 | -------------------------------------------------------------------------------- /examples/security/config/application.yml: -------------------------------------------------------------------------------- 1 | encrypt: 2 | key: vprxxl5blpycu3kt8602 3 | spring: 4 | cloud: 5 | config: 6 | server: 7 | git: 8 | uri: https://github.com/spring-cloud-samples/config-repo 9 | profiles: 10 | active: git,security 11 | security: 12 | user: 13 | name: user 14 | password: password -------------------------------------------------------------------------------- /examples/vault/compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose example for testing Vault 2 | 3 | services: 4 | # Configured through environment variables 5 | config-server-env: 6 | depends_on: 7 | - vault 8 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 9 | ports: 10 | - "8888" 11 | environment: 12 | SPRING_PROFILES_ACTIVE: vault 13 | SPRING_CLOUD_CONFIG_SERVER_VAULT_TOKEN: 00000000-0000-0000-0000-000000000000 14 | SPRING_CLOUD_CONFIG_SERVER_VAULT_HOST: vault 15 | SPRING_CLOUD_CONFIG_SERVER_VAULT_KV_VERSION: 2 16 | 17 | # Configured through mounted config volume 18 | config-server-dir: 19 | depends_on: 20 | - vault 21 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 22 | ports: 23 | - "8888" 24 | volumes: 25 | - ./config:/config 26 | 27 | # Configured through system properties 28 | config-server-props: 29 | depends_on: 30 | - vault 31 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 32 | ports: 33 | - "8888" 34 | environment: 35 | JAVA_OPTS: > 36 | -Dspring.profiles.active=vault 37 | -Dspring.cloud.config.server.vault.token=00000000-0000-0000-0000-000000000000 38 | -Dspring.cloud.config.server.vault.host=vault 39 | -Dspring.cloud.config.server.vault.kv-version=2 40 | 41 | # Configured through command line arguments 42 | config-server-args: 43 | depends_on: 44 | - vault 45 | image: "${REGISTRY:-docker.io}/${IMAGE_NAME:-hyness/spring-cloud-config-server}:${TAG:-latest}" 46 | ports: 47 | - "8888" 48 | command: 49 | - --spring.profiles.active=vault 50 | - --spring.cloud.config.server.vault.token=00000000-0000-0000-0000-000000000000 51 | - --spring.cloud.config.server.vault.host=vault 52 | - --spring.cloud.config.server.vault.kv-version=2 53 | 54 | vault: 55 | privileged: true 56 | image: hashicorp/vault 57 | ports: 58 | - "8200:8200" 59 | environment: 60 | - VAULT_DEV_ROOT_TOKEN_ID=00000000-0000-0000-0000-000000000000 61 | - VAULT_TOKEN=00000000-0000-0000-0000-000000000000 62 | - VAULT_ADDR=http://127.0.0.1:8200 63 | volumes: 64 | - ./populate-vault.sh:/data/populate-vault.sh 65 | -------------------------------------------------------------------------------- /examples/vault/config/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | server: 5 | vault: 6 | token: 00000000-0000-0000-0000-000000000000 7 | host: vault 8 | kv-version: 2 9 | profiles: 10 | active: vault 11 | -------------------------------------------------------------------------------- /examples/vault/populate-vault.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | vault kv put secret/application foo=bar baz=bam 3 | vault kv put secret/myapp foo=myappsbar 4 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | jdkVersion = 17 2 | jvmType = jre 3 | dockerUsername = user 4 | dockerPassword = password 5 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | aws = "2.17.195" 3 | aws-msk-iam-auth = "2.3.0" 4 | kotlin = "1.9.25" 5 | kotlin-logging = "7.0.4" 6 | spring-boot = "3.4.4" 7 | spring-cloud = "2024.0.1" 8 | spring-cloud-config = "4.2.2" 9 | 10 | [plugins] 11 | kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } 12 | kotlin-plugin-spring = { id = "org.jetbrains.kotlin.plugin.spring", version.ref = "kotlin" } 13 | spring-boot = { id = "org.springframework.boot", version.ref = "spring-boot" } 14 | 15 | [bundles] 16 | aws = ["aws-msk-iam-auth", "aws-s3", "aws-secretsmanager", "aws-ssm", "aws-sts"] 17 | jdbc-drivers = ["jdbc-driver-firebird", "jdbc-driver-hikari", "jdbc-driver-mariadb", "jdbc-driver-mssql", "jdbc-driver-postgres"] 18 | kotlin = ["kotlin-reflect", "kotlin-stdlib"] 19 | spring-cloud-bus = ["spring-cloud-bus", "spring-cloud-bus-kafka", "spring-cloud-bus-amqp"] 20 | spring-cloud-config = ["spring-cloud-config-server", "spring-cloud-config-monitor"] 21 | 22 | [libraries] 23 | aws-msk-iam-auth = { module = "software.amazon.msk:aws-msk-iam-auth", version.ref = "aws-msk-iam-auth" } 24 | aws-s3 = { module = "software.amazon.awssdk:s3", version.ref = "aws" } 25 | aws-secretsmanager = { module = "software.amazon.awssdk:secretsmanager", version.ref = "aws" } 26 | aws-ssm = { module = "software.amazon.awssdk:ssm", version.ref = "aws" } 27 | aws-sts = { module = "software.amazon.awssdk:sts", version.ref = "aws" } 28 | awaitility-kotlin = { module = "org.awaitility:awaitility-kotlin" } 29 | jdbc-driver-firebird = { module = "org.firebirdsql.jdbc:jaybird" } 30 | jdbc-driver-hikari = { module = "com.zaxxer:HikariCP" } 31 | jdbc-driver-mariadb = { module = "org.mariadb.jdbc:mariadb-java-client" } 32 | jdbc-driver-mssql = { module = "com.microsoft.sqlserver:mssql-jdbc" } 33 | jdbc-driver-postgres = { module = "org.postgresql:postgresql" } 34 | kotlin-logging = { module = "io.github.oshai:kotlin-logging-jvm", version.ref = "kotlin-logging" } 35 | kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect" } 36 | kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib" } 37 | micrometer-prometheus = { module = "io.micrometer:micrometer-registry-prometheus" } 38 | spring-boot-actuator = { module = "org.springframework.boot:spring-boot-starter-actuator" } 39 | spring-boot-security = { module = "org.springframework.boot:spring-boot-starter-security" } 40 | spring-boot-test = { module = "org.springframework.boot:spring-boot-starter-test" } 41 | spring-boot-testcontainers = { module = "org.springframework.boot:spring-boot-testcontainers" } 42 | spring-data-redis = { module = "org.springframework.boot:spring-boot-starter-data-redis" } 43 | spring-cloud = { module = "org.springframework.cloud:spring-cloud-dependencies", version.ref = "spring-cloud" } 44 | spring-cloud-bus = { module = "org.springframework.cloud:spring-cloud-bus" } 45 | spring-cloud-bus-amqp = { module = "org.springframework.cloud:spring-cloud-starter-bus-amqp" } 46 | spring-cloud-bus-kafka = { module = "org.springframework.cloud:spring-cloud-starter-bus-kafka" } 47 | spring-cloud-config-monitor = { module = "org.springframework.cloud:spring-cloud-config-monitor", version.ref = "spring-cloud-config" } 48 | spring-cloud-config-server = { module = "org.springframework.cloud:spring-cloud-config-server", version.ref = "spring-cloud-config" } 49 | spring-jdbc = { module = "org.springframework:spring-jdbc" } 50 | spring-vault = { module = "org.springframework.vault:spring-vault-core" } 51 | testcontainers-junit5 = { module = "org.testcontainers:junit-jupiter" } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyness/spring-cloud-config-server/e06c625f71067b6ad2e9075645a540f30d9aeb11/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | if ! command -v java >/dev/null 2>&1 137 | then 138 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 139 | 140 | Please set the JAVA_HOME variable in your environment to match the 141 | location of your Java installation." 142 | fi 143 | fi 144 | 145 | # Increase the maximum file descriptors if we can. 146 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 147 | case $MAX_FD in #( 148 | max*) 149 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 150 | # shellcheck disable=SC2039,SC3045 151 | MAX_FD=$( ulimit -H -n ) || 152 | warn "Could not query maximum file descriptor limit" 153 | esac 154 | case $MAX_FD in #( 155 | '' | soft) :;; #( 156 | *) 157 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 158 | # shellcheck disable=SC2039,SC3045 159 | ulimit -n "$MAX_FD" || 160 | warn "Could not set maximum file descriptor limit to $MAX_FD" 161 | esac 162 | fi 163 | 164 | # Collect all arguments for the java command, stacking in reverse order: 165 | # * args from the command line 166 | # * the main class name 167 | # * -classpath 168 | # * -D...appname settings 169 | # * --module-path (only if needed) 170 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 171 | 172 | # For Cygwin or MSYS, switch paths to Windows format before running java 173 | if "$cygwin" || "$msys" ; then 174 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 175 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 176 | 177 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 178 | 179 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 180 | for arg do 181 | if 182 | case $arg in #( 183 | -*) false ;; # don't mess with options #( 184 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 185 | [ -e "$t" ] ;; #( 186 | *) false ;; 187 | esac 188 | then 189 | arg=$( cygpath --path --ignore --mixed "$arg" ) 190 | fi 191 | # Roll the args list around exactly as many times as the number of 192 | # args, so each arg winds up back in the position where it started, but 193 | # possibly modified. 194 | # 195 | # NB: a `for` loop captures its iteration list before it begins, so 196 | # changing the positional parameters here affects neither the number of 197 | # iterations, nor the values presented in `arg`. 198 | shift # remove old arg 199 | set -- "$@" "$arg" # push replacement arg 200 | done 201 | fi 202 | 203 | 204 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 205 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 206 | 207 | # Collect all arguments for the java command: 208 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 209 | # and any embedded shellness will be escaped. 210 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 211 | # treated as '${Hostname}' itself on the command line. 212 | 213 | set -- \ 214 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 215 | -classpath "$CLASSPATH" \ 216 | org.gradle.wrapper.GradleWrapperMain \ 217 | "$@" 218 | 219 | # Stop when "xargs" is not available. 220 | if ! command -v xargs >/dev/null 2>&1 221 | then 222 | die "xargs is not available" 223 | fi 224 | 225 | # Use "xargs" to parse quoted args. 226 | # 227 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 228 | # 229 | # In Bash we could simply go: 230 | # 231 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 232 | # set -- "${ARGS[@]}" "$@" 233 | # 234 | # but POSIX shell has neither arrays nor command substitution, so instead we 235 | # post-process each arg (as a line of input to sed) to backslash-escape any 236 | # character that might be a shell metacharacter, then use eval to reverse 237 | # that process (while maintaining the separation between arguments), and wrap 238 | # the whole thing up as a single "set" statement. 239 | # 240 | # This will of course break if any of these variables contains a newline or 241 | # an unmatched quote. 242 | # 243 | 244 | eval "set -- $( 245 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 246 | xargs -n1 | 247 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 248 | tr '\n' ' ' 249 | )" '"$@"' 250 | 251 | exec "$JAVACMD" "$@" 252 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /project.toml: -------------------------------------------------------------------------------- 1 | [[build.env]] 2 | NAME="BPE_DELIM_JAVA_TOOL_OPTIONS" 3 | VALUE=" " 4 | 5 | [[build.env]] 6 | NAME="BPE_PREPEND_JAVA_TOOL_OPTIONS" 7 | VALUE="-Dserver.port=8888 -Dspring.config.name=application -Dspring.config.additional-location=optional:file:/config/ -Dspring.cloud.config.server.native.searchLocations=classpath:/,classpath:/config,file:./,file:./config,file:/config" 8 | -------------------------------------------------------------------------------- /src/main/kotlin/org/freshlegacycode/cloud/config/server/ConfigServerApplication.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest 4 | import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration 5 | import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration 6 | import org.springframework.boot.actuate.health.HealthEndpoint 7 | import org.springframework.boot.autoconfigure.SpringBootApplication 8 | import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration 9 | import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration 10 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration 11 | import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration 12 | import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration 13 | import org.springframework.boot.context.properties.ConfigurationProperties 14 | import org.springframework.boot.context.properties.EnableConfigurationProperties 15 | import org.springframework.boot.runApplication 16 | import org.springframework.cloud.bus.* 17 | import org.springframework.cloud.bus.jackson.BusJacksonAutoConfiguration 18 | import org.springframework.cloud.config.monitor.EnvironmentMonitorAutoConfiguration 19 | import org.springframework.cloud.config.server.EnableConfigServer 20 | import org.springframework.context.annotation.Bean 21 | import org.springframework.context.annotation.Configuration 22 | import org.springframework.context.annotation.Import 23 | import org.springframework.context.annotation.Profile 24 | import org.springframework.security.config.annotation.web.builders.HttpSecurity 25 | import org.springframework.security.config.annotation.web.invoke 26 | import org.springframework.security.web.SecurityFilterChain 27 | import org.springframework.cloud.stream.binder.kafka.config.ExtendedBindingHandlerMappingsProviderConfiguration as KafkaBinderAutoConfiguration 28 | import org.springframework.cloud.stream.binder.rabbit.config.ExtendedBindingHandlerMappingsProviderConfiguration as RabbitBinderAutoConfiguration 29 | 30 | @EnableConfigServer 31 | @SpringBootApplication(exclude = [ 32 | DataSourceAutoConfiguration::class, 33 | RedisAutoConfiguration::class, 34 | ManagementContextAutoConfiguration::class, 35 | ManagementWebSecurityAutoConfiguration::class, 36 | SecurityAutoConfiguration::class, 37 | RabbitBinderAutoConfiguration::class, 38 | KafkaBinderAutoConfiguration::class, 39 | BusAutoConfiguration::class, 40 | PathServiceMatcherAutoConfiguration::class, 41 | BusAutoConfiguration::class, 42 | BusRefreshAutoConfiguration::class, 43 | BusShutdownAutoConfiguration::class, 44 | BusStreamAutoConfiguration::class, 45 | BusJacksonAutoConfiguration::class, 46 | EnvironmentMonitorAutoConfiguration::class, 47 | KafkaAutoConfiguration::class, 48 | RabbitAutoConfiguration::class, 49 | ]) 50 | class ConfigServerApplication 51 | 52 | @Profile("!no-actuator") 53 | @Configuration 54 | @Import(ManagementContextAutoConfiguration::class) 55 | internal class ActuatorBackendConfiguration 56 | 57 | @Profile("jdbc") 58 | @Configuration 59 | @Import(DataSourceAutoConfiguration::class) 60 | internal class JdbcBackendConfiguration 61 | 62 | @Profile("cloud-bus-kafka") 63 | @Configuration 64 | @Import(KafkaAutoConfiguration::class, KafkaBinderAutoConfiguration::class) 65 | internal class CloudBusKafkaConfiguration : CloudBusConfiguration() 66 | 67 | @Profile("cloud-bus-rabbit") 68 | @Configuration 69 | @Import(RabbitAutoConfiguration::class, RabbitBinderAutoConfiguration::class) 70 | internal class CloudBusRabbitConfiguration : CloudBusConfiguration() 71 | 72 | @Import(BusAutoConfiguration::class, 73 | BusRefreshAutoConfiguration::class, 74 | BusShutdownAutoConfiguration::class, 75 | BusStreamAutoConfiguration::class, 76 | BusJacksonAutoConfiguration::class, 77 | PathServiceMatcherAutoConfiguration::class, 78 | EnvironmentMonitorAutoConfiguration::class) 79 | internal abstract class CloudBusConfiguration 80 | 81 | @Profile("redis") 82 | @Configuration 83 | @Import(RedisAutoConfiguration::class) 84 | internal class RedisBackendConfiguration 85 | 86 | @Profile("security") 87 | @Configuration 88 | @Import(SecurityAutoConfiguration::class, ManagementWebSecurityAutoConfiguration::class) 89 | internal class SecurityConfiguration 90 | 91 | @Profile("security") 92 | @Configuration 93 | @EnableConfigurationProperties(ConfigServerSecurityProperties::class) 94 | class ConfigServerSecurityConfiguration(val properties: ConfigServerSecurityProperties) { 95 | @Bean 96 | fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { 97 | http { 98 | authorizeHttpRequests { 99 | authorize(EndpointRequest.to(HealthEndpoint::class.java), permitAll) 100 | properties.allowedPaths.forEach { 101 | authorize(it, permitAll) 102 | } 103 | authorize(anyRequest, authenticated) 104 | } 105 | formLogin {} 106 | httpBasic {} 107 | csrf { 108 | disable() 109 | } 110 | } 111 | return http.build() 112 | } 113 | } 114 | 115 | @ConfigurationProperties("spring.cloud.config.security") 116 | data class ConfigServerSecurityProperties(val allowedPaths: List = listOf()) 117 | 118 | fun main(args: Array) { 119 | runApplication(*args) 120 | } 121 | -------------------------------------------------------------------------------- /src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8888 3 | --- 4 | spring: 5 | cloud: 6 | stream: 7 | defaultBinder: rabbit 8 | config: 9 | activate: 10 | on-profile: cloud-bus-rabbit 11 | --- 12 | spring: 13 | cloud: 14 | stream: 15 | defaultBinder: kafka 16 | config: 17 | activate: 18 | on-profile: cloud-bus-kafka 19 | -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/AwsParamStoreBackendTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.assertj.core.api.Assertions.assertThat 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.containerTimeout 5 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logConsumer 6 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 7 | import org.junit.jupiter.api.BeforeAll 8 | import org.junit.jupiter.api.Tag 9 | import org.junit.jupiter.api.Tags 10 | import org.junit.jupiter.params.ParameterizedTest 11 | import org.junit.jupiter.params.provider.EnumSource 12 | import org.springframework.http.MediaType.APPLICATION_JSON 13 | import org.springframework.test.web.reactive.server.WebTestClient 14 | import org.testcontainers.containers.ComposeContainer 15 | import org.testcontainers.containers.wait.strategy.Wait 16 | import org.testcontainers.junit.jupiter.Container 17 | import org.testcontainers.junit.jupiter.Testcontainers 18 | import kotlin.jvm.optionals.getOrNull 19 | 20 | @Testcontainers 21 | @Tags(Tag("integration"), Tag("aws"), Tag("aws-param-store")) 22 | class AwsParamStoreBackendTest { 23 | @EnumSource 24 | @ParameterizedTest 25 | internal fun `given a config server, when configured with aws parameter store backend, is valid`(type: ContainerConfigurationType) { 26 | logger.info { "Verifying ${type.label}" } 27 | val webClient = WebTestClient.bindToServer() 28 | .baseUrl(cloudConfigContainer.getUrl(type)) 29 | .responseTimeout(containerTimeout) 30 | .build() 31 | 32 | webClient.get() 33 | .uri("/foo/development") 34 | .accept(APPLICATION_JSON) 35 | .exchange() 36 | .expectStatus().isOk 37 | .expectHeader().contentType(APPLICATION_JSON) 38 | .expectBody() 39 | .jsonPath("$.name").isEqualTo("foo") 40 | .jsonPath("$.propertySources[0].name").isEqualTo("aws:ssm:parameter:/config/foo-development/") 41 | } 42 | 43 | companion object { 44 | @Container 45 | val cloudConfigContainer: ComposeContainer = "examples/aws/paramstore/compose.yml".toComposeContainer() 46 | .withExposedService("localstack", 4566, Wait.forHealthcheck()) 47 | .withLogConsumer("localstack", logConsumer) 48 | 49 | @JvmStatic 50 | @BeforeAll 51 | internal fun populateData() { 52 | logger.info { "Populating test data" } 53 | val execResult = (cloudConfigContainer.getContainerByServiceName("localstack") 54 | .getOrNull() 55 | ?.execInContainer("sh", "/data/populate-paramstore.sh") 56 | ?: throw RuntimeException("Could not populate paramstore test data")) 57 | 58 | assertThat(execResult.exitCode).isZero() 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/AwsS3BackendTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.assertj.core.api.Assertions.assertThat 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.containerTimeout 5 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logConsumer 6 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 7 | import org.junit.jupiter.api.BeforeAll 8 | import org.junit.jupiter.api.Disabled 9 | import org.junit.jupiter.api.Tag 10 | import org.junit.jupiter.api.Tags 11 | import org.junit.jupiter.params.ParameterizedTest 12 | import org.junit.jupiter.params.provider.EnumSource 13 | import org.springframework.http.MediaType.APPLICATION_JSON 14 | import org.springframework.test.web.reactive.server.WebTestClient 15 | import org.testcontainers.containers.ComposeContainer 16 | import org.testcontainers.containers.wait.strategy.Wait 17 | import org.testcontainers.junit.jupiter.Container 18 | import org.testcontainers.junit.jupiter.Testcontainers 19 | import kotlin.jvm.optionals.getOrNull 20 | 21 | @Disabled("Test flakes in ci only") 22 | @Testcontainers 23 | @Tags(Tag("integration"), Tag("aws"), Tag("aws-s3")) 24 | class AwsS3BackendTest { 25 | 26 | @EnumSource 27 | @ParameterizedTest 28 | internal fun `given a config server, when configured with aws s3 backend, is valid`(type: ContainerConfigurationType) { 29 | logger.info { "Verifying ${type.label}" } 30 | val webClient = WebTestClient.bindToServer() 31 | .baseUrl(cloudConfigContainer.getUrl(type)) 32 | .responseTimeout(containerTimeout) 33 | .build() 34 | 35 | webClient.get() 36 | .uri("/foo/development") 37 | .accept(APPLICATION_JSON) 38 | .exchange() 39 | .expectStatus().isOk 40 | .expectHeader().contentType(APPLICATION_JSON) 41 | .expectBody() 42 | .jsonPath("$.name").isEqualTo("foo") 43 | .jsonPath("$.propertySources[0].name").isEqualTo("s3:foo-development") 44 | } 45 | 46 | companion object { 47 | @Container 48 | val cloudConfigContainer: ComposeContainer = "examples/aws/s3/compose.yml".toComposeContainer() 49 | .withExposedService("localstack", 4566, Wait.forHealthcheck()) 50 | .withLogConsumer("localstack", logConsumer) 51 | 52 | @JvmStatic 53 | @BeforeAll 54 | internal fun populateData() { 55 | logger.info { "Populating test data" } 56 | val execResult = (cloudConfigContainer.getContainerByServiceName("localstack") 57 | .getOrNull() 58 | ?.execInContainer("sh", "/data/populate-s3.sh") 59 | ?: throw RuntimeException("Could not populate s3 test data")) 60 | 61 | assertThat(execResult.exitCode).isZero() 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/AwsSecretsManagerBackendTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.assertj.core.api.Assertions.assertThat 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.containerTimeout 5 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logConsumer 6 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 7 | import org.junit.jupiter.api.BeforeAll 8 | import org.junit.jupiter.api.Tag 9 | import org.junit.jupiter.api.Tags 10 | import org.junit.jupiter.params.ParameterizedTest 11 | import org.junit.jupiter.params.provider.EnumSource 12 | import org.springframework.http.MediaType.APPLICATION_JSON 13 | import org.springframework.test.web.reactive.server.WebTestClient 14 | import org.testcontainers.containers.ComposeContainer 15 | import org.testcontainers.containers.wait.strategy.Wait 16 | import org.testcontainers.junit.jupiter.Container 17 | import org.testcontainers.junit.jupiter.Testcontainers 18 | import kotlin.jvm.optionals.getOrNull 19 | 20 | @Testcontainers 21 | @Tags(Tag("integration"), Tag("aws"), Tag("aws-secrets-manager")) 22 | class AwsSecretsManagerBackendTest { 23 | 24 | @EnumSource 25 | @ParameterizedTest 26 | internal fun `given a config server, when configured with aws secrets manager backend, is valid`(type: ContainerConfigurationType) { 27 | logger.info { "Verifying ${type.label}" } 28 | val webClient = WebTestClient.bindToServer() 29 | .baseUrl(cloudConfigContainer.getUrl(type)) 30 | .responseTimeout(containerTimeout) 31 | .build() 32 | 33 | webClient.get() 34 | .uri("/foo/development") 35 | .accept(APPLICATION_JSON) 36 | .exchange() 37 | .expectStatus().isOk 38 | .expectHeader().contentType(APPLICATION_JSON) 39 | .expectBody() 40 | .jsonPath("$.name").isEqualTo("foo") 41 | .jsonPath("$.propertySources[0].name").isEqualTo("aws:secrets:/secret/foo-development/") 42 | } 43 | 44 | companion object { 45 | @Container 46 | val cloudConfigContainer: ComposeContainer = "examples/aws/secretsmanager/compose.yml".toComposeContainer() 47 | .withExposedService("localstack",4566, Wait.forHealthcheck()) 48 | .withLogConsumer("localstack", logConsumer) 49 | 50 | @JvmStatic 51 | @BeforeAll 52 | internal fun populateData() { 53 | logger.info { "Populating test data" } 54 | val execResult = (cloudConfigContainer.getContainerByServiceName("localstack") 55 | .getOrNull() 56 | ?.execInContainer("sh", "/data/populate-secretsmanager.sh") 57 | ?: throw RuntimeException("Could not populate secretsmanager test data")) 58 | 59 | assertThat(execResult.exitCode).isZero() 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/CloudBusKafkaRemoteGitBackendTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.containerTimeout 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 5 | import org.junit.jupiter.api.Tag 6 | import org.junit.jupiter.api.Tags 7 | import org.junit.jupiter.params.ParameterizedTest 8 | import org.junit.jupiter.params.provider.EnumSource 9 | import org.springframework.http.MediaType.APPLICATION_JSON 10 | import org.springframework.test.web.reactive.server.WebTestClient 11 | import org.testcontainers.junit.jupiter.Container 12 | import org.testcontainers.junit.jupiter.Testcontainers 13 | 14 | @Testcontainers 15 | @Tags(Tag("integration"), Tag("cloud-bus"),Tag("kafka"), Tag("cloud-bus-kafka")) 16 | class CloudBusKafkaRemoteGitBackendTest { 17 | @EnumSource 18 | @ParameterizedTest 19 | internal fun `given a config server, when configured with cloud bus and remote git backend, is valid`(type: ContainerConfigurationType) { 20 | logger.info { "Verifying ${type.label}" } 21 | val webClient = WebTestClient.bindToServer() 22 | .baseUrl(cloudConfigContainer.getUrl(type)) 23 | .responseTimeout(containerTimeout) 24 | .build() 25 | 26 | webClient.get() 27 | .uri("/foo/development") 28 | .accept(APPLICATION_JSON) 29 | .exchange() 30 | .expectStatus().isOk 31 | .expectHeader().contentType(APPLICATION_JSON) 32 | .expectBody() 33 | .consumeWith { 34 | println(it) 35 | } 36 | .jsonPath("$.name").isEqualTo("foo") 37 | .jsonPath("$.propertySources[0].name").isEqualTo("https://github.com/spring-cloud-samples/config-repo/foo-development.properties") 38 | } 39 | 40 | companion object { 41 | @Container 42 | val cloudConfigContainer = "examples/cloud-bus/kafka/compose.yml".toComposeContainer().apply { 43 | withExposedService("kafka", 9092) 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/CloudBusRabbitRemoteGitBackendTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.containerTimeout 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 5 | import org.junit.jupiter.api.Tag 6 | import org.junit.jupiter.api.Tags 7 | import org.junit.jupiter.params.ParameterizedTest 8 | import org.junit.jupiter.params.provider.EnumSource 9 | import org.springframework.http.MediaType.APPLICATION_JSON 10 | import org.springframework.test.web.reactive.server.WebTestClient 11 | import org.testcontainers.junit.jupiter.Container 12 | import org.testcontainers.junit.jupiter.Testcontainers 13 | 14 | @Testcontainers 15 | @Tags(Tag("integration"), Tag("cloud-bus"), Tag("rabbitmq"), Tag("cloud-bus-rabbitmq")) 16 | class CloudBusRabbitRemoteGitBackendTest { 17 | @EnumSource 18 | @ParameterizedTest 19 | internal fun `given a config server, when configured with cloud bus and remote git backend, is valid`(type: ContainerConfigurationType) { 20 | logger.info { "Verifying ${type.label}" } 21 | val webClient = WebTestClient.bindToServer() 22 | .baseUrl(cloudConfigContainer.getUrl(type)) 23 | .responseTimeout(containerTimeout) 24 | .build() 25 | 26 | webClient.get() 27 | .uri("/foo/development") 28 | .accept(APPLICATION_JSON) 29 | .exchange() 30 | .expectStatus().isOk 31 | .expectHeader().contentType(APPLICATION_JSON) 32 | .expectBody() 33 | .consumeWith { 34 | println(it) 35 | } 36 | .jsonPath("$.name").isEqualTo("foo") 37 | .jsonPath("$.propertySources[0].name").isEqualTo("https://github.com/spring-cloud-samples/config-repo/foo-development.properties") 38 | } 39 | 40 | companion object { 41 | @Container 42 | val cloudConfigContainer = "examples/cloud-bus/rabbit/compose.yml".toComposeContainer().apply { 43 | withExposedService("rabbitmq", 5672) 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/ConfigServerApplicationTests.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import io.github.oshai.kotlinlogging.KotlinLogging 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.cloudConfigWait 5 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logConsumer 6 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 7 | import org.freshlegacycode.cloud.config.server.ContainerConfigurationType.* 8 | import org.junit.jupiter.api.Tag 9 | import org.junit.jupiter.api.Test 10 | import org.slf4j.LoggerFactory 11 | import org.springframework.boot.test.context.SpringBootTest 12 | import org.testcontainers.containers.ComposeContainer 13 | import org.testcontainers.containers.output.Slf4jLogConsumer 14 | import org.testcontainers.containers.wait.strategy.Wait 15 | import org.testcontainers.containers.wait.strategy.WaitStrategy 16 | import java.io.File 17 | import kotlin.time.Duration.Companion.seconds 18 | import kotlin.time.toJavaDuration 19 | 20 | @Tag("unit") 21 | @SpringBootTest(properties = ["spring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo"]) 22 | class ConfigServerApplicationTests { 23 | @Test 24 | fun `context loads`() {} 25 | 26 | companion object { 27 | internal val logger = KotlinLogging.logger {} 28 | internal val logConsumer = 29 | ConfigServerApplicationTests::class.java.run(LoggerFactory::getLogger).run(::Slf4jLogConsumer) 30 | internal val cloudConfigWait: WaitStrategy = "/actuator/health".run(Wait::forHttp) 31 | internal val containerTimeout = 60.seconds.toJavaDuration() 32 | } 33 | } 34 | 35 | enum class ContainerConfigurationType(val container: String, val label: String) { 36 | CONFIG_DIR("config-server-dir", "Cloud config with config dir"), 37 | COMMAND_LINE("config-server-args", "Cloud config with command line arguments"), 38 | ENV_VARS("config-server-env", "Cloud config with environment variables"), 39 | SYS_PROPS("config-server-props", "Cloud config with system properties") 40 | } 41 | 42 | internal fun ComposeContainer.getUrl(type: ContainerConfigurationType) = getContainerByServiceName(type.container) 43 | .orElseThrow() 44 | .let { "http://localhost:${it.firstMappedPort}" } 45 | 46 | internal fun String.toComposeContainer(): ComposeContainer = ComposeContainer(run(::File)) 47 | .withEnv(systemPropertiesToMap()) 48 | .withExposedService(ENV_VARS.container, 8888, cloudConfigWait) 49 | .withExposedService(CONFIG_DIR.container, 8888, cloudConfigWait) 50 | .withExposedService(SYS_PROPS.container, 8888, cloudConfigWait) 51 | .withExposedService(COMMAND_LINE.container, 8888, cloudConfigWait) 52 | .withLogConsumer(ENV_VARS.container, logConsumer) 53 | .withLogConsumer(CONFIG_DIR.container, logConsumer) 54 | .withLogConsumer(SYS_PROPS.container, logConsumer) 55 | .withLogConsumer(COMMAND_LINE.container, logConsumer) 56 | 57 | internal fun systemPropertiesToMap() = mapOf("REGISTRY" to "registry", "IMAGE_NAME" to "name", "TAG" to "tag") 58 | .map { (key, value) -> key to value.run(System::getProperty) } 59 | .toMap() 60 | .also { logger.info { "Starting container using environment: $it" } } 61 | -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/FileSystemBackendTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.containerTimeout 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 5 | import org.junit.jupiter.api.Tag 6 | import org.junit.jupiter.api.Tags 7 | import org.junit.jupiter.params.ParameterizedTest 8 | import org.junit.jupiter.params.provider.EnumSource 9 | import org.springframework.http.MediaType.APPLICATION_JSON 10 | import org.springframework.test.web.reactive.server.WebTestClient 11 | import org.testcontainers.junit.jupiter.Container 12 | import org.testcontainers.junit.jupiter.Testcontainers 13 | 14 | @Testcontainers 15 | @Tags(Tag("integration"), Tag("native")) 16 | class FileSystemBackendTest { 17 | @EnumSource 18 | @ParameterizedTest 19 | internal fun `given a config server, when configured with file system backend, is valid`(type: ContainerConfigurationType) { 20 | logger.info { "Verifying ${type.label}" } 21 | val webClient = WebTestClient.bindToServer() 22 | .baseUrl(cloudConfigContainer.getUrl(type)) 23 | .responseTimeout(containerTimeout) 24 | .build() 25 | 26 | webClient.get() 27 | .uri("/foo/development") 28 | .accept(APPLICATION_JSON) 29 | .exchange() 30 | .expectStatus().isOk 31 | .expectHeader().contentType(APPLICATION_JSON) 32 | .expectBody() 33 | .jsonPath("$.name").isEqualTo("foo") 34 | .jsonPath("$.propertySources[0].name").isEqualTo("file:/native-files/foo-development.properties") 35 | } 36 | 37 | companion object { 38 | @Container 39 | val cloudConfigContainer = "examples/native/compose.yml".toComposeContainer() 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/JdbcBackendMariaDbTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.junit.jupiter.api.Tag 4 | import org.testcontainers.junit.jupiter.Container 5 | import org.testcontainers.junit.jupiter.Testcontainers 6 | 7 | @Testcontainers 8 | @Tag("mariadb") 9 | class JdbcBackendMariaDbTest : JdbcBackendTest() { 10 | override fun getContainer() = cloudConfigContainer 11 | 12 | companion object { 13 | @Container 14 | val cloudConfigContainer = "examples/jdbc/mariadb/compose.yml".toComposeContainer().apply { 15 | withExposedService("mariadb", 3306) 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/JdbcBackendPostgresTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.junit.jupiter.api.Tag 4 | import org.testcontainers.junit.jupiter.Container 5 | import org.testcontainers.junit.jupiter.Testcontainers 6 | 7 | @Testcontainers 8 | @Tag("postgres") 9 | class JdbcBackendPostgresTest : JdbcBackendTest() { 10 | override fun getContainer() = cloudConfigContainer 11 | 12 | companion object { 13 | @Container 14 | val cloudConfigContainer = "examples/jdbc/postgres/compose.yml".toComposeContainer().apply { 15 | withExposedService("postgres", 5432) 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/JdbcBackendTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.containerTimeout 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 5 | import org.junit.jupiter.api.Tag 6 | import org.junit.jupiter.api.Tags 7 | import org.junit.jupiter.params.ParameterizedTest 8 | import org.junit.jupiter.params.provider.EnumSource 9 | import org.springframework.http.MediaType.APPLICATION_JSON 10 | import org.springframework.test.web.reactive.server.WebTestClient 11 | import org.testcontainers.containers.ComposeContainer 12 | import org.testcontainers.junit.jupiter.Testcontainers 13 | 14 | @Testcontainers 15 | @Tags(Tag("integration"), Tag("jdbc")) 16 | abstract class JdbcBackendTest { 17 | abstract fun getContainer(): ComposeContainer 18 | 19 | @EnumSource 20 | @ParameterizedTest 21 | internal fun `given a config server, when configured with jdbc backend, is valid`(type: ContainerConfigurationType) { 22 | logger.info{ "Verifying ${type.label}" } 23 | val webClient = WebTestClient.bindToServer() 24 | .baseUrl(getContainer().getUrl(type)) 25 | .responseTimeout(containerTimeout) 26 | .build() 27 | 28 | webClient.get() 29 | .uri("/jdbc-app/dev/latest") 30 | .accept(APPLICATION_JSON) 31 | .exchange() 32 | .expectStatus().isOk 33 | .expectHeader().contentType(APPLICATION_JSON) 34 | .expectBody() 35 | .jsonPath("$.name").isEqualTo("jdbc-app") 36 | .jsonPath("$.propertySources[0].source.['sample key']").isEqualTo("a value") 37 | } 38 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/PrometheusActuatorTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.assertj.core.api.Assertions.assertThat 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.containerTimeout 5 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 6 | import org.junit.jupiter.api.Tag 7 | import org.junit.jupiter.api.Tags 8 | import org.junit.jupiter.params.ParameterizedTest 9 | import org.junit.jupiter.params.provider.EnumSource 10 | import org.springframework.http.MediaType.TEXT_PLAIN 11 | import org.springframework.test.web.reactive.server.WebTestClient 12 | import org.testcontainers.junit.jupiter.Container 13 | import org.testcontainers.junit.jupiter.Testcontainers 14 | import kotlin.text.Charsets.UTF_8 15 | 16 | @Testcontainers 17 | @Tags(Tag("integration"), Tag("prometheus")) 18 | class PrometheusActuatorTest { 19 | @EnumSource 20 | @ParameterizedTest 21 | internal fun `given a config server, when configured with remote git backend and prometheus actuator, is valid`(type: ContainerConfigurationType) { 22 | logger.info { "Verifying ${type.label}" } 23 | val webClient = WebTestClient.bindToServer() 24 | .baseUrl(cloudConfigContainer.getUrl(type)) 25 | .responseTimeout(containerTimeout) 26 | .build() 27 | 28 | webClient.get() 29 | .uri("/actuator/prometheus") 30 | .exchange() 31 | .expectStatus().isOk 32 | .expectHeader().contentTypeCompatibleWith(TEXT_PLAIN) 33 | .expectBody() 34 | .consumeWith { 35 | assertThat(it.responseBodyContent?.toString(UTF_8)) 36 | .contains("# TYPE system_cpu_usage gauge") 37 | } 38 | } 39 | 40 | companion object { 41 | @Container 42 | val cloudConfigContainer = "examples/prometheus/compose.yml".toComposeContainer() 43 | } 44 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/RedisBackendTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.assertj.core.api.Assertions.assertThat 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.containerTimeout 5 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logConsumer 6 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 7 | import org.junit.jupiter.api.BeforeAll 8 | import org.junit.jupiter.api.Tag 9 | import org.junit.jupiter.api.Tags 10 | import org.junit.jupiter.params.ParameterizedTest 11 | import org.junit.jupiter.params.provider.EnumSource 12 | import org.springframework.http.MediaType.APPLICATION_JSON 13 | import org.springframework.test.web.reactive.server.WebTestClient 14 | import org.testcontainers.containers.ComposeContainer 15 | import org.testcontainers.junit.jupiter.Container 16 | import org.testcontainers.junit.jupiter.Testcontainers 17 | import kotlin.jvm.optionals.getOrNull 18 | 19 | @Testcontainers 20 | @Tags(Tag("integration"), Tag("redis")) 21 | class RedisBackendTest { 22 | @EnumSource 23 | @ParameterizedTest 24 | internal fun `given a config server, when configured with redis backend, is valid`(type: ContainerConfigurationType) { 25 | logger.info { "Verifying ${type.label}" } 26 | val webClient = WebTestClient.bindToServer() 27 | .baseUrl(cloudConfigContainer.getUrl(type)) 28 | .responseTimeout(containerTimeout) 29 | .build() 30 | webClient.get() 31 | .uri("/redis-app/development") 32 | .accept(APPLICATION_JSON) 33 | .exchange() 34 | .expectStatus().isOk 35 | .expectHeader().contentType(APPLICATION_JSON) 36 | .expectBody() 37 | .consumeWith { logger.info{ it } } 38 | .jsonPath("$.name").isEqualTo("redis-app") 39 | .jsonPath("$.propertySources[0].source.['server.port']").isEqualTo("8100") 40 | } 41 | 42 | companion object { 43 | @Container 44 | val cloudConfigContainer: ComposeContainer = "examples/redis/compose.yml".toComposeContainer() 45 | .withExposedService("redis", 6379) 46 | .withLogConsumer("redis", logConsumer) 47 | 48 | @JvmStatic 49 | @BeforeAll 50 | internal fun populateData() { 51 | logger.info { "Populating test data" } 52 | val execResult = (cloudConfigContainer.getContainerByServiceName("redis") 53 | .getOrNull() 54 | ?.execInContainer("sh", "/data/populate-redis.sh") 55 | ?: throw RuntimeException("Could not populate redis test data")) 56 | 57 | assertThat(execResult.exitCode).isZero() 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/RemoteGitRepoBackendTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.containerTimeout 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 5 | import org.junit.jupiter.api.Tag 6 | import org.junit.jupiter.api.Tags 7 | import org.junit.jupiter.params.ParameterizedTest 8 | import org.junit.jupiter.params.provider.EnumSource 9 | import org.springframework.http.MediaType.APPLICATION_JSON 10 | import org.springframework.test.web.reactive.server.WebTestClient 11 | import org.testcontainers.containers.ComposeContainer 12 | import org.testcontainers.junit.jupiter.Container 13 | import org.testcontainers.junit.jupiter.Testcontainers 14 | 15 | @Testcontainers 16 | @Tags(Tag("integration"), Tag("git")) 17 | class RemoteGitRepoBackendTest { 18 | @EnumSource 19 | @ParameterizedTest 20 | internal fun `given a config server, when configured with remote git backend, is valid`(type: ContainerConfigurationType) { 21 | logger.info { "Verifying ${type.label}" } 22 | val webClient = WebTestClient.bindToServer() 23 | .baseUrl(cloudConfigContainer.getUrl(type)) 24 | .responseTimeout(containerTimeout) 25 | .build() 26 | 27 | webClient.get() 28 | .uri("/foo/development") 29 | .accept(APPLICATION_JSON) 30 | .exchange() 31 | .expectStatus().isOk 32 | .expectHeader().contentType(APPLICATION_JSON) 33 | .expectBody() 34 | .jsonPath("$.name").isEqualTo("foo") 35 | .jsonPath("$.propertySources[0].name").isEqualTo("https://github.com/spring-cloud-samples/config-repo/foo-development.properties") 36 | } 37 | 38 | companion object { 39 | @Container 40 | val cloudConfigContainer: ComposeContainer = "examples/git/compose.yml".toComposeContainer() 41 | } 42 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/SecurityEncryptTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.assertj.core.api.Assertions.assertThat 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.containerTimeout 5 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 6 | import org.junit.jupiter.api.Tag 7 | import org.junit.jupiter.api.Tags 8 | import org.junit.jupiter.params.ParameterizedTest 9 | import org.junit.jupiter.params.provider.EnumSource 10 | import org.springframework.http.HttpHeaders.AUTHORIZATION 11 | import org.springframework.http.MediaType.TEXT_PLAIN 12 | import org.springframework.test.web.reactive.server.WebTestClient 13 | import org.springframework.web.reactive.function.BodyInserters.fromValue 14 | import org.testcontainers.containers.ComposeContainer 15 | import org.testcontainers.junit.jupiter.Container 16 | import org.testcontainers.junit.jupiter.Testcontainers 17 | import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric 18 | import org.testcontainers.shaded.org.bouncycastle.util.encoders.Base64 19 | 20 | @Testcontainers 21 | @Tags(Tag("integration"), Tag("security")) 22 | class SecurityEncryptTest { 23 | @EnumSource 24 | @ParameterizedTest 25 | internal fun `given a config server, when configured with remote git backend, is valid`(type: ContainerConfigurationType) { 26 | logger.info { "Verifying ${type.label}" } 27 | val encodedCredentials = "Basic ${Base64.toBase64String("user:password".toByteArray())}" 28 | val value = randomAlphanumeric(20) 29 | 30 | val webClient = WebTestClient.bindToServer() 31 | .baseUrl(cloudConfigContainer.getUrl(type)) 32 | .responseTimeout(containerTimeout) 33 | .build() 34 | 35 | val encrypted = webClient.post() 36 | .uri("/encrypt") 37 | .contentType(TEXT_PLAIN) 38 | .header(AUTHORIZATION, encodedCredentials) 39 | .body(fromValue(value)) 40 | .exchange() 41 | .expectStatus().isOk 42 | .expectHeader().contentTypeCompatibleWith(TEXT_PLAIN) 43 | .returnResult(String::class.java) 44 | .responseBody 45 | .blockLast() 46 | 47 | assertThat(encrypted).isNotBlank().isNotEqualTo(value) 48 | 49 | val decrypted = webClient.post() 50 | .uri("/decrypt") 51 | .contentType(TEXT_PLAIN) 52 | .header(AUTHORIZATION, encodedCredentials) 53 | .body(fromValue(encrypted!!)) 54 | .exchange() 55 | .expectStatus().isOk 56 | .expectHeader().contentTypeCompatibleWith(TEXT_PLAIN) 57 | .returnResult(String::class.java) 58 | .responseBody 59 | .blockLast() 60 | 61 | assertThat(decrypted).isEqualTo(value) 62 | } 63 | 64 | companion object { 65 | @Container 66 | val cloudConfigContainer: ComposeContainer = "examples/security/compose.yml".toComposeContainer() 67 | } 68 | } -------------------------------------------------------------------------------- /src/test/kotlin/org/freshlegacycode/cloud/config/server/VaultBackendTest.kt: -------------------------------------------------------------------------------- 1 | package org.freshlegacycode.cloud.config.server 2 | 3 | import org.assertj.core.api.Assertions.assertThat 4 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.containerTimeout 5 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logConsumer 6 | import org.freshlegacycode.cloud.config.server.ConfigServerApplicationTests.Companion.logger 7 | import org.junit.jupiter.api.BeforeAll 8 | import org.junit.jupiter.api.Tag 9 | import org.junit.jupiter.api.Tags 10 | import org.junit.jupiter.params.ParameterizedTest 11 | import org.junit.jupiter.params.provider.EnumSource 12 | import org.springframework.http.MediaType.APPLICATION_JSON 13 | import org.springframework.test.web.reactive.server.WebTestClient 14 | import org.testcontainers.containers.ComposeContainer 15 | import org.testcontainers.junit.jupiter.Container 16 | import org.testcontainers.junit.jupiter.Testcontainers 17 | import kotlin.jvm.optionals.getOrNull 18 | 19 | @Testcontainers 20 | @Tags(Tag("integration"), Tag("vault")) 21 | class VaultBackendTest { 22 | @EnumSource 23 | @ParameterizedTest 24 | internal fun `given a config server, when configured with vault backend, is valid`(type: ContainerConfigurationType) { 25 | logger.info { "Verifying ${type.label}" } 26 | val webClient = WebTestClient.bindToServer() 27 | .baseUrl(cloudConfigContainer.getUrl(type)) 28 | .responseTimeout(containerTimeout) 29 | .build() 30 | 31 | webClient.get() 32 | .uri("/myapp/default") 33 | .accept(APPLICATION_JSON) 34 | .exchange() 35 | .expectStatus().isOk 36 | .expectHeader().contentType(APPLICATION_JSON) 37 | .expectBody() 38 | .jsonPath("$.name").isEqualTo("myapp") 39 | .jsonPath("$.propertySources[0].source.foo").isEqualTo("myappsbar") 40 | } 41 | 42 | companion object { 43 | @Container 44 | val cloudConfigContainer: ComposeContainer = "examples/vault/compose.yml".toComposeContainer() 45 | .withExposedService("vault", 8200) 46 | .withLogConsumer("vault", logConsumer) 47 | 48 | @JvmStatic 49 | @BeforeAll 50 | internal fun populateData() { 51 | logger.info { "Populating test data" } 52 | val execResult = (cloudConfigContainer.getContainerByServiceName("vault") 53 | .getOrNull() 54 | ?.execInContainer("sh", "/data/populate-vault.sh") 55 | ?: throw RuntimeException("Could not populate vault test data")) 56 | 57 | assertThat(execResult.exitCode).isZero() 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | #junit.jupiter.execution.parallel.enabled = true 2 | #junit.jupiter.execution.parallel.mode.default = concurrent 3 | #junit.jupiter.execution.parallel.mode.classes.default = same_thread 4 | junit.jupiter.execution.parallel.config.strategy = fixed 5 | junit.jupiter.execution.parallel.config.fixed.parallelism = 3 --------------------------------------------------------------------------------