I'm in the middle of implementing a new EnvironmentRepository and so far it's been easy enough extending from the base class and looking at the examples of existing implementations.
One issue I'm having is finding a way to add/extend spring-cloud-config-monitor
so that my new EnvironmentRepository can also use the /monitor
endpoint to refresh and automatically notify the consumers about new configuration. I tried creating a new BasePropertyPathNotificationExtractor
but so far I can't get things wired so that the PropertyPathEndpoint can be called.
Documentation on how this is done or a sample bit of code would be extremely helpful to those extending spring-cloud-config
. I suppose I can just create my own /my-monitor
endpoint and publish the event like so?
this.applicationEventPublisher.publishEvent(new RefreshRemoteApplicationEvent(this, this.busId, service));
Comment From: ryanjbaxter
So you are creating a Bean
for your BasePropertyPathNotificationExctractor
and its not present in the list here?
https://github.com/spring-cloud/spring-cloud-config/blob/9c695648be6a88c232ed7792759fc9adfad82c2d/spring-cloud-config-monitor/src/main/java/org/springframework/cloud/config/monitor/EnvironmentMonitorAutoConfiguration.java#L54
Comment From: Alos
Yes. It looks like I was able to register my extractor effectively, the issue might be further down the path. Now debugging the notifyByPath
and the bus configuration.
Comment From: ryanjbaxter
OK let me know.
Comment From: Alos
Ok I think I know what's happening, but I can't figure out the correct way of solving it.
My new NewDogPropertyPathNotificationExtractor
is correctly added. The PropertyPathEndpoint
's notifyByPath
method correctly loops around and picks up my new extractor, the problem is that the new extractor uses BasePropertyPathNotificationExtractor's extract method that looks to see if the request contains a commits
.
The update to the /monitor
endpoint has no such information. Should I overwrite the extract
method on my implementation or is there a way to trigger the refresh in another way (besides poking at the /monitor
endpoint)?
Comment From: ryanjbaxter
I would just override the extract
method in your implementation
Comment From: Alos
If I wanted to override the extractor to fire off events to a dog-service
(so that it can perform its context refresh and ask for its configuration again) what would I need to return as a PropertyPathNotification
? So far I've made sure that the PropertyPathNotification
has "dog-service" in its path. This made the guessServiceName
populate the services
set with: ["dog:service", "dog-service"] this triggered the following logs:
MyCustomPropertyPathNotificationExtractor : paths [dog-service]
o.s.c.c.monitor.PropertyPathEndpoint. : Refresh for: dog:service
o.s.c.s.m.DirectWithAttributesChannel. : Channel 'unknown.channel.name' has 1 subscriber(s).
o.s.cloud.bus.event.RefreshListener. : Received remote refresh request.
o.s.cloud.bus.event.RefreshListener : Refresh not performed, the event was targeting dog:service:**
o.s.c.c.monitor.PropertyPathEndpoint : Refresh for: dog-service
o.s.cloud.bus.event.RefreshListener : Received remote refresh request.
o.s.cloud.bus.event.RefreshListener : Refresh not performed, the event was targeting dog-service:**
c.g.c.a.l.MyCustomEnvironmentRepository : Fetching configuration for application: dog-service, profile: kubernetes,development, label: null
I don't see where the spring-cloud-monitor would take the refresh event and try to call the implementation to fire a refresh event into the service bus. Can you point me to the part of the code that does this? Do I need to craft the path in a specific way to make sure the Config Service fires the event?
Comment From: Alos
Actually I think its working!
Logs on the dog-service:
o.s.c.c.c.ConfigServerConfigDataLoader : Fetching config from server at : http://config-service:8080
o.s.c.c.c.ConfigServerConfigDataLoader : Located environment: name=dog-service, profiles=[kubernetes,development], label=null, version=null, state=null
o.s.cloud.bus.event.RefreshListener : Keys refreshed []
o.s.c.s.binder.DefaultBinderFactory : Retrieving cached binder: pubsub
My only concern is the double services caused by the guessServiceName
and the fact that the Keys are not refreshed in the client it self :S
Comment From: ryanjbaxter
I would have to debug something to understand why there are two of the same service names in the list. If you can provide a sample that would help.
Comment From: Alos
I'm calling the /monitor
endpoint like this:
curl -X POST http://localhost:8080/monitor -H "X-SOME-Event: push" -H "Content-Type: application/json" -d '{"updates":["dog-service"]}'
My extractor looks like this:
public class MyPropertyPathNotificationExtractor extends BasePropertyPathNotificationExtractor {
@Override
public PropertyPathNotification extract(
MultiValueMap<String, String> headers, Map<String, Object> request) {
if (Objects.nonNull(request) && request.get("updates") instanceof Collection) {
Set<String> paths = new LinkedHashSet<>();
List<String> updates = (List<String>) request.get("updates");
if (!updates.isEmpty()) {
paths.addAll(updates);
log.info("paths {}", paths);
return new PropertyPathNotification(paths.toArray(new String[0]));
}
}
return null;
}
@Override
protected boolean requestBelongsToMyRepoManager(MultiValueMap<String, String> headers) {
log.info("Refreshing repo");
return "push".equals(headers.getFirst("X-SOME-Event"));
}
}
Basically the MyPropertyPathNotificationExtractor
returns a PropertyPathNotification
that has "dog-service" it its paths
array.
From there the guessServiceName
somehow adds ["dog:service", "dog-service"]. This is because in:
https://github.com/spring-cloud/spring-cloud-config/blob/8493efb8457b4107c4bfa63a0fc45b0ba6b98756/spring-cloud-config-monitor/src/main/java/org/springframework/cloud/config/monitor/PropertyPathEndpoint.java#L105
it goes into the while loop and then into the:
if ("application".equals(name)) {
services.add("*:" + profile);
}
Since our applications are running in K8s we named them foo-service
i.e cat-service, dog-service, duck-service, etc.
Comment From: ryanjbaxter
I really dont understand where "dog:service" is coming from.
guessServiceNameshould produce a set
[dog-service, dog]if path is
dog-service`. Sorry I am just not understanding whats going on.
Comment From: spring-cloud-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-cloud-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.