Skip to content

Commit c0b5197

Browse files
author
Chris Wiechmann
committed
Introduced a change command for APIs
1 parent 6827812 commit c0b5197

16 files changed

Lines changed: 339 additions & 46 deletions

File tree

modules/api-export/pom.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
<dependency>
2727
<groupId>com.github.axway-api-management-plus.apim-cli</groupId>
2828
<artifactId>apimcli-api-import</artifactId>
29-
<version>${project.version}</version>
30-
<scope>test</scope>
3129
</dependency>
3230
<dependency>
3331
<groupId>com.github.axway-api-management-plus.apim-cli</groupId>

modules/api-export/src/main/java/com/axway/apim/APIExportApp.java

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import com.axway.apim.api.API;
1111
import com.axway.apim.api.export.impl.APIResultHandler;
1212
import com.axway.apim.api.export.impl.APIResultHandler.APIListImpl;
13+
import com.axway.apim.api.export.lib.APIChangeParams;
1314
import com.axway.apim.api.export.lib.APIDeleteCLIOptions;
1415
import com.axway.apim.api.export.lib.APIExportGetCLIOptions;
1516
import com.axway.apim.api.export.lib.APIExportParams;
1617
import com.axway.apim.api.export.lib.APIUnpublishCLIOptions;
18+
import com.axway.apim.api.export.lib.ChangeAPICLIOptions;
1719
import com.axway.apim.cli.APIMCLIServiceProvider;
1820
import com.axway.apim.cli.CLIServiceMethod;
1921
import com.axway.apim.lib.errorHandling.AppException;
@@ -33,7 +35,7 @@ public class APIExportApp implements APIMCLIServiceProvider {
3335
private static ErrorState errorState = ErrorState.getInstance();
3436

3537
public static void main(String args[]) {
36-
int rc = export(args);
38+
int rc = change(args);
3739
System.exit(rc);
3840
}
3941

@@ -43,13 +45,13 @@ public static int export(String args[]) {
4345
APIExportParams params = new APIExportParams(new APIExportGetCLIOptions(args));
4446
switch(params.getOutputFormat()) {
4547
case console:
46-
return runExport(params, APIListImpl.CONSOLE_EXPORTER);
48+
return execute(params, APIListImpl.CONSOLE_EXPORTER);
4749
case json:
48-
return runExport(params, APIListImpl.JSON_EXPORTER);
50+
return execute(params, APIListImpl.JSON_EXPORTER);
4951
case csv:
50-
return runExport(params, APIListImpl.CSV_EXPORTER);
52+
return execute(params, APIListImpl.CSV_EXPORTER);
5153
default:
52-
return runExport(params, APIListImpl.CONSOLE_EXPORTER);
54+
return execute(params, APIListImpl.CONSOLE_EXPORTER);
5355
}
5456
} catch (AppException e) {
5557

@@ -71,7 +73,7 @@ public static int export(String args[]) {
7173
public static int delete(String args[]) {
7274
try {
7375
APIExportParams params = new APIExportParams(new APIDeleteCLIOptions(args));
74-
return runExport(params, APIListImpl.API_DELETE_HANDLER);
76+
return execute(params, APIListImpl.API_DELETE_HANDLER);
7577
} catch (Exception e) {
7678
LOG.error(e.getMessage(), e);
7779
return ErrorCode.UNXPECTED_ERROR.getCode();
@@ -82,14 +84,36 @@ public static int delete(String args[]) {
8284
public static int unpublish(String args[]) {
8385
try {
8486
APIExportParams params = new APIExportParams(new APIUnpublishCLIOptions(args));
85-
return runExport(params, APIListImpl.API_UNPUBLISH_HANDLER);
87+
return execute(params, APIListImpl.API_UNPUBLISH_HANDLER);
8688
} catch (Exception e) {
8789
LOG.error(e.getMessage(), e);
8890
return ErrorCode.UNXPECTED_ERROR.getCode();
8991
}
9092
}
9193

92-
private static int runExport(APIExportParams params, APIListImpl resultHandlerImpl) {
94+
@CLIServiceMethod(name = "publish", description = "Publish the selected APIs")
95+
public static int publish(String args[]) {
96+
try {
97+
APIExportParams params = new APIExportParams(new APIUnpublishCLIOptions(args));
98+
return execute(params, APIListImpl.API_PUBLISH_HANDLER);
99+
} catch (Exception e) {
100+
LOG.error(e.getMessage(), e);
101+
return ErrorCode.UNXPECTED_ERROR.getCode();
102+
}
103+
}
104+
105+
@CLIServiceMethod(name = "change", description = "Changes the selected APIs according to given parameters")
106+
public static int change(String args[]) {
107+
try {
108+
APIChangeParams params = new APIChangeParams(new ChangeAPICLIOptions(args));
109+
return execute(params, APIListImpl.API_CHANGE_HANDLER);
110+
} catch (Exception e) {
111+
LOG.error(e.getMessage(), e);
112+
return ErrorCode.UNXPECTED_ERROR.getCode();
113+
}
114+
}
115+
116+
private static int execute(APIExportParams params, APIListImpl resultHandlerImpl) {
93117
try {
94118
// We need to clean some Singleton-Instances, as tests are running in the same JVM
95119
APIManagerAdapter.deleteInstance();
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package com.axway.apim.api.export.impl;
2+
3+
import java.util.ArrayList;
4+
import java.util.Iterator;
5+
import java.util.List;
6+
7+
import com.axway.apim.adapter.APIManagerAdapter;
8+
import com.axway.apim.adapter.APIManagerAdapter.CUSTOM_PROP_TYPE;
9+
import com.axway.apim.adapter.apis.APIFilter;
10+
import com.axway.apim.adapter.apis.APIFilter.Builder.APIType;
11+
import com.axway.apim.api.API;
12+
import com.axway.apim.api.export.lib.APIChangeParams;
13+
import com.axway.apim.api.export.lib.APIExportParams;
14+
import com.axway.apim.api.model.ServiceProfile;
15+
import com.axway.apim.api.state.APIChangeState;
16+
import com.axway.apim.apiimport.APIImportManager;
17+
import com.axway.apim.lib.errorHandling.AppException;
18+
import com.axway.apim.lib.errorHandling.ErrorCode;
19+
import com.axway.apim.lib.utils.Utils;
20+
21+
public class APIChangeHandler extends APIResultHandler {
22+
23+
APIChangeParams changeParams;
24+
25+
public APIChangeHandler(APIExportParams params) {
26+
super(params);
27+
this.changeParams = (APIChangeParams)params;
28+
}
29+
30+
@Override
31+
public void execute(List<API> apis) throws AppException {
32+
APIManagerAdapter adapter = APIManagerAdapter.getInstance();
33+
List<APIChangeState> apisToChange = new ArrayList<APIChangeState>();
34+
LOG.info(apis.size() + " selected to change.");
35+
for(API api : apis) {
36+
try {
37+
if(changeParams.getNewBackend()!=null) {
38+
api = changeBackendBasePath(api, changeParams.getNewBackend(), changeParams.getOldBackend());
39+
}
40+
// Reload the actual API again, to get a clone
41+
API actualAPI = adapter.apiAdapter.getAPI(new APIFilter.Builder(APIType.ACTUAL_API).hasId(api.getId()).build(), false);
42+
APIChangeState changeState = new APIChangeState(actualAPI, api);
43+
if(!changeState.hasAnyChanges()) {
44+
LOG.warn("No changes for API: '"+api.getName()+"'");
45+
continue;
46+
}
47+
if(changeState.isBreaking() && !params.isForce()) {
48+
LOG.error("Changing API: '"+api.getName()+"' is a potentially breaking change which can't be applied without enforcing it! Try option: -force");
49+
continue;
50+
}
51+
LOG.info("Planned changes for API: '" + api.getName() + "': " + changeState.getAllChanges());
52+
apisToChange.add(changeState);
53+
} catch(Exception e) {
54+
LOG.error("Error preparing required changes for API: " + api.getName(), e);
55+
}
56+
}
57+
if(apisToChange.size()==0) {
58+
System.out.println("No changes required for the selected APIs.");
59+
return;
60+
}
61+
System.out.println("Okay, going to change: " + apisToChange.size() + " API(s)");
62+
if(Utils.askYesNo("Do you wish to proceed? (Y/N)")) {
63+
APIImportManager importManager = new APIImportManager();
64+
for(APIChangeState changeState : apisToChange) {
65+
LOG.info("Apply changes for API: '" + changeState.getDesiredAPI().getName() +"'");
66+
try {
67+
importManager.applyChanges(changeState);
68+
} catch(Exception e) {
69+
LOG.error("Error applying changes for API: " + changeState.getDesiredAPI().getName(), e);
70+
}
71+
}
72+
System.out.println("Done!");
73+
}
74+
}
75+
76+
@Override
77+
public APIFilter getFilter() {
78+
// We need to load the complete API, as this becomes the desired API
79+
// hence, all App, Orgs, Quotas, etc. must be taken over the new API
80+
return getBaseAPIFilterBuilder()
81+
.includeCustomProperties(APIManagerAdapter.getAllConfiguredCustomProperties(CUSTOM_PROP_TYPE.api))
82+
.includeOriginalAPIDefinition(true)
83+
.includeClientApplications(true)
84+
.includeClientAppQuota(true)
85+
.includeClientOrganizations(true)
86+
.includeQuotas(true)
87+
.build();
88+
}
89+
90+
private API changeBackendBasePath(API api, String newBackendBasepath, String oldBackendBasepath) throws AppException {
91+
if(oldBackendBasepath!=null) {
92+
String actualBackend = getActualBackendBasepath(api);
93+
if(!oldBackendBasepath.equals(actualBackend)) {
94+
LOG.warn("Backend of API: " + api.getName() + " wont be changed as it has a different backend configured. Current: '" + actualBackend + "' New: '"+oldBackendBasepath+"'");
95+
return api;
96+
}
97+
}
98+
Iterator<ServiceProfile> it = api.getServiceProfiles().values().iterator();
99+
while(it.hasNext()) {
100+
ServiceProfile profile = it.next();
101+
profile.setBasePath(newBackendBasepath);
102+
}
103+
return api;
104+
}
105+
106+
private String getActualBackendBasepath(API api) throws AppException {
107+
Iterator<ServiceProfile> it = api.getServiceProfiles().values().iterator();
108+
String lastBasepath = null;
109+
while(it.hasNext()) {
110+
ServiceProfile profile = it.next();
111+
if(lastBasepath!=null && !lastBasepath.equals(profile.getBasePath())) {
112+
throw new AppException("API has multiple backends configured. Please export - change - import the API to change it.", ErrorCode.UNSUPPORTED_FEATURE);
113+
}
114+
lastBasepath = profile.getBasePath();
115+
}
116+
return lastBasepath;
117+
}
118+
119+
}

modules/api-export/src/main/java/com/axway/apim/api/export/impl/APIResultHandler.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ public enum APIListImpl {
4343
CONSOLE_EXPORTER(ConsoleAPIExporter.class),
4444
CSV_EXPORTER(CSVAPIExporter.class),
4545
API_DELETE_HANDLER(DeleteAPIHandler.class),
46-
API_UNPUBLISH_HANDLER(UnpublishAPIHandler.class);
46+
API_PUBLISH_HANDLER(PublishAPIHandler.class),
47+
API_UNPUBLISH_HANDLER(UnpublishAPIHandler.class),
48+
API_CHANGE_HANDLER(APIChangeHandler.class);
4749

4850
private final Class<APIResultHandler> implClass;
4951

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.axway.apim.api.export.impl;
2+
3+
import java.util.List;
4+
5+
import com.axway.apim.adapter.APIStatusManager;
6+
import com.axway.apim.adapter.apis.APIFilter;
7+
import com.axway.apim.api.API;
8+
import com.axway.apim.api.export.lib.APIExportParams;
9+
import com.axway.apim.lib.errorHandling.AppException;
10+
11+
public class PublishAPIHandler extends APIResultHandler {
12+
13+
public PublishAPIHandler(APIExportParams params) {
14+
super(params);
15+
}
16+
17+
@Override
18+
public void execute(List<API> apis) throws AppException {
19+
APIStatusManager statusManager = new APIStatusManager();
20+
System.out.println("Going to publish: " + apis.size() + " API(s)");
21+
for(API api : apis) {
22+
try {
23+
statusManager.update(api, API.STATE_PUBLISHED, true);
24+
} catch(Exception e) {
25+
LOG.error("Error publishing API: " + api.getName());
26+
}
27+
}
28+
System.out.println("Done!");
29+
}
30+
31+
@Override
32+
public APIFilter getFilter() {
33+
return getBaseAPIFilterBuilder().build();
34+
}
35+
36+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.axway.apim.api.export.lib;
2+
3+
import com.axway.apim.lib.APIMCoreCLIOptions;
4+
import com.axway.apim.lib.CommandParameters;
5+
import com.axway.apim.lib.errorHandling.AppException;
6+
7+
public class APIChangeParams extends APIExportParams {
8+
9+
public APIChangeParams(APIMCoreCLIOptions parser) throws AppException {
10+
super(parser);
11+
}
12+
13+
public static synchronized APIChangeParams getInstance() {
14+
return (APIChangeParams)CommandParameters.getInstance();
15+
}
16+
17+
public String getNewBackend() {
18+
return getValue("newBackend");
19+
}
20+
21+
public String getOldBackend() {
22+
return getValue("oldBackend");
23+
}
24+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.axway.apim.api.export.lib;
2+
3+
import org.apache.commons.cli.CommandLine;
4+
import org.apache.commons.cli.ParseException;
5+
6+
public class APIPublishCLIOptions extends APIExportCLIOptions {
7+
8+
CommandLine cmd;
9+
10+
public APIPublishCLIOptions(String[] args) throws ParseException {
11+
super(args);
12+
}
13+
14+
@Override
15+
public void printUsage(String message, String[] args) {
16+
super.printUsage(message, args);
17+
System.out.println("----------------------------------------------------------------------------------------");
18+
System.out.println("How to publish APIs using different filter options:");
19+
System.out.println(getBinaryName()+" api publish -s api-env");
20+
System.out.println(getBinaryName()+" api publish -s api-env -n \"*API*\"");
21+
System.out.println(getBinaryName()+" api publish -s api-env -id f6106454-1651-430e-8a2f-e3514afad8ee");
22+
System.out.println(getBinaryName()+" api publish -s api-env -policy \"*Policy ABC*\"");
23+
System.out.println(getBinaryName()+" api publish -s api-env -name \"*API*\" -policy \"*Policy ABC*\"");
24+
System.out.println();
25+
System.out.println();
26+
System.out.println("For more information and advanced examples please visit:");
27+
System.out.println("https://github.com/Axway-API-Management-Plus/apim-cli/wiki");
28+
}
29+
30+
@Override
31+
protected String getAppName() {
32+
return "API-Export";
33+
}
34+
35+
36+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.axway.apim.api.export.lib;
2+
3+
import org.apache.commons.cli.CommandLine;
4+
import org.apache.commons.cli.Option;
5+
import org.apache.commons.cli.ParseException;
6+
7+
public class ChangeAPICLIOptions extends APIExportCLIOptions {
8+
9+
CommandLine cmd;
10+
11+
public ChangeAPICLIOptions(String[] args) throws ParseException {
12+
super(args);
13+
Option option = new Option("newBackend", true, "The new backend you would like to change to.");
14+
option.setRequired(false);
15+
option.setArgName("https://new.server.com:8080/api");
16+
options.addOption(option);
17+
18+
option = new Option("oldBackend", true, "If given, only APIs matching to this backend will be changed");
19+
option.setRequired(false);
20+
option.setArgName("https://old.server.com:8080/api");
21+
options.addOption(option);
22+
}
23+
24+
@Override
25+
public void printUsage(String message, String[] args) {
26+
super.printUsage(message, args);
27+
System.out.println("----------------------------------------------------------------------------------------");
28+
System.out.println("Changing APIs examples:");
29+
System.out.println();
30+
System.out.println("Changes the backend basepath of selected APIs from any to new");
31+
System.out.println(getBinaryName()+" api change -s api-env <FILTER-APIs> -newBackend https://new.backend.host:6756/api");
32+
System.out.println();
33+
System.out.println("Changes the backend basepath of select APIs having the given oldBackend");
34+
System.out.println(getBinaryName()+" api change -s api-env <FILTER-APIs> -newBackend https://new.backend.host:6756/api -oldBackend https://old.backend....");
35+
System.out.println();
36+
System.out.println("For more information and advanced examples please visit:");
37+
System.out.println("https://github.com/Axway-API-Management-Plus/apim-cli/wiki");
38+
}
39+
40+
@Override
41+
protected String getAppName() {
42+
return "Application-Export";
43+
}
44+
45+
46+
}

modules/api-import/src/main/java/com/axway/apim/apiimport/APIImportConfigAdapter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ private void handleAllOrganizations(API apiConfig) throws AppException {
322322

323323
private void addQuotaConfiguration(API apiConfig) throws AppException {
324324
if(apiConfig.getState()==API.STATE_UNPUBLISHED) return;
325-
DesiredAPI importAPI = (DesiredAPI)apiConfig;
325+
API importAPI = apiConfig;
326326
initQuota(importAPI.getSystemQuota());
327327
initQuota(importAPI.getApplicationQuota());
328328
}

0 commit comments

Comments
 (0)