mirror of
https://github.com/spring-cloud/spring-cloud-netflix.git
synced 2026-09-20 00:59:01 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdd36d1857 | ||
|
|
df68046eca |
@@ -0,0 +1,41 @@
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
- image: springcloud/pipeline-base
|
||||
user: appuser
|
||||
environment:
|
||||
_JAVA_OPTIONS: "-Xms1024m -Xmx2048m"
|
||||
TERM: dumb
|
||||
branches:
|
||||
ignore:
|
||||
- gh-pages # list of branches to ignore
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: sc-netflix-{{ .Branch }}
|
||||
- run:
|
||||
name: "Download dependencies"
|
||||
command: |
|
||||
cd spring-cloud-netflix-hystrix-contract && ../mvnw clean install && \
|
||||
./mvnw -s .settings.xml -U --fail-never dependency:go-offline || true
|
||||
- save_cache:
|
||||
key: sc-netflix-{{ .Branch }}
|
||||
paths:
|
||||
- ~/.m2
|
||||
- run:
|
||||
name: "Running build"
|
||||
command: ./mvnw -s .settings.xml clean org.jacoco:jacoco-maven-plugin:prepare-agent install -U -P sonar -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
|
||||
- run:
|
||||
name: "Aggregate test results"
|
||||
when: always
|
||||
command: |
|
||||
mkdir -p ~/junit/
|
||||
find . -type f -regex ".*/target/.*-reports/.*" -exec cp {} ~/junit/ \;
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
- store_artifacts:
|
||||
path: ~/junit/
|
||||
destination: artifacts
|
||||
- store_test_results:
|
||||
path: ~/junit/
|
||||
destination: testartifacts
|
||||
@@ -1,33 +0,0 @@
|
||||
# This workflow will build a Java project with Maven
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
|
||||
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ 4.0.x ]
|
||||
pull_request:
|
||||
branches: [ 4.0.x ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
java: ["17"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK ${{ matrix.java }}
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: ${{ matrix.java }}
|
||||
cache: 'maven'
|
||||
- name: Build with Maven
|
||||
run: ./mvnw clean install -B -U -P sonar
|
||||
- uses: codecov/codecov-action@v3
|
||||
with:
|
||||
fail_ci_if_error: false
|
||||
@@ -1 +0,0 @@
|
||||
17
|
||||
@@ -1,3 +1,3 @@
|
||||
# Enable auto-env through the sdkman_auto_env config
|
||||
# Add key=value pairs of SDKs to use below
|
||||
java=17.0.1-tem
|
||||
java=8.0.292.hs-adpt
|
||||
|
||||
+246
-21
@@ -21,9 +21,10 @@ Edit the files in the src/main/asciidoc/ directory instead.
|
||||
:sc-ext: java
|
||||
:project-full-name: Spring Cloud Netflix
|
||||
|
||||
image::https://github.com/spring-cloud/spring-cloud-netflix/actions/workflows/maven.yml/badge.svg?branch=4.0.x&style=svg["Build",link="https://github.com/spring-cloud/spring-cloud-netflix/actions/workflows/maven.yml"]
|
||||
image::https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/main.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/main"]
|
||||
image::https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/main/graph/badge.svg["Codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/main"]
|
||||
image::https://api.codacy.com/project/badge/Grade/a6885a06921e4f72a0df0b7aabd6d118["Codacy code quality", link="https://www.codacy.com/app/Spring-Cloud/spring-cloud-netflix?utm_source=github.com&utm_medium=referral&utm_content=spring-cloud/spring-cloud-netflix&utm_campaign=Badge_Grade"]
|
||||
|
||||
image:https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/4.0.x/graph/badge.svg["Codecov", link="https://app.codecov.io/gh/spring-cloud/spring-cloud-netflix/tree/4.0.x"]
|
||||
|
||||
:doctype: book
|
||||
:idprefix:
|
||||
@@ -56,10 +57,10 @@ patterns provided include Service Discovery (Eureka).
|
||||
|
||||
== Building
|
||||
|
||||
|
||||
:jdkversion: 17
|
||||
|
||||
[[basic-compile-and-test]]
|
||||
== Basic Compile and Test
|
||||
=== Basic Compile and Test
|
||||
|
||||
To build the source you will need to install JDK {jdkversion}.
|
||||
|
||||
@@ -86,36 +87,31 @@ source control.
|
||||
The projects that require middleware (i.e. Redis) for testing generally
|
||||
require that a local instance of [Docker](https://www.docker.com/get-started) is installed and running.
|
||||
|
||||
[[documentation]]
|
||||
== Documentation
|
||||
|
||||
=== Documentation
|
||||
|
||||
The spring-cloud-build module has a "docs" profile, and if you switch
|
||||
that on it will try to build asciidoc sources using https://docs.antora.org/antora/latest/[Antora] from
|
||||
`modules/ROOT/`.
|
||||
|
||||
As part of that process it will look for a
|
||||
`docs/src/main/asciidoc/README.adoc` and process it by loading all the includes, but not
|
||||
that on it will try to build asciidoc sources from
|
||||
`src/main/asciidoc`. As part of that process it will look for a
|
||||
`README.adoc` and process it by loading all the includes, but not
|
||||
parsing or rendering it, just copying it to `${main.basedir}`
|
||||
(defaults to `$\{basedir}`, i.e. the root of the project). If there are
|
||||
(defaults to `${basedir}`, i.e. the root of the project). If there are
|
||||
any changes in the README it will then show up after a Maven build as
|
||||
a modified file in the correct place. Just commit it and push the change.
|
||||
|
||||
[[working-with-the-code]]
|
||||
== Working with the code
|
||||
=== Working with the code
|
||||
If you don't have an IDE preference we would recommend that you use
|
||||
https://www.springsource.com/developer/sts[Spring Tools Suite] or
|
||||
https://eclipse.org[Eclipse] when working with the code. We use the
|
||||
https://eclipse.org/m2e/[m2eclipse] eclipse plugin for maven support. Other IDEs and tools
|
||||
should also work without issue as long as they use Maven 3.3.3 or better.
|
||||
|
||||
[[activate-the-spring-maven-profile]]
|
||||
=== Activate the Spring Maven profile
|
||||
==== Activate the Spring Maven profile
|
||||
Spring Cloud projects require the 'spring' Maven profile to be activated to resolve
|
||||
the spring milestone and snapshot repositories. Use your preferred IDE to set this
|
||||
profile to be active, or you may experience build errors.
|
||||
|
||||
[[importing-into-eclipse-with-m2eclipse]]
|
||||
=== Importing into eclipse with m2eclipse
|
||||
==== Importing into eclipse with m2eclipse
|
||||
We recommend the https://eclipse.org/m2e/[m2eclipse] eclipse plugin when working with
|
||||
eclipse. If you don't already have m2eclipse installed it is available from the "eclipse
|
||||
marketplace".
|
||||
@@ -129,8 +125,7 @@ add the "spring" profile to your `settings.xml`. Alternatively you can
|
||||
copy the repository settings from the "spring" profile of the parent
|
||||
pom into your `settings.xml`.
|
||||
|
||||
[[importing-into-eclipse-without-m2eclipse]]
|
||||
=== Importing into eclipse without m2eclipse
|
||||
==== Importing into eclipse without m2eclipse
|
||||
If you prefer not to use m2eclipse you can generate eclipse project metadata using the
|
||||
following command:
|
||||
|
||||
@@ -143,12 +138,242 @@ The generated eclipse projects can be imported by selecting `import existing pro
|
||||
from the `file` menu.
|
||||
|
||||
|
||||
|
||||
NOTE: To build the module `spring-cloud-netflix-hystrix-contract` along with the entire Netflix project run the
|
||||
`build.sh` script in the `scripts` directory.
|
||||
|
||||
== Contributing
|
||||
|
||||
NOTE: Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at {github-project}[github].
|
||||
:spring-cloud-build-branch: master
|
||||
|
||||
Spring Cloud is released under the non-restrictive Apache 2.0 license,
|
||||
and follows a very standard Github development process, using Github
|
||||
tracker for issues and merging pull requests into master. If you want
|
||||
to contribute even something trivial please do not hesitate, but
|
||||
follow the guidelines below.
|
||||
|
||||
=== Sign the Contributor License Agreement
|
||||
Before we accept a non-trivial patch or pull request we will need you to sign the
|
||||
https://cla.pivotal.io/sign/spring[Contributor License Agreement].
|
||||
Signing the contributor's agreement does not grant anyone commit rights to the main
|
||||
repository, but it does mean that we can accept your contributions, and you will get an
|
||||
author credit if we do. Active contributors might be asked to join the core team, and
|
||||
given the ability to merge pull requests.
|
||||
|
||||
=== Code of Conduct
|
||||
This project adheres to the Contributor Covenant https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc[code of
|
||||
conduct]. By participating, you are expected to uphold this code. Please report
|
||||
unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
=== Code Conventions and Housekeeping
|
||||
None of these is essential for a pull request, but they will all help. They can also be
|
||||
added after the original pull request but before a merge.
|
||||
|
||||
* Use the Spring Framework code format conventions. If you use Eclipse
|
||||
you can import formatter settings using the
|
||||
`eclipse-code-formatter.xml` file from the
|
||||
https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml[Spring
|
||||
Cloud Build] project. If using IntelliJ, you can use the
|
||||
https://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter
|
||||
Plugin] to import the same file.
|
||||
* Make sure all new `.java` files to have a simple Javadoc class comment with at least an
|
||||
`@author` tag identifying you, and preferably at least a paragraph on what the class is
|
||||
for.
|
||||
* Add the ASF license header comment to all new `.java` files (copy from existing files
|
||||
in the project)
|
||||
* Add yourself as an `@author` to the .java files that you modify substantially (more
|
||||
than cosmetic changes).
|
||||
* Add some Javadocs and, if you change the namespace, some XSD doc elements.
|
||||
* A few unit tests would help a lot as well -- someone has to do it.
|
||||
* If no-one else is using your branch, please rebase it against the current master (or
|
||||
other target branch in the main project).
|
||||
* When writing a commit message please follow https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions],
|
||||
if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit
|
||||
message (where XXXX is the issue number).
|
||||
|
||||
=== Checkstyle
|
||||
|
||||
Spring Cloud Build comes with a set of checkstyle rules. You can find them in the `spring-cloud-build-tools` module. The most notable files under the module are:
|
||||
|
||||
.spring-cloud-build-tools/
|
||||
----
|
||||
└── src
|
||||
├── checkstyle
|
||||
│ └── checkstyle-suppressions.xml <3>
|
||||
└── main
|
||||
└── resources
|
||||
├── checkstyle-header.txt <2>
|
||||
└── checkstyle.xml <1>
|
||||
----
|
||||
<1> Default Checkstyle rules
|
||||
<2> File header setup
|
||||
<3> Default suppression rules
|
||||
|
||||
==== Checkstyle configuration
|
||||
|
||||
Checkstyle rules are *disabled by default*. To add checkstyle to your project just define the following properties and plugins.
|
||||
|
||||
.pom.xml
|
||||
----
|
||||
<properties>
|
||||
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError> <1>
|
||||
<maven-checkstyle-plugin.failsOnViolation>true
|
||||
</maven-checkstyle-plugin.failsOnViolation> <2>
|
||||
<maven-checkstyle-plugin.includeTestSourceDirectory>true
|
||||
</maven-checkstyle-plugin.includeTestSourceDirectory> <3>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin> <4>
|
||||
<groupId>io.spring.javaformat</groupId>
|
||||
<artifactId>spring-javaformat-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin> <5>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin> <5>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
</build>
|
||||
----
|
||||
<1> Fails the build upon Checkstyle errors
|
||||
<2> Fails the build upon Checkstyle violations
|
||||
<3> Checkstyle analyzes also the test sources
|
||||
<4> Add the Spring Java Format plugin that will reformat your code to pass most of the Checkstyle formatting rules
|
||||
<5> Add checkstyle plugin to your build and reporting phases
|
||||
|
||||
If you need to suppress some rules (e.g. line length needs to be longer), then it's enough for you to define a file under `${project.root}/src/checkstyle/checkstyle-suppressions.xml` with your suppressions. Example:
|
||||
|
||||
.projectRoot/src/checkstyle/checkstyle-suppresions.xml
|
||||
----
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE suppressions PUBLIC
|
||||
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
|
||||
"https://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
|
||||
<suppressions>
|
||||
<suppress files=".*ConfigServerApplication\.java" checks="HideUtilityClassConstructor"/>
|
||||
<suppress files=".*ConfigClientWatch\.java" checks="LineLengthCheck"/>
|
||||
</suppressions>
|
||||
----
|
||||
|
||||
It's advisable to copy the `${spring-cloud-build.rootFolder}/.editorconfig` and `${spring-cloud-build.rootFolder}/.springformat` to your project. That way, some default formatting rules will be applied. You can do so by running this script:
|
||||
|
||||
```bash
|
||||
$ curl https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/.editorconfig -o .editorconfig
|
||||
$ touch .springformat
|
||||
```
|
||||
|
||||
=== IDE setup
|
||||
|
||||
==== Intellij IDEA
|
||||
|
||||
In order to setup Intellij you should import our coding conventions, inspection profiles and set up the checkstyle plugin.
|
||||
The following files can be found in the https://github.com/spring-cloud/spring-cloud-build/tree/master/spring-cloud-build-tools[Spring Cloud Build] project.
|
||||
|
||||
.spring-cloud-build-tools/
|
||||
----
|
||||
└── src
|
||||
├── checkstyle
|
||||
│ └── checkstyle-suppressions.xml <3>
|
||||
└── main
|
||||
└── resources
|
||||
├── checkstyle-header.txt <2>
|
||||
├── checkstyle.xml <1>
|
||||
└── intellij
|
||||
├── Intellij_Project_Defaults.xml <4>
|
||||
└── Intellij_Spring_Boot_Java_Conventions.xml <5>
|
||||
----
|
||||
<1> Default Checkstyle rules
|
||||
<2> File header setup
|
||||
<3> Default suppression rules
|
||||
<4> Project defaults for Intellij that apply most of Checkstyle rules
|
||||
<5> Project style conventions for Intellij that apply most of Checkstyle rules
|
||||
|
||||
.Code style
|
||||
|
||||
image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-code-style.png[Code style]
|
||||
|
||||
Go to `File` -> `Settings` -> `Editor` -> `Code style`. There click on the icon next to the `Scheme` section. There, click on the `Import Scheme` value and pick the `Intellij IDEA code style XML` option. Import the `spring-cloud-build-tools/src/main/resources/intellij/Intellij_Spring_Boot_Java_Conventions.xml` file.
|
||||
|
||||
.Inspection profiles
|
||||
|
||||
image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-inspections.png[Code style]
|
||||
|
||||
Go to `File` -> `Settings` -> `Editor` -> `Inspections`. There click on the icon next to the `Profile` section. There, click on the `Import Profile` and import the `spring-cloud-build-tools/src/main/resources/intellij/Intellij_Project_Defaults.xml` file.
|
||||
|
||||
.Checkstyle
|
||||
|
||||
To have Intellij work with Checkstyle, you have to install the `Checkstyle` plugin. It's advisable to also install the `Assertions2Assertj` to automatically convert the JUnit assertions
|
||||
|
||||
image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-checkstyle.png[Checkstyle]
|
||||
|
||||
Go to `File` -> `Settings` -> `Other settings` -> `Checkstyle`. There click on the `+` icon in the `Configuration file` section. There, you'll have to define where the checkstyle rules should be picked from. In the image above, we've picked the rules from the cloned Spring Cloud Build repository. However, you can point to the Spring Cloud Build's GitHub repository (e.g. for the `checkstyle.xml` : `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle.xml`). We need to provide the following variables:
|
||||
|
||||
- `checkstyle.header.file` - please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/main/resources/checkstyle-header.txt` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle-header.txt` URL.
|
||||
- `checkstyle.suppressions.file` - default suppressions. Please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` URL.
|
||||
- `checkstyle.additional.suppressions.file` - this variable corresponds to suppressions in your local project. E.g. you're working on `spring-cloud-contract`. Then point to the `project-root/src/checkstyle/checkstyle-suppressions.xml` folder. Example for `spring-cloud-contract` would be: `/home/username/spring-cloud-contract/src/checkstyle/checkstyle-suppressions.xml`.
|
||||
|
||||
IMPORTANT: Remember to set the `Scan Scope` to `All sources` since we apply checkstyle rules for production and test sources.
|
||||
|
||||
=== Duplicate Finder
|
||||
|
||||
Spring Cloud Build brings along the `basepom:duplicate-finder-maven-plugin`, that enables flagging duplicate and conflicting classes and resources on the java classpath.
|
||||
|
||||
==== Duplicate Finder configuration
|
||||
|
||||
Duplicate finder is *enabled by default* and will run in the `verify` phase of your Maven build, but it will only take effect in your project if you add the `duplicate-finder-maven-plugin` to the `build` section of the projecst's `pom.xml`.
|
||||
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.basepom.maven</groupId>
|
||||
<artifactId>duplicate-finder-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
----
|
||||
|
||||
For other properties, we have set defaults as listed in the https://github.com/basepom/duplicate-finder-maven-plugin/wiki[plugin documentation].
|
||||
|
||||
You can easily override them but setting the value of the selected property prefixed with `duplicate-finder-maven-plugin`. For example, set `duplicate-finder-maven-plugin.skip` to `true` in order to skip duplicates check in your build.
|
||||
|
||||
If you need to add `ignoredClassPatterns` or `ignoredResourcePatterns` to your setup, make sure to add them in the plugin configuration section of your project:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.basepom.maven</groupId>
|
||||
<artifactId>duplicate-finder-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<ignoredClassPatterns>
|
||||
<ignoredClassPattern>org.joda.time.base.BaseDateTime</ignoredClassPattern>
|
||||
<ignoredClassPattern>.*module-info</ignoredClassPattern>
|
||||
</ignoredClassPatterns>
|
||||
<ignoredResourcePatterns>
|
||||
<ignoredResourcePattern>changelog.txt</ignoredResourcePattern>
|
||||
</ignoredResourcePatterns>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
----
|
||||
|
||||
|
||||
== License
|
||||
|
||||
|
||||
+1
-3
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>4.0.4-SNAPSHOT</version>
|
||||
<version>3.1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-docs</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
@@ -18,8 +18,6 @@
|
||||
.*.eureka.*
|
||||
</configprops.inclusionPattern>
|
||||
<upload-docs-zip.phase>deploy</upload-docs-zip.phase>
|
||||
<!-- Don't upload docs jar to central / repo.spring.io -->
|
||||
<maven-deploy-plugin-default.phase>none</maven-deploy-plugin-default.phase>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
include::_attributes.adoc[]
|
||||
|
||||
image::https://github.com/spring-cloud/spring-cloud-netflix/actions/workflows/maven.yml/badge.svg?branch=4.0.x&style=svg["Build",link="https://github.com/spring-cloud/spring-cloud-netflix/actions/workflows/maven.yml"]
|
||||
image::https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/main.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/main"]
|
||||
image::https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/main/graph/badge.svg["Codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/main"]
|
||||
image::https://api.codacy.com/project/badge/Grade/a6885a06921e4f72a0df0b7aabd6d118["Codacy code quality", link="https://www.codacy.com/app/Spring-Cloud/spring-cloud-netflix?utm_source=github.com&utm_medium=referral&utm_content=spring-cloud/spring-cloud-netflix&utm_campaign=Badge_Grade"]
|
||||
|
||||
image:https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/4.0.x/graph/badge.svg["Codecov", link="https://app.codecov.io/gh/spring-cloud/spring-cloud-netflix/tree/4.0.x"]
|
||||
|
||||
include::intro.adoc[]
|
||||
|
||||
@@ -14,14 +15,14 @@ include::intro.adoc[]
|
||||
|
||||
== Building
|
||||
|
||||
include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/docs/modules/ROOT/partials/building.adoc[]
|
||||
include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/docs/src/main/asciidoc/building-jdk8.adoc[]
|
||||
|
||||
NOTE: To build the module `spring-cloud-netflix-hystrix-contract` along with the entire Netflix project run the
|
||||
`build.sh` script in the `scripts` directory.
|
||||
|
||||
== Contributing
|
||||
|
||||
include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/docs/modules/ROOT/partials/contributing-docs.adoc[]
|
||||
include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/docs/src/main/asciidoc/contributing.adoc[]
|
||||
|
||||
== License
|
||||
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
|===
|
||||
|Name | Default | Description
|
||||
|
||||
|eureka.client.eureka-connection-idle-timeout-seconds | `+++30+++` | Indicates how much time (in seconds) that the HTTP connections to eureka server can stay idle before it can be closed. In the AWS environment, it is recommended that the values is 30 seconds or less, since the firewall cleans up the connection information after a few mins leaving the connection hanging in limbo.
|
||||
|eureka.client.eureka-server-connect-timeout-seconds | `+++5+++` | Indicates how long to wait (in seconds) before a connection to eureka server needs to timeout. Note that the connections in the client are pooled by {@link HttpClient} and this setting affects the actual connection creation and also the wait time to get the connection from the pool.
|
||||
|eureka.client.eureka-connection-idle-timeout-seconds | `30` | Indicates how much time (in seconds) that the HTTP connections to eureka server can stay idle before it can be closed. In the AWS environment, it is recommended that the values is 30 seconds or less, since the firewall cleans up the connection information after a few mins leaving the connection hanging in limbo.
|
||||
|eureka.client.eureka-server-connect-timeout-seconds | `5` | Indicates how long to wait (in seconds) before a connection to eureka server needs to timeout. Note that the connections in the client are pooled by org.apache.http.client.HttpClient and this setting affects the actual connection creation and also the wait time to get the connection from the pool.
|
||||
|eureka.client.eureka-server-d-n-s-name | | Gets the DNS name to be queried to get the list of eureka servers.This information is not required if the contract returns the service urls by implementing serviceUrls. The DNS mechanism is used when useDnsForFetchingServiceUrls is set to true and the eureka client expects the DNS to configured a certain way so that it can fetch changing eureka servers dynamically. The changes are effective at runtime.
|
||||
|eureka.client.eureka-server-port | | Gets the port to be used to construct the service url to contact eureka server when the list of eureka servers come from the DNS.This information is not required if the contract returns the service urls eurekaServerServiceUrls(String). The DNS mechanism is used when useDnsForFetchingServiceUrls is set to true and the eureka client expects the DNS to configured a certain way so that it can fetch changing eureka servers dynamically. The changes are effective at runtime.
|
||||
|eureka.client.eureka-server-read-timeout-seconds | `+++8+++` | Indicates how long to wait (in seconds) before a read from eureka server needs to timeout.
|
||||
|eureka.client.eureka-server-total-connections | `+++200+++` | Gets the total number of connections that is allowed from eureka client to all eureka servers.
|
||||
|eureka.client.eureka-server-total-connections-per-host | `+++50+++` | Gets the total number of connections that is allowed from eureka client to a eureka server host.
|
||||
|eureka.client.eureka-server-read-timeout-seconds | `8` | Indicates how long to wait (in seconds) before a read from eureka server needs to timeout.
|
||||
|eureka.client.eureka-server-total-connections | `200` | Gets the total number of connections that is allowed from eureka client to all eureka servers.
|
||||
|eureka.client.eureka-server-total-connections-per-host | `50` | Gets the total number of connections that is allowed from eureka client to a eureka server host.
|
||||
|eureka.client.eureka-server-u-r-l-context | | Gets the URL context to be used to construct the service url to contact eureka server when the list of eureka servers come from the DNS. This information is not required if the contract returns the service urls from eurekaServerServiceUrls. The DNS mechanism is used when useDnsForFetchingServiceUrls is set to true and the eureka client expects the DNS to configured a certain way so that it can fetch changing eureka servers dynamically. The changes are effective at runtime.
|
||||
|eureka.client.eureka-service-url-poll-interval-seconds | `+++0+++` | Indicates how often(in seconds) to poll for changes to eureka server information. Eureka servers could be added or removed and this setting controls how soon the eureka clients should know about it.
|
||||
|eureka.client.prefer-same-zone-eureka | `+++true+++` | Indicates whether or not this instance should try to use the eureka server in the same zone for latency and/or other reason. Ideally eureka clients are configured to talk to servers in the same zone The changes are effective at runtime at the next registry fetch cycle as specified by registryFetchIntervalSeconds
|
||||
|eureka.client.register-with-eureka | `+++true+++` | Indicates whether or not this instance should register its information with eureka server for discovery by others. In some cases, you do not want your instances to be discovered whereas you just want do discover other instances.
|
||||
|eureka.server.peer-eureka-nodes-update-interval-ms | `+++0+++` |
|
||||
|eureka.server.peer-eureka-status-refresh-time-interval-ms | `+++0+++` |
|
||||
|spring.cloud.loadbalancer.eureka.approximate-zone-from-hostname | `+++false+++` | Used to determine whether we should try to get the `zone` value from host name.
|
||||
|eureka.client.eureka-service-url-poll-interval-seconds | `0` | Indicates how often(in seconds) to poll for changes to eureka server information. Eureka servers could be added or removed and this setting controls how soon the eureka clients should know about it.
|
||||
|eureka.client.prefer-same-zone-eureka | `true` | Indicates whether or not this instance should try to use the eureka server in the same zone for latency and/or other reason. Ideally eureka clients are configured to talk to servers in the same zone The changes are effective at runtime at the next registry fetch cycle as specified by registryFetchIntervalSeconds
|
||||
|eureka.client.register-with-eureka | `true` | Indicates whether or not this instance should register its information with eureka server for discovery by others. In some cases, you do not want your instances to be discovered whereas you just want do discover other instances.
|
||||
|eureka.server.peer-eureka-nodes-update-interval-ms | `0` |
|
||||
|eureka.server.peer-eureka-status-refresh-time-interval-ms | `0` |
|
||||
|ribbon.eureka.enabled | `true` | Enables the use of Eureka with Ribbon.
|
||||
|spring.cloud.loadbalancer.eureka.approximate-zone-from-hostname | `false` | Used to determine whether we should try to get the `zone` value from host name.
|
||||
|
||||
|===
|
||||
@@ -80,9 +80,6 @@ See {github-code}/spring-cloud-netflix-eureka-client/src/main/java/org/springfra
|
||||
|
||||
To disable the Eureka Discovery Client, you can set `eureka.client.enabled` to `false`. Eureka Discovery Client will also be disabled when `spring.cloud.discovery.enabled` is set to `false`.
|
||||
|
||||
|
||||
NOTE: Specifying the version of the Spring Cloud Netflix Eureka server as a path parameter is not currently supported. This means you cannot set the version in the context path (`eurekaServerURLContext`). Instead, you can include the version in the server URL (for example, you can set `defaultZone: http://localhost:8761/eureka/v2`).
|
||||
|
||||
=== Authenticating with the Eureka Server
|
||||
|
||||
HTTP basic authentication is automatically added to your eureka client if one of the `eureka.client.serviceUrl.defaultZone` URLs has credentials embedded in it (curl style, as follows: `https://user:password@localhost:8761/eureka`).
|
||||
@@ -112,19 +109,6 @@ NOTE: Because of a limitation in Eureka, it is not possible to support per-serve
|
||||
|
||||
If you want to customize the RestTemplate used by the Eureka HTTP Client you may want to create a bean of `EurekaClientHttpRequestFactorySupplier` and provide your own logic for generating a `ClientHttpRequestFactory` instance.
|
||||
|
||||
All default timeout-related properties for RestTemplate used by the Eureka HTTP Client are set to 3 minutes (in keeping with Apache HC5 default `RequestConfig` and `SocketConfig`). Therefore, to specify the timeout values, you must specify the value directly with the properties in `eureka.client.rest-template-timeout`. (All timeout properties are in milliseconds.)
|
||||
|
||||
.application.yml
|
||||
[source,yaml]
|
||||
----
|
||||
eureka:
|
||||
client:
|
||||
rest-template-timeout:
|
||||
connect-timeout: 5000
|
||||
connect-request-timeout: 8000
|
||||
socket-timeout: 10000
|
||||
----
|
||||
|
||||
=== Status Page and Health Indicator
|
||||
|
||||
The status page and health indicators for a Eureka instance default to `/info` and `/health` respectively, which are the default locations of useful endpoints in a Spring Boot Actuator application.
|
||||
@@ -307,7 +291,7 @@ The following example shows the dependencies you need to add:
|
||||
|
||||
You need not use the raw Netflix `EurekaClient`.
|
||||
Also, it is usually more convenient to use it behind a wrapper of some sort.
|
||||
Spring Cloud has support for <<spring-cloud-feign, Feign>> (a REST client builder) and https://docs.spring.io/spring-cloud-commons/docs/current/reference/html/#spring-cloud-loadbalancer[Spring Cloud LoadBalancer] through the logical Eureka service identifiers (VIPs) instead of physical URLs.
|
||||
Spring Cloud has support for <<spring-cloud-feign, Feign>> (a REST client builder) and <<spring-cloud-ribbon, Spring `RestTemplate`>> through the logical Eureka service identifiers (VIPs) instead of physical URLs.
|
||||
|
||||
You can also use the `org.springframework.cloud.client.discovery.DiscoveryClient`, which provides a simple API (not specific to Netflix) for discovery clients, as shown in the following example:
|
||||
|
||||
@@ -379,12 +363,6 @@ it can use the domain name from the server hostname as a proxy for the zone.
|
||||
If there is no other source of zone data, then a guess is made, based on the client configuration (as opposed to the instance configuration).
|
||||
We take `eureka.client.availabilityZones`, which is a map from region name to a list of zones, and pull out the first zone for the instance's own region (that is, the `eureka.client.region`, which defaults to "us-east-1", for compatibility with native Netflix).
|
||||
|
||||
=== AOT and Native Image Support
|
||||
|
||||
Spring Cloud Netflix Eureka Client integration supports Spring AOT transformations and native images, however, only with refresh mode disabled.
|
||||
|
||||
WARNING: If you want to run Eureka Client in AOT or native image modes, make sure to set `spring.cloud.refresh.enabled` to `false`
|
||||
|
||||
[[spring-cloud-eureka-server]]
|
||||
== Service Discovery: Eureka Server
|
||||
|
||||
@@ -452,10 +430,6 @@ dependencyManagement {
|
||||
----
|
||||
====
|
||||
|
||||
=== `defaultOpenForTrafficCount` and its effect on EurekaServer warmup time
|
||||
|
||||
Netflix Eureka's `waitTimeInMsWhenSyncEmpty` setting is not taken into account in Spring Cloud Eureka server at the beginning. In order to enable the warmup time, set `eureka.server.defaultOpenForTrafficCount=0`.
|
||||
|
||||
[[spring-cloud-eureka-server-zones-and-regions]]
|
||||
=== High Availability, Zones and Regions
|
||||
|
||||
@@ -575,26 +549,27 @@ You can set your hostname at the run-time by using an environment variable -- fo
|
||||
=== Securing The Eureka Server
|
||||
|
||||
You can secure your Eureka server simply by adding Spring Security to your
|
||||
server's classpath via `spring-boot-starter-security`. By default, when Spring Security is on the classpath it will require that
|
||||
server's classpath via `spring-boot-starter-security`. By default when Spring Security is on the classpath it will require that
|
||||
a valid CSRF token be sent with every request to the app. Eureka clients will not generally possess a valid
|
||||
cross site request forgery (CSRF) token you will need to disable this requirement for the `/eureka/**` endpoints.
|
||||
For example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests((authz) -> authz
|
||||
.anyRequest().authenticated())
|
||||
.httpBasic(withDefaults());
|
||||
http.csrf().ignoringRequestMatchers("/eureka/**");
|
||||
return http.build();
|
||||
@EnableWebSecurity
|
||||
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.csrf().ignoringAntMatchers("/eureka/**");
|
||||
super.configure(http);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
For more information on CSRF see the https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#csrf[Spring Security documentation].
|
||||
|
||||
A demo Eureka Server can be found in the Spring Cloud Samples https://github.com/spring-cloud-samples/eureka/tree/Eureka-With-Security-4.x[repo].
|
||||
A demo Eureka Server can be found in the Spring Cloud Samples https://github.com/spring-cloud-samples/eureka/tree/Eureka-With-Security[repo].
|
||||
|
||||
=== JDK 11 Support
|
||||
|
||||
@@ -609,10 +584,6 @@ when running a Eureka server you must include these dependencies in your POM or
|
||||
</dependency>
|
||||
----
|
||||
|
||||
=== AOT and Native Image Support
|
||||
|
||||
Spring Cloud Netflix Eureka Server does not support Spring AOT transformations or native images.
|
||||
|
||||
== Configuration properties
|
||||
|
||||
To see the list of all Spring Cloud Netflix related configuration properties please check link:appendix.html[the Appendix page].
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>4.0.4-SNAPSHOT</version>
|
||||
<version>3.1.2-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Spring Cloud Netflix</name>
|
||||
<description>Spring Cloud Netflix</description>
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-build</artifactId>
|
||||
<version>4.0.6-SNAPSHOT</version>
|
||||
<version>3.1.2-SNAPSHOT</version>
|
||||
<relativePath />
|
||||
</parent>
|
||||
<scm>
|
||||
@@ -21,19 +21,16 @@
|
||||
</scm>
|
||||
<properties>
|
||||
<bintray.package>netflix</bintray.package>
|
||||
<spring-cloud-commons.version>4.0.5-SNAPSHOT</spring-cloud-commons.version>
|
||||
<spring-cloud-config.version>4.0.5-SNAPSHOT</spring-cloud-config.version>
|
||||
<testcontainers.version>1.17.6</testcontainers.version>
|
||||
<mockserverclient.version>5.15.0</mockserverclient.version>
|
||||
<spring-cloud-commons.version>3.1.2-SNAPSHOT</spring-cloud-commons.version>
|
||||
<spring-cloud-config.version>3.1.2-SNAPSHOT</spring-cloud-config.version>
|
||||
|
||||
<!-- Sonar -->
|
||||
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
|
||||
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
|
||||
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
|
||||
<sonar.language>java</sonar.language>
|
||||
<eureka-jersey.version>1.19.4</eureka-jersey.version>
|
||||
<maven-resources-plugin.version>3.1.0</maven-resources-plugin.version>
|
||||
<!-- FIXME: 4.0.0 -->
|
||||
<duplicate-finder-maven-plugin.skip>true</duplicate-finder-maven-plugin.skip>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -59,6 +56,14 @@
|
||||
</additionalConfig>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>io.spring.javaformat</groupId>
|
||||
<artifactId>spring-javaformat-maven-plugin</artifactId>
|
||||
@@ -76,7 +81,6 @@
|
||||
<ignoredResourcePattern>plugin.properties</ignoredResourcePattern>
|
||||
<ignoredResourcePattern>mozilla/public-suffix-list.txt</ignoredResourcePattern>
|
||||
</ignoredResourcePatterns>
|
||||
<checkTestClasspath>false</checkTestClasspath>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
@@ -116,23 +120,32 @@
|
||||
<version>1</version>
|
||||
</dependency>
|
||||
<!-- Eureka core dep that is now optional -->
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-servlet</artifactId>
|
||||
<version>${eureka-jersey.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-core</artifactId>
|
||||
<version>${eureka-jersey.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-client</artifactId>
|
||||
<version>${eureka-jersey.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-server</artifactId>
|
||||
<version>${eureka-jersey.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey.contribs</groupId>
|
||||
<artifactId>jersey-apache-client4</artifactId>
|
||||
<version>${eureka-jersey.version}</version>
|
||||
</dependency>
|
||||
<!-- end eureka deps -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>mockserver</artifactId>
|
||||
<version>${testcontainers.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>${testcontainers.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-client-java</artifactId>
|
||||
<version>${mockserverclient.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<reporting>
|
||||
|
||||
@@ -4,7 +4,7 @@ set -o errexit
|
||||
|
||||
mkdir -p target
|
||||
|
||||
SCRIPT_URL="https://raw.githubusercontent.com/spring-cloud-samples/brewery/3.1.x/runAcceptanceTests.sh"
|
||||
SCRIPT_URL="https://raw.githubusercontent.com/spring-cloud-samples/brewery/main/runAcceptanceTests.sh"
|
||||
AT_WHAT_TO_TEST="EUREKA"
|
||||
|
||||
cd target
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
<parent>
|
||||
<artifactId>spring-cloud-dependencies-parent</artifactId>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<version>4.0.6-SNAPSHOT</version>
|
||||
<version>3.1.2-SNAPSHOT</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-dependencies</artifactId>
|
||||
<version>4.0.4-SNAPSHOT</version>
|
||||
<version>3.1.2-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>spring-cloud-netflix-dependencies</name>
|
||||
<description>Spring Cloud Netflix Dependencies</description>
|
||||
<properties>
|
||||
<eureka.version>2.0.1</eureka.version>
|
||||
<eureka.version>1.10.17</eureka.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
@@ -67,10 +67,6 @@
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.glassfish.jersey.core</groupId>
|
||||
<artifactId>jersey-client</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -116,22 +112,6 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.eureka</groupId>
|
||||
<artifactId>eureka-core-jersey3</artifactId>
|
||||
<version>${eureka.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.eureka</groupId>
|
||||
<artifactId>eureka-client-jersey3</artifactId>
|
||||
<version>${eureka.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>aopalliance</groupId>
|
||||
<artifactId>aopalliance</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- TODO: Move back to Eureka dependency when 1.10.17 released -->
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>4.0.4-SNAPSHOT</version>
|
||||
<version>3.1.2-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-eureka-client-tls-tests</artifactId>
|
||||
@@ -82,11 +82,6 @@
|
||||
<artifactId>spring-boot-autoconfigure-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
@@ -120,12 +115,6 @@
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
+4
-4
@@ -22,15 +22,15 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.test.TestSocketUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
public class AppRunner implements AutoCloseable {
|
||||
|
||||
private final Class<?> appClass;
|
||||
private Class<?> appClass;
|
||||
|
||||
private final Map<String, String> props;
|
||||
private Map<String, String> props;
|
||||
|
||||
private ConfigurableApplicationContext app;
|
||||
|
||||
@@ -56,7 +56,7 @@ public class AppRunner implements AutoCloseable {
|
||||
}
|
||||
|
||||
private int availabeTcpPort() {
|
||||
return TestSocketUtils.findAvailableTcpPort();
|
||||
return SocketUtils.findAvailableTcpPort();
|
||||
}
|
||||
|
||||
private String[] props() {
|
||||
|
||||
+7
-5
@@ -56,7 +56,6 @@ abstract class BaseCertTest {
|
||||
protected BaseCertTest() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
static EurekaServerRunner startEurekaServer(Class config) {
|
||||
EurekaServerRunner server = new EurekaServerRunner(config);
|
||||
server.enableTls();
|
||||
@@ -71,7 +70,6 @@ abstract class BaseCertTest {
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
static EurekaClientRunner startService(EurekaServerRunner server, Class config) {
|
||||
EurekaClientRunner service = new EurekaClientRunner(config, server, "testservice");
|
||||
enableTlsClient(service);
|
||||
@@ -155,7 +153,9 @@ abstract class BaseCertTest {
|
||||
EurekaClientRunner client = createEurekaClient();
|
||||
enableTlsClient(client);
|
||||
client.setKeyStore(clientCert, WRONG_PASSWORD, WRONG_PASSWORD);
|
||||
Assertions.assertThrows(BeanCreationException.class, client::start);
|
||||
Assertions.assertThrows(BeanCreationException.class, () -> {
|
||||
client.start();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -163,7 +163,9 @@ abstract class BaseCertTest {
|
||||
EurekaClientRunner client = createEurekaClient();
|
||||
enableTlsClient(client);
|
||||
client.setKeyStore(new File("nonExistFile"));
|
||||
Assertions.assertThrows(BeanCreationException.class, client::start);
|
||||
Assertions.assertThrows(BeanCreationException.class, () -> {
|
||||
client.start();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -181,7 +183,7 @@ abstract class BaseCertTest {
|
||||
}
|
||||
|
||||
private static File saveCert(KeyAndCert keyCert) throws Exception {
|
||||
return saveKeyStore(keyCert.subject(), keyCert::storeCert);
|
||||
return saveKeyStore(keyCert.subject(), () -> keyCert.storeCert());
|
||||
}
|
||||
|
||||
private static File saveKeyStore(String prefix, KeyStoreSupplier func) throws Exception {
|
||||
|
||||
+3
-4
@@ -72,13 +72,13 @@ public class EurekaClientRunner extends AppRunner {
|
||||
}
|
||||
|
||||
public void waitServiceViaEureka(int seconds) {
|
||||
assertInSeconds(this::foundServiceViaEureka, seconds);
|
||||
assertInSeconds(() -> foundServiceViaEureka(), seconds);
|
||||
}
|
||||
|
||||
private void assertInSeconds(BooleanSupplier assertion, int seconds) {
|
||||
long start = System.currentTimeMillis();
|
||||
long limit = 1000L * seconds;
|
||||
long duration;
|
||||
long duration = 0;
|
||||
|
||||
do {
|
||||
if (assertion.getAsBoolean()) {
|
||||
@@ -98,9 +98,8 @@ public class EurekaClientRunner extends AppRunner {
|
||||
return !discovery.getServices().isEmpty();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public AbstractDiscoveryClientOptionalArgs<Void> discoveryClientOptionalArgs() {
|
||||
return getBean(AbstractDiscoveryClientOptionalArgs.class);
|
||||
return this.getBean(AbstractDiscoveryClientOptionalArgs.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-2
@@ -16,13 +16,13 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka;
|
||||
|
||||
import com.netflix.discovery.DiscoveryClient;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs;
|
||||
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -39,7 +39,9 @@ public class EurekaClientTest extends BaseCertTest {
|
||||
public static void setupAll() {
|
||||
server = startEurekaServer(EurekaClientTest.TestEurekaServer.class);
|
||||
service = startService(server, EurekaClientTest.TestApp.class);
|
||||
assertThat(service.discoveryClientOptionalArgs()).isInstanceOf(RestTemplateDiscoveryClientOptionalArgs.class);
|
||||
// Will use Jersey
|
||||
assertThat(service.discoveryClientOptionalArgs())
|
||||
.isInstanceOf(DiscoveryClient.DiscoveryClientOptionalArgs.class);
|
||||
log.info("Successfully asserted that Jersey will be used");
|
||||
waitForRegistration(() -> new EurekaClientTest().createEurekaClient());
|
||||
}
|
||||
|
||||
+3
-3
@@ -25,9 +25,9 @@ import java.security.cert.X509Certificate;
|
||||
|
||||
public class KeyAndCert {
|
||||
|
||||
private final KeyPair keyPair;
|
||||
private KeyPair keyPair;
|
||||
|
||||
private final X509Certificate certificate;
|
||||
private X509Certificate certificate;
|
||||
|
||||
public KeyAndCert(KeyPair keyPair, X509Certificate certificate) {
|
||||
this.keyPair = keyPair;
|
||||
@@ -51,7 +51,7 @@ public class KeyAndCert {
|
||||
}
|
||||
|
||||
public String subject() {
|
||||
String dn = certificate.getSubjectX500Principal().getName();
|
||||
String dn = certificate.getSubjectDN().getName();
|
||||
int index = dn.indexOf('=');
|
||||
return dn.substring(index + 1);
|
||||
}
|
||||
|
||||
+3
-1
@@ -56,7 +56,9 @@ public class KeyTool {
|
||||
|
||||
public KeyAndCert signCertificate(KeyPair keyPair, String subject, KeyAndCert signer) throws Exception {
|
||||
X509Certificate certificate = createCert(keyPair.getPublic(), signer.privateKey(), signer.subject(), subject);
|
||||
return new KeyAndCert(keyPair, certificate);
|
||||
KeyAndCert result = new KeyAndCert(keyPair, certificate);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public KeyPair createKeyPair() throws Exception {
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>4.0.4-SNAPSHOT</version>
|
||||
<version>3.1.2-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
|
||||
@@ -15,7 +14,7 @@
|
||||
<description>Spring Cloud Netflix Eureka Client</description>
|
||||
<properties>
|
||||
<!-- Why do I need this now? -->
|
||||
<maven.javadoc.failOnError>false</maven.javadoc.failOnError>
|
||||
<maven.javadoc.failOnError>false</maven.javadoc.failOnError>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -41,7 +40,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-config-server</artifactId>
|
||||
<scope>test</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
@@ -51,6 +50,43 @@
|
||||
<dependency>
|
||||
<groupId>com.netflix.eureka</groupId>
|
||||
<artifactId>eureka-client</artifactId>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-client</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-core</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jersey.contribs</groupId>
|
||||
<artifactId>jersey-apache-client4</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>aopalliance</groupId>
|
||||
<artifactId>aopalliance</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-core</artifactId>
|
||||
<version>${eureka-jersey.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-client</artifactId>
|
||||
<version>${eureka-jersey.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey.contribs</groupId>
|
||||
<artifactId>jersey-apache-client4</artifactId>
|
||||
<version>${eureka-jersey.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
@@ -68,10 +104,6 @@
|
||||
<artifactId>spring-boot-autoconfigure-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||
<artifactId>httpclient5</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
@@ -108,20 +140,5 @@
|
||||
<artifactId>reactor-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>mockserver</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-client-java</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
+8
-10
@@ -28,7 +28,6 @@ import com.netflix.discovery.DiscoveryClient;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpResponse;
|
||||
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -49,23 +48,22 @@ public class CloudEurekaClient extends DiscoveryClient {
|
||||
|
||||
private final AtomicLong cacheRefreshedCount = new AtomicLong(0);
|
||||
|
||||
private final ApplicationEventPublisher publisher;
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
private final Field eurekaTransportField;
|
||||
private Field eurekaTransportField;
|
||||
|
||||
private final ApplicationInfoManager applicationInfoManager;
|
||||
private ApplicationInfoManager applicationInfoManager;
|
||||
|
||||
private final AtomicReference<EurekaHttpClient> eurekaHttpClient = new AtomicReference<>();
|
||||
private AtomicReference<EurekaHttpClient> eurekaHttpClient = new AtomicReference<>();
|
||||
|
||||
public CloudEurekaClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config,
|
||||
TransportClientFactories transportClientFactories, ApplicationEventPublisher publisher) {
|
||||
this(applicationInfoManager, config, transportClientFactories, null, publisher);
|
||||
ApplicationEventPublisher publisher) {
|
||||
this(applicationInfoManager, config, null, publisher);
|
||||
}
|
||||
|
||||
public CloudEurekaClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config,
|
||||
TransportClientFactories transportClientFactories, AbstractDiscoveryClientOptionalArgs<?> args,
|
||||
ApplicationEventPublisher publisher) {
|
||||
super(applicationInfoManager, config, transportClientFactories, args);
|
||||
AbstractDiscoveryClientOptionalArgs<?> args, ApplicationEventPublisher publisher) {
|
||||
super(applicationInfoManager, config, args);
|
||||
this.applicationInfoManager = applicationInfoManager;
|
||||
this.publisher = publisher;
|
||||
this.eurekaTransportField = ReflectionUtils.findField(DiscoveryClient.class, "eurekaTransport");
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.eureka;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Convenience annotation for clients to enable Eureka discovery configuration
|
||||
* (specifically). Use this (optionally) in case you want discovery and know for sure that
|
||||
* it is Eureka you want. All it does is turn on discovery and let the autoconfiguration
|
||||
* find the eureka classes if they are available (i.e. you need Eureka on the classpath as
|
||||
* well).
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface EnableEurekaClient {
|
||||
|
||||
}
|
||||
+9
-115
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,36 +24,14 @@ import java.lang.annotation.Target;
|
||||
import java.util.Map;
|
||||
|
||||
import com.netflix.appinfo.ApplicationInfoManager;
|
||||
import com.netflix.appinfo.DataCenterInfo;
|
||||
import com.netflix.appinfo.EurekaInstanceConfig;
|
||||
import com.netflix.appinfo.HealthCheckHandler;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.appinfo.LeaseInfo;
|
||||
import com.netflix.appinfo.MyDataCenterInfo;
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
|
||||
import com.netflix.discovery.DiscoveryClient;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.TimedSupervisorTask;
|
||||
import com.netflix.discovery.converters.jackson.DataCenterTypeInfoResolver;
|
||||
import com.netflix.discovery.converters.jackson.builder.ApplicationsJacksonBuilder;
|
||||
import com.netflix.discovery.converters.jackson.mixin.InstanceInfoJsonMixIn;
|
||||
import com.netflix.discovery.shared.Application;
|
||||
import com.netflix.discovery.shared.Applications;
|
||||
import com.netflix.discovery.shared.resolver.AsyncResolver;
|
||||
import com.netflix.discovery.shared.resolver.DefaultEndpoint;
|
||||
import com.netflix.discovery.shared.resolver.EurekaEndpoint;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpResponse;
|
||||
import com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator;
|
||||
import com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aot.hint.MemberCategory;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
import org.springframework.aot.hint.TypeReference;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
|
||||
@@ -89,7 +67,6 @@ import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceId;
|
||||
@@ -116,7 +93,7 @@ import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceI
|
||||
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration" })
|
||||
public class EurekaClientAutoConfiguration {
|
||||
|
||||
private final ConfigurableEnvironment env;
|
||||
private ConfigurableEnvironment env;
|
||||
|
||||
public EurekaClientAutoConfiguration(ConfigurableEnvironment env) {
|
||||
this.env = env;
|
||||
@@ -257,14 +234,13 @@ public class EurekaClientAutoConfiguration {
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
|
||||
@Autowired(required = false)
|
||||
@Autowired
|
||||
private AbstractDiscoveryClientOptionalArgs<?> optionalArgs;
|
||||
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
|
||||
public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config,
|
||||
TransportClientFactories<?> transportClientFactories) {
|
||||
return new CloudEurekaClient(manager, config, transportClientFactories, this.optionalArgs, this.context);
|
||||
public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config) {
|
||||
return new CloudEurekaClient(manager, config, this.optionalArgs, this.context);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -293,7 +269,7 @@ public class EurekaClientAutoConfiguration {
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
|
||||
@Autowired(required = false)
|
||||
@Autowired
|
||||
private AbstractDiscoveryClientOptionalArgs<?> optionalArgs;
|
||||
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
@@ -301,8 +277,7 @@ public class EurekaClientAutoConfiguration {
|
||||
@org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
@Lazy
|
||||
public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config,
|
||||
EurekaInstanceConfig instance, TransportClientFactories<?> transportClientFactories,
|
||||
@Autowired(required = false) HealthCheckHandler healthCheckHandler) {
|
||||
EurekaInstanceConfig instance, @Autowired(required = false) HealthCheckHandler healthCheckHandler) {
|
||||
// If we use the proxy of the ApplicationInfoManager we could run into a
|
||||
// problem
|
||||
// when shutdown is called on the CloudEurekaClient where the
|
||||
@@ -317,8 +292,8 @@ public class EurekaClientAutoConfiguration {
|
||||
else {
|
||||
appManager = manager;
|
||||
}
|
||||
CloudEurekaClient cloudEurekaClient = new CloudEurekaClient(appManager, config, transportClientFactories,
|
||||
this.optionalArgs, this.context);
|
||||
CloudEurekaClient cloudEurekaClient = new CloudEurekaClient(appManager, config, this.optionalArgs,
|
||||
this.context);
|
||||
cloudEurekaClient.registerHealthCheck(healthCheckHandler);
|
||||
return cloudEurekaClient;
|
||||
}
|
||||
@@ -401,84 +376,3 @@ public class EurekaClientAutoConfiguration {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Remove after adding hints to GraalVM reachability metadata repo
|
||||
class EurekaClientHints implements RuntimeHintsRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
if (!ClassUtils.isPresent("com.netflix.discovery.DiscoveryClient", classLoader)) {
|
||||
return;
|
||||
}
|
||||
hints.reflection().registerType(TypeReference.of(DiscoveryClient.class),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(EurekaEndpoint.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(DefaultEndpoint.class),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
|
||||
.registerType(TypeReference.of(EurekaHttpClientDecorator.class),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS,
|
||||
MemberCategory.INTROSPECT_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(EurekaHttpResponse.class),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
|
||||
.registerType(TypeReference.of(EurekaHttpClientDecorator.RequestExecutor.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(ApplicationInfoManager.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS))
|
||||
.registerType(TypeReference.of(InstanceInfo.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.DECLARED_FIELDS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
|
||||
.registerType(TypeReference.of(InstanceInfo.ActionType.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(InstanceInfo.PortWrapper.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(LeaseInfo.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(MyDataCenterInfo.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(DataCenterInfo.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(DataCenterInfo.Name.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(EurekaClient.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_METHODS))
|
||||
.registerType(TypeReference.of(TimedSupervisorTask.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(DataCenterTypeInfoResolver.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS))
|
||||
.registerType(TypeReference.of(ApplicationsJacksonBuilder.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(InstanceInfoJsonMixIn.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(Application.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(Applications.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(AsyncResolver.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(RetryableEurekaHttpClient.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(SessionedEurekaHttpClient.class),
|
||||
hint -> hint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.DECLARED_FIELDS))
|
||||
.registerType(TypeReference.of(EurekaServiceInstance.class),
|
||||
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-5
@@ -25,7 +25,6 @@ import java.util.Objects;
|
||||
import com.netflix.appinfo.EurekaAccept;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.shared.transport.EurekaTransportConfig;
|
||||
import org.apache.hc.client5.http.classic.HttpClient;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@@ -127,14 +126,14 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
|
||||
/**
|
||||
* Indicates how long to wait (in seconds) before a connection to eureka server needs
|
||||
* to timeout. Note that the connections in the client are pooled by
|
||||
* {@link HttpClient} and this setting affects the actual connection creation and also
|
||||
* the wait time to get the connection from the pool.
|
||||
* org.apache.http.client.HttpClient and this setting affects the actual connection
|
||||
* creation and also the wait time to get the connection from the pool.
|
||||
*/
|
||||
private int eurekaServerConnectTimeoutSeconds = 5;
|
||||
|
||||
/**
|
||||
* Gets the name of the implementation which implements BackupRegistry to fetch the
|
||||
* registry information as a fallback option for only the first time when the eureka
|
||||
* registry information as a fall back option for only the first time when the eureka
|
||||
* client starts.
|
||||
*
|
||||
* This may be needed for applications which needs additional resiliency for registry
|
||||
@@ -473,7 +472,7 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
|
||||
if (serviceUrls == null || serviceUrls.isEmpty()) {
|
||||
serviceUrls = this.serviceUrl.get(DEFAULT_ZONE);
|
||||
}
|
||||
if (StringUtils.hasText(serviceUrls)) {
|
||||
if (!StringUtils.isEmpty(serviceUrls)) {
|
||||
final String[] serviceUrlsSplit = StringUtils.commaDelimitedListToStringArray(serviceUrls);
|
||||
List<String> eurekaServiceUrls = new ArrayList<>(serviceUrlsSplit.length);
|
||||
for (String eurekaServiceUrl : serviceUrlsSplit) {
|
||||
|
||||
+39
-48
@@ -19,21 +19,19 @@ package org.springframework.cloud.netflix.eureka;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.netflix.appinfo.HealthCheckHandler;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.actuate.health.CompositeHealthContributor;
|
||||
import org.springframework.boot.actuate.health.CompositeReactiveHealthContributor;
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.boot.actuate.health.HealthContributor;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
import org.springframework.boot.actuate.health.NamedContributor;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthContributor;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.Status;
|
||||
import org.springframework.boot.actuate.health.StatusAggregator;
|
||||
@@ -60,34 +58,33 @@ import org.springframework.util.Assert;
|
||||
* @author Spencer Gibb
|
||||
* @author Nowrin Anwar Joyita
|
||||
* @author Bertrand Renuart
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @see HealthCheckHandler
|
||||
* @see StatusAggregator
|
||||
*/
|
||||
public class EurekaHealthCheckHandler
|
||||
implements HealthCheckHandler, ApplicationContextAware, InitializingBean, Ordered, Lifecycle {
|
||||
|
||||
private static final Map<Status, InstanceInfo.InstanceStatus> STATUS_MAPPING = new HashMap<>() {
|
||||
private static final Map<Status, InstanceInfo.InstanceStatus> STATUS_MAPPING = new HashMap<Status, InstanceInfo.InstanceStatus>() {
|
||||
{
|
||||
put(Status.UNKNOWN, InstanceStatus.UNKNOWN);
|
||||
put(Status.OUT_OF_SERVICE, InstanceStatus.DOWN);
|
||||
put(Status.OUT_OF_SERVICE, InstanceStatus.OUT_OF_SERVICE);
|
||||
put(Status.DOWN, InstanceStatus.DOWN);
|
||||
put(Status.UP, InstanceStatus.UP);
|
||||
}
|
||||
};
|
||||
|
||||
private final StatusAggregator statusAggregator;
|
||||
private StatusAggregator statusAggregator;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private final Map<String, HealthContributor> healthContributors = new HashMap<>();
|
||||
private Map<String, HealthIndicator> healthIndicators = new HashMap<>();
|
||||
|
||||
/**
|
||||
* {@code true} until the context is stopped.
|
||||
*/
|
||||
private boolean running = true;
|
||||
|
||||
private final Map<String, ReactiveHealthContributor> reactiveHealthContributors = new HashMap<>();
|
||||
private Map<String, ReactiveHealthIndicator> reactiveHealthIndicators = new HashMap<>();
|
||||
|
||||
public EurekaHealthCheckHandler(StatusAggregator statusAggregator) {
|
||||
this.statusAggregator = statusAggregator;
|
||||
@@ -102,27 +99,39 @@ public class EurekaHealthCheckHandler
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
populateHealthContributors(applicationContext.getBeansOfType(HealthContributor.class));
|
||||
reactiveHealthContributors.putAll(applicationContext.getBeansOfType(ReactiveHealthContributor.class));
|
||||
final Map<String, HealthIndicator> healthIndicators = applicationContext.getBeansOfType(HealthIndicator.class);
|
||||
final Map<String, ReactiveHealthIndicator> reactiveHealthIndicators = applicationContext
|
||||
.getBeansOfType(ReactiveHealthIndicator.class);
|
||||
|
||||
populateHealthIndicators(healthIndicators);
|
||||
populateReactiveHealthIndicators(reactiveHealthIndicators);
|
||||
}
|
||||
|
||||
void populateHealthContributors(Map<String, HealthContributor> healthContributors) {
|
||||
for (Map.Entry<String, HealthContributor> entry : healthContributors.entrySet()) {
|
||||
void populateHealthIndicators(Map<String, HealthIndicator> healthIndicators) {
|
||||
for (Map.Entry<String, HealthIndicator> entry : healthIndicators.entrySet()) {
|
||||
// ignore EurekaHealthIndicator and flatten the rest of the composite
|
||||
// otherwise there is a never ending cycle of down. See gh-643
|
||||
if (entry.getValue() instanceof DiscoveryCompositeHealthContributor indicator) {
|
||||
indicator.getIndicators().forEach((name, discoveryHealthIndicator) -> {
|
||||
if (!(discoveryHealthIndicator instanceof EurekaHealthIndicator)) {
|
||||
this.healthContributors.put(name, (HealthIndicator) discoveryHealthIndicator::health);
|
||||
if (entry.getValue() instanceof DiscoveryCompositeHealthContributor) {
|
||||
DiscoveryCompositeHealthContributor indicator = (DiscoveryCompositeHealthContributor) entry.getValue();
|
||||
indicator.forEach(contributor -> {
|
||||
if (!(contributor.getContributor() instanceof EurekaHealthIndicator)) {
|
||||
this.healthIndicators.put(contributor.getName(),
|
||||
(HealthIndicator) contributor.getContributor());
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.healthContributors.put(entry.getKey(), entry.getValue());
|
||||
this.healthIndicators.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void populateReactiveHealthIndicators(Map<String, ReactiveHealthIndicator> reactiveHealthIndicators) {
|
||||
for (Map.Entry<String, ReactiveHealthIndicator> entry : reactiveHealthIndicators.entrySet()) {
|
||||
this.reactiveHealthIndicators.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceStatus getStatus(InstanceStatus instanceStatus) {
|
||||
if (running) {
|
||||
@@ -142,39 +151,21 @@ public class EurekaHealthCheckHandler
|
||||
}
|
||||
|
||||
protected Status getStatus(StatusAggregator statusAggregator) {
|
||||
Status status;
|
||||
|
||||
Set<Status> statusSet = new HashSet<>();
|
||||
for (HealthContributor contributor : healthContributors.values()) {
|
||||
processContributor(statusSet, contributor);
|
||||
if (healthIndicators != null) {
|
||||
statusSet.addAll(healthIndicators.values().stream().map(HealthIndicator::health).map(Health::getStatus)
|
||||
.collect(Collectors.toSet()));
|
||||
}
|
||||
for (ReactiveHealthContributor contributor : reactiveHealthContributors.values()) {
|
||||
processContributor(statusSet, contributor);
|
||||
}
|
||||
return statusAggregator.getAggregateStatus(statusSet);
|
||||
}
|
||||
|
||||
private void processContributor(Set<Status> statusSet, HealthContributor contributor) {
|
||||
if (contributor instanceof CompositeHealthContributor) {
|
||||
for (NamedContributor<HealthContributor> contrib : (CompositeHealthContributor) contributor) {
|
||||
processContributor(statusSet, contrib.getContributor());
|
||||
}
|
||||
if (reactiveHealthIndicators != null) {
|
||||
statusSet.addAll(reactiveHealthIndicators.values().stream().map(ReactiveHealthIndicator::health)
|
||||
.map(Mono::block).filter(Objects::nonNull).map(Health::getStatus).collect(Collectors.toSet()));
|
||||
}
|
||||
else if (contributor instanceof HealthIndicator) {
|
||||
statusSet.add(((HealthIndicator) contributor).health().getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
private void processContributor(Set<Status> statusSet, ReactiveHealthContributor contributor) {
|
||||
if (contributor instanceof CompositeReactiveHealthContributor) {
|
||||
for (NamedContributor<ReactiveHealthContributor> contrib : (CompositeReactiveHealthContributor) contributor) {
|
||||
processContributor(statusSet, contrib.getContributor());
|
||||
}
|
||||
}
|
||||
else if (contributor instanceof ReactiveHealthIndicator) {
|
||||
Health health = ((ReactiveHealthIndicator) contributor).health().block();
|
||||
if (health != null) {
|
||||
statusSet.add(health.getStatus());
|
||||
}
|
||||
}
|
||||
status = statusAggregator.getAggregateStatus(statusSet);
|
||||
return status;
|
||||
}
|
||||
|
||||
protected InstanceStatus mapToInstanceStatus(Status status) {
|
||||
|
||||
+1
-1
@@ -92,7 +92,7 @@ public class EurekaHealthIndicator implements DiscoveryHealthIndicator {
|
||||
if (AopUtils.isAopProxy(eurekaClient)) {
|
||||
discoveryClient = ProxyUtils.getTargetObject(eurekaClient);
|
||||
}
|
||||
else if (eurekaClient instanceof DiscoveryClient) {
|
||||
else if (DiscoveryClient.class.isInstance(eurekaClient)) {
|
||||
discoveryClient = (DiscoveryClient) eurekaClient;
|
||||
}
|
||||
return discoveryClient;
|
||||
|
||||
+1
-3
@@ -25,7 +25,6 @@ import com.netflix.appinfo.DataCenterInfo;
|
||||
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
|
||||
import com.netflix.appinfo.MyDataCenterInfo;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.commons.util.InetUtils;
|
||||
import org.springframework.cloud.commons.util.InetUtils.HostInfo;
|
||||
@@ -286,7 +285,6 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
|
||||
private EurekaInstanceConfigBean() {
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public EurekaInstanceConfigBean(InetUtils inetUtils) {
|
||||
this.inetUtils = inetUtils;
|
||||
this.hostInfo = this.inetUtils.findFirstNonLoopbackHostInfo();
|
||||
@@ -607,7 +605,7 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, Envi
|
||||
leaseExpirationDurationInSeconds, virtualHostName, instanceId, secureVirtualHostName, aSGName,
|
||||
metadataMap, dataCenterInfo, ipAddress, statusPageUrlPath, statusPageUrl, homePageUrlPath, homePageUrl,
|
||||
healthCheckUrlPath, healthCheckUrl, secureHealthCheckUrl, namespace, hostname, preferIpAddress,
|
||||
initialStatus, Arrays.hashCode(defaultAddressResolutionOrder), environment);
|
||||
initialStatus, defaultAddressResolutionOrder, environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ import static com.netflix.appinfo.InstanceInfo.PortType.SECURE;
|
||||
*/
|
||||
public class EurekaServiceInstance implements ServiceInstance {
|
||||
|
||||
private final InstanceInfo instance;
|
||||
private InstanceInfo instance;
|
||||
|
||||
public EurekaServiceInstance(InstanceInfo instance) {
|
||||
Assert.notNull(instance, "Service instance required");
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.eureka;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
import com.netflix.discovery.DiscoveryClient.DiscoveryClientOptionalArgs;
|
||||
import com.sun.jersey.api.client.filter.ClientFilter;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class MutableDiscoveryClientOptionalArgs extends DiscoveryClientOptionalArgs {
|
||||
|
||||
private Collection<ClientFilter> additionalFilters;
|
||||
|
||||
@Override
|
||||
public void setAdditionalFilters(Collection<ClientFilter> additionalFilters) {
|
||||
additionalFilters = new LinkedHashSet<>(additionalFilters);
|
||||
this.additionalFilters = additionalFilters;
|
||||
super.setAdditionalFilters(additionalFilters);
|
||||
}
|
||||
|
||||
public Collection<ClientFilter> getAdditionalFilters() {
|
||||
return this.additionalFilters;
|
||||
}
|
||||
|
||||
}
|
||||
-98
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.eureka;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.core5.http.io.SocketConfig;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateEurekaHttpClient;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Properties for configuring timeouts used in {@link RestTemplate} required by
|
||||
* {@link RestTemplateEurekaHttpClient}.
|
||||
*
|
||||
* @author Jiwon Jeon
|
||||
* @since 3.1.6
|
||||
*/
|
||||
@ConfigurationProperties("eureka.client.rest-template-timeout")
|
||||
public class RestTemplateTimeoutProperties {
|
||||
|
||||
/**
|
||||
* Default values are set to 180000, in keeping with {@link RequestConfig} and
|
||||
* {@link SocketConfig} defaults.
|
||||
*/
|
||||
private int connectTimeout = 3 * 60 * 1000;
|
||||
|
||||
private int connectRequestTimeout = 3 * 60 * 1000;
|
||||
|
||||
private int socketTimeout = 3 * 60 * 1000;
|
||||
|
||||
public int getConnectTimeout() {
|
||||
return connectTimeout;
|
||||
}
|
||||
|
||||
public int getConnectRequestTimeout() {
|
||||
return connectRequestTimeout;
|
||||
}
|
||||
|
||||
public int getSocketTimeout() {
|
||||
return socketTimeout;
|
||||
}
|
||||
|
||||
public void setConnectTimeout(int connectTimeout) {
|
||||
this.connectTimeout = connectTimeout;
|
||||
}
|
||||
|
||||
public void setConnectRequestTimeout(int connectRequestTimeout) {
|
||||
this.connectRequestTimeout = connectRequestTimeout;
|
||||
}
|
||||
|
||||
public void setSocketTimeout(int socketTimeout) {
|
||||
this.socketTimeout = socketTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RestTemplateTimeoutProperties that = (RestTemplateTimeoutProperties) o;
|
||||
|
||||
return connectTimeout == that.connectTimeout && connectRequestTimeout == that.connectRequestTimeout
|
||||
&& socketTimeout == that.socketTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(connectTimeout, connectRequestTimeout, socketTimeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RestTemplateTimeoutProperties{" + ", connectTimeout=" + connectTimeout + ", connectRequestTimeout="
|
||||
+ connectRequestTimeout + ", socketTimeout=" + socketTimeout + '}';
|
||||
}
|
||||
|
||||
}
|
||||
+15
-42
@@ -20,29 +20,24 @@ import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
|
||||
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.configuration.SSLContextFactory;
|
||||
import org.springframework.cloud.configuration.TlsProperties;
|
||||
import org.springframework.cloud.netflix.eureka.RestTemplateTimeoutProperties;
|
||||
import org.springframework.cloud.netflix.eureka.MutableDiscoveryClientOptionalArgs;
|
||||
import org.springframework.cloud.netflix.eureka.http.DefaultEurekaClientHttpRequestFactorySupplier;
|
||||
import org.springframework.cloud.netflix.eureka.http.EurekaClientHttpRequestFactorySupplier;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClientFactories;
|
||||
import org.springframework.cloud.netflix.eureka.http.WebClientDiscoveryClientOptionalArgs;
|
||||
import org.springframework.cloud.netflix.eureka.http.WebClientTransportClientFactories;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
@@ -51,7 +46,6 @@ import org.springframework.web.reactive.function.client.WebClient;
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(RestTemplateTimeoutProperties.class)
|
||||
public class DiscoveryClientOptionalArgsConfiguration {
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(DiscoveryClientOptionalArgsConfiguration.class);
|
||||
@@ -64,7 +58,7 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
|
||||
@ConditionalOnMissingClass("org.glassfish.jersey.client.JerseyClient")
|
||||
@ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter")
|
||||
@ConditionalOnMissingBean(value = { AbstractDiscoveryClientOptionalArgs.class }, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", matchIfMissing = true,
|
||||
havingValue = "false")
|
||||
@@ -79,22 +73,21 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
|
||||
@ConditionalOnMissingClass("org.glassfish.jersey.client.JerseyClient")
|
||||
@ConditionalOnMissingBean(value = { TransportClientFactories.class }, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", matchIfMissing = true,
|
||||
havingValue = "false")
|
||||
public RestTemplateTransportClientFactories restTemplateTransportClientFactories(
|
||||
RestTemplateDiscoveryClientOptionalArgs optionalArgs) {
|
||||
return new RestTemplateTransportClientFactories(optionalArgs);
|
||||
EurekaClientHttpRequestFactorySupplier defaultEurekaClientHttpRequestFactorySupplier() {
|
||||
return new DefaultEurekaClientHttpRequestFactorySupplier();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
|
||||
EurekaClientHttpRequestFactorySupplier defaultEurekaClientHttpRequestFactorySupplier(
|
||||
RestTemplateTimeoutProperties restTemplateTimeoutProperties) {
|
||||
return new DefaultEurekaClientHttpRequestFactorySupplier(restTemplateTimeoutProperties);
|
||||
@ConditionalOnClass(name = "com.sun.jersey.api.client.filter.ClientFilter")
|
||||
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
|
||||
public MutableDiscoveryClientOptionalArgs discoveryClientOptionalArgs(TlsProperties tlsProperties)
|
||||
throws GeneralSecurityException, IOException {
|
||||
logger.info("Eureka HTTP Client uses Jersey");
|
||||
MutableDiscoveryClientOptionalArgs result = new MutableDiscoveryClientOptionalArgs();
|
||||
setupTLS(result, tlsProperties);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void setupTLS(AbstractDiscoveryClientOptionalArgs<?> args, TlsProperties properties)
|
||||
@@ -105,20 +98,7 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(name = "org.glassfish.jersey.client.JerseyClient")
|
||||
@ConditionalOnBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
|
||||
static class DiscoveryClientOptionalArgsTlsConfiguration {
|
||||
|
||||
DiscoveryClientOptionalArgsTlsConfiguration(TlsProperties tlsProperties,
|
||||
AbstractDiscoveryClientOptionalArgs optionalArgs) throws GeneralSecurityException, IOException {
|
||||
logger.info("Eureka HTTP Client uses Jersey");
|
||||
setupTLS(optionalArgs, tlsProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnMissingClass("org.glassfish.jersey.client.JerseyClient")
|
||||
@ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter")
|
||||
@ConditionalOnClass(name = "org.springframework.web.reactive.function.client.WebClient")
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", havingValue = "true")
|
||||
protected static class WebClientConfiguration {
|
||||
@@ -139,17 +119,10 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = TransportClientFactories.class, search = SearchStrategy.CURRENT)
|
||||
public WebClientTransportClientFactories webClientTransportClientFactories(
|
||||
ObjectProvider<WebClient.Builder> builder) {
|
||||
return new WebClientTransportClientFactories(builder::getIfAvailable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingClass({ "org.glassfish.jersey.client.JerseyClient",
|
||||
@ConditionalOnMissingClass({ "com.sun.jersey.api.client.filter.ClientFilter",
|
||||
"org.springframework.web.reactive.function.client.WebClient" })
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", havingValue = "true")
|
||||
protected static class WebClientNotFoundConfiguration {
|
||||
|
||||
+8
-8
@@ -16,16 +16,17 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.config;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import com.netflix.appinfo.EurekaInstanceConfig;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.config.server.config.ConfigServerProperties;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -35,22 +36,21 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
@ConditionalOnClass(value = { EurekaInstanceConfigBean.class, EurekaClient.class },
|
||||
name = "org.springframework.cloud.config.server.config.ConfigServerProperties")
|
||||
@ConditionalOnClass({ EurekaInstanceConfigBean.class, EurekaClient.class, ConfigServerProperties.class })
|
||||
public class EurekaClientConfigServerAutoConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private EurekaInstanceConfig instance;
|
||||
|
||||
@Autowired
|
||||
private Environment env;
|
||||
@Autowired(required = false)
|
||||
private ConfigServerProperties server;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
if (this.instance == null) {
|
||||
if (this.instance == null || this.server == null) {
|
||||
return;
|
||||
}
|
||||
String prefix = this.env.getProperty("spring.cloud.config.server.prefix");
|
||||
String prefix = this.server.getPrefix();
|
||||
if (StringUtils.hasText(prefix) && !StringUtils.hasText(this.instance.getMetadataMap().get("configPath"))) {
|
||||
this.instance.getMetadataMap().put("configPath", prefix);
|
||||
}
|
||||
|
||||
+18
-45
@@ -16,18 +16,11 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.config;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.boot.BootstrapContext;
|
||||
import org.springframework.boot.BootstrapRegistry;
|
||||
import org.springframework.boot.BootstrapRegistryInitializer;
|
||||
import org.springframework.boot.context.properties.bind.BindHandler;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.config.client.ConfigClientProperties;
|
||||
import org.springframework.cloud.config.client.ConfigServerInstanceProvider;
|
||||
import org.springframework.cloud.configuration.TlsProperties;
|
||||
@@ -44,53 +37,33 @@ public class EurekaConfigServerBootstrapper implements BootstrapRegistryInitiali
|
||||
if (!ClassUtils.isPresent("org.springframework.cloud.config.client.ConfigServerInstanceProvider", null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// It is important that we pass a lambda for the Function or else we will get a
|
||||
// ClassNotFoundException when config is not on the classpath
|
||||
registry.registerIfAbsent(ConfigServerInstanceProvider.Function.class, EurekaFunction::create);
|
||||
}
|
||||
|
||||
private static Boolean getDiscoveryEnabled(Binder binder) {
|
||||
return binder.bind(ConfigClientProperties.CONFIG_DISCOVERY_ENABLED, Boolean.class).orElse(false)
|
||||
&& binder.bind("eureka.client.enabled", Boolean.class).orElse(true)
|
||||
&& binder.bind("spring.cloud.discovery.enabled", Boolean.class).orElse(true);
|
||||
}
|
||||
|
||||
final static class EurekaFunction implements ConfigServerInstanceProvider.Function {
|
||||
|
||||
private final BootstrapContext context;
|
||||
|
||||
static EurekaFunction create(BootstrapContext context) {
|
||||
return new EurekaFunction(context);
|
||||
}
|
||||
|
||||
private EurekaFunction(BootstrapContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> apply(String serviceId, Binder binder, BindHandler bindHandler, Log log) {
|
||||
if (binder == null || !getDiscoveryEnabled(binder)) {
|
||||
return Collections.emptyList();
|
||||
registry.registerIfAbsent(EurekaClientConfigBean.class, context -> {
|
||||
Binder binder = context.get(Binder.class);
|
||||
if (!getDiscoveryEnabled(binder)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
EurekaClientConfigBean config = binder.bind(EurekaClientConfigBean.PREFIX, EurekaClientConfigBean.class)
|
||||
return binder.bind(EurekaClientConfigBean.PREFIX, EurekaClientConfigBean.class)
|
||||
.orElseGet(EurekaClientConfigBean::new);
|
||||
});
|
||||
|
||||
registry.registerIfAbsent(ConfigServerInstanceProvider.Function.class, context -> {
|
||||
Binder binder = context.get(Binder.class);
|
||||
if (!getDiscoveryEnabled(binder)) {
|
||||
return null;
|
||||
}
|
||||
EurekaClientConfigBean config = context.get(EurekaClientConfigBean.class);
|
||||
EurekaHttpClient httpClient = new RestTemplateTransportClientFactory(
|
||||
context.getOrElse(TlsProperties.class, null),
|
||||
context.getOrElse(EurekaClientHttpRequestFactorySupplier.class,
|
||||
new DefaultEurekaClientHttpRequestFactorySupplier()))
|
||||
.newClient(HostnameBasedUrlRandomizer.randomEndpoint(config, binder));
|
||||
return new EurekaConfigServerInstanceProvider(httpClient, config).getInstances(serviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> apply(String serviceId) {
|
||||
// This should never be called now but is here for backward
|
||||
// compatibility
|
||||
return apply(serviceId, null, null, null);
|
||||
}
|
||||
return new EurekaConfigServerInstanceProvider(httpClient, config)::getInstances;
|
||||
});
|
||||
}
|
||||
|
||||
private Boolean getDiscoveryEnabled(Binder binder) {
|
||||
return binder.bind(ConfigClientProperties.CONFIG_DISCOVERY_ENABLED, Boolean.class).orElse(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-5
@@ -18,7 +18,6 @@ package org.springframework.cloud.netflix.eureka.config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.endpoint.EndpointUtils;
|
||||
import com.netflix.discovery.shared.resolver.DefaultEndpoint;
|
||||
|
||||
@@ -27,7 +26,7 @@ import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public final class HostnameBasedUrlRandomizer implements EndpointUtils.ServiceUrlRandomizer {
|
||||
final class HostnameBasedUrlRandomizer implements EndpointUtils.ServiceUrlRandomizer {
|
||||
|
||||
private final String hostname;
|
||||
|
||||
@@ -57,18 +56,18 @@ public final class HostnameBasedUrlRandomizer implements EndpointUtils.ServiceUr
|
||||
}
|
||||
}
|
||||
|
||||
public static String getEurekaUrl(EurekaClientConfig config, String hostname) {
|
||||
static String getEurekaUrl(EurekaClientConfigBean config, String hostname) {
|
||||
List<String> urls = EndpointUtils.getDiscoveryServiceUrls(config, EurekaClientConfigBean.DEFAULT_ZONE,
|
||||
new HostnameBasedUrlRandomizer(hostname));
|
||||
return urls.get(0);
|
||||
}
|
||||
|
||||
public static DefaultEndpoint randomEndpoint(EurekaClientConfig config, Environment env) {
|
||||
static DefaultEndpoint randomEndpoint(EurekaClientConfigBean config, Environment env) {
|
||||
String hostname = env.getProperty("eureka.instance.hostname");
|
||||
return new DefaultEndpoint(getEurekaUrl(config, hostname));
|
||||
}
|
||||
|
||||
public static DefaultEndpoint randomEndpoint(EurekaClientConfig config, Binder binder) {
|
||||
static DefaultEndpoint randomEndpoint(EurekaClientConfigBean config, Binder binder) {
|
||||
String hostname = binder.bind("eureka.instance.hostname", String.class).orElseGet(() -> null);
|
||||
return new DefaultEndpoint(getEurekaUrl(config, hostname));
|
||||
}
|
||||
|
||||
+8
-65
@@ -16,22 +16,13 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.http;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
|
||||
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
|
||||
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder;
|
||||
import org.apache.hc.core5.http.io.SocketConfig;
|
||||
import org.apache.hc.core5.util.Timeout;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
|
||||
import org.springframework.cloud.netflix.eureka.RestTemplateTimeoutProperties;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -41,71 +32,23 @@ import org.springframework.lang.Nullable;
|
||||
* {@link HttpClients}.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Jiwon Jeon
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public class DefaultEurekaClientHttpRequestFactorySupplier implements EurekaClientHttpRequestFactorySupplier {
|
||||
|
||||
private final RestTemplateTimeoutProperties restTemplateTimeoutProperties;
|
||||
|
||||
/**
|
||||
* @deprecated in favour of
|
||||
* {@link DefaultEurekaClientHttpRequestFactorySupplier#DefaultEurekaClientHttpRequestFactorySupplier(RestTemplateTimeoutProperties)}
|
||||
*/
|
||||
@Deprecated
|
||||
public DefaultEurekaClientHttpRequestFactorySupplier() {
|
||||
this.restTemplateTimeoutProperties = new RestTemplateTimeoutProperties();
|
||||
}
|
||||
|
||||
public DefaultEurekaClientHttpRequestFactorySupplier(RestTemplateTimeoutProperties restTemplateTimeoutProperties) {
|
||||
this.restTemplateTimeoutProperties = restTemplateTimeoutProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientHttpRequestFactory get(SSLContext sslContext, @Nullable HostnameVerifier hostnameVerifier) {
|
||||
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
|
||||
if (sslContext != null || hostnameVerifier != null || restTemplateTimeoutProperties != null) {
|
||||
httpClientBuilder.setConnectionManager(
|
||||
buildConnectionManager(sslContext, hostnameVerifier, restTemplateTimeoutProperties));
|
||||
HttpClientBuilder httpClientBuilder = HttpClients.custom();
|
||||
if (sslContext != null) {
|
||||
httpClientBuilder = httpClientBuilder.setSSLContext(sslContext);
|
||||
}
|
||||
if (restTemplateTimeoutProperties != null) {
|
||||
httpClientBuilder.setDefaultRequestConfig(buildRequestConfig());
|
||||
if (hostnameVerifier != null) {
|
||||
httpClientBuilder = httpClientBuilder.setSSLHostnameVerifier(hostnameVerifier);
|
||||
}
|
||||
|
||||
CloseableHttpClient httpClient = httpClientBuilder.build();
|
||||
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
|
||||
requestFactory.setHttpClient(httpClient);
|
||||
return requestFactory;
|
||||
}
|
||||
|
||||
private HttpClientConnectionManager buildConnectionManager(SSLContext sslContext, HostnameVerifier hostnameVerifier,
|
||||
RestTemplateTimeoutProperties restTemplateTimeoutProperties) {
|
||||
PoolingHttpClientConnectionManagerBuilder connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder
|
||||
.create();
|
||||
SSLConnectionSocketFactoryBuilder sslConnectionSocketFactoryBuilder = SSLConnectionSocketFactoryBuilder
|
||||
.create();
|
||||
if (sslContext != null) {
|
||||
sslConnectionSocketFactoryBuilder.setSslContext(sslContext);
|
||||
}
|
||||
if (hostnameVerifier != null) {
|
||||
sslConnectionSocketFactoryBuilder.setHostnameVerifier(hostnameVerifier);
|
||||
}
|
||||
connectionManagerBuilder.setSSLSocketFactory(sslConnectionSocketFactoryBuilder.build());
|
||||
if (restTemplateTimeoutProperties != null) {
|
||||
connectionManagerBuilder.setDefaultSocketConfig(SocketConfig.custom()
|
||||
.setSoTimeout(Timeout.of(restTemplateTimeoutProperties.getSocketTimeout(), TimeUnit.MILLISECONDS))
|
||||
.build());
|
||||
}
|
||||
return connectionManagerBuilder.build();
|
||||
}
|
||||
|
||||
private RequestConfig buildRequestConfig() {
|
||||
return RequestConfig.custom()
|
||||
.setConnectTimeout(Timeout.of(restTemplateTimeoutProperties.getConnectTimeout(), TimeUnit.MILLISECONDS))
|
||||
.setConnectionRequestTimeout(
|
||||
Timeout.of(restTemplateTimeoutProperties.getConnectRequestTimeout(), TimeUnit.MILLISECONDS))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
@@ -28,6 +28,16 @@ public class RestTemplateDiscoveryClientOptionalArgs extends AbstractDiscoveryCl
|
||||
public RestTemplateDiscoveryClientOptionalArgs(
|
||||
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) {
|
||||
this.eurekaClientHttpRequestFactorySupplier = eurekaClientHttpRequestFactorySupplier;
|
||||
setTransportClientFactories(new RestTemplateTransportClientFactories(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated - use
|
||||
* {@link RestTemplateDiscoveryClientOptionalArgs#RestTemplateDiscoveryClientOptionalArgs(EurekaClientHttpRequestFactorySupplier)}
|
||||
*/
|
||||
@Deprecated
|
||||
public RestTemplateDiscoveryClientOptionalArgs() {
|
||||
this(new DefaultEurekaClientHttpRequestFactorySupplier());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-15
@@ -50,7 +50,7 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
private String serviceUrl;
|
||||
|
||||
@@ -66,10 +66,6 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
return this.serviceUrl;
|
||||
}
|
||||
|
||||
public RestTemplate getRestTemplate() {
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> register(InstanceInfo info) {
|
||||
String urlPath = serviceUrl + "apps/" + info.getAppName();
|
||||
@@ -81,7 +77,7 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.POST, new HttpEntity<>(info, headers),
|
||||
Void.class);
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value()).headers(headersOf(response)).build();
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue()).headers(headersOf(response)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -90,7 +86,7 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.DELETE, null, Void.class);
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value()).headers(headersOf(response)).build();
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue()).headers(headersOf(response)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -104,7 +100,7 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
InstanceInfo.class);
|
||||
|
||||
EurekaHttpResponseBuilder<InstanceInfo> eurekaResponseBuilder = anEurekaHttpResponse(
|
||||
response.getStatusCode().value(), InstanceInfo.class).headers(headersOf(response));
|
||||
response.getStatusCodeValue(), InstanceInfo.class).headers(headersOf(response));
|
||||
|
||||
if (response.hasBody()) {
|
||||
eurekaResponseBuilder.entity(response.getBody());
|
||||
@@ -121,7 +117,7 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.PUT, null, Void.class);
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value()).headers(headersOf(response)).build();
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue()).headers(headersOf(response)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -131,7 +127,7 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.DELETE, null, Void.class);
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value()).headers(headersOf(response)).build();
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue()).headers(headersOf(response)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,7 +145,7 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
ResponseEntity<EurekaApplications> response = restTemplate.exchange(url, HttpMethod.GET, null,
|
||||
EurekaApplications.class);
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value(),
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue(),
|
||||
response.getStatusCode().value() == HttpStatus.OK.value() && response.hasBody()
|
||||
? (Applications) response.getBody() : null).headers(headersOf(response)).build();
|
||||
}
|
||||
@@ -175,10 +171,10 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
ResponseEntity<Application> response = restTemplate.exchange(urlPath, HttpMethod.GET, null, Application.class);
|
||||
|
||||
Application application = response.getStatusCode().value() == HttpStatus.OK.value() && response.hasBody()
|
||||
Application application = response.getStatusCodeValue() == HttpStatus.OK.value() && response.hasBody()
|
||||
? response.getBody() : null;
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value(), application).headers(headersOf(response)).build();
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue(), application).headers(headersOf(response)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -197,8 +193,8 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
|
||||
ResponseEntity<InstanceInfo> response = restTemplate.exchange(urlPath, HttpMethod.GET, null,
|
||||
InstanceInfo.class);
|
||||
|
||||
return anEurekaHttpResponse(response.getStatusCode().value(),
|
||||
response.getStatusCode().value() == HttpStatus.OK.value() && response.hasBody() ? response.getBody()
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue(),
|
||||
response.getStatusCodeValue() == HttpStatus.OK.value() && response.hasBody() ? response.getBody()
|
||||
: null).headers(headersOf(response)).build();
|
||||
}
|
||||
|
||||
|
||||
+7
@@ -25,6 +25,7 @@ import javax.net.ssl.SSLContext;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.shared.transport.TransportClientFactory;
|
||||
import com.netflix.discovery.shared.transport.jersey.EurekaJerseyClient;
|
||||
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
|
||||
|
||||
/**
|
||||
@@ -38,6 +39,12 @@ public class RestTemplateTransportClientFactories implements TransportClientFact
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportClientFactory newTransportClientFactory(Collection<Void> additionalFilters,
|
||||
EurekaJerseyClient providedJerseyClient) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportClientFactory newTransportClientFactory(EurekaClientConfig clientConfig,
|
||||
Collection<Void> additionalFilters, InstanceInfo myInstanceInfo) {
|
||||
|
||||
+35
-75
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Optional;
|
||||
@@ -29,7 +27,7 @@ import com.fasterxml.jackson.databind.BeanDescription;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
|
||||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
@@ -46,16 +44,12 @@ import com.netflix.discovery.shared.transport.TransportClientFactory;
|
||||
|
||||
import org.springframework.cloud.configuration.SSLContextFactory;
|
||||
import org.springframework.cloud.configuration.TlsProperties;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Provides the custom {@link RestTemplate} required by the
|
||||
@@ -107,20 +101,11 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
|
||||
@Override
|
||||
public EurekaHttpClient newClient(EurekaEndpoint serviceUrl) {
|
||||
return new RestTemplateEurekaHttpClient(restTemplate(serviceUrl.getServiceUrl()),
|
||||
stripUserInfo(serviceUrl.getServiceUrl()));
|
||||
}
|
||||
|
||||
// apache http client 5.2 fails with non-null userinfo
|
||||
// basic auth added in restTemplate() below
|
||||
private String stripUserInfo(String serviceUrl) {
|
||||
return UriComponentsBuilder.fromUriString(serviceUrl).userInfo(null).toUriString();
|
||||
return new RestTemplateEurekaHttpClient(restTemplate(serviceUrl.getServiceUrl()), serviceUrl.getServiceUrl());
|
||||
}
|
||||
|
||||
private RestTemplate restTemplate(String serviceUrl) {
|
||||
ClientHttpRequestFactory requestFactory = this.eurekaClientHttpRequestFactorySupplier
|
||||
.get(this.sslContext.orElse(null), this.hostnameVerifier.orElse(null));
|
||||
RestTemplate restTemplate = new RestTemplate(requestFactory);
|
||||
RestTemplate restTemplate = restTemplate();
|
||||
|
||||
try {
|
||||
URI serviceURI = new URI(serviceUrl);
|
||||
@@ -139,33 +124,32 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
restTemplate.getMessageConverters().add(0, mappingJacksonHttpMessageConverter());
|
||||
restTemplate.setErrorHandler(new ErrorHandler());
|
||||
|
||||
restTemplate.getInterceptors().add((request, body, execution) -> {
|
||||
ClientHttpResponse response = execution.execute(request, body);
|
||||
if (!response.getStatusCode().equals(HttpStatus.NOT_FOUND)) {
|
||||
return response;
|
||||
}
|
||||
return new NotFoundHttpResponse(response);
|
||||
});
|
||||
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
private RestTemplate restTemplate() {
|
||||
ClientHttpRequestFactory requestFactory = this.eurekaClientHttpRequestFactorySupplier
|
||||
.get(this.sslContext.orElse(null), this.hostnameVerifier.orElse(null));
|
||||
return new RestTemplate(requestFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the serialization configurations required by the Eureka Server. JSON
|
||||
* content exchanged with eureka requires a root node matching the entity being
|
||||
* serialized or deserialized. Achived with
|
||||
* {@link SerializationFeature#WRAP_ROOT_VALUE} and
|
||||
* {@link DeserializationFeature#UNWRAP_ROOT_VALUE}.
|
||||
* {@link PropertyNamingStrategies.SnakeCaseStrategy} is applied to the underlying
|
||||
* {@link PropertyNamingStrategy.SnakeCaseStrategy} is applied to the underlying
|
||||
* {@link ObjectMapper}.
|
||||
* @return a {@link MappingJackson2HttpMessageConverter} object
|
||||
*/
|
||||
public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
|
||||
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
|
||||
converter.setObjectMapper(new ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE));
|
||||
converter.setObjectMapper(new ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE));
|
||||
|
||||
SimpleModule jsonModule = new SimpleModule();
|
||||
jsonModule.setSerializerModifier(createJsonSerializerModifier());
|
||||
jsonModule.setSerializerModifier(createJsonSerializerModifier()); // keyFormatter,
|
||||
// compact));
|
||||
converter.getObjectMapper().registerModule(jsonModule);
|
||||
|
||||
converter.getObjectMapper().configure(SerializationFeature.WRAP_ROOT_VALUE, true);
|
||||
@@ -173,14 +157,34 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
converter.getObjectMapper().addMixIn(Applications.class, ApplicationsJsonMixIn.class);
|
||||
converter.getObjectMapper().addMixIn(InstanceInfo.class, InstanceInfoJsonMixIn.class);
|
||||
|
||||
// converter.getObjectMapper().addMixIn(DataCenterInfo.class,
|
||||
// DataCenterInfoXmlMixIn.class);
|
||||
// converter.getObjectMapper().addMixIn(InstanceInfo.PortWrapper.class,
|
||||
// PortWrapperXmlMixIn.class);
|
||||
// converter.getObjectMapper().addMixIn(Application.class,
|
||||
// ApplicationXmlMixIn.class);
|
||||
// converter.getObjectMapper().addMixIn(Applications.class,
|
||||
// ApplicationsXmlMixIn.class);
|
||||
|
||||
return converter;
|
||||
}
|
||||
|
||||
public static BeanSerializerModifier createJsonSerializerModifier() {
|
||||
public static BeanSerializerModifier createJsonSerializerModifier() { // final
|
||||
// KeyFormatter
|
||||
// keyFormatter,
|
||||
// final
|
||||
// boolean
|
||||
// compactMode)
|
||||
// {
|
||||
return new BeanSerializerModifier() {
|
||||
@Override
|
||||
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc,
|
||||
JsonSerializer<?> serializer) {
|
||||
/*
|
||||
* if (beanDesc.getBeanClass().isAssignableFrom(Applications.class)) {
|
||||
* return new ApplicationsJsonBeanSerializer((BeanSerializerBase)
|
||||
* serializer, keyFormatter); }
|
||||
*/
|
||||
if (beanDesc.getBeanClass().isAssignableFrom(InstanceInfo.class)) {
|
||||
return new InstanceInfoJsonBeanSerializer((BeanSerializerBase) serializer, false);
|
||||
}
|
||||
@@ -193,54 +197,10 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
public void shutdown() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Response that ignores body, specifically for 404 errors.
|
||||
*/
|
||||
private static class NotFoundHttpResponse implements ClientHttpResponse {
|
||||
|
||||
private final ClientHttpResponse response;
|
||||
|
||||
NotFoundHttpResponse(ClientHttpResponse response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpStatusCode getStatusCode() throws IOException {
|
||||
return response.getStatusCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRawStatusCode() throws IOException {
|
||||
return response.getRawStatusCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusText() throws IOException {
|
||||
return response.getStatusText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
response.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getBody() throws IOException {
|
||||
// ignore body on 404 for heartbeat, see gh-4145
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
return response.getHeaders();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ErrorHandler extends DefaultResponseErrorHandler {
|
||||
|
||||
@Override
|
||||
protected boolean hasError(HttpStatusCode statusCode) {
|
||||
protected boolean hasError(HttpStatus statusCode) {
|
||||
/**
|
||||
* When the Eureka server restarts and a client tries to sent a heartbeat the
|
||||
* server will respond with a 404. By default RestTemplate will throw an
|
||||
|
||||
+1
@@ -29,6 +29,7 @@ import org.springframework.web.reactive.function.client.WebClient;
|
||||
public class WebClientDiscoveryClientOptionalArgs extends AbstractDiscoveryClientOptionalArgs<Void> {
|
||||
|
||||
public WebClientDiscoveryClientOptionalArgs(Supplier<WebClient.Builder> builder) {
|
||||
setTransportClientFactories(new WebClientTransportClientFactories(builder));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+45
-41
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.http;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
@@ -26,13 +28,12 @@ import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpResponse;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpResponse.EurekaHttpResponseBuilder;
|
||||
import com.netflix.discovery.util.StringUtil;
|
||||
import reactor.core.publisher.Mono;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
@@ -45,6 +46,8 @@ import static com.netflix.discovery.shared.transport.EurekaHttpResponse.anEureka
|
||||
*/
|
||||
public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private WebClient webClient;
|
||||
|
||||
public WebClientEurekaHttpClient(WebClient webClient) {
|
||||
@@ -53,18 +56,16 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> register(InstanceInfo info) {
|
||||
return webClient.post().uri("apps/" + info.getAppName()).body(BodyInserters.fromValue(info))
|
||||
return webClient.post().uri("apps/" + info.getAppName(), Void.class).body(BodyInserters.fromValue(info))
|
||||
.header(HttpHeaders.ACCEPT_ENCODING, "gzip")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity().map(this::eurekaHttpResponse)
|
||||
.block();
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).exchange()
|
||||
.map(response -> eurekaHttpResponse(response)).block();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EurekaHttpResponse<Void> cancel(String appName, String id) {
|
||||
return webClient.delete().uri("apps/" + appName + '/' + id).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity().map(this::eurekaHttpResponse)
|
||||
.block();
|
||||
return webClient.delete().uri("apps/" + appName + '/' + id, Void.class).exchange()
|
||||
.map(response -> eurekaHttpResponse(response)).block();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,15 +75,14 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
+ "&lastDirtyTimestamp=" + info.getLastDirtyTimestamp().toString()
|
||||
+ (overriddenStatus != null ? "&overriddenstatus=" + overriddenStatus.name() : "");
|
||||
|
||||
ResponseEntity<InstanceInfo> response = webClient.put().uri(urlPath)
|
||||
ClientResponse response = webClient.put().uri(urlPath, InstanceInfo.class)
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError).toEntity(InstanceInfo.class).block();
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).exchange().block();
|
||||
|
||||
EurekaHttpResponseBuilder<InstanceInfo> builder = anEurekaHttpResponse(statusCodeValueOf(response),
|
||||
InstanceInfo.class).headers(headersOf(response));
|
||||
|
||||
InstanceInfo entity = response.getBody();
|
||||
InstanceInfo entity = response.toEntity(InstanceInfo.class).block().getBody();
|
||||
|
||||
if (entity != null) {
|
||||
builder.entity(entity);
|
||||
@@ -98,9 +98,9 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
String urlPath = "apps/" + appName + '/' + id + "/status?value=" + newStatus.name() + "&lastDirtyTimestamp="
|
||||
+ info.getLastDirtyTimestamp().toString();
|
||||
|
||||
return webClient.put().uri(urlPath).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.retrieve().onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity()
|
||||
.map(this::eurekaHttpResponse).block();
|
||||
return webClient.put().uri(urlPath, Void.class)
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).exchange()
|
||||
.map(response -> eurekaHttpResponse(response)).block();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -108,9 +108,9 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
String urlPath = "apps/" + appName + '/' + id + "/status?lastDirtyTimestamp="
|
||||
+ info.getLastDirtyTimestamp().toString();
|
||||
|
||||
return webClient.delete().uri(urlPath).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.retrieve().onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity()
|
||||
.map(this::eurekaHttpResponse).block();
|
||||
return webClient.delete().uri(urlPath, Void.class)
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).exchange()
|
||||
.map(response -> eurekaHttpResponse(response)).block();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -125,14 +125,13 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
url = url + (urlPath.contains("?") ? "&" : "?") + "regions=" + StringUtil.join(regions);
|
||||
}
|
||||
|
||||
ResponseEntity<Applications> response = webClient.get().uri(url)
|
||||
ClientResponse response = webClient.get().uri(url, Applications.class)
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError).toEntity(Applications.class).block();
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).exchange().block();
|
||||
|
||||
int statusCode = statusCodeValueOf(response);
|
||||
|
||||
Applications body = response.getBody();
|
||||
Applications body = response.toEntity(Applications.class).block().getBody();
|
||||
|
||||
return anEurekaHttpResponse(statusCode, statusCode == HttpStatus.OK.value() && body != null ? body : null)
|
||||
.headers(headersOf(response)).build();
|
||||
@@ -156,12 +155,11 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
@Override
|
||||
public EurekaHttpResponse<Application> getApplication(String appName) {
|
||||
|
||||
ResponseEntity<Application> response = webClient.get().uri("apps/" + appName)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError).toEntity(Application.class).block();
|
||||
ClientResponse response = webClient.get().uri("apps/" + appName, Application.class)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).exchange().block();
|
||||
|
||||
int statusCode = statusCodeValueOf(response);
|
||||
Application body = response.getBody();
|
||||
Application body = response.toEntity(Application.class).block().getBody();
|
||||
|
||||
Application application = statusCode == HttpStatus.OK.value() && body != null ? body : null;
|
||||
|
||||
@@ -179,12 +177,11 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
}
|
||||
|
||||
private EurekaHttpResponse<InstanceInfo> getInstanceInternal(String urlPath) {
|
||||
ResponseEntity<InstanceInfo> response = webClient.get().uri(urlPath)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, this::ignoreError).toEntity(InstanceInfo.class).block();
|
||||
ClientResponse response = webClient.get().uri(urlPath, InstanceInfo.class)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).exchange().block();
|
||||
|
||||
int statusCode = statusCodeValueOf(response);
|
||||
InstanceInfo body = response.getBody();
|
||||
InstanceInfo body = response.toEntity(InstanceInfo.class).block().getBody();
|
||||
|
||||
return anEurekaHttpResponse(statusCode, statusCode == HttpStatus.OK.value() && body != null ? body : null)
|
||||
.headers(headersOf(response)).build();
|
||||
@@ -199,19 +196,26 @@ public class WebClientEurekaHttpClient implements EurekaHttpClient {
|
||||
return this.webClient;
|
||||
}
|
||||
|
||||
private Mono<? extends Throwable> ignoreError(ClientResponse response) {
|
||||
return Mono.empty();
|
||||
private static Map<String, String> headersOf(ClientResponse response) {
|
||||
ClientResponse.Headers httpHeaders = response.headers();
|
||||
if (httpHeaders == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
HttpHeaders asHeaders = httpHeaders.asHttpHeaders();
|
||||
if (asHeaders == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
asHeaders.entrySet().stream()
|
||||
.forEach(entry -> entry.getValue().stream().forEach(v -> headers.put(entry.getKey(), v)));
|
||||
return headers;
|
||||
}
|
||||
|
||||
private static Map<String, String> headersOf(ResponseEntity<?> response) {
|
||||
return response.getHeaders().toSingleValueMap();
|
||||
private int statusCodeValueOf(ClientResponse response) {
|
||||
return response.statusCode().value();
|
||||
}
|
||||
|
||||
private int statusCodeValueOf(ResponseEntity<?> response) {
|
||||
return response.getStatusCode().value();
|
||||
}
|
||||
|
||||
private EurekaHttpResponse<Void> eurekaHttpResponse(ResponseEntity<?> response) {
|
||||
private EurekaHttpResponse<Void> eurekaHttpResponse(ClientResponse response) {
|
||||
return anEurekaHttpResponse(statusCodeValueOf(response)).headers(headersOf(response)).build();
|
||||
}
|
||||
|
||||
|
||||
+7
@@ -26,6 +26,7 @@ import javax.net.ssl.SSLContext;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.shared.transport.TransportClientFactory;
|
||||
import com.netflix.discovery.shared.transport.jersey.EurekaJerseyClient;
|
||||
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
|
||||
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
@@ -42,6 +43,12 @@ public class WebClientTransportClientFactories implements TransportClientFactori
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportClientFactory newTransportClientFactory(Collection<Void> additionalFilters,
|
||||
EurekaJerseyClient providedJerseyClient) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportClientFactory newTransportClientFactory(EurekaClientConfig clientConfig,
|
||||
Collection<Void> additionalFilters, InstanceInfo myInstanceInfo) {
|
||||
|
||||
+4
-11
@@ -24,7 +24,7 @@ import com.fasterxml.jackson.databind.BeanDescription;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
|
||||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
@@ -38,7 +38,6 @@ import com.netflix.discovery.shared.Applications;
|
||||
import com.netflix.discovery.shared.resolver.EurekaEndpoint;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.TransportClientFactory;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -123,13 +122,13 @@ public class WebClientTransportClientFactory implements TransportClientFactory {
|
||||
* serialized or deserialized. Achieved with
|
||||
* {@link SerializationFeature#WRAP_ROOT_VALUE} and
|
||||
* {@link DeserializationFeature#UNWRAP_ROOT_VALUE}.
|
||||
* {@link PropertyNamingStrategies.SnakeCaseStrategy} is applied to the underlying
|
||||
* {@link PropertyNamingStrategy.SnakeCaseStrategy} is applied to the underlying
|
||||
* {@link ObjectMapper}.
|
||||
* @return a {@link ObjectMapper} object
|
||||
*/
|
||||
private ObjectMapper objectMapper() {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
|
||||
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
|
||||
|
||||
SimpleModule jsonModule = new SimpleModule();
|
||||
jsonModule.setSerializerModifier(createJsonSerializerModifier());
|
||||
@@ -148,16 +147,10 @@ public class WebClientTransportClientFactory implements TransportClientFactory {
|
||||
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
|
||||
// literally 400 pass the tests, not 4xxClientError
|
||||
if (clientResponse.statusCode().value() == 400) {
|
||||
ClientResponse newResponse = clientResponse.mutate().statusCode(HttpStatus.OK).build();
|
||||
ClientResponse newResponse = ClientResponse.from(clientResponse).statusCode(HttpStatus.OK).build();
|
||||
newResponse.body((clientHttpResponse, context) -> clientHttpResponse.getBody());
|
||||
return Mono.just(newResponse);
|
||||
}
|
||||
if (clientResponse.statusCode().equals(HttpStatus.NOT_FOUND)) {
|
||||
ClientResponse newResponse = clientResponse.mutate().statusCode(clientResponse.statusCode())
|
||||
// ignore body on 404 for heartbeat, see gh-4145
|
||||
.body(Flux.empty()).build();
|
||||
return Mono.just(newResponse);
|
||||
}
|
||||
return Mono.just(clientResponse);
|
||||
});
|
||||
}
|
||||
|
||||
+5
-4
@@ -16,9 +16,10 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.loadbalancer;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import com.netflix.appinfo.EurekaInstanceConfig;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -65,11 +66,11 @@ public class EurekaLoadBalancerClientConfiguration {
|
||||
|
||||
@PostConstruct
|
||||
public void postprocess() {
|
||||
if (StringUtils.hasText(zoneConfig.getZone())) {
|
||||
if (!StringUtils.isEmpty(zoneConfig.getZone())) {
|
||||
return;
|
||||
}
|
||||
String zone = getZoneFromEureka();
|
||||
if (StringUtils.hasText(zone)) {
|
||||
if (!StringUtils.isEmpty(zone)) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Setting the value of '" + LOADBALANCER_ZONE + "' to " + zone);
|
||||
}
|
||||
@@ -85,7 +86,7 @@ public class EurekaLoadBalancerClientConfiguration {
|
||||
}
|
||||
else {
|
||||
zone = eurekaConfig == null ? null : eurekaConfig.getMetadataMap().get("zone");
|
||||
if (!StringUtils.hasText(zone) && clientConfig != null) {
|
||||
if (StringUtils.isEmpty(zone) && clientConfig != null) {
|
||||
String[] zones = clientConfig.getAvailabilityZones(clientConfig.getRegion());
|
||||
// Pick the first one from the regions we want to connect to
|
||||
zone = zones != null && zones.length > 0 ? zones[0] : null;
|
||||
|
||||
+6
-6
@@ -44,17 +44,17 @@ public class EurekaAutoServiceRegistration
|
||||
|
||||
private static final Log log = LogFactory.getLog(EurekaAutoServiceRegistration.class);
|
||||
|
||||
private final AtomicBoolean running = new AtomicBoolean(false);
|
||||
private AtomicBoolean running = new AtomicBoolean(false);
|
||||
|
||||
private final int order = 0;
|
||||
private int order = 0;
|
||||
|
||||
private final AtomicInteger port = new AtomicInteger(0);
|
||||
private AtomicInteger port = new AtomicInteger(0);
|
||||
|
||||
private final ApplicationContext context;
|
||||
private ApplicationContext context;
|
||||
|
||||
private final EurekaServiceRegistry serviceRegistry;
|
||||
private EurekaServiceRegistry serviceRegistry;
|
||||
|
||||
private final EurekaRegistration registration;
|
||||
private EurekaRegistration registration;
|
||||
|
||||
public EurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry serviceRegistry,
|
||||
EurekaRegistration registration) {
|
||||
|
||||
+2
-12
@@ -25,7 +25,6 @@ import com.netflix.appinfo.HealthCheckHandler;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -60,7 +59,7 @@ public class EurekaRegistration implements Registration {
|
||||
|
||||
private ObjectProvider<HealthCheckHandler> healthCheckHandler;
|
||||
|
||||
public EurekaRegistration(CloudEurekaInstanceConfig instanceConfig, EurekaClient eurekaClient,
|
||||
private EurekaRegistration(CloudEurekaInstanceConfig instanceConfig, EurekaClient eurekaClient,
|
||||
ApplicationInfoManager applicationInfoManager, ObjectProvider<HealthCheckHandler> healthCheckHandler) {
|
||||
this.eurekaClient = eurekaClient;
|
||||
this.instanceConfig = instanceConfig;
|
||||
@@ -182,8 +181,6 @@ public class EurekaRegistration implements Registration {
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
private TransportClientFactories<?> transportClientFactories;
|
||||
|
||||
Builder(CloudEurekaInstanceConfig instanceConfig) {
|
||||
this.instanceConfig = instanceConfig;
|
||||
}
|
||||
@@ -203,11 +200,6 @@ public class EurekaRegistration implements Registration {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder with(TransportClientFactories<?> transportClientFactories) {
|
||||
this.transportClientFactories = transportClientFactories;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder with(EurekaClientConfig clientConfig, ApplicationEventPublisher publisher) {
|
||||
this.clientConfig = clientConfig;
|
||||
this.publisher = publisher;
|
||||
@@ -224,11 +216,9 @@ public class EurekaRegistration implements Registration {
|
||||
if (this.eurekaClient == null) {
|
||||
Assert.notNull(this.clientConfig, "if eurekaClient is null, EurekaClientConfig may not be null");
|
||||
Assert.notNull(this.publisher, "if eurekaClient is null, ApplicationEventPublisher may not be null");
|
||||
Assert.notNull(this.transportClientFactories,
|
||||
"if eurekaClient is null, TransportClientFactories may not be null");
|
||||
|
||||
this.eurekaClient = new CloudEurekaClient(this.applicationInfoManager, this.clientConfig,
|
||||
this.transportClientFactories, this.publisher);
|
||||
this.publisher);
|
||||
}
|
||||
return new EurekaRegistration(instanceConfig, eurekaClient, applicationInfoManager, healthCheckHandler);
|
||||
}
|
||||
|
||||
-1
@@ -86,7 +86,6 @@ public class EurekaServiceRegistry implements ServiceRegistry<EurekaRegistration
|
||||
registration.getEurekaClient().setStatus(newStatus, info);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object getStatus(EurekaRegistration registration) {
|
||||
String appname = registration.getApplicationInfoManager().getInfo().getAppName();
|
||||
|
||||
+6
-7
@@ -12,18 +12,17 @@
|
||||
"description": "Determines whether the EurekaClient instance can be refreshed or not(If disabled none of the Eureka client properties will be refreshable).",
|
||||
"type": "java.lang.Boolean"
|
||||
},
|
||||
{
|
||||
"defaultValue": true,
|
||||
"name": "ribbon.eureka.enabled",
|
||||
"description": "Enables the use of Eureka with Ribbon.",
|
||||
"type": "java.lang.Boolean"
|
||||
},
|
||||
{
|
||||
"defaultValue": false,
|
||||
"name": "eureka.client.webclient.enabled",
|
||||
"description": "Enables the use of WebClient for Eureka HTTP Client.",
|
||||
"type": "java.lang.Boolean"
|
||||
},
|
||||
{
|
||||
"defaultValue": 1,
|
||||
"name": "eureka.instance.metadata-map.weight",
|
||||
"description": "The weight of service instance for weighted load balancing.",
|
||||
"type": "java.lang.Integer",
|
||||
"sourceType": "org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration,\
|
||||
org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration,\
|
||||
org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration,\
|
||||
org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration,\
|
||||
org.springframework.cloud.netflix.eureka.reactive.EurekaReactiveDiscoveryClientConfiguration,\
|
||||
org.springframework.cloud.netflix.eureka.loadbalancer.LoadBalancerEurekaAutoConfiguration
|
||||
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.netflix.eureka.config.EurekaConfigServerBootstrapConfiguration
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
org.springframework.aot.hint.RuntimeHintsRegistrar=\
|
||||
org.springframework.cloud.netflix.eureka.EurekaClientHints
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration
|
||||
org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration
|
||||
org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration
|
||||
org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration
|
||||
org.springframework.cloud.netflix.eureka.reactive.EurekaReactiveDiscoveryClientConfiguration
|
||||
org.springframework.cloud.netflix.eureka.loadbalancer.LoadBalancerEurekaAutoConfiguration
|
||||
+49
-24
@@ -23,10 +23,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.netflix.appinfo.ApplicationInfoManager;
|
||||
import com.netflix.appinfo.HealthCheckHandler;
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
|
||||
import com.netflix.discovery.shared.transport.jersey.EurekaJerseyClient;
|
||||
import com.sun.jersey.client.apache4.ApacheHttpClient4;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
@@ -38,6 +38,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.context.event.ApplicationPreparedEvent;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
@@ -47,7 +48,6 @@ import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicator;
|
||||
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
|
||||
import org.springframework.cloud.commons.util.UtilAutoConfiguration;
|
||||
import org.springframework.cloud.context.config.ContextRefreshedWithApplicationEvent;
|
||||
import org.springframework.cloud.context.refresh.ContextRefresher;
|
||||
import org.springframework.cloud.context.scope.GenericScope;
|
||||
import org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration;
|
||||
@@ -74,7 +74,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.fail;
|
||||
*/
|
||||
class EurekaClientAutoConfigurationTests {
|
||||
|
||||
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
||||
@AfterEach
|
||||
void after() {
|
||||
@@ -95,7 +95,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSetManagementPortInMetadataMapIfEqualToServerPort() {
|
||||
void shouldSetManagementPortInMetadataMapIfEqualToServerPort() throws Exception {
|
||||
TestPropertyValues.of("server.port=8989").applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
|
||||
@@ -105,7 +105,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSetManagementAndJmxPortsInMetadataMap() {
|
||||
void shouldNotSetManagementAndJmxPortsInMetadataMap() throws Exception {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=0").applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
|
||||
@@ -116,7 +116,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSetManagementAndJmxPortsInMetadataMap() {
|
||||
void shouldSetManagementAndJmxPortsInMetadataMap() throws Exception {
|
||||
TestPropertyValues.of("management.server.port=9999", "com.sun.management.jmxremote.port=6789")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
@@ -127,7 +127,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotResetManagementAndJmxPortsInMetadataMap() {
|
||||
void shouldNotResetManagementAndJmxPortsInMetadataMap() throws Exception {
|
||||
TestPropertyValues.of("management.server.port=9999", "eureka.instance.metadata-map.jmx.port=9898",
|
||||
"eureka.instance.metadata-map.management.port=7878").applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
@@ -202,7 +202,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrl_and_healthCheckUrl_do_not_contain_server_context_path() {
|
||||
void statusPageUrl_and_healthCheckUrl_do_not_contain_server_context_path() throws Exception {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.port=9999", "server.contextPath=/service")
|
||||
.applyTo(this.context);
|
||||
|
||||
@@ -215,7 +215,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrl_and_healthCheckUrl_contain_management_context_path() {
|
||||
void statusPageUrl_and_healthCheckUrl_contain_management_context_path() throws Exception {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.servlet.context-path=/management")
|
||||
.applyTo(this.context);
|
||||
|
||||
@@ -228,7 +228,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrl_and_healthCheckUrl_contain_management_context_path_random_port() {
|
||||
void statusPageUrl_and_healthCheckUrl_contain_management_context_path_random_port() throws Exception {
|
||||
TestPropertyValues.of("server.port=0", "management.server.servlet.context-path=/management")
|
||||
.applyTo(this.context);
|
||||
|
||||
@@ -287,7 +287,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrl_and_healthCheckUrl_contain_management_base_path() {
|
||||
void statusPageUrl_and_healthCheckUrl_contain_management_base_path() throws Exception {
|
||||
TestPropertyValues.of("server.port=8989", "management.server.base-path=/management").applyTo(this.context);
|
||||
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
@@ -299,7 +299,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusPageUrl_and_healthCheckUrl_contain_management_base_path_random_port() {
|
||||
void statusPageUrl_and_healthCheckUrl_contain_management_base_path_random_port() throws Exception {
|
||||
TestPropertyValues.of("server.port=0", "management.server.base-path=/management").applyTo(this.context);
|
||||
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
@@ -470,9 +470,9 @@ class EurekaClientAutoConfigurationTests {
|
||||
|
||||
ContextRefresher refresher = this.context.getBean(ContextRefresher.class);
|
||||
if (refresher instanceof ApplicationListener) {
|
||||
ApplicationListener<ContextRefreshedWithApplicationEvent> listener = (ApplicationListener) refresher;
|
||||
listener.onApplicationEvent(new ContextRefreshedWithApplicationEvent(Mockito.mock(SpringApplication.class),
|
||||
new String[0], this.context));
|
||||
ApplicationListener<ApplicationPreparedEvent> listener = (ApplicationListener) refresher;
|
||||
listener.onApplicationEvent(
|
||||
new ApplicationPreparedEvent(Mockito.mock(SpringApplication.class), new String[0], this.context));
|
||||
}
|
||||
refresher.refresh();
|
||||
|
||||
@@ -501,7 +501,17 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultAppName() {
|
||||
void basicAuth() {
|
||||
TestPropertyValues
|
||||
.of("server.port=8989", "eureka.client.serviceUrl.defaultZone=https://user:foo@example.com:80/eureka")
|
||||
.applyTo(this.context);
|
||||
setupContext(MockClientConfiguration.class);
|
||||
// ApacheHttpClient4 http = this.context.getBean(ApacheHttpClient4.class);
|
||||
// Mockito.verify(http).addFilter(Matchers.any(HTTPBasicAuthFilter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultAppName() throws Exception {
|
||||
setupContext();
|
||||
assertThat(getInstanceConfig().getAppname()).isEqualTo("unknown");
|
||||
assertThat(getInstanceConfig().getVirtualHostName()).isEqualTo("unknown");
|
||||
@@ -509,7 +519,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAppName() {
|
||||
void testAppName() throws Exception {
|
||||
TestPropertyValues.of("spring.application.name=mytest").applyTo(this.context);
|
||||
setupContext();
|
||||
assertThat(getInstanceConfig().getAppname()).isEqualTo("mytest");
|
||||
@@ -518,7 +528,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAppNameUpper() {
|
||||
void testAppNameUpper() throws Exception {
|
||||
addSystemEnvironment(this.context.getEnvironment(), "SPRING_APPLICATION_NAME=mytestupper");
|
||||
setupContext();
|
||||
assertThat(getInstanceConfig().getAppname()).isEqualTo("mytestupper");
|
||||
@@ -560,7 +570,7 @@ class EurekaClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInstanceNamePreferred() {
|
||||
void testInstanceNamePreferred() throws Exception {
|
||||
addSystemEnvironment(this.context.getEnvironment(), "SPRING_APPLICATION_NAME=mytestspringappname");
|
||||
TestPropertyValues.of("eureka.instance.appname=mytesteurekaappname").applyTo(this.context);
|
||||
setupContext();
|
||||
@@ -606,7 +616,6 @@ class EurekaClientAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private void assertBeanNotPresent(Class beanClass) {
|
||||
try {
|
||||
context.getBean(beanClass);
|
||||
@@ -662,9 +671,8 @@ class EurekaClientAutoConfigurationTests {
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
|
||||
public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config,
|
||||
TransportClientFactories<?> transportClientFactories, ApplicationContext context,
|
||||
AbstractDiscoveryClientOptionalArgs optionalArgs) {
|
||||
return new CloudEurekaClient(manager, config, transportClientFactories, optionalArgs, context) {
|
||||
ApplicationContext context) {
|
||||
return new CloudEurekaClient(manager, config, null, context) {
|
||||
@Override
|
||||
public synchronized void shutdown() {
|
||||
CountDownLatch latch = countDownLatch();
|
||||
@@ -678,6 +686,23 @@ class EurekaClientAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
protected static class MockClientConfiguration {
|
||||
|
||||
@Bean
|
||||
public EurekaJerseyClient jerseyClient() {
|
||||
EurekaJerseyClient mock = Mockito.mock(EurekaJerseyClient.class);
|
||||
Mockito.when(mock.getClient()).thenReturn(apacheClient());
|
||||
return mock;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ApacheHttpClient4 apacheClient() {
|
||||
return Mockito.mock(ApacheHttpClient4.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
|
||||
public static class AutoServiceRegistrationConfiguration {
|
||||
|
||||
+2
-2
@@ -36,7 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class EurekaClientConfigBeanTests {
|
||||
|
||||
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
||||
@AfterEach
|
||||
void init() {
|
||||
@@ -67,7 +67,7 @@ class EurekaClientConfigBeanTests {
|
||||
void serviceUrlWithCompositePropertySource() {
|
||||
CompositePropertySource source = new CompositePropertySource("composite");
|
||||
this.context.getEnvironment().getPropertySources().addFirst(source);
|
||||
source.addPropertySource(new MapPropertySource("config", Collections.singletonMap(
|
||||
source.addPropertySource(new MapPropertySource("config", Collections.<String, Object>singletonMap(
|
||||
"eureka.client.serviceUrl.defaultZone",
|
||||
"https://example.com,https://example2.com, https://www.hugedomains.com/domain_profile.cfm?d=example3&e=com")));
|
||||
this.context.register(PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class);
|
||||
|
||||
+14
-115
@@ -16,23 +16,18 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.AbstractReactiveHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.CompositeHealthContributor;
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.boot.actuate.health.HealthContributor;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
import org.springframework.boot.actuate.health.NamedContributor;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.SimpleStatusAggregator;
|
||||
import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicator;
|
||||
@@ -49,7 +44,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Jakub Narloch
|
||||
* @author Nowrin Anwar Joyita
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
class EurekaHealthCheckHandlerTests {
|
||||
|
||||
@@ -69,7 +63,7 @@ class EurekaHealthCheckHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAllUp() {
|
||||
void testAllUp() throws Exception {
|
||||
initialize(UpHealthConfiguration.class, ReactiveUpHealthConfiguration.class);
|
||||
|
||||
InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UNKNOWN);
|
||||
@@ -77,7 +71,7 @@ class EurekaHealthCheckHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHealthCheckNotReturnedWhenStopped() {
|
||||
void testHealthCheckNotReturnedWhenStopped() throws Exception {
|
||||
initialize(UpHealthConfiguration.class);
|
||||
|
||||
healthCheckHandler.stop();
|
||||
@@ -90,7 +84,7 @@ class EurekaHealthCheckHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDownWithBlockingIndicators() {
|
||||
void testDownWithBlockingIndicators() throws Exception {
|
||||
initialize(UpHealthConfiguration.class, DownHealthConfiguration.class);
|
||||
|
||||
InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UNKNOWN);
|
||||
@@ -98,7 +92,7 @@ class EurekaHealthCheckHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDownWithReactiveIndicators() {
|
||||
void testDownWithReactiveIndicators() throws Exception {
|
||||
initialize(UpHealthConfiguration.class, ReactiveDownHealthConfiguration.class);
|
||||
|
||||
InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UNKNOWN);
|
||||
@@ -106,7 +100,7 @@ class EurekaHealthCheckHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDownWhenBlockingIndicatorUpAndReactiveDown() {
|
||||
void testDownWhenBlockingIndicatorUpAndReactiveDown() throws Exception {
|
||||
initialize(ReactiveUpHealthConfiguration.class, DownHealthConfiguration.class);
|
||||
|
||||
InstanceStatus status = this.healthCheckHandler.getStatus(InstanceStatus.UNKNOWN);
|
||||
@@ -114,7 +108,7 @@ class EurekaHealthCheckHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDownWhenBlockingIndicatorDownAndReactiveUp() {
|
||||
void testDownWhenBlockingIndicatorDownAndReactiveUp() throws Exception {
|
||||
initialize(ReactiveUpHealthConfiguration.class, ReactiveDownHealthConfiguration.class);
|
||||
|
||||
InstanceStatus status = this.healthCheckHandler.getStatus(InstanceStatus.UNKNOWN);
|
||||
@@ -122,7 +116,7 @@ class EurekaHealthCheckHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUnknown() {
|
||||
void testUnknown() throws Exception {
|
||||
initialize(FatalHealthConfiguration.class);
|
||||
|
||||
InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UNKNOWN);
|
||||
@@ -130,38 +124,15 @@ class EurekaHealthCheckHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEurekaIgnored() {
|
||||
@Disabled // FIXME: 3.0.0
|
||||
void testEurekaIgnored() throws Exception {
|
||||
initialize(EurekaDownHealthConfiguration.class);
|
||||
|
||||
InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UP);
|
||||
assertThat(status).isEqualTo(InstanceStatus.UP);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCompositeComponentsDown() {
|
||||
initialize(CompositeComponentsDownHealthConfiguration.class);
|
||||
|
||||
InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UP);
|
||||
assertThat(status).isEqualTo(InstanceStatus.DOWN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCompositeComponentsUp() {
|
||||
initialize(CompositeComponentsUpHealthConfiguration.class);
|
||||
|
||||
InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UP);
|
||||
assertThat(status).isEqualTo(InstanceStatus.UP);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCompositeComponentsOneDown() {
|
||||
initialize(CompositeComponentsOneDownHealthConfiguration.class);
|
||||
|
||||
InstanceStatus status = healthCheckHandler.getStatus(InstanceStatus.UP);
|
||||
assertThat(status).isEqualTo(InstanceStatus.DOWN);
|
||||
}
|
||||
|
||||
private void initialize(Class<?>... configurations) {
|
||||
private void initialize(Class<?>... configurations) throws Exception {
|
||||
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(configurations);
|
||||
healthCheckHandler.setApplicationContext(applicationContext);
|
||||
healthCheckHandler.afterPropertiesSet();
|
||||
@@ -173,7 +144,7 @@ class EurekaHealthCheckHandlerTests {
|
||||
public HealthIndicator healthIndicator() {
|
||||
return new AbstractHealthIndicator() {
|
||||
@Override
|
||||
protected void doHealthCheck(Health.Builder builder) {
|
||||
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||
builder.up();
|
||||
}
|
||||
};
|
||||
@@ -187,7 +158,7 @@ class EurekaHealthCheckHandlerTests {
|
||||
public HealthIndicator healthIndicator() {
|
||||
return new AbstractHealthIndicator() {
|
||||
@Override
|
||||
protected void doHealthCheck(Health.Builder builder) {
|
||||
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||
builder.down();
|
||||
}
|
||||
};
|
||||
@@ -201,7 +172,7 @@ class EurekaHealthCheckHandlerTests {
|
||||
public HealthIndicator healthIndicator() {
|
||||
return new AbstractHealthIndicator() {
|
||||
@Override
|
||||
protected void doHealthCheck(Health.Builder builder) {
|
||||
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||
builder.status("fatal");
|
||||
}
|
||||
};
|
||||
@@ -267,76 +238,4 @@ class EurekaHealthCheckHandlerTests {
|
||||
|
||||
}
|
||||
|
||||
protected static class CompositeComponentsDownHealthConfiguration {
|
||||
|
||||
@Bean
|
||||
public CompositeHealthContributor compositeHealthContributor() {
|
||||
return new TestCompositeHealthContributor(InstanceStatus.DOWN, InstanceStatus.DOWN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class CompositeComponentsUpHealthConfiguration {
|
||||
|
||||
@Bean
|
||||
public CompositeHealthContributor compositeHealthContributor() {
|
||||
return new TestCompositeHealthContributor(InstanceStatus.UP, InstanceStatus.UP);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class CompositeComponentsOneDownHealthConfiguration {
|
||||
|
||||
@Bean
|
||||
public CompositeHealthContributor compositeHealthContributor() {
|
||||
return new TestCompositeHealthContributor(InstanceStatus.UP, InstanceStatus.DOWN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestCompositeHealthContributor implements CompositeHealthContributor {
|
||||
|
||||
private final Map<String, HealthContributor> contributorMap = new HashMap<>();
|
||||
|
||||
TestCompositeHealthContributor(InstanceStatus firstContributorStatus, InstanceStatus secondContributorStatus) {
|
||||
contributorMap.put("first", new AbstractHealthIndicator() {
|
||||
@Override
|
||||
protected void doHealthCheck(Health.Builder builder) {
|
||||
builder.status(firstContributorStatus.name());
|
||||
}
|
||||
});
|
||||
contributorMap.put("second", new AbstractHealthIndicator() {
|
||||
@Override
|
||||
protected void doHealthCheck(Health.Builder builder) {
|
||||
builder.status(secondContributorStatus.name());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public HealthContributor getContributor(String name) {
|
||||
return contributorMap.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<NamedContributor<HealthContributor>> iterator() {
|
||||
Iterator<Map.Entry<String, HealthContributor>> iterator = contributorMap.entrySet().iterator();
|
||||
return new Iterator<>() {
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedContributor<HealthContributor> next() {
|
||||
Map.Entry<String, HealthContributor> entry = iterator.next();
|
||||
return NamedContributor.of(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+18
-9
@@ -18,9 +18,11 @@ package org.springframework.cloud.netflix.eureka;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
@@ -44,14 +46,14 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class EurekaInstanceConfigBeanTests {
|
||||
|
||||
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
||||
private String hostName;
|
||||
|
||||
private String ipAddress;
|
||||
|
||||
@BeforeEach
|
||||
void init() {
|
||||
void init() throws Exception {
|
||||
try (InetUtils utils = new InetUtils(new InetUtilsProperties())) {
|
||||
InetUtils.HostInfo hostInfo = utils.findFirstNonLoopbackHostInfo();
|
||||
this.hostName = hostInfo.getHostname();
|
||||
@@ -156,6 +158,13 @@ class EurekaInstanceConfigBeanTests {
|
||||
assertThat(getInstanceConfig().getInitialStatus()).as("initialStatus wrong").isEqualTo(InstanceStatus.UP);
|
||||
}
|
||||
|
||||
void testBadInitialStatus() {
|
||||
TestPropertyValues.of("eureka.instance.initial-status:FOO").applyTo(this.context);
|
||||
Assertions.assertThrows(BeanCreationException.class, () -> {
|
||||
setupContext();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomInitialStatus() {
|
||||
TestPropertyValues.of("eureka.instance.initial-status:STARTING").applyTo(this.context);
|
||||
@@ -164,7 +173,7 @@ class EurekaInstanceConfigBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPreferIpAddress() {
|
||||
void testPreferIpAddress() throws Exception {
|
||||
TestPropertyValues.of("eureka.instance.preferIpAddress:true").applyTo(this.context);
|
||||
setupContext();
|
||||
EurekaInstanceConfigBean instance = getInstanceConfig();
|
||||
@@ -174,7 +183,7 @@ class EurekaInstanceConfigBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultVirtualHostName() {
|
||||
void testDefaultVirtualHostName() throws Exception {
|
||||
TestPropertyValues.of("spring.application.name:myapp").applyTo(this.context);
|
||||
setupContext();
|
||||
assertThat(getInstanceConfig().getVirtualHostName()).as("virtualHostName wrong").isEqualTo("myapp");
|
||||
@@ -183,7 +192,7 @@ class EurekaInstanceConfigBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomVirtualHostName() {
|
||||
void testCustomVirtualHostName() throws Exception {
|
||||
TestPropertyValues.of("spring.application.name:myapp", "eureka.instance.virtualHostName=myvirthost",
|
||||
"eureka.instance.secureVirtualHostName=mysecurevirthost").applyTo(this.context);
|
||||
setupContext();
|
||||
@@ -194,7 +203,7 @@ class EurekaInstanceConfigBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultAppName() {
|
||||
void testDefaultAppName() throws Exception {
|
||||
setupContext();
|
||||
assertThat(getInstanceConfig().getAppname()).as("default app name is wrong").isEqualTo("unknown");
|
||||
assertThat(getInstanceConfig().getVirtualHostName()).as("default virtual hostname is wrong")
|
||||
@@ -204,21 +213,21 @@ class EurekaInstanceConfigBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomInstanceId() {
|
||||
void testCustomInstanceId() throws Exception {
|
||||
TestPropertyValues.of("eureka.instance.instanceId=myinstance").applyTo(this.context);
|
||||
setupContext();
|
||||
assertThat(getInstanceConfig().getInstanceId()).as("instance id is wrong").isEqualTo("myinstance");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomInstanceIdWithMetadata() {
|
||||
void testCustomInstanceIdWithMetadata() throws Exception {
|
||||
TestPropertyValues.of("eureka.instance.metadataMap.instanceId=myinstance").applyTo(this.context);
|
||||
setupContext();
|
||||
assertThat(getInstanceConfig().getInstanceId()).as("instance id is wrong").isEqualTo("myinstance");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultInstanceId() {
|
||||
void testDefaultInstanceId() throws Exception {
|
||||
setupContext();
|
||||
assertThat(getInstanceConfig().getInstanceId()).as("default instance id is wrong").isEqualTo(null);
|
||||
}
|
||||
|
||||
+5
-3
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -32,10 +34,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class InstanceInfoFactoryTests {
|
||||
|
||||
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
||||
@Test
|
||||
void instanceIdIsHostNameByDefault() {
|
||||
void instanceIdIsHostNameByDefault() throws IOException {
|
||||
InstanceInfo instanceInfo = setupInstance();
|
||||
try (InetUtils utils = new InetUtils(new InetUtilsProperties())) {
|
||||
assertThat(instanceInfo.getId()).isEqualTo(utils.findFirstNonLoopbackHostInfo().getHostname());
|
||||
@@ -43,7 +45,7 @@ class InstanceInfoFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void instanceIdIsIpWhenIpPreferred() {
|
||||
void instanceIdIsIpWhenIpPreferred() throws Exception {
|
||||
InstanceInfo instanceInfo = setupInstance("eureka.instance.preferIpAddress:true");
|
||||
assertThat(instanceInfo.getId().matches("(\\d+\\.){3}\\d+")).isTrue();
|
||||
}
|
||||
|
||||
+5
-5
@@ -21,7 +21,6 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.cloud.commons.util.UtilAutoConfiguration;
|
||||
import org.springframework.cloud.config.server.config.ConfigServerProperties;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
|
||||
|
||||
@@ -36,15 +35,16 @@ class EurekaClientConfigServerAutoConfigurationTests {
|
||||
@Test
|
||||
void offByDefault() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaClientConfigServerAutoConfiguration.class))
|
||||
.run(c -> assertThat(c.getBeanNamesForType(EurekaInstanceConfigBean.class).length).isEqualTo(0));
|
||||
.withConfiguration(AutoConfigurations.of(EurekaClientConfigServerAutoConfiguration.class)).run(c -> {
|
||||
assertThat(c.getBeanNamesForType(EurekaInstanceConfigBean.class).length).isEqualTo(0);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void onWhenRequested() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaClientConfigServerAutoConfiguration.class,
|
||||
UtilAutoConfiguration.class, ConfigServerProperties.class, EurekaInstanceConfigBean.class))
|
||||
ConfigServerProperties.class, EurekaInstanceConfigBean.class))
|
||||
.withPropertyValues("spring.cloud.config.server.prefix=/config").run(c -> {
|
||||
assertThat(c.getBeanNamesForType(EurekaInstanceConfig.class).length).isEqualTo(1);
|
||||
EurekaInstanceConfig instance = c.getBean(EurekaInstanceConfig.class);
|
||||
@@ -56,7 +56,7 @@ class EurekaClientConfigServerAutoConfigurationTests {
|
||||
void notOverridingMetamapSettings() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaClientConfigServerAutoConfiguration.class,
|
||||
UtilAutoConfiguration.class, ConfigServerProperties.class, EurekaInstanceConfigBean.class))
|
||||
ConfigServerProperties.class, EurekaInstanceConfigBean.class))
|
||||
.withPropertyValues("spring.cloud.config.server.prefix=/config")
|
||||
.withPropertyValues("eureka.instance.metadataMap.configPath=/differentpath").run(c -> {
|
||||
assertThat(c.getBeanNamesForType(EurekaInstanceConfig.class).length).isEqualTo(1);
|
||||
|
||||
+36
-14
@@ -63,50 +63,63 @@ public class EurekaConfigServerBootstrapConfigurationTests {
|
||||
public void offByDefault() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
.run(context -> {
|
||||
assertEurekaBeansNotPresent(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void properBeansCreatedWhenDiscoveryEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true").run(this::assertEurekaBeansPresent);
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true").run(context -> {
|
||||
assertEurekaBeansPresent(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenDiscoveryNotEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=false")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=false").run(context -> {
|
||||
assertEurekaBeansNotPresent(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenDiscoveryDisabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.disabled").run(this::assertEurekaBeansNotPresent);
|
||||
.withPropertyValues("spring.cloud.config.discovery.disabled").run(context -> {
|
||||
assertEurekaBeansNotPresent(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenEurekaClientEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("eureka.client.enabled=true").run(this::assertEurekaBeansNotPresent);
|
||||
.withPropertyValues("eureka.client.enabled=true").run(context -> {
|
||||
assertEurekaBeansNotPresent(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenEurekaClientNotEnabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("eureka.client.enabled=false").run(this::assertEurekaBeansNotPresent);
|
||||
.withPropertyValues("eureka.client.enabled=false").run(context -> {
|
||||
assertEurekaBeansNotPresent(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansNotCreatedWhenEurekaClientDisabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("eureka.client.disabled").run(this::assertEurekaBeansNotPresent);
|
||||
.withPropertyValues("eureka.client.disabled").run(context -> {
|
||||
assertEurekaBeansNotPresent(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -114,7 +127,9 @@ public class EurekaConfigServerBootstrapConfigurationTests {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=true")
|
||||
.run(this::assertEurekaBeansPresent);
|
||||
.run(context -> {
|
||||
assertEurekaBeansPresent(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -122,7 +137,9 @@ public class EurekaConfigServerBootstrapConfigurationTests {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=false")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
.run(context -> {
|
||||
assertEurekaBeansNotPresent(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -130,7 +147,9 @@ public class EurekaConfigServerBootstrapConfigurationTests {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=false", "eureka.client.enabled=true")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
.run(context -> {
|
||||
assertEurekaBeansNotPresent(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -138,7 +157,9 @@ public class EurekaConfigServerBootstrapConfigurationTests {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=false", "eureka.client.enabled=false")
|
||||
.run(this::assertEurekaBeansNotPresent);
|
||||
.run(context -> {
|
||||
assertEurekaBeansNotPresent(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -150,8 +171,9 @@ public class EurekaConfigServerBootstrapConfigurationTests {
|
||||
"eureka.client.use-dns-for-fetching-service-urls=true",
|
||||
"eureka.client.eureka-server-d-n-s-name=myeurekahost",
|
||||
"eureka.client.eureka-server-u-r-l-context=eureka", "eureka.client.eureka-server-port=30000")
|
||||
.run(context -> assertThat(output)
|
||||
.contains("Cannot get cnames bound to the region:txt.us-east-1.myeurekahost"));
|
||||
.run(context -> {
|
||||
assertThat(output).contains("Cannot get cnames bound to the region:txt.us-east-1.myeurekahost");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+12
-10
@@ -22,12 +22,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.cloud.netflix.eureka.http.WebClientEurekaHttpClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
@@ -62,17 +61,20 @@ class EurekaConfigServerBootstrapConfigurationWebClientIntegrationTests {
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
static class WebClientController {
|
||||
static class WebClientController extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@GetMapping("/")
|
||||
@GetMapping
|
||||
public String hello() {
|
||||
return ".".repeat(300000);
|
||||
StringBuilder s = new StringBuilder();
|
||||
for (int i = 0; i < 300000; i++) {
|
||||
s.append(".");
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests().anyRequest().permitAll().and().csrf().disable();
|
||||
return http.build();
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests().anyRequest().permitAll().and().csrf().disable();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-155
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.BeanDescription;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
|
||||
import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.converters.jackson.serializer.InstanceInfoJsonBeanSerializer;
|
||||
import com.netflix.discovery.shared.Application;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockserver.client.MockServerClient;
|
||||
import org.testcontainers.containers.MockServerContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.environment.PropertySource;
|
||||
import org.springframework.cloud.netflix.eureka.http.EurekaApplications;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockserver.model.HttpRequest.request;
|
||||
import static org.mockserver.model.HttpResponse.response;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@Testcontainers
|
||||
public class EurekaConfigServerBootstrapperIT {
|
||||
|
||||
public static final DockerImageName MOCKSERVER_IMAGE = DockerImageName.parse("mockserver/mockserver")
|
||||
.withTag("mockserver-" + MockServerClient.class.getPackage().getImplementationVersion());
|
||||
|
||||
@Container
|
||||
static MockServerContainer mockServer = new MockServerContainer(MOCKSERVER_IMAGE);
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@BeforeEach
|
||||
void before() {
|
||||
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void after() {
|
||||
this.context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws JsonProcessingException {
|
||||
Environment environment = new Environment("test", "default");
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put("hello", "world");
|
||||
PropertySource p = new PropertySource("p1", properties);
|
||||
environment.add(p);
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
SimpleModule jsonModule = new SimpleModule();
|
||||
jsonModule.setSerializerModifier(createJsonSerializerModifier());
|
||||
objectMapper.registerModule(jsonModule);
|
||||
try (MockServerClient mockServerClient = new MockServerClient(mockServer.getHost(),
|
||||
mockServer.getMappedPort(MockServerContainer.PORT))) {
|
||||
mockServerClient.when(request().withPath("/application/default"))
|
||||
.respond(response().withBody(objectMapper.writeValueAsString(environment))
|
||||
.withHeader("content-type", "application/json"));
|
||||
InstanceInfo configServerInstanceInfo = InstanceInfo.Builder.newBuilder()
|
||||
.setVIPAddress("eureka-configserver").setInstanceId("eureka-configserver")
|
||||
.setAppName("eureka-configserver").setStatus(InstanceInfo.InstanceStatus.UP)
|
||||
.enablePort(InstanceInfo.PortType.UNSECURE, true).setHostName("localhost")
|
||||
.setPort(mockServer.getMappedPort(MockServerContainer.PORT)).build();
|
||||
Application configServer = new Application("eureka-configserver",
|
||||
Collections.singletonList(configServerInstanceInfo));
|
||||
EurekaApplications eurekaApplications = new EurekaApplications("hashcode", 0L,
|
||||
Collections.singletonList(configServer));
|
||||
mockServerClient.when(request().withPath("/apps/"))
|
||||
.respond(response()
|
||||
.withBody("{\"applications\":" + objectMapper.writeValueAsString(eurekaApplications) + "}")
|
||||
.withHeader("content-type", "application/json"));
|
||||
this.context = setup().run();
|
||||
assertThat(this.context.getEnvironment().getProperty("hello")).isEqualTo("world");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static BeanSerializerModifier createJsonSerializerModifier() {
|
||||
return new BeanSerializerModifier() {
|
||||
@Override
|
||||
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc,
|
||||
JsonSerializer<?> serializer) {
|
||||
if (beanDesc.getBeanClass().isAssignableFrom(InstanceInfo.class)) {
|
||||
return new InstanceInfoJsonBeanSerializer((BeanSerializerBase) serializer, false);
|
||||
}
|
||||
return serializer;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
SpringApplicationBuilder setup(String... env) {
|
||||
SpringApplicationBuilder builder = new SpringApplicationBuilder(TestConfig.class)
|
||||
.properties(addDefaultEnv(env));
|
||||
return builder;
|
||||
}
|
||||
|
||||
private String[] addDefaultEnv(String[] env) {
|
||||
Set<String> set = new LinkedHashSet<>();
|
||||
if (env != null && env.length > 0) {
|
||||
set.addAll(Arrays.asList(env));
|
||||
}
|
||||
set.add("spring.config.import=classpath:bootstrapper.yaml");
|
||||
set.add("spring.cloud.config.enabled=true");
|
||||
set.add("spring.cloud.service-registry.auto-registration.enabled=false");
|
||||
set.add("eureka.client.serviceUrl.defaultZone=http://" + mockServer.getHost() + ":"
|
||||
+ mockServer.getMappedPort(MockServerContainer.PORT));
|
||||
return set.toArray(new String[0]);
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
static class TestConfig {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+7
-47
@@ -16,79 +16,39 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.config;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.properties.bind.BindHandler;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.cloud.config.client.ConfigClientProperties;
|
||||
import org.springframework.cloud.config.client.ConfigServerInstanceProvider;
|
||||
import org.springframework.web.client.ResourceAccessException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
class EurekaConfigServerBootstrapperTests {
|
||||
|
||||
@Test
|
||||
void notEnabledReturnsEmptyList() {
|
||||
void notEnabledDoesNotAddInstanceProviderFn() {
|
||||
new SpringApplicationBuilder(TestConfig.class)
|
||||
.properties("spring.cloud.service-registry.auto-registration.enabled=false")
|
||||
.addBootstrapRegistryInitializer(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
assertThat(providerFn.apply("id")).as("Should return empty list").isEmpty();
|
||||
})).run().close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoveryClientNotEnabledProvidesEmptyList() {
|
||||
new SpringApplicationBuilder(TestConfig.class)
|
||||
.properties("spring.cloud.config.discovery.enabled=true", "spring.cloud.discovery.enabled=false",
|
||||
"spring.cloud.service-registry.auto-registration.enabled=false")
|
||||
.addBootstrapRegistryInitializer(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
Binder binder = event.getBootstrapContext().get(Binder.class);
|
||||
BindHandler bindHandler = event.getBootstrapContext().get(BindHandler.class);
|
||||
assertThat(providerFn.apply("id", binder, bindHandler, mock(Log.class)))
|
||||
.as("Should return empty list").isEmpty();
|
||||
})).run().close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eurekaClientNotEnabledProvidesEmptyList() {
|
||||
new SpringApplicationBuilder(TestConfig.class)
|
||||
.properties("spring.cloud.config.discovery.enabled=true", "eureka.client.enabled=false",
|
||||
"spring.cloud.service-registry.auto-registration.enabled=false")
|
||||
.addBootstrapRegistryInitializer(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
Binder binder = event.getBootstrapContext().get(Binder.class);
|
||||
BindHandler bindHandler = event.getBootstrapContext().get(BindHandler.class);
|
||||
assertThat(providerFn.apply("id", binder, bindHandler, mock(Log.class)))
|
||||
.as("Should return empty list").isEmpty();
|
||||
assertThat(providerFn).as("ConfigServerInstanceProvider.Function was created when it shouldn't")
|
||||
.isNull();
|
||||
})).run().close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void enabledAddsInstanceProviderFn() {
|
||||
new SpringApplicationBuilder(TestConfig.class)
|
||||
.properties("spring.config.import: classpath:bootstrapper.yaml",
|
||||
ConfigClientProperties.PREFIX + ".enabled=true")
|
||||
.properties("spring.cloud.config.discovery.enabled=true",
|
||||
"spring.cloud.service-registry.auto-registration.enabled=false")
|
||||
.addBootstrapRegistryInitializer(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
Binder binder = event.getBootstrapContext().get(Binder.class);
|
||||
BindHandler bindHandler = event.getBootstrapContext().get(BindHandler.class);
|
||||
assertThatThrownBy(() -> providerFn.apply("id", binder, bindHandler, mock(Log.class)))
|
||||
.isInstanceOf(ResourceAccessException.class)
|
||||
.hasMessageContaining("I/O error on GET request for \"http://localhost:8761/eureka/apps/\"")
|
||||
.as("Should have tried to connect to Eureka to fetch instances.");
|
||||
assertThat(providerFn).as("ConfigServerInstanceProvider.Function was not created when it should.")
|
||||
.isNotNull();
|
||||
})).run().close();
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -40,6 +40,7 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||
public class EurekaHttpClientsOptionalArgsConfigurationNoWebfluxTest {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void contextFailsWithoutWebClient() {
|
||||
|
||||
ConfigurableApplicationContext ctx = null;
|
||||
@@ -51,7 +52,7 @@ public class EurekaHttpClientsOptionalArgsConfigurationNoWebfluxTest {
|
||||
}
|
||||
catch (Exception e) {
|
||||
// this is the desired state
|
||||
assertThat(e).hasStackTraceContaining("WebClient is not on the classpath");
|
||||
assertThat(e).hasMessageContaining("WebClient is not on the classpath");
|
||||
}
|
||||
if (ctx != null) {
|
||||
ctx.close();
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.config;
|
||||
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
|
||||
import com.netflix.discovery.DiscoveryClient.DiscoveryClientOptionalArgs;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class JerseyOptionalArgsConfigurationTest {
|
||||
|
||||
@Autowired
|
||||
private AbstractDiscoveryClientOptionalArgs optionalArgs;
|
||||
private DiscoveryClientOptionalArgs optionalArgs;
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
|
||||
+2
-15
@@ -36,7 +36,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* Tests the Eureka health check handler.
|
||||
*
|
||||
* @author Jakub Narloch
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@SpringBootTest(classes = EurekaHealthCheckTests.EurekaHealthCheckApplication.class,
|
||||
webEnvironment = WebEnvironment.RANDOM_PORT, value = { "eureka.client.healthcheck.enabled=true", "debug=true" })
|
||||
@@ -48,24 +47,12 @@ class EurekaHealthCheckTests {
|
||||
|
||||
@Test
|
||||
void shouldRegisterService() {
|
||||
System.setProperty("status", "UP");
|
||||
|
||||
InstanceInfo.InstanceStatus status = this.discoveryClient.getHealthCheckHandler()
|
||||
.getStatus(InstanceInfo.InstanceStatus.UNKNOWN);
|
||||
|
||||
assertThat(status).isNotNull();
|
||||
assertThat(status).isEqualTo(InstanceInfo.InstanceStatus.UP);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldMapOutOfServiceToDown() {
|
||||
System.setProperty("status", "OUT_OF_SERVICE");
|
||||
|
||||
InstanceInfo.InstanceStatus status = this.discoveryClient.getHealthCheckHandler()
|
||||
.getStatus(InstanceInfo.InstanceStatus.UNKNOWN);
|
||||
|
||||
assertThat(status).isNotNull();
|
||||
assertThat(status).isEqualTo(InstanceInfo.InstanceStatus.DOWN);
|
||||
assertThat(status).isEqualTo(InstanceInfo.InstanceStatus.OUT_OF_SERVICE);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@@ -74,7 +61,7 @@ class EurekaHealthCheckTests {
|
||||
|
||||
@Bean
|
||||
public HealthIndicator healthIndicator() {
|
||||
return () -> new Health.Builder().status(System.getProperty("status")).build();
|
||||
return () -> new Health.Builder().outOfService().build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-11
@@ -19,7 +19,6 @@ package org.springframework.cloud.netflix.eureka.http;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.shared.Applications;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -29,7 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
/**
|
||||
* @author Haytham Mohamed
|
||||
**/
|
||||
abstract class AbstractEurekaHttpClientTests {
|
||||
abstract class AbstractEurekaHttpClientTest {
|
||||
|
||||
protected EurekaHttpClient eurekaHttpClient;
|
||||
|
||||
@@ -49,9 +48,8 @@ abstract class AbstractEurekaHttpClientTests {
|
||||
|
||||
@Test
|
||||
void testSendHeartBeat() {
|
||||
EurekaHttpResponse<InstanceInfo> response = eurekaHttpClient.sendHeartBeat("test", "test", info, null);
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK.value());
|
||||
assertThat(response.getEntity()).isNotNull();
|
||||
assertThat(eurekaHttpClient.sendHeartBeat("test", "test", info, null).getStatusCode())
|
||||
.isEqualTo(HttpStatus.OK.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,12 +58,6 @@ abstract class AbstractEurekaHttpClientTests {
|
||||
.isEqualTo(HttpStatus.NOT_FOUND.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendHeartBeatFourOFourWithBody() {
|
||||
assertThat(eurekaHttpClient.sendHeartBeat("fourOFourWithBody", "test", info, null).getStatusCode())
|
||||
.isEqualTo(HttpStatus.NOT_FOUND.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStatusUpdate() {
|
||||
assertThat(eurekaHttpClient.statusUpdate("test", "test", InstanceInfo.InstanceStatus.UP, info).getStatusCode())
|
||||
+16
-23
@@ -35,17 +35,16 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@@ -61,7 +60,6 @@ import static org.springframework.util.Assert.isTrue;
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@RestController
|
||||
@RequestMapping("/eureka")
|
||||
@SpringBootApplication
|
||||
public class EurekaServerMockApplication {
|
||||
|
||||
@@ -118,11 +116,6 @@ public class EurekaServerMockApplication {
|
||||
if ("fourOFour".equals(appName)) {
|
||||
return new ResponseEntity(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
if ("fourOFourWithBody".equals(appName)) {
|
||||
return new ResponseEntity(
|
||||
"{ \"error\": \"Not Found\", \"message\": null, \"path\": \"/1\", \"requestId\": \"9e5d3244-1\", \"status\": 404, \"timestamp\": \"2023-03-04T03:31:20.810+00:00\" }",
|
||||
HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(new InstanceInfo(null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, 0, null, null, null, null, null, null, null, new HashMap<>(), 0L, 0L, null, null),
|
||||
HttpStatus.OK);
|
||||
@@ -142,7 +135,7 @@ public class EurekaServerMockApplication {
|
||||
|
||||
}
|
||||
|
||||
@GetMapping({ "/apps/", "/apps/delta", "/vips/{address}", "/svips/{address}" })
|
||||
@GetMapping({ "/apps", "/apps/delta", "/vips/{address}", "/svips/{address}" })
|
||||
public Applications getApplications(@PathVariable(required = false) String address,
|
||||
@RequestParam(required = false) String regions) {
|
||||
Applications applications = new Applications();
|
||||
@@ -162,23 +155,23 @@ public class EurekaServerMockApplication {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
protected static class TestSecurityConfiguration {
|
||||
protected static class TestSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Bean
|
||||
public InMemoryUserDetailsManager userDetailsService() {
|
||||
UserDetails user = User.withDefaultPasswordEncoder().username("test").password("test").roles("USER")
|
||||
.build();
|
||||
return new InMemoryUserDetailsManager(user);
|
||||
TestSecurityConfiguration() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatcher("/v2/apps/**")
|
||||
.httpBasic();
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
public UserDetailsService userDetailsService() {
|
||||
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
|
||||
manager.createUser(User.withUsername("test").password("{noop}test").roles("USER").build());
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// super.configure(http);
|
||||
http.antMatcher("/apps/**").httpBasic();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-24
@@ -16,12 +16,9 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.http;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider;
|
||||
import com.netflix.discovery.shared.resolver.DefaultEndpoint;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -29,27 +26,20 @@ import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.cloud.commons.util.InetUtils;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
@SpringBootTest(classes = EurekaServerMockApplication.class,
|
||||
properties = { "debug=true", "security.basic.enabled=true", "eureka.client.fetch-registry=false",
|
||||
"eureka.client.register-with-eureka=false", "logging.level.org.springframework=INFO" },
|
||||
webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
properties = { "debug=true", "security.basic.enabled=true" }, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@DirtiesContext
|
||||
class RestTemplateEurekaHttpClientTests extends AbstractEurekaHttpClientTests {
|
||||
class RestTemplateEurekaHttpClientTest extends AbstractEurekaHttpClientTest {
|
||||
|
||||
@Autowired
|
||||
private InetUtils inetUtils;
|
||||
|
||||
@Value("http://${security.user.name}:${security.user.password}@localhost:${local.server.port}/eureka")
|
||||
@Value("http://${security.user.name}:${security.user.password}@localhost:${local.server.port}")
|
||||
private String serviceUrl;
|
||||
|
||||
@BeforeEach
|
||||
@@ -71,15 +61,4 @@ class RestTemplateEurekaHttpClientTests extends AbstractEurekaHttpClientTests {
|
||||
info = new EurekaConfigBasedInstanceInfoProvider(config).get();
|
||||
}
|
||||
|
||||
@Test
|
||||
void basicAuth() {
|
||||
assertThat(eurekaHttpClient).isInstanceOf(RestTemplateEurekaHttpClient.class);
|
||||
RestTemplateEurekaHttpClient restTemplateEurekaHttpClient = (RestTemplateEurekaHttpClient) eurekaHttpClient;
|
||||
RestTemplate restTemplate = restTemplateEurekaHttpClient.getRestTemplate();
|
||||
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
|
||||
boolean hasBasicAuth = interceptors.stream()
|
||||
.anyMatch(interceptor -> interceptor instanceof BasicAuthenticationInterceptor);
|
||||
assertThat(hasBasicAuth).as("Basic Auth not configured").isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.http;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
class RestTemplateTransportClientFactoriesTest {
|
||||
|
||||
@Test
|
||||
void testJerseyIsUnsupported() {
|
||||
Assertions.assertThrows(UnsupportedOperationException.class, () -> {
|
||||
new RestTemplateTransportClientFactories(new RestTemplateDiscoveryClientOptionalArgs(null))
|
||||
.newTransportClientFactory(null, null);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
+3
-4
@@ -33,16 +33,15 @@ import org.springframework.web.reactive.function.client.WebClient;
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
@SpringBootTest(classes = EurekaServerMockApplication.class,
|
||||
properties = { "debug=true", "security.basic.enabled=true", "eureka.client.webclient.enabled=true",
|
||||
"eureka.client.fetch-registry=false", "eureka.client.register-with-eureka=false" },
|
||||
properties = { "debug=true", "security.basic.enabled=true", "eureka.client.webclient.enabled=true" },
|
||||
webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@DirtiesContext
|
||||
class WebClientEurekaHttpClientTests extends AbstractEurekaHttpClientTests {
|
||||
class WebClientEurekaHttpClientTest extends AbstractEurekaHttpClientTest {
|
||||
|
||||
@Autowired
|
||||
private InetUtils inetUtils;
|
||||
|
||||
@Value("http://${security.user.name}:${security.user.password}@localhost:${local.server.port}/eureka/")
|
||||
@Value("http://${security.user.name}:${security.user.password}@localhost:${local.server.port}")
|
||||
private String serviceUrl;
|
||||
|
||||
@BeforeEach
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.http;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
class WebClientTransportClientFactoriesTest {
|
||||
|
||||
@Test
|
||||
void testJerseyIsUnsupported() {
|
||||
Assertions.assertThrows(UnsupportedOperationException.class, () -> {
|
||||
new WebClientTransportClientFactories(WebClient::builder).newTransportClientFactory(null, null);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+5
-5
@@ -35,16 +35,16 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class EurekaLoadBalancerClientConfigurationTests {
|
||||
|
||||
private final EurekaClientConfigBean eurekaClientConfig = new EurekaClientConfigBean();
|
||||
private EurekaClientConfigBean eurekaClientConfig = new EurekaClientConfigBean();
|
||||
|
||||
private final EurekaInstanceConfigBean eurekaInstanceConfig = new EurekaInstanceConfigBean(
|
||||
private EurekaInstanceConfigBean eurekaInstanceConfig = new EurekaInstanceConfigBean(
|
||||
new InetUtils(new InetUtilsProperties()));
|
||||
|
||||
private final LoadBalancerZoneConfig zoneConfig = new LoadBalancerZoneConfig(null);
|
||||
private LoadBalancerZoneConfig zoneConfig = new LoadBalancerZoneConfig(null);
|
||||
|
||||
private final EurekaLoadBalancerProperties eurekaLoadBalancerProperties = new EurekaLoadBalancerProperties();
|
||||
private EurekaLoadBalancerProperties eurekaLoadBalancerProperties = new EurekaLoadBalancerProperties();
|
||||
|
||||
private final EurekaLoadBalancerClientConfiguration postprocessor = new EurekaLoadBalancerClientConfiguration(
|
||||
private EurekaLoadBalancerClientConfiguration postprocessor = new EurekaLoadBalancerClientConfiguration(
|
||||
eurekaClientConfig, eurekaInstanceConfig, zoneConfig, eurekaLoadBalancerProperties);
|
||||
|
||||
@Test
|
||||
|
||||
+12
-12
@@ -33,7 +33,7 @@ class DefaultManagementMetadataProviderTest {
|
||||
private final ManagementMetadataProvider provider = new DefaultManagementMetadataProvider();
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
void setUp() throws Exception {
|
||||
when(INSTANCE.getHostname()).thenReturn("host");
|
||||
when(INSTANCE.getHealthCheckUrlPath()).thenReturn("health");
|
||||
when(INSTANCE.getStatusPageUrlPath()).thenReturn("info");
|
||||
@@ -41,7 +41,7 @@ class DefaultManagementMetadataProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void serverPortIsRandomAndManagementPortIsNull() {
|
||||
void serverPortIsRandomAndManagementPortIsNull() throws Exception {
|
||||
int serverPort = 0;
|
||||
String serverContextPath = "/";
|
||||
String managementContextPath = null;
|
||||
@@ -53,7 +53,7 @@ class DefaultManagementMetadataProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void managementPortIsRandom() {
|
||||
void managementPortIsRandom() throws Exception {
|
||||
int serverPort = 0;
|
||||
String serverContextPath = "/";
|
||||
String managementContextPath = null;
|
||||
@@ -65,7 +65,7 @@ class DefaultManagementMetadataProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void serverPort() {
|
||||
void serverPort() throws Exception {
|
||||
int serverPort = 7777;
|
||||
String serverContextPath = "/";
|
||||
String managementContextPath = null;
|
||||
@@ -80,7 +80,7 @@ class DefaultManagementMetadataProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void serverPortManagementPort() {
|
||||
void serverPortManagementPort() throws Exception {
|
||||
int serverPort = 7777;
|
||||
String serverContextPath = "/";
|
||||
String managementContextPath = null;
|
||||
@@ -95,7 +95,7 @@ class DefaultManagementMetadataProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void serverPortManagementPortServerContextPath() {
|
||||
void serverPortManagementPortServerContextPath() throws Exception {
|
||||
int serverPort = 7777;
|
||||
String serverContextPath = "/Server";
|
||||
String managementContextPath = null;
|
||||
@@ -110,7 +110,7 @@ class DefaultManagementMetadataProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void serverPortManagementPortServerContextPathManagementContextPath() {
|
||||
void serverPortManagementPortServerContextPathManagementContextPath() throws Exception {
|
||||
int serverPort = 7777;
|
||||
String serverContextPath = "/Server";
|
||||
String managementContextPath = "/Management";
|
||||
@@ -125,7 +125,7 @@ class DefaultManagementMetadataProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void serverPortServerContextPathManagementContextPath() {
|
||||
void serverPortServerContextPathManagementContextPath() throws Exception {
|
||||
int serverPort = 7777;
|
||||
String serverContextPath = "/Server";
|
||||
String managementContextPath = "/Management";
|
||||
@@ -140,7 +140,7 @@ class DefaultManagementMetadataProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void serverPortManagementContextPath() {
|
||||
void serverPortManagementContextPath() throws Exception {
|
||||
int serverPort = 7777;
|
||||
String serverContextPath = "/";
|
||||
String managementContextPath = "/Management";
|
||||
@@ -155,7 +155,7 @@ class DefaultManagementMetadataProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void serverPortServerContextPath() {
|
||||
void serverPortServerContextPath() throws Exception {
|
||||
int serverPort = 7777;
|
||||
String serverContextPath = "/Server";
|
||||
String managementContextPath = null;
|
||||
@@ -170,7 +170,7 @@ class DefaultManagementMetadataProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void serverPortManagementPortManagementContextPath() {
|
||||
void serverPortManagementPortManagementContextPath() throws Exception {
|
||||
int serverPort = 7777;
|
||||
String serverContextPath = "/";
|
||||
String managementContextPath = "/Management";
|
||||
@@ -186,7 +186,7 @@ class DefaultManagementMetadataProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setSecureHealthCheckUrl() {
|
||||
void setSecureHealthCheckUrl() throws Exception {
|
||||
int serverPort = 7777;
|
||||
String serverContextPath = "/";
|
||||
String managementContextPath = "/Management";
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class EurekaReactiveDiscoveryClientConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(UtilAutoConfiguration.class,
|
||||
ReactiveCommonsClientAutoConfiguration.class, EurekaClientAutoConfiguration.class,
|
||||
DiscoveryClientOptionalArgsConfiguration.class, EurekaReactiveDiscoveryClientConfiguration.class));
|
||||
|
||||
+4
@@ -18,6 +18,7 @@ package org.springframework.cloud.netflix.eureka.reactive;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.shared.Application;
|
||||
import com.netflix.discovery.shared.Applications;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -46,6 +47,9 @@ class EurekaReactiveDiscoveryClientTests {
|
||||
@Mock
|
||||
private EurekaClient eurekaClient;
|
||||
|
||||
@Mock
|
||||
private EurekaClientConfig clientConfig;
|
||||
|
||||
@InjectMocks
|
||||
private EurekaReactiveDiscoveryClient client;
|
||||
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.netflix.eureka.sample;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.netflix.appinfo.HealthCheckHandler;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
@@ -102,7 +103,7 @@ public class EurekaSampleApplication implements ApplicationContextAware, Closeab
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
public void close() throws IOException {
|
||||
deregister();
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -62,7 +62,6 @@ class EurekaServiceRegistryTests {
|
||||
verifyNoInteractions(eurekaClient);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
void eurekaClientGetStatus() {
|
||||
EurekaServiceRegistry registry = new EurekaServiceRegistry();
|
||||
@@ -99,7 +98,6 @@ class EurekaServiceRegistryTests {
|
||||
OUT_OF_SERVICE.toString());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
void eurekaClientGetStatusNoInstance() {
|
||||
EurekaServiceRegistry registry = new EurekaServiceRegistry();
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
|
||||
# for EurekaRibbonClientPropertyOverrideIntegrationTests
|
||||
foo3:
|
||||
ribbon:
|
||||
NFLoadBalancerPingClassName: com.netflix.loadbalancer.DummyPing
|
||||
NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
|
||||
|
||||
security:
|
||||
basic:
|
||||
enabled: false
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
spring:
|
||||
config:
|
||||
import: "optional:configserver:"
|
||||
cloud:
|
||||
config:
|
||||
enabled: true
|
||||
discovery:
|
||||
service-id: eureka-configserver
|
||||
enabled: true
|
||||
service-registry:
|
||||
auto-registration:
|
||||
enabled: false
|
||||
@@ -5,17 +5,15 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>4.0.4-SNAPSHOT</version>
|
||||
<version>3.1.2-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<artifactId>spring-cloud-netflix-eureka-server</artifactId>
|
||||
<name>Spring Cloud Netflix Eureka Server</name>
|
||||
<url>https://projects.spring.io/spring-cloud/</url>
|
||||
<properties>
|
||||
<wro4j.version>1.10.1</wro4j.version>
|
||||
<wro4j.version>1.8.0</wro4j.version>
|
||||
<wiremock.version>2.27.2</wiremock.version>
|
||||
<!-- FIXME: 4.0.0 -->
|
||||
<duplicate-finder-maven-plugin.skip>true</duplicate-finder-maven-plugin.skip>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -50,39 +48,39 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.eureka</groupId>
|
||||
<artifactId>eureka-client-jersey3</artifactId>
|
||||
<artifactId>eureka-client</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>aopalliance</groupId>
|
||||
<artifactId>aopalliance</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.eureka</groupId>
|
||||
<artifactId>eureka-core-jersey3</artifactId>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-servlet</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.containers</groupId>
|
||||
<artifactId>jersey-container-servlet</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.core</groupId>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.core</groupId>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.inject</groupId>
|
||||
<artifactId>jersey-hk2</artifactId>
|
||||
<groupId>com.netflix.eureka</groupId>
|
||||
<artifactId>eureka-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>blitz4j</artifactId>
|
||||
<groupId>com.netflix.blitz4j</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.hk2</groupId>
|
||||
<artifactId>spring-bridge</artifactId>
|
||||
<!-- FIXME: 4.0 -->
|
||||
<version>3.0.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.inject</groupId>
|
||||
<artifactId>jakarta.inject-api</artifactId>
|
||||
<!-- FIXME: 4.0 -->
|
||||
<version>2.0.1</version>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
</dependency>
|
||||
<!-- Eureka deps that are now optional in eureka -->
|
||||
<dependency>
|
||||
@@ -178,12 +176,6 @@
|
||||
<contextFolder>${basedir}/src/main/wro</contextFolder>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<!-- https://github.com/wro4j/wro4j/issues/1129 -->
|
||||
<dependency>
|
||||
<groupId>org.webjars.npm</groupId>
|
||||
<artifactId>glob</artifactId>
|
||||
<version>7.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars.npm</groupId>
|
||||
<artifactId>jquery</artifactId>
|
||||
@@ -194,6 +186,11 @@
|
||||
<artifactId>bootstrap</artifactId>
|
||||
<version>5.1.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>3.6.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ public class CloudJacksonJson extends LegacyJacksonJson {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> String encode(T object) {
|
||||
public <T> String encode(T object) throws IOException {
|
||||
return this.codec.writeToString(object);
|
||||
}
|
||||
|
||||
|
||||
+6
-9
@@ -24,6 +24,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.netflix.appinfo.AmazonInfo;
|
||||
import com.netflix.appinfo.ApplicationInfoManager;
|
||||
import com.netflix.appinfo.DataCenterInfo;
|
||||
@@ -37,7 +39,6 @@ import com.netflix.eureka.registry.PeerAwareInstanceRegistry;
|
||||
import com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl;
|
||||
import com.netflix.eureka.resources.StatusResource;
|
||||
import com.netflix.eureka.util.StatusInfo;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@@ -47,7 +48,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Gang Li
|
||||
* @author Weix Sun
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("${eureka.dashboard.path:/}")
|
||||
@@ -56,13 +56,10 @@ public class EurekaController {
|
||||
@Value("${eureka.dashboard.path:/}")
|
||||
private String dashboardPath = "";
|
||||
|
||||
private final ApplicationInfoManager applicationInfoManager;
|
||||
private ApplicationInfoManager applicationInfoManager;
|
||||
|
||||
private final EurekaProperties eurekaProperties;
|
||||
|
||||
public EurekaController(ApplicationInfoManager applicationInfoManager, EurekaProperties eurekaProperties) {
|
||||
public EurekaController(ApplicationInfoManager applicationInfoManager) {
|
||||
this.applicationInfoManager = applicationInfoManager;
|
||||
this.eurekaProperties = eurekaProperties;
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
@@ -119,8 +116,8 @@ public class EurekaController {
|
||||
private void populateHeader(Map<String, Object> model) {
|
||||
model.put("currentTime", StatusResource.getCurrentTimeAsString());
|
||||
model.put("upTime", StatusInfo.getUpTime());
|
||||
model.put("environment", eurekaProperties.getEnvironment());
|
||||
model.put("datacenter", eurekaProperties.getDatacenter());
|
||||
model.put("environment", "N/A"); // FIXME:
|
||||
model.put("datacenter", "N/A"); // FIXME:
|
||||
PeerAwareInstanceRegistry registry = getRegistry();
|
||||
model.put("registry", registry);
|
||||
model.put("isBelowRenewThreshold", registry.isBelowRenewThresold() == 1);
|
||||
|
||||
-83
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.server;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Configuration properties for the Eureka deployment.
|
||||
*
|
||||
* @author Weix Sun
|
||||
*/
|
||||
@ConfigurationProperties("eureka")
|
||||
public class EurekaProperties {
|
||||
|
||||
/**
|
||||
* Eureka environment. Defaults to "test".
|
||||
*/
|
||||
private String environment = "test";
|
||||
|
||||
/**
|
||||
* Eureka datacenter. Defaults to "default".
|
||||
*/
|
||||
private String datacenter = "default";
|
||||
|
||||
public String getEnvironment() {
|
||||
return environment;
|
||||
}
|
||||
|
||||
public void setEnvironment(String environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public String getDatacenter() {
|
||||
return datacenter;
|
||||
}
|
||||
|
||||
public void setDatacenter(String datacenter) {
|
||||
this.datacenter = datacenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
EurekaProperties that = (EurekaProperties) o;
|
||||
return Objects.equals(datacenter, that.datacenter) && Objects.equals(environment, that.environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(environment, datacenter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("EurekaProperties{");
|
||||
sb.append("environment='").append(environment).append('\'');
|
||||
sb.append(", datacenter=").append(datacenter);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
+31
-228
@@ -16,73 +16,41 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.Application;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
import com.netflix.appinfo.ApplicationInfoManager;
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
import com.netflix.discovery.Jersey3DiscoveryClientOptionalArgs;
|
||||
import com.netflix.discovery.converters.EurekaJacksonCodec;
|
||||
import com.netflix.discovery.converters.wrappers.CodecWrapper;
|
||||
import com.netflix.discovery.converters.wrappers.CodecWrappers;
|
||||
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
|
||||
import com.netflix.discovery.shared.transport.jersey3.EurekaIdentityHeaderFilter;
|
||||
import com.netflix.discovery.shared.transport.jersey3.EurekaJersey3Client;
|
||||
import com.netflix.discovery.shared.transport.jersey3.EurekaJersey3ClientImpl;
|
||||
import com.netflix.discovery.shared.transport.jersey3.Jersey3TransportClientFactories;
|
||||
import com.netflix.eureka.DefaultEurekaServerContext;
|
||||
import com.netflix.eureka.EurekaServerConfig;
|
||||
import com.netflix.eureka.EurekaServerContext;
|
||||
import com.netflix.eureka.EurekaServerIdentity;
|
||||
import com.netflix.eureka.cluster.PeerEurekaNode;
|
||||
import com.netflix.eureka.cluster.PeerEurekaNodes;
|
||||
import com.netflix.eureka.registry.PeerAwareInstanceRegistry;
|
||||
import com.netflix.eureka.resources.DefaultServerCodecs;
|
||||
import com.netflix.eureka.resources.ServerCodecs;
|
||||
import com.netflix.eureka.transport.EurekaServerHttpClientFactory;
|
||||
import com.netflix.eureka.transport.Jersey3DynamicGZIPContentEncodingFilter;
|
||||
import com.netflix.eureka.transport.Jersey3EurekaServerHttpClientFactory;
|
||||
import com.netflix.eureka.transport.Jersey3ReplicationClient;
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.client.Client;
|
||||
import jakarta.ws.rs.client.ClientRequestFilter;
|
||||
import jakarta.ws.rs.core.Application;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.glassfish.hk2.api.ServiceLocator;
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.glassfish.jersey.server.spi.Container;
|
||||
import org.glassfish.jersey.server.spi.ContainerLifecycleListener;
|
||||
import org.glassfish.jersey.servlet.ServletContainer;
|
||||
import org.glassfish.jersey.servlet.ServletProperties;
|
||||
import org.jvnet.hk2.spring.bridge.api.SpringBridge;
|
||||
import org.jvnet.hk2.spring.bridge.api.SpringIntoHK2Bridge;
|
||||
import com.netflix.eureka.transport.JerseyReplicationClient;
|
||||
import com.sun.jersey.api.core.DefaultResourceConfig;
|
||||
import com.sun.jersey.spi.container.servlet.ServletContainer;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.cloud.client.actuator.HasFeatures;
|
||||
@@ -99,36 +67,25 @@ import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* @author Gunnar Hillert
|
||||
* @author Biju Kunjummen
|
||||
* @author Fahim Farook
|
||||
* @author Weix Sun
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import(EurekaServerInitializerConfiguration.class)
|
||||
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
|
||||
@EnableConfigurationProperties({ EurekaDashboardProperties.class, InstanceRegistryProperties.class,
|
||||
EurekaProperties.class })
|
||||
@EnableConfigurationProperties({ EurekaDashboardProperties.class, InstanceRegistryProperties.class })
|
||||
@PropertySource("classpath:/eureka/server.properties")
|
||||
public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
|
||||
|
||||
private static final Log log = LogFactory.getLog(EurekaServerAutoConfiguration.class);
|
||||
|
||||
/**
|
||||
* List of packages containing Jersey resources required by the Eureka server.
|
||||
*/
|
||||
private static final String[] EUREKA_PACKAGES = new String[] { "com.netflix.discovery", "com.netflix.eureka" };
|
||||
|
||||
/**
|
||||
* Static content pattern for dashboard elements (images, css, etc...).
|
||||
*/
|
||||
private static final String STATIC_CONTENT_PATTERN = "/(fonts|images|css|js)/.*";
|
||||
|
||||
@Autowired
|
||||
private ApplicationInfoManager applicationInfoManager;
|
||||
|
||||
@@ -156,8 +113,8 @@ public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true)
|
||||
public EurekaController eurekaController(EurekaProperties eurekaProperties) {
|
||||
return new EurekaController(this.applicationInfoManager, eurekaProperties);
|
||||
public EurekaController eurekaController() {
|
||||
return new EurekaController(this.applicationInfoManager);
|
||||
}
|
||||
|
||||
static {
|
||||
@@ -187,30 +144,9 @@ public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(TransportClientFactories.class)
|
||||
public Jersey3TransportClientFactories jersey3TransportClientFactories() {
|
||||
return Jersey3TransportClientFactories.getInstance();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(EurekaServerHttpClientFactory.class)
|
||||
public Jersey3EurekaServerHttpClientFactory jersey3EurekaServerHttpClientFactory() {
|
||||
return new Jersey3EurekaServerHttpClientFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AbstractDiscoveryClientOptionalArgs.class)
|
||||
public Jersey3DiscoveryClientOptionalArgs jersey3DiscoveryClientOptionalArgs() {
|
||||
return new Jersey3DiscoveryClientOptionalArgs();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PeerAwareInstanceRegistry peerAwareInstanceRegistry(ServerCodecs serverCodecs,
|
||||
EurekaServerHttpClientFactory eurekaServerHttpClientFactory) {
|
||||
public PeerAwareInstanceRegistry peerAwareInstanceRegistry(ServerCodecs serverCodecs) {
|
||||
this.eurekaClient.getApplications(); // force initialization
|
||||
return new InstanceRegistry(this.eurekaServerConfig, this.eurekaClientConfig, serverCodecs, this.eurekaClient,
|
||||
eurekaServerHttpClientFactory,
|
||||
this.instanceRegistryProperties.getExpectedNumberOfClientsSendingRenews(),
|
||||
this.instanceRegistryProperties.getDefaultOpenForTrafficCount());
|
||||
}
|
||||
@@ -244,84 +180,24 @@ public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
|
||||
* @return a jersey {@link FilterRegistrationBean}
|
||||
*/
|
||||
@Bean
|
||||
public FilterRegistrationBean<?> jerseyFilterRegistration(ResourceConfig eurekaJerseyApp) {
|
||||
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
|
||||
ServletContainer servletContainer = new ServletContainer(eurekaJerseyApp);
|
||||
bean.setFilter(servletContainer);
|
||||
public FilterRegistrationBean<?> jerseyFilterRegistration(javax.ws.rs.core.Application eurekaJerseyApp) {
|
||||
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<Filter>();
|
||||
bean.setFilter(new ServletContainer(eurekaJerseyApp));
|
||||
bean.setOrder(Ordered.LOWEST_PRECEDENCE);
|
||||
bean.setUrlPatterns(Collections.singletonList(EurekaConstants.DEFAULT_PREFIX + "/*"));
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<?> eurekaVersionFilterRegistration(ServerProperties serverProperties,
|
||||
Environment env) {
|
||||
final String contextPath = serverProperties.getServlet().getContextPath();
|
||||
String regex = EurekaConstants.DEFAULT_PREFIX + STATIC_CONTENT_PATTERN;
|
||||
if (StringUtils.hasText(contextPath)) {
|
||||
regex = contextPath + regex;
|
||||
}
|
||||
String debugResponseHeader = env.getProperty("eureka.server.version.filter.debug.response-header");
|
||||
boolean addDebugResponseHeader = StringUtils.hasText(debugResponseHeader);
|
||||
Pattern staticPattern = Pattern.compile(regex);
|
||||
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
|
||||
bean.setFilter(new OncePerRequestFilter() {
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
HttpServletRequest req = request;
|
||||
String requestURI = request.getRequestURI();
|
||||
if (!requestURI.startsWith(EurekaConstants.DEFAULT_PREFIX + "/v2")
|
||||
// don't forward static requests (images, js, etc...) to /v2
|
||||
&& !staticPattern.matcher(requestURI).matches()) {
|
||||
|
||||
String prefix = EurekaConstants.DEFAULT_PREFIX;
|
||||
if (StringUtils.hasText(contextPath)) {
|
||||
prefix = contextPath + prefix;
|
||||
}
|
||||
String updatedPath = EurekaConstants.DEFAULT_PREFIX + "/v2" + requestURI.substring(prefix.length());
|
||||
if (StringUtils.hasText(contextPath)) {
|
||||
updatedPath = contextPath + updatedPath;
|
||||
}
|
||||
final String computedPath = updatedPath;
|
||||
// only used if a special debug property is set, so in prod this is
|
||||
// always skipped.
|
||||
if (addDebugResponseHeader) {
|
||||
response.addHeader(debugResponseHeader, computedPath);
|
||||
}
|
||||
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request) {
|
||||
@Override
|
||||
public String getRequestURI() {
|
||||
return computedPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServletPath() {
|
||||
return computedPath;
|
||||
}
|
||||
};
|
||||
req = wrapper;
|
||||
}
|
||||
filterChain.doFilter(req, response);
|
||||
}
|
||||
});
|
||||
bean.setOrder(0);
|
||||
bean.setUrlPatterns(Collections.singletonList(EurekaConstants.DEFAULT_PREFIX + "/*"));
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a Jersey {@link jakarta.ws.rs.core.Application} with all the resources
|
||||
* Construct a Jersey {@link javax.ws.rs.core.Application} with all the resources
|
||||
* required by the Eureka server.
|
||||
* @param environment an {@link Environment} instance to retrieve classpath resources
|
||||
* @param resourceLoader a {@link ResourceLoader} instance to get classloader from
|
||||
* @return created {@link Application} object
|
||||
*/
|
||||
@Bean
|
||||
public ResourceConfig jerseyApplication(Environment environment, ResourceLoader resourceLoader,
|
||||
BeanFactory beanFactory) {
|
||||
public javax.ws.rs.core.Application jerseyApplication(Environment environment, ResourceLoader resourceLoader) {
|
||||
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false,
|
||||
environment);
|
||||
@@ -342,32 +218,15 @@ public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
|
||||
}
|
||||
}
|
||||
|
||||
// https://javaee.github.io/hk2/spring-bridge
|
||||
|
||||
// Construct the Jersey ResourceConfig
|
||||
ResourceConfig rc = new ResourceConfig(classes).property(
|
||||
Map<String, Object> propsAndFeatures = new HashMap<>();
|
||||
propsAndFeatures.put(
|
||||
// Skip static content used by the webapp
|
||||
ServletProperties.FILTER_STATIC_CONTENT_REGEX, EurekaConstants.DEFAULT_PREFIX + STATIC_CONTENT_PATTERN);
|
||||
ServletContainer.PROPERTY_WEB_PAGE_CONTENT_REGEX,
|
||||
EurekaConstants.DEFAULT_PREFIX + "/(fonts|images|css|js)/.*");
|
||||
|
||||
rc.register(new ContainerLifecycleListener() {
|
||||
@Override
|
||||
public void onStartup(Container container) {
|
||||
ServiceLocator serviceLocator = container.getApplicationHandler().getInjectionManager()
|
||||
.getInstance(ServiceLocator.class);
|
||||
SpringBridge.getSpringBridge().initializeSpringBridge(serviceLocator);
|
||||
serviceLocator.getService(SpringIntoHK2Bridge.class).bridgeSpringBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(Container container) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShutdown(Container container) {
|
||||
|
||||
}
|
||||
});
|
||||
DefaultResourceConfig rc = new DefaultResourceConfig(classes);
|
||||
rc.setPropertiesAndFeatures(propsAndFeatures);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -375,7 +234,7 @@ public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
|
||||
@Bean
|
||||
@ConditionalOnBean(name = "httpTraceFilter")
|
||||
public FilterRegistrationBean<?> traceFilterRegistration(@Qualifier("httpTraceFilter") Filter filter) {
|
||||
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
|
||||
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<Filter>();
|
||||
bean.setFilter(filter);
|
||||
bean.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
|
||||
return bean;
|
||||
@@ -412,7 +271,7 @@ public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
|
||||
static class RefreshablePeerEurekaNodes extends PeerEurekaNodes
|
||||
implements ApplicationListener<EnvironmentChangeEvent> {
|
||||
|
||||
/* for testing */ ReplicationClientAdditionalFilters replicationClientAdditionalFilters;
|
||||
private ReplicationClientAdditionalFilters replicationClientAdditionalFilters;
|
||||
|
||||
RefreshablePeerEurekaNodes(final PeerAwareInstanceRegistry registry, final EurekaServerConfig serverConfig,
|
||||
final EurekaClientConfig clientConfig, final ServerCodecs serverCodecs,
|
||||
@@ -424,8 +283,10 @@ public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
protected PeerEurekaNode createPeerEurekaNode(String peerEurekaNodeUrl) {
|
||||
Jersey3ReplicationClient replicationClient = createReplicationClient(serverConfig, serverCodecs,
|
||||
peerEurekaNodeUrl, this.replicationClientAdditionalFilters.getFilters());
|
||||
JerseyReplicationClient replicationClient = JerseyReplicationClient.createReplicationClient(serverConfig,
|
||||
serverCodecs, peerEurekaNodeUrl);
|
||||
|
||||
this.replicationClientAdditionalFilters.getFilters().forEach(replicationClient::addReplicationClientFilter);
|
||||
|
||||
String targetHost = hostFromUrl(peerEurekaNodeUrl);
|
||||
if (targetHost == null) {
|
||||
@@ -434,64 +295,6 @@ public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
|
||||
return new PeerEurekaNode(registry, targetHost, peerEurekaNodeUrl, replicationClient, serverConfig);
|
||||
}
|
||||
|
||||
// FIXME: 4.0 update Jersey3ReplicationClient.createReplicationClient to handle
|
||||
// additional filters
|
||||
private static Jersey3ReplicationClient createReplicationClient(EurekaServerConfig config,
|
||||
ServerCodecs serverCodecs, String serviceUrl, Collection<ClientRequestFilter> additionalFilters) {
|
||||
String name = Jersey3ReplicationClient.class.getSimpleName() + ": " + serviceUrl + "apps/: ";
|
||||
|
||||
EurekaJersey3Client jerseyClient;
|
||||
try {
|
||||
String hostname;
|
||||
try {
|
||||
hostname = new URL(serviceUrl).getHost();
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
hostname = serviceUrl;
|
||||
}
|
||||
|
||||
String jerseyClientName = "Discovery-PeerNodeClient-" + hostname;
|
||||
EurekaJersey3ClientImpl.EurekaJersey3ClientBuilder clientBuilder = new EurekaJersey3ClientImpl.EurekaJersey3ClientBuilder()
|
||||
.withClientName(jerseyClientName).withUserAgent("Java-EurekaClient-Replication")
|
||||
.withEncoderWrapper(serverCodecs.getFullJsonCodec())
|
||||
.withDecoderWrapper(serverCodecs.getFullJsonCodec())
|
||||
.withConnectionTimeout(config.getPeerNodeConnectTimeoutMs())
|
||||
.withReadTimeout(config.getPeerNodeReadTimeoutMs())
|
||||
.withMaxConnectionsPerHost(config.getPeerNodeTotalConnectionsPerHost())
|
||||
.withMaxTotalConnections(config.getPeerNodeTotalConnections())
|
||||
.withConnectionIdleTimeout(config.getPeerNodeConnectionIdleTimeoutSeconds());
|
||||
|
||||
if (serviceUrl.startsWith("https://") && "true"
|
||||
.equals(System.getProperty("com.netflix.eureka.shouldSSLConnectionsUseSystemSocketFactory"))) {
|
||||
clientBuilder.withSystemSSLConfiguration();
|
||||
}
|
||||
jerseyClient = clientBuilder.build();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
throw new RuntimeException("Cannot Create new Replica Node :" + name, e);
|
||||
}
|
||||
|
||||
String ip = null;
|
||||
try {
|
||||
ip = InetAddress.getLocalHost().getHostAddress();
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
log.warn("Cannot find localhost ip", e);
|
||||
}
|
||||
|
||||
Client jerseyApacheClient = jerseyClient.getClient();
|
||||
jerseyApacheClient.register(new Jersey3DynamicGZIPContentEncodingFilter(config));
|
||||
|
||||
for (ClientRequestFilter filter : additionalFilters) {
|
||||
jerseyApacheClient.register(filter);
|
||||
}
|
||||
|
||||
EurekaServerIdentity identity = new EurekaServerIdentity(ip);
|
||||
jerseyApacheClient.register(new EurekaIdentityHeaderFilter(identity));
|
||||
|
||||
return new Jersey3ReplicationClient(jerseyClient, serviceUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(final EnvironmentChangeEvent event) {
|
||||
if (shouldUpdate(event.getKeys())) {
|
||||
|
||||
+8
-2
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.server;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import com.netflix.appinfo.ApplicationInfoManager;
|
||||
import com.netflix.appinfo.DataCenterInfo;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
@@ -31,13 +33,11 @@ import com.netflix.eureka.aws.AwsBinderDelegate;
|
||||
import com.netflix.eureka.registry.PeerAwareInstanceRegistry;
|
||||
import com.netflix.eureka.util.EurekaMonitors;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Weix Sun
|
||||
*/
|
||||
public class EurekaServerBootstrap {
|
||||
|
||||
@@ -67,6 +67,7 @@ public class EurekaServerBootstrap {
|
||||
|
||||
public void contextInitialized(ServletContext context) {
|
||||
try {
|
||||
initEurekaEnvironment();
|
||||
initEurekaServerContext();
|
||||
|
||||
context.setAttribute(EurekaServerContext.class.getName(), this.serverContext);
|
||||
@@ -92,6 +93,11 @@ public class EurekaServerBootstrap {
|
||||
log.info("Eureka Service is now shutdown...");
|
||||
}
|
||||
|
||||
protected void initEurekaEnvironment() throws Exception {
|
||||
log.info("Setting the eureka configuration..");
|
||||
|
||||
}
|
||||
|
||||
protected void initEurekaServerContext() throws Exception {
|
||||
// For backward compatibility
|
||||
JsonXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), XStream.PRIORITY_VERY_HIGH);
|
||||
|
||||
+5
-5
@@ -1049,11 +1049,11 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
|
||||
registrySyncRetryWaitMs, remoteRegionAppWhitelist, remoteRegionConnectTimeoutMs,
|
||||
remoteRegionConnectionIdleTimeoutSeconds, remoteRegionFetchThreadPoolSize, remoteRegionReadTimeoutMs,
|
||||
remoteRegionRegistryFetchInterval, remoteRegionTotalConnections, remoteRegionTotalConnectionsPerHost,
|
||||
remoteRegionTrustStore, remoteRegionTrustStorePassword, Arrays.hashCode(remoteRegionUrls),
|
||||
remoteRegionUrlsWithName, renewalPercentThreshold, renewalThresholdUpdateIntervalMs,
|
||||
responseCacheAutoExpirationInSeconds, responseCacheUpdateIntervalMs, retentionTimeInMSInDeltaQueue,
|
||||
route53BindRebindRetries, route53BindingRetryIntervalMs, route53DomainTTL, syncWhenTimestampDiffers,
|
||||
useReadOnlyResponseCache, waitTimeInMsWhenSyncEmpty, xmlCodecName, initialCapacityOfResponseCache,
|
||||
remoteRegionTrustStore, remoteRegionTrustStorePassword, remoteRegionUrls, remoteRegionUrlsWithName,
|
||||
renewalPercentThreshold, renewalThresholdUpdateIntervalMs, responseCacheAutoExpirationInSeconds,
|
||||
responseCacheUpdateIntervalMs, retentionTimeInMSInDeltaQueue, route53BindRebindRetries,
|
||||
route53BindingRetryIntervalMs, route53DomainTTL, syncWhenTimestampDiffers, useReadOnlyResponseCache,
|
||||
waitTimeInMsWhenSyncEmpty, xmlCodecName, initialCapacityOfResponseCache,
|
||||
expectedClientRenewalIntervalSeconds, useAwsAsgApi, myUrl);
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -16,8 +16,9 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.server;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import com.netflix.eureka.EurekaServerConfig;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -52,7 +53,7 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware
|
||||
|
||||
private boolean running;
|
||||
|
||||
private final int order = 1;
|
||||
private int order = 1;
|
||||
|
||||
@Override
|
||||
public void setServletContext(ServletContext servletContext) {
|
||||
|
||||
+3
-5
@@ -25,7 +25,6 @@ import com.netflix.eureka.EurekaServerConfig;
|
||||
import com.netflix.eureka.lease.Lease;
|
||||
import com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl;
|
||||
import com.netflix.eureka.resources.ServerCodecs;
|
||||
import com.netflix.eureka.transport.EurekaServerHttpClientFactory;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -46,12 +45,11 @@ public class InstanceRegistry extends PeerAwareInstanceRegistryImpl implements A
|
||||
|
||||
private ApplicationContext ctxt;
|
||||
|
||||
private final int defaultOpenForTrafficCount;
|
||||
private int defaultOpenForTrafficCount;
|
||||
|
||||
public InstanceRegistry(EurekaServerConfig serverConfig, EurekaClientConfig clientConfig, ServerCodecs serverCodecs,
|
||||
EurekaClient eurekaClient, EurekaServerHttpClientFactory eurekaServerHttpClientFactory,
|
||||
int expectedNumberOfClientsSendingRenews, int defaultOpenForTrafficCount) {
|
||||
super(serverConfig, clientConfig, serverCodecs, eurekaClient, eurekaServerHttpClientFactory);
|
||||
EurekaClient eurekaClient, int expectedNumberOfClientsSendingRenews, int defaultOpenForTrafficCount) {
|
||||
super(serverConfig, clientConfig, serverCodecs, eurekaClient);
|
||||
|
||||
this.expectedNumberOfClientsSendingRenews = expectedNumberOfClientsSendingRenews;
|
||||
this.defaultOpenForTrafficCount = defaultOpenForTrafficCount;
|
||||
|
||||
+4
-4
@@ -19,20 +19,20 @@ package org.springframework.cloud.netflix.eureka.server;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
import jakarta.ws.rs.client.ClientRequestFilter;
|
||||
import com.sun.jersey.api.client.filter.ClientFilter;
|
||||
|
||||
/**
|
||||
* @author Yuxin Bai
|
||||
*/
|
||||
public class ReplicationClientAdditionalFilters {
|
||||
|
||||
private final Collection<ClientRequestFilter> filters;
|
||||
private Collection<ClientFilter> filters;
|
||||
|
||||
public ReplicationClientAdditionalFilters(Collection<ClientRequestFilter> filters) {
|
||||
public ReplicationClientAdditionalFilters(Collection<ClientFilter> filters) {
|
||||
this.filters = new LinkedHashSet<>(filters);
|
||||
}
|
||||
|
||||
public Collection<ClientRequestFilter> getFilters() {
|
||||
public Collection<ClientFilter> getFilters() {
|
||||
return this.filters;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration
|
||||
-1
@@ -1 +0,0 @@
|
||||
org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration
|
||||
+16
-11
@@ -1,17 +1,22 @@
|
||||
<#import "/spring.ftl" as spring />
|
||||
<nav class="navbar navbar-expand-md navbar-dark" role="navigation">
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container">
|
||||
<a class="navbar-brand my-auto" href="<@spring.url dashboardPath/>"><span></span></a>
|
||||
<button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#navbarContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarContent">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2" href="<@spring.url dashboardPath/>">Home</a>
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="<@spring.url dashboardPath/>"><span></span></a>
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li>
|
||||
<a href="<@spring.url dashboardPath/>">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2" href="<@spring.url dashboardPath/>/lastn">Last 1000 since startup</a>
|
||||
<li>
|
||||
<a href="<@spring.url dashboardPath/>/lastn">Last 1000 since startup</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
<#import "/spring.ftl" as spring />
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
|
||||
<head>
|
||||
<base href="<@spring.url basePath/>">
|
||||
<title>Eureka - Last N events</title>
|
||||
<link rel="stylesheet" type="text/css" href="eureka/css/wro.css">
|
||||
</head>
|
||||
<body id="three">
|
||||
<script type="text/javascript">
|
||||
if ( document.documentMode ) {
|
||||
document.write('<p>You are using an <strong>outdated</strong> browser. Please upgrade your browser to improve your experience.</p>');
|
||||
}
|
||||
</script>
|
||||
|
||||
<!--[if lt IE 7]>
|
||||
<p>You are using an <strong>outdated</strong> browser. Please upgrade your browser to improve your experience.</p>
|
||||
<![endif]-->
|
||||
|
||||
<#include "header.ftlh">
|
||||
|
||||
<div class="container-fluid xd-container">
|
||||
<#include "navbar.ftlh">
|
||||
|
||||
<div id="xd-jobs" class="tab-pane col-md-12">
|
||||
<div id="xd-jobs" class="tab-pane active col-md-12">
|
||||
<ul class="nav nav-tabs" role="tablist" id="myTab">
|
||||
<li class="nav-item"><a href="<@spring.url dashboardPath/>/lastn#cancelled" class="nav-link p-2" data-bs-toggle="tab">Last 1000 cancelled leases</a></li>
|
||||
<li class="nav-item"><a href="<@spring.url dashboardPath/>/lastn#registered" class="nav-link p-2 active" data-bs-toggle="tab">Last 1000 newly registered leases</a></li>
|
||||
<li class="active"><a data-toggle="tab" href="#cancelled">Last 1000 cancelled leases</a></li>
|
||||
<li><a data-toggle="tab" href="#registered">Last 1000 newly registered leases</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane" id="cancelled">
|
||||
@@ -40,7 +42,7 @@
|
||||
<tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="tab-pane active" id="registered">
|
||||
<div class="tab-pane" id="registered">
|
||||
<table id='lastNRegistered' class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr><th>Timestamp</th><th>Lease</th></tr>
|
||||
@@ -60,5 +62,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="eureka/js/wro.js" ></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
$('#myTab a:last').tab('show')
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
</#if>
|
||||
|
||||
<h1>DS Replicas</h1>
|
||||
<ul class="list-group mb-3">
|
||||
<ul class="list-group">
|
||||
<#list replicas as replica>
|
||||
<li class="list-group-item"><a href="${replica.value}">${replica.key}</a></li>
|
||||
</#list>
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<#import "/spring.ftl" as spring />
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
|
||||
<head>
|
||||
<base href="<@spring.url basePath/>">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Eureka</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
@@ -13,12 +17,6 @@
|
||||
</head>
|
||||
|
||||
<body id="one">
|
||||
<script type="text/javascript">
|
||||
if ( document.documentMode ) {
|
||||
document.write('<p>You are using an <strong>outdated</strong> browser. Please upgrade your browser to improve your experience.</p>');
|
||||
}
|
||||
</script>
|
||||
|
||||
<#include "header.ftlh">
|
||||
<div class="container-fluid xd-container">
|
||||
<#include "navbar.ftlh">
|
||||
@@ -105,5 +103,11 @@
|
||||
</table>
|
||||
</div>
|
||||
<script type="text/javascript" src="eureka/js/wro.js" ></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('table.stripeable tr:odd').addClass('odd');
|
||||
$('table.stripeable tr:even').addClass('even');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
.navbar {
|
||||
border-top: 4px solid #6db33f;
|
||||
background-color: #34302d;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-bottom: 0px;
|
||||
border-bottom: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
@@ -22,35 +21,63 @@
|
||||
height: 46px;
|
||||
background: url("../images/spring-logo-eureka.png") -1px -48px no-repeat;
|
||||
opacity: 0;
|
||||
transition: opacity 0.12s ease-in-out;
|
||||
-moz-transition: opacity 0.12s ease-in-out;
|
||||
-webkit-transition: opacity 0.12s ease-in-out;
|
||||
-o-transition: opacity 0.12s ease-in-out;
|
||||
}
|
||||
.navbar a:hover.navbar-brand span {
|
||||
opacity: 1;
|
||||
color: #eeeeee;
|
||||
background-color: #6db33f;
|
||||
}
|
||||
.nav-link, .navbar-text {
|
||||
color: #34302d;
|
||||
.navbar li > a, .navbar-text {
|
||||
color: #f1f1f1;
|
||||
font-family: "montserratregular", sans-serif;
|
||||
text-shadow: none;
|
||||
font-size: 14px;
|
||||
padding: 28px 20px;
|
||||
transition: all 0.15s;
|
||||
-moz-transition: all 0.15s;
|
||||
-webkit-transition: all 0.15s;
|
||||
-moz-transition: all 0.15s;
|
||||
-o-transition: all 0.15s;
|
||||
-ms-transition: all 0.15s;
|
||||
}
|
||||
.navbar .nav-link:link {
|
||||
color: #f1f1f1;
|
||||
.navbar li > a {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.navbar .nav-item .nav-link:hover {
|
||||
color: #f1f1f1;
|
||||
.navbar .navbar-text {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.navbar li:hover > a {
|
||||
color: #eeeeee;
|
||||
background-color: #6db33f;
|
||||
}
|
||||
.navbar-toggler {
|
||||
color: #f1f1f1;
|
||||
.navbar-toggle {
|
||||
border-width: 0;
|
||||
}
|
||||
table {
|
||||
.navbar-toggle .icon-bar + .icon-bar {
|
||||
margin-top: 3px;
|
||||
}
|
||||
.navbar-toggle .icon-bar {
|
||||
width: 19px;
|
||||
height: 3px;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.navbar-default-toggle:hover .icon-bar {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.navbar-default a:active{
|
||||
background-color: #6db33f;
|
||||
}
|
||||
|
||||
.nav-tabs:active a:hover{
|
||||
color: #f1f1f1;
|
||||
background-color: #34302D;
|
||||
border-color: #34302D;
|
||||
}
|
||||
|
||||
table{
|
||||
border-color: #34302D;
|
||||
}
|
||||
@@ -2,10 +2,10 @@
|
||||
@import "header.css";
|
||||
@import "responsive.css";
|
||||
|
||||
a:link {
|
||||
a:link{
|
||||
color: #5fa134;
|
||||
}
|
||||
a:hover {
|
||||
a:hover{
|
||||
color: #5fa134;
|
||||
}
|
||||
body {
|
||||
@@ -19,14 +19,9 @@ body {
|
||||
background-color: #34302D;
|
||||
padding: 9px 12px;
|
||||
}
|
||||
.nav-tabs .nav-link {
|
||||
.nav > li > a {
|
||||
color: #838789;
|
||||
}
|
||||
.nav-tabs .nav-link.active, .nav-tabs .nav-link.active:hover {
|
||||
color: #f1f1f1;
|
||||
background-color: #34302D;
|
||||
border-color: #34302D;
|
||||
}
|
||||
.btn-default {
|
||||
border-width: 2px;
|
||||
transition: border 0.15s;
|
||||
@@ -100,3 +95,4 @@ table td.action-column {
|
||||
.help-block {
|
||||
color: #f1f1f1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
@media (max-width: 768px) {
|
||||
.navbar-toggle {
|
||||
position: absolute;
|
||||
z-index: 9999;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
.navbar a.navbar-brand {
|
||||
display: block;
|
||||
margin: 0 auto 0 auto;
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
float: none;
|
||||
background: url("../images/spring-logo-eureka-mobile.png") 0 center no-repeat;
|
||||
}
|
||||
.homepage-billboard .homepage-subtitle {
|
||||
|
||||
+2
-5
@@ -26,7 +26,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.cloud.netflix.eureka.server.ApplicationContextTests.Application;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpEntity;
|
||||
@@ -40,8 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT,
|
||||
properties = { "spring.application.name=eureka", "server.servlet.context-path=/context",
|
||||
"management.security.enabled=false", "management.endpoints.web.exposure.include=*",
|
||||
"eureka.server.version.filter.debug.response-header=X-Version-Filter-Computed-Path" })
|
||||
"management.security.enabled=false", "management.endpoints.web.exposure.include=*" })
|
||||
class ApplicationContextTests {
|
||||
|
||||
private static final String BASE_PATH = new WebEndpointProperties().getBasePath();
|
||||
@@ -55,8 +54,6 @@ class ApplicationContextTests {
|
||||
ResponseEntity<Map> entity = new TestRestTemplate()
|
||||
.getForEntity("http://localhost:" + this.port + "/context/eureka/apps", Map.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
String computedPath = entity.getHeaders().getFirst("X-Version-Filter-Computed-Path");
|
||||
assertThat(computedPath).isEqualTo("/context/eureka/v2/apps");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+2
-2
@@ -57,9 +57,9 @@ class ApplicationDashboardPathTests {
|
||||
// The "DS Replicas"
|
||||
assertThat(body.contains("<h1>Instances currently registered with Eureka</h1>")).isTrue();
|
||||
// The Home
|
||||
assertThat(body.contains("<a class=\"nav-link px-2\" href=\"/dashboard\">Home</a>")).isTrue();
|
||||
assertThat(body.contains("<a href=\"/dashboard\">Home</a>")).isTrue();
|
||||
// The Lastn
|
||||
assertThat(body.contains("<a class=\"nav-link px-2\" href=\"/dashboard/lastn\">Last")).isTrue();
|
||||
assertThat(body.contains("<a href=\"/dashboard/lastn\">Last")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointPr
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.cloud.netflix.eureka.server.ApplicationServletPathTests.Application;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpEntity;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user