Skip to content

Commit 7f4006c

Browse files
committed
In progress support for ConfigurationClient
1 parent 3a4345d commit 7f4006c

File tree

34 files changed

+750
-145
lines changed

34 files changed

+750
-145
lines changed

ROADMAP.adoc

+4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ These should be built on the `Endpoint` API.
4848

4949
### HTTP Server
5050

51+
#### Misc TODO Items
52+
53+
* URI variable values passed to Controller methods should be URI decoded
54+
5155
#### Content Negotiation
5256

5357
Content negotiation must be supported

configurations/netflix-ribbon/src/test/groovy/io/micronaut/configurations/ribbon/MockConsulServer.groovy

+24-3
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,21 @@
1515
*/
1616
package io.micronaut.configurations.ribbon
1717

18+
import io.micronaut.context.annotation.Parameter
1819
import io.micronaut.core.async.publisher.Publishers
1920
import io.micronaut.discovery.consul.client.v1.CatalogEntry
2021
import io.micronaut.discovery.consul.client.v1.ConsulOperations
2122
import io.micronaut.discovery.consul.client.v1.HealthEntry
23+
import io.micronaut.discovery.consul.client.v1.KeyValue
2224
import io.micronaut.discovery.consul.client.v1.NewServiceEntry
2325
import io.micronaut.discovery.consul.client.v1.ServiceEntry
2426
import io.micronaut.http.HttpStatus
2527
import io.micronaut.http.annotation.*
2628
import io.micronaut.runtime.server.EmbeddedServer
29+
import io.reactivex.Flowable
2730
import org.reactivestreams.Publisher
2831

32+
import javax.annotation.Nullable
2933
import javax.inject.Singleton
3034
import javax.validation.constraints.NotNull
3135
import java.util.concurrent.ConcurrentHashMap
@@ -53,18 +57,35 @@ class MockConsulServer implements ConsulOperations {
5357
}
5458

5559
@Override
56-
Publisher<HttpStatus> pass(String checkId, Optional<String> note) {
60+
Publisher<Boolean> putValue(String key, @Body String value) {
61+
return Flowable.just(true)
62+
}
63+
64+
@Override
65+
Publisher<List<KeyValue>> readValues(String key) {
66+
return Flowable.just(Collections.emptyList())
67+
}
68+
69+
@Override
70+
Publisher<List<KeyValue>> readValues(String key,
71+
@Nullable @Parameter("dc") String datacenter,
72+
@Nullable Boolean raw, @Nullable String seperator) {
73+
return Flowable.just(Collections.emptyList())
74+
}
75+
76+
@Override
77+
Publisher<HttpStatus> pass(String checkId, @Nullable String note) {
5778
passingReports.add(checkId)
5879
return Publishers.just(HttpStatus.OK)
5980
}
6081

6182
@Override
62-
Publisher<HttpStatus> warn(String checkId, Optional<String> note) {
83+
Publisher<HttpStatus> warn(String checkId, @Nullable String note) {
6384
return Publishers.just(HttpStatus.OK)
6485
}
6586

6687
@Override
67-
Publisher<HttpStatus> fail(String checkId, Optional<String> note) {
88+
Publisher<HttpStatus> fail(String checkId, @Nullable String note) {
6889
return Publishers.just(HttpStatus.OK)
6990
}
7091

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2018 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.micronaut.core.naming;
17+
18+
/**
19+
* An interface for types that are described by a description
20+
* @author graemerocher
21+
* @since 1.0
22+
*/
23+
public interface Described {
24+
/**
25+
* A description that describes this object
26+
*
27+
* @return The description
28+
*/
29+
String getDescription();
30+
}

discovery-client/src/main/java/io/micronaut/discovery/client/DiscoveryClientConfiguration.java

+13-4
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@
3131
import java.net.URI;
3232
import java.net.URISyntaxException;
3333
import java.net.URL;
34-
import java.util.ArrayList;
35-
import java.util.Collections;
36-
import java.util.List;
37-
import java.util.Map;
34+
import java.util.*;
3835
import java.util.function.Function;
3936
import java.util.stream.Collectors;
4037
import java.util.stream.Stream;
@@ -48,6 +45,7 @@
4845
public abstract class DiscoveryClientConfiguration extends HttpClientConfiguration {
4946

5047

48+
private final ApplicationConfiguration applicationConfiguration;
5149
private List<ServiceInstance> defaultZone = Collections.emptyList();
5250
private List<ServiceInstance> otherZones = Collections.emptyList();
5351

@@ -56,12 +54,23 @@ public abstract class DiscoveryClientConfiguration extends HttpClientConfigurati
5654
private boolean secure;
5755

5856
public DiscoveryClientConfiguration() {
57+
this.applicationConfiguration = null;
5958
}
6059

6160
public DiscoveryClientConfiguration(ApplicationConfiguration applicationConfiguration) {
6261
super(applicationConfiguration);
62+
this.applicationConfiguration = applicationConfiguration;
6363
}
6464

65+
/**
66+
* @return Resolves the service ID to use
67+
*/
68+
public Optional<String> getServiceId() {
69+
if(applicationConfiguration != null) {
70+
return applicationConfiguration.getName();
71+
}
72+
return Optional.empty();
73+
}
6574
/**
6675
* @return The Discovery servers within the default zone
6776
*/

discovery-client/src/main/java/io/micronaut/discovery/consul/ConsulConfiguration.java

+37-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import io.micronaut.context.annotation.ConfigurationProperties;
1919
import io.micronaut.core.util.Toggleable;
20+
import io.micronaut.discovery.config.ConfigDiscoveryConfiguration;
2021
import io.micronaut.discovery.consul.client.v1.ConsulClient;
2122
import io.micronaut.discovery.consul.condition.RequiresConsul;
2223
import io.micronaut.http.HttpMethod;
@@ -57,6 +58,8 @@ public class ConsulConfiguration extends DiscoveryClientConfiguration {
5758

5859
private ConsulDiscoveryConfiguration discovery = new ConsulDiscoveryConfiguration();
5960

61+
private ConsulConfigDiscoveryConfiguration configuration = new ConsulConfigDiscoveryConfiguration();
62+
6063
public ConsulConfiguration() {
6164
setPort(8500);
6265
}
@@ -67,6 +70,18 @@ public ConsulConfiguration(ApplicationConfiguration applicationConfiguration) {
6770
setPort(8500);
6871
}
6972

73+
/**
74+
* @return The configuration discovery configuration
75+
*/
76+
public ConsulConfigDiscoveryConfiguration getConfiguration() {
77+
return configuration;
78+
}
79+
80+
public void setConfiguration(ConsulConfigDiscoveryConfiguration configuration) {
81+
if(configuration != null)
82+
this.configuration = configuration;
83+
}
84+
7085
/**
7186
* @return The token to include in all requests as the {@code X-Consul-Token} header
7287
*/
@@ -91,7 +106,8 @@ public ConsulDiscoveryConfiguration getDiscovery() {
91106
}
92107

93108
public void setDiscovery(ConsulDiscoveryConfiguration discovery) {
94-
this.discovery = discovery;
109+
if(discovery != null)
110+
this.discovery = discovery;
95111
}
96112

97113
public void setAslToken(String aslToken) {
@@ -104,7 +120,26 @@ protected String getServiceID() {
104120
}
105121

106122
public void setRegistration(ConsulRegistrationConfiguration registration) {
107-
this.registration = registration;
123+
if(registration != null)
124+
this.registration = registration;
125+
}
126+
127+
@ConfigurationProperties(ConfigDiscoveryConfiguration.PREFIX)
128+
public static class ConsulConfigDiscoveryConfiguration extends ConfigDiscoveryConfiguration {
129+
130+
private String datacenter;
131+
132+
/**
133+
* The data center to use to read configuration
134+
* @return The data center name
135+
*/
136+
public Optional<String> getDatacenter() {
137+
return Optional.ofNullable(datacenter);
138+
}
139+
140+
public void setDatacenter(String datacenter) {
141+
this.datacenter = datacenter;
142+
}
108143
}
109144

110145
@ConfigurationProperties(DiscoveryConfiguration.PREFIX)

discovery-client/src/main/java/io/micronaut/discovery/consul/client/v1/AbstractConsulClient.java

+58-10
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,26 @@
1616
package io.micronaut.discovery.consul.client.v1;
1717

1818
import io.micronaut.context.annotation.Requires;
19+
import io.micronaut.context.env.Environment;
20+
import io.micronaut.context.env.PropertySource;
1921
import io.micronaut.core.async.publisher.Publishers;
22+
import io.micronaut.core.util.CollectionUtils;
2023
import io.micronaut.discovery.DiscoveryClient;
2124
import io.micronaut.discovery.ServiceInstance;
25+
import io.micronaut.discovery.config.ConfigDiscoveryConfiguration;
26+
import io.micronaut.discovery.config.ConfigurationClient;
2227
import io.micronaut.discovery.consul.ConsulConfiguration;
2328
import io.micronaut.discovery.consul.ConsulServiceInstance;
2429
import io.micronaut.http.client.Client;
30+
import io.reactivex.Emitter;
31+
import io.reactivex.Flowable;
32+
import io.reactivex.functions.Consumer;
33+
import io.reactivex.functions.Function;
2534
import org.reactivestreams.Publisher;
2635

27-
import javax.annotation.Nullable;
2836
import javax.inject.Inject;
2937
import java.io.IOException;
30-
import java.util.ArrayList;
31-
import java.util.Collections;
32-
import java.util.List;
33-
import java.util.Optional;
38+
import java.util.*;
3439

3540
/**
3641
* Abstract implementation of {@link ConsulClient} that also implements {@link DiscoveryClient}
@@ -41,7 +46,7 @@
4146
@SuppressWarnings("unused")
4247
@Client(id = ConsulClient.SERVICE_ID, path = "/v1", configuration = ConsulConfiguration.class)
4348
@Requires(beans = ConsulConfiguration.class)
44-
public abstract class AbstractConsulClient implements ConsulClient {
49+
public abstract class AbstractConsulClient implements ConsulClient, ConfigurationClient {
4550

4651
private ConsulConfiguration consulConfiguration = new ConsulConfiguration();
4752

@@ -56,6 +61,53 @@ public String getDescription() {
5661
return ConsulClient.SERVICE_ID;
5762
}
5863

64+
@Override
65+
public Publisher<PropertySource> getPropertySources(Environment environment) {
66+
Set<String> activeNames = environment.getActiveNames();
67+
Optional<String> serviceId = consulConfiguration.getServiceId();
68+
ConsulConfiguration.ConsulConfigDiscoveryConfiguration configDiscoveryConfiguration = consulConfiguration.getConfiguration();
69+
70+
ConfigDiscoveryConfiguration.Format format = configDiscoveryConfiguration.getFormat();
71+
String path = configDiscoveryConfiguration.getPath().orElse(ConfigDiscoveryConfiguration.DEFAULT_PATH);
72+
if(!path.endsWith("/")) {
73+
path += "/";
74+
}
75+
76+
String commonConfigPath = path + Environment.DEFAULT_NAME;
77+
String applicationSpecificPath = null;
78+
if(serviceId.isPresent()) {
79+
applicationSpecificPath = path + serviceId.get();
80+
}
81+
82+
String dc = configDiscoveryConfiguration.getDatacenter().orElse(null);
83+
Flowable<List<KeyValue>> configurationValues = Flowable.fromPublisher(readValues(path, dc, null, null));
84+
String finalApplicationSpecificPath = applicationSpecificPath;
85+
String finalPath = path;
86+
return configurationValues.flatMap(keyValues -> Flowable.generate(emitter -> {
87+
if(CollectionUtils.isEmpty(keyValues)) {
88+
emitter.onComplete();
89+
}
90+
else {
91+
Map<String, PropertySource> propertySources = new HashMap();
92+
93+
for (KeyValue keyValue : keyValues) {
94+
String key = keyValue.getKey();
95+
String value = keyValue.getValue();
96+
97+
if(key.startsWith(finalPath)) {
98+
key = key.substring(finalPath.length());
99+
100+
}
101+
}
102+
103+
for (PropertySource propertySource : propertySources.values()) {
104+
emitter.onNext(propertySource);
105+
}
106+
emitter.onComplete();
107+
}
108+
}));
109+
}
110+
59111
@Override
60112
public Publisher<List<ServiceInstance>> getInstances(String serviceId) {
61113
if(SERVICE_ID.equals(serviceId)) {
@@ -81,8 +133,4 @@ public Publisher<List<ServiceInstance>> getInstances(String serviceId) {
81133
}
82134
}
83135

84-
@Override
85-
public void close() throws IOException {
86-
// no-op.. will be closed by @Client
87-
}
88136
}

discovery-client/src/main/java/io/micronaut/discovery/consul/client/v1/ConsulClient.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.micronaut.core.async.publisher.Publishers;
1919
import io.micronaut.core.async.publisher.Publishers;
2020
import io.micronaut.discovery.DiscoveryClient;
21+
import io.micronaut.discovery.config.ConfigurationClient;
2122
import io.micronaut.http.HttpStatus;
2223
import io.micronaut.http.annotation.Body;
2324
import io.micronaut.http.annotation.Get;
@@ -35,7 +36,7 @@
3536
* @author Graeme Rocher
3637
* @since 1.0
3738
*/
38-
public interface ConsulClient extends ConsulOperations, DiscoveryClient {
39+
public interface ConsulClient extends ConsulOperations, DiscoveryClient, ConfigurationClient {
3940
/**
4041
* The default ID of the consul service
4142
*/

0 commit comments

Comments
 (0)