Can Spring set datasource from service discovery? - spring

Before I start trying to programmatically set datasource configuration in my app using service discovery, I would like to be sure this functionality is not already managed by Spring.
In my case I am using Consul as the discovery service. So I read http://cloud.spring.io/spring-cloud-consul/1.0.x/index.html but don't really find something to answer my question (prolly because of my flawed knowledge of Spring configuration itself).
Basically I would configure the discovery system in a bootstrap.yml file
spring:
cloud:
consul:
host: localhost
port: 8500
then in the application.yml I would set something like:
spring:
datasource:
url: jdbc:${consul.service.datasource}
Is this possible "natively". If not, what do I miss in the concepts involved?

Related

Access vault secret using spring-cloud-vault and use it in application.properties

I have a vault server hosted in Openshift and I have to access secrets from the Vault into my spring application.
My bootstrap.yml looks like this :
spring:
application:
name: application-name
profiles: dev
cloud:
vault:
fail-fast: true
host: HOST
port: 443
scheme: https
token: MY_TOKEN
authentication: TOKEN
kv:
enabled: true
backend: secret
profile-separator: '/'
application-name: application-name
I checked vault logs and able to make connection from spring application to vault.
I can access the secret using Value Property Source.
However, I want to populate the secret's value into application.properties to update properties like spring.datasource.username and spring.datasource.password.
Is there any way to access the secret directly from application.properties?
TL; DR: Yes, you can use Vault properties in application.(properties|yml). It's not recommended to use these in bootstrap.(properties.yml).
Spring Cloud comes with a Bootstrap context where configuration libraries (such as Spring Cloud Consul, Spring Cloud Config and Spring Cloud Vault) are initialized. These integrations fetch configuration and provide these as a parent PropertySources to your application. Spring Boot considers these (you have options to use these PropertySources with the highest/lowest priority) during property binding and when you resolve a property value using Environment.
When bootstrapping an application, then typically one of the first things that happen is property binding in #ConfigurationProperties objects. At the time when bootstrap.(properties|yml) is loaded, typically Spring Cloud Config integrations didn't run yet so at that time you don't see properties contributed by these libraries. Therefore, there's the split between bootstrap context and the actual application context.

Spring Cloud Gateway in CloudFoundry

I've been trying to get my apps to run after deploing them to a CloudFoundry instance. The instance I'm using will not allow to perform requests using http (they will simply timeout) so I have to route all requests to https.
The components/versions I am using are:
Java 10
Spring Boot 2.0.4.RELEASE/Spring Cloud Finchley.SR1
spring-cloud-gateway
spring-cloud-config-server
spring-cloud-starter-netflix-eureka
The failing config
EurekaClient Config (in gateway and the backend where the gw should route to)
eureka:
client:
serviceUrl:
defaultZone: ${DISCOVERY_SERVICE_URL:http://localhost:8061}/eureka/
instance:
hostname: ${vcap.application.uris[0]:localhost}
nonSecurePortEnabled: false
securePortEnabled: true
securePort: ${server.port}
statusPageUrl: https://${eureka.instance.hostname}/actuator/info
healthCheckUrl: https://${eureka.instance.hostname}/actuator/health
homePageUrl: https://${eureka.instance.hostname}/
secure-virtual-host-name: https://${vcap.application.application_uris[0]}
Gateway Config
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/user/**
filters:
- RewritePath=/user/(?<segment>.*), /$\{segment}
Things I have already tried:
Using lb:https://user-service like described in docs -> Will have no effect as far as I can see
Use real urls to the apps (uri: https://user-service.cf-instance.io) -> Routing works as expected.
But I do not want to define the urls in my config, they should returned by eureka and build up correctly by the gateway.
Thanks in advance
Edit:
Here is the output of /eureka/apps
https://pastebin.com/WP3b6PQG
I am currently working to get the current code into GitHub I will edit this post when I've found the time to get a clear state.
Edit 2:
You can find the full example (With SpringCloudGateway, Eureka, ...) at my GitHub
This is an running example, the applied config will not use the Eureka. To use Eureka the gateway-service-cloud.yml in config service has to be adopted.
- id: user-service
uri: lb://user-service
Please ignore the documentation service, this will not work yet, I first need to rewrite the path.
Ok, I found out the solution during fixing the "routing" problem with my documentation-service.
My problem was setting the property eureka.instance.securePort to ${server.port}. This property has to be set to 443 (the default 443 is not applied when nothing is set). When adding this to my configurations everything works as expected after pushing my application.

Variables in yaml configuration not substituted

I'm trying to set up some microservices with Spring Boot and Eureka. I'm using YAML configuration and when I start up the services, they are registered with the Eureka service. The problem I have is that the environment variables in my configuration files are not substituted but are interpreted as a string (see instanceId).
Example application.yml:
server:
port: 0
eureka:
instance:
leaseRenewalIntervalSeconds: 10
instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${random.value}}
client:
registryFetchIntervalSeconds: 5
What I see on the Eureka app:
I've Googled the problem but I can't seem to find a solution. Does anybody known why this might happen or where I could start looking for solutions? I'm fairly new to this and I don't have a clue. Thanks.

Reading key value from consul in springboot application

I want to read my external configs like database host and port from consul.
I want to access it in my Springboot application.
So I have created a springboot application and have added cloud config for consul configuration.
I have created an bootstrap.yml where I give my consul host and port and I am able to connect.
But I am not able to fetch any key-value pair from consul.
I have posted my bootstrap.yml below asd well.
Can somebody guide me how to do that
spring:
cloud:
consul:
host: localhost
port: 8500
config:
enabled: true
data-key: config/application/datakey
TIA
You can make use of ConsulClient and then use getKVValue method to read the kv configs you have set in consul.

Spring rest controller in management port?

When using spring-boot, how to you expose a controller at management port, the port defined by management.port?
In Spring Boot 2.x it is done using #RestControllerEndpoint annotation. For example if you define following properties in application.yml:
management:
server:
port: 8081
endpoints:
web:
base-path: "/actuator" # default value
and some controller as #RestControllerEndpoint(id="debug"), it will be mapped as
http://localhost:8081/actuator/debug/...
More info:
https://www.javadevjournal.com/spring-boot/spring-boot-actuator-custom-endpoint/
Okay, I ended up implementing
org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint
This exposes the Controller into management port rather than application port.

Resources