diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index e96daa3a8e..2c0e27c314 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -1093,6 +1093,13 @@ jobs: image: ghcr.io/balhar-jakub/api-catalog-services:${{ github.run_id }}-${{ github.run_number }} volumes: - /api-defs:/api-defs + api-catalog-services-2: + image: ghcr.io/balhar-jakub/api-catalog-services:${{ github.run_id }}-${{ github.run_number }} + volumes: + - /api-defs:/api-defs + env: + APIML_SERVICE_HOSTNAME: api-catalog-services-2 + APIML_HEALTH_PROTECTED: false caching-service: image: ghcr.io/balhar-jakub/caching-service:${{ github.run_id }}-${{ github.run_number }} discoverable-client: diff --git a/apiml/src/main/java/org/zowe/apiml/EurekaHealthIndicatorApiml.java b/apiml/src/main/java/org/zowe/apiml/EurekaHealthIndicatorApiml.java new file mode 100644 index 0000000000..a4c7e4d007 --- /dev/null +++ b/apiml/src/main/java/org/zowe/apiml/EurekaHealthIndicatorApiml.java @@ -0,0 +1,62 @@ +/* + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Copyright Contributors to the Zowe Project. + */ + +package org.zowe.apiml; + +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.Status; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.netflix.eureka.EurekaHealthIndicator; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.stream.Collectors; + +/** + * This class is replacement of org.springframework.cloud.netflix.eureka.EurekaHealthIndicator, because it is using + * a different Eureka client + */ +@Primary +@Component("eurekaHealthIndicator") +public class EurekaHealthIndicatorApiml extends EurekaHealthIndicator { + + private DiscoveryClient discoveryClient; + + public EurekaHealthIndicatorApiml(DiscoveryClient discoveryClient) { + super(null, null, null); + this.discoveryClient = discoveryClient; + } + + @Override + public String getName() { + return "eureka"; + } + + @Override + public Health health() { + Health.Builder builder = Health.unknown(); + Status status = getStatus(builder); + return builder.status(status).withDetail("applications", getApplications()).build(); + } + + private Status getStatus(Health.Builder builder) { + return new Status("UP", "Eureka discovery client has not yet successfully connected to a Eureka server"); + } + + private Map getApplications() { + return discoveryClient.getServices().stream() + .collect(Collectors.toMap( + String::toLowerCase, + serviceId -> discoveryClient.getInstances(serviceId).size()) + ); + } + +} diff --git a/integration-tests/src/test/java/org/zowe/apiml/startup/impl/ApiMediationLayerStartupChecker.java b/integration-tests/src/test/java/org/zowe/apiml/startup/impl/ApiMediationLayerStartupChecker.java index 6ba06ec4dc..e1772b9355 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/startup/impl/ApiMediationLayerStartupChecker.java +++ b/integration-tests/src/test/java/org/zowe/apiml/startup/impl/ApiMediationLayerStartupChecker.java @@ -15,26 +15,23 @@ import com.jayway.jsonpath.PathNotFoundException; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import net.minidev.json.JSONArray; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.methods.HttpGet; +import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; -import org.zowe.apiml.util.config.ConfigReader; -import org.zowe.apiml.util.config.Credentials; -import org.zowe.apiml.util.config.DiscoverableClientConfiguration; -import org.zowe.apiml.util.config.DiscoveryServiceConfiguration; -import org.zowe.apiml.util.config.GatewayServiceConfiguration; -import org.zowe.apiml.util.config.SslContext; +import org.zowe.apiml.product.constants.CoreService; +import org.zowe.apiml.util.config.*; import org.zowe.apiml.util.http.HttpClientUtils; import org.zowe.apiml.util.http.HttpRequestUtils; import java.io.IOException; -import java.util.ArrayList; -import java.util.Base64; -import java.util.List; +import java.util.*; +import java.util.stream.Stream; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.SECONDS; @@ -48,26 +45,20 @@ public class ApiMediationLayerStartupChecker { private static final boolean IS_MODULITH_ENABLED = Boolean.parseBoolean(System.getProperty("environment.modulith")); - private final GatewayServiceConfiguration gatewayConfiguration; - private final DiscoverableClientConfiguration discoverableClientConfiguration; - private final DiscoveryServiceConfiguration discoveryServiceConfiguration; - private final Credentials credentials; + private final String authorizationHeader; private final List servicesToCheck = new ArrayList<>(); private final String healthEndpoint = "/application/health"; - public ApiMediationLayerStartupChecker() { - gatewayConfiguration = ConfigReader.environmentConfiguration().getGatewayServiceConfiguration(); - credentials = ConfigReader.environmentConfiguration().getCredentials(); - discoverableClientConfiguration = ConfigReader.environmentConfiguration().getDiscoverableClientConfiguration(); - discoveryServiceConfiguration = ConfigReader.environmentConfiguration().getDiscoveryServiceConfiguration(); + var credentials = ConfigReader.environmentConfiguration().getCredentials(); + authorizationHeader = "Basic " + Base64.getEncoder().encodeToString(String.format("%s:%s", credentials.getUser(), credentials.getPassword()).getBytes()); - servicesToCheck.add(new Service("Gateway", "$.status")); + servicesToCheck.add(new Service("Gateway", "$.status", ConfigReader.environmentConfiguration().getGatewayServiceConfiguration())); if (!IS_MODULITH_ENABLED) { - servicesToCheck.add(new Service("ZAAS", "$.components.gateway.details.zaas")); + servicesToCheck.add(new Service("ZAAS", "$.components.gateway.details.zaas", ConfigReader.environmentConfiguration().getZaasConfiguration())); } - servicesToCheck.add(new Service("Api Catalog", "$.components.gateway.details.apicatalog")); - servicesToCheck.add(new Service("Discovery Service", "$.components.gateway.details.discovery")); + servicesToCheck.add(new Service("Api Catalog", "$.components.gateway.details.apicatalog", ConfigReader.environmentConfiguration().getApiCatalogServiceConfiguration())); + servicesToCheck.add(new Service("Discovery Service", "$.components.gateway.details.discovery", ConfigReader.environmentConfiguration().getDiscoveryServiceConfiguration())); } public void waitUntilReady() { @@ -76,10 +67,10 @@ public void waitUntilReady() { .atMost(10, MINUTES) .pollDelay(0, SECONDS) .pollInterval(poolInterval, SECONDS) - .until(this::areAllServicesUp); + .until(this::isApimlReady); } - private DocumentContext getDocumentAsContext(HttpGet request) { + private static DocumentContext getDocumentAsContext(HttpGet request) { try { final HttpResponse response = HttpClientUtils.client().execute(request); if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { @@ -99,92 +90,189 @@ private DocumentContext getDocumentAsContext(HttpGet request) { } } - private boolean areAllServicesUp() { + private boolean isApimlReady() { try { - var gatewayHosts = gatewayConfiguration.getHost().split(","); - var requestToGateway1 = HttpRequestUtils.getRequest(gatewayHosts[0], healthEndpoint); - // If second one does not exist, redundant call and check to same gateway - var requestToGateway2 = HttpRequestUtils.getRequest(gatewayHosts.length > 1 ? gatewayHosts[1] : gatewayHosts[0], healthEndpoint); + return Stream.of( + checkHealthEndpointWithEureka(ConfigReader.environmentConfiguration().getZaasConfiguration()), + checkHealthEndpointWithEureka(ConfigReader.environmentConfiguration().getGatewayServiceConfiguration()), + // Consider properly the case with multiple gateway services running on different ports. + callInternalPorts(), + allServicesAreUp() + ).allMatch(x -> x); + } catch (Exception e) { + log.error("Error during checking if APIML is up", e); + return false; + } + } - requestToGateway1.addHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString(String.format("%s:%s", credentials.getUser(), credentials.getPassword()).getBytes())); - requestToGateway2.addHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString(String.format("%s:%s", credentials.getUser(), credentials.getPassword()).getBytes())); - DocumentContext context1 = getDocumentAsContext(requestToGateway1); - DocumentContext context2 = getDocumentAsContext(requestToGateway2); + private String getHealthEndpoint(ServiceConfiguration serviceConfiguration, String host) { + String path = healthEndpoint; + if (serviceConfiguration instanceof ApiCatalogServiceConfiguration) { + path = "/apicatalog" + path; + } + return String.format("%s://%s:%d%s", serviceConfiguration.getScheme(), host, serviceConfiguration.getPort(), path); + } + + private boolean allServicesAreUp() { + return servicesToCheck.stream() + .map(service -> service.configuration) + .filter(service -> !IS_MODULITH_ENABLED || !isModulithComponent(service.getServiceId())) + .flatMap(service -> Arrays.stream(service.getHost().split(",")) + .map(host -> getHealthEndpoint(service, host)) + .map(HttpGet::new) + .map(request -> { + request.addHeader("Authorization", authorizationHeader); + DocumentContext context = getDocumentAsContext(request); + boolean response = (context != null) && "UP".equals(context.read("$.status")); + if (!response) { + log.debug("Service {} is not ready at {} : {}", service.getServiceId(), request.getURI(), context); + } + return response; + }) + ).allMatch(x -> x); + } + + private boolean checkHealthEndpointWithEureka(ServiceConfiguration serviceConfiguration) { + if (serviceConfiguration == null) { + return true; + } + return Arrays.stream(serviceConfiguration.getHost().split(",")) + .map(host -> getHealthEndpoint(serviceConfiguration, host)) + .map(HttpGet::new) + .allMatch(request -> { + request.addHeader("Authorization", authorizationHeader); + DocumentContext context = getDocumentAsContext(request); + + return isApimlReadyByFullHealthEndpoint(context, request.getURI().getHost()); + }); + } - if (context1 == null || context2 == null) { + private boolean isApimlReadyByFullHealthEndpoint(DocumentContext context, String host) { + try { + if (context == null) { return false; } + JSONArray servicesJsonArray = context.read("$.components.discoveryComposite.components.discoveryClient.details.services"); + List services = servicesJsonArray.stream().map(Objects::toString).map(String::toLowerCase).toList(); + boolean areAllServicesUp = true; for (Service toCheck : servicesToCheck) { - boolean isUp = isServiceUp(context1, toCheck.path); - logDebug(toCheck.name + " is {}", isUp); - - if (!isUp) { - areAllServicesUp = false; + if (toCheck.configuration instanceof GatewayServiceConfiguration) { + boolean isUp = isServiceUp(context, toCheck.path); + logDebug(toCheck.name + " is {}", isUp); + areAllServicesUp &= isUp; } + areAllServicesUp &= services.contains(toCheck.configuration.getServiceId().toLowerCase()); + areAllServicesUp &= checkServicesCount(context, toCheck.configuration, host); } if (!IS_MODULITH_ENABLED && !isAuthUp()) { areAllServicesUp = false; } - String allComponents = context1.read("$.components.discoveryComposite.components.discoveryClient.details.services").toString(); - boolean isTestApplicationUp = allComponents.toLowerCase().contains("discoverableclient"); - boolean needsTestApplication = discoverableClientConfiguration.getInstances() > 0; + if (!areAllServicesUp) { + log.debug("API ML is not ready, check which services are missing in the above messages"); + } + + return areAllServicesUp; + } catch (PathNotFoundException e) { + log.warn("Check failed on retrieving the information from document: {}", e.getMessage()); + return false; + } + } + + private boolean isModulithComponent(String serviceId) { + return StringUtils.equalsAnyIgnoreCase(serviceId, + CoreService.API_CATALOG.getServiceId(), + CoreService.CACHING.getServiceId(), + CoreService.ZAAS.getServiceId(), + CoreService.DISCOVERY.getServiceId() + ); + } + + private V getService(Map map, String key) { + V out = map.get(key.toLowerCase()); + if (out == null) { + out = map.get(key.toUpperCase()); + } + if (out == null) { + out = map.entrySet().stream() + .filter(e -> key.equalsIgnoreCase(e.getKey())) + .map(Map.Entry::getValue) + .findFirst() + .orElseThrow(() -> new NullPointerException("Cannot find record for " + key)); + } + return out; + } - log.debug("Discoverable Client is {}", isTestApplicationUp); - log.debug("Needs Discoverable Client: {}", needsTestApplication); - isTestApplicationUp = !needsTestApplication || isTestApplicationUp; + private boolean checkServicesCount(DocumentContext context, ServiceConfiguration serviceConfiguration, String gatewayHost) { + if (serviceConfiguration.getInstances() == 0) { + return true; + } - Integer amountOfActiveGateways1 = context1.read("$.components.gateway.details.gatewayCount"); - Integer amountOfActiveGateways2 = context2.read("$.components.gateway.details.gatewayCount"); - var expectedGatewayCount = Integer.getInteger("environment.gwCount", gatewayConfiguration.getInstances()); + Map services = context.read("$.components.discoveryComposite.components.eureka.details.applications"); + Integer amountOfActiveService = getService(services, serviceConfiguration.getServiceId()); + if (amountOfActiveService == null) { + amountOfActiveService = services.get(serviceConfiguration.getServiceId().toUpperCase()); + } + var expectedCount = serviceConfiguration.getInstances(); + if (serviceConfiguration instanceof GatewayServiceConfiguration) { + expectedCount = Integer.getInteger("environment.gwCount", expectedCount); + } - boolean isValidAmountOfGatewaysUp = amountOfActiveGateways1 != null && amountOfActiveGateways2 != null && - amountOfActiveGateways1 >= expectedGatewayCount && amountOfActiveGateways2 >= expectedGatewayCount; - log.debug("There are {} gateways in GW1 and {} in GW2", amountOfActiveGateways1, amountOfActiveGateways2); + if (IS_MODULITH_ENABLED && isModulithComponent(serviceConfiguration.getServiceId())) { + expectedCount = Math.min(expectedCount, 1); + } - if (!isValidAmountOfGatewaysUp) { - log.debug("Expecting at least {} gateways", gatewayConfiguration.getInstances()); - callEurekaApps(); - return false; - } + boolean isValidAmountOfServicesUp = amountOfActiveService != null && + amountOfActiveService >= expectedCount; + log.debug("There are {} {} in GW on {}", amountOfActiveService, serviceConfiguration.getServiceId(), gatewayHost); - // Consider properly the case with multiple gateway services running on different ports. - if (gatewayConfiguration.getInternalPorts() != null && !gatewayConfiguration.getInternalPorts().isEmpty()) { - String[] internalPorts = gatewayConfiguration.getInternalPorts().split(","); - String[] hosts = gatewayConfiguration.getHost().split(","); + if (!isValidAmountOfServicesUp) { + log.debug("Expecting at least {} services ({})", expectedCount, serviceConfiguration.getServiceId()); + callEurekaApps(); + return false; + } - for (int i = 0; i < Math.min(internalPorts.length, hosts.length); i++) { - log.debug("Trying to access the Gateway at port {}", internalPorts[i]); - requestToGateway1 = HttpRequestUtils.getRequest(healthEndpoint); - requestToGateway1.addHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString(String.format("%s:%s", credentials.getUser(), credentials.getPassword()).getBytes())); - var response = HttpClientUtils.client().execute(requestToGateway1); + return true; + } - if (response.getStatusLine().getStatusCode() != 200) { - log.debug("Response from gateway at {} was: {}", requestToGateway1.getURI(), response.getEntity() != null ? EntityUtils.toString(response.getEntity()) : "undefined"); - throw new IOException(); - } + private boolean callInternalPorts() { + var gatewayConfiguration = ConfigReader.environmentConfiguration().getGatewayServiceConfiguration(); - } + if (StringUtils.isBlank(gatewayConfiguration.getInternalPorts())) { + log.debug("No internal ports are defined"); + return true; + } - } + String[] internalPorts = gatewayConfiguration.getInternalPorts().split(","); + String[] hosts = gatewayConfiguration.getHost().split(","); - var result = areAllServicesUp && isTestApplicationUp; - if (!result) { - log.debug("API ML is not ready, check which services are missing in the above messages"); - } + for (int i = 0; i < Math.min(internalPorts.length, hosts.length); i++) { + log.debug("Trying to access the Gateway at port {}", internalPorts[i]); + var requestToGateway = HttpRequestUtils.getRequest(healthEndpoint); + requestToGateway.addHeader("Authorization", authorizationHeader); + try { + var response = HttpClientUtils.client().execute(requestToGateway); - return result; - } catch (PathNotFoundException | IOException e) { - log.warn("Check failed on retrieving the information from document: {}", e.getMessage()); - return false; + if (response.getStatusLine().getStatusCode() != 200) { + log.debug("Response from gateway at {} was: {}", requestToGateway.getURI(), response.getEntity() != null ? EntityUtils.toString(response.getEntity()) : "undefined"); + return false; + } + } catch (IOException ioException) { + return false; + } } + return true; } private void callEurekaApps() { + var discoveryServiceConfiguration = ConfigReader.environmentConfiguration().getDiscoveryServiceConfiguration(); HttpGet requestToEurekaApps = new HttpGet(HttpRequestUtils.getUriFromService(discoveryServiceConfiguration, "/eureka/apps")); - CloseableHttpClient client = HttpClients.custom().setSSLContext(SslContext.sslClientCertValid).build(); + CloseableHttpClient client = HttpClients.custom() + .setSSLContext(SslContext.sslClientCertValid) + .setSSLHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) + .build(); try (client) { var response = client.execute(requestToEurekaApps); var entity = response.getEntity(); @@ -205,7 +293,7 @@ private boolean isAuthUp() { } else { requestToZaas = new HttpGet(HttpRequestUtils.getUriFromGateway(healthEndpoint)); } - requestToZaas.addHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString(String.format("%s:%s", credentials.getUser(), credentials.getPassword()).getBytes())); + requestToZaas.addHeader("Authorization", authorizationHeader); DocumentContext zaasContext = getDocumentAsContext(requestToZaas); if (zaasContext == null) { return false; @@ -230,7 +318,11 @@ private void logDebug(String logMessage, boolean state) { @AllArgsConstructor private class Service { + String name; String path; + ServiceConfiguration configuration; + } + } diff --git a/integration-tests/src/test/java/org/zowe/apiml/util/config/ApiCatalogServiceConfiguration.java b/integration-tests/src/test/java/org/zowe/apiml/util/config/ApiCatalogServiceConfiguration.java index 7e30cbb3f2..1f1a482b63 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/util/config/ApiCatalogServiceConfiguration.java +++ b/integration-tests/src/test/java/org/zowe/apiml/util/config/ApiCatalogServiceConfiguration.java @@ -13,14 +13,22 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.zowe.apiml.product.constants.CoreService; @Data @AllArgsConstructor @NoArgsConstructor public class ApiCatalogServiceConfiguration implements ServiceConfiguration { + private String scheme; private String url; private String host; private int port; private int instances; + + @Override + public String getServiceId() { + return CoreService.API_CATALOG.getServiceId(); + } + } diff --git a/integration-tests/src/test/java/org/zowe/apiml/util/config/CachingServiceConfiguration.java b/integration-tests/src/test/java/org/zowe/apiml/util/config/CachingServiceConfiguration.java index eca6eeba76..4dbebed7f6 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/util/config/CachingServiceConfiguration.java +++ b/integration-tests/src/test/java/org/zowe/apiml/util/config/CachingServiceConfiguration.java @@ -13,6 +13,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.zowe.apiml.product.constants.CoreService; @Data @AllArgsConstructor @@ -36,4 +37,9 @@ public int getPort() { throw new IllegalStateException("Method is not implemented"); } + @Override + public String getServiceId() { + return CoreService.CACHING.getServiceId(); + } + } diff --git a/integration-tests/src/test/java/org/zowe/apiml/util/config/CentralGatewayServiceConfiguration.java b/integration-tests/src/test/java/org/zowe/apiml/util/config/CentralGatewayServiceConfiguration.java index 322b967735..868b53f499 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/util/config/CentralGatewayServiceConfiguration.java +++ b/integration-tests/src/test/java/org/zowe/apiml/util/config/CentralGatewayServiceConfiguration.java @@ -13,6 +13,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.zowe.apiml.product.constants.CoreService; @Data @AllArgsConstructor @@ -23,4 +24,9 @@ public class CentralGatewayServiceConfiguration implements ServiceConfiguration private String host; private int port; + @Override + public String getServiceId() { + return "centralGateway"; + } + } diff --git a/integration-tests/src/test/java/org/zowe/apiml/util/config/DiscoverableClientConfiguration.java b/integration-tests/src/test/java/org/zowe/apiml/util/config/DiscoverableClientConfiguration.java index cb2d706cfa..beccb25992 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/util/config/DiscoverableClientConfiguration.java +++ b/integration-tests/src/test/java/org/zowe/apiml/util/config/DiscoverableClientConfiguration.java @@ -13,6 +13,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.zowe.apiml.product.constants.CoreService; /** * Configuration parameters for DiscoverableClient @@ -21,9 +22,16 @@ @NoArgsConstructor @AllArgsConstructor public class DiscoverableClientConfiguration implements ServiceConfiguration { + private String scheme; private String applId; private String host; private int port; private int instances; + + @Override + public String getServiceId() { + return "discoverableclient"; + } + } diff --git a/integration-tests/src/test/java/org/zowe/apiml/util/config/DiscoveryServiceConfiguration.java b/integration-tests/src/test/java/org/zowe/apiml/util/config/DiscoveryServiceConfiguration.java index 43843846eb..1d582469dd 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/util/config/DiscoveryServiceConfiguration.java +++ b/integration-tests/src/test/java/org/zowe/apiml/util/config/DiscoveryServiceConfiguration.java @@ -13,11 +13,13 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.zowe.apiml.product.constants.CoreService; @Data @AllArgsConstructor @NoArgsConstructor public class DiscoveryServiceConfiguration implements ServiceConfiguration { + private String scheme; private String user; private String password; @@ -26,5 +28,11 @@ public class DiscoveryServiceConfiguration implements ServiceConfiguration { private int port; private int additionalPort; private int instances; + + @Override + public String getServiceId() { + return CoreService.DISCOVERY.getServiceId(); + } + } diff --git a/integration-tests/src/test/java/org/zowe/apiml/util/config/GatewayServiceConfiguration.java b/integration-tests/src/test/java/org/zowe/apiml/util/config/GatewayServiceConfiguration.java index 8978dd2879..0e8aa3b020 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/util/config/GatewayServiceConfiguration.java +++ b/integration-tests/src/test/java/org/zowe/apiml/util/config/GatewayServiceConfiguration.java @@ -13,11 +13,13 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.zowe.apiml.product.constants.CoreService; @Data @AllArgsConstructor @NoArgsConstructor public class GatewayServiceConfiguration implements ServiceConfiguration { + private String scheme; private String host; private String dvipaHost; @@ -27,4 +29,10 @@ public class GatewayServiceConfiguration implements ServiceConfiguration { private String internalPorts; private String servicesEndpoint; private int bucketCapacity; + + @Override + public String getServiceId() { + return CoreService.GATEWAY.getServiceId(); + } + } diff --git a/integration-tests/src/test/java/org/zowe/apiml/util/config/ServiceConfiguration.java b/integration-tests/src/test/java/org/zowe/apiml/util/config/ServiceConfiguration.java index 58687487ae..0b1f598eab 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/util/config/ServiceConfiguration.java +++ b/integration-tests/src/test/java/org/zowe/apiml/util/config/ServiceConfiguration.java @@ -10,10 +10,22 @@ package org.zowe.apiml.util.config; +import org.apache.commons.lang3.StringUtils; + public interface ServiceConfiguration { String getScheme(); String getHost(); int getPort(); + default int getInstances() { + var host = getHost(); + if (StringUtils.isBlank(host)) { + return 0; + } + return getHost().split(",").length; + } + + String getServiceId(); + } diff --git a/integration-tests/src/test/java/org/zowe/apiml/util/config/ZaasConfiguration.java b/integration-tests/src/test/java/org/zowe/apiml/util/config/ZaasConfiguration.java index 2933c6785f..c27708494c 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/util/config/ZaasConfiguration.java +++ b/integration-tests/src/test/java/org/zowe/apiml/util/config/ZaasConfiguration.java @@ -13,13 +13,21 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.zowe.apiml.product.constants.CoreService; @Data @AllArgsConstructor @NoArgsConstructor public class ZaasConfiguration implements ServiceConfiguration { + private String scheme; private String host; private int port; private int instances; + + @Override + public String getServiceId() { + return CoreService.ZAAS.getServiceId(); + } + } diff --git a/integration-tests/src/test/java/org/zowe/apiml/util/config/ZosmfServiceConfiguration.java b/integration-tests/src/test/java/org/zowe/apiml/util/config/ZosmfServiceConfiguration.java index 306a268d6a..5521017850 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/util/config/ZosmfServiceConfiguration.java +++ b/integration-tests/src/test/java/org/zowe/apiml/util/config/ZosmfServiceConfiguration.java @@ -18,9 +18,11 @@ @AllArgsConstructor @NoArgsConstructor public class ZosmfServiceConfiguration implements ServiceConfiguration { + private String scheme; private String host; private int port; private String serviceId; private String contextRoot; + } diff --git a/integration-tests/src/test/resources/environment-configuration-ha.yml b/integration-tests/src/test/resources/environment-configuration-ha.yml index c9be90c682..c1d29886db 100644 --- a/integration-tests/src/test/resources/environment-configuration-ha.yml +++ b/integration-tests/src/test/resources/environment-configuration-ha.yml @@ -13,7 +13,7 @@ gatewayServiceConfiguration: bucketCapacity: 20 zaasConfiguration: scheme: https - host: zaas-service + host: zaas-service,zaas-service-2 port: 10023 discoveryServiceConfiguration: scheme: https