From 777246a849b1adf597a4fa6f34d49b4f9231f38c Mon Sep 17 00:00:00 2001 From: sj895092 Date: Wed, 27 Nov 2024 14:49:45 +0100 Subject: [PATCH 01/37] server drop down fix Signed-off-by: sj895092 --- .../src/components/Swagger/SwaggerUIApiml.jsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx index 8fd836cb4c..49c6e52c21 100644 --- a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx +++ b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx @@ -15,18 +15,18 @@ import getBaseUrl from '../../helpers/urls'; import { CustomizedSnippedGenerator } from '../../utils/generateSnippets'; import { AdvancedFilterPlugin } from '../../utils/filterApis'; -function transformSwaggerToCurrentHost(swagger) { +function transformSwaggerToCurrentHost(swagger, serviceURL) { swagger.host = window.location.host; if (swagger.servers !== null && swagger.servers !== undefined) { swagger.servers.forEach((server) => { - const location = `${window.location.protocol}//${window.location.host}`; try { const swaggerUrl = new URL(server.url); - server.url = location + swaggerUrl.pathname; + server.url = serviceURL + swaggerUrl.pathname.replace("/", ""); } catch (e) { // not a proper url, assume it is an endpoint - server.url = location + server; + server.url = serviceURL + server; + } }); } @@ -130,11 +130,15 @@ export default class SwaggerUIApiml extends Component { // If no version selected use the default apiDoc if ( (selectedVersion === null || selectedVersion === undefined) && + selectedService.baseUrl !== null && + selectedService.baseUrl !== undefined && selectedService.apiDoc !== null && selectedService.apiDoc !== undefined && selectedService.apiDoc.length !== 0 ) { - const swagger = transformSwaggerToCurrentHost(JSON.parse(selectedService.apiDoc)); + console.log("selected service " + selectedService.homePageUrl); + console.log("selected service " + selectedService.baseUrl); + const swagger = transformSwaggerToCurrentHost(JSON.parse(selectedService.apiDoc), selectedService.baseUrl); this.setState({ swaggerReady: true, @@ -161,7 +165,7 @@ export default class SwaggerUIApiml extends Component { plugins: [this.customPlugins, AdvancedFilterPlugin, CustomizedSnippedGenerator(codeSnippets)], responseInterceptor: (res) => { // response.text field is used to render the swagger - const swagger = transformSwaggerToCurrentHost(JSON.parse(res.text)); + const swagger = transformSwaggerToCurrentHost(JSON.parse(res.text),selectedService.baseUrl); res.text = JSON.stringify(swagger); return res; }, From 7a36dabb7e1bfece933a55839a218755fb4b91b7 Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Wed, 27 Nov 2024 17:30:18 +0100 Subject: [PATCH 02/37] wip - fix Signed-off-by: Andrea Tabone --- .../src/components/Swagger/SwaggerUIApiml.jsx | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx index 49c6e52c21..88cd08bf78 100644 --- a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx +++ b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx @@ -15,17 +15,19 @@ import getBaseUrl from '../../helpers/urls'; import { CustomizedSnippedGenerator } from '../../utils/generateSnippets'; import { AdvancedFilterPlugin } from '../../utils/filterApis'; -function transformSwaggerToCurrentHost(swagger, serviceURL) { +function transformSwaggerToCurrentHost(swagger, selectedService) { swagger.host = window.location.host; if (swagger.servers !== null && swagger.servers !== undefined) { swagger.servers.forEach((server) => { try { const swaggerUrl = new URL(server.url); - server.url = serviceURL + swaggerUrl.pathname.replace("/", ""); + const updatedPathname = swaggerUrl.pathname.replace(/^\/[^/]+/, selectedService.serviceId); + // Rebuild the server URL with the new pathname + server.url = selectedService.baseUrl + updatedPathname; } catch (e) { // not a proper url, assume it is an endpoint - server.url = serviceURL + server; + server.url = selectedService.baseUrl + server; } }); @@ -129,16 +131,12 @@ export default class SwaggerUIApiml extends Component { try { // If no version selected use the default apiDoc if ( - (selectedVersion === null || selectedVersion === undefined) && - selectedService.baseUrl !== null && - selectedService.baseUrl !== undefined && - selectedService.apiDoc !== null && - selectedService.apiDoc !== undefined && - selectedService.apiDoc.length !== 0 + !selectedVersion && + selectedService?.serviceId && + selectedService?.baseUrl && + selectedService?.apiDoc?.length ) { - console.log("selected service " + selectedService.homePageUrl); - console.log("selected service " + selectedService.baseUrl); - const swagger = transformSwaggerToCurrentHost(JSON.parse(selectedService.apiDoc), selectedService.baseUrl); + const swagger = transformSwaggerToCurrentHost(JSON.parse(selectedService.apiDoc), selectedService); this.setState({ swaggerReady: true, @@ -152,7 +150,7 @@ export default class SwaggerUIApiml extends Component { }, }); } - if (selectedVersion !== null && selectedVersion !== undefined) { + if (selectedVersion) { const basePath = `${selectedService.serviceId}/${selectedVersion}`; const url = `${getBaseUrl()}${process.env.REACT_APP_APIDOC_UPDATE}/${basePath}`; this.setState({ @@ -165,7 +163,7 @@ export default class SwaggerUIApiml extends Component { plugins: [this.customPlugins, AdvancedFilterPlugin, CustomizedSnippedGenerator(codeSnippets)], responseInterceptor: (res) => { // response.text field is used to render the swagger - const swagger = transformSwaggerToCurrentHost(JSON.parse(res.text),selectedService.baseUrl); + const swagger = transformSwaggerToCurrentHost(JSON.parse(res.text), selectedService); res.text = JSON.stringify(swagger); return res; }, From 6900bb2774c23f173623b7fef541287d6fefeab9 Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Wed, 27 Nov 2024 17:39:17 +0100 Subject: [PATCH 03/37] distinguish between gw and other services Signed-off-by: Andrea Tabone --- .../src/components/Swagger/SwaggerUIApiml.jsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx index 88cd08bf78..2821117267 100644 --- a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx +++ b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx @@ -22,9 +22,15 @@ function transformSwaggerToCurrentHost(swagger, selectedService) { swagger.servers.forEach((server) => { try { const swaggerUrl = new URL(server.url); - const updatedPathname = swaggerUrl.pathname.replace(/^\/[^/]+/, selectedService.serviceId); - // Rebuild the server URL with the new pathname - server.url = selectedService.baseUrl + updatedPathname; + // if it's not a GW instance, use the URL from the browser + if (!swaggerUrl.pathname.includes("gateway")) { + const location = `${window.location.protocol}//${window.location.host}`; + server.url = location + swaggerUrl.pathname; + } else { + // if it's a GW instance, construct the server URL by using the base URL and service ID of the specific instance + const updatedPathname = swaggerUrl.pathname.replace(/^\/[^/]+/, selectedService.serviceId); + server.url = selectedService.baseUrl + updatedPathname; + } } catch (e) { // not a proper url, assume it is an endpoint server.url = selectedService.baseUrl + server; From bc6ab4f493228d4cccc0b7e6cb996d6c3565944d Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Fri, 29 Nov 2024 11:26:48 +0100 Subject: [PATCH 04/37] wip - update basePathn for additional GW Signed-off-by: Andrea Tabone --- .../apicatalog/services/cached/CachedProductFamilyService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java index 03cb15e6dc..9803f3847b 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java @@ -384,9 +384,10 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { String title = instanceInfo.getMetadata().get(SERVICE_TITLE); if (StringUtils.equalsIgnoreCase(GATEWAY.getServiceId(), serviceId)) { if (RegistrationType.of(instanceInfo.getMetadata()).isAdditional()) { - // additional registration for GW means domain one, update serviceId with the ApimlId + // additional registration for GW means domain one, update serviceId and basePath with the ApimlId String apimlId = instanceInfo.getMetadata().get(APIML_ID); if (apimlId != null) { + apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), apimlId); serviceId = apimlId; title += " (" + apimlId + ")"; } From 6875f5dd38738c7f2b4b295a5498daf259e05c60 Mon Sep 17 00:00:00 2001 From: sj895092 Date: Mon, 2 Dec 2024 13:40:33 +0100 Subject: [PATCH 05/37] adding apimlid to the URL Signed-off-by: sj895092 --- api-catalog-ui/frontend/src/helpers/urls.jsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/api-catalog-ui/frontend/src/helpers/urls.jsx b/api-catalog-ui/frontend/src/helpers/urls.jsx index 2609495feb..20aa88e497 100644 --- a/api-catalog-ui/frontend/src/helpers/urls.jsx +++ b/api-catalog-ui/frontend/src/helpers/urls.jsx @@ -24,10 +24,16 @@ const getBaseUrl = (pEnvironment, pLocation) => { // Going through the Gateway const urlParts = location.pathname.split('/'); - if (urlParts[2] === 'ui') { - return `${location.protocol}//${location.host}/${urlParts[1]}/api/${urlParts[3]}`; - } + if(urlParts[1]==="apicatalog") { + if (urlParts[2] === 'ui') { + return `${location.protocol}//${location.host}/${urlParts[1]}/api/${urlParts[3]}`; + } + } else { + if (urlParts[3] === 'ui') { + return `${location.protocol}//${location.host}/${urlParts[1]}${urlParts[2]}/api/${urlParts[4]}`; + } + } // Testing environment if (environment.REACT_APP_GATEWAY_URL && environment.REACT_APP_CATALOG_HOME) { return `${environment.REACT_APP_GATEWAY_URL}${environment.REACT_APP_CATALOG_HOME}`; @@ -35,9 +41,11 @@ const getBaseUrl = (pEnvironment, pLocation) => { // Local development environment if (environment.REACT_APP_CATALOG_HOME) { + if(urlParts[1]!== "apicatalog") { + return `${location.protocol}//${location.host}/${urlParts[1]}${environment.REACT_APP_CATALOG_HOME}`; + } return `${location.protocol}//${location.host}${environment.REACT_APP_CATALOG_HOME}`; } - // Standalone access to the Catalog return location.href; }; From 52693e66fe02451ad327ab10f5303aa3b8188506 Mon Sep 17 00:00:00 2001 From: sj895092 Date: Mon, 2 Dec 2024 14:29:33 +0100 Subject: [PATCH 06/37] removing the URLs changes Signed-off-by: sj895092 --- api-catalog-ui/frontend/src/helpers/urls.jsx | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/api-catalog-ui/frontend/src/helpers/urls.jsx b/api-catalog-ui/frontend/src/helpers/urls.jsx index 20aa88e497..2609495feb 100644 --- a/api-catalog-ui/frontend/src/helpers/urls.jsx +++ b/api-catalog-ui/frontend/src/helpers/urls.jsx @@ -24,16 +24,10 @@ const getBaseUrl = (pEnvironment, pLocation) => { // Going through the Gateway const urlParts = location.pathname.split('/'); - - if(urlParts[1]==="apicatalog") { - if (urlParts[2] === 'ui') { - return `${location.protocol}//${location.host}/${urlParts[1]}/api/${urlParts[3]}`; - } - } else { - if (urlParts[3] === 'ui') { - return `${location.protocol}//${location.host}/${urlParts[1]}${urlParts[2]}/api/${urlParts[4]}`; - } + if (urlParts[2] === 'ui') { + return `${location.protocol}//${location.host}/${urlParts[1]}/api/${urlParts[3]}`; } + // Testing environment if (environment.REACT_APP_GATEWAY_URL && environment.REACT_APP_CATALOG_HOME) { return `${environment.REACT_APP_GATEWAY_URL}${environment.REACT_APP_CATALOG_HOME}`; @@ -41,11 +35,9 @@ const getBaseUrl = (pEnvironment, pLocation) => { // Local development environment if (environment.REACT_APP_CATALOG_HOME) { - if(urlParts[1]!== "apicatalog") { - return `${location.protocol}//${location.host}/${urlParts[1]}${environment.REACT_APP_CATALOG_HOME}`; - } return `${location.protocol}//${location.host}${environment.REACT_APP_CATALOG_HOME}`; } + // Standalone access to the Catalog return location.href; }; From 20d85162d7526aac9d6d66a36d18b7737754f47d Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Mon, 2 Dec 2024 14:50:14 +0100 Subject: [PATCH 07/37] add header Signed-off-by: Andrea Tabone --- api-catalog-ui/frontend/src/epics/fetch-tiles.jsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx b/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx index 482b6a41c8..cb9cf39c17 100644 --- a/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx +++ b/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx @@ -31,6 +31,16 @@ const terminatingStatusCodes = [500, 401, 403]; // override the termination if any of these APIM message codes are in the response const excludedMessageCodes = ['ZWEAM104']; +/** + * Extract the ApimlId from the current URL + * @returns {string} The ApimlId + */ +function getApimlIdFromUrl() { + const pathname = window.location.pathname; // Get the path portion of the URL + const pathParts = pathname.split('/'); // Split the path into segments + return pathParts[1]; // Return the ApimlId (second segment) +} + function checkOrigin() { // only allow the gateway url to authenticate the user let allowOrigin = process.env.REACT_APP_GATEWAY_URL; @@ -122,6 +132,7 @@ const createFetchTilesEpic = 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': origin(), 'X-Requested-With': 'XMLHttpRequest', + 'X-ApimlId': getApimlIdFromUrl(), }, }).pipe( map((ajaxResponse) => { From 2cea8f555a5c3591a8795fe7fed75cbdc9f9e7a1 Mon Sep 17 00:00:00 2001 From: sj895092 Date: Mon, 2 Dec 2024 15:50:05 +0100 Subject: [PATCH 08/37] fetching and updating apiml id of additional gateway Signed-off-by: sj895092 --- .../controllers/api/ApiCatalogController.java | 7 +++++ .../cached/CachedProductFamilyService.java | 28 ++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java index 0779c3ea60..6f24b57521 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java @@ -15,6 +15,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -48,6 +49,9 @@ public class ApiCatalogController { private final CachedProductFamilyService cachedProductFamilyService; private final CachedApiDocService cachedApiDocService; + @Autowired + private HttpServletRequest request; + @InjectApimlLogger private final ApimlLogger apimlLog = ApimlLogger.empty(); @@ -86,6 +90,9 @@ public ApiCatalogController(CachedProductFamilyService cachedProductFamilyServic }) public ResponseEntity> getAllAPIContainers() throws ContainerStatusRetrievalThrowable { try { + String apimlId = request.getHeader("X-ApimlId"); + cachedProductFamilyService.getContextPath(apimlId); + Iterable allContainers = cachedProductFamilyService.getAllContainers(); List apiContainers = toList(allContainers); if (apiContainers == null || apiContainers.isEmpty()) { diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java index 9803f3847b..56e09415cd 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java @@ -60,6 +60,8 @@ public class CachedProductFamilyService { private final AuthenticationSchemes schemes = new AuthenticationSchemes(); private final CustomStyleConfig customStyleConfig; + private String apimlId; + @Value("${apiml.catalog.hide.serviceInfo:false}") private boolean hideServiceInfo; @@ -380,6 +382,9 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { log.info("createApiServiceFromInstance#incorrectVersions {}", ex.getMessage()); } + + String apimlIdFromDomain = getApimlId(); + String serviceId = instanceInfo.getAppName(); String title = instanceInfo.getMetadata().get(SERVICE_TITLE); if (StringUtils.equalsIgnoreCase(GATEWAY.getServiceId(), serviceId)) { @@ -387,11 +392,19 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { // additional registration for GW means domain one, update serviceId and basePath with the ApimlId String apimlId = instanceInfo.getMetadata().get(APIML_ID); if (apimlId != null) { - apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), apimlId); +// apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), apimlId); serviceId = apimlId; + if (apimlIdFromDomain.isEmpty()) { + String customApimlId = apimlIdFromDomain + "/" + apimlId ; + apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), customApimlId); + } + apiBasePath = apiBasePath.replace(serviceId.toLowerCase(),apimlId); title += " (" + apimlId + ")"; } } + else { + apiBasePath = "/"; + } } return new APIService.Builder(StringUtils.lowerCase(serviceId)) @@ -407,6 +420,11 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { .build(); } + public void getContextPath(String apimlId) { + if (!apimlId.isEmpty() && !apimlId.equals("apicatalog")) { + setApimlId(apimlId); + } + } private boolean isSso(InstanceInfo instanceInfo) { Map eurekaMetadata = instanceInfo.getMetadata(); return Authentication.builder() @@ -445,4 +463,12 @@ private void setStatus(APIContainer apiContainer, int servicesCount, int activeS } + public String getApimlId() { + return apimlId; + } + + public void setApimlId(String apimlId) { + this.apimlId = apimlId; + } + } From 43ded7f3a8400773629e20e503c9e7780a76eff8 Mon Sep 17 00:00:00 2001 From: sj895092 Date: Mon, 2 Dec 2024 16:03:18 +0100 Subject: [PATCH 09/37] fetching and updating apiml id of additional gateway Signed-off-by: sj895092 --- .../apicatalog/services/cached/CachedProductFamilyService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java index 56e09415cd..06996b4742 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java @@ -397,8 +397,9 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { if (apimlIdFromDomain.isEmpty()) { String customApimlId = apimlIdFromDomain + "/" + apimlId ; apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), customApimlId); + } else { + apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), apimlId); } - apiBasePath = apiBasePath.replace(serviceId.toLowerCase(),apimlId); title += " (" + apimlId + ")"; } } From d897088dd28a6e9870ea4280032dee960bba5d61 Mon Sep 17 00:00:00 2001 From: ShobhaJayanna <36433611+shobhajayanna@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:09:11 +0100 Subject: [PATCH 10/37] refactor Signed-off-by: sj895092 --- .../services/cached/CachedProductFamilyService.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java index 06996b4742..591df6b5f1 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java @@ -382,9 +382,6 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { log.info("createApiServiceFromInstance#incorrectVersions {}", ex.getMessage()); } - - String apimlIdFromDomain = getApimlId(); - String serviceId = instanceInfo.getAppName(); String title = instanceInfo.getMetadata().get(SERVICE_TITLE); if (StringUtils.equalsIgnoreCase(GATEWAY.getServiceId(), serviceId)) { @@ -394,9 +391,9 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { if (apimlId != null) { // apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), apimlId); serviceId = apimlId; + String apimlIdFromDomain = getApimlId(); if (apimlIdFromDomain.isEmpty()) { - String customApimlId = apimlIdFromDomain + "/" + apimlId ; - apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), customApimlId); + apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), apimlIdFromDomain + "/" + apimlId); } else { apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), apimlId); } @@ -468,7 +465,7 @@ public String getApimlId() { return apimlId; } - public void setApimlId(String apimlId) { + private void setApimlId(String apimlId) { this.apimlId = apimlId; } From 3aa93400db6ae5c1107d3b26cbaa16d4bc84774b Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Tue, 3 Dec 2024 11:45:24 +0100 Subject: [PATCH 11/37] check for catalog and null value Signed-off-by: Andrea Tabone --- api-catalog-ui/frontend/src/epics/fetch-tiles.jsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx b/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx index cb9cf39c17..afc3faac54 100644 --- a/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx +++ b/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx @@ -33,12 +33,16 @@ const excludedMessageCodes = ['ZWEAM104']; /** * Extract the ApimlId from the current URL - * @returns {string} The ApimlId + * @returns {string|null} The ApimlId */ function getApimlIdFromUrl() { const pathname = window.location.pathname; // Get the path portion of the URL const pathParts = pathname.split('/'); // Split the path into segments - return pathParts[1]; // Return the ApimlId (second segment) + // Ensure there are enough segments and the second segment is not 'apicatalog' + if (pathParts.length > 1 && pathParts[1] !== 'apicatalog') { + return pathParts[1]; // Return the ApimlId (second segment) + } + return null; // Explicitly return null if no valid ApimlId is found } function checkOrigin() { From c8321a88c058c3a6f700e4b1fe809b2334dd4053 Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Tue, 3 Dec 2024 11:55:01 +0100 Subject: [PATCH 12/37] revert back the serverurl construction Signed-off-by: Andrea Tabone --- .../src/components/Swagger/SwaggerUIApiml.jsx | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx index 2821117267..ca5bdb636f 100644 --- a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx +++ b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx @@ -15,26 +15,18 @@ import getBaseUrl from '../../helpers/urls'; import { CustomizedSnippedGenerator } from '../../utils/generateSnippets'; import { AdvancedFilterPlugin } from '../../utils/filterApis'; -function transformSwaggerToCurrentHost(swagger, selectedService) { +function transformSwaggerToCurrentHost(swagger) { swagger.host = window.location.host; if (swagger.servers !== null && swagger.servers !== undefined) { swagger.servers.forEach((server) => { + const location = `${window.location.protocol}//${window.location.host}`; try { const swaggerUrl = new URL(server.url); - // if it's not a GW instance, use the URL from the browser - if (!swaggerUrl.pathname.includes("gateway")) { - const location = `${window.location.protocol}//${window.location.host}`; - server.url = location + swaggerUrl.pathname; - } else { - // if it's a GW instance, construct the server URL by using the base URL and service ID of the specific instance - const updatedPathname = swaggerUrl.pathname.replace(/^\/[^/]+/, selectedService.serviceId); - server.url = selectedService.baseUrl + updatedPathname; - } + server.url = location + swaggerUrl.pathname; } catch (e) { // not a proper url, assume it is an endpoint - server.url = selectedService.baseUrl + server; - + server.url = location + server; } }); } @@ -137,12 +129,10 @@ export default class SwaggerUIApiml extends Component { try { // If no version selected use the default apiDoc if ( - !selectedVersion && - selectedService?.serviceId && - selectedService?.baseUrl && + (selectedVersion === null || selectedVersion === undefined) && selectedService?.apiDoc?.length ) { - const swagger = transformSwaggerToCurrentHost(JSON.parse(selectedService.apiDoc), selectedService); + const swagger = transformSwaggerToCurrentHost(JSON.parse(selectedService.apiDoc)); this.setState({ swaggerReady: true, @@ -169,7 +159,7 @@ export default class SwaggerUIApiml extends Component { plugins: [this.customPlugins, AdvancedFilterPlugin, CustomizedSnippedGenerator(codeSnippets)], responseInterceptor: (res) => { // response.text field is used to render the swagger - const swagger = transformSwaggerToCurrentHost(JSON.parse(res.text), selectedService); + const swagger = transformSwaggerToCurrentHost(JSON.parse(res.text)); res.text = JSON.stringify(swagger); return res; }, From 87a42709eec2f8810a8fe5b5d0e21637383049c2 Mon Sep 17 00:00:00 2001 From: sj895092 Date: Tue, 3 Dec 2024 16:22:48 +0100 Subject: [PATCH 13/37] fix tests Signed-off-by: sj895092 --- .../controllers/api/ApiCatalogController.java | 10 +++++----- .../cached/CachedProductFamilyService.java | 17 +++++++---------- .../api/ApiCatalogControllerTests.java | 12 ++++++++++++ 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java index 6f24b57521..ffbb3d638e 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java @@ -49,8 +49,6 @@ public class ApiCatalogController { private final CachedProductFamilyService cachedProductFamilyService; private final CachedApiDocService cachedApiDocService; - @Autowired - private HttpServletRequest request; @InjectApimlLogger private final ApimlLogger apimlLog = ApimlLogger.empty(); @@ -88,11 +86,13 @@ public ApiCatalogController(CachedProductFamilyService cachedProductFamilyServic @ApiResponse(responseCode = "404", description = "URI not found"), @ApiResponse(responseCode = "500", description = "An unexpected condition occurred") }) - public ResponseEntity> getAllAPIContainers() throws ContainerStatusRetrievalThrowable { + public ResponseEntity> getAllAPIContainers(HttpServletRequest request) throws ContainerStatusRetrievalThrowable { try { - String apimlId = request.getHeader("X-ApimlId"); - cachedProductFamilyService.getContextPath(apimlId); + String apimlId = request.getHeader("X-ApimlId"); + if (apimlId != null) { + cachedProductFamilyService.getApimlIdFromContextPath(apimlId); + } Iterable allContainers = cachedProductFamilyService.getAllContainers(); List apiContainers = toList(allContainers); if (apiContainers == null || apiContainers.isEmpty()) { diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java index 591df6b5f1..a69a408a89 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java @@ -385,23 +385,20 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { String serviceId = instanceInfo.getAppName(); String title = instanceInfo.getMetadata().get(SERVICE_TITLE); if (StringUtils.equalsIgnoreCase(GATEWAY.getServiceId(), serviceId)) { + String apimlIdFromDomain = getApimlId(); if (RegistrationType.of(instanceInfo.getMetadata()).isAdditional()) { // additional registration for GW means domain one, update serviceId and basePath with the ApimlId String apimlId = instanceInfo.getMetadata().get(APIML_ID); if (apimlId != null) { -// apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), apimlId); serviceId = apimlId; - String apimlIdFromDomain = getApimlId(); - if (apimlIdFromDomain.isEmpty()) { - apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), apimlIdFromDomain + "/" + apimlId); - } else { - apiBasePath = apiBasePath.replace(serviceId.toLowerCase(), apimlId); - } + apiBasePath = StringUtils.isEmpty(apimlIdFromDomain) ? "/" + apimlId : "/" + apimlIdFromDomain.toLowerCase() + "/" + apimlId ; title += " (" + apimlId + ")"; } } else { - apiBasePath = "/"; + + apiBasePath = StringUtils.isEmpty(apimlIdFromDomain) ? "/" : "/" + apimlIdFromDomain ; + } } @@ -418,8 +415,8 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { .build(); } - public void getContextPath(String apimlId) { - if (!apimlId.isEmpty() && !apimlId.equals("apicatalog")) { + public void getApimlIdFromContextPath(String apimlId) { + if (!StringUtils.isEmpty(apimlId)) { setApimlId(apimlId); } } diff --git a/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java b/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java index d0499d0b70..518c828b03 100644 --- a/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java +++ b/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java @@ -13,10 +13,13 @@ import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.shared.Application; import io.restassured.module.mockmvc.RestAssuredMockMvc; +import jakarta.servlet.http.HttpServletRequest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.zowe.apiml.apicatalog.exceptions.ContainerStatusRetrievalThrowable; @@ -35,7 +38,10 @@ import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; import static io.restassured.module.mockmvc.RestAssuredMockMvc.standaloneSetup; +import static org.mockito.Mockito.when; + +@SpringBootTest class ApiCatalogControllerTests { private final String pathToContainers = "/containers"; @@ -45,8 +51,14 @@ class ApiCatalogControllerTests { private ApiCatalogController underTest; + @MockBean + private HttpServletRequest request; + @BeforeEach void setUp() { + + when(request.getHeader("X-ApimlId")).thenReturn("apiml1"); + cachedServicesService = mock(CachedServicesService.class); cachedProductFamilyService = mock(CachedProductFamilyService.class); cachedApiDocService = mock(CachedApiDocService.class); From 27d8aa7d3b72436950f3000517bd96d86e575b6a Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Wed, 4 Dec 2024 11:06:03 +0100 Subject: [PATCH 14/37] fix dependency to align to v3 Signed-off-by: Andrea Tabone --- gradle/versions.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/versions.gradle b/gradle/versions.gradle index d85d76001e..214fcc6730 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -67,12 +67,12 @@ dependencyResolutionManagement { version('log4j', '2.24.1') version('lombok', '1.18.34') version('netty', '4.1.115.Final') - version('nettyReactor', '1.2.0') + version('nettyReactor', '1.1.23') version('nimbusJoseJwt', '9.46') version('openApiDiff', '2.0.1') version('picocli', '4.7.6') - version('reactor', '3.7.0') + version('reactor', '3.6.11') version('restAssured', '5.5.0') version('rhino', '1.7.15') version('springDoc', '2.6.0') From 5d71211ef53dbea7c325d4b34ad4a7898903e98a Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Wed, 4 Dec 2024 13:51:30 +0100 Subject: [PATCH 15/37] fix UI Signed-off-by: Andrea Tabone --- .../cached/CachedProductFamilyService.java | 4 ++-- .../src/components/ServiceTab/ServiceTab.jsx | 19 ++++++++++------ .../src/components/Swagger/SwaggerUIApiml.jsx | 22 ++++++++++++------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java index a69a408a89..73f2556c78 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java @@ -391,13 +391,13 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { String apimlId = instanceInfo.getMetadata().get(APIML_ID); if (apimlId != null) { serviceId = apimlId; - apiBasePath = StringUtils.isEmpty(apimlIdFromDomain) ? "/" + apimlId : "/" + apimlIdFromDomain.toLowerCase() + "/" + apimlId ; + apiBasePath = StringUtils.isEmpty(apimlIdFromDomain) ? "/" + apimlId : "/" + apimlIdFromDomain.toLowerCase() + "/" + apimlId; title += " (" + apimlId + ")"; } } else { - apiBasePath = StringUtils.isEmpty(apimlIdFromDomain) ? "/" : "/" + apimlIdFromDomain ; + apiBasePath = StringUtils.isEmpty(apimlIdFromDomain) ? "/" : "/" + apimlIdFromDomain; } } diff --git a/api-catalog-ui/frontend/src/components/ServiceTab/ServiceTab.jsx b/api-catalog-ui/frontend/src/components/ServiceTab/ServiceTab.jsx index 383f0d7806..0079b2a80e 100644 --- a/api-catalog-ui/frontend/src/components/ServiceTab/ServiceTab.jsx +++ b/api-catalog-ui/frontend/src/components/ServiceTab/ServiceTab.jsx @@ -36,14 +36,19 @@ export default class ServiceTab extends Component { const { selectedVersion } = this.state; let basePath = ''; - if (selectedService.basePath) { - const version = selectedVersion || selectedService.defaultApiVersion; - let gatewayUrl = ''; - if (selectedService.apis && selectedService.apis[version] && selectedService.apis[version].gatewayUrl) { - gatewayUrl = selectedService.apis[version].gatewayUrl; + if (selectedService?.basePath) { + if (selectedService?.instances && selectedService?.instances[0].includes('gateway')) { + // Return the basePath right away, since it's a GW instance (either primary or additional) + basePath = selectedService.basePath; + } else { + const version = selectedVersion || selectedService.defaultApiVersion; + let gatewayUrl = ''; + if (selectedService.apis && selectedService.apis[version] && selectedService.apis[version].gatewayUrl) { + gatewayUrl = selectedService.apis[version].gatewayUrl; + } + // Take the first part of the basePath and then add the gatewayUrl + basePath = `/${selectedService.serviceId}/${gatewayUrl}`; } - // Take the first part of the basePath and then add the gatewayUrl - basePath = `/${selectedService.serviceId}/${gatewayUrl}`; } return basePath; } diff --git a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx index ca5bdb636f..3ce1300491 100644 --- a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx +++ b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx @@ -15,22 +15,28 @@ import getBaseUrl from '../../helpers/urls'; import { CustomizedSnippedGenerator } from '../../utils/generateSnippets'; import { AdvancedFilterPlugin } from '../../utils/filterApis'; -function transformSwaggerToCurrentHost(swagger) { +function transformSwaggerToCurrentHost(swagger, selectedService) { swagger.host = window.location.host; - if (swagger.servers !== null && swagger.servers !== undefined) { + if (swagger.servers?.length) { swagger.servers.forEach((server) => { const location = `${window.location.protocol}//${window.location.host}`; try { const swaggerUrl = new URL(server.url); - server.url = location + swaggerUrl.pathname; + if (swaggerUrl?.pathname?.includes('gateway')) { + const basePath = selectedService?.basePath === '/' ? '' : selectedService?.basePath || ''; + + server.url = location + basePath + swaggerUrl.pathname; + } + else { + server.url = location + swaggerUrl.pathname; + } } catch (e) { // not a proper url, assume it is an endpoint server.url = location + server; } }); } - return swagger; } @@ -132,7 +138,7 @@ export default class SwaggerUIApiml extends Component { (selectedVersion === null || selectedVersion === undefined) && selectedService?.apiDoc?.length ) { - const swagger = transformSwaggerToCurrentHost(JSON.parse(selectedService.apiDoc)); + const swagger = transformSwaggerToCurrentHost(JSON.parse(selectedService.apiDoc), selectedService); this.setState({ swaggerReady: true, @@ -146,9 +152,9 @@ export default class SwaggerUIApiml extends Component { }, }); } - if (selectedVersion) { + if (selectedVersion && selectedService) { const basePath = `${selectedService.serviceId}/${selectedVersion}`; - const url = `${getBaseUrl()}${process.env.REACT_APP_APIDOC_UPDATE}/${basePath}`; + const url = `${getBaseUrl()}${process?.env.REACT_APP_APIDOC_UPDATE}/${basePath}`; this.setState({ swaggerReady: true, swaggerProps: { @@ -159,7 +165,7 @@ export default class SwaggerUIApiml extends Component { plugins: [this.customPlugins, AdvancedFilterPlugin, CustomizedSnippedGenerator(codeSnippets)], responseInterceptor: (res) => { // response.text field is used to render the swagger - const swagger = transformSwaggerToCurrentHost(JSON.parse(res.text)); + const swagger = transformSwaggerToCurrentHost(JSON.parse(res.text), selectedService); res.text = JSON.stringify(swagger); return res; }, From e27437942907a8e02b171f5b47db582798424b08 Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Wed, 4 Dec 2024 17:05:52 +0100 Subject: [PATCH 16/37] refactoring Signed-off-by: Andrea Tabone --- .../controllers/api/ApiCatalogController.java | 9 ++++--- .../cached/CachedProductFamilyService.java | 27 +++++-------------- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java index ffbb3d638e..2b5ecfe377 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java @@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -48,7 +49,7 @@ public class ApiCatalogController { private final CachedProductFamilyService cachedProductFamilyService; private final CachedApiDocService cachedApiDocService; - + private final static String APIMLID_HEADER = "X-ApimlId"; @InjectApimlLogger private final ApimlLogger apimlLog = ApimlLogger.empty(); @@ -89,9 +90,9 @@ public ApiCatalogController(CachedProductFamilyService cachedProductFamilyServic public ResponseEntity> getAllAPIContainers(HttpServletRequest request) throws ContainerStatusRetrievalThrowable { try { - String apimlId = request.getHeader("X-ApimlId"); - if (apimlId != null) { - cachedProductFamilyService.getApimlIdFromContextPath(apimlId); + String apimlId = request.getHeader(APIMLID_HEADER); + if (!StringUtils.isEmpty(apimlId)) { + cachedProductFamilyService.updateApimlId(apimlId); } Iterable allContainers = cachedProductFamilyService.getAllContainers(); List apiContainers = toList(allContainers); diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java index 73f2556c78..cc5e9a0a1e 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java @@ -12,6 +12,7 @@ import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.shared.Application; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; @@ -60,6 +61,7 @@ public class CachedProductFamilyService { private final AuthenticationSchemes schemes = new AuthenticationSchemes(); private final CustomStyleConfig customStyleConfig; + @Getter private String apimlId; @Value("${apiml.catalog.hide.serviceInfo:false}") @@ -109,9 +111,7 @@ public List getRecentlyUpdatedContainers() { container -> { boolean isRecent = container.isRecentUpdated(cacheRefreshUpdateThresholdInMillis); if (isRecent) { - log.debug("Container: " + container.getId() + " last updated: " - + container.getLastUpdatedTimestamp().getTime() + - " was updated recently"); + log.debug("Container: {} last updated: {} was updated recently", container.getId(), container.getLastUpdatedTimestamp().getTime()); } return isRecent; }).toList(); @@ -251,7 +251,7 @@ public void calculateContainerServiceValues(APIContainer apiContainer) { /** * Map the configuration to customize the Catalog UI to the container * - * @param apiContainer + * @param apiContainer API container */ private void setCustomUiConfig(APIContainer apiContainer) { apiContainer.setCustomStyleConfig(customStyleConfig); @@ -346,7 +346,7 @@ private APIContainer createNewContainerFromService(String productFamilyId, Insta container.setDescription(description); container.setTitle(title); container.setVersion(version); - log.debug("updated Container cache with product family: " + productFamilyId + ": " + title); + log.debug("updated Container cache with product family: {}: {}", productFamilyId, title); // create API Service from instance and update container last changed date container.addService(createAPIServiceFromInstance(instanceInfo)); @@ -396,9 +396,7 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { } } else { - apiBasePath = StringUtils.isEmpty(apimlIdFromDomain) ? "/" : "/" + apimlIdFromDomain; - } } @@ -415,10 +413,8 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { .build(); } - public void getApimlIdFromContextPath(String apimlId) { - if (!StringUtils.isEmpty(apimlId)) { - setApimlId(apimlId); - } + public void updateApimlId(String apimlId) { + this.apimlId = apimlId; } private boolean isSso(InstanceInfo instanceInfo) { Map eurekaMetadata = instanceInfo.getMetadata(); @@ -457,13 +453,4 @@ private void setStatus(APIContainer apiContainer, int servicesCount, int activeS } } - - public String getApimlId() { - return apimlId; - } - - private void setApimlId(String apimlId) { - this.apimlId = apimlId; - } - } From fe8a38cf948ac39ddcb3b715b3eb5d33d267c886 Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Thu, 5 Dec 2024 12:03:57 +0100 Subject: [PATCH 17/37] fix issue with ReferenceError: process is not defined Signed-off-by: Andrea Tabone --- .../frontend/src/epics/fetch-tiles.jsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx b/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx index afc3faac54..91459d4472 100644 --- a/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx +++ b/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx @@ -22,9 +22,9 @@ import { import { userActions } from '../actions/user-actions'; import getBaseUrl from '../helpers/urls'; -const updatePeriod = Number(process.env.REACT_APP_STATUS_UPDATE_PERIOD); -const debounce = Number(process.env.REACT_APP_STATUS_UPDATE_DEBOUNCE); -const scalingDuration = process.env.REACT_APP_STATUS_UPDATE_SCALING_DURATION; +const updatePeriod = Number(process?.env.REACT_APP_STATUS_UPDATE_PERIOD); +const debounce = Number(process?.env.REACT_APP_STATUS_UPDATE_DEBOUNCE); +const scalingDuration = process?.env.REACT_APP_STATUS_UPDATE_SCALING_DURATION; // terminate the epic if you get any of the following Ajax error codes const terminatingStatusCodes = [500, 401, 403]; @@ -47,11 +47,11 @@ function getApimlIdFromUrl() { function checkOrigin() { // only allow the gateway url to authenticate the user - let allowOrigin = process.env.REACT_APP_GATEWAY_URL; + let allowOrigin = process?.env.REACT_APP_GATEWAY_URL; if ( - process.env.REACT_APP_GATEWAY_URL === null || - process.env.REACT_APP_GATEWAY_URL === undefined || - process.env.REACT_APP_GATEWAY_URL === '' + process?.env.REACT_APP_GATEWAY_URL === null || + process?.env.REACT_APP_GATEWAY_URL === undefined || + process?.env.REACT_APP_GATEWAY_URL === '' ) { allowOrigin = window.location.origin; } @@ -67,7 +67,7 @@ function checkOrigin() { * @returns the URL to call */ function getUrl(action) { - let url = `${getBaseUrl()}${process.env.REACT_APP_CATALOG_UPDATE}`; + let url = `${getBaseUrl()}${process?.env.REACT_APP_CATALOG_UPDATE}`; if (action.payload !== undefined) { url += `/${action.payload}`; } @@ -97,7 +97,7 @@ function shouldTerminate(error) { export const retryMechanism = (scheduler) => - ({ maxRetries = Number(process.env.REACT_APP_STATUS_UPDATE_MAX_RETRIES) } = {}) => + ({ maxRetries = Number(process?.env.REACT_APP_STATUS_UPDATE_MAX_RETRIES) } = {}) => (attempts) => attempts.pipe( mergeMap((error, i) => { From d7f1e01cd896650a5583cc114e49ddb6f672250a Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Thu, 5 Dec 2024 13:49:39 +0100 Subject: [PATCH 18/37] fix issue with ReferenceError: process is not defined Signed-off-by: Andrea Tabone --- api-catalog-ui/frontend/package-lock.json | 1 + api-catalog-ui/frontend/package.json | 5 +++-- api-catalog-ui/frontend/src/epics/fetch-tiles.jsx | 2 ++ api-catalog-ui/frontend/src/index.js | 5 ++++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/api-catalog-ui/frontend/package-lock.json b/api-catalog-ui/frontend/package-lock.json index c5bbe565da..7af0f3c103 100644 --- a/api-catalog-ui/frontend/package-lock.json +++ b/api-catalog-ui/frontend/package-lock.json @@ -36,6 +36,7 @@ "lodash": "4.17.21", "loglevel": "1.9.2", "openapi-snippet": "0.14.0", + "process": "0.11.10", "react": "18.3.1", "react-app-polyfill": "3.0.0", "react-dom": "18.3.1", diff --git a/api-catalog-ui/frontend/package.json b/api-catalog-ui/frontend/package.json index 5c8cda7ba5..8ee9b73005 100644 --- a/api-catalog-ui/frontend/package.json +++ b/api-catalog-ui/frontend/package.json @@ -32,6 +32,7 @@ "lodash": "4.17.21", "loglevel": "1.9.2", "openapi-snippet": "0.14.0", + "process": "0.11.10", "react": "18.3.1", "react-app-polyfill": "3.0.0", "react-dom": "18.3.1", @@ -136,8 +137,8 @@ "source-map-explorer": "2.5.3", "start-server-and-test": "2.0.8", "tmpl": "1.0.5", - "yaml": "2.6.0", - "undici": "6.19.8" + "undici": "6.19.8", + "yaml": "2.6.0" }, "overrides": { "nth-check": "2.1.1", diff --git a/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx b/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx index 91459d4472..cbeee2caa8 100644 --- a/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx +++ b/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx @@ -11,6 +11,8 @@ import * as log from 'loglevel'; import { of, throwError, timer } from 'rxjs'; import { ofType } from 'redux-observable'; +import process from 'process'; +window.process = process; // Polyfill process for the browser import { catchError, debounceTime, exhaustMap, map, mergeMap, retryWhen, takeUntil } from 'rxjs/operators'; import { FETCH_TILES_REQUEST, FETCH_NEW_TILES_REQUEST, FETCH_TILES_STOP } from '../constants/catalog-tile-constants'; import { diff --git a/api-catalog-ui/frontend/src/index.js b/api-catalog-ui/frontend/src/index.js index f6d3d897b6..749bfd6270 100644 --- a/api-catalog-ui/frontend/src/index.js +++ b/api-catalog-ui/frontend/src/index.js @@ -8,6 +8,7 @@ * Copyright Contributors to the Zowe Project. */ +import process from 'process'; import 'react-app-polyfill/ie11'; import { createRoot } from 'react-dom/client'; import { Provider } from 'react-redux'; @@ -32,6 +33,8 @@ import { AsyncAppContainer } from './components/App/AsyncModules'; import('./index.css'); +window.process = process; // Polyfill process for the browser + function errorHandler(error, getState, lastAction, dispatch) { log.error(error); log.debug('current state', getState()); @@ -54,7 +57,7 @@ const epicMiddleware = createEpicMiddleware({ }); const composeEnhancers = compose; const middlewares = [epicMiddleware, thunk, reduxCatch(errorHandler)]; -if (process.env.NODE_ENV !== 'production') { +if (typeof process !== 'undefined' && process?.env?.NODE_ENV !== 'production') { middlewares.push(logger); } const persistedReducer = persistReducer(persistConfig, rootReducer); From d391229ff7d641fb11ec669790d827fa669b7a4c Mon Sep 17 00:00:00 2001 From: sj895092 Date: Thu, 5 Dec 2024 14:56:20 +0100 Subject: [PATCH 19/37] adding tests Signed-off-by: sj895092 --- .../controllers/api/ApiCatalogController.java | 11 ++-------- .../cached/CachedProductFamilyService.java | 22 ++++++++----------- .../api/ApiCatalogControllerTests.java | 10 --------- .../CachedProductFamilyServiceTest.java | 2 ++ 4 files changed, 13 insertions(+), 32 deletions(-) diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java index 2b5ecfe377..9dc265b92e 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java @@ -15,9 +15,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -49,7 +47,7 @@ public class ApiCatalogController { private final CachedProductFamilyService cachedProductFamilyService; private final CachedApiDocService cachedApiDocService; - private final static String APIMLID_HEADER = "X-ApimlId"; + @InjectApimlLogger private final ApimlLogger apimlLog = ApimlLogger.empty(); @@ -87,13 +85,8 @@ public ApiCatalogController(CachedProductFamilyService cachedProductFamilyServic @ApiResponse(responseCode = "404", description = "URI not found"), @ApiResponse(responseCode = "500", description = "An unexpected condition occurred") }) - public ResponseEntity> getAllAPIContainers(HttpServletRequest request) throws ContainerStatusRetrievalThrowable { + public ResponseEntity> getAllAPIContainers() throws ContainerStatusRetrievalThrowable { try { - - String apimlId = request.getHeader(APIMLID_HEADER); - if (!StringUtils.isEmpty(apimlId)) { - cachedProductFamilyService.updateApimlId(apimlId); - } Iterable allContainers = cachedProductFamilyService.getAllContainers(); List apiContainers = toList(allContainers); if (apiContainers == null || apiContainers.isEmpty()) { diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java index cc5e9a0a1e..2a2e2e58ce 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java @@ -12,7 +12,6 @@ import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.shared.Application; -import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; @@ -61,9 +60,6 @@ public class CachedProductFamilyService { private final AuthenticationSchemes schemes = new AuthenticationSchemes(); private final CustomStyleConfig customStyleConfig; - @Getter - private String apimlId; - @Value("${apiml.catalog.hide.serviceInfo:false}") private boolean hideServiceInfo; @@ -111,7 +107,9 @@ public List getRecentlyUpdatedContainers() { container -> { boolean isRecent = container.isRecentUpdated(cacheRefreshUpdateThresholdInMillis); if (isRecent) { - log.debug("Container: {} last updated: {} was updated recently", container.getId(), container.getLastUpdatedTimestamp().getTime()); + log.debug("Container: " + container.getId() + " last updated: " + + container.getLastUpdatedTimestamp().getTime() + + " was updated recently"); } return isRecent; }).toList(); @@ -251,7 +249,7 @@ public void calculateContainerServiceValues(APIContainer apiContainer) { /** * Map the configuration to customize the Catalog UI to the container * - * @param apiContainer API container + * @param apiContainer */ private void setCustomUiConfig(APIContainer apiContainer) { apiContainer.setCustomStyleConfig(customStyleConfig); @@ -346,7 +344,7 @@ private APIContainer createNewContainerFromService(String productFamilyId, Insta container.setDescription(description); container.setTitle(title); container.setVersion(version); - log.debug("updated Container cache with product family: {}: {}", productFamilyId, title); + log.debug("updated Container cache with product family: " + productFamilyId + ": " + title); // create API Service from instance and update container last changed date container.addService(createAPIServiceFromInstance(instanceInfo)); @@ -385,18 +383,18 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { String serviceId = instanceInfo.getAppName(); String title = instanceInfo.getMetadata().get(SERVICE_TITLE); if (StringUtils.equalsIgnoreCase(GATEWAY.getServiceId(), serviceId)) { - String apimlIdFromDomain = getApimlId(); + if (RegistrationType.of(instanceInfo.getMetadata()).isAdditional()) { // additional registration for GW means domain one, update serviceId and basePath with the ApimlId String apimlId = instanceInfo.getMetadata().get(APIML_ID); if (apimlId != null) { serviceId = apimlId; - apiBasePath = StringUtils.isEmpty(apimlIdFromDomain) ? "/" + apimlId : "/" + apimlIdFromDomain.toLowerCase() + "/" + apimlId; + apiBasePath = "/" + serviceId.toLowerCase(); title += " (" + apimlId + ")"; } } else { - apiBasePath = StringUtils.isEmpty(apimlIdFromDomain) ? "/" : "/" + apimlIdFromDomain; + apiBasePath = "/"; } } @@ -413,9 +411,6 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { .build(); } - public void updateApimlId(String apimlId) { - this.apimlId = apimlId; - } private boolean isSso(InstanceInfo instanceInfo) { Map eurekaMetadata = instanceInfo.getMetadata(); return Authentication.builder() @@ -453,4 +448,5 @@ private void setStatus(APIContainer apiContainer, int servicesCount, int activeS } } + } diff --git a/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java b/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java index 518c828b03..1a26dc0987 100644 --- a/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java +++ b/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java @@ -13,13 +13,10 @@ import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.shared.Application; import io.restassured.module.mockmvc.RestAssuredMockMvc; -import jakarta.servlet.http.HttpServletRequest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.zowe.apiml.apicatalog.exceptions.ContainerStatusRetrievalThrowable; @@ -38,10 +35,8 @@ import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; import static io.restassured.module.mockmvc.RestAssuredMockMvc.standaloneSetup; -import static org.mockito.Mockito.when; -@SpringBootTest class ApiCatalogControllerTests { private final String pathToContainers = "/containers"; @@ -51,14 +46,9 @@ class ApiCatalogControllerTests { private ApiCatalogController underTest; - @MockBean - private HttpServletRequest request; - @BeforeEach void setUp() { - when(request.getHeader("X-ApimlId")).thenReturn("apiml1"); - cachedServicesService = mock(CachedServicesService.class); cachedProductFamilyService = mock(CachedProductFamilyService.class); cachedApiDocService = mock(CachedApiDocService.class); diff --git a/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyServiceTest.java b/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyServiceTest.java index 7728dff03e..20839e7376 100644 --- a/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyServiceTest.java +++ b/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyServiceTest.java @@ -546,6 +546,7 @@ void givenPrimaryInstance_whenCreateDto_thenDoNotUpdateTitle() { var dto = createDto(RegistrationType.ADDITIONAL); assertEquals("title (apimlId)", dto.getTitle()); assertEquals("apimlid", dto.getServiceId()); + assertEquals("/apimlid", dto.getBasePath()); } @Test @@ -553,6 +554,7 @@ void givenPrimaryInstance_whenCreateDto_thenAddApimlIdIntoTitle() { var dto = createDto(RegistrationType.PRIMARY); assertEquals("title", dto.getTitle()); assertEquals("gateway", dto.getServiceId()); + assertEquals("/", dto.getBasePath()); } } From eed026747d3a070d4e1a24baccbfb79c1f965c46 Mon Sep 17 00:00:00 2001 From: ShobhaJayanna <36433611+Shobhajayanna@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:08:43 +0100 Subject: [PATCH 20/37] Update ApiCatalogController.java Signed-off-by: ShobhaJayanna <36433611+Shobhajayanna@users.noreply.github.com> --- .../apiml/apicatalog/controllers/api/ApiCatalogController.java | 1 - 1 file changed, 1 deletion(-) diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java index 9dc265b92e..0779c3ea60 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogController.java @@ -48,7 +48,6 @@ public class ApiCatalogController { private final CachedProductFamilyService cachedProductFamilyService; private final CachedApiDocService cachedApiDocService; - @InjectApimlLogger private final ApimlLogger apimlLog = ApimlLogger.empty(); From ebb940136c409f4572faf625f7f63038b77e598b Mon Sep 17 00:00:00 2001 From: ShobhaJayanna <36433611+Shobhajayanna@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:09:14 +0100 Subject: [PATCH 21/37] Update ApiCatalogControllerTests.java Signed-off-by: ShobhaJayanna <36433611+Shobhajayanna@users.noreply.github.com> --- .../apicatalog/controllers/api/ApiCatalogControllerTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java b/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java index 1a26dc0987..9d5ebb25ad 100644 --- a/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java +++ b/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java @@ -48,7 +48,6 @@ class ApiCatalogControllerTests { @BeforeEach void setUp() { - cachedServicesService = mock(CachedServicesService.class); cachedProductFamilyService = mock(CachedProductFamilyService.class); cachedApiDocService = mock(CachedApiDocService.class); From 0647089bc94cbc8099911c088b66162f3f2923c1 Mon Sep 17 00:00:00 2001 From: ShobhaJayanna <36433611+Shobhajayanna@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:09:44 +0100 Subject: [PATCH 22/37] Update ApiCatalogControllerTests.java Signed-off-by: ShobhaJayanna <36433611+Shobhajayanna@users.noreply.github.com> --- .../apicatalog/controllers/api/ApiCatalogControllerTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java b/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java index 9d5ebb25ad..d0499d0b70 100644 --- a/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java +++ b/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/controllers/api/ApiCatalogControllerTests.java @@ -36,7 +36,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static io.restassured.module.mockmvc.RestAssuredMockMvc.standaloneSetup; - class ApiCatalogControllerTests { private final String pathToContainers = "/containers"; From e70ec7119c69aed5ff4a37d01ef984497900d70e Mon Sep 17 00:00:00 2001 From: ShobhaJayanna <36433611+Shobhajayanna@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:10:41 +0100 Subject: [PATCH 23/37] Update CachedProductFamilyService.java Signed-off-by: ShobhaJayanna <36433611+Shobhajayanna@users.noreply.github.com> --- .../apicatalog/services/cached/CachedProductFamilyService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java index 2a2e2e58ce..761b3b2f7e 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java @@ -383,7 +383,6 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { String serviceId = instanceInfo.getAppName(); String title = instanceInfo.getMetadata().get(SERVICE_TITLE); if (StringUtils.equalsIgnoreCase(GATEWAY.getServiceId(), serviceId)) { - if (RegistrationType.of(instanceInfo.getMetadata()).isAdditional()) { // additional registration for GW means domain one, update serviceId and basePath with the ApimlId String apimlId = instanceInfo.getMetadata().get(APIML_ID); From 92c1686398cd9f45eada779780486bfa9a9a6ead Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Thu, 5 Dec 2024 16:19:31 +0100 Subject: [PATCH 24/37] add integration test Signed-off-by: Andrea Tabone --- .../gateway/CentralRegistryTest.java | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java index fff55eb448..7a045c757c 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java +++ b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java @@ -10,11 +10,14 @@ package org.zowe.apiml.functional.gateway; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; import io.restassured.RestAssured; import io.restassured.common.mapper.TypeRef; import io.restassured.http.ContentType; import io.restassured.response.ValidatableResponse; import lombok.SneakyThrows; +import net.minidev.json.JSONArray; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -26,7 +29,9 @@ import org.zowe.apiml.util.categories.DiscoverableClientDependentTest; import org.zowe.apiml.util.config.*; +import java.net.MalformedURLException; import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -37,16 +42,23 @@ import static io.restassured.RestAssured.with; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.*; import static org.springframework.http.HttpHeaders.ACCEPT; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; +import static org.zowe.apiml.util.SecurityUtils.GATEWAY_TOKEN_COOKIE_NAME; +import static org.zowe.apiml.util.SecurityUtils.gatewayToken; @DiscoverableClientDependentTest @Tag("GatewayCentralRegistry") class CentralRegistryTest implements TestWithStartedInstances { static final String CENTRAL_REGISTRY_PATH = "/" + CoreService.GATEWAY.getServiceId() + "/api/v1/registry"; + public static final String DOMAIN_APIML = "domain-apiml"; + public static final String CENTRAL_APIML = "central-apiml"; static ServiceConfiguration conf = ConfigReader.environmentConfiguration().getCentralGatewayServiceConfiguration(); static DiscoveryServiceConfiguration discoveryConf = ConfigReader.environmentConfiguration().getDiscoveryServiceConfiguration(); + static GatewayServiceConfiguration gatewayConf = ConfigReader.environmentConfiguration().getGatewayServiceConfiguration(); + @BeforeAll @SneakyThrows @@ -86,7 +98,7 @@ void shouldFindBothApimlIds() { List apimlIds = listCentralRegistry(null, null, null) .extract().jsonPath().getList("apimlId"); - assertThat(apimlIds).contains("central-apiml", "domain-apiml"); + assertThat(apimlIds).contains(CENTRAL_APIML, DOMAIN_APIML); } @Test @@ -103,7 +115,7 @@ void shouldFindTwoRegisteredGatewaysInTheEurekaApps() { assertThat(metadata) .extracting(map -> map.get("apiml.service.apimlId")) - .containsOnly("central-apiml", "domain-apiml"); + .containsOnly(CENTRAL_APIML, DOMAIN_APIML); } @Test @@ -152,6 +164,36 @@ private ValidatableResponse listEurekaApps() { .contentType(ContentType.JSON); } + @Test + void shouldContainCorrectBasePaths() throws MalformedURLException, URISyntaxException { + URI containers = new URL(gatewayConf.getScheme(), gatewayConf.getHost(), gatewayConf.getPort(), "/apicatalog/api/v1/containers/apimediationlayer") + .toURI(); + System.out.println(containers); + + final String jwt = gatewayToken(); + String responseBody = with().given() + .header(ACCEPT, APPLICATION_JSON_VALUE) + .cookie(GATEWAY_TOKEN_COOKIE_NAME, jwt) + .get(containers) + .then() + .statusCode(200) + .contentType("application/json") + .extract() + .body() + .asString(); + + DocumentContext jsonContext = JsonPath.parse(responseBody); + + JSONArray gatewayBasePath = jsonContext.read("$[0].services[?(@.serviceId == 'central-apiml')].basePath"); + assertNotNull(gatewayBasePath, "BasePath for central gw should not be null"); + assertFalse(gatewayBasePath.isEmpty(), "BasePath for central gw should not be empty"); + assertEquals("/", gatewayBasePath.get(0)); + JSONArray domainGatewayBasePath = jsonContext.read("$[0].services[?(@.serviceId == 'domain-apiml')].basePath"); + assertNotNull(domainGatewayBasePath, "BasePath for domain gw should not be null"); + assertFalse(domainGatewayBasePath.isEmpty(), "BasePath for domain gw should not be empty"); + assertEquals("/" + DOMAIN_APIML, domainGatewayBasePath.get(0)); + } + @SneakyThrows private URI buildRegistryURI(String apimlId, String apiId, String serviceId) { From 0e9a8a6ad2c5df2728b3a1e0d024527707819975 Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Thu, 5 Dec 2024 16:28:46 +0100 Subject: [PATCH 25/37] revert back unnecessary code Signed-off-by: Andrea Tabone --- api-catalog-ui/frontend/src/epics/fetch-tiles.jsx | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx b/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx index cbeee2caa8..36edcd30bd 100644 --- a/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx +++ b/api-catalog-ui/frontend/src/epics/fetch-tiles.jsx @@ -33,20 +33,6 @@ const terminatingStatusCodes = [500, 401, 403]; // override the termination if any of these APIM message codes are in the response const excludedMessageCodes = ['ZWEAM104']; -/** - * Extract the ApimlId from the current URL - * @returns {string|null} The ApimlId - */ -function getApimlIdFromUrl() { - const pathname = window.location.pathname; // Get the path portion of the URL - const pathParts = pathname.split('/'); // Split the path into segments - // Ensure there are enough segments and the second segment is not 'apicatalog' - if (pathParts.length > 1 && pathParts[1] !== 'apicatalog') { - return pathParts[1]; // Return the ApimlId (second segment) - } - return null; // Explicitly return null if no valid ApimlId is found -} - function checkOrigin() { // only allow the gateway url to authenticate the user let allowOrigin = process?.env.REACT_APP_GATEWAY_URL; @@ -138,7 +124,6 @@ const createFetchTilesEpic = 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': origin(), 'X-Requested-With': 'XMLHttpRequest', - 'X-ApimlId': getApimlIdFromUrl(), }, }).pipe( map((ajaxResponse) => { From 466eaedc189e079cd7d830f381465bd72f1d62cb Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Fri, 6 Dec 2024 10:43:09 +0100 Subject: [PATCH 26/37] add api-catalog service container Signed-off-by: Andrea Tabone --- .github/workflows/integration-tests.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 93325c9df2..47fdb56565 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -270,6 +270,10 @@ jobs: services: # First group of services represents central apiml instance with central gateway registry + api-catalog-services: + image: ghcr.io/balhar-jakub/api-catalog-services:${{ github.run_id }}-${{ github.run_number }} + volumes: + - /api-defs:/api-defs discovery-service: image: ghcr.io/balhar-jakub/discovery-service:${{ github.run_id }}-${{ github.run_number }} gateway-service: From 58d574a0605986c9cfffc91a4a9838173b9e7b25 Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Fri, 6 Dec 2024 11:46:12 +0100 Subject: [PATCH 27/37] fix e2e tests Signed-off-by: Andrea Tabone --- .../e2e/detail-page/multiple-gateway-services.cy.js | 2 +- .../cypress/e2e/detail-page/swagger-rendering.cy.js | 7 ++++++- .../zowe/apiml/functional/gateway/CentralRegistryTest.java | 1 - 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/api-catalog-ui/frontend/cypress/e2e/detail-page/multiple-gateway-services.cy.js b/api-catalog-ui/frontend/cypress/e2e/detail-page/multiple-gateway-services.cy.js index 2290286c6b..fe6214ed4b 100644 --- a/api-catalog-ui/frontend/cypress/e2e/detail-page/multiple-gateway-services.cy.js +++ b/api-catalog-ui/frontend/cypress/e2e/detail-page/multiple-gateway-services.cy.js @@ -43,7 +43,7 @@ describe('>>> Multi-tenancy deployment test', () => { '#swaggerContainer > div > div:nth-child(2) > div.scheme-container > section > div:nth-child(1) > div > div > label > select > option' ) .should('exist') - .should('contain', `${baseUrl.match(/^https?:\/\/([^/?#]+)(?:[/?#]|$)/i)[1]}/gateway/api/v1`); + .should('contain', `${baseUrl.match(/^https?:\/\/([^/?#]+)(?:[/?#]|$)/i)[1]}/apiml2/gateway/api/v1`); cy.get('.tabs-container').should('not.exist'); cy.get('.serviceTab').should('exist').and('contain', 'API Gateway'); diff --git a/api-catalog-ui/frontend/cypress/e2e/detail-page/swagger-rendering.cy.js b/api-catalog-ui/frontend/cypress/e2e/detail-page/swagger-rendering.cy.js index 9e01a1309c..7214f781d0 100644 --- a/api-catalog-ui/frontend/cypress/e2e/detail-page/swagger-rendering.cy.js +++ b/api-catalog-ui/frontend/cypress/e2e/detail-page/swagger-rendering.cy.js @@ -56,7 +56,12 @@ describe("Swagger rendering", () => { .get('label') .should('contain', "API Base Path:"); - const regex = new RegExp(`^\/${service.serviceId}\/api(\/v1)?$`); + let regexContent = `^\/${service.serviceId}\/api(\/v1)?$`; + if (service.serviceId === 'gateway') { + regexContent = '/'; + } + const regex = new RegExp(regexContent); + cy.get('@basePath') .get('#apiBasePath').invoke("text").should(text => { expect(text).to.match(regex); diff --git a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java index 7a045c757c..f3479642ae 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java +++ b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java @@ -168,7 +168,6 @@ private ValidatableResponse listEurekaApps() { void shouldContainCorrectBasePaths() throws MalformedURLException, URISyntaxException { URI containers = new URL(gatewayConf.getScheme(), gatewayConf.getHost(), gatewayConf.getPort(), "/apicatalog/api/v1/containers/apimediationlayer") .toURI(); - System.out.println(containers); final String jwt = gatewayToken(); String responseBody = with().given() From 81aaa98eb05cd2cbad9ebeb1f0ac8092efbc735b Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Fri, 6 Dec 2024 15:04:17 +0100 Subject: [PATCH 28/37] increase coverage and fix code smells Signed-off-by: Andrea Tabone --- .../cached/CachedProductFamilyService.java | 2 +- .../src/components/ServiceTab/ServiceTab.jsx | 3 +- .../components/ServiceTab/ServiceTab.test.jsx | 1 + .../src/components/Swagger/SwaggerUIApiml.jsx | 7 ++++ ...gerUI.test.jsx => SwaggerUIApiml.test.jsx} | 41 ++++++++++++++++++- .../gateway/CentralRegistryTest.java | 7 ++-- 6 files changed, 54 insertions(+), 7 deletions(-) rename api-catalog-ui/frontend/src/components/Swagger/{SwaggerUI.test.jsx => SwaggerUIApiml.test.jsx} (89%) diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java index 761b3b2f7e..edc2993115 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/services/cached/CachedProductFamilyService.java @@ -388,7 +388,7 @@ APIService createAPIServiceFromInstance(InstanceInfo instanceInfo) { String apimlId = instanceInfo.getMetadata().get(APIML_ID); if (apimlId != null) { serviceId = apimlId; - apiBasePath = "/" + serviceId.toLowerCase(); + apiBasePath = String.join("/", "", serviceId.toLowerCase()); title += " (" + apimlId + ")"; } } diff --git a/api-catalog-ui/frontend/src/components/ServiceTab/ServiceTab.jsx b/api-catalog-ui/frontend/src/components/ServiceTab/ServiceTab.jsx index 0079b2a80e..0fda99ea06 100644 --- a/api-catalog-ui/frontend/src/components/ServiceTab/ServiceTab.jsx +++ b/api-catalog-ui/frontend/src/components/ServiceTab/ServiceTab.jsx @@ -37,7 +37,7 @@ export default class ServiceTab extends Component { let basePath = ''; if (selectedService?.basePath) { - if (selectedService?.instances && selectedService?.instances[0].includes('gateway')) { + if (selectedService?.instances?.[0]?.includes('gateway')) { // Return the basePath right away, since it's a GW instance (either primary or additional) basePath = selectedService.basePath; } else { @@ -326,6 +326,7 @@ ServiceTab.propTypes = { gatewayUrl: PropTypes.string, }) ), + instances: PropTypes.arrayOf(PropTypes.string), apiVersions: PropTypes.arrayOf(PropTypes.string), serviceId: PropTypes.string, status: PropTypes.string, diff --git a/api-catalog-ui/frontend/src/components/ServiceTab/ServiceTab.test.jsx b/api-catalog-ui/frontend/src/components/ServiceTab/ServiceTab.test.jsx index a22c631bbb..15ba989606 100644 --- a/api-catalog-ui/frontend/src/components/ServiceTab/ServiceTab.test.jsx +++ b/api-catalog-ui/frontend/src/components/ServiceTab/ServiceTab.test.jsx @@ -31,6 +31,7 @@ const selectedService = { defaultApiVersion: ['org.zowe v1'], ssoAllInstances: true, apis: { 'org.zowe v1': { gatewayUrl: 'api/v1' } }, + instances: ["localhost:gateway:10010"] }; const selectedServiceDown = { diff --git a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx index 3ce1300491..870e1c75c8 100644 --- a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx +++ b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx @@ -14,6 +14,7 @@ import InstanceInfo from '../ServiceTab/InstanceInfo'; import getBaseUrl from '../../helpers/urls'; import { CustomizedSnippedGenerator } from '../../utils/generateSnippets'; import { AdvancedFilterPlugin } from '../../utils/filterApis'; +import PropTypes from "prop-types"; function transformSwaggerToCurrentHost(swagger, selectedService) { swagger.host = window.location.host; @@ -208,6 +209,12 @@ export default class SwaggerUIApiml extends Component { } } +SwaggerUIApiml.propTypes = { + selectedService: PropTypes.shape({ + apiDoc: PropTypes.string, + }).isRequired, +}; + SwaggerUIApiml.defaultProps = { url: `${getBaseUrl()}/apidoc`, }; diff --git a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUI.test.jsx b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.test.jsx similarity index 89% rename from api-catalog-ui/frontend/src/components/Swagger/SwaggerUI.test.jsx rename to api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.test.jsx index 874199559f..f0557c609b 100644 --- a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUI.test.jsx +++ b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.test.jsx @@ -104,7 +104,8 @@ describe('>>> Swagger component tests', () => { const container = document.createElement('div'); document.body.appendChild(container); - await act(async () => createRoot(container).render(, container)); + const root = createRoot(container); + await act(async () => root.render()); expect(container.textContent).toContain(`API documentation could not be retrieved`); }); @@ -294,6 +295,44 @@ describe('>>> Swagger component tests', () => { expect(swaggerDiv).toBeDefined(); }); + it('should set correct Gateway server URL based on its basePath', async () => { + const endpoint = '/gateway/api/v1'; + const service = { + serviceId: 'gateway', + title: 'Gateway service', + description: 'Gateway service', + status: 'UP', + secured: true, + homePageUrl: 'http://localhost:10010/', + basePath: '/', + apiDoc: JSON.stringify({ + openapi: '3.0.0', + servers: [{ url: `https://bad.com${endpoint}` }], + }), + apis: { + default: { + apiId: 'gateway', + }, + }, + defaultApiVersion: 0, + }; + const wrapper = shallow( +
+ +
+ ); + + + const tiles = [{}]; + const container = document.createElement('div'); + + await act(async () => + createRoot(container).render(, container) + ); + expect(container.textContent).toContain(`Servershttp://localhost${endpoint}`); + + }); + it('should not create element api portal disabled and span already exists', () => { const service = { serviceId: 'testservice', diff --git a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java index f3479642ae..468202ba15 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java +++ b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java @@ -52,13 +52,12 @@ @Tag("GatewayCentralRegistry") class CentralRegistryTest implements TestWithStartedInstances { static final String CENTRAL_REGISTRY_PATH = "/" + CoreService.GATEWAY.getServiceId() + "/api/v1/registry"; + public static final String APIML_CONTAINER_PATH = "/" + CoreService.API_CATALOG.getServiceId() + "/api/v1/containers/apimediationlayer"; public static final String DOMAIN_APIML = "domain-apiml"; public static final String CENTRAL_APIML = "central-apiml"; static ServiceConfiguration conf = ConfigReader.environmentConfiguration().getCentralGatewayServiceConfiguration(); static DiscoveryServiceConfiguration discoveryConf = ConfigReader.environmentConfiguration().getDiscoveryServiceConfiguration(); - static GatewayServiceConfiguration gatewayConf = ConfigReader.environmentConfiguration().getGatewayServiceConfiguration(); - @BeforeAll @SneakyThrows @@ -81,7 +80,7 @@ void setup() { void shouldFindRegisteredGatewayInCentralApiml() { ValidatableResponse response = listCentralRegistry("/central-apiml", "zowe.apiml.gateway", null); - List> services = response.extract().jsonPath().getObject("[0].services", new TypeRef>>() { + List> services = response.extract().jsonPath().getObject("[0].services", new TypeRef<>() { }); assertThat(services).hasSize(1); @@ -166,7 +165,7 @@ private ValidatableResponse listEurekaApps() { @Test void shouldContainCorrectBasePaths() throws MalformedURLException, URISyntaxException { - URI containers = new URL(gatewayConf.getScheme(), gatewayConf.getHost(), gatewayConf.getPort(), "/apicatalog/api/v1/containers/apimediationlayer") + URI containers = new URL(conf.getScheme(), conf.getHost(), conf.getPort(), APIML_CONTAINER_PATH) .toURI(); final String jwt = gatewayToken(); From 53d7e20a0b6e2735cc4445799ae4f099712d5abf Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Fri, 6 Dec 2024 16:45:17 +0100 Subject: [PATCH 29/37] cleanup workflow Signed-off-by: Andrea Tabone --- .github/workflows/integration-tests.yml | 24 ++++--------------- .../src/components/Swagger/SwaggerUIApiml.jsx | 1 + 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 47fdb56565..68e1eb4642 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -276,22 +276,17 @@ jobs: - /api-defs:/api-defs discovery-service: image: ghcr.io/balhar-jakub/discovery-service:${{ github.run_id }}-${{ github.run_number }} - gateway-service: - image: ghcr.io/balhar-jakub/gateway-service:${{ github.run_id }}-${{ github.run_number }} - env: - APIML_SERVICE_APIMLID: central-apiml - APIML_SERVICE_HOSTNAME: gateway-service zaas-service: image: ghcr.io/balhar-jakub/zaas-service:${{ github.run_id }}-${{ github.run_number }} env: APIML_SECURITY_X509_ENABLED: true APIML_SECURITY_X509_ACCEPTFORWARDEDCERT: true APIML_SECURITY_X509_CERTIFICATESURL: https://gateway-service:10010/gateway/certificates - central-gateway-service: + gateway-service: image: ghcr.io/balhar-jakub/gateway-service:${{ github.run_id }}-${{ github.run_number }} env: APIML_SERVICE_APIMLID: central-apiml - APIML_SERVICE_HOSTNAME: central-gateway-service + APIML_SERVICE_HOSTNAME: gateway-service APIML_GATEWAY_REGISTRY_ENABLED: true APIML_SECURITY_X509_REGISTRY_ALLOWEDUSERS: USER,UNKNOWNUSER @@ -303,16 +298,6 @@ jobs: env: APIML_SERVICE_HOSTNAME: discovery-service-2 APIML_SERVICE_PORT: 10031 - gateway-service-2: - image: ghcr.io/balhar-jakub/gateway-service:${{ github.run_id }}-${{ github.run_number }} - env: - APIML_SERVICE_APIMLID: domain-apiml - APIML_SERVICE_HOSTNAME: gateway-service-2 - APIML_SERVICE_PORT: 10037 - APIML_SERVICE_DISCOVERYSERVICEURLS: https://discovery-service-2:10031/eureka/ - ZWE_CONFIGS_APIML_SERVICE_ADDITIONALREGISTRATION_0_DISCOVERYSERVICEURLS: https://discovery-service:10011/eureka - ZWE_CONFIGS_APIML_SERVICE_ADDITIONALREGISTRATION_0_ROUTES_0_GATEWAYURL: / - ZWE_CONFIGS_APIML_SERVICE_ADDITIONALREGISTRATION_0_ROUTES_0_SERVICEURL: / zaas-service-2: image: ghcr.io/balhar-jakub/zaas-service:${{ github.run_id }}-${{ github.run_number }} env: @@ -320,11 +305,11 @@ jobs: APIML_SECURITY_X509_ACCEPTFORWARDEDCERT: true APIML_SECURITY_X509_CERTIFICATESURL: https://gateway-service:10010/gateway/certificates APIML_SERVICE_DISCOVERYSERVICEURLS: https://discovery-service-2:10031/eureka/ - central-gateway-service-2: + gateway-service-2: image: ghcr.io/balhar-jakub/gateway-service:${{ github.run_id }}-${{ github.run_number }} env: APIML_SERVICE_APIMLID: domain-apiml - APIML_SERVICE_HOSTNAME: central-gateway-service-2 + APIML_SERVICE_HOSTNAME: gateway-service-2 APIML_GATEWAY_REGISTRY_ENABLED: false APIML_SECURITY_X509_REGISTRY_ALLOWEDUSERS: USER,UNKNOWNUSER APIML_SERVICE_DISCOVERYSERVICEURLS: https://discovery-service-2:10031/eureka/ @@ -451,7 +436,6 @@ jobs: gateway-service: image: ghcr.io/balhar-jakub/gateway-service:${{ github.run_id }}-${{ github.run_number }} env: - APIML_SECURITY_X509_ENABLED: true APIML_SECURITY_X509_ACCEPTFORWARDEDCERT: true APIML_SECURITY_X509_CERTIFICATESURL: https://gateway-service:10010/gateway/certificates mock-services: diff --git a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx index 870e1c75c8..603fd2e5f2 100644 --- a/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx +++ b/api-catalog-ui/frontend/src/components/Swagger/SwaggerUIApiml.jsx @@ -213,6 +213,7 @@ SwaggerUIApiml.propTypes = { selectedService: PropTypes.shape({ apiDoc: PropTypes.string, }).isRequired, + url: PropTypes.string, }; SwaggerUIApiml.defaultProps = { From 584f734e7ce77e2992a36e20f8af966cb8e43e68 Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Fri, 6 Dec 2024 17:00:45 +0100 Subject: [PATCH 30/37] fix test Signed-off-by: Andrea Tabone --- .../org/zowe/apiml/functional/gateway/CentralRegistryTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java index 468202ba15..62c73711e7 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java +++ b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java @@ -110,7 +110,7 @@ void shouldFindTwoRegisteredGatewaysInTheEurekaApps() { .jsonPath() .getObject("applications.application.findAll { it.name == 'GATEWAY' }.instance.metadata", typeRef).get(0); - assertThat(metadata).hasSize(4); + assertThat(metadata).hasSize(2); assertThat(metadata) .extracting(map -> map.get("apiml.service.apimlId")) From 696adb2791e838ba40c8d5c91fdfc15543493fc4 Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Fri, 6 Dec 2024 17:31:19 +0100 Subject: [PATCH 31/37] fix config Signed-off-by: Andrea Tabone --- .../org/zowe/apiml/functional/gateway/CentralRegistryTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java index 62c73711e7..32a1eabcb6 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java +++ b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java @@ -56,7 +56,7 @@ class CentralRegistryTest implements TestWithStartedInstances { public static final String DOMAIN_APIML = "domain-apiml"; public static final String CENTRAL_APIML = "central-apiml"; - static ServiceConfiguration conf = ConfigReader.environmentConfiguration().getCentralGatewayServiceConfiguration(); + static ServiceConfiguration conf = ConfigReader.environmentConfiguration().getGatewayServiceConfiguration(); static DiscoveryServiceConfiguration discoveryConf = ConfigReader.environmentConfiguration().getDiscoveryServiceConfiguration(); @BeforeAll From 6363ecc2bdc59c265141e5a3d5b1c71741178788 Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Sat, 7 Dec 2024 11:07:56 +0100 Subject: [PATCH 32/37] add missing mock service and multi-tenancy setup config for local env Signed-off-by: Andrea Tabone --- .github/workflows/integration-tests.yml | 2 + config/local/multi-tenancy/README.md | 12 +++ .../multi-tenancy/central/gateway-service.yml | 30 ++++++++ .../domain/api-catalog-service.yml | 73 +++++++++++++++++++ .../domain/discovery-service.yml | 30 ++++++++ .../multi-tenancy/domain/gateway-service.yml | 31 ++++++++ .../multi-tenancy/domain/zaas-service.yml | 73 +++++++++++++++++++ 7 files changed, 251 insertions(+) create mode 100644 config/local/multi-tenancy/README.md create mode 100644 config/local/multi-tenancy/central/gateway-service.yml create mode 100644 config/local/multi-tenancy/domain/api-catalog-service.yml create mode 100644 config/local/multi-tenancy/domain/discovery-service.yml create mode 100644 config/local/multi-tenancy/domain/gateway-service.yml create mode 100644 config/local/multi-tenancy/domain/zaas-service.yml diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 68e1eb4642..ea7eecb6fd 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -289,6 +289,8 @@ jobs: APIML_SERVICE_HOSTNAME: gateway-service APIML_GATEWAY_REGISTRY_ENABLED: true APIML_SECURITY_X509_REGISTRY_ALLOWEDUSERS: USER,UNKNOWNUSER + mock-services: + image: ghcr.io/balhar-jakub/mock-services:${{ github.run_id }}-${{ github.run_number }} # Second group of services represents domain apiml instance which registers it's gateway in central's discovery service discovery-service-2: diff --git a/config/local/multi-tenancy/README.md b/config/local/multi-tenancy/README.md new file mode 100644 index 0000000000..edc3c77997 --- /dev/null +++ b/config/local/multi-tenancy/README.md @@ -0,0 +1,12 @@ +# Deploying Services Locally Using Multi-Tenancy Setup + +Start the services using the configuration in the [central](./central) and [domain](./domain) folders. + +## Setting Up Mutual Registration +For mutual registration of the Central Gateway and Domain Gateway, you need to set the following environment variables to specify the discovery service URLs for registration: + +1. **Domain Gateway**: + Set the following environment variable: `ZWE_CONFIGS_APIML_SERVICE_ADDITIONALREGISTRATION_0_DISCOVERYSERVICEURLS=https://localhost:10011/eureka` + +2. **Central Gateway**: + Set the following environment variable: `ZWE_CONFIGS_APIML_SERVICE_ADDITIONALREGISTRATION_0_DISCOVERYSERVICEURLS=https://localhost:10021/eureka` diff --git a/config/local/multi-tenancy/central/gateway-service.yml b/config/local/multi-tenancy/central/gateway-service.yml new file mode 100644 index 0000000000..75affbb305 --- /dev/null +++ b/config/local/multi-tenancy/central/gateway-service.yml @@ -0,0 +1,30 @@ +apiml: + health.protected: true + gateway.registry.enabled: true + security.x509.registry.allowedUsers: Zowe Service + service: + apimlId: apiml1 + forwardClientCertEnabled: true + hostname: localhost + port: 10010 + banner: console +eureka: + client: + serviceUrl: + defaultZone: https://localhost:10011/eureka/ +server: + ssl: + keyAlias: localhost + keyPassword: password + keyStore: keystore/localhost/localhost.keystore.p12 + keyStorePassword: password + keyStoreType: PKCS12 + trustStore: keystore/localhost/localhost.truststore.p12 + trustStorePassword: password + trustStoreType: PKCS12 +spring: + output: + ansi: + enabled: always + profiles: + include: debug diff --git a/config/local/multi-tenancy/domain/api-catalog-service.yml b/config/local/multi-tenancy/domain/api-catalog-service.yml new file mode 100644 index 0000000000..6a17ebf713 --- /dev/null +++ b/config/local/multi-tenancy/domain/api-catalog-service.yml @@ -0,0 +1,73 @@ +spring.profiles.include: diag + +eureka: + client: + initialInstanceInfoReplicationIntervalSeconds: 1 + registryFetchIntervalSeconds: 1 + instance: + leaseExpirationDurationInSeconds: 6 + leaseRenewalIntervalInSeconds: 1 + metadata-map: + apiml: + catalog: + tile: + id: ${apiml.catalog.id} + title: ${apiml.catalog.title} + description: ${apiml.catalog.description} + version: ${apiml.catalog.version} + +# routes: +# ui-v1: +# gatewayUrl: "/ui/v1/apiml2" +# serviceUrl: /apicatalog +# api-v1: +# gatewayUrl: "/api/v1" +# serviceUrl: /apicatalog + +server: + ssl: + enabled: true + keyAlias: localhost + keyPassword: password + keyStore: keystore/localhost/localhost.keystore.p12 + keyStorePassword: password + keyStoreType: PKCS12 + trustStore: keystore/localhost/localhost.truststore.p12 + trustStorePassword: password + trustStoreType: PKCS12 + +apiml: + health.protected: true + service: + hostname: localhost + ipAddress: 127.0.0.1 + port: 10024 + discoveryServiceUrls: https://localhost:10021/eureka/ + dsIpAddress: 0.0.0.0 + eurekaPassword: password + eurekaUserName: eureka + gatewayHostname: https://localhost:10020 + preferIpAddress: false + + service-registry: + cacheRefreshInitialDelayInMillis: 10000 + cacheRefreshRetryDelayInMillis: 10000 + cacheRefreshUpdateThresholdInMillis: 120000 + serviceFetchDelayInMillis: 10000 + banner: console + discovery: + staticApiDefinitionsDirectories: config/local/api-defs + +spring: + config: + useLegacyProcessing: true + output: + ansi: + enabled: always + +--- +spring.config.activate.on-profile: standalone + +apiml.catalog.standalone: + enabled: true + servicesDirectory: config/local/catalog-standalone-defs diff --git a/config/local/multi-tenancy/domain/discovery-service.yml b/config/local/multi-tenancy/domain/discovery-service.yml new file mode 100644 index 0000000000..7e09a78bfe --- /dev/null +++ b/config/local/multi-tenancy/domain/discovery-service.yml @@ -0,0 +1,30 @@ +spring.profiles.active: diag + +apiml: + health.protected: true + service: + hostname: localhost + ipAddress: 127.0.0.1 + port: 10021 + discovery: + staticApiDefinitionsDirectories: config/local/api-defs + security: + ssl.verifySslCertificatesOfServices: true + banner: console + +spring.output.ansi.enabled: always + +--- +spring.config.activate.on-profile: https + + +server: + ssl: + keyAlias: localhost + keyPassword: password + keyStoreType: PKCS12 + keyStore: keystore/localhost/localhost.keystore.p12 + keyStorePassword: password + trustStoreType: PKCS12 + trustStore: keystore/localhost/localhost.truststore.p12 + trustStorePassword: password diff --git a/config/local/multi-tenancy/domain/gateway-service.yml b/config/local/multi-tenancy/domain/gateway-service.yml new file mode 100644 index 0000000000..601e3051bb --- /dev/null +++ b/config/local/multi-tenancy/domain/gateway-service.yml @@ -0,0 +1,31 @@ +apiml: + health.protected: true + gateway.registry.enabled: true + security.x509.registry.allowedUsers: Zowe Service + service: + apimlId: apiml2 +# id: gateway + forwardClientCertEnabled: true + hostname: localhost + port: 10020 + banner: console +eureka: + client: + serviceUrl: + defaultZone: https://localhost:10021/eureka/ +server: + ssl: + keyAlias: localhost + keyPassword: password + keyStore: keystore/localhost/localhost.keystore.p12 + keyStorePassword: password + keyStoreType: PKCS12 + trustStore: keystore/localhost/localhost.truststore.p12 + trustStorePassword: password + trustStoreType: PKCS12 +spring: + output: + ansi: + enabled: always + profiles: + include: debug diff --git a/config/local/multi-tenancy/domain/zaas-service.yml b/config/local/multi-tenancy/domain/zaas-service.yml new file mode 100644 index 0000000000..32795833d1 --- /dev/null +++ b/config/local/multi-tenancy/domain/zaas-service.yml @@ -0,0 +1,73 @@ +spring.profiles.include: diag, debug +apiml: + service: + hostname: localhost + ipAddress: 127.0.0.1 + port: 10033 + discoveryServiceUrls: https://localhost:10021/eureka/ + + security: + allowTokenRefresh: true + webfinger: + fileLocation: config/local/webfinger.yml + personalAccessToken: + enabled: true + oidc: + enabled: false + clientId: + clientSecret: + registry: zowe.okta.com + identityMapperUrl: https://localhost:10010/zss/api/v1/certificate/dn + identityMapperUser: APIMTST + jwks: + uri: + auth: + jwt: + customAuthHeader: + passticket: + customUserHeader: + customAuthHeader: + provider: zosmf + zosmf: + serviceId: mockzosmf # Replace me with the correct z/OSMF service id + ssl: + verifySslCertificatesOfServices: true + x509: + enabled: true + acceptForwardedCert: true + certificatesUrl: https://localhost:10020/gateway/certificates + + banner: console + +spring: + config: + useLegacyProcessing: true + output: + ansi: + enabled: always + +server: + ssl: + keyAlias: localhost + keyPassword: password + keyStore: keystore/localhost/localhost.keystore.p12 + keyStorePassword: password + keyStoreType: PKCS12 + trustStore: keystore/localhost/localhost.truststore.p12 + trustStorePassword: password + trustStoreType: PKCS12 + +--- +spring.config.activate.on-profile: attls + +apiml: + service: + scheme: http + discoveryServiceUrls: http://localhost:10021/eureka/ + security: + saf: + urls: + authenticate: http://localhost:10013/zss/saf/authenticate + verify: http://localhost:10013/zss/saf/verify + + From baa271eddb844e8b9fa48a00fa9120d889faf02f Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Sat, 7 Dec 2024 11:15:31 +0100 Subject: [PATCH 33/37] minor eslint fix Signed-off-by: Andrea Tabone --- api-catalog-ui/frontend/src/utils/utilFunctions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api-catalog-ui/frontend/src/utils/utilFunctions.js b/api-catalog-ui/frontend/src/utils/utilFunctions.js index 8d7848f8ac..dd4886ae98 100644 --- a/api-catalog-ui/frontend/src/utils/utilFunctions.js +++ b/api-catalog-ui/frontend/src/utils/utilFunctions.js @@ -14,6 +14,7 @@ export const isValidUrl = (url) => { try { return Boolean(new URL(url)); } catch (e) { + console.error(`Invalid URL: ${url}, Error: ${e.message}`); return false; } }; @@ -93,8 +94,7 @@ export const customUIStyle = async (uiConfig) => { const root = document.documentElement; const logo = document.getElementById('logo'); if (logo && uiConfig.logo) { - const img = await fetchImagePath(); - logo.src = img; + logo.src = await fetchImagePath(); logo.style.height = 'auto'; logo.style.width = 'auto'; } From 3b9b012a09ffa4c2686099e49833b6747b8b354e Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Sat, 7 Dec 2024 11:42:53 +0100 Subject: [PATCH 34/37] minor eslint fix Signed-off-by: Andrea Tabone --- api-catalog-ui/frontend/src/utils/utilFunctions.js | 1 + 1 file changed, 1 insertion(+) diff --git a/api-catalog-ui/frontend/src/utils/utilFunctions.js b/api-catalog-ui/frontend/src/utils/utilFunctions.js index dd4886ae98..ba19de70cd 100644 --- a/api-catalog-ui/frontend/src/utils/utilFunctions.js +++ b/api-catalog-ui/frontend/src/utils/utilFunctions.js @@ -14,6 +14,7 @@ export const isValidUrl = (url) => { try { return Boolean(new URL(url)); } catch (e) { + // eslint-disable-next-line no-console console.error(`Invalid URL: ${url}, Error: ${e.message}`); return false; } From 4a5b347ea2d8d20fdd89edf976610d532f29f29a Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Sat, 7 Dec 2024 12:16:51 +0100 Subject: [PATCH 35/37] add debug messages Signed-off-by: Andrea Tabone --- .../apiml/functional/gateway/CentralRegistryTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java index 32a1eabcb6..82ce621dc6 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java +++ b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java @@ -183,12 +183,12 @@ void shouldContainCorrectBasePaths() throws MalformedURLException, URISyntaxExce DocumentContext jsonContext = JsonPath.parse(responseBody); JSONArray gatewayBasePath = jsonContext.read("$[0].services[?(@.serviceId == 'central-apiml')].basePath"); - assertNotNull(gatewayBasePath, "BasePath for central gw should not be null"); - assertFalse(gatewayBasePath.isEmpty(), "BasePath for central gw should not be empty"); + assertNotNull(gatewayBasePath, String.format("BasePath for central gw should not be null but it was '%s'", gatewayBasePath)); + assertFalse(gatewayBasePath.isEmpty(), String.format("BasePath for central gw should not be empty but it was '%s'", gatewayBasePath)); assertEquals("/", gatewayBasePath.get(0)); JSONArray domainGatewayBasePath = jsonContext.read("$[0].services[?(@.serviceId == 'domain-apiml')].basePath"); - assertNotNull(domainGatewayBasePath, "BasePath for domain gw should not be null"); - assertFalse(domainGatewayBasePath.isEmpty(), "BasePath for domain gw should not be empty"); + assertNotNull(domainGatewayBasePath, String.format("BasePath for domain gw should not be null but it was '%s'", domainGatewayBasePath)); + assertFalse(domainGatewayBasePath.isEmpty(), String.format("BasePath for domain gw should not be empty but it was '%s'", domainGatewayBasePath)); assertEquals("/" + DOMAIN_APIML, domainGatewayBasePath.get(0)); } From e6ba6c83713aaac170f5a599c8bc41929ee688e8 Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Sat, 7 Dec 2024 12:33:15 +0100 Subject: [PATCH 36/37] fix test Signed-off-by: Andrea Tabone --- .../org/zowe/apiml/functional/gateway/CentralRegistryTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java index 82ce621dc6..b0b9a142d3 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java +++ b/integration-tests/src/test/java/org/zowe/apiml/functional/gateway/CentralRegistryTest.java @@ -182,7 +182,7 @@ void shouldContainCorrectBasePaths() throws MalformedURLException, URISyntaxExce DocumentContext jsonContext = JsonPath.parse(responseBody); - JSONArray gatewayBasePath = jsonContext.read("$[0].services[?(@.serviceId == 'central-apiml')].basePath"); + JSONArray gatewayBasePath = jsonContext.read("$[0].services[?(@.serviceId == 'gateway')].basePath"); assertNotNull(gatewayBasePath, String.format("BasePath for central gw should not be null but it was '%s'", gatewayBasePath)); assertFalse(gatewayBasePath.isEmpty(), String.format("BasePath for central gw should not be empty but it was '%s'", gatewayBasePath)); assertEquals("/", gatewayBasePath.get(0)); From 2babacbebcf37e8e7089d5cacbbdca52682c992a Mon Sep 17 00:00:00 2001 From: Andrea Tabone Date: Mon, 9 Dec 2024 15:43:43 +0100 Subject: [PATCH 37/37] address comment Signed-off-by: Andrea Tabone --- config/local/multi-tenancy/README.md | 7 +- .../multi-tenancy/central/gateway-service.yml | 30 --------- .../domain/api-catalog-service.yml | 67 ------------------- .../domain/discovery-service.yml | 25 ------- .../multi-tenancy/domain/gateway-service.yml | 23 ------- .../multi-tenancy/domain/zaas-service.yml | 64 ------------------ 6 files changed, 6 insertions(+), 210 deletions(-) delete mode 100644 config/local/multi-tenancy/central/gateway-service.yml diff --git a/config/local/multi-tenancy/README.md b/config/local/multi-tenancy/README.md index edc3c77997..1d0cd54d80 100644 --- a/config/local/multi-tenancy/README.md +++ b/config/local/multi-tenancy/README.md @@ -1,6 +1,11 @@ # Deploying Services Locally Using Multi-Tenancy Setup -Start the services using the configuration in the [central](./central) and [domain](./domain) folders. +Start the Domain services using the additional configuration in the [domain](./domain) folder, which overrides certain properties, along with the configuration in the [local](../../local). +You can do that by passing multiple files via `spring.config.additional-location`. + +**Example:** + +`spring.config.additional-location=file:./config/local/api-catalog-service.yml,file:./config/local/multi-tenancy/domain/api-catalog-service.yml` ## Setting Up Mutual Registration For mutual registration of the Central Gateway and Domain Gateway, you need to set the following environment variables to specify the discovery service URLs for registration: diff --git a/config/local/multi-tenancy/central/gateway-service.yml b/config/local/multi-tenancy/central/gateway-service.yml deleted file mode 100644 index 75affbb305..0000000000 --- a/config/local/multi-tenancy/central/gateway-service.yml +++ /dev/null @@ -1,30 +0,0 @@ -apiml: - health.protected: true - gateway.registry.enabled: true - security.x509.registry.allowedUsers: Zowe Service - service: - apimlId: apiml1 - forwardClientCertEnabled: true - hostname: localhost - port: 10010 - banner: console -eureka: - client: - serviceUrl: - defaultZone: https://localhost:10011/eureka/ -server: - ssl: - keyAlias: localhost - keyPassword: password - keyStore: keystore/localhost/localhost.keystore.p12 - keyStorePassword: password - keyStoreType: PKCS12 - trustStore: keystore/localhost/localhost.truststore.p12 - trustStorePassword: password - trustStoreType: PKCS12 -spring: - output: - ansi: - enabled: always - profiles: - include: debug diff --git a/config/local/multi-tenancy/domain/api-catalog-service.yml b/config/local/multi-tenancy/domain/api-catalog-service.yml index 6a17ebf713..1855a635a0 100644 --- a/config/local/multi-tenancy/domain/api-catalog-service.yml +++ b/config/local/multi-tenancy/domain/api-catalog-service.yml @@ -1,73 +1,6 @@ -spring.profiles.include: diag - -eureka: - client: - initialInstanceInfoReplicationIntervalSeconds: 1 - registryFetchIntervalSeconds: 1 - instance: - leaseExpirationDurationInSeconds: 6 - leaseRenewalIntervalInSeconds: 1 - metadata-map: - apiml: - catalog: - tile: - id: ${apiml.catalog.id} - title: ${apiml.catalog.title} - description: ${apiml.catalog.description} - version: ${apiml.catalog.version} - -# routes: -# ui-v1: -# gatewayUrl: "/ui/v1/apiml2" -# serviceUrl: /apicatalog -# api-v1: -# gatewayUrl: "/api/v1" -# serviceUrl: /apicatalog - -server: - ssl: - enabled: true - keyAlias: localhost - keyPassword: password - keyStore: keystore/localhost/localhost.keystore.p12 - keyStorePassword: password - keyStoreType: PKCS12 - trustStore: keystore/localhost/localhost.truststore.p12 - trustStorePassword: password - trustStoreType: PKCS12 - apiml: - health.protected: true service: - hostname: localhost - ipAddress: 127.0.0.1 port: 10024 discoveryServiceUrls: https://localhost:10021/eureka/ - dsIpAddress: 0.0.0.0 - eurekaPassword: password - eurekaUserName: eureka gatewayHostname: https://localhost:10020 - preferIpAddress: false - - service-registry: - cacheRefreshInitialDelayInMillis: 10000 - cacheRefreshRetryDelayInMillis: 10000 - cacheRefreshUpdateThresholdInMillis: 120000 - serviceFetchDelayInMillis: 10000 - banner: console - discovery: - staticApiDefinitionsDirectories: config/local/api-defs - -spring: - config: - useLegacyProcessing: true - output: - ansi: - enabled: always - ---- -spring.config.activate.on-profile: standalone -apiml.catalog.standalone: - enabled: true - servicesDirectory: config/local/catalog-standalone-defs diff --git a/config/local/multi-tenancy/domain/discovery-service.yml b/config/local/multi-tenancy/domain/discovery-service.yml index 7e09a78bfe..6c5d16d366 100644 --- a/config/local/multi-tenancy/domain/discovery-service.yml +++ b/config/local/multi-tenancy/domain/discovery-service.yml @@ -1,30 +1,5 @@ -spring.profiles.active: diag - apiml: - health.protected: true service: - hostname: localhost - ipAddress: 127.0.0.1 port: 10021 - discovery: - staticApiDefinitionsDirectories: config/local/api-defs - security: - ssl.verifySslCertificatesOfServices: true - banner: console - -spring.output.ansi.enabled: always - ---- -spring.config.activate.on-profile: https -server: - ssl: - keyAlias: localhost - keyPassword: password - keyStoreType: PKCS12 - keyStore: keystore/localhost/localhost.keystore.p12 - keyStorePassword: password - trustStoreType: PKCS12 - trustStore: keystore/localhost/localhost.truststore.p12 - trustStorePassword: password diff --git a/config/local/multi-tenancy/domain/gateway-service.yml b/config/local/multi-tenancy/domain/gateway-service.yml index 601e3051bb..2469da958b 100644 --- a/config/local/multi-tenancy/domain/gateway-service.yml +++ b/config/local/multi-tenancy/domain/gateway-service.yml @@ -1,31 +1,8 @@ apiml: - health.protected: true - gateway.registry.enabled: true - security.x509.registry.allowedUsers: Zowe Service service: apimlId: apiml2 -# id: gateway - forwardClientCertEnabled: true - hostname: localhost port: 10020 - banner: console eureka: client: serviceUrl: defaultZone: https://localhost:10021/eureka/ -server: - ssl: - keyAlias: localhost - keyPassword: password - keyStore: keystore/localhost/localhost.keystore.p12 - keyStorePassword: password - keyStoreType: PKCS12 - trustStore: keystore/localhost/localhost.truststore.p12 - trustStorePassword: password - trustStoreType: PKCS12 -spring: - output: - ansi: - enabled: always - profiles: - include: debug diff --git a/config/local/multi-tenancy/domain/zaas-service.yml b/config/local/multi-tenancy/domain/zaas-service.yml index 32795833d1..7d39879902 100644 --- a/config/local/multi-tenancy/domain/zaas-service.yml +++ b/config/local/multi-tenancy/domain/zaas-service.yml @@ -1,73 +1,9 @@ -spring.profiles.include: diag, debug apiml: service: - hostname: localhost - ipAddress: 127.0.0.1 port: 10033 discoveryServiceUrls: https://localhost:10021/eureka/ security: - allowTokenRefresh: true - webfinger: - fileLocation: config/local/webfinger.yml - personalAccessToken: - enabled: true - oidc: - enabled: false - clientId: - clientSecret: - registry: zowe.okta.com - identityMapperUrl: https://localhost:10010/zss/api/v1/certificate/dn - identityMapperUser: APIMTST - jwks: - uri: - auth: - jwt: - customAuthHeader: - passticket: - customUserHeader: - customAuthHeader: - provider: zosmf - zosmf: - serviceId: mockzosmf # Replace me with the correct z/OSMF service id - ssl: - verifySslCertificatesOfServices: true x509: - enabled: true - acceptForwardedCert: true certificatesUrl: https://localhost:10020/gateway/certificates - banner: console - -spring: - config: - useLegacyProcessing: true - output: - ansi: - enabled: always - -server: - ssl: - keyAlias: localhost - keyPassword: password - keyStore: keystore/localhost/localhost.keystore.p12 - keyStorePassword: password - keyStoreType: PKCS12 - trustStore: keystore/localhost/localhost.truststore.p12 - trustStorePassword: password - trustStoreType: PKCS12 - ---- -spring.config.activate.on-profile: attls - -apiml: - service: - scheme: http - discoveryServiceUrls: http://localhost:10021/eureka/ - security: - saf: - urls: - authenticate: http://localhost:10013/zss/saf/authenticate - verify: http://localhost:10013/zss/saf/verify - -