Compare commits

..
Author SHA1 Message Date
buildmaster 993f04a6c7 Update SNAPSHOT to 2.2.9.RELEASE 2021-07-06 14:36:22 +00:00
Chintan Radia e394c1227b Fix transfer encoding is set to chunked by settin entity contentLength to 0 for DELETE requests (#4002) 2021-06-15 11:10:51 +02:00
Alexander Kogut c1afe1d2a0 Handle special characters in TraceProxyRequestHelper (#3995) 2021-06-10 14:23:13 +02:00
Olga Maciaszek-Sharma 89c37a3842 Handle stopping instance (#3999)
* Fix for #1571

See https://github.com/spring-cloud/spring-cloud-netflix/issues/1571#issuecomment-351638405 for more information about the rational behind the changes.

Original contributor: Bertrand Renuart <bertrand.renuart@itma.lu>
2021-05-24 19:08:25 +02:00
Jay Bryant 17e72988dc Cherry pick 8ad6682836 2021-05-24 17:11:51 +02:00
Olga MaciaszekSharma 849f1e7e99 Fix doc. 2021-05-24 17:06:38 +02:00
Olga MaciaszekSharma 3f4c702aa5 Upgrade bcpkix to 1.68. 2021-05-24 14:04:51 +02:00
spencergibb 1bd64613d1 updates eureka to 1.10.14
Fixes gh-3994
2021-05-21 16:15:50 -04:00
Olga MaciaszekSharma 86101cd733 Switch from main to master. 2021-04-26 19:12:59 +02:00
Olga MaciaszekSharma a5734695b7 Revert "Switch to GH actions."
This reverts commit e839d1dfbd.
2021-04-26 19:05:25 +02:00
Olga MaciaszekSharma 14c7ac2dda Fix README generation.
# Conflicts:
#	docs/README.adoc
2021-04-26 19:00:10 +02:00
Olga MaciaszekSharma e839d1dfbd Switch to GH actions. 2021-04-26 18:44:52 +02:00
buildmaster c5268f0d89 Bumping versions to 2.2.9.BUILD-SNAPSHOT after release 2021-04-21 16:01:59 +00:00
buildmaster 2b33f7a8b6 Going back to snapshots 2021-04-21 16:01:59 +00:00
buildmaster 848bfab4ee Update SNAPSHOT to 2.2.8.RELEASE 2021-04-21 15:51:58 +00:00
buildmaster 4646484a30 Bumping versions 2021-04-20 21:20:11 +00:00
Olga MaciaszekSharma 6f1332ee72 Reformat. 2021-04-20 17:23:37 +02:00
Olga Maciaszek-Sharma bff9419201 Do not load RibbonAutoConfiguration when spring.cloud.loadbalancer.ribbon.enabled is false. (#3977) 2021-03-05 16:08:15 +01:00
Olga Maciaszek-Sharma 7b90195ee8 Upgrade SC Contract version in Hystrix-Contract. 2021-02-18 16:51:43 +01:00
Felipe Adorno df7ecf81c9 get timeout from property source (#3965)
I try solve the problem getting values from environment, if have any other way to do that please ping me.

Fixes #3786
2021-02-17 17:38:43 -05:00
buildmaster f2526d5e03 Bumping versions to 2.2.8.BUILD-SNAPSHOT after release 2021-02-11 14:05:01 +00:00
buildmaster 8e00d28bcc Going back to snapshots 2021-02-11 14:05:00 +00:00
buildmaster 92cb1a7aa0 Update SNAPSHOT to 2.2.7.RELEASE 2021-02-11 14:01:40 +00:00
Olga Maciaszek-Sharma 8ecb3dca51 Fix request verification (#3969)
* Add tests reproducing the issue.

* Strip `'` from path for route search.

* Add information on contributing, community support and commercial support to project site.

* Add checking for "#". Add logging.

* Add test.

* Revert "Add test."

This reverts commit 81875849

* Revert "Add checking for "#". Add logging."

This reverts commit 0232945a

* Verify for urls.

* Verify for encoded and double-encoded Strings.

* Verify insecure paths with `..\` and '..//'. Add more tests.
2021-02-11 11:58:55 +01:00
Olga Maciaszek-Sharma df64a02013 Use org security policy. 2021-01-22 10:15:20 +01:00
Olga Maciaszek-Sharma 74f7c0eefd Add information on contributing, community support and commercial support to project site. 2021-01-18 11:07:00 +01:00
spencergibb 4978f8f7de No longer manage xstream dependency version.
xstream is managed as a compile dependency eureka-client now, Spring Cloud Netflix no longer needs to manage it.

See #3955
2021-01-14 12:23:05 -05:00
Theo Sun 0b490f6d27 bump versions (#3955) 2021-01-14 11:51:19 -05:00
Olga Maciaszek-Sharma c6141c5b15 Add license link to the docs. 2021-01-14 16:03:01 +01:00
hrksingh 992269781a Update EurekaInstanceConfigBean.java (#3937)
Updated spelling mistake in Javadoc  from prference to preference

(cherry picked from commit 1d6a5876fb)
2021-01-11 15:42:35 +01:00
Olga Maciaszek-Sharma 4ec5556420 Upgrade xstream to 1.4.14. 2020-12-01 18:58:40 +01:00
Olga Maciaszek-Sharma 2fe021fbdb Switch to server.servlet.encoding.force. Fixes gh-3895. 2020-12-01 18:46:38 +01:00
Olga Maciaszek-Sharma a452c1d8e9 Upgrade Eureka to 1.10.10. 2020-12-01 18:33:49 +01:00
Olga Maciaszek-Sharma 3bf50f3ef5 Upgrade bcpkix-jdk15on. 2020-12-01 18:21:50 +01:00
buildmaster ab17bbfee2 Bumping versions to 2.2.7.BUILD-SNAPSHOT after release 2020-11-09 10:28:44 +00:00
buildmaster 7240308834 Going back to snapshots 2020-11-09 10:28:44 +00:00
buildmaster 53c5b4ba86 Update SNAPSHOT to 2.2.6.RELEASE 2020-11-09 10:24:42 +00:00
spencergibb ce82ea3b71 Updates equals() for events.
Fixes gh-3918
2020-11-02 12:57:46 -05:00
Olga Maciaszek-Sharma 08add768d0 Bump mockito-core to 3.6.0. 2020-10-30 17:14:44 +01:00
Olga Maciaszek-Sharma 4064646b39 Bump eureka to 1.10.7. 2020-10-30 16:53:31 +01:00
Olga Maciaszek-Sharma ce73a587f5 Handle nulls. Minor refactoring. 2020-10-30 16:08:24 +01:00
joyita07 78ca251e96 Added support for ReactiveHealthIndicator. (#3903) 2020-10-30 14:36:13 +01:00
Olga Maciaszek-Sharma 6ce8123be1 Upgrade eureka to 1.10.4. 2020-10-06 20:32:08 +02:00
Olga Maciaszek-Sharma d11f91cdb1 Upgrade mockito-core to 3.5.13. 2020-10-06 20:06:08 +02:00
Olga Maciaszek-Sharma 57053ed7eb Upgrade xstream to 1.4.13. 2020-10-06 19:46:21 +02:00
Olga Maciaszek-Sharma 0297304397 Upgrade bcpkix-jdk15on to 1.66. 2020-10-06 19:23:15 +02:00
Olga Maciaszek-Sharma 4bdb799c8c Revert "Upgrade wro4j to 1.9.0."
This reverts commit 6e70f55049.
2020-10-06 18:36:18 +02:00
Olga Maciaszek-Sharma 6e70f55049 Upgrade wro4j to 1.9.0. 2020-10-06 18:13:48 +02:00
Olga Maciaszek-Sharma be57fe3d8b Upgrade jquery to 3.5.1. 2020-10-06 18:03:38 +02:00
Olga Maciaszek-Sharma 931cca4f44 Upgrade eureka-jersey to 1.19.4. 2020-10-06 17:43:46 +02:00
Olga Maciaszek-Sharma 0d7c73c583 Set errexit output (#3894) 2020-09-22 14:48:02 +02:00
spencergibb d498a6e091 Updates spring-cloud-contract to 2.2.4.RELEASE 2020-09-01 19:15:25 -04:00
buildmaster 34ede67962 Bumping versions to 2.2.6.BUILD-SNAPSHOT after release 2020-08-28 19:53:11 +00:00
buildmaster 24e842cfdd Going back to snapshots 2020-08-28 19:53:10 +00:00
buildmaster a1a9d8c599 Update SNAPSHOT to 2.2.5.RELEASE 2020-08-28 19:46:50 +00:00
Haytham Mohamed c5e8b66368 upgrade jquery from version 3.4.1 to 3.5.1 fixes gh-3843 (#3854)
fixes gh-3843
2020-08-28 12:37:40 -04:00
Ryan Baxter 88985f33af Merge branch 'jialindai-2.2.x' into 2.2.x 2020-08-24 16:12:25 -04:00
Ryan Baxter eeaeeb3e6f Code review changes 2020-08-24 16:11:59 -04:00
JiaLin a3436d08eb Use common TLS classes 2020-08-23 15:53:14 +08:00
JiaLin 5f3f35fd68 merge changes from upstream 2020-08-19 00:20:44 +08:00
spencergibb 23d15f70bc Updates s-c-build to 2.3.2.BUILD-SNAPSHOT 2020-08-03 13:00:36 -04:00
JiaLin 072418826e Update spring-cloud-netflix.adoc 2020-08-01 22:19:48 +08:00
JiaLin cbc914259b add client side TLS support 2020-08-01 21:55:32 +08:00
buildmaster 896b33c109 Bumping versions to 2.2.5.BUILD-SNAPSHOT after release 2020-07-31 20:37:36 +00:00
buildmaster a826a960e6 Going back to snapshots 2020-07-31 20:37:36 +00:00
buildmaster a579eb4594 Update SNAPSHOT to 2.2.4.RELEASE 2020-07-31 20:33:25 +00:00
Ryan Baxter 624bbc8b50 add allow list for proxy.stream endpoint 2020-07-30 15:15:09 -04:00
Samuel Renier 4de8761123 Updates eureka.version to 1.9.25
fixes gh-3839
2020-07-28 16:09:29 -04:00
spencergibb 8d5a3f8ec1 Updates WebClientEurekaHttpClient to use auto configured WebClient.
This allows it to take advantage of settings that are auto-configured such as spring.codec.*.

Fixes gh-3819
2020-07-28 15:57:51 -04:00
spencergibb f6120d525f Adds test to verify on("load",
See gh-3817
2020-07-28 15:29:07 -04:00
MadeInChina 4bf57b9cd2 Fix spring-cloud-starter-hystrix-dashboard jquery3.4.1 usage error (#3816) (#3817) 2020-07-28 15:21:19 -04:00
spencergibb 3bd44d69ca Updates to include dns discovery for config server bootstrap.
Fixes gh-3827
2020-07-22 18:20:03 -04:00
Rafael Renan Pacheco 6506e03bcf Adds missing eureka.client.enabled property condition
Fixes gh-3814
Fixes gh-3823
2020-06-17 17:07:32 -04:00
slamhan 443628827e Deduplicates context path in health-check-url
fixes gh-3809
2020-06-17 16:33:08 -04:00
spencergibb 85261361d7 Makes WebClient opt in in eureka config server bootstrap.
Fixes gh-3822
2020-06-17 13:09:39 -04:00
Marcin Grzejszczak 34a07a15e2 Migrated to docs.spring.io & updated sc-build 2020-06-04 15:45:36 +02:00
buildmaster 21b8599be5 Bumping versions to 2.2.4.BUILD-SNAPSHOT after release 2020-05-28 17:39:17 +00:00
buildmaster a8539b33db Going back to snapshots 2020-05-28 17:39:17 +00:00
buildmaster 5d983b082e Update SNAPSHOT to 2.2.3.RELEASE 2020-05-28 17:34:08 +00:00
spencergibb e556ccc7ed Moves DiscoveryClientOptionalArgsConfiguration to auto-configuration.
Throws an error if eureka.client.webclient.enabled is true and webflux is not on the classpath.
2020-05-15 18:24:49 -04:00
spencergibb 529b7ae12a Uses RestTemplateEurekaHttpClient if webflux not on classpath
See gh-3795
2020-05-15 11:11:38 -04:00
spencergibb a18479da64 Ignores .sdkmanrc 2020-05-15 11:10:39 -04:00
Spencer Gibb 8d19948f4b Uses http to look up config server from eureka (#3796)
This eliminates the oddness of having multiple discovery client beans and related behavior and simplifies bootstrap significantly.

Moves to ConfigServerInstanceProvider.Function for config client bootstrap.

Removes conditions for dealing with DiscoverClient in parent context.

Updates tests to reflect the new reality of no DiscoveryClient in bootstrap.

Renames config bootstrap to EurekaConfigServerBootstrapConfiguration

Fixes gh-3795

See https://github.com/spring-cloud/spring-cloud-gateway/issues/1514
2020-05-14 15:04:30 -04:00
Spencer Gibb 182951a0d5 Updates to eureka v1.9.21
fixes gh-3787
2020-05-01 10:46:10 -04:00
Olga Maciaszek-Sharma 0783016676 Fix failing checkstyle. 2020-04-23 16:49:09 +02:00
Olga Maciaszek-Sharma c36743de83 Update license comments. 2020-04-23 14:59:09 +02:00
Haytham Mohamed 297f8950b1 Merge pull request #3779 from Haybu/enh-2.2.x/issue-3737
Adds opt-in webclient support for eureka client
2020-04-22 14:31:23 -05:00
Haytham Mohamed 849642ff84 define eureka.client.webclient.enabled in the manual properties metadata json file 2020-04-20 15:41:53 -05:00
Haytham Mohamed dff3b91bef ready for submission 2020-04-17 02:10:31 -05:00
Haytham Mohamed 7db58f7d16 update tests 2020-04-17 01:43:03 -05:00
Haytham Mohamed e820a484d6 add WebClient as opt-in option 2020-04-16 23:44:32 -05:00
XiaoZiShan 2afba0977f 😀typo I found reading zuul source code (#3776)
a little excited but seeing the current module into the maintenance phase and not knowing if it will be merged, I would like to be involved in the spring community to contribute.
2020-04-15 20:25:46 +02:00
Olga Maciaszek-Sharma 61d2f956e3 Remove superfluous directive. Fixes gh-3756. 2020-04-14 21:38:46 +02:00
Olga Maciaszek-Sharma 17b9002fef Upgrade jQuery. Fixes gh-3773. 2020-04-10 17:35:43 +02:00
Eduard Wirch d6f375490a Fix circular dependency in ZuulProxyAutoConfiguration (#3769)
ZuulProxyAutoConfiguration declared a ServiceRouteMapper bean and required it for a field injection at the same time.

Fixes gh-3733
2020-04-07 15:20:07 -04:00
Spencer Gibb bee39ec1bf Updates eureka to 1.9.19
fixes gh-3770
2020-04-07 15:19:33 -04:00
Spencer Gibb 0dc755518c Adds maintenance mode info for concurrency-limits module.
see gh-3767
2020-04-07 11:46:48 -04:00
Spencer Gibb ad3f2cb53a Deprecates concurrency-limits module.
fixes gh-3767
2020-04-07 11:31:44 -04:00
Spencer Gibb 74f9fd4f9d bumps build to 2.3.0.BUILD-SNAPSHOT 2020-03-19 10:59:24 -04:00
Spencer Gibb c69a3eed70 Makes springClientFactory conditional on missing bean 2020-03-18 18:20:38 -04:00
Spencer Gibb 0c12ec9132 Adds validation starter 2020-03-18 18:05:38 -04:00
Spencer Gibb 2f6f0a0f05 Fixes assertion to use valid class 2020-03-18 18:03:21 -04:00
Spencer Gibb c0174be906 bumps build to 2.2.4.BUILD-SNAPSHOT 2020-03-18 18:00:49 -04:00
Spencer Gibb 7e96ed15f2 Updates docs branches 2020-03-06 12:42:52 -05:00
Spencer Gibb 1b07143fde Removes management of spring-cloud-netflix-hystrix-contract
spring-cloud-netflix-hystrix-contract is not a published artifact and can make validating the bom more complicated than needed.

Fixes gh-3740
2020-03-04 17:46:57 -05:00
buildmaster ea31d78891 Bumping versions to 2.2.3.BUILD-SNAPSHOT after release 2020-03-04 16:14:34 +00:00
buildmaster 492731632c Going back to snapshots 2020-03-04 16:14:33 +00:00
buildmaster 551fecde83 Update SNAPSHOT to 2.2.2.RELEASE 2020-03-04 16:05:27 +00:00
Spencer Gibb aed8d19aea Updates contract version to 2.2.1.RELEASE 2020-02-04 18:23:35 -05:00
Olga Maciaszek-Sharma ff6b50d0a8 Adjust to changes in commons. 2020-02-04 19:40:28 +01:00
Spencer Gibb 3cb98b70ce Updates eureka to 1.9.17
Doesn't shutdown servo for AbstractDocumentationTests.

fixes gh-3743
2020-01-29 12:17:00 -05:00
Spencer Gibb d1ffc8d72e Revert "Updates eureka to 1.9.17"
This reverts commit 49f88c4e
2020-01-27 15:42:45 -05:00
Spencer Gibb 49f88c4e7c Updates eureka to 1.9.17
fixes gh-3743
2020-01-27 14:14:03 -05:00
Spencer Gibb 53bffa7f04 formatting 2020-01-27 12:26:33 -05:00
Spencer Gibb 8e1ada2b3d formatting 2020-01-27 12:26:17 -05:00
Spencer Gibb 4122aadb73 Removes implementation in preference of parent class 2020-01-27 12:24:42 -05:00
Spencer Gibb 92c0c7d503 Merge branch '2.1.x' into 2.2.x 2020-01-27 12:24:15 -05:00
Dmitrii_Priporov 34b1a07124 Implements ServiceInstance.getScheme() using InstanceInfo.
fixes gh-3727
2020-01-27 12:24:07 -05:00
Spencer Gibb ae637ab3e5 Implements getScheme 2020-01-27 12:23:41 -05:00
Spencer Gibb 2cd7e41c05 Merge branch '2.1.x' into 2.2.x 2020-01-27 11:30:32 -05:00
Flora KALISA cf95248c37 Documents defaultZone case sensitivity
Fixes gh-3695
2020-01-27 11:29:33 -05:00
buildmaster b904eaa886 Bumping versions 2020-01-21 13:55:23 +00:00
Spencer Gibb 3455489f47 Migrates deprecations 2020-01-17 17:58:31 -05:00
buildmaster af919cac66 Bumping versions 2020-01-15 17:47:08 +00:00
Eric Bussieres ead46658c0 Fix for customizer not applied (#3722)
* Fix for customizer not applied when circuit breaker are created in advance

* Checkstyle
2020-01-14 13:34:04 -05:00
buildmaster 732f7d40ea Bumping versions 2020-01-14 17:46:24 +00:00
Spencer Gibb 67444a07c2 Merge branch '2.1.x' 2020-01-13 20:36:16 -05:00
OLPMO a6da307048 Optimize some code (#3693)
* Optimize some code

* fix error of ImportOrder
2020-01-13 20:32:00 -05:00
Andrew McCallum 55dabe8e6b Fix Apache HTTP client typos (#3687) 2020-01-13 18:38:46 -05:00
LiangYong 7e82a47dd3 fixed #3692 issue (#3728)
* fixed #3692 issue

fixed #3692  : Ribbon not getting list of servers from properties with lazy initialization

* Fixeds #3692 issue & add add test

* fix check style failed
2020-01-10 17:18:35 +01:00
fecqs c56e4a35d5 Fixes misspelling in sagan index 2020-01-06 20:32:01 -05:00
buildmaster 02f3bb8bba Bumping versions 2019-12-20 17:46:33 +00:00
buildmaster a4fc71a5b1 Bumping versions to 2.2.2.BUILD-SNAPSHOT after release 2019-12-20 12:36:13 +00:00
buildmaster a33387faa6 Going back to snapshots 2019-12-20 12:36:13 +00:00
buildmaster ec087d0747 Update SNAPSHOT to 2.2.1.RELEASE 2019-12-20 12:31:01 +00:00
Olga Maciaszek-Sharma 23659f8aea Gh 3718 add zoned loadbalancer instrumentation (#3720)
* Add instrumentation for zoned LoadBalancer.

* Add documentation.

* Fix after review.

* Fix after review.
2019-12-19 17:46:50 +01:00
Spencer Gibb b51a15c3f2 ignores .flattened-pom.xml 2019-12-17 17:49:38 -05:00
Spencer Gibb dc30eb2073 removes .flattened-pom.xml 2019-12-17 17:49:03 -05:00
Deepika Mohan c6b8873f0c Fix typo: clas -> class (#3710) 2019-12-16 16:45:52 +01:00
buildmaster 78cce48aa1 Bumping versions 2019-11-26 17:45:50 +00:00
buildmaster 73c40cf561 Bumping versions to 2.2.1.BUILD-SNAPSHOT after release 2019-11-26 10:03:40 +00:00
buildmaster a10d7b69d4 Going back to snapshots 2019-11-26 10:03:40 +00:00
buildmaster 4164297a89 Update SNAPSHOT to 2.2.0.RELEASE 2019-11-26 09:57:00 +00:00
buildmaster 56534dba1c Bumping versions 2019-11-22 17:45:45 +00:00
buildmaster f50e3d60a9 Bumping versions 2019-11-20 17:45:30 +00:00
Ryan Baxter e31d478c11 Update issue templates 2019-11-19 16:25:35 -05:00
Ryan Baxter 0fa901f6bc Create security.md 2019-11-19 16:24:32 -05:00
buildmaster 23366ac178 Bumping versions to 2.1.5.BUILD-SNAPSHOT after release 2019-11-18 14:58:44 +00:00
buildmaster 6fc234494a Going back to snapshots 2019-11-18 14:58:44 +00:00
Ryan Baxter 67fd109d68 Merge branch 'master' of github.com:spring-cloud/spring-cloud-netflix 2019-11-13 19:38:36 -05:00
Ryan Baxter 3ecf5a7420 Update configuration to use proxyBeanMethods=false. Fixes #3677 2019-11-13 19:38:30 -05:00
buildmaster 69f4c901a9 Going back to snapshots 2019-11-08 21:41:50 +00:00
buildmaster 3130493a3c Update SNAPSHOT to 2.2.0.RC2 2019-11-08 21:38:52 +00:00
buildmaster 87529e0994 Bumping versions 2019-11-07 13:52:14 +00:00
Marcin Grzejszczak e8816398a8 Added maven flatten plugin 2019-11-07 14:37:26 +01:00
Dave Syer bb1269d635 Also add build helper config for contract tests 2019-11-06 09:43:26 +00:00
Dave Syer 38cec4e35d Fix some dependencies that show up in the wrong scope
Apparently you can build on the command line but Eclipse is fussy
now and wouldn't compile these projects without explicit
dependencies.
2019-11-06 09:43:26 +00:00
buildmaster 2b5d246725 Bumping versions 2019-11-05 17:47:29 +00:00
Ryan Baxter 9b2405f3eb Adding configuration metadata for spring cloud circuitbreaker 2019-11-04 16:28:31 -05:00
Ryan Baxter 4ca1901417 Fix command key configuration. Use id as command key and class as group key. 2019-10-31 16:43:41 -04:00
Ryan Baxter 2208011dd3 Add property to disable spring cloud circuit breaker for hystrix 2019-10-31 16:42:59 -04:00
Ryan Baxter 9a2b254d0c Merge remote-tracking branch 'origin/2.1.x' 2019-10-24 17:09:37 -04:00
buildmaster d74b319b44 Going back to snapshots 2019-10-24 20:39:42 +00:00
buildmaster 3d3d528e02 Update SNAPSHOT to 2.2.0.RC1 2019-10-24 20:36:47 +00:00
buildmaster 28326b506b Going back to snapshots 2019-10-03 19:22:30 +00:00
buildmaster 392565f395 Update SNAPSHOT to 2.2.0.M3 2019-10-03 19:19:39 +00:00
Tim Ysewyn 532a95e783 Added support for reactive service discovery 2019-10-02 16:40:51 +02:00
Spencer Gibb ac60c28baa Updates to use "components" rather than "details"
See https://github.com/spring-projects/spring-boot/issues/17929
2019-09-30 13:17:07 -04:00
Olga Maciaszek-Sharma 40ec6066c1 Merge 2.1.x. 2019-09-26 16:34:04 +02:00
buildmaster e8ff2ebaf8 Bumping versions 2019-09-25 17:45:22 +00:00
Olga Maciaszek-Sharma 24f5e0b043 Gh 3409 turbine stream test (#3665)
* Add stream-test-support.

* Fix condition.

* Remove outdated workaround.
2019-09-25 19:32:09 +02:00
Spencer Gibb 8eb843c951 Updates health check handler to use new StatusAggregator 2019-09-25 12:59:39 -04:00
Spencer Gibb 543ab09012 polish 2019-09-25 12:59:11 -04:00
Ryan Baxter 7389f25f1c Merge remote-tracking branch 'origin/2.1.x' 2019-09-19 16:43:33 -04:00
Olga Maciaszek-Sharma 669ce753b2 Merge branch '2.1.x'
# Conflicts:
#	docs/pom.xml
#	pom.xml
#	spring-cloud-netflix-archaius/pom.xml
#	spring-cloud-netflix-concurrency-limits/pom.xml
#	spring-cloud-netflix-core/pom.xml
#	spring-cloud-netflix-dependencies/pom.xml
#	spring-cloud-netflix-eureka-client/pom.xml
#	spring-cloud-netflix-eureka-server/pom.xml
#	spring-cloud-netflix-hystrix-contract/pom.xml
#	spring-cloud-netflix-hystrix-dashboard/pom.xml
#	spring-cloud-netflix-hystrix-stream/pom.xml
#	spring-cloud-netflix-hystrix/pom.xml
#	spring-cloud-netflix-ribbon/pom.xml
#	spring-cloud-netflix-sidecar/pom.xml
#	spring-cloud-netflix-turbine-stream/pom.xml
#	spring-cloud-netflix-turbine/pom.xml
#	spring-cloud-netflix-zuul/pom.xml
#	spring-cloud-starter-netflix/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-archaius/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-eureka-client/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-eureka-server/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-hystrix-dashboard/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-hystrix/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-ribbon/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-turbine-stream/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-turbine/pom.xml
#	spring-cloud-starter-netflix/spring-cloud-starter-netflix-zuul/pom.xml
2019-09-18 13:40:33 +02:00
buildmaster 7dbac954d1 Bumping versions 2019-09-16 17:45:17 +00:00
Rafał Żukowski 828bc82363 ConditionalOnMissingBean on formBodyWrapperFilter, debugFilter… (#3609) 2019-09-16 12:26:08 -04:00
Olga Maciaszek-Sharma e8b50d80ed Update docs. (#3650) 2019-09-13 17:09:01 +02:00
Olga Maciaszek-Sharma 181d210aa5 Add Spring Cloud LoadBalancer starter to Eureka starters. Fixes gh-3646. (#3647) 2019-09-11 12:48:46 +02:00
Spencer Gibb d4db93a86a Merge branch '2.1.x' 2019-09-04 15:54:32 -04:00
Ryan Baxter 438d3f9b0e Fromatting 2019-09-03 16:57:48 -04:00
Ryan Baxter d5de0fc55c Merge remote-tracking branch 'origin/2.1.x' 2019-09-03 16:18:00 -04:00
Spencer Gibb 388faaa8e5 Removes okhttp3 again after added back in older branch. 2019-09-03 14:36:27 -04:00
Ryan Baxter b386a78dae Merge remote-tracking branch 'origin/2.1.x' 2019-09-03 10:56:45 -04:00
Denys Ivano 0ea0472b4f Re-create connection manager on "zuul.host.*" property change (#3407)
* Re-create connection manager on "zuul.host.*" property change 

Fixes #3406

* Wrap connectionManager.shutdown() in try/catch block. Polishing
2019-09-03 10:55:47 -04:00
Spencer Gibb 6d74bebf66 Removes dependency management for okhttp3 2019-08-29 12:22:29 -04:00
Spencer Gibb a99b5d66ca Merge branch '2.1.x' 2019-08-29 12:17:02 -04:00
Ryan Baxter b0e694601e Merge remote-tracking branch 'origin/2.1.x' 2019-08-28 20:18:54 -04:00
Ryan Baxter e160395978 Separated circuitbreaker auto config to its own file 2019-08-28 13:57:09 -04:00
Ryan Baxter 46c25b38d7 Adding spring cloud circuitbreaker hystrix implementation 2019-08-27 20:14:16 -04:00
buildmaster 455c60c15c Going back to snapshots 2019-08-14 14:55:06 +00:00
buildmaster 00b419be94 Update SNAPSHOT to 2.2.0.M2 2019-08-14 14:51:52 +00:00
Spencer Gibb df33d0bd07 Merge branch '2.1.x' 2019-08-01 17:02:03 -04:00
Marcin Grzejszczak 9d40b5dc4e Added symbolic link of index.adoc 2019-07-29 14:33:54 +02:00
buildmaster b8fb056981 Going back to snapshots 2019-07-03 18:03:09 +00:00
buildmaster b0ace4774e Update SNAPSHOT to 2.2.0.M1 2019-07-03 18:00:04 +00:00
Ryan Baxter 34c96c99cf Merge remote-tracking branch 'origin/2.1.x' 2019-07-03 11:27:08 -04:00
Greg Adams c24e7e05bf conditional sidecar autoconfig EurekaInstanceConfigBean (#3568)
fix for gh-3545
2019-06-17 20:43:08 -04:00
Spencer Gibb fd710d8a7d Merge branch '2.1.x' 2019-06-13 20:10:40 -04:00
Spencer Gibb 62deb59314 Rename freemarker templates to ftlh
fixes gh-3566
2019-06-13 19:51:37 -04:00
Spencer Gibb 925f460d64 Rename freemarker templates to ftlh
fixes gh-3566
2019-06-13 19:38:07 -04:00
Spencer Gibb 6c2359a0ca Merge branch '2.1.x' 2019-06-10 12:33:50 -04:00
Spencer Gibb 571d1b7bb7 Merge branch '2.1.x' 2019-06-05 15:44:45 -04:00
PeichengLiu c01d9e6b59 fix a syntax error in the document (#3525) 2019-06-03 10:18:48 -04:00
Ryan Baxter 609b4f5838 Moving to Horsham 2019-05-29 11:25:41 -04:00
Olga Maciaszek-Sharma 23e1c36462 Reformat with the newest Spring javaformat plugin version 2019-05-29 16:35:22 +02:00
Olga Maciaszek-Sharma 4d765b37bb Merge branch '2.1.x' 2019-05-29 16:22:15 +02:00
Siavash Shaghafi e606cc527e adds caution about property name case-sensitivity (#3533)
* adds caution about property name case-sensitivity

* applies review suggestion
2019-05-23 13:55:27 +02:00
Ryan Baxter 4403e1c8ff Merge remote-tracking branch 'origin/2.1.x' 2019-05-21 13:00:16 -04:00
Ryan Baxter 0b0f5d2334 Merge branch 'master' of github.com:spring-cloud/spring-cloud-netflix 2019-05-21 11:09:30 -04:00
Ryan Baxter 25cd7a5810 Formatting changes 2019-05-21 11:09:18 -04:00
Dave Syer 7aab07365d Add jaxb-runtime to eureka server starter
See https://github.com/spring-io/start.spring.io/issues/119
2019-05-20 10:40:35 +01:00
Dave Syer 6acaa9be8b Update xstream to latest patch level 2019-05-13 13:52:10 +01:00
Dave Syer 11a9819e3b Tweak test to work with Java 12
Also some format changes (checkstyle/Boot plugin)
2019-05-13 10:57:55 +01:00
Dave Syer 4997b69433 Remove deprecated class usage 2019-05-13 09:14:23 +01:00
Dave Syer e2f1f368b5 Make http trace filter bean injection conditional
Recent changes in Spring Boot have meant that there is no longer
an httpTraceFilter bean by default. We can just make it conditional.

Fixes gh-3528
2019-05-13 09:04:55 +01:00
Ryan Baxter 7ea5c3a32f Merge remote-tracking branch 'origin/2.1.x' 2019-05-10 14:23:30 -04:00
Marcin Grzejszczak 03b1e326ce Added sagan pages; fixes gh-3521 2019-04-29 13:21:56 +04:00
Spencer Gibb 7449915919 Bumps to Germantown 2019-04-25 10:28:47 +02:00
Ryan Baxter 0e66862cbb Merge remote-tracking branch 'origin/2.1.x' 2019-04-10 20:29:34 -04:00
Spencer Gibb ee9c704a4c Fixes change in framework api 2019-04-05 11:34:26 -04:00
Spencer Gibb 105f8d85b3 adds checkstyle suppressions. 2019-04-05 11:22:53 -04:00
Ryan Baxter cc6ec1572b Merge branch 'spring-operator-polish-urls-remaining-master' 2019-03-28 20:12:30 -04:00
Ryan Baxter 37d39617bf Fixing tests 2019-03-28 20:12:03 -04:00
Ryan Baxter 3c92af4a06 Merge branch 'polish-urls-remaining-master' of https://github.com/spring-operator/spring-cloud-netflix into spring-operator-polish-urls-remaining-master 2019-03-28 16:16:27 -04:00
Spring Operator eff47e0464 URL Cleanup (#3441)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed But Review Recommended
These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended.

* http://www.puppycrawl.com/dtds/suppressions_1_1.dtd (404) with 1 occurrences migrated to:
  https://www.puppycrawl.com/dtds/suppressions_1_1.dtd ([https](https://www.puppycrawl.com/dtds/suppressions_1_1.dtd) result 404).

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* http://maven.apache.org/xsd/maven-4.0.0.xsd with 27 occurrences migrated to:
  https://maven.apache.org/xsd/maven-4.0.0.xsd ([https](https://maven.apache.org/xsd/maven-4.0.0.xsd) result 200).

# Ignored
These URLs were intentionally ignored.

* http://maven.apache.org/POM/4.0.0 with 54 occurrences
* http://www.isdc.ro/wro with 1 occurrences
* http://www.w3.org/2001/XMLSchema-instance with 27 occurrences
2019-03-26 11:50:20 -04:00
Spring Operator c1771dce56 URL Cleanup (#3451)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://www.apache.org/licenses/ with 1 occurrences migrated to:
  https://www.apache.org/licenses/ ([https](https://www.apache.org/licenses/) result 200).
* [ ] http://www.apache.org/licenses/LICENSE-2.0 with 414 occurrences migrated to:
  https://www.apache.org/licenses/LICENSE-2.0 ([https](https://www.apache.org/licenses/LICENSE-2.0) result 200).
2019-03-21 20:29:33 -04:00
Spring Operator 88b71f05fa URL Cleanup
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# HTTP URLs that Could Not Be Fixed
These URLs were unable to be fixed. Please review them to see if they can be manually resolved.

* [ ] http://conor.cc (200) with 4 occurrences could not be migrated:
   ([https](https://conor.cc) result SSLProtocolException).
* [ ] http://richclarkdesign.com (200) with 1 occurrences could not be migrated:
   ([https](https://richclarkdesign.com) result SSLHandshakeException).
* [ ] http://tinysort.sjeiti.com/ (200) with 1 occurrences could not be migrated:
   ([https](https://tinysort.sjeiti.com/) result SSLException).
* [ ] http://unknown-origin.com (200) with 1 occurrences could not be migrated:
   ([https](https://unknown-origin.com) result AnnotatedConnectException).
* [ ] http://www.sjeiti.com/ (301) with 1 occurrences could not be migrated:
   ([https](https://www.sjeiti.com/) result SSLException).
* [ ] http://foo.com (301) with 1 occurrences could not be migrated:
   ([https](https://foo.com) result SSLHandshakeException).

# Fixed URLs

## Fixed But Review Recommended
These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended.

* [ ] http://ejohn.org/ (301) with 1 occurrences migrated to:
  https://johnresig.com/ ([https](https://ejohn.org/) result ClosedChannelException).
* [ ] http://ejohn.org/blog/javascript-micro-templating/ (301) with 1 occurrences migrated to:
  https://johnresig.com/blog/javascript-micro-templating/ ([https](https://ejohn.org/blog/javascript-micro-templating/) result ClosedChannelException).
* [ ] http://example3.com/ (302) with 1 occurrences migrated to:
  https://www.hugedomains.com/domain_profile.cfm?d=example3&e=com ([https](https://example3.com/) result ConnectTimeoutException).
* [ ] http://example3.com (302) with 2 occurrences migrated to:
  https://www.hugedomains.com/domain_profile.cfm?d=example3&e=com ([https](https://example3.com) result ConnectTimeoutException).
* [ ] http://192.168.13.90:9999/actuator/health (ConnectTimeoutException) with 1 occurrences migrated to:
  https://192.168.13.90:9999/actuator/health ([https](https://192.168.13.90:9999/actuator/health) result ConnectTimeoutException).
* [ ] http://192.168.13.90:9999/actuator/info (ConnectTimeoutException) with 1 occurrences migrated to:
  https://192.168.13.90:9999/actuator/info ([https](https://192.168.13.90:9999/actuator/info) result ConnectTimeoutException).
* [ ] http://www.w3.org/TR/html4/loose.dtd (ReadTimeoutException) with 1 occurrences migrated to:
  https://www.w3.org/TR/html4/loose.dtd ([https](https://www.w3.org/TR/html4/loose.dtd) result SSLException).
* [ ] http://%s:%s (UnknownHostException) with 1 occurrences migrated to:
  https://%s:%s ([https](https://%s:%s) result UnknownHostException).
* [ ] http://allowed-origin.com (UnknownHostException) with 2 occurrences migrated to:
  https://allowed-origin.com ([https](https://allowed-origin.com) result UnknownHostException).
* [ ] http://badClients/good (UnknownHostException) with 1 occurrences migrated to:
  https://badClients/good ([https](https://badClients/good) result UnknownHostException).
* [ ] http://badClients/null (UnknownHostException) with 1 occurrences migrated to:
  https://badClients/null ([https](https://badClients/null) result UnknownHostException).
* [ ] http://badClients/ping (UnknownHostException) with 1 occurrences migrated to:
  https://badClients/ping ([https](https://badClients/ping) result UnknownHostException).
* [ ] http://badClients/timeout (UnknownHostException) with 1 occurrences migrated to:
  https://badClients/timeout ([https](https://badClients/timeout) result UnknownHostException).
* [ ] http://bar (UnknownHostException) with 1 occurrences migrated to:
  https://bar ([https](https://bar) result UnknownHostException).
* [ ] http://compose.docker.io/ (UnknownHostException) with 2 occurrences migrated to:
  https://compose.docker.io/ ([https](https://compose.docker.io/) result UnknownHostException).
* [ ] http://custom-example.com (UnknownHostException) with 1 occurrences migrated to:
  https://custom-example.com ([https](https://custom-example.com) result UnknownHostException).
* [ ] http://custom-example.com/ (UnknownHostException) with 1 occurrences migrated to:
  https://custom-example.com/ ([https](https://custom-example.com/) result UnknownHostException).
* [ ] http://defaul-host3:8678/eureka/,http://defaul-host4:8678/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://defaul-host3:8678/eureka/,http://defaul-host4:8678/eureka/ ([https](https://defaul-host3:8678/eureka/,https://defaul-host4:8678/eureka/) result UnknownHostException).
* [ ] http://defaul-host4:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://defaul-host4:8678/eureka/ ([https](https://defaul-host4:8678/eureka/) result UnknownHostException).
* [ ] http://defaul-host5:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://defaul-host5:8678/eureka/ ([https](https://defaul-host5:8678/eureka/) result UnknownHostException).
* [ ] http://defaul-host6:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://defaul-host6:8678/eureka/ ([https](https://defaul-host6:8678/eureka/) result UnknownHostException).
* [ ] http://default-host1:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://default-host1:8678/eureka/ ([https](https://default-host1:8678/eureka/) result UnknownHostException).
* [ ] http://default-host2:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://default-host2:8678/eureka/ ([https](https://default-host2:8678/eureka/) result UnknownHostException).
* [ ] http://default-host3:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://default-host3:8678/eureka/ ([https](https://default-host3:8678/eureka/) result UnknownHostException).
* [ ] http://earlymade.com (UnknownHostException) with 4 occurrences migrated to:
  https://earlymade.com ([https](https://earlymade.com) result UnknownHostException).
* [ ] http://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/ ([https](https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/) result UnknownHostException).
* [ ] http://example.com,http://example2.com (UnknownHostException) with 2 occurrences migrated to:
  https://example.com,http://example2.com ([https](https://example.com,https://example2.com) result UnknownHostException).
* [ ] http://example1.com,http://example2.com (UnknownHostException) with 1 occurrences migrated to:
  https://example1.com,http://example2.com ([https](https://example1.com,https://example2.com) result UnknownHostException).
* [ ] http://first.example.com (UnknownHostException) with 1 occurrences migrated to:
  https://first.example.com ([https](https://first.example.com) result UnknownHostException).
* [ ] http://foo (UnknownHostException) with 5 occurrences migrated to:
  https://foo ([https](https://foo) result UnknownHostException).
* [ ] http://foo/ (UnknownHostException) with 2 occurrences migrated to:
  https://foo/ ([https](https://foo/) result UnknownHostException).
* [ ] http://foo/%20bar (UnknownHostException) with 1 occurrences migrated to:
  https://foo/%20bar ([https](https://foo/%20bar) result UnknownHostException).
* [ ] http://foo/%20bar?hello=1+2 (UnknownHostException) with 2 occurrences migrated to:
  https://foo/%20bar?hello=1+2 ([https](https://foo/%20bar?hello=1+2) result UnknownHostException).
* [ ] http://foo:7001/ (UnknownHostException) with 1 occurrences migrated to:
  https://foo:7001/ ([https](https://foo:7001/) result UnknownHostException).
* [ ] http://foo:7777/ (UnknownHostException) with 1 occurrences migrated to:
  https://foo:7777/ ([https](https://foo:7777/) result UnknownHostException).
* [ ] http://host/doStuff (UnknownHostException) with 1 occurrences migrated to:
  https://host/doStuff ([https](https://host/doStuff) result UnknownHostException).
* [ ] http://host:7777/Management/health (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/Management/health ([https](https://host:7777/Management/health) result UnknownHostException).
* [ ] http://host:7777/Management/info (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/Management/info ([https](https://host:7777/Management/info) result UnknownHostException).
* [ ] http://host:7777/Server/Management/health (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/Server/Management/health ([https](https://host:7777/Server/Management/health) result UnknownHostException).
* [ ] http://host:7777/Server/Management/info (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/Server/Management/info ([https](https://host:7777/Server/Management/info) result UnknownHostException).
* [ ] http://host:7777/Server/health (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/Server/health ([https](https://host:7777/Server/health) result UnknownHostException).
* [ ] http://host:7777/Server/info (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/Server/info ([https](https://host:7777/Server/info) result UnknownHostException).
* [ ] http://host:7777/health (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/health ([https](https://host:7777/health) result UnknownHostException).
* [ ] http://host:7777/info (UnknownHostException) with 1 occurrences migrated to:
  https://host:7777/info ([https](https://host:7777/info) result UnknownHostException).
* [ ] http://host:8888/Management/health (UnknownHostException) with 3 occurrences migrated to:
  https://host:8888/Management/health ([https](https://host:8888/Management/health) result UnknownHostException).
* [ ] http://host:8888/Management/info (UnknownHostException) with 3 occurrences migrated to:
  https://host:8888/Management/info ([https](https://host:8888/Management/info) result UnknownHostException).
* [ ] http://host:8888/health (UnknownHostException) with 2 occurrences migrated to:
  https://host:8888/health ([https](https://host:8888/health) result UnknownHostException).
* [ ] http://host:8888/info (UnknownHostException) with 2 occurrences migrated to:
  https://host:8888/info ([https](https://host:8888/info) result UnknownHostException).
* [ ] http://hostname:port/turbine/turbine.stream (UnknownHostException) with 1 occurrences migrated to:
  https://hostname:port/turbine/turbine.stream ([https](https://hostname:port/turbine/turbine.stream) result UnknownHostException).
* [ ] http://hystrix-app:port/actuator/hystrix.stream (UnknownHostException) with 1 occurrences migrated to:
  https://hystrix-app:port/actuator/hystrix.stream ([https](https://hystrix-app:port/actuator/hystrix.stream) result UnknownHostException).
* [ ] http://legacy.example.com (UnknownHostException) with 1 occurrences migrated to:
  https://legacy.example.com ([https](https://legacy.example.com) result UnknownHostException).
* [ ] http://mhhost2:0/foo/health (UnknownHostException) with 2 occurrences migrated to:
  https://mhhost2:0/foo/health ([https](https://mhhost2:0/foo/health) result UnknownHostException).
* [ ] http://mhhost2:0/foo/info (UnknownHostException) with 2 occurrences migrated to:
  https://mhhost2:0/foo/info ([https](https://mhhost2:0/foo/info) result UnknownHostException).
* [ ] http://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME ([https](https://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream ([https](https://my.turbine.sever:8989/turbine.stream) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream?cluster=customers (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream?cluster=customers ([https](https://my.turbine.sever:8989/turbine.stream?cluster=customers) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream?cluster=default (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream?cluster=default ([https](https://my.turbine.sever:8989/turbine.stream?cluster=default) result UnknownHostException).
* [ ] http://my.turbine.sever:8989/turbine.stream?cluster=products (UnknownHostException) with 1 occurrences migrated to:
  https://my.turbine.sever:8989/turbine.stream?cluster=products ([https](https://my.turbine.sever:8989/turbine.stream?cluster=products) result UnknownHostException).
* [ ] http://myhost2:9000 (UnknownHostException) with 1 occurrences migrated to:
  https://myhost2:9000 ([https](https://myhost2:9000) result UnknownHostException).
* [ ] http://myhost:8080 (UnknownHostException) with 1 occurrences migrated to:
  https://myhost:8080 ([https](https://myhost:8080) result UnknownHostException).
* [ ] http://myhost:8989 (UnknownHostException) with 1 occurrences migrated to:
  https://myhost:8989 ([https](https://myhost:8989) result UnknownHostException).
* [ ] http://myhost:9000 (UnknownHostException) with 1 occurrences migrated to:
  https://myhost:9000 ([https](https://myhost:9000) result UnknownHostException).
* [ ] http://myservice (UnknownHostException) with 1 occurrences migrated to:
  https://myservice ([https](https://myservice) result UnknownHostException).
* [ ] http://peer1/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://peer1/eureka/ ([https](https://peer1/eureka/) result UnknownHostException).
* [ ] http://peer1/eureka/,http://peer2/eureka/,http://peer3/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://peer1/eureka/,http://peer2/eureka/,http://peer3/eureka/ ([https](https://peer1/eureka/,https://peer2/eureka/,https://peer3/eureka/) result UnknownHostException).
* [ ] http://peer2/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://peer2/eureka/ ([https](https://peer2/eureka/) result UnknownHostException).
* [ ] http://region1-zone-host:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://region1-zone-host:8678/eureka/ ([https](https://region1-zone-host:8678/eureka/) result UnknownHostException).
* [ ] http://region2-zone-host:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://region2-zone-host:8678/eureka/ ([https](https://region2-zone-host:8678/eureka/) result UnknownHostException).
* [ ] http://region4-zone-host:8678/eureka/ (UnknownHostException) with 2 occurrences migrated to:
  https://region4-zone-host:8678/eureka/ ([https](https://region4-zone-host:8678/eureka/) result UnknownHostException).
* [ ] http://sidecar.local.spring.io:5678/configserver/default-master.yml (UnknownHostException) with 1 occurrences migrated to:
  https://sidecar.local.spring.io:5678/configserver/default-master.yml ([https](https://sidecar.local.spring.io:5678/configserver/default-master.yml) result UnknownHostException).
* [ ] http://simple/ (UnknownHostException) with 1 occurrences migrated to:
  https://simple/ ([https](https://simple/) result UnknownHostException).
* [ ] http://simple/emptypost (UnknownHostException) with 1 occurrences migrated to:
  https://simple/emptypost ([https](https://simple/emptypost) result UnknownHostException).
* [ ] http://simple/header (UnknownHostException) with 1 occurrences migrated to:
  https://simple/header ([https](https://simple/header) result UnknownHostException).
* [ ] http://simple/path/ (UnknownHostException) with 2 occurrences migrated to:
  https://simple/path/ ([https](https://simple/path/) result UnknownHostException).
* [ ] http://simple/post (UnknownHostException) with 1 occurrences migrated to:
  https://simple/post ([https](https://simple/post) result UnknownHostException).
* [ ] http://simple/request?param= (UnknownHostException) with 1 occurrences migrated to:
  https://simple/request?param= ([https](https://simple/request?param=) result UnknownHostException).
* [ ] http://simple_bad (UnknownHostException) with 1 occurrences migrated to:
  https://simple_bad ([https](https://simple_bad) result UnknownHostException).
* [ ] http://turbine-hostname:port/turbine.stream (UnknownHostException) with 1 occurrences migrated to:
  https://turbine-hostname:port/turbine.stream ([https](https://turbine-hostname:port/turbine.stream) result UnknownHostException).
* [ ] http://turbine-hostname:port/turbine.stream?cluster= (UnknownHostException) with 1 occurrences migrated to:
  https://turbine-hostname:port/turbine.stream?cluster= ([https](https://turbine-hostname:port/turbine.stream?cluster=) result UnknownHostException).
* [ ] http://user2:pwd2@test2.com (UnknownHostException) with 1 occurrences migrated to:
  https://user2:pwd2@test2.com ([https](https://user2:pwd2@test2.com) result UnknownHostException).
* [ ] http://user:foo@example.com:80/eureka (UnknownHostException) with 1 occurrences migrated to:
  https://user:foo@example.com:80/eureka ([https](https://user:foo@example.com:80/eureka) result UnknownHostException).
* [ ] http://user:password@localhost:8761/eureka (UnknownHostException) with 1 occurrences migrated to:
  https://user:password@localhost:8761/eureka ([https](https://user:password@localhost:8761/eureka) result UnknownHostException).
* [ ] http://user:password@localhost:8761/eureka/ (UnknownHostException) with 1 occurrences migrated to:
  https://user:password@localhost:8761/eureka/ ([https](https://user:password@localhost:8761/eureka/) result UnknownHostException).
* [ ] http://user:pwd@test1.com (UnknownHostException) with 1 occurrences migrated to:
  https://user:pwd@test1.com ([https](https://user:pwd@test1.com) result UnknownHostException).
* [ ] http://www.puppycrawl.com/dtds/suppressions_1_1.dtd (404) with 1 occurrences migrated to:
  https://www.puppycrawl.com/dtds/suppressions_1_1.dtd ([https](https://www.puppycrawl.com/dtds/suppressions_1_1.dtd) result 404).

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://asciidoctor.org with 1 occurrences migrated to:
  https://asciidoctor.org ([https](https://asciidoctor.org) result 200).
* [ ] http://example.com with 15 occurrences migrated to:
  https://example.com ([https](https://example.com) result 200).
* [ ] http://example.com/ with 5 occurrences migrated to:
  https://example.com/ ([https](https://example.com/) result 200).
* [ ] http://example.com/users_service with 1 occurrences migrated to:
  https://example.com/users_service ([https](https://example.com/users_service) result 200).
* [ ] http://github.com/ with 1 occurrences migrated to:
  https://github.com/ ([https](https://github.com/) result 200).
* [ ] http://hello.com with 3 occurrences migrated to:
  https://hello.com ([https](https://hello.com) result 200).
* [ ] http://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html with 1 occurrences migrated to:
  https://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html ([https](https://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html) result 200).
* [ ] http://martinfowler.com/bliki/CircuitBreaker.html with 1 occurrences migrated to:
  https://martinfowler.com/bliki/CircuitBreaker.html ([https](https://martinfowler.com/bliki/CircuitBreaker.html) result 200).
* [ ] http://projects.spring.io/spring-cloud/ with 6 occurrences migrated to:
  https://projects.spring.io/spring-cloud/ ([https](https://projects.spring.io/spring-cloud/) result 200).
* [ ] http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html with 3 occurrences migrated to:
  https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html ([https](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) result 200).
* [ ] http://www.gnu.org/licenses/gpl.html with 1 occurrences migrated to:
  https://www.gnu.org/licenses/gpl.html ([https](https://www.gnu.org/licenses/gpl.html) result 200).
* [ ] http://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27 with 1 occurrences migrated to:
  https://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27 ([https](https://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146/27) result 200).
* [ ] http://commons.apache.org/proper/commons-configuration with 1 occurrences migrated to:
  https://commons.apache.org/proper/commons-configuration ([https](https://commons.apache.org/proper/commons-configuration) result 301).
* [ ] http://creativecommons.org/licenses/MIT/ with 4 occurrences migrated to:
  https://creativecommons.org/licenses/MIT/ ([https](https://creativecommons.org/licenses/MIT/) result 301).
* [ ] http://plugins.jetbrains.com/plugin/6546 with 3 occurrences migrated to:
  https://plugins.jetbrains.com/plugin/6546 ([https](https://plugins.jetbrains.com/plugin/6546) result 301).
* [ ] http://raw.github.com/ with 1 occurrences migrated to:
  https://raw.github.com/ ([https](https://raw.github.com/) result 301).
* [ ] http://service.com with 3 occurrences migrated to:
  https://service.com ([https](https://service.com) result 301).
* [ ] http://www.opensource.org/licenses/mit-license.php with 1 occurrences migrated to:
  https://www.opensource.org/licenses/mit-license.php ([https](https://www.opensource.org/licenses/mit-license.php) result 301).
* [ ] http://eclipse.org with 2 occurrences migrated to:
  https://eclipse.org ([https](https://eclipse.org) result 302).
* [ ] http://eclipse.org/m2e/ with 4 occurrences migrated to:
  https://eclipse.org/m2e/ ([https](https://eclipse.org/m2e/) result 302).
* [ ] http://example2.com/ with 1 occurrences migrated to:
  https://example2.com/ ([https](https://example2.com/) result 302).
* [ ] http://simplegrid.info with 4 occurrences migrated to:
  https://simplegrid.info ([https](https://simplegrid.info) result 302).
* [ ] http://simplegrid.info/ with 1 occurrences migrated to:
  https://simplegrid.info/ ([https](https://simplegrid.info/) result 302).
* [ ] http://www.springsource.com/developer/sts with 2 occurrences migrated to:
  https://www.springsource.com/developer/sts ([https](https://www.springsource.com/developer/sts) result 302).

# Ignored
These URLs were intentionally ignored.

* http://localhost with 135 occurrences
* http://localhost/ with 2 occurrences
* http://localhost/info with 1 occurrences
* http://localhost/ping with 2 occurrences
* http://localhost/status with 1 occurrences
* http://localhost:%d/lazy/sample with 1 occurrences
* http://localhost:%d/service/redirectedUri with 1 occurrences
* http://localhost:5678/configserver with 1 occurrences
* http://localhost:5678/customers with 1 occurrences
* http://localhost:5678/hosts/ with 1 occurrences
* http://localhost:7777/local with 4 occurrences
* http://localhost:8000/health.json with 1 occurrences
* http://localhost:8000/src/test/resources/health.json with 1 occurrences
* http://localhost:8080 with 2 occurrences
* http://localhost:8081 with 3 occurrences
* http://localhost:8383/turbine.stream?cluster=RACES with 1 occurrences
* http://localhost:8383/turbine.stream?cluster=WEB with 1 occurrences
* http://localhost:8678/eureka/ with 1 occurrences
* http://localhost:8761 with 2 occurrences
* http://localhost:8761/eureka/ with 5 occurrences
* http://localhost:9000 with 2 occurrences
* http://test1.com with 1 occurrences
* http://test1.com,http://test2.com with 1 occurrences
* http://test1.com,http://user2:pwd2@test2.com with 1 occurrences
* http://test2.com with 1 occurrences
* http://test3.com,http://test4.com with 1 occurrences
* http://test3.com,http://user4:pwd4@test4.com with 1 occurrences
* http://test:test@localhost:8761 with 1 occurrences
* http://test@localhost:8761 with 1 occurrences
* http://testService with 1 occurrences
2019-03-20 15:47:00 -05:00
Craig Andrews 52e4f5ea59 Set traceRequestBody to false by default (#3439)
traceRequestBody requires the body to be buffered which reduces performance and can be problematic, such as when used in combination with `zuul.use-filter=true` and `zuul.servlet-path=/` See https://github.com/spring-cloud/spring-cloud-netflix/issues/3418

traceRequestBody should only be set when logging the request body is actually necessary.
2019-03-19 14:51:42 -04:00
Spring Operator 77b8965e29 URL Cleanup (#3411)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed Success 
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* http://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch migrated to:  
  https://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch ([https](https://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch) result 200).
* http://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin migrated to:  
  https://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin ([https](https://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin) result 200).
* http://www.apache.org/licenses/LICENSE-2.0 migrated to:  
  https://www.apache.org/licenses/LICENSE-2.0 ([https](https://www.apache.org/licenses/LICENSE-2.0) result 200).

# Ignored
These URLs were intentionally ignored.

* http://maven.apache.org/POM/4.0.0
* http://maven.apache.org/xsd/maven-4.0.0.xsd
* http://www.w3.org/2001/XMLSchema-instance
2019-03-11 18:58:19 -04:00
Ryan Baxter 0791a02223 Ignore failing test 2019-03-07 16:17:51 -05:00
Ryan Baxter 8fdc6f0898 Fix health check handler so it is compatible with boot 2.2.0 2019-03-07 16:17:26 -05:00
Marcin Grzejszczak 3d5484e410 Hoxton 2019-03-07 18:12:01 +01:00
534 changed files with 7274 additions and 2062 deletions
+4 -4
View File
@@ -3,7 +3,7 @@
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
tracker for issues and merging pull requests into main. If you want
to contribute even something trivial please do not hesitate, but
follow the guidelines below.
@@ -17,7 +17,7 @@ given the ability to merge pull requests.
## Code of Conduct
This project adheres to the Contributor Covenant [code of
conduct](https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report
conduct](https://github.com/spring-cloud/spring-cloud-build/blob/main/docs/src/main/asciidoc/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report
unacceptable behavior to spring-code-of-conduct@pivotal.io.
## Code Conventions and Housekeeping
@@ -27,7 +27,7 @@ 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
[Spring Cloud Build](https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml) project. If using IntelliJ, you can use the
[Spring Cloud Build](https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/spring-cloud-dependencies-parent/eclipse-code-formatter.xml) project. If using IntelliJ, you can use the
[Eclipse Code Formatter Plugin](https://plugins.jetbrains.com/plugin/6546) 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
@@ -38,7 +38,7 @@ added after the original pull request but before a merge.
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
* If no-one else is using your branch, please rebase it against the current main (or
other target branch in the main project).
* When writing a commit message please follow [these conventions](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit
+17
View File
@@ -0,0 +1,17 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: waiting-for-triage
assignees: ''
---
**Describe the bug**
Please provide details of the problem, including the version of Spring Cloud that you
are using.
**Sample**
If possible, please provide a test case or sample application that reproduces
the problem. This makes it much easier for us to diagnose the problem and to verify that
we have fixed it.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+3
View File
@@ -18,3 +18,6 @@ _site/
.shelf
*.swp
*.swo
.vscode/
.flattened-pom.xml
.sdkmanrc
-11
View File
@@ -1,11 +0,0 @@
require 'asciidoctor'
require 'erb'
options = {:mkdirs => true, :safe => :unsafe, :attributes => ['linkcss', 'allow-uri-read']}
guard 'shell' do
watch(/^docs\/[A-Z-a-z][^#]*\.adoc$/) {|m|
Asciidoctor.load_file('docs/src/main/asciidoc/README.adoc', :to_file => './README.adoc', safe: :safe, parse: false, attributes: 'allow-uri-read')
Asciidoctor.render_file('docs/src/main/asciidoc/spring-cloud-netflix.adoc', options.merge(:to_dir => 'target/generated-docs'))
}
end
+206 -6
View File
@@ -1,10 +1,47 @@
// Do not edit this file (e.g. go instead to src/main/asciidoc)
////
DO NOT EDIT THIS FILE. IT WAS GENERATED.
Manual changes to this file will be lost when it is generated again.
Edit the files in the src/main/asciidoc/ directory instead.
////
image::https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/master.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/master"]
image::https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/master/graph/badge.svg["Codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/master"]
:doctype: book
:idprefix:
:idseparator: -
:toc: left
:toclevels: 4
:tabsize: 4
:numbered:
:sectanchors:
:sectnums:
:icons: font
:hide-uri-scheme:
:docinfo: shared,private
:sc-ext: java
:project-full-name: Spring Cloud Netflix
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"]
:doctype: book
:idprefix:
:idseparator: -
:toc: left
:toclevels: 4
:tabsize: 4
:numbered:
:sectanchors:
:sectnums:
:icons: font
:hide-uri-scheme:
:docinfo: shared,private
:sc-ext: java
:project-full-name: Spring Cloud Netflix
This project provides Netflix OSS integrations for Spring Boot apps through autoconfiguration
and binding to the Spring Environment and other Spring programming model idioms. With a few
simple annotations you can quickly enable and configure the common patterns inside your
@@ -23,6 +60,21 @@ Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon).
* External Configuration: a bridge from the Spring Environment to Archaius (enables native configuration of Netflix components using Spring Boot conventions)
* Router and Filter: automatic registration of Zuul filters, and a simple convention over configuration approach to reverse proxy creation
:doctype: book
:idprefix:
:idseparator: -
:toc: left
:toclevels: 4
:tabsize: 4
:numbered:
:sectanchors:
:sectnums:
:icons: font
:hide-uri-scheme:
:docinfo: shared,private
:sc-ext: java
:project-full-name: Spring Cloud Netflix
== Modules In Maintenance Mode
@@ -35,6 +87,7 @@ of the Greenwich release train.
The following Spring Cloud Netflix modules and corresponding starters will be placed into maintenance mode:
* spring-cloud-netflix-archaius
* spring-cloud-netflix-concurrency-limits
* spring-cloud-netflix-hystrix-contract
* spring-cloud-netflix-hystrix-dashboard
* spring-cloud-netflix-hystrix-stream
@@ -44,7 +97,7 @@ The following Spring Cloud Netflix modules and corresponding starters will be pl
* spring-cloud-netflix-turbine
* spring-cloud-netflix-zuul
NOTE: This does not include the Eureka or concurrency-limits modules.
NOTE: This does not include the Eureka modules.
== Building
@@ -84,7 +137,7 @@ credentials and you already have those.
The projects that require middleware generally include a
`docker-compose.yml`, so consider using
https://compose.docker.io/[Docker Compose] to run the middeware servers
https://docs.docker.com/compose/[Docker Compose] to run the middeware servers
in Docker containers. See the README in the
https://github.com/spring-cloud-samples/scripts[scripts demo
repository] for specific instructions about the common cases of mongo,
@@ -111,6 +164,11 @@ 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
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
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
@@ -139,8 +197,13 @@ 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
: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
@@ -184,4 +247,141 @@ added after the original pull request but before a merge.
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).
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.
== License
The project license file is available https://raw.githubusercontent.com/spring-cloud/spring-cloud-netflix/main/LICENSE.txt[here].
-329
View File
@@ -1,329 +0,0 @@
////
DO NOT EDIT THIS FILE. IT WAS GENERATED.
Manual changes to this file will be lost when it is generated again.
Edit the files in the src/main/asciidoc/ directory instead.
////
image::https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/master.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/master"]
image::https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/master/graph/badge.svg["Codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/master"]
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"]
This project provides Netflix OSS integrations for Spring Boot apps through autoconfiguration
and binding to the Spring Environment and other Spring programming model idioms. With a few
simple annotations you can quickly enable and configure the common patterns inside your
application and build large distributed systems with battle-tested Netflix components. The
patterns provided include Service Discovery (Eureka), Circuit Breaker (Hystrix),
Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon).
== Features
* Service Discovery: Eureka instances can be registered and clients can discover the instances using Spring-managed beans
* Service Discovery: an embedded Eureka server can be created with declarative Java configuration
* Circuit Breaker: Hystrix clients can be built with a simple annotation-driven method decorator
* Circuit Breaker: embedded Hystrix dashboard with declarative Java configuration
* Client Side Load Balancer: Ribbon
* External Configuration: a bridge from the Spring Environment to Archaius (enables native configuration of Netflix components using Spring Boot conventions)
* Router and Filter: automatic registration of Zuul filters, and a simple convention over configuration approach to reverse proxy creation
== Modules In Maintenance Mode
Placing a module in maintenance mode means that the Spring Cloud team will no longer be adding new features to the module.
We will fix blocker bugs and security issues, and we will also consider and review small pull requests from the community.
We intend to continue to support these modules for a period of at least a year from the general availability
of the Greenwich release train.
The following Spring Cloud Netflix modules and corresponding starters will be placed into maintenance mode:
* spring-cloud-netflix-archaius
* spring-cloud-netflix-hystrix-contract
* spring-cloud-netflix-hystrix-dashboard
* spring-cloud-netflix-hystrix-stream
* spring-cloud-netflix-hystrix
* spring-cloud-netflix-ribbon
* spring-cloud-netflix-turbine-stream
* spring-cloud-netflix-turbine
* spring-cloud-netflix-zuul
NOTE: This does not include the Eureka or concurrency-limits modules.
== Building
:jdkversion: 1.8
=== Basic Compile and Test
To build the source you will need to install JDK {jdkversion}.
Spring Cloud uses Maven for most build-related activities, and you
should be able to get off the ground quite quickly by cloning the
project you are interested in and typing
----
$ ./mvnw install
----
NOTE: You can also install Maven (>=3.3.3) yourself and run the `mvn` command
in place of `./mvnw` in the examples below. If you do that you also
might need to add `-P spring` if your local Maven settings do not
contain repository declarations for spring pre-release artifacts.
NOTE: Be aware that you might need to increase the amount of memory
available to Maven by setting a `MAVEN_OPTS` environment variable with
a value like `-Xmx512m -XX:MaxPermSize=128m`. We try to cover this in
the `.mvn` configuration, so if you find you have to do it to make a
build succeed, please raise a ticket to get the settings added to
source control.
For hints on how to build the project look in `.travis.yml` if there
is one. There should be a "script" and maybe "install" command. Also
look at the "services" section to see if any services need to be
running locally (e.g. mongo or rabbit). Ignore the git-related bits
that you might find in "before_install" since they're related to setting git
credentials and you already have those.
The projects that require middleware generally include a
`docker-compose.yml`, so consider using
https://docs.docker.com/compose/[Docker Compose] to run the middeware servers
in Docker containers. See the README in the
https://github.com/spring-cloud-samples/scripts[scripts demo
repository] for specific instructions about the common cases of mongo,
rabbit and redis.
NOTE: If all else fails, build with the command from `.travis.yml` (usually
`./mvnw install`).
=== Documentation
The spring-cloud-build module has a "docs" profile, and if you switch
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
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
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.
==== 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".
NOTE: Older versions of m2e do not support Maven 3.3, so once the
projects are imported into Eclipse you will also need to tell
m2eclipse to use the right profile for the projects. If you
see many different errors related to the POMs in the projects, check
that you have an up to date installation. If you can't upgrade m2e,
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
If you prefer not to use m2eclipse you can generate eclipse project metadata using the
following command:
[indent=0]
----
$ ./mvnw eclipse:eclipse
----
The generated eclipse projects can be imported by selecting `import existing projects`
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
: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.
+56 -23
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>2.1.4.RELEASE</version>
<version>2.2.9.RELEASE</version>
</parent>
<artifactId>spring-cloud-netflix-docs</artifactId>
<packaging>pom</packaging>
@@ -13,45 +13,78 @@
<description>Spring Cloud Docs</description>
<properties>
<docs.main>spring-cloud-netflix</docs.main>
<docs.whitelisted.branches>1.2.x,1.3.x,1.4.x</docs.whitelisted.branches>
<main.basedir>${basedir}/..</main.basedir>
<configprops.inclusionPattern>
.*.eureka.*|.*.hystrix.*|.*.ribbon.*|.*.sidecar.*|.*.turbine.*|.*.zuul.*|.*.archaius.*
</configprops.inclusionPattern>
<upload-docs-zip.phase>deploy</upload-docs-zip.phase>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-cloud-starter-netflix-archaius</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-cloud-starter-netflix-turbine-stream</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
<profiles>
<profile>
<id>docs</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<inherited>false</inherited>
</plugin>
<plugin>
<groupId>com.agilejava.docbkx</groupId>
<artifactId>docbkx-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<inherited>false</inherited>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<inherited>false</inherited>
<artifactId>maven-deploy-plugin</artifactId>
</plugin>
</plugins>
</build>
+10 -4
View File
@@ -1,5 +1,7 @@
image::https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/master.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-netflix/tree/master"]
image::https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/master/graph/badge.svg["Codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-netflix/branch/master"]
include::_attributes.adoc[]
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"]
@@ -19,11 +21,15 @@ include::maintenance-mode.adoc[]
== Building
include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/building-jdk8.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/master/docs/src/main/asciidoc/contributing.adoc[]
include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/docs/src/main/asciidoc/contributing.adoc[]
== License
The project license file is available https://raw.githubusercontent.com/spring-cloud/spring-cloud-netflix/main/LICENSE.txt[here].
+15
View File
@@ -0,0 +1,15 @@
:doctype: book
:idprefix:
:idseparator: -
:toc: left
:toclevels: 4
:tabsize: 4
:numbered:
:sectanchors:
:sectnums:
:icons: font
:hide-uri-scheme:
:docinfo: shared,private
:sc-ext: java
:project-full-name: Spring Cloud Netflix
+27
View File
@@ -0,0 +1,27 @@
|===
|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 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-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` |
|management.endpoint.hystrix.config | | Hystrix settings. These are traditionally set using servlet parameters. Refer to the documentation of Hystrix for more details.
|management.endpoint.hystrix.stream.enabled | `true` | Whether to enable the hystrix.stream endpoint.
|management.metrics.binders.hystrix.enabled | `true` | Enables creation of OK Http Client factory beans.
|ribbon.eureka.enabled | `true` | Enables the use of Eureka with Ribbon.
|spring.cloud.circuitbreaker.hystrix.enabled | `true` | Enables auto-configuration of the Hystrix Spring Cloud CircuitBreaker API implementation.
|spring.cloud.loadbalancer.eureka.approximate-zone-from-hostname | `false` | Used to determine whether we should try to get the `zone` value from host name.
|spring.cloud.loadbalancer.ribbon.enabled | `true` | Causes `RibbonLoadBalancerClient` to be used by default.
|zuul.ribbon-isolation-strategy | |
|zuul.ribbon.eager-load.enabled | `false` | Enables eager loading of Ribbon clients on startup.
|===
+14
View File
@@ -0,0 +1,14 @@
:numbered!:
[appendix]
[[common-application-properties]]
== Common application properties
include::_attributes.adoc[]
Various properties can be specified inside your `application.properties` file, inside your `application.yml` file, or as command line switches.
This appendix provides a list of common {project-full-name} properties and references to the underlying classes that consume them.
NOTE: Property contributions can come from additional jar files on your classpath, so you should not consider this an exhaustive list.
Also, you can define your own properties.
include::_configprops.adoc[]
+5 -5
View File
@@ -39,7 +39,7 @@ function check_if_anything_to_sync() {
}
function retrieve_current_branch() {
# Code getting the name of the current branch. For master we want to publish as we did until now
# Code getting the name of the current branch. For main we want to publish as we did until now
# https://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch
# If there is a branch already passed will reuse it - otherwise will try to find it
CURRENT_BRANCH=${BRANCH}
@@ -134,8 +134,8 @@ function add_docs_from_target() {
# Copies the docs by using the retrieved properties from Maven build
function copy_docs_for_current_version() {
if [[ "${CURRENT_BRANCH}" == "master" ]] ; then
echo -e "Current branch is master - will copy the current docs only to the root folder"
if [[ "${CURRENT_BRANCH}" == "main" ]] ; then
echo -e "Current branch is main - will copy the current docs only to the root folder"
for f in docs/target/generated-docs/*; do
file=${f#docs/target/generated-docs/*}
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then
@@ -216,7 +216,7 @@ function commit_changes_if_applicable() {
git commit -a -m "Sync docs from ${CURRENT_BRANCH} to gh-pages" && COMMIT_SUCCESSFUL="yes" || echo "Failed to commit changes"
# Uncomment the following push if you want to auto push to
# the gh-pages branch whenever you commit to master locally.
# the gh-pages branch whenever you commit to main locally.
# This is a little extreme. Use with care!
###################################################################
if [[ "${COMMIT_SUCCESSFUL}" == "yes" ]] ; then
@@ -249,7 +249,7 @@ The idea of this script is to update gh-pages branch with the generated docs. Wi
the script will work in the following manner:
- if there's no gh-pages / target for docs module then the script ends
- for master branch the generated docs are copied to the root of gh-pages branch
- for main branch the generated docs are copied to the root of gh-pages branch
- for any other branch (if that branch is whitelisted) a subfolder with branch name is created
and docs are copied there
- if the version switch is passed (-v) then a tag with (v) prefix will be retrieved and a folder
+2
View File
@@ -1,3 +1,5 @@
include::_attributes.adoc[]
This project provides Netflix OSS integrations for Spring Boot apps through autoconfiguration
and binding to the Spring Environment and other Spring programming model idioms. With a few
simple annotations you can quickly enable and configure the common patterns inside your
+3 -1
View File
@@ -1,3 +1,4 @@
include::_attributes.adoc[]
== Modules In Maintenance Mode
@@ -10,6 +11,7 @@ of the Greenwich release train.
The following Spring Cloud Netflix modules and corresponding starters will be placed into maintenance mode:
* spring-cloud-netflix-archaius
* spring-cloud-netflix-concurrency-limits
* spring-cloud-netflix-hystrix-contract
* spring-cloud-netflix-hystrix-dashboard
* spring-cloud-netflix-hystrix-stream
@@ -19,5 +21,5 @@ The following Spring Cloud Netflix modules and corresponding starters will be pl
* spring-cloud-netflix-turbine
* spring-cloud-netflix-zuul
NOTE: This does not include the Eureka or concurrency-limits modules.
NOTE: This does not include the Eureka modules.
+55
View File
@@ -0,0 +1,55 @@
Spring Cloud Netflix provides Netflix OSS integrations for Spring Boot apps through autoconfiguration and binding to the Spring Environment and other Spring programming model idioms. With a few simple annotations you can quickly enable and configure the common patterns inside your application and build large distributed systems with battle-tested Netflix components. The patterns provided include Service Discovery (Eureka), Circuit Breaker (Hystrix), Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon)..
## Features
Spring Cloud Netflix features:
* Service Discovery: Eureka instances can be registered and clients can discover the instances using Spring-managed beans
* Service Discovery: an embedded Eureka server can be created with declarative Java configuration
* Circuit Breaker: Hystrix clients can be built with a simple annotation-driven method decorator
* Circuit Breaker: embedded Hystrix dashboard with declarative Java configuration
* Declarative REST Client: Feign creates a dynamic implementation of an interface decorated with JAX-RS or Spring MVC annotations
* Client Side Load Balancer: Ribbon
* External Configuration: a bridge from the Spring Environment to Archaius (enables native configuration of Netflix components using Spring Boot conventions)
* Router and Filter: automatic registration of Zuul filters, and a simple convention over configuration approach to reverse proxy creation
## Getting Started
As long as Spring Cloud Netflix and Eureka Core are on the
classpath any Spring Boot application with `@EnableEurekaClient` will try to contact a Eureka
server on `http://localhost:8761` (the default value of
`eureka.client.serviceUrl.defaultZone`):
```java
@SpringBootApplication
@EnableEurekaClient
@RestController
public class Application {
@RequestMapping("/")
public String home() {
return "Hello World";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
```
To run your own server use the `spring-cloud-starter-netflix-eureka-server` dependency and `@EnableEurekaServer`.
## Contributing
We welcome contributions. You can read more on how to contribute to the project https://github.com/spring-cloud/spring-cloud-netflix#contributing[here].
## Community Support
* You can report issues through https://github.com/spring-cloud/spring-cloud-netflix/issues[Github].
* We monitor https://stackoverflow.com/[StackOverflow] for questions with the `spring-cloud-netflix` tag.
* You can contact our team at https://gitter.im/spring-cloud/spring-cloud[Gitter].
## Commercial Support
Commercial Support is provided as part of the https://spring.io/support[VMware Spring Runtime] offering.
@@ -0,0 +1,70 @@
include::_attributes.adoc[]
=== Disabling Spring Cloud Circuit Breaker Hystrix
You can disable the auto-configuration by setting `spring.cloud.circuitbreaker.hystrix.enabled`
to `false`.
=== Configuring Hystrix Circuit Breakers
==== Default Configuration
To provide a default configuration for all of your circuit breakers create a `Customize` bean that is passed a
`HystrixCircuitBreakerFactory` or `ReactiveHystrixCircuitBreakerFactory`.
The `configureDefault` method can be used to provide a default configuration.
====
[source,java]
----
@Bean
public Customizer<HystrixCircuitBreakerFactory> defaultConfig() {
return factory -> factory.configureDefault(id -> HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(id))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withExecutionTimeoutInMilliseconds(4000)));
}
----
====
===== Reactive Example
====
[source,java]
----
@Bean
public Customizer<ReactiveHystrixCircuitBreakerFactory> defaultConfig() {
return factory -> factory.configureDefault(id -> HystrixObservableCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(id))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withExecutionTimeoutInMilliseconds(4000)));
}
----
====
==== Specific Circuit Breaker Configuration
Similarly to providing a default configuration, you can create a `Customize` bean this is passed a
`HystrixCircuitBreakerFactory`
====
[source,java]
----
@Bean
public Customizer<HystrixCircuitBreakerFactory> customizer() {
return factory -> factory.configure(builder -> builder.commandProperties(
HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(2000)), "foo", "bar");
}
----
====
===== Reactive Example
====
[source,java]
----
@Bean
public Customizer<ReactiveHystrixCircuitBreakerFactory> customizer() {
return factory -> factory.configure(builder -> builder.commandProperties(
HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(2000)), "foo", "bar");
}
----
====
+103 -21
View File
@@ -1,10 +1,14 @@
:github-tag: master
include::_attributes.adoc[]
:github-tag: main
:github-repo: spring-cloud/spring-cloud-netflix
:github-raw: https://raw.github.com/{github-repo}/{github-tag}
:github-code: https://github.com/{github-repo}/tree/{github-tag}
:all: {asterisk}{asterisk}
:nofooter:
:branch: master
:branch: main
= Spring Cloud Netflix
*{spring-cloud-version}*
@@ -63,7 +67,9 @@ eureka:
defaultZone: http://localhost:8761/eureka/
----
In the preceding example, "defaultZone" is a magic string fallback value that provides the service URL for any client that does not express a preference (in other words, it is a useful default).
In the preceding example, `defaultZone` is a magic string fallback value that provides the service URL for any client that does not express a preference (in other words, it is a useful default).
WARNING: The `defaultZone` property is case sensitive and requires camel case because the `serviceUrl` property is a `Map<String, String>`. Therefore, the `defaultZone` property does not follow the normal Spring Boot snake-case convention of `default-zone`.
The default application name (that is, the service ID), virtual host, and non-secure port (taken from the `Environment`) are `${spring.application.name}`, `${spring.application.name}` and `${server.port}`, respectively.
@@ -76,11 +82,31 @@ To disable the Eureka Discovery Client, you can set `eureka.client.enabled` to `
=== 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: `http://user:password@localhost:8761/eureka`).
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`).
For more complex needs, you can create a `@Bean` of type `DiscoveryClientOptionalArgs` and inject `ClientFilter` instances into it, all of which is applied to the calls from the client to the server.
NOTE: Because of a limitation in Eureka, it is not possible to support per-server basic auth credentials, so only the first set that are found is used.
When Eureka server requires client side certificate for authentication, the client side certificate and trust store can be configured via properties, as shown in following example:
.application.yml
[source,yaml]
----
eureka:
client:
tls:
enabled: true
key-store: <path-of-key-store>
key-store-type: PKCS12
key-store-password: <key-store-password>
key-password: <key-password>
trust-store: <path-of-trust-store>
trust-store-type: PKCS12
trust-store-password: <trust-store-password>
----
The `eureka.client.tls.enabled` needs to be true to enable Eureka client side TLS. When `eureka.client.tls.trust-store` is omitted, a JVM default trust store is used. The default value for `eureka.client.tls.key-store-type` and `eureka.client.tls.trust-store-type` is PKCS12. When password properties are omitted, empty password is assumed.
=== 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.
@@ -200,7 +226,7 @@ public EurekaInstanceConfigBean eurekaInstanceConfig(InetUtils inetUtils) {
A vanilla Netflix Eureka instance is registered with an ID that is equal to its host name (that is, there is only one service per host).
Spring Cloud Eureka provides a sensible default, which is defined as follows:
`${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}}`
`${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}`
An example is `myhost:myappname:8080`.
@@ -331,6 +357,18 @@ When a refresh occurs clients will be unregistered from the Eureka server and th
where all instance of a given service are not available. One way to eliminate this from happening is to disable
the ability to refresh Eureka clients. To do this set `eureka.client.refresh.enable=false`.
=== Using Eureka with Spring Cloud LoadBalancer
We offer support for the Spring Cloud LoadBalancer `ZonePreferenceServiceInstanceListSupplier`.
The `zone` value from the Eureka instance metadata (`eureka.instance.metadataMap.zone`) is used for setting the
value of `spring-clod-loadbalancer-zone` property that is used to filter service instances by zone.
If that is missing and if the `spring.cloud.loadbalancer.eureka.approximateZoneFromHostname` flag is set to `true`,
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).
[[spring-cloud-eureka-server]]
== Service Discovery: Eureka Server
@@ -450,7 +488,7 @@ eureka:
hostname: peer1
client:
serviceUrl:
defaultZone: http://peer2/eureka/
defaultZone: https://peer2/eureka/
---
spring:
@@ -460,7 +498,7 @@ eureka:
hostname: peer2
client:
serviceUrl:
defaultZone: http://peer1/eureka/
defaultZone: https://peer1/eureka/
----
In the preceding example, we have a YAML file that can be used to run the same server on two hosts (`peer1` and `peer2`) by running it in different Spring profiles.
@@ -479,7 +517,7 @@ the registrations amongst themselves.
eureka:
client:
serviceUrl:
defaultZone: http://peer1/eureka/,http://peer2/eureka/,http://peer3/eureka/
defaultZone: https://peer1/eureka/,http://peer2/eureka/,http://peer3/eureka/
---
spring:
@@ -541,6 +579,34 @@ For more information on CSRF see the https://docs.spring.io/spring-security/site
A demo Eureka Server can be found in the Spring Cloud Samples https://github.com/spring-cloud-samples/eureka/tree/Eureka-With-Security[repo].
=== Disabling Ribbon with Eureka Server and Client starters
`spring-cloud-starter-netflix-eureka-server` and `spring-cloud-starter-netflix-eureka-client` come along with
a `spring-cloud-starter-netflix-ribbon`. Since Ribbon load-balancer is now in maintenance mode,
we suggest switching to using the Spring Cloud LoadBalancer, also included in Eureka starters, instead.
In order to that, you can set the value of `spring.cloud.loadbalancer.ribbon.enabled` property to `false`.
You can then also exclude ribbon-related dependencies from Eureka starters in your build files, like so:
[source,xml,indent=0]
----
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</exclusion>
<exclusion>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-eureka</artifactId>
</exclusion>
</exclusions>
</dependency>
----
=== JDK 11 Support
The JAXB modules which the Eureka server depends upon were removed in JDK 11. If you intend to use JDK 11
@@ -554,6 +620,10 @@ when running a Eureka server you must include these dependencies in your POM or
</dependency>
----
== Circuit Breaker: Spring Cloud Circuit Breaker With Hystrix
include::spring-cloud-circuitbreaker-hystrix.adoc[]
== Circuit Breaker: Hystrix Clients
Netflix has created a library called https://github.com/Netflix/Hystrix[Hystrix] that implements the https://martinfowler.com/bliki/CircuitBreaker.html[circuit breaker pattern].
@@ -703,6 +773,10 @@ Then visit `/hystrix` and point the dashboard to an individual instance's `/hyst
NOTE: When connecting to a `/hystrix.stream` endpoint that uses HTTPS, the certificate used by the server must be trusted by the JVM.
If the certificate is not trusted, you must import the certificate into the JVM in order for the Hystrix Dashboard to make a successful connection to the stream endpoint.
NOTE: In order to use the `/proxy.stream` endpoint you must configure a list of hosts to allow connections to. To set the
list of allowed hosts use `hystrix.dashboard.proxyStreamAllowList`. You can use an Ant-style pattern in the host name to
match against a wider range of host names.
=== Turbine
Looking at an individual instance's Hystrix data is not very useful in terms of the overall health of the system. https://github.com/Netflix/Turbine[Turbine] is an application that aggregates all of the relevant `/hystrix.stream` endpoints into a combined `/turbine.stream` for use in the Hystrix Dashboard.
@@ -806,7 +880,7 @@ The Turbine Stream server requires the use of Spring Webflux, therefore `spring-
By default `spring-boot-starter-webflux` is included when adding `spring-cloud-starter-netflix-turbine-stream` to your application.
You can then point the Hystrix Dashboard to the Turbine Stream Server instead of individual Hystrix streams.
If Turbine Stream is running on port 8989 on myhost, then put `http://myhost:8989` in the stream input field in the Hystrix Dashboard.
If Turbine Stream is running on port 8989 on myhost, then put `https://myhost:8989` in the stream input field in the Hystrix Dashboard.
Circuits are prefixed by their respective `serviceId`, followed by a dot (`.`), and then the circuit name.
Spring Cloud provides a `spring-cloud-starter-netflix-turbine-stream` that has all the dependencies you need to get a Turbine Stream server running.
@@ -866,7 +940,7 @@ public class TestConfiguration {
In this case, the client is composed from the components already in `RibbonClientConfiguration`, together with any in `CustomConfiguration` (where the latter generally overrides the former).
// TODO "generally"? We should link to the rules that dictate this behavior.
WARNING: The `CustomConfiguration` clas must be a `@Configuration` class, but take care that it is not in a `@ComponentScan` for the main application context.
WARNING: The `CustomConfiguration` class must be a `@Configuration` class, but take care that it is not in a `@ComponentScan` for the main application context.
Otherwise, it is shared by all the `@RibbonClients`. If you use `@ComponentScan` (or `@SpringBootApplication`), you need to take steps to avoid it being included (for instance, you can put it in a separate, non-overlapping package or specify the packages to scan explicitly in the `@ComponentScan`).
The following table shows the beans that Spring Cloud Netflix provides by default for Ribbon:
@@ -888,7 +962,7 @@ Creating a bean of one of those type and placing it in a `@RibbonClient` configu
[source,java,indent=0]
----
include::../../../../spring-cloud-netflix-ribbon/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonClientsPreprocessorIntegrationTests.java[tags=sample_override_ribbon_config,indent=0]
include::{project-root}/spring-cloud-netflix-ribbon/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonClientsPreprocessorIntegrationTests.java[tags=sample_override_ribbon_config,indent=0]
----
The include statement in the preceding example replaces `NoOpPing` with `PingUrl` and provides a custom `serverListFilter`.
@@ -899,7 +973,7 @@ A default configuration can be provided for all Ribbon Clients by using the `@Ri
[source,java,indent=0]
----
include::../../../../spring-cloud-netflix-ribbon/src/test/java/org/springframework/cloud/netflix/ribbon/test/RibbonClientDefaultConfigurationTestsConfig.java[tags=sample_default_ribbon_config,indent=0]
include::{project-root}/spring-cloud-netflix-ribbon/src/test/java/org/springframework/cloud/netflix/ribbon/test/RibbonClientDefaultConfigurationTestsConfig.java[tags=sample_default_ribbon_config,indent=0]
----
@@ -987,7 +1061,7 @@ public class MyClass {
public void doStuff() {
ServiceInstance instance = loadBalancer.choose("stores");
URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
URI storesUri = URI.create(String.format("https://%s:%s", instance.getHost(), instance.getPort()));
// ... do something with the URI
}
}
@@ -1326,7 +1400,7 @@ path, rendering the `users` path unreachable.
The default HTTP client used by Zuul is now backed by the Apache HTTP Client instead of the deprecated Ribbon `RestClient`.
To use `RestClient` or `okhttp3.OkHttpClient`, set `ribbon.restclient.enabled=true` or `ribbon.okhttp.enabled=true`, respectively.
If you would like to customize the Apache HTTP client or the OK HTTP client, provide a bean of type `ClosableHttpClient` or `OkHttpClient`.
If you would like to customize the Apache HTTP client or the OK HTTP client, provide a bean of type `CloseableHttpClient` or `OkHttpClient`.
=== Cookies and Sensitive Headers
@@ -1546,7 +1620,7 @@ The following example maps all paths in "/api/{all}" to the Zuul filter chain:
=== Disable Zuul Filters
Zuul for Spring Cloud comes with a number of `ZuulFilter` beans enabled by default in both proxy and server mode.
See https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters[the Zuul filters package] for the list of filters that you can enable.
See https://github.com/spring-cloud/spring-cloud-netflix/tree/main/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters[the Zuul filters package] for the list of filters that you can enable.
If you want to disable one, set `zuul.<SimpleClassName>.<filterType>.disable=true`.
By convention, the package after `filters` is the Zuul filter type.
For example to disable `org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter`, set `zuul.SendResponseFilter.post.disable=true`.
@@ -1751,7 +1825,7 @@ This path can be changed with the `zuul.servlet-path` property.
To pass information between filters, Zuul uses a https://github.com/Netflix/zuul/blob/1.x/zuul-core/src/main/java/com/netflix/zuul/context/RequestContext.java[`RequestContext`].
Its data is held in a `ThreadLocal` specific to each request.
Information about where to route requests, errors, and the actual `HttpServletRequest` and `HttpServletResponse` are stored there.
The `RequestContext` extends `ConcurrentHashMap`, so anything can be stored in the context. https://github.com/spring-cloud/spring-cloud-netflix/blob/master/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/support/FilterConstants.java[`FilterConstants`] contains the keys used by the filters installed by Spring Cloud Netflix (more on these <<zuul-developer-guide-enable-filters,later>>).
The `RequestContext` extends `ConcurrentHashMap`, so anything can be stored in the context. https://github.com/spring-cloud/spring-cloud-netflix/blob/main/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/support/FilterConstants.java[`FilterConstants`] contains the keys used by the filters installed by Spring Cloud Netflix (more on these <<zuul-developer-guide-enable-filters,later>>).
==== `@EnableZuulProxy` vs. `@EnableZuulServer`
@@ -1768,7 +1842,7 @@ The following filters are installed (as normal Spring Beans):
** `ServletDetectionFilter`: Detects whether the request is through the Spring Dispatcher. Sets a boolean with a key of `FilterConstants.IS_DISPATCHER_SERVLET_REQUEST_KEY`.
** `FormBodyWrapperFilter`: Parses form data and re-encodes it for downstream requests.
** `DebugFilter`: If the `debug` request parameter is set, sets `RequestContext.setDebugRouting()` and `RequestContext.setDebugRequest()` to `true`.
*Route filters:
* Route filters:
** `SendForwardFilter`: Forwards requests by using the Servlet `RequestDispatcher`. The forwarding location is stored in the `RequestContext` attribute, `FilterConstants.FORWARD_TO_KEY`. This is useful for forwarding to endpoints in the current application.
* Post filters:
** `SendResponseFilter`: Writes responses from proxied requests to the current response.
@@ -2050,14 +2124,14 @@ The following example response for `/hosts/customers` returns two instances on d
{
"host": "myhost",
"port": 9000,
"uri": "http://myhost:9000",
"uri": "https://myhost:9000",
"serviceId": "CUSTOMERS",
"secure": false
},
{
"host": "myhost2",
"port": 9000,
"uri": "http://myhost2:9000",
"uri": "https://myhost2:9000",
"serviceId": "CUSTOMERS",
"secure": false
}
@@ -2129,6 +2203,8 @@ See the https://github.com/Netflix/ribbon/wiki/Getting-Started#the-properties-fi
WARNING: Enabling `client.ribbon.OkToRetryOnAllOperations` includes retrying POST requests, which can have an impact
on the server's resources, due to the buffering of the request body.
CAUTION: The property names are case-sensitive, and since some of these properties are defined in the Netflix Ribbon project, they are in Pascal Case and the ones from Spring Cloud are in Camel Case.
In addition, you may want to retry requests when certain status codes are returned in the response.
You can list the response codes you would like the Ribbon client to retry by setting the `clientName.ribbon.retryableStatusCodes` property, as shown in the following example:
@@ -2152,8 +2228,8 @@ You can also disable retry functionality on a route-by-route basis by setting `z
Spring Cloud Netflix automatically creates the HTTP client used by Ribbon, Feign, and Zuul for you.
However, you can also provide your own HTTP clients customized as you need them to be.
To do so, you can create a bean of type `ClosableHttpClient` if you
are using the Apache Http Cient or `OkHttpClient` if you are using OK HTTP.
To do so, you can create a bean of type `CloseableHttpClient` if you
are using the Apache HTTP Client or `OkHttpClient` if you are using OK HTTP.
NOTE: When you create your own HTTP client, you are also responsible for implementing the correct connection management strategies for these clients.
Doing so improperly can result in resource management issues.
@@ -2161,3 +2237,9 @@ Doing so improperly can result in resource management issues.
include::maintenance-mode.adoc[]
== Configuration properties
To see the list of all Spring Cloud Netflix related configuration properties please check link:appendix.html[the Appendix page].
Vendored
+1 -1
View File
@@ -7,7 +7,7 @@
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
+12 -18
View File
@@ -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>2.1.4.RELEASE</version>
<version>2.2.9.RELEASE</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>2.1.9.RELEASE</version>
<version>2.3.5.RELEASE</version>
<relativePath />
</parent>
<scm>
@@ -21,27 +21,25 @@
</scm>
<properties>
<bintray.package>netflix</bintray.package>
<spring-cloud-commons.version>2.1.4.RELEASE</spring-cloud-commons.version>
<spring-cloud-config.version>2.1.5.RELEASE</spring-cloud-config.version>
<spring-cloud-stream.version>Fishtown.SR4</spring-cloud-stream.version>
<spring-cloud-commons.version>2.2.9.RELEASE</spring-cloud-commons.version>
<spring-cloud-config.version>2.2.8.RELEASE</spring-cloud-config.version>
<spring-cloud-stream.version>Horsham.SR13</spring-cloud-stream.version>
<!-- Has to be a stable version (not one that depends on this version of netflix): -->
<donotreplacespring-cloud-contract.version>2.1.3.RELEASE</donotreplacespring-cloud-contract.version>
<donotreplacespring-cloud-contract.version>2.2.4.RELEASE</donotreplacespring-cloud-contract.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>
<maven-checkstyle-plugin.includeTestSourceDirectory>true
</maven-checkstyle-plugin.includeTestSourceDirectory>
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError>
<maven-checkstyle-plugin.failOnViolation>true
</maven-checkstyle-plugin.failOnViolation>
<eureka-jersey.version>1.19.1</eureka-jersey.version>
<xstream.version>1.4.11.1</xstream.version>
<eureka-jersey.version>1.19.4</eureka-jersey.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
@@ -171,11 +169,6 @@
<artifactId>jersey-apache-client4</artifactId>
<version>${eureka-jersey.version}</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>${xstream.version}</version>
</dependency>
<!-- end eureka deps -->
</dependencies>
</dependencyManagement>
@@ -205,6 +198,7 @@
<module>spring-cloud-netflix-ribbon</module>
<module>spring-cloud-starter-netflix</module>
<module>spring-cloud-netflix-hystrix</module>
<module>spring-cloud-netflix-eureka-client-tls-tests</module>
<module>docs</module>
</modules>
<profiles>
+2
View File
@@ -1,4 +1,6 @@
#!/bin/bash
set -o errexit
(cd spring-cloud-netflix-hystrix-contract && ../mvnw clean install -B -Pdocs ${@})
./mvnw clean install -B -Pdocs ${@}
+2
View File
@@ -1,4 +1,6 @@
#!/bin/bash
set -o errexit
(cd spring-cloud-netflix-hystrix-contract && ../mvnw clean install -B -Pdocs -DskipTests)
./mvnw clean install -B -Pdocs -DskipTests -fae
+2 -2
View File
@@ -4,7 +4,7 @@ set -o errexit
mkdir -p target
SCRIPT_URL="https://raw.githubusercontent.com/spring-cloud-samples/brewery/master/runAcceptanceTests.sh"
SCRIPT_URL="https://raw.githubusercontent.com/spring-cloud-samples/brewery/main/runAcceptanceTests.sh"
AT_WHAT_TO_TEST="EUREKA"
cd target
@@ -18,7 +18,7 @@ echo "Killing all running apps"
./runAcceptanceTests.sh -t "${AT_WHAT_TO_TEST}" --killattheend
SCRIPT_URL="https://raw.githubusercontent.com/spring-cloud-samples/tests/master/scripts/runTests.sh"
SCRIPT_URL="https://raw.githubusercontent.com/spring-cloud-samples/tests/main/scripts/runTests.sh"
curl "${SCRIPT_URL}" --output runIntegrationTests.sh
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<artifactId>spring-cloud-netflix</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>2.1.4.RELEASE</version>
<version>2.2.9.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -41,7 +41,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -51,6 +51,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
@@ -65,8 +66,10 @@ import static com.netflix.config.ConfigurationManager.URL_CONFIG_NAME;
/**
* @author Spencer Gibb
* @author Liang Yong
*/
@Configuration
@Lazy(false)
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ ConcurrentCompositeConfiguration.class,
ConfigurationBuilder.class })
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@@ -194,20 +197,21 @@ public class ArchaiusAutoConfiguration {
ReflectionUtils.setField(field, null, value);
}
@Configuration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Health.class)
protected static class ArchaiusEndpointConfiguration {
@Bean
@ConditionalOnEnabledEndpoint
@ConditionalOnAvailableEndpoint
protected ArchaiusEndpoint archaiusEndpoint() {
return new ArchaiusEndpoint();
}
}
@Configuration
@ConditionalOnProperty(value = "archaius.propagate.environmentChangedEvent", matchIfMissing = true)
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "archaius.propagate.environmentChangedEvent",
matchIfMissing = true)
@ConditionalOnClass(EnvironmentChangeEvent.class)
protected static class PropagateEventsConfiguration
implements ApplicationListener<EnvironmentChangeEvent> {
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -0,0 +1,50 @@
/*
* Copyright 2013-2020 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.archaius;
import com.netflix.config.DynamicProperty;
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Liang Yong
*/
@SpringBootTest(classes = LazyLoadConfigurationTests.TestConfig.class,
properties = { "client.ribbon.listOfServers=foo.com,bar.com",
"spring.main.lazy-initialization=true" })
public class LazyLoadConfigurationTests {
@Test
public void enableLazyInitialization() {
DynamicProperty instance = DynamicProperty
.getInstance("client.ribbon.listOfServers");
assertThat(instance.getString()).isEqualTo("foo.com,bar.com");
}
@SpringBootConfiguration
@EnableAutoConfiguration
static class TestConfig {
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -26,7 +26,7 @@ import org.springframework.context.annotation.Configuration;
/**
* @author Alexandru-George Burghelea
*/
@Configuration
@Configuration(proxyBeanMethods = false)
public class TestArchaiusExternalConfiguration {
@Bean
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>2.1.4.RELEASE</version>
<version>2.2.9.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-concurrency-limits</artifactId>
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -27,7 +27,9 @@ import io.micrometer.core.instrument.Tags;
* A Micrometer-specific {@link MetricRegistry} implementation.
*
* @author Spencer Gibb
* @deprecated to be removed in 3.0.0
*/
@Deprecated
public class MicrometerMetricRegistry implements MetricRegistry {
private final MeterRegistry meterRegistry;
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -29,7 +29,9 @@ import org.springframework.web.server.WebFilterChain;
* {@link Limiter} to handle requests.
*
* @author Spencer Gibb
* @deprecated to be removed in 3.0.0
*/
@Deprecated
public class ConcurrencyLimitsWebFilter implements WebFilter {
private final Limiter<ServerWebExchange> limiter;
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -35,8 +35,10 @@ import org.springframework.web.server.WebFilter;
* Reactive autoconfiguration class for registering Netflix {@link Limiter} bean.
*
* @author Spencer Gibb
* @deprecated to be removed in 3.0.0
*/
@Configuration
@Deprecated
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.REACTIVE)
@ConditionalOnClass({ WebFilter.class, Mono.class })
public class ReactiveConcurrencyLimitsAutoConfiguration {
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -27,7 +27,9 @@ import org.springframework.web.server.ServerWebExchange;
* Builder for ServerWebExchange Limiter.
*
* @author Spencer Gibb
* @deprecated to be removed in 3.0.0
*/
@Deprecated
public class ServerWebExchangeLimiterBuilder extends
AbstractPartitionedLimiter.Builder<ServerWebExchangeLimiterBuilder, ServerWebExchange> {
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -34,7 +34,9 @@ import org.springframework.web.servlet.ModelAndView;
* {@link Limiter} to handle requests.
*
* @author Spencer Gibb
* @deprecated to be removed in 3.0.0
*/
@Deprecated
public class ConcurrencyLimitsHandlerInterceptor implements HandlerInterceptor {
private final Limiter<HttpServletRequest> limiter;
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -39,10 +39,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
* MVC autoconfiguration class for registering Netflix {@link Limiter} bean.
*
* @author Spencer Gibb
* @deprecated to be removed in 3.0.0
*/
@Configuration
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ HttpServletRequest.class, HandlerInterceptor.class })
@Deprecated
public class MvcConcurrencyLimitsAutoConfiguration implements WebMvcConfigurer {
private final ObjectProvider<Consumer<ServletLimiterBuilder>> configurerProvider;
@@ -62,7 +64,7 @@ public class MvcConcurrencyLimitsAutoConfiguration implements WebMvcConfigurer {
return builder.build();
}
@Configuration
@Configuration(proxyBeanMethods = false)
protected static class HandlerInterceptorConfiguration implements WebMvcConfigurer {
@Autowired
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -66,7 +66,7 @@ public class AbstractConcurrencyLimitsTests {
}
@Configuration
@Configuration(proxyBeanMethods = false)
@RestController
protected static class HelloControllerConfiguration {
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -37,7 +37,8 @@ import org.springframework.web.reactive.function.client.WebClient;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@RunWith(SpringRunner.class)
@SpringBootTest(properties = "logging.level.reactor.netty=DEBUG", webEnvironment = RANDOM_PORT)
@SpringBootTest(properties = "logging.level.reactor.netty=DEBUG",
webEnvironment = RANDOM_PORT)
public class ConcurrencyLimitsHandlerInterceptorTests
extends AbstractConcurrencyLimitsTests {
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>2.1.4.RELEASE</version>
<version>2.2.9.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-core</artifactId>
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2019 the original author or authors.
* Copyright 2018-2020 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.
@@ -27,7 +27,7 @@ import org.springframework.context.annotation.Configuration;
* @deprecated Module spring-cloud-netflix-core is deprecated as of 2.1.0, use
* spring-cloud-netflix-hystrix instead.
*/
@Configuration
@Configuration(proxyBeanMethods = false)
@Deprecated
public class CoreAutoConfiguration {
+8 -18
View File
@@ -5,20 +5,20 @@
<parent>
<artifactId>spring-cloud-dependencies-parent</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>2.1.9.RELEASE</version>
<version>2.3.5.RELEASE</version>
<relativePath/>
</parent>
<artifactId>spring-cloud-netflix-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<version>2.2.9.RELEASE</version>
<packaging>pom</packaging>
<name>spring-cloud-netflix-dependencies</name>
<description>Spring Cloud Netflix Dependencies</description>
<properties>
<archaius.version>0.7.6</archaius.version>
<archaius.version>0.7.7</archaius.version>
<concurrency-limits.version>0.1.12</concurrency-limits.version>
<eureka.version>1.9.13</eureka.version>
<eureka.version>1.10.14</eureka.version>
<eventbus.version>0.3.0</eventbus.version>
<hystrix.version>1.5.18</hystrix.version>
<okhttp3.version>3.8.1</okhttp3.version>
<ribbon.version>2.3.0</ribbon.version>
<servo.version>0.12.21</servo.version>
<zuul.version>1.3.1</zuul.version>
@@ -56,11 +56,6 @@
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-contract</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
@@ -370,14 +365,9 @@
</exclusions>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp3.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
<version>${okhttp3.version}</version>
<groupId>com.netflix.netflix-commons</groupId>
<artifactId>netflix-eventbus</artifactId>
<version>${eventbus.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
@@ -0,0 +1,103 @@
<?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"
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>2.2.9.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-eureka-client-tls-tests</artifactId>
<packaging>jar</packaging>
<name>Spring Cloud Netflix Eureka Client TLS Tests</name>
<description>Spring Cloud Netflix Eureka Client TLS Tests</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.68</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,125 @@
/*
* Copyright 2018-2019 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.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.SocketUtils;
public class AppRunner implements AutoCloseable {
private Class<?> appClass;
private Map<String, String> props;
private ConfigurableApplicationContext app;
public AppRunner(Class<?> appClass) {
this.appClass = appClass;
props = new LinkedHashMap<>();
}
public void property(String key, String value) {
props.put(key, value);
}
public void start() {
if (app == null) {
SpringApplicationBuilder builder = new SpringApplicationBuilder(appClass);
builder.properties("spring.jmx.enabled=false");
builder.properties(String.format("server.port=%d", availabeTcpPort()));
builder.properties(props());
app = builder.build().run();
}
}
private int availabeTcpPort() {
return SocketUtils.findAvailableTcpPort();
}
private String[] props() {
List<String> result = new ArrayList<>();
for (String key : props.keySet()) {
String value = props.get(key);
result.add(String.format("%s=%s", key, value));
}
return result.toArray(new String[0]);
}
public void stop() {
if (app != null) {
app.stop();
app = null;
}
}
public ConfigurableApplicationContext app() {
return app;
}
public String getProperty(String key) {
return app.getEnvironment().getProperty(key);
}
public <T> T getBean(Class<T> type) {
return app.getBean(type);
}
public ApplicationContext parent() {
return app.getParent();
}
public <T> Map<String, T> getParentBeans(Class<T> type) {
return parent().getBeansOfType(type);
}
public int port() {
if (app == null) {
throw new RuntimeException("App is not running.");
}
return app.getEnvironment().getProperty("server.port", Integer.class, -1);
}
public String root() {
if (app == null) {
throw new RuntimeException("App is not running.");
}
String protocol = tlsEnabled() ? "https" : "http";
return String.format("%s://localhost:%d/", protocol, port());
}
private boolean tlsEnabled() {
return app.getEnvironment().getProperty("server.ssl.enabled", Boolean.class,
false);
}
@Override
public void close() {
stop();
}
}
@@ -0,0 +1,93 @@
/*
* Copyright 2018-2019 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.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import org.junit.BeforeClass;
public abstract class BaseCertTest {
protected static final String KEY_STORE_PASSWORD = "test-key-store-password";
protected static final String KEY_PASSWORD = "test-key-password";
protected static final String WRONG_PASSWORD = "test-wrong-password";
protected static File caCert;
protected static File wrongCaCert;
protected static File serverCert;
protected static File clientCert;
protected static File wrongClientCert;
protected BaseCertTest() {
}
@BeforeClass
public static void createCertificates() throws Exception {
KeyTool tool = new KeyTool();
KeyAndCert ca = tool.createCA("MyCA");
KeyAndCert server = ca.sign("server");
KeyAndCert client = ca.sign("client");
caCert = saveCert(ca);
serverCert = saveKeyAndCert(server);
clientCert = saveKeyAndCert(client);
KeyAndCert wrongCa = tool.createCA("WrongCA");
KeyAndCert wrongClient = wrongCa.sign("client");
wrongCaCert = saveCert(wrongCa);
wrongClientCert = saveKeyAndCert(wrongClient);
}
private static File saveKeyAndCert(KeyAndCert keyCert) throws Exception {
return saveKeyStore(keyCert.subject(),
() -> keyCert.storeKeyAndCert(KEY_PASSWORD));
}
private static File saveCert(KeyAndCert keyCert) throws Exception {
return saveKeyStore(keyCert.subject(), () -> keyCert.storeCert());
}
private static File saveKeyStore(String prefix, KeyStoreSupplier func)
throws Exception {
File result = File.createTempFile(prefix, ".p12");
result.deleteOnExit();
try (OutputStream output = new FileOutputStream(result)) {
KeyStore store = func.createKeyStore();
store.store(output, KEY_STORE_PASSWORD.toCharArray());
}
return result;
}
interface KeyStoreSupplier {
KeyStore createKeyStore() throws Exception;
}
}
@@ -0,0 +1,99 @@
/*
* Copyright 2018-2019 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.io.File;
import java.util.function.BooleanSupplier;
import org.springframework.cloud.client.discovery.DiscoveryClient;
public class EurekaClientRunner extends AppRunner {
public EurekaClientRunner(Class<?> appClass, AppRunner server) {
super(appClass);
property("eureka.client.registerWithEureka", "false");
property("eureka.client.fetchRegistry", "true");
property("eureka.client.serviceUrl.defaultZone", server.root() + "eureka/");
property("eureka.client.refresh.enable", "true");
}
public EurekaClientRunner(Class<?> appClass, AppRunner server, String service) {
this(appClass, server);
property("eureka.client.registerWithEureka", "true");
property("spring.application.name", service);
}
public void enableTls() {
property("eureka.client.tls.enabled", "true");
}
public void disableTls() {
property("eureka.client.tls.enabled", "false");
}
public void setKeyStore(File keyStore, String keyStorePassword, String keyPassword) {
property("eureka.client.tls.key-store", pathOf(keyStore));
property("eureka.client.tls.key-store-password", keyStorePassword);
property("eureka.client.tls.key-password", keyPassword);
}
public void setKeyStore(File keyStore) {
property("eureka.client.tls.key-store", pathOf(keyStore));
}
public void setTrustStore(File trustStore, String password) {
property("eureka.client.tls.trust-store", pathOf(trustStore));
property("eureka.client.tls.trust-store-password", password);
}
public void setTrustStore(File trustStore) {
property("eureka.client.tls.trust-store", pathOf(trustStore));
}
private String pathOf(File file) {
return String.format("file:%s", file.getAbsolutePath());
}
public void waitServiceViaEureka(int seconds) {
assertInSeconds(() -> foundServiceViaEureka(), seconds);
}
private void assertInSeconds(BooleanSupplier assertion, int seconds) {
long start = System.currentTimeMillis();
long limit = 1000L * seconds;
long duration = 0;
do {
if (assertion.getAsBoolean()) {
return;
}
duration = System.currentTimeMillis() - start;
Thread.yield();
}
while (duration < limit);
throw new RuntimeException();
}
public boolean foundServiceViaEureka() {
DiscoveryClient discovery = getBean(DiscoveryClient.class);
return !discovery.getServices().isEmpty();
}
}
@@ -0,0 +1,158 @@
/*
* Copyright 2018-2019 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.io.File;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import static org.assertj.core.api.Assertions.assertThat;
public class EurekaClientTest extends BaseCertTest {
private static EurekaServerRunner server;
private static EurekaClientRunner service;
@BeforeClass
public static void setupAll() {
startEurekaServer();
startService();
waitForRegistration();
}
@AfterClass
public static void tearDownAll() {
stopService();
stopEurekaServer();
}
private static void startEurekaServer() {
server = new EurekaServerRunner(TestEurekaServer.class);
server.enableTls();
server.setKeyStore(serverCert, KEY_STORE_PASSWORD, "server", KEY_PASSWORD);
server.setTrustStore(caCert, KEY_STORE_PASSWORD);
server.start();
}
private static void stopEurekaServer() {
server.stop();
}
private static void startService() {
service = new EurekaClientRunner(TestApp.class, server, "testservice");
enableTlsClient(service);
service.start();
}
private static void stopService() {
service.stop();
}
private static void waitForRegistration() {
try (EurekaClientRunner client = createEurekaClient()) {
enableTlsClient(client);
client.start();
client.waitServiceViaEureka(60);
}
}
private static EurekaClientRunner createEurekaClient() {
return new EurekaClientRunner(TestApp.class, server);
}
private static void enableTlsClient(EurekaClientRunner runner) {
runner.enableTls();
runner.setKeyStore(clientCert, KEY_STORE_PASSWORD, KEY_PASSWORD);
runner.setTrustStore(caCert, KEY_STORE_PASSWORD);
}
/**
* Already proved this in waitForRegistration(). Keep this Test to express test
* purpose explicitly.
*/
@Test
public void clientCertCanWork() {
}
@Test
public void noCertCannotWork() {
try (EurekaClientRunner client = createEurekaClient()) {
client.disableTls();
client.start();
assertThat(client.foundServiceViaEureka()).isFalse();
}
}
@Test
public void wrongCertCannotWork() {
try (EurekaClientRunner client = createEurekaClient()) {
enableTlsClient(client);
client.setKeyStore(wrongClientCert);
client.start();
assertThat(client.foundServiceViaEureka()).isFalse();
}
}
@Test(expected = BeanCreationException.class)
public void wrongPasswordCauseFailure() {
EurekaClientRunner client = createEurekaClient();
enableTlsClient(client);
client.setKeyStore(clientCert, WRONG_PASSWORD, WRONG_PASSWORD);
client.start();
}
@Test(expected = BeanCreationException.class)
public void nonExistKeyStoreCauseFailure() {
EurekaClientRunner client = createEurekaClient();
enableTlsClient(client);
client.setKeyStore(new File("nonExistFile"));
client.start();
}
@Test
public void wrongTrustStoreCannotWork() {
try (EurekaClientRunner client = createEurekaClient()) {
enableTlsClient(client);
client.setTrustStore(wrongCaCert);
client.start();
assertThat(client.foundServiceViaEureka()).isFalse();
}
}
@SpringBootConfiguration
@EnableAutoConfiguration
public static class TestApp {
}
@SpringBootConfiguration
@EnableAutoConfiguration
@EnableEurekaServer
public static class TestEurekaServer {
}
}
@@ -0,0 +1,56 @@
/*
* Copyright 2018-2019 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.io.File;
public class EurekaServerRunner extends AppRunner {
public EurekaServerRunner(Class<?> appClass) {
super(appClass);
property("eureka.client.registerWithEureka", "false");
property("eureka.client.fetchRegistry", "false");
property("eureka.server.waitTimeInMsWhenSyncEmpty", "0");
property("eureka.client.refresh.enable", "true");
}
public void enableTls() {
property("server.ssl.enabled", "true");
property("server.ssl.client-auth", "need");
}
public void setKeyStore(File keyStore, String keyStorePassword, String key,
String keyPassword) {
property("server.ssl.key-store", pathOf(keyStore));
property("server.ssl.key-store-type", "PKCS12");
property("server.ssl.key-store-password", keyStorePassword);
property("server.ssl.key-alias", key);
property("server.ssl.key-password", keyPassword);
}
public void setTrustStore(File trustStore, String password) {
property("server.ssl.trust-store", pathOf(trustStore));
property("server.ssl.trust-store-type", "PKCS12");
property("server.ssl.trust-store-password", password);
}
private String pathOf(File file) {
return String.format("file:%s", file.getAbsolutePath());
}
}
@@ -0,0 +1,94 @@
/*
* Copyright 2018-2019 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.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
public class KeyAndCert {
private KeyPair keyPair;
private X509Certificate certificate;
public KeyAndCert(KeyPair keyPair, X509Certificate certificate) {
this.keyPair = keyPair;
this.certificate = certificate;
}
public KeyPair keyPair() {
return keyPair;
}
public PublicKey publicKey() {
return keyPair.getPublic();
}
public PrivateKey privateKey() {
return keyPair.getPrivate();
}
public X509Certificate certificate() {
return certificate;
}
public String subject() {
String dn = certificate.getSubjectDN().getName();
int index = dn.indexOf('=');
return dn.substring(index + 1);
}
public KeyAndCert sign(String subject) throws Exception {
KeyTool tool = new KeyTool();
return tool.signCertificate(subject, this);
}
public KeyAndCert sign(KeyPair keyPair, String subject) throws Exception {
KeyTool tool = new KeyTool();
return tool.signCertificate(keyPair, subject, this);
}
public KeyStore storeKeyAndCert(String keyPassword) throws Exception {
KeyStore result = KeyStore.getInstance("PKCS12");
result.load(null);
result.setKeyEntry(subject(), keyPair.getPrivate(), keyPassword.toCharArray(),
certChain());
return result;
}
private Certificate[] certChain() {
return new Certificate[] { certificate() };
}
public KeyStore storeCert() throws Exception {
return storeCert("PKCS12");
}
public KeyStore storeCert(String storeType) throws Exception {
KeyStore result = KeyStore.getInstance(storeType);
result.load(null);
result.setCertificateEntry(subject(), certificate());
return result;
}
}
@@ -0,0 +1,126 @@
/*
* Copyright 2018-2019 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.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Date;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
public class KeyTool {
private static final long ONE_DAY = 1000L * 60L * 60L * 24L;
private static final long TEN_YEARS = ONE_DAY * 365L * 10L;
public KeyAndCert createCA(String ca) throws Exception {
KeyPair keyPair = createKeyPair();
X509Certificate certificate = createCert(keyPair, ca);
return new KeyAndCert(keyPair, certificate);
}
public KeyAndCert signCertificate(String subject, KeyAndCert signer)
throws Exception {
return signCertificate(createKeyPair(), subject, signer);
}
public KeyAndCert signCertificate(KeyPair keyPair, String subject, KeyAndCert signer)
throws Exception {
X509Certificate certificate = createCert(keyPair.getPublic(), signer.privateKey(),
signer.subject(), subject);
KeyAndCert result = new KeyAndCert(keyPair, certificate);
return result;
}
public KeyPair createKeyPair() throws Exception {
return createKeyPair(1024);
}
public KeyPair createKeyPair(int keySize) throws Exception {
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
gen.initialize(keySize, new SecureRandom());
return gen.generateKeyPair();
}
public X509Certificate createCert(KeyPair keyPair, String ca) throws Exception {
JcaX509v3CertificateBuilder builder = certBuilder(keyPair.getPublic(), ca, ca);
builder.addExtension(Extension.keyUsage, true,
new KeyUsage(KeyUsage.keyCertSign));
builder.addExtension(Extension.basicConstraints, false,
new BasicConstraints(true));
return signCert(builder, keyPair.getPrivate());
}
public X509Certificate createCert(PublicKey publicKey, PrivateKey privateKey,
String issuer, String subject) throws Exception {
JcaX509v3CertificateBuilder builder = certBuilder(publicKey, issuer, subject);
builder.addExtension(Extension.keyUsage, true,
new KeyUsage(KeyUsage.digitalSignature));
builder.addExtension(Extension.basicConstraints, false,
new BasicConstraints(false));
GeneralName[] names = new GeneralName[] {
new GeneralName(GeneralName.dNSName, "localhost") };
builder.addExtension(Extension.subjectAlternativeName, false,
GeneralNames.getInstance(new DERSequence(names)));
return signCert(builder, privateKey);
}
private JcaX509v3CertificateBuilder certBuilder(PublicKey publicKey, String issuer,
String subject) {
X500Name issuerName = new X500Name(String.format("dc=%s", issuer));
X500Name subjectName = new X500Name(String.format("dc=%s", subject));
long now = System.currentTimeMillis();
BigInteger serialNum = BigInteger.valueOf(now);
Date notBefore = new Date(now - ONE_DAY);
Date notAfter = new Date(now + TEN_YEARS);
return new JcaX509v3CertificateBuilder(issuerName, serialNum, notBefore, notAfter,
subjectName, publicKey);
}
private X509Certificate signCert(JcaX509v3CertificateBuilder builder,
PrivateKey privateKey) throws Exception {
ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA")
.build(privateKey);
X509CertificateHolder holder = builder.build(signer);
return new JcaX509CertificateConverter().getCertificate(holder);
}
}
+21 -6
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>2.1.4.RELEASE</version>
<version>2.2.9.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
@@ -27,6 +27,11 @@
<artifactId>spring-boot-starter-actuator</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix</artifactId>
@@ -46,6 +51,11 @@
<artifactId>spring-cloud-config-server</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.eureka</groupId>
<artifactId>eureka-client</artifactId>
@@ -62,11 +72,6 @@
<optional>true</optional>
</dependency>
<!-- Eureka core deps that are now optional -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-apache-client4</artifactId>
@@ -82,6 +87,11 @@
<artifactId>ribbon</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.netflix-commons</groupId>
<artifactId>netflix-eventbus</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-core</artifactId>
@@ -127,5 +137,10 @@
<artifactId>spring-retry</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -50,13 +50,11 @@ import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.cloud.client.CommonsClientAutoConfiguration;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.client.actuator.HasFeatures;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration;
import org.springframework.cloud.netflix.eureka.metadata.DefaultManagementMetadataProvider;
import org.springframework.cloud.netflix.eureka.metadata.ManagementMetadata;
import org.springframework.cloud.netflix.eureka.metadata.ManagementMetadataProvider;
@@ -68,7 +66,6 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.StringUtils;
@@ -83,17 +80,17 @@ import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceI
* @author Ryan Baxter
* @author Daniel Lavoie
* @author Olga Maciaszek-Sharma
* @author Tim Ysewyn
*/
@Configuration
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnClass(EurekaClientConfig.class)
@Import(DiscoveryClientOptionalArgsConfiguration.class)
@ConditionalOnBean(EurekaDiscoveryClientConfiguration.Marker.class)
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
@ConditionalOnDiscoveryEnabled
@AutoConfigureBefore({ NoopDiscoveryClientAutoConfiguration.class,
CommonsClientAutoConfiguration.class, ServiceRegistryAutoConfiguration.class })
@AutoConfigureAfter(name = {
"org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration",
"org.springframework.cloud.autoconfigure.RefreshAutoConfiguration",
"org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration",
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration" })
@@ -111,15 +108,10 @@ public class EurekaClientAutoConfiguration {
}
@Bean
@ConditionalOnMissingBean(value = EurekaClientConfig.class, search = SearchStrategy.CURRENT)
@ConditionalOnMissingBean(value = EurekaClientConfig.class,
search = SearchStrategy.CURRENT)
public EurekaClientConfigBean eurekaClientConfigBean(ConfigurableEnvironment env) {
EurekaClientConfigBean client = new EurekaClientConfigBean();
if ("bootstrap".equals(this.env.getProperty("spring.config.name"))) {
// We don't register during bootstrap by default, but there will be another
// chance later.
client.setRegisterWithEureka(false);
}
return client;
return new EurekaClientConfigBean();
}
@Bean
@@ -133,7 +125,8 @@ public class EurekaClientAutoConfiguration {
}
@Bean
@ConditionalOnMissingBean(value = EurekaInstanceConfig.class, search = SearchStrategy.CURRENT)
@ConditionalOnMissingBean(value = EurekaInstanceConfig.class,
search = SearchStrategy.CURRENT)
public EurekaInstanceConfigBean eurekaInstanceConfigBean(InetUtils inetUtils,
ManagementMetadataProvider managementMetadataProvider) {
String hostname = getProperty("eureka.instance.hostname");
@@ -215,12 +208,6 @@ public class EurekaClientAutoConfiguration {
}
}
@Bean
public DiscoveryClient discoveryClient(EurekaClient client,
EurekaClientConfig clientConfig) {
return new EurekaDiscoveryClient(client, clientConfig);
}
@Bean
public EurekaServiceRegistry eurekaServiceRegistry() {
return new EurekaServiceRegistry();
@@ -242,14 +229,16 @@ public class EurekaClientAutoConfiguration {
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@ConditionalOnProperty(
value = "spring.cloud.service-registry.auto-registration.enabled",
matchIfMissing = true)
public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(
ApplicationContext context, EurekaServiceRegistry registry,
EurekaRegistration registration) {
return new EurekaAutoServiceRegistration(context, registry, registration);
}
@Configuration
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingRefreshScope
protected static class EurekaClientConfiguration {
@@ -260,7 +249,8 @@ public class EurekaClientAutoConfiguration {
private AbstractDiscoveryClientOptionalArgs<?> optionalArgs;
@Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
@ConditionalOnMissingBean(value = EurekaClient.class,
search = SearchStrategy.CURRENT)
public EurekaClient eurekaClient(ApplicationInfoManager manager,
EurekaClientConfig config) {
return new CloudEurekaClient(manager, config, this.optionalArgs,
@@ -268,7 +258,8 @@ public class EurekaClientAutoConfiguration {
}
@Bean
@ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)
@ConditionalOnMissingBean(value = ApplicationInfoManager.class,
search = SearchStrategy.CURRENT)
public ApplicationInfoManager eurekaApplicationInfoManager(
EurekaInstanceConfig config) {
InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
@@ -277,18 +268,20 @@ public class EurekaClientAutoConfiguration {
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@ConditionalOnProperty(
value = "spring.cloud.service-registry.auto-registration.enabled",
matchIfMissing = true)
public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient,
CloudEurekaInstanceConfig instanceConfig,
ApplicationInfoManager applicationInfoManager,
@Autowired(required = false) ObjectProvider<HealthCheckHandler> healthCheckHandler) {
ApplicationInfoManager applicationInfoManager, @Autowired(
required = false) ObjectProvider<HealthCheckHandler> healthCheckHandler) {
return EurekaRegistration.builder(instanceConfig).with(applicationInfoManager)
.with(eurekaClient).with(healthCheckHandler).build();
}
}
@Configuration
@Configuration(proxyBeanMethods = false)
@ConditionalOnRefreshScope
protected static class RefreshableEurekaClientConfiguration {
@@ -299,7 +292,8 @@ public class EurekaClientAutoConfiguration {
private AbstractDiscoveryClientOptionalArgs<?> optionalArgs;
@Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
@ConditionalOnMissingBean(value = EurekaClient.class,
search = SearchStrategy.CURRENT)
@org.springframework.cloud.context.config.annotation.RefreshScope
@Lazy
public EurekaClient eurekaClient(ApplicationInfoManager manager,
@@ -326,7 +320,8 @@ public class EurekaClientAutoConfiguration {
}
@Bean
@ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)
@ConditionalOnMissingBean(value = ApplicationInfoManager.class,
search = SearchStrategy.CURRENT)
@org.springframework.cloud.context.config.annotation.RefreshScope
@Lazy
public ApplicationInfoManager eurekaApplicationInfoManager(
@@ -338,11 +333,13 @@ public class EurekaClientAutoConfiguration {
@Bean
@org.springframework.cloud.context.config.annotation.RefreshScope
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@ConditionalOnProperty(
value = "spring.cloud.service-registry.auto-registration.enabled",
matchIfMissing = true)
public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient,
CloudEurekaInstanceConfig instanceConfig,
ApplicationInfoManager applicationInfoManager,
@Autowired(required = false) ObjectProvider<HealthCheckHandler> healthCheckHandler) {
ApplicationInfoManager applicationInfoManager, @Autowired(
required = false) ObjectProvider<HealthCheckHandler> healthCheckHandler) {
return EurekaRegistration.builder(instanceConfig).with(applicationInfoManager)
.with(eurekaClient).with(healthCheckHandler).build();
}
@@ -362,7 +359,8 @@ public class EurekaClientAutoConfiguration {
@Documented
@ConditionalOnClass(RefreshScope.class)
@ConditionalOnBean(RefreshAutoConfiguration.class)
@ConditionalOnProperty(value = "eureka.client.refresh.enable", havingValue = "true", matchIfMissing = true)
@ConditionalOnProperty(value = "eureka.client.refresh.enable", havingValue = "true",
matchIfMissing = true)
@interface ConditionalOnRefreshScope {
}
@@ -383,14 +381,15 @@ public class EurekaClientAutoConfiguration {
}
@ConditionalOnProperty(value = "eureka.client.refresh.enable", havingValue = "false")
@ConditionalOnProperty(value = "eureka.client.refresh.enable",
havingValue = "false")
static class OnPropertyDisabled {
}
}
@Configuration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Health.class)
protected static class EurekaHealthIndicatorConfiguration {
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1086,7 +1086,7 @@ public class EurekaClientConfigBean implements EurekaClientConfig, Ordered {
.append(decoderName).append("', ").append("clientDataAccept='")
.append(clientDataAccept).append("', ")
.append("shouldUnregisterOnShutdown='").append(shouldUnregisterOnShutdown)
.append("', ").append("shouldEnforceRegistrationAtInit='")
.append("shouldEnforceRegistrationAtInit='")
.append(shouldEnforceRegistrationAtInit).append("', ").append("order='")
.append(order).append("'}").toString();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -16,11 +16,9 @@
package org.springframework.cloud.netflix.eureka;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.InstanceInfo;
@@ -29,13 +27,9 @@ import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
import static com.netflix.appinfo.InstanceInfo.PortType.SECURE;
/**
* A {@link DiscoveryClient} implementation for Eureka.
@@ -106,58 +100,19 @@ public class EurekaDiscoveryClient implements DiscoveryClient {
}
/**
* An Eureka-specific {@link ServiceInstance} implementation.
* An Eureka-specific {@link ServiceInstance} implementation. Extends
* {@link org.springframework.cloud.netflix.eureka.EurekaServiceInstance} for
* backwards compatibility.
*
* @deprecated In favor of
* {@link org.springframework.cloud.netflix.eureka.EurekaServiceInstance}.
*/
public static class EurekaServiceInstance implements ServiceInstance {
private InstanceInfo instance;
@Deprecated
public static class EurekaServiceInstance
extends org.springframework.cloud.netflix.eureka.EurekaServiceInstance {
public EurekaServiceInstance(InstanceInfo instance) {
Assert.notNull(instance, "Service instance required");
this.instance = instance;
}
public InstanceInfo getInstanceInfo() {
return instance;
}
@Override
public String getInstanceId() {
return this.instance.getId();
}
@Override
public String getServiceId() {
return this.instance.getAppName();
}
@Override
public String getHost() {
return this.instance.getHostName();
}
@Override
public int getPort() {
if (isSecure()) {
return this.instance.getSecurePort();
}
return this.instance.getPort();
}
@Override
public boolean isSecure() {
// assume if secure is enabled, that is the default
return this.instance.isPortEnabled(SECURE);
}
@Override
public URI getUri() {
return DefaultServiceInstance.getUri(this);
}
@Override
public Map<String, String> getMetadata() {
return this.instance.getMetadata();
super(instance);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -21,12 +21,13 @@ import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.HealthAggregator;
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
import org.springframework.boot.actuate.health.SimpleStatusAggregator;
import org.springframework.boot.actuate.health.StatusAggregator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent;
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration;
@@ -40,39 +41,61 @@ import org.springframework.context.annotation.Configuration;
* @author Jon Schneider
* @author Jakub Narloch
* @author Olga Maciaszek-Sharma
* @author Tim Ysewyn
*/
@Configuration
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnClass(EurekaClientConfig.class)
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
@ConditionalOnDiscoveryEnabled
@ConditionalOnBlockingDiscoveryEnabled
public class EurekaDiscoveryClientConfiguration {
/**
* Deprecated in favor of auto configuration order.
* @return Marker bean
* @deprecated in favor of auto configuration order.
*/
@Deprecated
@Bean
public Marker eurekaDiscoverClientMarker() {
return new Marker();
}
@Configuration
@ConditionalOnProperty(value = "eureka.client.healthcheck.enabled", matchIfMissing = false)
@Bean
@ConditionalOnMissingBean
public EurekaDiscoveryClient discoveryClient(EurekaClient client,
EurekaClientConfig clientConfig) {
return new EurekaDiscoveryClient(client, clientConfig);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "eureka.client.healthcheck.enabled",
matchIfMissing = false)
protected static class EurekaHealthCheckHandlerConfiguration {
@Autowired(required = false)
private HealthAggregator healthAggregator = new OrderedHealthAggregator();
private StatusAggregator statusAggregator = new SimpleStatusAggregator();
@Bean
@ConditionalOnMissingBean(HealthCheckHandler.class)
public EurekaHealthCheckHandler eurekaHealthCheckHandler() {
return new EurekaHealthCheckHandler(this.healthAggregator);
return new EurekaHealthCheckHandler(this.statusAggregator);
}
}
/**
* Deprecated in favor of auto configuration order.
*
* @deprecated in favor of auto configuration order.
*/
@Deprecated
class Marker {
}
@Configuration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RefreshScopeRefreshedEvent.class)
protected static class EurekaClientConfigurationRefresher
implements ApplicationListener<RefreshScopeRefreshedEvent> {
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2021 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.
@@ -17,24 +17,36 @@
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.CompositeHealthIndicator;
import org.springframework.boot.actuate.health.DefaultHealthIndicatorRegistry;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthAggregator;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.HealthIndicatorRegistryFactory;
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
import org.springframework.boot.actuate.health.Status;
import org.springframework.boot.actuate.health.StatusAggregator;
import org.springframework.cloud.client.discovery.health.DiscoveryCompositeHealthContributor;
import org.springframework.cloud.client.discovery.health.DiscoveryCompositeHealthIndicator;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.Lifecycle;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
import static com.netflix.appinfo.InstanceInfo.InstanceStatus;
/**
* A Eureka health checker, maps the application status into {@link InstanceStatus} that
* will be propagated to Eureka registry.
@@ -43,12 +55,20 @@ import static com.netflix.appinfo.InstanceInfo.InstanceStatus;
* {@link HealthCheckHandler}. By default this implementation will perform aggregation of
* all registered {@link HealthIndicator} through registered {@link HealthAggregator}.
*
* A {@code null} status is returned when the application context is closed (or in the
* process of being closed). This prevents Eureka from updating the health status and only
* consider the status present in the current InstanceInfo.
*
* @author Jakub Narloch
* @author Spencer Gibb
* @author Nowrin Anwar Joyita
* @author Bertrand Renuart
* @see HealthCheckHandler
* @see StatusAggregator
* @see HealthAggregator
*/
public class EurekaHealthCheckHandler
implements HealthCheckHandler, ApplicationContextAware, InitializingBean {
public class EurekaHealthCheckHandler implements HealthCheckHandler,
ApplicationContextAware, InitializingBean, Ordered, Lifecycle {
private static final Map<Status, InstanceInfo.InstanceStatus> STATUS_MAPPING = new HashMap<Status, InstanceInfo.InstanceStatus>() {
{
@@ -59,13 +79,41 @@ public class EurekaHealthCheckHandler
}
};
private final CompositeHealthIndicator healthIndicator;
private StatusAggregator statusAggregator;
private ApplicationContext applicationContext;
/**
* {@code true} until the context is stopped.
*/
private boolean running = true;
private Map<String, HealthIndicator> healthIndicators;
private Map<String, ReactiveHealthIndicator> reactiveHealthIndicators = new HashMap<>();
@Deprecated
private CompositeHealthIndicator healthIndicator;
@Deprecated
private HealthIndicatorRegistryFactory healthIndicatorRegistryFactory;
@Deprecated
private HealthAggregator healthAggregator;
@Deprecated
public EurekaHealthCheckHandler(HealthAggregator healthAggregator) {
Assert.notNull(healthAggregator, "HealthAggregator must not be null");
this.healthIndicator = new CompositeHealthIndicator(healthAggregator);
this.healthAggregator = healthAggregator;
healthIndicatorRegistryFactory = new HealthIndicatorRegistryFactory();
healthIndicator = new CompositeHealthIndicator(this.healthAggregator,
new DefaultHealthIndicatorRegistry());
}
public EurekaHealthCheckHandler(StatusAggregator statusAggregator) {
this.statusAggregator = statusAggregator;
Assert.notNull(statusAggregator, "StatusAggregator must not be null");
}
@Override
@@ -78,7 +126,22 @@ public class EurekaHealthCheckHandler
public void afterPropertiesSet() throws Exception {
final Map<String, HealthIndicator> healthIndicators = applicationContext
.getBeansOfType(HealthIndicator.class);
this.healthIndicators = new HashMap<>();
final Map<String, ReactiveHealthIndicator> reactiveHealthIndicators = applicationContext
.getBeansOfType(ReactiveHealthIndicator.class);
if (statusAggregator != null) {
populateHealthIndicators(healthIndicators);
populateReactiveHealthIndicators(reactiveHealthIndicators);
}
else {
createHealthIndicator(healthIndicators);
}
}
@Deprecated
void createHealthIndicator(Map<String, HealthIndicator> healthIndicators) {
for (Map.Entry<String, HealthIndicator> entry : healthIndicators.entrySet()) {
// ignore EurekaHealthIndicator and flatten the rest of the composite
@@ -89,28 +152,101 @@ public class EurekaHealthCheckHandler
for (DiscoveryCompositeHealthIndicator.Holder holder : indicator
.getHealthIndicators()) {
if (!(holder.getDelegate() instanceof EurekaHealthIndicator)) {
healthIndicator.addHealthIndicator(holder.getDelegate().getName(),
holder);
this.healthIndicators.put(holder.getDelegate().getName(), holder);
}
}
}
else {
healthIndicator.addHealthIndicator(entry.getKey(), entry.getValue());
this.healthIndicators.put(entry.getKey(), entry.getValue());
}
}
healthIndicator = new CompositeHealthIndicator(healthAggregator,
healthIndicatorRegistryFactory
.createHealthIndicatorRegistry(this.healthIndicators));
}
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) {
DiscoveryCompositeHealthContributor indicator = (DiscoveryCompositeHealthContributor) entry
.getValue();
indicator.forEach(contributor -> {
if (!(contributor
.getContributor() instanceof EurekaHealthIndicator)) {
this.healthIndicators.put(contributor.getName(),
(HealthIndicator) contributor.getContributor());
}
});
}
else {
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) {
return getHealthStatus();
if (running) {
return getHealthStatus();
}
else {
// Return nothing if the context is not running, so the status held by the
// InstanceInfo remains unchanged.
// See gh-1571
return null;
}
}
protected InstanceStatus getHealthStatus() {
final Status status = getHealthIndicator().health().getStatus();
final Status status;
if (statusAggregator != null) {
status = getStatus(statusAggregator);
}
else {
status = getStatus(getHealthIndicator());
}
return mapToInstanceStatus(status);
}
@Deprecated
private Status getStatus(CompositeHealthIndicator healthIndicator) {
Status status;
status = healthIndicator.health().getStatus();
return status;
}
protected Status getStatus(StatusAggregator statusAggregator) {
Status status;
Set<Status> statusSet = new HashSet<>();
if (healthIndicators != null) {
statusSet.addAll(
healthIndicators.values().stream().map(HealthIndicator::health)
.map(Health::getStatus).collect(Collectors.toSet()));
}
if (reactiveHealthIndicators != null) {
statusSet.addAll(reactiveHealthIndicators.values().stream()
.map(ReactiveHealthIndicator::health).map(Mono::block)
.filter(Objects::nonNull).map(Health::getStatus)
.collect(Collectors.toSet()));
}
status = statusAggregator.getAggregateStatus(statusSet);
return status;
}
protected InstanceStatus mapToInstanceStatus(Status status) {
if (!STATUS_MAPPING.containsKey(status)) {
return InstanceStatus.UNKNOWN;
@@ -118,8 +254,34 @@ public class EurekaHealthCheckHandler
return STATUS_MAPPING.get(status);
}
@Deprecated
protected CompositeHealthIndicator getHealthIndicator() {
return healthIndicator;
}
@Override
public int getOrder() {
// registered with a high order priority so the close() method is invoked early
// and *BEFORE* EurekaAutoServiceRegistration
// (must be in effect when the registration is closed and the eureka replication
// triggered -> health check handler is
// consulted at that moment)
return Ordered.HIGHEST_PRECEDENCE;
}
@Override
public void start() {
running = true;
}
@Override
public void stop() {
running = false;
}
@Override
public boolean isRunning() {
return true;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -266,7 +266,7 @@ public class EurekaInstanceConfigBean
/**
* Flag to say that, when guessing a hostname, the IP address of the server should be
* used in prference to the hostname reported by the OS.
* used in preference to the hostname reported by the OS.
*/
private boolean preferIpAddress = false;
@@ -0,0 +1,120 @@
/*
* Copyright 2013-2020 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.net.URI;
import java.util.Map;
import java.util.Objects;
import com.netflix.appinfo.InstanceInfo;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.core.style.ToStringCreator;
import org.springframework.util.Assert;
import static com.netflix.appinfo.InstanceInfo.PortType.SECURE;
/**
* An Eureka-specific {@link ServiceInstance} implementation.
*
* @author Spencer Gibb
* @author Dave Syer
* @author Olga Maciaszek-Sharma
* @author Tim Ysewyn
*/
public class EurekaServiceInstance implements ServiceInstance {
private InstanceInfo instance;
public EurekaServiceInstance(InstanceInfo instance) {
Assert.notNull(instance, "Service instance required");
this.instance = instance;
}
public InstanceInfo getInstanceInfo() {
return instance;
}
@Override
public String getInstanceId() {
return this.instance.getId();
}
@Override
public String getServiceId() {
return this.instance.getAppName();
}
@Override
public String getHost() {
return this.instance.getHostName();
}
@Override
public int getPort() {
if (isSecure()) {
return this.instance.getSecurePort();
}
return this.instance.getPort();
}
@Override
public boolean isSecure() {
// assume if secure is enabled, that is the default
return this.instance.isPortEnabled(SECURE);
}
@Override
public URI getUri() {
return DefaultServiceInstance.getUri(this);
}
@Override
public Map<String, String> getMetadata() {
return this.instance.getMetadata();
}
@Override
public String getScheme() {
return getUri().getScheme();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EurekaServiceInstance that = (EurekaServiceInstance) o;
return Objects.equals(this.instance, that.instance);
}
@Override
public int hashCode() {
return Objects.hash(this.instance);
}
@Override
public String toString() {
return new ToStringCreator(this).append("instance", instance).toString();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2019 the original author or authors.
* Copyright 2017-2020 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.
@@ -16,35 +16,119 @@
package org.springframework.cloud.netflix.eureka.config;
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
import java.io.IOException;
import java.security.GeneralSecurityException;
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
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.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.cloud.configuration.SSLContextFactory;
import org.springframework.cloud.configuration.TlsProperties;
import org.springframework.cloud.netflix.eureka.MutableDiscoveryClientOptionalArgs;
import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs;
import org.springframework.cloud.netflix.eureka.http.WebClientDiscoveryClientOptionalArgs;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
/**
* @author Daniel Lavoie
*/
@Configuration
@Configuration(proxyBeanMethods = false)
public class DiscoveryClientOptionalArgsConfiguration {
protected static final Log logger = LogFactory
.getLog(DiscoveryClientOptionalArgsConfiguration.class);
@Bean
@ConfigurationProperties("eureka.client.tls")
public TlsProperties tlsProperties() {
return new TlsProperties();
}
@Bean
@ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter")
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs() {
return new RestTemplateDiscoveryClientOptionalArgs();
@ConditionalOnMissingBean(value = { AbstractDiscoveryClientOptionalArgs.class },
search = SearchStrategy.CURRENT)
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
matchIfMissing = true, havingValue = "false")
public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs(
TlsProperties tlsProperties) throws GeneralSecurityException, IOException {
logger.info("Eureka HTTP Client uses RestTemplate.");
RestTemplateDiscoveryClientOptionalArgs result = new RestTemplateDiscoveryClientOptionalArgs();
setupTLS(result, tlsProperties);
return result;
}
@Bean
@ConditionalOnClass(name = "com.sun.jersey.api.client.filter.ClientFilter")
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
public MutableDiscoveryClientOptionalArgs discoveryClientOptionalArgs() {
return new MutableDiscoveryClientOptionalArgs();
@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) throws GeneralSecurityException, IOException {
if (properties.isEnabled()) {
SSLContextFactory factory = new SSLContextFactory(properties);
args.setSSLContext(factory.createSSLContext());
}
}
@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 {
@Autowired
private TlsProperties tlsProperties;
@Bean
@ConditionalOnMissingBean(
value = { AbstractDiscoveryClientOptionalArgs.class,
RestTemplateDiscoveryClientOptionalArgs.class },
search = SearchStrategy.CURRENT)
public WebClientDiscoveryClientOptionalArgs webClientDiscoveryClientOptionalArgs(
ObjectProvider<WebClient.Builder> builder)
throws GeneralSecurityException, IOException {
logger.info("Eureka HTTP Client uses WebClient.");
WebClientDiscoveryClientOptionalArgs result = new WebClientDiscoveryClientOptionalArgs(
builder::getIfAvailable);
setupTLS(result, tlsProperties);
return result;
}
}
@Configuration
@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 {
public WebClientNotFoundConfiguration() {
throw new IllegalStateException("eureka.client.webclient.enabled is true, "
+ "but WebClient is not on the classpath. Please add "
+ "spring-boot-starter-webflux as a dependency.");
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2020 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.
@@ -34,7 +34,7 @@ import org.springframework.util.StringUtils;
*
* @author Dave Syer
*/
@Configuration
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnClass({ EurekaInstanceConfigBean.class, EurekaClient.class,
ConfigServerProperties.class })
@@ -0,0 +1,187 @@
/*
* Copyright 2013-2020 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.ArrayList;
import java.util.List;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.endpoint.EndpointUtils;
import com.netflix.discovery.shared.Applications;
import com.netflix.discovery.shared.resolver.DefaultEndpoint;
import com.netflix.discovery.shared.transport.EurekaHttpClient;
import com.netflix.discovery.shared.transport.EurekaHttpResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.config.client.ConfigServerInstanceProvider;
import org.springframework.cloud.config.client.ConfigServicePropertySourceLocator;
import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean;
import org.springframework.cloud.netflix.eureka.EurekaServiceInstance;
import org.springframework.cloud.netflix.eureka.http.RestTemplateEurekaHttpClient;
import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClientFactory;
import org.springframework.cloud.netflix.eureka.http.WebClientEurekaHttpClient;
import org.springframework.cloud.netflix.eureka.http.WebClientTransportClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
/**
* Bootstrap configuration for config client that wants to lookup the config server via
* discovery.
*
* @author Dave Syer
*/
@ConditionalOnClass(ConfigServicePropertySourceLocator.class)
@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled",
matchIfMissing = false)
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
public class EurekaConfigServerBootstrapConfiguration {
private static final Log log = LogFactory
.getLog(EurekaConfigServerBootstrapConfiguration.class);
@Bean
@ConditionalOnMissingBean(value = EurekaClientConfig.class,
search = SearchStrategy.CURRENT)
public EurekaClientConfigBean eurekaClientConfigBean() {
return new EurekaClientConfigBean();
}
@Bean
@ConditionalOnMissingBean(EurekaHttpClient.class)
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
matchIfMissing = true, havingValue = "false")
public RestTemplateEurekaHttpClient configDiscoveryRestTemplateEurekaHttpClient(
EurekaClientConfigBean config, Environment env) {
return (RestTemplateEurekaHttpClient) new RestTemplateTransportClientFactory()
.newClient(new DefaultEndpoint(getEurekaUrl(config, env)));
}
private static String getEurekaUrl(EurekaClientConfigBean config, Environment env) {
List<String> urls = EndpointUtils.getDiscoveryServiceUrls(config,
EurekaClientConfigBean.DEFAULT_ZONE, new HostnameBasedUrlRandomizer(
env.getProperty("eureka.instance.hostname")));
return urls.get(0);
}
private boolean isSuccessful(EurekaHttpResponse<Applications> response) {
HttpStatus httpStatus = HttpStatus.resolve(response.getStatusCode());
return httpStatus != null && httpStatus.is2xxSuccessful();
}
@Bean
public ConfigServerInstanceProvider.Function eurekaConfigServerInstanceProvider(
EurekaHttpClient client, EurekaClientConfig config) {
return serviceId -> {
if (log.isDebugEnabled()) {
log.debug("eurekaConfigServerInstanceProvider finding instances for "
+ serviceId);
}
EurekaHttpResponse<Applications> response = client
.getApplications(config.getRegion());
List<ServiceInstance> instances = new ArrayList<>();
if (!isSuccessful(response) || response.getEntity() == null) {
return instances;
}
Applications applications = response.getEntity();
applications.shuffleInstances(config.shouldFilterOnlyUpInstances());
List<InstanceInfo> infos = applications
.getInstancesByVirtualHostName(serviceId);
for (InstanceInfo info : infos) {
instances.add(new EurekaServiceInstance(info));
}
if (log.isDebugEnabled()) {
log.debug("eurekaConfigServerInstanceProvider found " + infos.size()
+ " instance(s) for " + serviceId + ", " + instances);
}
return instances;
};
}
private static final class HostnameBasedUrlRandomizer
implements EndpointUtils.ServiceUrlRandomizer {
private final String hostname;
private HostnameBasedUrlRandomizer(String hostname) {
this.hostname = hostname;
}
@Override
public void randomize(List<String> urlList) {
int listSize = 0;
if (urlList != null) {
listSize = urlList.size();
}
if (!StringUtils.hasText(hostname) || listSize == 0) {
return;
}
// Find the hashcode of the instance hostname and use it to find an entry
// and then arrange the rest of the entries after this entry.
int instanceHashcode = hostname.hashCode();
if (instanceHashcode < 0) {
instanceHashcode = instanceHashcode * -1;
}
int backupInstance = instanceHashcode % listSize;
for (int i = 0; i < backupInstance; i++) {
String zone = urlList.remove(0);
urlList.add(zone);
}
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(
name = "org.springframework.web.reactive.function.client.WebClient")
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
havingValue = "true")
@ImportAutoConfiguration({ CodecsAutoConfiguration.class,
WebClientAutoConfiguration.class })
protected static class WebClientConfiguration {
@Bean
@ConditionalOnMissingBean(EurekaHttpClient.class)
public WebClientEurekaHttpClient configDiscoveryWebClientEurekaHttpClient(
EurekaClientConfigBean config, ObjectProvider<WebClient.Builder> builder,
Environment env) {
return (WebClientEurekaHttpClient) new WebClientTransportClientFactory(
builder::getIfAvailable)
.newClient(new DefaultEndpoint(getEurekaUrl(config, env)));
}
}
}
@@ -1,55 +0,0 @@
/*
* Copyright 2013-2019 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 javax.annotation.PostConstruct;
import com.netflix.discovery.EurekaClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Bootstrap configuration for a config client that wants to lookup the config server via
* discovery.
*
* @author Dave Syer
*/
@ConditionalOnBean({ EurekaDiscoveryClientConfiguration.class })
@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false)
public class EurekaDiscoveryClientConfigServiceAutoConfiguration {
@Autowired
private ConfigurableApplicationContext context;
@PostConstruct
public void init() {
if (this.context.getParent() != null) {
if (this.context.getBeanNamesForType(EurekaClient.class).length > 0
&& this.context.getParent()
.getBeanNamesForType(EurekaClient.class).length > 0) {
// If the parent has a EurekaClient as well it should be shutdown, so the
// local one can register accurate instance info
this.context.getParent().getBean(EurekaClient.class).shutdown();
}
}
}
}
@@ -1,43 +0,0 @@
/*
* Copyright 2013-2019 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 org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.config.client.ConfigServicePropertySourceLocator;
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Eureka-specific helper for config client that wants to lookup the config server via
* discovery.
*
* @author Dave Syer
*/
@ConditionalOnClass(ConfigServicePropertySourceLocator.class)
@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false)
@Configuration
@Import({ EurekaDiscoveryClientConfiguration.class, // this emulates
// @EnableDiscoveryClient, the import
// selector doesn't run before the
// bootstrap phase
EurekaClientAutoConfiguration.class })
public class EurekaDiscoveryClientConfigServiceBootstrapConfiguration {
}
@@ -0,0 +1,32 @@
/*
* Copyright 2017-2020 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 org.springframework.cloud.configuration.TlsProperties;
/**
* Eureka client TLS properties.
*/
public class EurekaTlsProperties extends TlsProperties {
/**
* Prefix for Eureka client TLS properties.
*/
public static final String PREFIX = "eureka.client.tls";
}
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2019 the original author or authors.
* Copyright 2017-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2019 the original author or authors.
* Copyright 2017-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2019 the original author or authors.
* Copyright 2017-2020 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.
@@ -62,6 +62,10 @@ public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
}
}
public String getServiceUrl() {
return this.serviceUrl;
}
@Override
public EurekaHttpResponse<Void> register(InstanceInfo info) {
String urlPath = serviceUrl + "apps/" + info.getAppName();
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2019 the original author or authors.
* Copyright 2017-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2019 the original author or authors.
* Copyright 2017-2020 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.
@@ -39,7 +39,7 @@ import com.netflix.discovery.shared.transport.EurekaHttpClient;
import com.netflix.discovery.shared.transport.TransportClientFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.support.BasicAuthorizationInterceptor;
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;
@@ -66,7 +66,7 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
if (serviceURI.getUserInfo() != null) {
String[] credentials = serviceURI.getUserInfo().split(":");
if (credentials.length == 2) {
restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor(
restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(
credentials[0], credentials[1]));
}
}
@@ -0,0 +1,41 @@
/*
* Copyright 2017-2020 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 java.util.function.Supplier;
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
import org.springframework.web.reactive.function.client.WebClient;
/**
* @author Daniel Lavoie
* @author Haytham Mohamed
*/
public class WebClientDiscoveryClientOptionalArgs
extends AbstractDiscoveryClientOptionalArgs<Void> {
@Deprecated
public WebClientDiscoveryClientOptionalArgs() {
this(WebClient::builder);
}
public WebClientDiscoveryClientOptionalArgs(Supplier<WebClient.Builder> builder) {
setTransportClientFactories(new WebClientTransportClientFactories(builder));
}
}
@@ -0,0 +1,240 @@
/*
* Copyright 2017-2020 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 java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
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 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.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import static com.netflix.discovery.shared.transport.EurekaHttpResponse.anEurekaHttpResponse;
/**
* @author Daniel Lavoie
* @author Haytham Mohamed
*/
public class WebClientEurekaHttpClient implements EurekaHttpClient {
protected final Log logger = LogFactory.getLog(getClass());
private WebClient webClient;
public WebClientEurekaHttpClient(WebClient webClient) {
this.webClient = webClient;
}
@Override
public EurekaHttpResponse<Void> register(InstanceInfo 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)
.exchange().map(response -> eurekaHttpResponse(response)).block();
}
@Override
public EurekaHttpResponse<Void> cancel(String appName, String id) {
return webClient.delete().uri("apps/" + appName + '/' + id, Void.class).exchange()
.map(response -> eurekaHttpResponse(response)).block();
}
@Override
public EurekaHttpResponse<InstanceInfo> sendHeartBeat(String appName, String id,
InstanceInfo info, InstanceStatus overriddenStatus) {
String urlPath = "apps/" + appName + '/' + id + "?status="
+ info.getStatus().toString() + "&lastDirtyTimestamp="
+ info.getLastDirtyTimestamp().toString() + (overriddenStatus != null
? "&overriddenstatus=" + overriddenStatus.name() : "");
ClientResponse response = webClient.put().uri(urlPath, InstanceInfo.class)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).exchange()
.block();
EurekaHttpResponseBuilder<InstanceInfo> builder = anEurekaHttpResponse(
statusCodeValueOf(response), InstanceInfo.class)
.headers(headersOf(response));
InstanceInfo entity = response.toEntity(InstanceInfo.class).block().getBody();
if (entity != null) {
builder.entity(entity);
}
return builder.build();
}
@Override
public EurekaHttpResponse<Void> statusUpdate(String appName, String id,
InstanceStatus newStatus, InstanceInfo info) {
String urlPath = "apps/" + appName + '/' + id + "/status?value="
+ newStatus.name() + "&lastDirtyTimestamp="
+ info.getLastDirtyTimestamp().toString();
return webClient.put().uri(urlPath, Void.class)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.exchange().map(response -> eurekaHttpResponse(response)).block();
}
@Override
public EurekaHttpResponse<Void> deleteStatusOverride(String appName, String id,
InstanceInfo info) {
String urlPath = "apps/" + appName + '/' + id + "/status?lastDirtyTimestamp="
+ info.getLastDirtyTimestamp().toString();
return webClient.delete().uri(urlPath, Void.class)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.exchange().map(response -> eurekaHttpResponse(response)).block();
}
@Override
public EurekaHttpResponse<Applications> getApplications(String... regions) {
return getApplicationsInternal("apps/", regions);
}
private EurekaHttpResponse<Applications> getApplicationsInternal(String urlPath,
String[] regions) {
String url = urlPath;
if (regions != null && regions.length > 0) {
url = url + (urlPath.contains("?") ? "&" : "?") + "regions="
+ StringUtil.join(regions);
}
ClientResponse response = webClient.get().uri(url, Applications.class)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).exchange()
.block();
int statusCode = statusCodeValueOf(response);
Applications body = response.toEntity(Applications.class).block().getBody();
return anEurekaHttpResponse(statusCode,
statusCode == HttpStatus.OK.value() && body != null ? body : null)
.headers(headersOf(response)).build();
}
@Override
public EurekaHttpResponse<Applications> getDelta(String... regions) {
return getApplicationsInternal("apps/delta", regions);
}
@Override
public EurekaHttpResponse<Applications> getVip(String vipAddress, String... regions) {
return getApplicationsInternal("vips/" + vipAddress, regions);
}
@Override
public EurekaHttpResponse<Applications> getSecureVip(String secureVipAddress,
String... regions) {
return getApplicationsInternal("svips/" + secureVipAddress, regions);
}
@Override
public EurekaHttpResponse<Application> getApplication(String appName) {
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.toEntity(Application.class).block().getBody();
Application application = statusCode == HttpStatus.OK.value() && body != null
? body : null;
return anEurekaHttpResponse(statusCode, application).headers(headersOf(response))
.build();
}
@Override
public EurekaHttpResponse<InstanceInfo> getInstance(String appName, String id) {
return getInstanceInternal("apps/" + appName + '/' + id);
}
@Override
public EurekaHttpResponse<InstanceInfo> getInstance(String id) {
return getInstanceInternal("instances/" + id);
}
private EurekaHttpResponse<InstanceInfo> getInstanceInternal(String urlPath) {
ClientResponse response = webClient.get().uri(urlPath, InstanceInfo.class)
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).exchange()
.block();
int statusCode = statusCodeValueOf(response);
InstanceInfo body = response.toEntity(InstanceInfo.class).block().getBody();
return anEurekaHttpResponse(statusCode,
statusCode == HttpStatus.OK.value() && body != null ? body : null)
.headers(headersOf(response)).build();
}
@Override
public void shutdown() {
// Nothing to do
}
public WebClient getWebClient() {
return this.webClient;
}
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 int statusCodeValueOf(ClientResponse response) {
return response.statusCode().value();
}
private EurekaHttpResponse<Void> eurekaHttpResponse(ClientResponse response) {
return anEurekaHttpResponse(statusCodeValueOf(response))
.headers(headersOf(response)).build();
}
}
@@ -0,0 +1,68 @@
/*
* Copyright 2017-2020 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 java.util.Collection;
import java.util.Optional;
import java.util.function.Supplier;
import javax.net.ssl.HostnameVerifier;
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;
/**
* @author Daniel Lavoie
* @author Haytham Mohamed
*/
public class WebClientTransportClientFactories implements TransportClientFactories<Void> {
private final Supplier<WebClient.Builder> builder;
public WebClientTransportClientFactories(Supplier<WebClient.Builder> builder) {
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) {
return new WebClientTransportClientFactory(builder);
}
@Override
public TransportClientFactory newTransportClientFactory(
final EurekaClientConfig clientConfig,
final Collection<Void> additionalFilters, final InstanceInfo myInstanceInfo,
final Optional<SSLContext> sslContext,
final Optional<HostnameVerifier> hostnameVerifier) {
return new WebClientTransportClientFactory(builder);
}
}
@@ -0,0 +1,195 @@
/*
* Copyright 2017-2020 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 java.net.URI;
import java.net.URISyntaxException;
import java.util.function.Supplier;
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.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializationFeature;
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.mixin.ApplicationsJsonMixIn;
import com.netflix.discovery.converters.jackson.mixin.InstanceInfoJsonMixIn;
import com.netflix.discovery.converters.jackson.serializer.InstanceInfoJsonBeanSerializer;
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.Mono;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ClientCodecConfigurer;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeFilterFunctions;
import org.springframework.web.reactive.function.client.WebClient;
/**
* Provides the custom {@link WebClient.Builder} required by the
* {@link WebClientEurekaHttpClient}. Relies on Jackson for serialization and
* deserialization.
*
* @author Daniel Lavoie
* @author Haytham Mohamed
*/
public class WebClientTransportClientFactory implements TransportClientFactory {
private final Supplier<WebClient.Builder> builderSupplier;
@Deprecated
public WebClientTransportClientFactory() {
this(WebClient::builder);
}
public WebClientTransportClientFactory(Supplier<WebClient.Builder> builderSupplier) {
this.builderSupplier = builderSupplier;
}
@Override
public EurekaHttpClient newClient(EurekaEndpoint endpoint) {
// we want a copy to modify. Don't change the original
WebClient.Builder builder = this.builderSupplier.get().clone();
setUrl(builder, endpoint.getServiceUrl());
setCodecs(builder);
builder.filter(http4XxErrorExchangeFilterFunction());
return new WebClientEurekaHttpClient(builder.build());
}
private WebClient.Builder setUrl(WebClient.Builder builder, String serviceUrl) {
String url = serviceUrl;
try {
URI serviceURI = new URI(serviceUrl);
if (serviceURI.getUserInfo() != null) {
String[] credentials = serviceURI.getUserInfo().split(":");
if (credentials.length == 2) {
builder.filter(ExchangeFilterFunctions
.basicAuthentication(credentials[0], credentials[1]));
url = serviceUrl.replace(credentials[0] + ":" + credentials[1] + "@",
"");
}
}
}
catch (URISyntaxException ignore) {
}
return builder.baseUrl(url);
}
private void setCodecs(WebClient.Builder builder) {
ObjectMapper objectMapper = objectMapper();
builder.codecs(configurer -> {
ClientCodecConfigurer.ClientDefaultCodecs defaults = configurer
.defaultCodecs();
defaults.jackson2JsonEncoder(
new Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON));
defaults.jackson2JsonDecoder(
new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON));
});
}
// Skip over 4xx http errors
private ExchangeFilterFunction http4XxErrorExchangeFilterFunction() {
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
// literally 400 pass the tests, not 4xxClientError
if (clientResponse.statusCode().value() == 400) {
ClientResponse newResponse = ClientResponse.from(clientResponse)
.statusCode(HttpStatus.OK).build();
newResponse.body(
(clientHttpResponse, context) -> clientHttpResponse.getBody());
return Mono.just(newResponse);
}
return Mono.just(clientResponse);
});
}
/**
* 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. Achieved with
* {@link SerializationFeature#WRAP_ROOT_VALUE} and
* {@link DeserializationFeature#UNWRAP_ROOT_VALUE}.
* {@link PropertyNamingStrategy.SnakeCaseStrategy} is applied to the underlying
* {@link ObjectMapper}.
* @deprecated to be removed.
* @return a {@link MappingJackson2HttpMessageConverter} object
*/
@Deprecated
public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(objectMapper());
return converter;
}
/**
* 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. Achieved with
* {@link SerializationFeature#WRAP_ROOT_VALUE} and
* {@link DeserializationFeature#UNWRAP_ROOT_VALUE}.
* {@link PropertyNamingStrategy.SnakeCaseStrategy} is applied to the underlying
* {@link ObjectMapper}.
* @return a {@link ObjectMapper} object
*/
private ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
SimpleModule jsonModule = new SimpleModule();
jsonModule.setSerializerModifier(createJsonSerializerModifier());
objectMapper.registerModule(jsonModule);
objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
objectMapper.addMixIn(Applications.class, ApplicationsJsonMixIn.class);
objectMapper.addMixIn(InstanceInfo.class, InstanceInfoJsonMixIn.class);
return objectMapper;
}
@Deprecated // reduce visibility in future release
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;
}
};
}
@Override
public void shutdown() {
}
}
@@ -0,0 +1,104 @@
/*
* Copyright 2013-2020 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.loadbalancer;
import javax.annotation.PostConstruct;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.discovery.EurekaClientConfig;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.cloud.loadbalancer.config.LoadBalancerZoneConfig;
import org.springframework.cloud.netflix.ribbon.eureka.ZoneUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import static org.springframework.cloud.netflix.eureka.loadbalancer.LoadBalancerEurekaAutoConfiguration.LOADBALANCER_ZONE;
/**
* A configuration for Spring Cloud LoadBalancer that retrieves client instance zone from
* Eureka and sets it as a property. Based on
* {@link EurekaLoadBalancerClientConfiguration}.
*
* @author Olga Maciaszek-Sharma
* @since 2.2.1
* @see EurekaLoadBalancerClientConfiguration
*/
@Configuration
@ConditionalOnBean({ LoadBalancerZoneConfig.class, EurekaLoadBalancerProperties.class })
public class EurekaLoadBalancerClientConfiguration {
private static final Log LOG = LogFactory
.getLog(EurekaLoadBalancerClientConfiguration.class);
private final EurekaClientConfig clientConfig;
private final EurekaInstanceConfig eurekaConfig;
private final LoadBalancerZoneConfig zoneConfig;
private final EurekaLoadBalancerProperties eurekaLoadBalancerProperties;
public EurekaLoadBalancerClientConfiguration(
@Autowired(required = false) EurekaClientConfig clientConfig,
@Autowired(required = false) EurekaInstanceConfig eurekaInstanceConfig,
LoadBalancerZoneConfig zoneConfig,
EurekaLoadBalancerProperties eurekaLoadBalancerProperties) {
this.clientConfig = clientConfig;
this.eurekaConfig = eurekaInstanceConfig;
this.zoneConfig = zoneConfig;
this.eurekaLoadBalancerProperties = eurekaLoadBalancerProperties;
}
@PostConstruct
public void postprocess() {
if (!StringUtils.isEmpty(zoneConfig.getZone())) {
return;
}
String zone = getZoneFromEureka();
if (!StringUtils.isEmpty(zone)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Setting the value of '" + LOADBALANCER_ZONE + "' to " + zone);
}
zoneConfig.setZone(zone);
}
}
private String getZoneFromEureka() {
String zone;
boolean approximateZoneFromHostname = eurekaLoadBalancerProperties
.isApproximateZoneFromHostname();
if (approximateZoneFromHostname && eurekaConfig != null) {
return ZoneUtils.extractApproximateZone(this.eurekaConfig.getHostName(false));
}
else {
zone = eurekaConfig == null ? null
: eurekaConfig.getMetadataMap().get("zone");
if (StringUtils.isEmpty(zone)) {
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;
}
return zone;
}
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2012-2020 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.loadbalancer;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* A {@link ConfigurationProperties} bean for the Eureka-specific instrumentation of
* Spring Cloud LoadBalancer.
*
* @author Olga Maciaszek-Sharma
* @since 2.2.1
*/
@ConfigurationProperties("spring.cloud.loadbalancer.eureka")
public class EurekaLoadBalancerProperties {
/**
* Used to determine whether we should try to get the `zone` value from host name.
*/
private boolean approximateZoneFromHostname = false;
public boolean isApproximateZoneFromHostname() {
return approximateZoneFromHostname;
}
public void setApproximateZoneFromHostname(boolean approximateZoneFromHostname) {
this.approximateZoneFromHostname = approximateZoneFromHostname;
}
}
@@ -0,0 +1,61 @@
/*
* Copyright 2013-2020 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.loadbalancer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientConfigurationRegistrar;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.cloud.loadbalancer.config.LoadBalancerZoneConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
/**
* An Autoconfiguration that loads default config for Spring Cloud LoadBalancer clients.
*
* @author Olga Maciaszek-Sharma
* @since 2.2.1
* @see EurekaLoadBalancerClientConfiguration
*/
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnClass(LoadBalancerClientConfigurationRegistrar.class)
@LoadBalancerClients(defaultConfiguration = EurekaLoadBalancerClientConfiguration.class)
@ConditionalOnProperty(name = "eureka.client.enabled", matchIfMissing = true)
public class LoadBalancerEurekaAutoConfiguration {
/**
* Spring Cloud LoadBalancer Zone property name.
*/
public static final String LOADBALANCER_ZONE = "spring.cloud.loadbalancer.zone";
@Bean
@ConditionalOnMissingBean
EurekaLoadBalancerProperties eurekaLoadBalancerProperties() {
return new EurekaLoadBalancerProperties();
}
@Bean
@ConditionalOnMissingBean
LoadBalancerZoneConfig zoneConfig(Environment environment) {
return new LoadBalancerZoneConfig(environment.getProperty(LOADBALANCER_ZONE));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2019 the original author or authors.
* Copyright 2017-2020 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.
@@ -123,7 +123,7 @@ public class DefaultManagementMetadataProvider implements ManagementMetadataProv
String refinedContextPath = '/'
+ StringUtils.trimLeadingCharacter(contextPath, '/');
URL base = new URL(scheme, hostname, port, refinedContextPath);
String refinedStatusPath = StringUtils.trimLeadingCharacter(statusPath, '/');
String refinedStatusPath = refinedStatusPath(statusPath, contextPath);
return new URL(base, refinedStatusPath).toString();
}
catch (MalformedURLException e) {
@@ -133,6 +133,13 @@ public class DefaultManagementMetadataProvider implements ManagementMetadataProv
}
}
private String refinedStatusPath(String statusPath, String contextPath) {
if (statusPath.startsWith(contextPath) && !"/".equals(contextPath)) {
statusPath = StringUtils.replace(statusPath, contextPath, "");
}
return StringUtils.trimLeadingCharacter(statusPath, '/');
}
private String getErrorMessage(String scheme, String hostname, int port,
String contextPath, String statusPath) {
return String.format(
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2019 the original author or authors.
* Copyright 2017-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2019 the original author or authors.
* Copyright 2017-2020 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.
@@ -0,0 +1,75 @@
/*
* Copyright 2019-2020 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.reactive;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EurekaServiceInstance;
import org.springframework.core.Ordered;
/**
* A {@link ReactiveDiscoveryClient} implementation for Eureka.
*
* @author Tim Ysewyn
*/
public class EurekaReactiveDiscoveryClient implements ReactiveDiscoveryClient {
private final EurekaClient eurekaClient;
private final EurekaClientConfig clientConfig;
public EurekaReactiveDiscoveryClient(EurekaClient eurekaClient,
EurekaClientConfig clientConfig) {
this.eurekaClient = eurekaClient;
this.clientConfig = clientConfig;
}
@Override
public String description() {
return "Spring Cloud Eureka Reactive Discovery Client";
}
@Override
public Flux<ServiceInstance> getInstances(String serviceId) {
return Flux
.defer(() -> Flux.fromIterable(
eurekaClient.getInstancesByVipAddress(serviceId, false)))
.map(EurekaServiceInstance::new);
}
@Override
public Flux<String> getServices() {
return Flux.defer(() -> Mono.justOrEmpty(eurekaClient.getApplications()))
.flatMapIterable(Applications::getRegisteredApplications)
.filter(application -> !application.getInstances().isEmpty())
.map(Application::getName).map(String::toLowerCase);
}
@Override
public int getOrder() {
return clientConfig instanceof Ordered ? ((Ordered) clientConfig).getOrder()
: ReactiveDiscoveryClient.DEFAULT_ORDER;
}
}
@@ -0,0 +1,74 @@
/*
* Copyright 2019-2020 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.reactive;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled;
import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled;
import org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration;
import org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration;
import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicatorProperties;
import org.springframework.cloud.client.discovery.health.reactive.ReactiveDiscoveryClientHealthIndicator;
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Configuration related to service discovery when using Netflix Eureka.
*
* @author Tim Ysewyn
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(EurekaClientConfig.class)
@ConditionalOnDiscoveryEnabled
@ConditionalOnReactiveDiscoveryEnabled
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureAfter({ EurekaClientAutoConfiguration.class,
ReactiveCompositeDiscoveryClientAutoConfiguration.class })
@AutoConfigureBefore(ReactiveCommonsClientAutoConfiguration.class)
@ImportAutoConfiguration(EurekaClientAutoConfiguration.class)
public class EurekaReactiveDiscoveryClientConfiguration {
@Bean
@ConditionalOnMissingBean
public EurekaReactiveDiscoveryClient eurekaReactiveDiscoveryClient(
EurekaClient client, EurekaClientConfig clientConfig) {
return new EurekaReactiveDiscoveryClient(client, clientConfig);
}
@Bean
@ConditionalOnClass(
name = "org.springframework.boot.actuate.health.ReactiveHealthIndicator")
@ConditionalOnDiscoveryHealthIndicatorEnabled
public ReactiveDiscoveryClientHealthIndicator eurekaReactiveDiscoveryClientHealthIndicator(
EurekaReactiveDiscoveryClient client,
DiscoveryClientHealthIndicatorProperties properties) {
return new ReactiveDiscoveryClientHealthIndicator(client, properties);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2020 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.

Some files were not shown because too many files have changed in this diff Show More