Skip to content

Commit 47c3e60

Browse files
pablocarlenx673747Pablo Carletaban03achmelo
authored
feat: apiml Spring-Modulith based module with Gateway and Discovery services (#4051)
Signed-off-by: nx673747 <nafi.xhafa@broadcom.com> Signed-off-by: Pablo Carle <pablo.carle@broadcom.com> Signed-off-by: Andrea Tabone <andrea.tabone@broadcom.com> Signed-off-by: Pablo Carle <pablocarle@users.noreply.github.com> Co-authored-by: nx673747 <nafi.xhafa@broadcom.com> Co-authored-by: Pablo Carle <pablo.carle@broadcom.com> Co-authored-by: Andrea Tabone <andrea.tabone@broadcom.com> Co-authored-by: Andrea Tabone <39694626+taban03@users.noreply.github.com> Co-authored-by: achmelo <37397715+achmelo@users.noreply.github.com> Co-authored-by: Jakub Balhar <jakub@balhar.net>
1 parent d0da88a commit 47c3e60

167 files changed

Lines changed: 6810 additions & 783 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/dump-jacoco/action.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ runs:
1212
java -jar ./scripts/jacococli.jar dump --retry 1 --address caching-service --port 6306 --destfile ./results/caching-service.exec || echo "Caching service is not available to obtain JaCoCo report at the moment"
1313
java -jar ./scripts/jacococli.jar dump --retry 1 --address discovery-service --port 6302 --destfile ./results/discovery-service.exec || echo "Discovery service is not available to obtain JaCoCo report at the moment"
1414
java -jar ./scripts/jacococli.jar dump --retry 1 --address api-catalog-services --port 6304 --destfile ./results/api-catalog-services.exec || echo "API Catalog is not available to obtain JaCoCo report at the moment"
15+
java -jar ./scripts/jacococli.jar dump --retry 1 --address apiml --port 6310 --destfile ./results/apiml.exec || echo "API ML (Modulith) is not available to obtain JaCoCo report at the moment"

.github/actions/validate-apiml-healthy/action.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ name: "Validate APIML Healthy"
22
description: "Validates APIML health using Gateway, Caching Service and Authentication Service health status"
33

44
inputs:
5+
gateway-host:
6+
description: "Gateway hostname"
7+
required: false
8+
default: "localhost"
9+
zaas-host:
10+
description: "ZAAS hostname"
11+
required: false
12+
default: "localhost"
513
caching-service:
614
description: "Check Caching Service health"
715
required: false
@@ -29,8 +37,8 @@ runs:
2937
valid="false"
3038
until [ $attemptCounter -gt $maxAttempts ]; do
3139
sleep 10
32-
gwHealth=$(curl -k -s https://localhost:10010/application/health)
33-
zaasHealth=$(curl -k -s https://localhost:10023/application/health)
40+
gwHealth=$(curl -k -s https://${{ inputs.gateway-host }}:10010/application/health)
41+
zaasHealth=$(curl -k -s https://${{ inputs.zaas-host }}:10023/application/health)
3442
echo "Polling for GW health: $attemptCounter"
3543
echo $gwHealth
3644

.github/workflows/integration-tests.yml

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,78 @@ jobs:
3232
3333
- uses: ./.github/actions/teardown
3434

35+
CITestsModulith:
36+
needs: PublishJibContainers
37+
runs-on: ubuntu-latest
38+
container: ubuntu:latest
39+
timeout-minutes: 15
40+
41+
services:
42+
apiml:
43+
image: ghcr.io/balhar-jakub/apiml:${{ github.run_id }}-${{ github.run_number }}
44+
env:
45+
APIML_SECURITY_AUTH_JWT_CUSTOMAUTHHEADER: customJwtHeader
46+
APIML_SECURITY_AUTH_PASSTICKET_CUSTOMUSERHEADER: customUserHeader
47+
APIML_SECURITY_AUTH_PASSTICKET_CUSTOMAUTHHEADER: customPassticketHeader
48+
ZWE_CONFIGS_APIML_SERVICE_ADDITIONALREGISTRATION_0_DISCOVERYSERVICEURLS: https://discovery-service-2:10011/eureka
49+
SERVER_MAX_HTTP_REQUEST_HEADER_SIZE: 16348
50+
SERVER_WEBSOCKET_REQUESTBUFFERSIZE: 16348
51+
APIML_GATEWAY_SERVICESTOLIMITREQUESTRATE: discoverableclient
52+
APIML_GATEWAY_COOKIENAMEFORRATELIMIT: apimlAuthenticationToken
53+
api-catalog-services:
54+
image: ghcr.io/balhar-jakub/api-catalog-services:${{ github.run_id }}-${{ github.run_number }}
55+
volumes:
56+
- /api-defs:/api-defs
57+
env:
58+
APIML_SERVICE_HOSTNAME: api-catalog-services
59+
APIML_SERVICE_DISCOVERYSERVICEURLS: https://apiml:10011/eureka
60+
APIML_SERVICE_GATEWAYHOSTNAME: https://apiml:10010
61+
caching-service:
62+
image: ghcr.io/balhar-jakub/caching-service:${{ github.run_id }}-${{ github.run_number }}
63+
env:
64+
APIML_SERVICE_DISCOVERYSERVICEURLS: https://apiml:10011/eureka
65+
discoverable-client:
66+
image: ghcr.io/balhar-jakub/discoverable-client:${{ github.run_id }}-${{ github.run_number }}
67+
env:
68+
APIML_SERVICE_DISCOVERYSERVICEURLS: https://apiml:10011/eureka
69+
zaas-service:
70+
image: ghcr.io/balhar-jakub/zaas-service:${{ github.run_id }}-${{ github.run_number }}
71+
env:
72+
APIML_SECURITY_X509_ENABLED: true
73+
APIML_SECURITY_X509_ACCEPTFORWARDEDCERT: true
74+
APIML_SECURITY_X509_CERTIFICATESURL: https://apiml:10010/gateway/certificates
75+
APIML_SERVICE_DISCOVERYSERVICEURLS: https://apiml:10011/eureka
76+
mock-services:
77+
image: ghcr.io/balhar-jakub/mock-services:${{ github.run_id }}-${{ github.run_number }}
78+
env:
79+
APIML_SERVICE_DISCOVERYSERVICEURLS: https://apiml:10011/eureka
80+
steps:
81+
- uses: actions/checkout@v4
82+
with:
83+
ref: ${{ github.head_ref }}
84+
85+
- uses: ./.github/actions/setup
86+
87+
- name: Run CI Tests
88+
run: >
89+
ENV_CONFIG=docker-modulith ./gradlew runStartUpCheck :integration-tests:runContainerModulithTests --info
90+
-Ddiscoverableclient.instances=1 -Denvironment.config=-docker-modulith
91+
-Partifactory_user=${{ secrets.ARTIFACTORY_USERNAME }} -Partifactory_password=${{ secrets.ARTIFACTORY_PASSWORD }}
92+
- uses: ./.github/actions/dump-jacoco
93+
if: always()
94+
- name: Store results
95+
uses: actions/upload-artifact@v4
96+
if: always()
97+
with:
98+
name: ContainerCITestsModulith-${{ env.JOB_ID }}
99+
path: |
100+
integration-tests/build/reports/**
101+
results/**
102+
integration-tests/build/test-results/runContainerModulithTests/binary/**
103+
integration-tests/build/test-results/runStartUpCheck/binary/**
104+
105+
- uses: ./.github/actions/teardown
106+
35107
CITests:
36108
needs: PublishJibContainers
37109
runs-on: ubuntu-latest
@@ -1519,7 +1591,7 @@ jobs:
15191591
- uses: ./.github/actions/teardown
15201592

15211593
PublishResults:
1522-
needs: [ CITests,CITestsWithInfinispan,CITestsZaas,GatewayProxy,GatewayServiceRouting,CITestsWebSocketChaoticHA ]
1594+
needs: [ CITests,CITestsModulith,CITestsWithInfinispan,CITestsZaas,GatewayProxy,GatewayServiceRouting,CITestsWebSocketChaoticHA ]
15231595
runs-on: ubuntu-latest
15241596
timeout-minutes: 20
15251597

@@ -1535,6 +1607,10 @@ jobs:
15351607
with:
15361608
name: ContainerCITests-${{ env.JOB_ID }}
15371609
path: containercitests
1610+
- uses: actions/download-artifact@v4
1611+
with:
1612+
name: ContainerCITestsModulith-${{ env.JOB_ID }}
1613+
path: containercitestsmodulith
15381614
- uses: actions/download-artifact@v4
15391615
with:
15401616
name: CITestsWithInfinispan-${{ env.JOB_ID }}
@@ -1558,7 +1634,7 @@ jobs:
15581634

15591635
- name: Code coverage and publish results
15601636
run: >
1561-
./gradlew --scan coverage sonar -Dresults="containercitests/results,citestswithinfinispan/results,GatewayProxy/results,citestswebsocketchaoticha/results,GatewayServiceRouting/results,ContainerCITestsZaas/results"
1637+
./gradlew --scan coverage sonar -Dresults="containercitests/results,containercitestsmodulith/results,citestswithinfinispan/results,GatewayProxy/results,citestswebsocketchaoticha/results,GatewayServiceRouting/results,ContainerCITestsZaas/results"
15621638
-Psonar.host.url=$SONAR_HOST_URL -Dsonar.token=$SONAR_TOKEN -Partifactory_user=$ARTIFACTORY_USERNAME -Partifactory_password=$ARTIFACTORY_PASSWORD
15631639
env:
15641640
ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ bin
4747
!api-catalog-package/src/main/resources/bin
4848
!discovery-package/src/main/resources/bin
4949
!caching-service-package/src/main/resources/bin
50+
!zaas-service-package/src/main/resources/bin
51+
!apiml-package/src/main/resources/bin
5052
var
5153
sdist
5254
develop-eggs

.run/ApimlApplication.run.xml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!--
2+
~ /*
3+
~ * This program and the accompanying materials are made available under the terms of the
4+
~ * Eclipse Public License v2.0 which accompanies this distribution, and is available at
5+
~ * https://www.eclipse.org/legal/epl-v20.html
6+
~ *
7+
~ * SPDX-License-Identifier: EPL-2.0
8+
~ *
9+
~ * Copyright Contributors to the Zowe Project.
10+
~ */
11+
-->
12+
13+
<component name="ProjectRunConfigurationManager">
14+
<configuration default="false" name="ApimlApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
15+
<additionalParameters>
16+
<param>
17+
<option name="enabled" value="true" />
18+
<option name="name" value="spring.config.additional-location" />
19+
<option name="value" value="file:./config/local/apiml-service.yml" />
20+
</param>
21+
</additionalParameters>
22+
<module name="api-layer.apiml.main" />
23+
<option name="SHORTEN_COMMAND_LINE" value="ARGS_FILE" />
24+
<option name="SPRING_BOOT_MAIN_CLASS" value="org.zowe.apiml.ApimlApplication" />
25+
<option name="VM_PARAMETERS" value="--add-opens=java.base/java.nio.channels.spi=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/javax.net.ssl=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED" />
26+
<method v="2">
27+
<option name="Make" enabled="true" />
28+
</method>
29+
</configuration>
30+
</component>

api-catalog-package/src/main/resources/bin/start.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ LIBPATH="$LIBPATH":"/usr/lib"
136136
LIBPATH="$LIBPATH":"${JAVA_HOME}"/bin
137137
LIBPATH="$LIBPATH":"${JAVA_HOME}"/bin/classic
138138
LIBPATH="$LIBPATH":"${JAVA_HOME}"/bin/j9vm
139-
LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390/classic
140-
LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390/default
141-
LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390/j9vm
139+
LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390x/classic
140+
LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390x/default
141+
LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390x/j9vm
142142
LIBPATH="$LIBPATH":"${LIBRARY_PATH}"
143143

144144
ADD_OPENS="--add-opens=java.base/java.lang=ALL-UNNAMED

api-catalog-services/build.gradle

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ apply from: "$projectDir/gradle/lite.gradle"
2323
apply plugin: 'com.google.cloud.tools.jib'
2424
apply from: "../gradle/jib.gradle"
2525

26-
def javaAgentPort = 6304
27-
def debugPort = 5124
26+
def applicationPort = '10014'
27+
def javaAgentPort = '6304'
28+
def debugPort = '5124'
2829
def componentName = "api-catalog-services"
2930
if (project.hasProperty('zowe.jib.image.suffix')) { // Prefix for the component name (for the standalone catalog container)
3031
componentName += '-' + project.getProperty('zowe.jib.image.suffix')
@@ -36,7 +37,7 @@ if (project.hasProperty('zowe.jib.image.debugPort')) {
3637
debugPort = project.getProperty('zowe.jib.image.debugPort')
3738
}
3839

39-
setJib(componentName, javaAgentPort, debugPort)
40+
setJib(componentName, javaAgentPort, debugPort, applicationPort)
4041

4142
springBoot {
4243
// This statement tells the Gradle Spring Boot plugin to generate a file
@@ -132,6 +133,18 @@ bootRun {
132133
args project.args.split(',')
133134
}
134135

136+
jvmArgs([
137+
'--add-opens=java.base/java.nio.channels.spi=ALL-UNNAMED',
138+
'--add-opens=java.base/sun.nio.ch=ALL-UNNAMED',
139+
'--add-opens=java.base/java.io=ALL-UNNAMED',
140+
'--add-opens=java.base/java.util=ALL-UNNAMED',
141+
'--add-opens=java.base/java.util.concurrent=ALL-UNNAMED',
142+
'--add-opens=java.base/java.lang.invoke=ALL-UNNAMED',
143+
'--add-opens=java.base/java.lang.reflect=ALL-UNNAMED',
144+
'--add-opens=java.base/javax.net.ssl=ALL-UNNAMED',
145+
'--add-opens=java.base/java.net=ALL-UNNAMED'
146+
])
147+
135148
debugOptions {
136149
port = 5014
137150
suspend = false

api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/instance/InstanceRetrievalService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ private List<EurekaServiceInstanceRequest> constructServiceInfoQueryRequest(Stri
232232
String[] discoveryServiceUrls = discoveryConfigProperties.getLocations();
233233
List<EurekaServiceInstanceRequest> eurekaServiceInstanceRequests = new ArrayList<>(discoveryServiceUrls.length);
234234
for (String discoveryUrl : discoveryServiceUrls) {
235-
String discoveryServiceLocatorUrl = discoveryUrl + APPS_ENDPOINT;
235+
String discoveryServiceLocatorUrl = discoveryUrl.endsWith("/") ? discoveryUrl + APPS_ENDPOINT : discoveryUrl + "/" + APPS_ENDPOINT;
236236
if (getDelta) {
237237
discoveryServiceLocatorUrl += DELTA_ENDPOINT;
238238
} else {

api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/staticapi/StaticAPIService.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,17 @@
1515
import org.apache.hc.client5.http.classic.methods.HttpPost;
1616
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
1717
import org.apache.hc.core5.http.HttpEntity;
18+
import org.apache.hc.core5.http.io.entity.EntityUtils;
1819
import org.springframework.beans.factory.annotation.Qualifier;
1920
import org.springframework.beans.factory.annotation.Value;
2021
import org.springframework.http.HttpStatus;
2122
import org.springframework.stereotype.Service;
2223
import org.zowe.apiml.apicatalog.discovery.DiscoveryConfigProperties;
2324

24-
import java.io.BufferedReader;
2525
import java.io.IOException;
26-
import java.io.InputStreamReader;
2726
import java.util.ArrayList;
2827
import java.util.Base64;
2928
import java.util.List;
30-
import java.util.stream.Collectors;
3129

3230
@Service
3331
@RequiredArgsConstructor
@@ -62,7 +60,7 @@ public StaticAPIResponse refresh() {
6260
final HttpEntity responseEntity = response.getEntity();
6361
String responseBody = "";
6462
if (responseEntity != null) {
65-
responseBody = new BufferedReader(new InputStreamReader(responseEntity.getContent())).lines().collect(Collectors.joining("\n"));
63+
responseBody = EntityUtils.toString(responseEntity);
6664
}
6765
return new StaticAPIResponse(response.getCode(), responseBody);
6866
});
@@ -99,7 +97,9 @@ private List<String> getDiscoveryServiceUrls() {
9997

10098
List<String> discoveryServiceUrls = new ArrayList<>();
10199
for (String location : discoveryServiceLocations) {
102-
discoveryServiceUrls.add(location.replace("/eureka", "") + REFRESH_ENDPOINT);
100+
location = location.replace("/eureka", "");
101+
location = location.endsWith("/") ? location : location + "/";
102+
discoveryServiceUrls.add(location + REFRESH_ENDPOINT);
103103
}
104104
return discoveryServiceUrls;
105105
}

api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/staticapi/StaticAPIRefreshControllerTest.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,13 @@
1212

1313
import org.junit.jupiter.api.BeforeEach;
1414
import org.junit.jupiter.api.Test;
15-
import org.junit.jupiter.api.extension.ExtendWith;
1615
import org.springframework.beans.factory.annotation.Autowired;
1716
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
1817
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
1918
import org.springframework.context.annotation.ComponentScan;
2019
import org.springframework.context.annotation.FilterType;
2120
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
2221
import org.springframework.test.context.ContextConfiguration;
23-
import org.springframework.test.context.junit.jupiter.SpringExtension;
2422
import org.springframework.test.web.servlet.MockMvc;
2523
import org.springframework.web.client.RestClientException;
2624
import org.zowe.apiml.apicatalog.services.status.model.ServiceNotFoundException;
@@ -32,7 +30,6 @@
3230
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
3331
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
3432

35-
@ExtendWith(SpringExtension.class)
3633
@WebMvcTest(controllers = {StaticAPIRefreshController.class},
3734
excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = WebSecurityConfigurer.class) },
3835
excludeAutoConfiguration = { SecurityAutoConfiguration.class}

0 commit comments

Comments
 (0)