diff --git a/src/main/java/cz/trask/migration/AbstractProcess.java b/src/main/java/cz/trask/migration/AbstractProcess.java index 18cf186..bcb86b5 100644 --- a/src/main/java/cz/trask/migration/AbstractProcess.java +++ b/src/main/java/cz/trask/migration/AbstractProcess.java @@ -35,8 +35,11 @@ public abstract class AbstractProcess { protected static final String PARAM_SOURCE_APIM = "source_apim"; protected static final String VERSION_32 = "v32"; - + public static final String PRIVATE_KEY_APIM_32 = "wso2apim32-pk.pem"; + + public static final String ARTIFACT_GROUP_SUBSCRIPTIONS = "SUBSCRIPTIONS"; + public static final String ARTIFACT_NAME_SUBSCRIPTIONS = "subs.yaml"; public static ObjectMapper mapper; public static ObjectMapper mapperYaml; diff --git a/src/main/java/cz/trask/migration/ApiSync.java b/src/main/java/cz/trask/migration/ApiSync.java index 7562233..e78854a 100644 --- a/src/main/java/cz/trask/migration/ApiSync.java +++ b/src/main/java/cz/trask/migration/ApiSync.java @@ -21,11 +21,11 @@ public class ApiSync { StartParameters sp = StartParameters.parse(commandLine); log.info("Parsed parameters: " + sp); - if (sp.getCommand().equals("import")) { + if (sp.getCommand().equalsIgnoreCase("wso2ToApicurio")) { log.info("Import command selected."); ImportToApicurio imp = new ImportToApicurio(); imp.process(); - } else if (sp.getCommand().equals("export")) { + } else if (sp.getCommand().equals("apicurioToWso2")) { log.info("Export command selected."); ExportToWso2FromV32 exp = new ExportToWso2FromV32(); exp.process(); diff --git a/src/main/java/cz/trask/migration/impl/v32/ImportToApicurio.java b/src/main/java/cz/trask/migration/impl/v32/ImportToApicurio.java index cd7e647..f4b8afe 100644 --- a/src/main/java/cz/trask/migration/impl/v32/ImportToApicurio.java +++ b/src/main/java/cz/trask/migration/impl/v32/ImportToApicurio.java @@ -25,6 +25,9 @@ import cz.trask.migration.model.FileType; import cz.trask.migration.model.HttpResponse; import cz.trask.migration.model.TokenResponse; import cz.trask.migration.model.ZipEntryData; +import cz.trask.migration.model.v32.Subscriptions; +import cz.trask.migration.model.v32.Subscriptions.ApplicationInfo; +import cz.trask.migration.model.v32.Subscriptions.Subscription; import io.apicurio.registry.rest.client.RegistryClient; import io.apicurio.registry.rest.client.RegistryClientFactory; import io.apicurio.registry.rest.client.exception.VersionAlreadyExistsException; @@ -105,8 +108,9 @@ public class ImportToApicurio extends AbstractProcess { "Bearer " + tokenResponse.getAccess_token()); // 1) Retrieve basic information - HttpResponse apiInfoResp = makeRequest("GET", config.getSource().getDevPortalApiUrl() + "/apis/" + api.getId(), - httpHeaders, Collections.emptyMap()); + HttpResponse apiInfoResp = makeRequest("GET", + config.getSource().getDevPortalApiUrl() + "/apis/" + api.getId(), httpHeaders, + Collections.emptyMap()); HttpResponse subsResp = makeRequest("GET", config.getSource().getPublisherApiUrl() + "/subscriptions?apiId=" + api.getId(), httpHeaders, @@ -131,7 +135,7 @@ public class ImportToApicurio extends AbstractProcess { // 3) Deserialize JSON responses Map apiMap = mapper.readValue(apiInfoResp.getResponse(), Map.class); - Map subsMap = mapper.readValue(subsResp.getResponse(), Map.class); + Subscriptions subs = mapper.readValue(subsResp.getResponse(), Subscriptions.class); @SuppressWarnings("unchecked") List tagsList = (List) apiMap.get("tags"); @@ -141,7 +145,7 @@ public class ImportToApicurio extends AbstractProcess { props.put("version", api.getVersion()); props.put("status", status); props.put(PARAM_SOURCE_APIM, VERSION_32); - addSubscriptionsToProps(props, subsMap); + addSubscriptionsToProps(props, subs); addEndpointsToProps(props, apiMap); addTagsToProps(props, tagsList); @@ -173,12 +177,13 @@ public class ImportToApicurio extends AbstractProcess { if (existingArtifacts == null) { // Create new artifact List references = createReferencesFromZip(zipEntries, group, api); + addSubscriptionsToReferences(references, subs, api); ArtifactMetaData meta = client.createArtifact(group, mainArtifactId, api.getVersion(), null, null, null, api.getName(), fullDesc, null, null, null, new ByteArrayInputStream(swaggerObj.toString().getBytes()), references); - setArtifactMetaData(meta, props, tagsList); + setArtifactMetaData(meta, props); // Create the three required rules createRule(meta, "NONE", RuleType.COMPATIBILITY); createRule(meta, "NONE", RuleType.VALIDITY); @@ -195,12 +200,13 @@ public class ImportToApicurio extends AbstractProcess { } List references = createReferencesFromZip(zipEntries, group, api); + addSubscriptionsToReferences(references, subs, api); if (!versionExists) { ArtifactMetaData meta = client.updateArtifact(group, mainArtifactId, api.getVersion(), api.getName(), fullDesc, new ByteArrayInputStream(swaggerObj.toString().getBytes()), references); - setArtifactMetaData(meta, props, tagsList); + setArtifactMetaData(meta, props); } else { // Version already exists – no action needed log.warn("API {} with version {} already exists. Skipping import.", api.getContext(), @@ -257,19 +263,15 @@ public class ImportToApicurio extends AbstractProcess { swagger.set("servers", servers); } - private void addSubscriptionsToProps(Map props, Map subsMap) { - if (subsMap == null || !subsMap.containsKey("list")) + private void addSubscriptionsToProps(Map props, Subscriptions subs) { + if (subs == null || subs.getList() == null || subs.getList().isEmpty()) return; - @SuppressWarnings("unchecked") - List> list = (List>) subsMap.get("list"); int i = 1; - for (Map sub : list) { - @SuppressWarnings("unchecked") - Map appInfo = (Map) sub.get("applicationInfo"); + for (Subscription sub : subs.getList()) { + ApplicationInfo appInfo = sub.getApplicationInfo(); if (appInfo == null) continue; - props.put("subscription" + i, - appInfo.getOrDefault("name", "") + " (Owner: " + appInfo.getOrDefault("subscriber", "") + ")"); + props.put("subscription" + i, appInfo.getName() + " (Owner: " + appInfo.getSubscriber() + ")"); i++; } } @@ -284,7 +286,10 @@ public class ImportToApicurio extends AbstractProcess { Map urls = (Map) env.get("URLs"); if (urls == null) continue; - urls.forEach((k, v) -> props.put(k + " Endpoint", v)); + urls.forEach((k, v) -> { + if (v != null) + props.put(k + " Endpoint", v); + }); } } @@ -306,7 +311,7 @@ public class ImportToApicurio extends AbstractProcess { api.getVersion(), is); Map props = new LinkedHashMap<>(); props.put(PARAM_SOURCE_APIM, VERSION_32); - setArtifactMetaData(meta, props, Collections.emptyList()); + setArtifactMetaData(meta, props); } ArtifactReference ref = new ArtifactReference(); @@ -319,14 +324,37 @@ public class ImportToApicurio extends AbstractProcess { return references; } - private void setArtifactMetaData(ArtifactMetaData meta, Map props, List tags) { + private void addSubscriptionsToReferences(List references, Subscriptions subs, APIInfo api) + throws Exception { + if (subs == null || subs.getList() == null || subs.getList().isEmpty()) + return; + + String artifactId = api.getName() + "/" + api.getVersion() + "/" + ARTIFACT_NAME_SUBSCRIPTIONS; + + byte[] subsBytes = mapperYaml.writeValueAsBytes(subs); + + try (ByteArrayInputStream is = new ByteArrayInputStream(subsBytes)) { + ArtifactMetaData meta = client.createArtifactWithVersion(ARTIFACT_GROUP_SUBSCRIPTIONS, artifactId, + api.getVersion(), is); + Map props = new LinkedHashMap<>(); + props.put(PARAM_SOURCE_APIM, VERSION_32); + setArtifactMetaData(meta, props); + } + + ArtifactReference ref = new ArtifactReference(); + ref.setName(ARTIFACT_NAME_SUBSCRIPTIONS); + ref.setGroupId(ARTIFACT_GROUP_SUBSCRIPTIONS); + ref.setArtifactId(artifactId); + ref.setVersion(api.getVersion()); + references.add(ref); + } + + private void setArtifactMetaData(ArtifactMetaData meta, Map props) { EditableMetaData metaData = new EditableMetaData(); metaData.setName(meta.getName()); metaData.setDescription(meta.getDescription()); if (props != null) metaData.setProperties(props); - if (tags != null) - metaData.setLabels(tags); client.updateArtifactMetaData(meta.getGroupId(), meta.getId(), metaData); } diff --git a/src/main/java/cz/trask/migration/model/FileType.java b/src/main/java/cz/trask/migration/model/FileType.java index 15d48e6..d57bbbc 100644 --- a/src/main/java/cz/trask/migration/model/FileType.java +++ b/src/main/java/cz/trask/migration/model/FileType.java @@ -1,5 +1,5 @@ package cz.trask.migration.model; public enum FileType { - APIDEF, OPENAPI, WSDL, POLICY_IN, POLICY_OUT, POLICY_FAULT, CERTIFICATE, UNKNOWN + APIDEF, OPENAPI, WSDL, POLICY_IN, POLICY_OUT, POLICY_FAULT, CERTIFICATE, SUBSCRIPTIONS, UNKNOWN } diff --git a/src/main/java/cz/trask/migration/model/v32/Subscriptions.java b/src/main/java/cz/trask/migration/model/v32/Subscriptions.java new file mode 100644 index 0000000..22e85e3 --- /dev/null +++ b/src/main/java/cz/trask/migration/model/v32/Subscriptions.java @@ -0,0 +1,31 @@ +package cz.trask.migration.model.v32; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class Subscriptions { + private List list; + + @Data + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Subscription { + private String subscriptionId; + private ApplicationInfo applicationInfo; + private String throttlingPolicy; + private String subscriptionStatus; + } + + @Data + @JsonIgnoreProperties(ignoreUnknown = true) + public static class ApplicationInfo { + private String applicationId; + private String name; + private String subscriber; + private String description; + private int subscriptionCount; + } +}