Skip to content

Commit

Permalink
Merge pull request #513 from Axway-API-Management-Plus/develop
Browse files Browse the repository at this point in the history
Release 1.14.7
  • Loading branch information
rathnapandi authored Oct 24, 2024
2 parents b75891c + 573ed77 commit 9202fbd
Show file tree
Hide file tree
Showing 96 changed files with 1,988 additions and 596 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ name: APIM CLI Integration Tests
on: [push]

env:
CASSANDRA_DOCKER_IMAGE: cassandra:4.0.13
APIM_DOCKER_IMAGE: docker.repository.axway.com/apigateway-docker-prod/7.7/gateway:7.7.0.20240530-2-BN0004-ubi9
CACHE_FILE_APIM: api-manager_7_7_20240530.cache.tar
CACHE_FILE_CASSANDRA: cassandra_4_0_13.cache.tar
FED_FILE: swagger-promote-7.7-20240530.fed
CASSANDRA_DOCKER_IMAGE: cassandra:4.1.6
APIM_DOCKER_IMAGE: docker.repository.axway.com/apigateway-docker-prod/7.7/gateway:7.7.0.20240830-4-BN0145-ubi9
CACHE_FILE_APIM: api-manager_7_7_20240830.cache.tar
CACHE_FILE_CASSANDRA: cassandra_4_1_6.cache.tar
FED_FILE: swagger-promote-7.7-20240830.fed
LOG_LEVEL: debug

jobs:
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).


# [1.14.7] In progress
## Fixed
- NullPointerException: Cannot invoke "com.axway.apim.api.model.APIMethod.getName() (See issue [#512](https://github.com/Axway-API-Management-Plus/apim-cli/issues/512))
- Enable caching for API Import action (See issue [#500](https://github.com/Axway-API-Management-Plus/apim-cli/issues/500))

### Added
- allow APIM cli to connect to API Manager protected by Cloudflare (See issue [#505](https://github.com/Axway-API-Management-Plus/apim-cli/issues/505))

- Added new paramater named customHeaders to handle additonal headers.
E.g ./apim.sh api get -n CalculatorService3 -o json -h localhost -u apiadmin -customHeaders abc:xyz
- Support August 2024 APIM Release (See issue [#504](https://github.com/Axway-API-Management-Plus/apim-cli/issues/504))

# [1.14.6] 2024-10-11
## Fixed
- Importing SOAP API with different endpoints (for import and for runtime calls) (See issue [#501](https://github.com/Axway-API-Management-Plus/apim-cli/issues/501))
Expand Down
27 changes: 14 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,20 @@ In addition to a number of executed unit-tests, sophisticated integration tests

The automated End-2-End test suite contains of __116__ different scenarios, which includes more than __284__ executions of CLI (Import & Export) following each by a validation step. The test suite is executed at Travis CI for the following versions and you may check yourself what is done by clicking on the badge icon:

| Version | Branch | Status | Comment |
|:-------------|:----------------------------------------------------| :---: |:-------------------------------------------------------------------|
| 7.7-20240530 | develop |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.14.5 |
| 7.7-20240228 | test-with-7.7-20240228 |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.14.4 |
| 7.7-20230130 | test-with-7.7-20231130 |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.14.3 |
| 7.7-20230830 | test-with-7.7-20230830 |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.14.2 |
| 7.7-20230530 | test-with-7.7-20230530 |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.14.0 |
| 7.7-20230228 | test-with-7.7-20230228 |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.13.4 |
| 7.7-20221130 | test-with-7.7-20221130 |[![APIM CLI Integration test](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml)| Requires version >=1.13.2, Multi-Org supported from version 1.13.3 |
| 7.7-20220830 | test-with-7.7-20220830 |[![APIM CLI Integration test](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg?branch=test-with-7.7-20220830)](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml)| Requires version >=1.13.0, Multi-Org is not yet supported |
| 7.7-20220530 | test-with-7.7-20220530 | [![Build Status](https://img.shields.io/travis/Axway-API-Management-Plus/apim-cli/test-with-7.7-20211130)](https://app.travis-ci.com/github/Axway-API-Management-Plus/apim-cli/branches)| Requires version >=1.12.0, Multi-Org is not yet supported |
| 7.7-20220228 | test-with-7.7-20220228 | [![Build Status](https://img.shields.io/travis/Axway-API-Management-Plus/apim-cli/test-with-7.7-20220228)](https://app.travis-ci.com/github/Axway-API-Management-Plus/apim-cli/branches)| Requires version >=1.10.1, Multi-Org is not yet supported |
| 7.7-20211130 | test-with-7.7-20211130 | [![Build Status](https://img.shields.io/travis/Axway-API-Management-Plus/apim-cli/test-with-7.7-20211130)](https://app.travis-ci.com/github/Axway-API-Management-Plus/apim-cli/branches)| Requires version >=1.3.11, Multi-Org is not yet supported |
| Version | Branch | Status | Comment |
|:-------------|:-----------------------| :---: |:-------------------------------------------------------------------|
| 7.7-20240830 | develop |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.14.7 |
| 7.7-20240530 | test-with-7.7-20240530 |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.14.5 |
| 7.7-20240228 | test-with-7.7-20240228 |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.14.4 |
| 7.7-20230130 | test-with-7.7-20231130 |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.14.3 |
| 7.7-20230830 | test-with-7.7-20230830 |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.14.2 |
| 7.7-20230530 | test-with-7.7-20230530 |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.14.0 |
| 7.7-20230228 | test-with-7.7-20230228 |![Build Status](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)| Requires version >=1.13.4 |
| 7.7-20221130 | test-with-7.7-20221130 |[![APIM CLI Integration test](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg)](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml)| Requires version >=1.13.2, Multi-Org supported from version 1.13.3 |
| 7.7-20220830 | test-with-7.7-20220830 |[![APIM CLI Integration test](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml/badge.svg?branch=test-with-7.7-20220830)](https://github.com/Axway-API-Management-Plus/apim-cli/actions/workflows/integration-test.yml)| Requires version >=1.13.0, Multi-Org is not yet supported |
| 7.7-20220530 | test-with-7.7-20220530 | [![Build Status](https://img.shields.io/travis/Axway-API-Management-Plus/apim-cli/test-with-7.7-20211130)](https://app.travis-ci.com/github/Axway-API-Management-Plus/apim-cli/branches)| Requires version >=1.12.0, Multi-Org is not yet supported |
| 7.7-20220228 | test-with-7.7-20220228 | [![Build Status](https://img.shields.io/travis/Axway-API-Management-Plus/apim-cli/test-with-7.7-20220228)](https://app.travis-ci.com/github/Axway-API-Management-Plus/apim-cli/branches)| Requires version >=1.10.1, Multi-Org is not yet supported |
| 7.7-20211130 | test-with-7.7-20211130 | [![Build Status](https://img.shields.io/travis/Axway-API-Management-Plus/apim-cli/test-with-7.7-20211130)](https://app.travis-ci.com/github/Axway-API-Management-Plus/apim-cli/branches)| Requires version >=1.3.11, Multi-Org is not yet supported |


At least version 7.7-20211130 is required.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -582,17 +582,17 @@ public static String getCertInfo(InputStream certificate, String password, CaCer
* Helper method to translate a Base64 encoded format
* as it's needed by the API-Manager.
*
* @param fileFontent the certificate content
* @param fileContent the certificate content
* @param filename the name of the certificate file used as a reference in the generated Json object
* @param contentType the content type
* @return a Json-Object structure as needed by the API-Manager
* @throws AppException when the certificate information can't be created
*/
public static JsonNode getFileData(byte[] fileFontent, String filename, ContentType contentType) throws AppException {
public JsonNode getFileData(byte[] fileContent, String filename, ContentType contentType) throws AppException {
try {
URI uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(cmd.getApiBasepath() + "/filedata/").build();
HttpEntity entity = MultipartEntityBuilder.create()
.addBinaryBody("file", fileFontent, contentType, filename)
.addBinaryBody("file", fileContent, contentType, filename)
.build();
POSTRequest postRequest = new POSTRequest(entity, uri);
try (CloseableHttpResponse httpResponse = (CloseableHttpResponse) postRequest.execute()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,8 @@ public enum FILTER_OP {
ne,
gt,
lt,
ge,
le,
like,
gele
like
}

private String id;
Expand Down Expand Up @@ -642,7 +640,6 @@ public Builder(APIType type) {
* @param loadBackendAPI is search backendEndAPI if set to true
*/
public Builder(APIType type, boolean loadBackendAPI) {
super();
initType(type);
this.apiType = type;
this.loadBackendAPI = loadBackendAPI;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@

public class APIManagerAPIAccessAdapter {

public static final String APIS = "/apis";

public enum Type {
organizations("Organization"),
applications("Application");
Expand Down Expand Up @@ -79,7 +81,7 @@ private void readAPIAccessFromAPIManager(Type type, String id) throws AppExcepti
return;
}
try {
URI uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(cmd.getApiBasepath() + "/" + type + "/" + id + "/apis").build();
URI uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(cmd.getApiBasepath() + "/" + type + "/" + id + APIS).build();
RestAPICall getRequest = new GETRequest(uri);
LOG.debug("Load API-Access with type: {} from API-Manager with ID: {}", type, id);
try (CloseableHttpResponse httpResponse = (CloseableHttpResponse) getRequest.execute()) {
Expand Down Expand Up @@ -110,7 +112,7 @@ public List<APIAccess> getAPIAccess(AbstractEntity entity, Type type, boolean in
String apiAccessResponse;
try {
apiAccessResponse = apiManagerResponse.get(type).get(entity.getId());
List<APIAccess> allApiAccess = mapper.readValue(apiAccessResponse, new TypeReference<List<APIAccess>>() {
List<APIAccess> allApiAccess = mapper.readValue(apiAccessResponse, new TypeReference<>() {
});
if (includeAPIName) {
for (APIAccess apiAccess : allApiAccess) {
Expand Down Expand Up @@ -153,6 +155,13 @@ private void removeFromCache(String id, Type type) {
}
}

private void removeApplicationFromCache(String id) {
Cache<String, String> usedCache = caches.get(Type.applications);
if (usedCache != null && usedCache.containsKey(id))
usedCache.remove(id);

}

public void saveAPIAccess(List<APIAccess> apiAccess, AbstractEntity entity, Type type) throws AppException {
List<APIAccess> existingAPIAccess = getAPIAccess(entity, type, true);
List<APIAccess> toBeRemovedAccesses = getMissingAPIAccesses(existingAPIAccess, apiAccess);
Expand Down Expand Up @@ -194,14 +203,38 @@ public void populateApiId(APIAccess apiAccess) throws AppException {
}
}

public APIAccess createAPIAccessForApplication(APIAccess apiAccess, String applicationId) throws AppException {
try {
URI uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(cmd.getApiBasepath() + "/applications/" + applicationId + APIS).build();
mapper.setSerializationInclusion(Include.NON_NULL);
FilterProvider filter = new SimpleFilterProvider().setDefaultFilter(
SimpleBeanPropertyFilter.serializeAllExcept("apiName", "apiVersion"));
mapper.setFilterProvider(filter);
HttpEntity entity = new StringEntity(mapper.writeValueAsString(apiAccess), ContentType.APPLICATION_JSON);
RestAPICall request = new POSTRequest(entity, uri);
try (CloseableHttpResponse httpResponse = (CloseableHttpResponse) request.execute()) {
int statusCode = httpResponse.getStatusLine().getStatusCode();
String response = EntityUtils.toString(httpResponse.getEntity());
if (statusCode != 201) {
LOG.error("Error granting access to application id : {} for API-Proxy : {} using URI: {} Received Status-Code: {} Response: {}", applicationId, apiAccess.getApiId(), uri, statusCode, response);
throw new AppException("Can't grant access to API.", ErrorCode.ERR_GRANTING_ACCESS_TO_API);
}
removeApplicationFromCache(applicationId);
return mapper.readValue(response, APIAccess.class);
}
} catch (Exception e) {
throw new AppException("Can't grant access to API.", ErrorCode.ERR_GRANTING_ACCESS_TO_API, e);
}
}

public void createAPIAccess(APIAccess apiAccess, AbstractEntity parentEntity, Type type) throws AppException {
List<APIAccess> existingAPIAccess = getAPIAccess(parentEntity, type, true);
if (existingAPIAccess != null && existingAPIAccess.contains(apiAccess)) {
apiAccess.setId(existingAPIAccess.get(0).getId());
return;
}
try {
URI uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(cmd.getApiBasepath() + "/" + type + "/" + parentEntity.getId() + "/apis").build();
URI uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(cmd.getApiBasepath() + "/" + type + "/" + parentEntity.getId() + APIS).build();
mapper.setSerializationInclusion(Include.NON_NULL);
FilterProvider filter = new SimpleFilterProvider().setDefaultFilter(
SimpleBeanPropertyFilter.serializeAllExcept("apiName", "apiVersion"));
Expand Down Expand Up @@ -252,12 +285,12 @@ public void deleteAPIAccess(APIAccess apiAccess, AbstractEntity parentEntity, Ty
if (statusCode < 200 || statusCode > 299) {
String errorResponse = EntityUtils.toString(httpResponse.getEntity());
LOG.error("Can't delete API access requests for application. Response-Code: {}. Got response: {}", statusCode, errorResponse);
throw new AppException("Can't delete API access requests for application. Response-Code: " + statusCode, ErrorCode.API_MANAGER_COMMUNICATION);
throw new AppException("Can't delete API access requests for application. Response-Code: " + statusCode, ErrorCode.REVOKE_ACCESS_APPLICATION_ERR);
}
removeFromCache(parentEntity.getId(), type);
}
} catch (Exception e) {
throw new AppException("Can't delete API access requests for application.", ErrorCode.CANT_CREATE_API_PROXY, e);
throw new AppException("Can't delete API access requests for application.", ErrorCode.REVOKE_ACCESS_APPLICATION_ERR, e);
}
}

Expand Down Expand Up @@ -291,7 +324,7 @@ public List<APIAccess> getMissingAPIAccesses(List<APIAccess> apiAccess, List<API
}


public List<ApiOrganizationSubscription> getApiAccess(String apiId) throws AppException{
public List<ApiOrganizationSubscription> getSubscribedOrganizationsAndApplications(String apiId) throws AppException {
try {
URI uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(cmd.getApiBasepath() + "/proxies/" + apiId + "/apiaccess").build();
RestAPICall request = new GETRequest(uri);
Expand All @@ -302,7 +335,8 @@ public List<ApiOrganizationSubscription> getApiAccess(String apiId) throws AppEx
LOG.error("Can't get API access requests for API. Response-Code: {}. Got response: {}", statusCode, response);
throw new AppException("Can't get API access requests for API: " + statusCode, ErrorCode.API_MANAGER_COMMUNICATION);
}
return mapper.readValue(response, new TypeReference<List<ApiOrganizationSubscription>>(){});
return mapper.readValue(response, new TypeReference<>() {
});
}
} catch (Exception e) {
throw new AppException("Can't delete API access requests for application.", ErrorCode.API_MANAGER_COMMUNICATION, e);
Expand Down
Loading

0 comments on commit 9202fbd

Please sign in to comment.