diff --git a/core-quarkus-extensions/build-parent/pom.xml b/core-quarkus-extensions/build-parent/pom.xml
index 52065c933..c3a51de37 100644
--- a/core-quarkus-extensions/build-parent/pom.xml
+++ b/core-quarkus-extensions/build-parent/pom.xml
@@ -35,7 +35,7 @@
3.6.2
0.8.7
3.5.3
- 6.4.1
+ 6.4.2-SNAPSHOT
11.4.3
3.4.3
diff --git a/core-quarkus-extensions/routes-registrator/deployment/pom.xml b/core-quarkus-extensions/routes-registrator/deployment/pom.xml
index edeb97659..cbc6007c7 100644
--- a/core-quarkus-extensions/routes-registrator/deployment/pom.xml
+++ b/core-quarkus-extensions/routes-registrator/deployment/pom.xml
@@ -28,6 +28,10 @@
com.fasterxml.jackson.core
jackson-databind
+
+ io.quarkus
+ quarkus-jackson-deployment
+
com.netcracker.cloud.quarkus
diff --git a/core-quarkus-extensions/routes-registrator/runtime/pom.xml b/core-quarkus-extensions/routes-registrator/runtime/pom.xml
index 6c4933e14..bff26d58e 100644
--- a/core-quarkus-extensions/routes-registrator/runtime/pom.xml
+++ b/core-quarkus-extensions/routes-registrator/runtime/pom.xml
@@ -22,6 +22,10 @@
com.squareup.okhttp3
okhttp
+
+ io.quarkus
+ quarkus-jackson
+
com.netcracker.cloud.quarkus
diff --git a/core-quarkus-extensions/routes-registrator/runtime/src/main/java/com/netcracker/cloud/quarkus/routesregistration/runtime/gateway/route/RouteRegistrationConfig.java b/core-quarkus-extensions/routes-registrator/runtime/src/main/java/com/netcracker/cloud/quarkus/routesregistration/runtime/gateway/route/RouteRegistrationConfig.java
index fd1bd9ea1..ce7e8b20a 100644
--- a/core-quarkus-extensions/routes-registrator/runtime/src/main/java/com/netcracker/cloud/quarkus/routesregistration/runtime/gateway/route/RouteRegistrationConfig.java
+++ b/core-quarkus-extensions/routes-registrator/runtime/src/main/java/com/netcracker/cloud/quarkus/routesregistration/runtime/gateway/route/RouteRegistrationConfig.java
@@ -1,9 +1,11 @@
package com.netcracker.cloud.quarkus.routesregistration.runtime.gateway.route;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.netcracker.cloud.quarkus.security.auth.M2MManager;
import com.netcracker.cloud.routesregistration.common.gateway.route.*;
import com.netcracker.cloud.routesregistration.common.gateway.route.rest.RegistrationRequestFactory;
import com.netcracker.cloud.routesregistration.common.gateway.route.transformation.RouteTransformer;
+import com.netcracker.cloud.routesregistration.common.service.TopologyConfigService;
import com.netcracker.cloud.security.core.auth.Token;
import io.quarkus.arc.Unremovable;
import io.reactivex.Scheduler;
@@ -125,7 +127,9 @@ RegistrationRequestFactory registrationRequestFactory() {
RoutesRestRegistrationProcessor routesRestRegistrationProcessor(ControlPlaneClient controlPlaneClient,
RouteRetryManager retryManager,
RouteTransformer routeTransformer,
- RegistrationRequestFactory registrationRequestFactory) {
+ RegistrationRequestFactory registrationRequestFactory,
+ TopologyConfigService topologyConfigService) {
+
return new RoutesRestRegistrationProcessor(
controlPlaneClient,
retryManager,
@@ -138,6 +142,11 @@ cloudServiceName, microserviceName, getPort(), "/", postRoutesAppnameDisabled)
);
}
+ @Produces
+ TopologyConfigService topologyConfigService(ObjectMapper objectMapper) {
+ return new TopologyConfigService(objectMapper);
+ }
+
private String getPort() {
return microservicePort;
}
diff --git a/core-rest-libraries/route-registration/route-registration-common-spring/src/main/java/com/netcracker/cloud/routesregistration/common/config/RouteRegistrationProcessorConfiguration.java b/core-rest-libraries/route-registration/route-registration-common-spring/src/main/java/com/netcracker/cloud/routesregistration/common/config/RouteRegistrationProcessorConfiguration.java
index 095d0e38d..1d3eb1cf3 100644
--- a/core-rest-libraries/route-registration/route-registration-common-spring/src/main/java/com/netcracker/cloud/routesregistration/common/config/RouteRegistrationProcessorConfiguration.java
+++ b/core-rest-libraries/route-registration/route-registration-common-spring/src/main/java/com/netcracker/cloud/routesregistration/common/config/RouteRegistrationProcessorConfiguration.java
@@ -1,15 +1,17 @@
package com.netcracker.cloud.routesregistration.common.config;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.netcracker.cloud.restclient.MicroserviceRestClient;
-import io.reactivex.Scheduler;
-import io.reactivex.schedulers.Schedulers;
import com.netcracker.cloud.routesregistration.common.annotation.processing.RouteHostMapping;
import com.netcracker.cloud.routesregistration.common.gateway.route.*;
import com.netcracker.cloud.routesregistration.common.gateway.route.rest.RegistrationRequestFactory;
import com.netcracker.cloud.routesregistration.common.gateway.route.transformation.RouteTransformer;
+import com.netcracker.cloud.routesregistration.common.service.TopologyConfigService;
import com.netcracker.cloud.routesregistration.common.spring.gateway.route.RouteAnnotationProcessor;
import com.netcracker.cloud.routesregistration.common.spring.gateway.route.RouteFormatter;
import com.netcracker.cloud.routesregistration.common.spring.gateway.route.SpringControlPlaneClient;
+import io.reactivex.Scheduler;
+import io.reactivex.schedulers.Schedulers;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
@@ -20,6 +22,8 @@
import java.util.List;
import java.util.Optional;
+import static com.netcracker.cloud.routesregistration.common.gateway.route.ServiceMeshType.ISTIO;
+
@Configuration
public class RouteRegistrationProcessorConfiguration {
private final String microserviceName;
@@ -47,7 +51,7 @@ public RouteRegistrationProcessorConfiguration(@Value("${cloud.microservice.name
this.postRoutesEnabled = postRoutesEnabled;
this.cloudServiceName = microserviceName;
- if(deploymentVersion != null && !deploymentVersion.isEmpty()){
+ if (deploymentVersion != null && !deploymentVersion.isEmpty()) {
this.cloudServiceName += "-" + deploymentVersion;
}
}
@@ -98,7 +102,9 @@ RouteTransformer routeTransformer() {
RoutesRestRegistrationProcessor routesRestRegistrationProcessor(ControlPlaneClient controlPlaneClient,
RouteRetryManager routeRetryManager,
RouteTransformer routeTransformer,
- RegistrationRequestFactory registrationRequestFactory) {
+ RegistrationRequestFactory registrationRequestFactory,
+ TopologyConfigService topologyConfigService) {
+
String microserviceInternalURL = Utils.formatMicroserviceInternalURL(
cloudServiceName,
microserviceName,
@@ -111,7 +117,8 @@ RoutesRestRegistrationProcessor routesRestRegistrationProcessor(ControlPlaneClie
routeRetryManager,
routeTransformer,
registrationRequestFactory,
- postRoutesEnabled,
+ postRoutesEnabled
+ && topologyConfigService.getServiceMeshType() != ISTIO,
microserviceName,
microserviceInternalURL);
}
@@ -130,4 +137,9 @@ RouteFormatter routeFormatter() {
RoutesRegistrationDelayProvider routesRegistrationDelayProvider() {
return new RoutesRegistrationDelayProvider();
}
+
+ @Bean
+ TopologyConfigService topologyConfigService(ObjectMapper objectMapper) {
+ return new TopologyConfigService(objectMapper);
+ }
}
diff --git a/core-rest-libraries/route-registration/route-registration-common/pom.xml b/core-rest-libraries/route-registration/route-registration-common/pom.xml
index 87974cdad..d280d626b 100644
--- a/core-rest-libraries/route-registration/route-registration-common/pom.xml
+++ b/core-rest-libraries/route-registration/route-registration-common/pom.xml
@@ -31,6 +31,11 @@
org.slf4j
slf4j-api
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.20.2
+
org.junit.jupiter
diff --git a/core-rest-libraries/route-registration/route-registration-common/src/main/java/com/netcracker/cloud/routesregistration/common/gateway/route/ServiceMeshType.java b/core-rest-libraries/route-registration/route-registration-common/src/main/java/com/netcracker/cloud/routesregistration/common/gateway/route/ServiceMeshType.java
new file mode 100644
index 000000000..d366f18b2
--- /dev/null
+++ b/core-rest-libraries/route-registration/route-registration-common/src/main/java/com/netcracker/cloud/routesregistration/common/gateway/route/ServiceMeshType.java
@@ -0,0 +1,6 @@
+package com.netcracker.cloud.routesregistration.common.gateway.route;
+
+public enum ServiceMeshType {
+ CORE,
+ ISTIO
+}
diff --git a/core-rest-libraries/route-registration/route-registration-common/src/main/java/com/netcracker/cloud/routesregistration/common/gateway/route/Utils.java b/core-rest-libraries/route-registration/route-registration-common/src/main/java/com/netcracker/cloud/routesregistration/common/gateway/route/Utils.java
index 292c8376f..0f909a4c1 100644
--- a/core-rest-libraries/route-registration/route-registration-common/src/main/java/com/netcracker/cloud/routesregistration/common/gateway/route/Utils.java
+++ b/core-rest-libraries/route-registration/route-registration-common/src/main/java/com/netcracker/cloud/routesregistration/common/gateway/route/Utils.java
@@ -12,7 +12,7 @@ public static String formatMicroserviceInternalURL(String cloudServiceName,
String contextPath,
boolean postRoutesAppnameDisabled) {
String host = microserviceName;
- if (cloudServiceName != null &&! cloudServiceName.isEmpty()) {
+ if (cloudServiceName != null && !cloudServiceName.isEmpty()) {
host = cloudServiceName;
}
diff --git a/core-rest-libraries/route-registration/route-registration-common/src/main/java/com/netcracker/cloud/routesregistration/common/service/TopologyConfigService.java b/core-rest-libraries/route-registration/route-registration-common/src/main/java/com/netcracker/cloud/routesregistration/common/service/TopologyConfigService.java
new file mode 100644
index 000000000..2568d4a90
--- /dev/null
+++ b/core-rest-libraries/route-registration/route-registration-common/src/main/java/com/netcracker/cloud/routesregistration/common/service/TopologyConfigService.java
@@ -0,0 +1,78 @@
+package com.netcracker.cloud.routesregistration.common.service;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.netcracker.cloud.routesregistration.common.gateway.route.ServiceMeshType;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Optional;
+
+@Slf4j
+public class TopologyConfigService {
+ private static final String TOPOLOGY_CONFIG_PATH_DEFAULT = "/etc/topology.json";
+ private static final String SERVICE_MESH_TYPE_PATH = "/featureFlags/core/serviceMeshType";
+
+ private final ObjectMapper objectMapper;
+ private final String topologyConfigPath;
+
+ private volatile ServiceMeshType serviceMeshType;
+
+ public TopologyConfigService(ObjectMapper objectMapper) {
+ this.objectMapper = objectMapper;
+ this.topologyConfigPath = Optional.ofNullable(System.getenv("TOPOLOGY_CONFIG_PATH"))
+ .filter(s -> !s.isBlank())
+ .orElse(TOPOLOGY_CONFIG_PATH_DEFAULT);
+ }
+
+ // visible for testing
+ TopologyConfigService(ObjectMapper objectMapper, String topologyConfigPath) {
+ this.objectMapper = objectMapper;
+ this.topologyConfigPath = topologyConfigPath;
+ }
+
+ public ServiceMeshType getServiceMeshType() {
+ if (serviceMeshType != null) {
+ return serviceMeshType;
+ }
+ synchronized (this) {
+ if (serviceMeshType != null) {
+ return serviceMeshType;
+ }
+ serviceMeshType = loadServiceMeshType();
+ }
+ return serviceMeshType;
+ }
+
+ private ServiceMeshType loadServiceMeshType() {
+ try (InputStream inputStream = Files.newInputStream(Paths.get(topologyConfigPath))) {
+ JsonNode root = objectMapper.readTree(inputStream);
+ JsonNode node = root.at(SERVICE_MESH_TYPE_PATH);
+
+ if (node.isMissingNode() || node.isNull()) {
+ log.warn("'{}' not found in topology config, defaulting to {}", SERVICE_MESH_TYPE_PATH, ServiceMeshType.CORE);
+ return ServiceMeshType.CORE;
+ }
+
+ return parseServiceMeshType(node.asText());
+
+ } catch (IOException e) {
+ log.warn("Failed to read topology config from '{}', defaulting to {}", topologyConfigPath, ServiceMeshType.CORE, e);
+ return ServiceMeshType.CORE;
+ }
+ }
+
+ private ServiceMeshType parseServiceMeshType(String value) {
+ return Arrays.stream(ServiceMeshType.values())
+ .filter(type -> type.name().equalsIgnoreCase(value))
+ .findFirst()
+ .orElseGet(() -> {
+ log.warn("Unknown serviceMeshType '{}', defaulting to {}", value, ServiceMeshType.CORE);
+ return ServiceMeshType.CORE;
+ });
+ }
+}
diff --git a/core-rest-libraries/route-registration/route-registration-common/src/test/java/com/netcracker/cloud/routesregistration/common/service/TopologyConfigServiceTest.java b/core-rest-libraries/route-registration/route-registration-common/src/test/java/com/netcracker/cloud/routesregistration/common/service/TopologyConfigServiceTest.java
new file mode 100644
index 000000000..65f871e4a
--- /dev/null
+++ b/core-rest-libraries/route-registration/route-registration-common/src/test/java/com/netcracker/cloud/routesregistration/common/service/TopologyConfigServiceTest.java
@@ -0,0 +1,94 @@
+package com.netcracker.cloud.routesregistration.common.service;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.netcracker.cloud.routesregistration.common.gateway.route.ServiceMeshType;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class TopologyConfigServiceTest {
+
+ private static final ObjectMapper objectMapper = new ObjectMapper();
+
+ private TopologyConfigService service(String content) throws IOException {
+ Path file = Files.createTempFile("topology", ".json");
+ Files.writeString(file, content);
+ file.toFile().deleteOnExit();
+ return new TopologyConfigService(objectMapper, file.toString());
+ }
+
+ private TopologyConfigService serviceWithPath(String path) {
+ return new TopologyConfigService(objectMapper, path);
+ }
+
+ @Test
+ void defaultsToCoreWhenFileNotFound() {
+ TopologyConfigService service = serviceWithPath("/nonexistent/topology.json");
+ assertEquals(ServiceMeshType.CORE, service.getServiceMeshType());
+ }
+
+ @Test
+ void defaultsToCoreWhenFileIsMalformed() throws IOException {
+ TopologyConfigService service = service("not valid json");
+ assertEquals(ServiceMeshType.CORE, service.getServiceMeshType());
+ }
+
+ @Test
+ void defaultsToCoreWhenNodeIsMissing() throws IOException {
+ TopologyConfigService service = service("{}");
+ assertEquals(ServiceMeshType.CORE, service.getServiceMeshType());
+ }
+
+ @Test
+ void defaultsToCoreWhenServiceMeshTypeIsNull() throws IOException {
+ TopologyConfigService service = service("""
+ {"featureFlags":{"core":{"serviceMeshType":null}}}
+ """);
+ assertEquals(ServiceMeshType.CORE, service.getServiceMeshType());
+ }
+
+ @Test
+ void defaultsToCoreWhenServiceMeshTypeIsUnknown() throws IOException {
+ TopologyConfigService service = service("""
+ {"featureFlags":{"core":{"serviceMeshType":"UNKNOWN"}}}
+ """);
+ assertEquals(ServiceMeshType.CORE, service.getServiceMeshType());
+ }
+
+ @Test
+ void returnsCoreWhenServiceMeshTypeIsCore() throws IOException {
+ TopologyConfigService service = service("""
+ {"featureFlags":{"core":{"serviceMeshType":"CORE"}}}
+ """);
+ assertEquals(ServiceMeshType.CORE, service.getServiceMeshType());
+ }
+
+ @Test
+ void returnsIstioWhenServiceMeshTypeIsIstio() throws IOException {
+ TopologyConfigService service = service("""
+ {"featureFlags":{"core":{"serviceMeshType":"ISTIO"}}}
+ """);
+ assertEquals(ServiceMeshType.ISTIO, service.getServiceMeshType());
+ }
+
+ @Test
+ void isCaseInsensitive() throws IOException {
+ TopologyConfigService service = service("""
+ {"featureFlags":{"core":{"serviceMeshType":"istio"}}}
+ """);
+ assertEquals(ServiceMeshType.ISTIO, service.getServiceMeshType());
+ }
+
+ @Test
+ void cachesResultOnSubsequentCalls() throws IOException {
+ TopologyConfigService service = service("""
+ {"featureFlags":{"core":{"serviceMeshType":"ISTIO"}}}
+ """);
+ assertEquals(ServiceMeshType.ISTIO, service.getServiceMeshType());
+ assertEquals(ServiceMeshType.ISTIO, service.getServiceMeshType());
+ }
+}