From c5aea4a8bc398fc1c6220875e55b9520fd7f7524 Mon Sep 17 00:00:00 2001 From: "mark.j.leonard" Date: Wed, 6 Jun 2018 14:47:42 +0100 Subject: Refactor for Sonar smells and code coverage Various code formatting and style fixes (to address Sonar code smells). Introduce a BabelServiceClientException to replace the use of the base Exception class. Make both the BabelServiceClient class and its Factory class use an interface, to allow for Spring injection (using annotations) and for simplified mocking. Refactor the Notification Publishing by making this the responsibility of the main Service classes and not the deployment manager. Issue-ID: AAI-1207 Change-Id: I6bf8a504fa7b98e9158c9976fd1d88c6c54027c1 Signed-off-by: mark.j.leonard --- .../aai/modelloader/ModelLoaderApplication.java | 37 ++++ .../aai/modelloader/config/ModelLoaderConfig.java | 69 ++++--- .../org/onap/aai/modelloader/entity/Artifact.java | 2 +- .../entity/catalog/VnfCatalogArtifact.java | 5 +- .../model/BabelArtifactParsingException.java | 11 +- .../modelloader/entity/model/ModelArtifact.java | 4 +- .../entity/model/ModelArtifactParser.java | 4 +- .../entity/model/NamedQueryArtifact.java | 8 +- .../notification/ArtifactDeploymentManager.java | 123 ----------- .../notification/ArtifactDownloadManager.java | 5 +- .../notification/CompDoneStatusMessageBuilder.java | 2 +- .../DistributionStatusMessageBuilder.java | 2 +- .../modelloader/notification/EventCallback.java | 41 +++- .../notification/NotificationDataImpl.java | 117 +++++++++++ .../notification/NotificationPublisher.java | 54 ++--- .../aai/modelloader/restclient/AaiRestClient.java | 6 +- .../modelloader/restclient/BabelServiceClient.java | 163 +-------------- .../restclient/BabelServiceClientException.java | 37 ++++ .../restclient/BabelServiceClientFactory.java | 38 ---- .../restclient/HttpsBabelServiceClient.java | 230 +++++++++++++++++++++ .../service/ArtifactDeploymentManager.java | 94 +++++++++ .../service/BabelServiceClientFactory.java | 30 +++ .../service/HttpsBabelServiceClientFactory.java | 56 +++++ .../service/ModelLoaderApplication.java | 37 ---- .../modelloader/service/ModelLoaderInterface.java | 8 +- .../modelloader/service/ModelLoaderService.java | 118 ++++++----- .../modelloader/service/NotificationDataImpl.java | 117 ----------- .../aai/modelloader/service/SdcConnectionJob.java | 40 ++-- .../aai/modelloader/util/JsonXmlConverter.java | 151 +++++++------- 29 files changed, 901 insertions(+), 708 deletions(-) create mode 100644 src/main/java/org/onap/aai/modelloader/ModelLoaderApplication.java delete mode 100644 src/main/java/org/onap/aai/modelloader/notification/ArtifactDeploymentManager.java create mode 100644 src/main/java/org/onap/aai/modelloader/notification/NotificationDataImpl.java create mode 100644 src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClientException.java delete mode 100644 src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClientFactory.java create mode 100644 src/main/java/org/onap/aai/modelloader/restclient/HttpsBabelServiceClient.java create mode 100644 src/main/java/org/onap/aai/modelloader/service/ArtifactDeploymentManager.java create mode 100644 src/main/java/org/onap/aai/modelloader/service/BabelServiceClientFactory.java create mode 100644 src/main/java/org/onap/aai/modelloader/service/HttpsBabelServiceClientFactory.java delete mode 100644 src/main/java/org/onap/aai/modelloader/service/ModelLoaderApplication.java delete mode 100644 src/main/java/org/onap/aai/modelloader/service/NotificationDataImpl.java (limited to 'src/main') diff --git a/src/main/java/org/onap/aai/modelloader/ModelLoaderApplication.java b/src/main/java/org/onap/aai/modelloader/ModelLoaderApplication.java new file mode 100644 index 0000000..66c44a3 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/ModelLoaderApplication.java @@ -0,0 +1,37 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.modelloader; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Model Loader Spring Boot Application. + */ + +@SpringBootApplication +public class ModelLoaderApplication { + + public static void main(String[] args) { + SpringApplication.run(ModelLoaderApplication.class, args); + } + +} diff --git a/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java b/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java index 3f03bb5..0a2bc85 100644 --- a/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java +++ b/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java @@ -1,5 +1,5 @@ /** - * ============LICENSE_START======================================================= + * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. @@ -43,30 +43,33 @@ public class ModelLoaderConfig implements IConfiguration { private static final String SUFFIX_KEYSTORE_FILE = "KEYSTORE_FILE"; private static final String SUFFIX_KEYSTORE_PASS = "KEYSTORE_PASSWORD"; + private static final String SUFFIX_TRUSTSTORE_FILE = "TRUSTSTORE_FILE"; + private static final String SUFFIX_TRUSTSTORE_PASS = "TRUSTSTORE_PASSWORD"; + // Configuration file properties - protected static final String PROP_ML_DISTRIBUTION_ACTIVE_SERVER_TLS_AUTH = - PREFIX_DISTRIBUTION_CLIENT + "ACTIVE_SERVER_TLS_AUTH"; - protected static final String PROP_ML_DISTRIBUTION_ASDC_CONNECTION_DISABLED = - PREFIX_DISTRIBUTION_CLIENT + "ASDC_CONNECTION_DISABLE"; + protected static final String PROP_ML_DISTRIBUTION_ACTIVE_SERVER_TLS_AUTH = PREFIX_DISTRIBUTION_CLIENT + + "ACTIVE_SERVER_TLS_AUTH"; + protected static final String PROP_ML_DISTRIBUTION_ASDC_CONNECTION_DISABLED = PREFIX_DISTRIBUTION_CLIENT + + "ASDC_CONNECTION_DISABLE"; protected static final String PROP_ML_DISTRIBUTION_ASDC_ADDRESS = PREFIX_DISTRIBUTION_CLIENT + "ASDC_ADDRESS"; protected static final String PROP_ML_DISTRIBUTION_CONSUMER_GROUP = PREFIX_DISTRIBUTION_CLIENT + "CONSUMER_GROUP"; protected static final String PROP_ML_DISTRIBUTION_CONSUMER_ID = PREFIX_DISTRIBUTION_CLIENT + "CONSUMER_ID"; - protected static final String PROP_ML_DISTRIBUTION_ENVIRONMENT_NAME = - PREFIX_DISTRIBUTION_CLIENT + "ENVIRONMENT_NAME"; - protected static final String PROP_ML_DISTRIBUTION_KEYSTORE_PASSWORD = - PREFIX_DISTRIBUTION_CLIENT + SUFFIX_KEYSTORE_PASS; - protected static final String PROP_ML_DISTRIBUTION_KEYSTORE_FILE = - PREFIX_DISTRIBUTION_CLIENT + SUFFIX_KEYSTORE_FILE; + protected static final String PROP_ML_DISTRIBUTION_ENVIRONMENT_NAME = PREFIX_DISTRIBUTION_CLIENT + + "ENVIRONMENT_NAME"; + protected static final String PROP_ML_DISTRIBUTION_KEYSTORE_PASSWORD = PREFIX_DISTRIBUTION_CLIENT + + SUFFIX_KEYSTORE_PASS; + protected static final String PROP_ML_DISTRIBUTION_KEYSTORE_FILE = PREFIX_DISTRIBUTION_CLIENT + + SUFFIX_KEYSTORE_FILE; protected static final String PROP_ML_DISTRIBUTION_PASSWORD = PREFIX_DISTRIBUTION_CLIENT + "PASSWORD"; - protected static final String PROP_ML_DISTRIBUTION_POLLING_INTERVAL = - PREFIX_DISTRIBUTION_CLIENT + "POLLING_INTERVAL"; + protected static final String PROP_ML_DISTRIBUTION_POLLING_INTERVAL = PREFIX_DISTRIBUTION_CLIENT + + "POLLING_INTERVAL"; protected static final String PROP_ML_DISTRIBUTION_POLLING_TIMEOUT = PREFIX_DISTRIBUTION_CLIENT + "POLLING_TIMEOUT"; protected static final String PROP_ML_DISTRIBUTION_USER = PREFIX_DISTRIBUTION_CLIENT + "USER"; protected static final String PROP_ML_DISTRIBUTION_ARTIFACT_TYPES = PREFIX_DISTRIBUTION_CLIENT + "ARTIFACT_TYPES"; - protected static final String PROP_ML_DISTRIBUTION_MSG_BUS_ADDRESSES = - PREFIX_DISTRIBUTION_CLIENT + "MSG_BUS_ADDRESSES"; - protected static final String PROP_ML_DISTRIBUTION_HTTPS_WITH_DMAAP = - PREFIX_DISTRIBUTION_CLIENT + "USE_HTTPS_WITH_DMAAP"; + protected static final String PROP_ML_DISTRIBUTION_MSG_BUS_ADDRESSES = PREFIX_DISTRIBUTION_CLIENT + + "MSG_BUS_ADDRESSES"; + protected static final String PROP_ML_DISTRIBUTION_HTTPS_WITH_DMAAP = PREFIX_DISTRIBUTION_CLIENT + + "USE_HTTPS_WITH_DMAAP"; protected static final String PROP_AAI_BASE_URL = PREFIX_AAI + "BASE_URL"; protected static final String PROP_AAI_KEYSTORE_FILE = PREFIX_AAI + SUFFIX_KEYSTORE_FILE; @@ -80,6 +83,8 @@ public class ModelLoaderConfig implements IConfiguration { protected static final String PROP_BABEL_BASE_URL = PREFIX_BABEL + "BASE_URL"; protected static final String PROP_BABEL_KEYSTORE_FILE = PREFIX_BABEL + SUFFIX_KEYSTORE_FILE; protected static final String PROP_BABEL_KEYSTORE_PASSWORD = PREFIX_BABEL + SUFFIX_KEYSTORE_PASS; + protected static final String PROP_BABEL_TRUSTSTORE_FILE = PREFIX_BABEL + SUFFIX_TRUSTSTORE_FILE; + protected static final String PROP_BABEL_TRUSTSTORE_PASSWORD = PREFIX_BABEL + SUFFIX_TRUSTSTORE_PASS; protected static final String PROP_BABEL_GENERATE_RESOURCE_URL = PREFIX_BABEL + "GENERATE_ARTIFACTS_URL"; protected static final String PROP_DEBUG_INGEST_SIMULATOR = PREFIX_DEBUG + "INGEST_SIMULATOR"; @@ -95,8 +100,8 @@ public class ModelLoaderConfig implements IConfiguration { private String modelVersion = null; - protected static final String FILESEP = - (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator"); + protected static final String FILESEP = (System.getProperty("file.separator") == null) ? "/" + : System.getProperty("file.separator"); public static void setConfigHome(String configHome) { ModelLoaderConfig.configHome = configHome; @@ -113,8 +118,10 @@ public class ModelLoaderConfig implements IConfiguration { /** * Original constructor * - * @param modelLoaderProperties properties needed to be configured for the model loader - * @param certLocation location of the certificate + * @param modelLoaderProperties + * properties needed to be configured for the model loader + * @param certLocation + * location of the certificate */ public ModelLoaderConfig(Properties modelLoaderProperties, String certLocation) { this.modelLoaderProperties = modelLoaderProperties; @@ -139,11 +146,10 @@ public class ModelLoaderConfig implements IConfiguration { } } - @Override public boolean activateServerTLSAuth() { String value = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ACTIVE_SERVER_TLS_AUTH); - return value == null ? false : Boolean.parseBoolean(value); + return value != null && Boolean.parseBoolean(value); } @Override @@ -209,7 +215,7 @@ public class ModelLoaderConfig implements IConfiguration { @Override public Boolean isUseHttpsWithDmaap() { String useHTTPS = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_HTTPS_WITH_DMAAP); - return useHTTPS == null ? false : Boolean.valueOf(useHTTPS); + return useHTTPS != null && Boolean.valueOf(useHTTPS); } @Override @@ -227,7 +233,7 @@ public class ModelLoaderConfig implements IConfiguration { return null; } else { return certLocation + File.separator + filename; - } + } } public String getAaiKeyStorePassword() { @@ -238,6 +244,19 @@ public class ModelLoaderConfig implements IConfiguration { return Password.deobfuscate(modelLoaderProperties.getProperty(PROP_BABEL_KEYSTORE_PASSWORD)); } + public String getBabelTrustStorePath() { + String filename = modelLoaderProperties.getProperty(PROP_BABEL_TRUSTSTORE_FILE); + if (filename == null) { + return null; + } else { + return certLocation + File.separator + filename; + } + } + + public String getBabelTrustStorePassword() { + return Password.deobfuscate(modelLoaderProperties.getProperty(PROP_BABEL_TRUSTSTORE_PASSWORD)); + } + public String getAaiBaseUrl() { return modelLoaderProperties.getProperty(PROP_AAI_BASE_URL); } diff --git a/src/main/java/org/onap/aai/modelloader/entity/Artifact.java b/src/main/java/org/onap/aai/modelloader/entity/Artifact.java index f576e24..f87535f 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/Artifact.java +++ b/src/main/java/org/onap/aai/modelloader/entity/Artifact.java @@ -20,7 +20,7 @@ */ package org.onap.aai.modelloader.entity; -public abstract class Artifact { +public class Artifact { private String payload; private ArtifactType type; diff --git a/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifact.java b/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifact.java index a8f4e60..9a84cf2 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifact.java +++ b/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifact.java @@ -26,7 +26,10 @@ import org.onap.aai.modelloader.entity.ArtifactType; public class VnfCatalogArtifact extends Artifact { public VnfCatalogArtifact(String payload) { - super(ArtifactType.VNF_CATALOG); + this(ArtifactType.VNF_CATALOG, payload); + } + public VnfCatalogArtifact(ArtifactType artifactType, String payload) { + super(artifactType); setPayload(payload); } } diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/BabelArtifactParsingException.java b/src/main/java/org/onap/aai/modelloader/entity/model/BabelArtifactParsingException.java index a3f14ba..dfb649c 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/model/BabelArtifactParsingException.java +++ b/src/main/java/org/onap/aai/modelloader/entity/model/BabelArtifactParsingException.java @@ -1,5 +1,5 @@ /** - * ============LICENSE_START======================================================= + * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. @@ -36,13 +36,4 @@ public class BabelArtifactParsingException extends Exception { super(message); } - /** - * Constructor for an instance of this exception with a message and actual exception encountered. - * - * @param message information about the exception - * @param cause the actual exception that was encountered - */ - public BabelArtifactParsingException(String message, Throwable cause) { - super(message, cause); - } } diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifact.java b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifact.java index 154cda1..705ceb5 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifact.java +++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifact.java @@ -209,7 +209,7 @@ public class ModelArtifact extends AbstractModelArtifact { String subURL = config.getAaiModelUrl(getModelNamespaceVersion()).trim(); String instance = getModelInvariantId(); - if ((!baseURL.endsWith("/")) && (!subURL.startsWith("/"))) { + if (!baseURL.endsWith("/") && !subURL.startsWith("/")) { baseURL = baseURL + "/"; } @@ -230,7 +230,7 @@ public class ModelArtifact extends AbstractModelArtifact { + AAI_MODEL_VER_SUB_URL; String instance = getModelVerId(); - if ((!baseURL.endsWith("/")) && (!subURL.startsWith("/"))) { + if (!baseURL.endsWith("/") && !subURL.startsWith("/")) { baseURL = baseURL + "/"; } diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactParser.java b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactParser.java index e687be0..adab6df 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactParser.java +++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactParser.java @@ -54,8 +54,8 @@ public class ModelArtifactParser extends AbstractModelArtifactParser { } else { if (node.getNodeName().equalsIgnoreCase(MODEL_VER)) { ((ModelArtifact) model).setModelVer(node); - if ((((ModelArtifact) model).getModelNamespace() != null) - && (!((ModelArtifact) model).getModelNamespace().isEmpty())) { + if (((ModelArtifact) model).getModelNamespace() != null + && !((ModelArtifact) model).getModelNamespace().isEmpty()) { Element e = (Element) node; e.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns", ((ModelArtifact) model).getModelNamespace()); diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifact.java b/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifact.java index 4df9879..a8fdc8e 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifact.java +++ b/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifact.java @@ -1,5 +1,5 @@ /** - * ============LICENSE_START======================================================= + * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. @@ -60,11 +60,11 @@ public class NamedQueryArtifact extends AbstractModelArtifact { List completedArtifacts) { OperationResult getResponse = aaiClient.getResource(getNamedQueryUrl(config), distId, MediaType.APPLICATION_XML_TYPE); - if ((getResponse == null) || (getResponse.getResultCode() != Response.Status.OK.getStatusCode())) { + if (getResponse == null || getResponse.getResultCode() != Response.Status.OK.getStatusCode()) { // Only attempt the PUT if the model doesn't already exist OperationResult putResponse = aaiClient.putResource(getNamedQueryUrl(config), getPayload(), distId, MediaType.APPLICATION_XML_TYPE); - if ((putResponse != null) && (putResponse.getResultCode() == Response.Status.CREATED.getStatusCode())) { + if (putResponse != null && putResponse.getResultCode() == Response.Status.CREATED.getStatusCode()) { completedArtifacts.add(this); logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getUniqueIdentifier() + " successfully ingested."); @@ -92,7 +92,7 @@ public class NamedQueryArtifact extends AbstractModelArtifact { String subURL = config.getAaiNamedQueryUrl(getModelNamespaceVersion()).trim(); String instance = this.getNamedQueryUuid(); - if ((!baseURL.endsWith("/")) && (!subURL.startsWith("/"))) { + if (!baseURL.endsWith("/") && !subURL.startsWith("/")) { baseURL = baseURL + "/"; } diff --git a/src/main/java/org/onap/aai/modelloader/notification/ArtifactDeploymentManager.java b/src/main/java/org/onap/aai/modelloader/notification/ArtifactDeploymentManager.java deleted file mode 100644 index ca17261..0000000 --- a/src/main/java/org/onap/aai/modelloader/notification/ArtifactDeploymentManager.java +++ /dev/null @@ -1,123 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aai.modelloader.notification; - -import java.util.ArrayList; -import java.util.List; -import org.onap.aai.modelloader.config.ModelLoaderConfig; -import org.onap.aai.modelloader.entity.Artifact; -import org.onap.aai.modelloader.entity.catalog.VnfCatalogArtifactHandler; -import org.onap.aai.modelloader.entity.model.ModelArtifactHandler; -import org.onap.aai.modelloader.restclient.AaiRestClient; -import org.onap.sdc.api.IDistributionClient; -import org.onap.sdc.api.notification.IArtifactInfo; -import org.onap.sdc.api.notification.INotificationData; - -/** - * This class is responsible for deploying model and catalog artifacts. - */ -public class ArtifactDeploymentManager { - - private IDistributionClient client; - private ModelLoaderConfig config; - private ModelArtifactHandler modelArtifactHandler; - private VnfCatalogArtifactHandler vnfCatalogArtifactHandler; - private NotificationPublisher notificationPublisher; - - public ArtifactDeploymentManager(IDistributionClient client, ModelLoaderConfig config) { - this.client = client; - this.config = config; - } - - /** - * Deploys model and catalog artifacts to A&AI - * - * @param data data about the notification that is being processed - * @param artifacts the specific artifacts found in the data. - * @param modelArtifacts collection of artifacts that represent yml files found in a TOSCA_CSAR file that have been - * converted to XML and also those for model query specs - * @param catalogArtifacts collection of artifacts that represent vnf catalog files - * @return boolean true if all deployments were successful otherwise false - */ - public boolean deploy(final INotificationData data, final List artifacts, - final List modelArtifacts, final List catalogArtifacts) { - - AaiRestClient aaiClient = new AaiRestClient(config); - String distributionId = data.getDistributionID(); - - List completedArtifacts = new ArrayList<>(); - boolean deploySuccess = - getModelArtifactHandler().pushArtifacts(modelArtifacts, distributionId, completedArtifacts, aaiClient); - - if (!deploySuccess) { - getModelArtifactHandler().rollback(completedArtifacts, distributionId, aaiClient); - } else { - List completedImageData = new ArrayList<>(); - deploySuccess = getVnfCatalogArtifactHandler().pushArtifacts(catalogArtifacts, distributionId, - completedImageData, aaiClient); - if (!deploySuccess) { - getModelArtifactHandler().rollback(completedArtifacts, distributionId, aaiClient); - getVnfCatalogArtifactHandler().rollback(completedImageData, distributionId, aaiClient); - } - } - - publishNotifications(data, "TOSCA_CSAR", artifacts, deploySuccess); - - return deploySuccess; - } - - private void publishNotifications(INotificationData data, String filterType, List artifacts, - boolean deploymentSuccess) { - if (deploymentSuccess) { - artifacts.stream().filter(a -> filterType.equalsIgnoreCase(a.getArtifactType())) - .forEach(a -> getNotificationPublisher().publishDeploySuccess(client, data, a)); - getNotificationPublisher().publishComponentSuccess(client, data); - } else { - artifacts.stream().filter(a -> filterType.equalsIgnoreCase(a.getArtifactType())) - .forEach(a -> getNotificationPublisher().publishDeployFailure(client, data, a)); - getNotificationPublisher().publishComponentFailure(client, data, "deploy failure"); - } - } - - private ModelArtifactHandler getModelArtifactHandler() { - if (modelArtifactHandler == null) { - modelArtifactHandler = new ModelArtifactHandler(config); - } - - return modelArtifactHandler; - } - - private NotificationPublisher getNotificationPublisher() { - if (notificationPublisher == null) { - notificationPublisher = new NotificationPublisher(); - } - - return notificationPublisher; - } - - private VnfCatalogArtifactHandler getVnfCatalogArtifactHandler() { - if (vnfCatalogArtifactHandler == null) { - this.vnfCatalogArtifactHandler = new VnfCatalogArtifactHandler(config); - } - - return vnfCatalogArtifactHandler; - } -} diff --git a/src/main/java/org/onap/aai/modelloader/notification/ArtifactDownloadManager.java b/src/main/java/org/onap/aai/modelloader/notification/ArtifactDownloadManager.java index 9dbe397..febc99a 100644 --- a/src/main/java/org/onap/aai/modelloader/notification/ArtifactDownloadManager.java +++ b/src/main/java/org/onap/aai/modelloader/notification/ArtifactDownloadManager.java @@ -39,7 +39,8 @@ import org.onap.aai.modelloader.entity.model.IModelParser; import org.onap.aai.modelloader.entity.model.NamedQueryArtifactParser; import org.onap.aai.modelloader.extraction.InvalidArchiveException; import org.onap.aai.modelloader.restclient.BabelServiceClient; -import org.onap.aai.modelloader.restclient.BabelServiceClientFactory; +import org.onap.aai.modelloader.restclient.BabelServiceClientException; +import org.onap.aai.modelloader.service.BabelServiceClientFactory; import org.onap.aai.modelloader.service.ModelLoaderMsgs; import org.onap.sdc.api.IDistributionClient; import org.onap.sdc.api.notification.IArtifactInfo; @@ -202,7 +203,7 @@ public class ArtifactDownloadManager { try { logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Creating Babel client"); babelClient = clientFactory.create(config); - } catch (Exception e) { + } catch (BabelServiceClientException e) { logger.error(ModelLoaderMsgs.BABEL_REST_REQUEST_ERROR, e, "POST", config.getBabelBaseUrl(), "Error posting artifact " + artifact.getArtifactName() + " " + serviceVersion + " to Babel: " + e.getLocalizedMessage()); diff --git a/src/main/java/org/onap/aai/modelloader/notification/CompDoneStatusMessageBuilder.java b/src/main/java/org/onap/aai/modelloader/notification/CompDoneStatusMessageBuilder.java index c389945..f198fa8 100644 --- a/src/main/java/org/onap/aai/modelloader/notification/CompDoneStatusMessageBuilder.java +++ b/src/main/java/org/onap/aai/modelloader/notification/CompDoneStatusMessageBuilder.java @@ -28,7 +28,7 @@ import org.onap.sdc.utils.DistributionStatusEnum; /** * This class is responsible for building an instance of {@link DistributionStatusMsg}. */ -public class CompDoneStatusMessageBuilder { +public final class CompDoneStatusMessageBuilder { private CompDoneStatusMessageBuilder() {} diff --git a/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMessageBuilder.java b/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMessageBuilder.java index 91cd3de..d799da0 100644 --- a/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMessageBuilder.java +++ b/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMessageBuilder.java @@ -29,7 +29,7 @@ import org.onap.sdc.utils.DistributionStatusEnum; /** * This class is responsible for building an instance of {@link DistributionStatusMsg}. */ -public class DistributionStatusMessageBuilder { +public final class DistributionStatusMessageBuilder { private DistributionStatusMessageBuilder() {} diff --git a/src/main/java/org/onap/aai/modelloader/notification/EventCallback.java b/src/main/java/org/onap/aai/modelloader/notification/EventCallback.java index 2baa217..42f72ce 100644 --- a/src/main/java/org/onap/aai/modelloader/notification/EventCallback.java +++ b/src/main/java/org/onap/aai/modelloader/notification/EventCallback.java @@ -1,5 +1,5 @@ /** - * ============LICENSE_START======================================================= + * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. @@ -28,13 +28,15 @@ import org.onap.aai.cl.mdc.MdcContext; import org.onap.aai.modelloader.config.ModelLoaderConfig; import org.onap.aai.modelloader.entity.Artifact; import org.onap.aai.modelloader.extraction.ArtifactInfoExtractor; -import org.onap.aai.modelloader.restclient.BabelServiceClientFactory; +import org.onap.aai.modelloader.service.ArtifactDeploymentManager; +import org.onap.aai.modelloader.service.BabelServiceClientFactory; import org.onap.aai.modelloader.service.ModelLoaderMsgs; import org.onap.sdc.api.IDistributionClient; import org.onap.sdc.api.consumer.INotificationCallback; import org.onap.sdc.api.notification.IArtifactInfo; import org.onap.sdc.api.notification.INotificationData; import org.slf4j.MDC; +import org.springframework.beans.factory.annotation.Autowired; public class EventCallback implements INotificationCallback { private static Logger logger = LoggerFactory.getInstance().getLogger(EventCallback.class.getName()); @@ -42,8 +44,11 @@ public class EventCallback implements INotificationCallback { private ArtifactDeploymentManager artifactDeploymentManager; private ArtifactDownloadManager artifactDownloadManager; + private NotificationPublisher notificationPublisher; private IDistributionClient client; private ModelLoaderConfig config; + @Autowired + private BabelServiceClientFactory babelServiceClientFactory; public EventCallback(IDistributionClient client, ModelLoaderConfig config) { this.client = client; @@ -63,18 +68,35 @@ public class EventCallback implements INotificationCallback { getArtifactDownloadManager().downloadArtifacts(data, artifacts, modelArtifacts, catalogArtifacts); if (success) { - success = getArtifactDeploymentManager().deploy(data, artifacts, modelArtifacts, catalogArtifacts); + success = getArtifactDeploymentManager().deploy(data, modelArtifacts, catalogArtifacts); } String statusString = success ? "SUCCESS" : "FAILURE"; auditLogger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Processed distribution " + data.getDistributionID() + " (" + statusString + ")"); + + publishNotifications(data, "TOSCA_CSAR", artifacts, success); + MDC.clear(); } + + private void publishNotifications(INotificationData data, String filterType, List artifacts, + boolean deploymentSuccess) { + if (deploymentSuccess) { + artifacts.stream().filter(a -> filterType.equalsIgnoreCase(a.getArtifactType())) + .forEach(a -> getNotificationPublisher().publishDeploySuccess(client, data, a)); + getNotificationPublisher().publishComponentSuccess(client, data); + } else { + artifacts.stream().filter(a -> filterType.equalsIgnoreCase(a.getArtifactType())) + .forEach(a -> getNotificationPublisher().publishDeployFailure(client, data, a)); + getNotificationPublisher().publishComponentFailure(client, data, "deploy failure"); + } + } + private ArtifactDeploymentManager getArtifactDeploymentManager() { if (artifactDeploymentManager == null) { - artifactDeploymentManager = new ArtifactDeploymentManager(client, config); + artifactDeploymentManager = new ArtifactDeploymentManager(config); } return artifactDeploymentManager; @@ -82,9 +104,18 @@ public class EventCallback implements INotificationCallback { private ArtifactDownloadManager getArtifactDownloadManager() { if (artifactDownloadManager == null) { - artifactDownloadManager = new ArtifactDownloadManager(client, config, new BabelServiceClientFactory()); + artifactDownloadManager = new ArtifactDownloadManager(client, config, babelServiceClientFactory); } return artifactDownloadManager; } + + + private NotificationPublisher getNotificationPublisher() { + if (notificationPublisher == null) { + notificationPublisher = new NotificationPublisher(); + } + + return notificationPublisher; + } } diff --git a/src/main/java/org/onap/aai/modelloader/notification/NotificationDataImpl.java b/src/main/java/org/onap/aai/modelloader/notification/NotificationDataImpl.java new file mode 100644 index 0000000..566415e --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/notification/NotificationDataImpl.java @@ -0,0 +1,117 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.modelloader.notification; + +import java.util.Collections; +import java.util.List; +import org.onap.sdc.api.notification.IArtifactInfo; +import org.onap.sdc.api.notification.INotificationData; +import org.onap.sdc.api.notification.IResourceInstance; + +public class NotificationDataImpl implements INotificationData { + + private String distributionID; + + @Override + public IArtifactInfo getArtifactMetadataByUUID(String arg0) { + return null; + } + + @Override + public String getDistributionID() { + return distributionID; + } + + public void setDistributionID(String distributionID) { + this.distributionID = distributionID; + } + + @Override + public List getResources() { + return Collections.emptyList(); + } + + @Override + public List getServiceArtifacts() { + return Collections.emptyList(); + } + + @Override + public String getServiceDescription() { + return null; + } + + @Override + public String getServiceInvariantUUID() { + return null; + } + + @Override + public String getServiceName() { + return null; + } + + @Override + public String getServiceUUID() { + return null; + } + + @Override + public String getServiceVersion() { + return null; + } + + @Override + public String getWorkloadContext() { + return null; + } + + @Override + public void setWorkloadContext(String arg0) { + // Unsupported method - not expected to be called + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((distributionID == null) ? 0 : distributionID.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + NotificationDataImpl other = (NotificationDataImpl) obj; + if (distributionID == null) { + if (other.distributionID != null) + return false; + } else if (!distributionID.equals(other.distributionID)) + return false; + return true; + } + +} diff --git a/src/main/java/org/onap/aai/modelloader/notification/NotificationPublisher.java b/src/main/java/org/onap/aai/modelloader/notification/NotificationPublisher.java index 967a290..626399e 100644 --- a/src/main/java/org/onap/aai/modelloader/notification/NotificationPublisher.java +++ b/src/main/java/org/onap/aai/modelloader/notification/NotificationPublisher.java @@ -1,5 +1,5 @@ /** - * ============LICENSE_START======================================================= + * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. @@ -20,8 +20,9 @@ */ package org.onap.aai.modelloader.notification; -import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.Properties; @@ -41,7 +42,7 @@ import org.onap.sdc.utils.DistributionStatusEnum; /** * This class is responsible for publishing the status of actions performed working with artifacts. */ -class NotificationPublisher { +public class NotificationPublisher { private static Logger logger = LoggerFactory.getInstance().getLogger(NotificationPublisher.class); private static Logger metricsLogger = LoggerFactory.getInstance().getMetricsLogger(NotificationPublisher.class); @@ -51,7 +52,7 @@ class NotificationPublisher { public NotificationPublisher() { Properties configProperties = new Properties(); try { - configProperties.load(new FileInputStream(ModelLoaderConfig.propertiesFile())); + configProperties.load(Files.newInputStream(Paths.get(ModelLoaderConfig.propertiesFile()))); } catch (IOException e) { String errorMsg = "Failed to load configuration: " + e.getMessage(); logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, e, errorMsg); @@ -141,28 +142,10 @@ class NotificationPublisher { * @param data data about the notification that resulted in this message being created * @param artifact the specific artifact to have its deployment status reported on */ - void publishDeployFailure(IDistributionClient client, INotificationData data, IArtifactInfo artifact) { + public void publishDeployFailure(IDistributionClient client, INotificationData data, IArtifactInfo artifact) { publishDeployStatus(client, data, artifact, DistributionStatusEnum.DEPLOY_ERROR, "failure"); } - private void publishDeployStatus(IDistributionClient client, INotificationData data, IArtifactInfo artifact, - DistributionStatusEnum distributionStatusEnum, String result) { - if (publishingEnabled) { - MdcOverride override = initMDCStartTime(); - - IDistributionClientResult sendStatus = client.sendDeploymentStatus( - DistributionStatusMessageBuilder.build(client, data, artifact, distributionStatusEnum)); - metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "deploy " + result, - artifact.getArtifactName(), sendStatus.getDistributionActionResult().toString()); - - if (sendStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, - "Failed to publish deploy " + result + " status: " + sendStatus.getDistributionMessageResult()); - } - } else { - logPublishingDisabled(distributionStatusEnum.toString(), result); - } - } /** * This method is responsible for publishing notification that the deployment of an artifact was succesful. @@ -171,11 +154,11 @@ class NotificationPublisher { * @param data data about the notification that resulted in this message being created * @param artifact the specific artifact to have its deployment status reported on */ - void publishDeploySuccess(IDistributionClient client, INotificationData data, IArtifactInfo artifact) { + public void publishDeploySuccess(IDistributionClient client, INotificationData data, IArtifactInfo artifact) { publishDeployStatus(client, data, artifact, DistributionStatusEnum.DEPLOY_OK, "success"); } - void publishComponentSuccess(IDistributionClient client, INotificationData data) { + public void publishComponentSuccess(IDistributionClient client, INotificationData data) { if (publishingEnabled) { MdcOverride override = initMDCStartTime(); @@ -194,7 +177,7 @@ class NotificationPublisher { } } - void publishComponentFailure(IDistributionClient client, INotificationData data, String errorReason) { + public void publishComponentFailure(IDistributionClient client, INotificationData data, String errorReason) { if (publishingEnabled) { MdcOverride override = initMDCStartTime(); @@ -214,6 +197,25 @@ class NotificationPublisher { } } + private void publishDeployStatus(IDistributionClient client, INotificationData data, IArtifactInfo artifact, + DistributionStatusEnum distributionStatusEnum, String result) { + if (publishingEnabled) { + MdcOverride override = initMDCStartTime(); + + IDistributionClientResult sendStatus = client.sendDeploymentStatus( + DistributionStatusMessageBuilder.build(client, data, artifact, distributionStatusEnum)); + metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "deploy " + result, + artifact.getArtifactName(), sendStatus.getDistributionActionResult().toString()); + + if (sendStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Failed to publish deploy " + result + " status: " + sendStatus.getDistributionMessageResult()); + } + } else { + logPublishingDisabled(distributionStatusEnum.toString(), result); + } + } + private void logPublishingDisabled(String statusType, String message) { logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Notification publishing is disabled, skipping publishing of the following status: " + statusType diff --git a/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java b/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java index 5576ea9..27db741 100644 --- a/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java +++ b/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java @@ -1,5 +1,5 @@ /** - * ============LICENSE_START======================================================= + * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. @@ -133,7 +133,7 @@ public class AaiRestClient { public OperationResult getAndDeleteResource(String url, String transId) { // First, GET the model OperationResult getResponse = getResource(url, transId, MediaType.APPLICATION_XML_TYPE); - if ((getResponse == null) || (getResponse.getResultCode() != Response.Status.OK.getStatusCode())) { + if (getResponse == null || getResponse.getResultCode() != Response.Status.OK.getStatusCode()) { return getResponse; } @@ -151,7 +151,7 @@ public class AaiRestClient { public boolean useBasicAuth() { - return (config.getAaiAuthenticationUser() != null) && (config.getAaiAuthenticationPassword() != null); + return config.getAaiAuthenticationUser() != null && config.getAaiAuthenticationPassword() != null; } private RestClient setupClient() { diff --git a/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClient.java b/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClient.java index fa677a9..f69752b 100644 --- a/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClient.java +++ b/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClient.java @@ -1,5 +1,5 @@ /** - * ============LICENSE_START======================================================= + * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. @@ -18,168 +18,15 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.modelloader.restclient; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.google.json.JsonSanitizer; -import com.sun.jersey.api.client.Client; // NOSONAR -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.WebResource; -import com.sun.jersey.api.client.config.DefaultClientConfig; -import java.io.FileInputStream; -import java.io.IOException; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Base64; -import java.util.Collections; import java.util.List; -import java.util.Objects; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import javax.ws.rs.core.Response; -import org.json.JSONObject; import org.onap.aai.babel.service.data.BabelArtifact; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.aai.modelloader.config.ModelLoaderConfig; -import org.onap.aai.modelloader.service.ModelLoaderMsgs; - -/** - * Initial version for testing End to End scenarios - * - */ -public class BabelServiceClient { - - private static Logger logger = LoggerFactory.getInstance().getLogger(BabelServiceClient.class); - - private static final String SSL_PROTOCOL = "TLS"; - private static final String KEYSTORE_ALGORITHM = "SunX509"; - private static final String KEYSTORE_TYPE = "PKCS12"; - - private ModelLoaderConfig config; - private Client client; - - private TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() { - @Override - public X509Certificate[] getAcceptedIssuers() { - return null; // NOSONAR - } - - @Override - public void checkClientTrusted(X509Certificate[] certs, String authType) { - // Do nothing - } - - @Override - public void checkServerTrusted(X509Certificate[] certs, String authType) { - // Do nothing - } - }}; - - public class BabelServiceException extends Exception { - - /** - * Babel Service error response - */ - private static final long serialVersionUID = 1L; - - public BabelServiceException(String message) { - super(message); - } - - } - - /** - * @param config - * @throws NoSuchAlgorithmException - * @throws KeyStoreException - * @throws CertificateException - * @throws IOException - * @throws UnrecoverableKeyException - * @throws KeyManagementException - */ - public BabelServiceClient(ModelLoaderConfig config) throws NoSuchAlgorithmException, KeyStoreException, - CertificateException, IOException, UnrecoverableKeyException, KeyManagementException { - this.config = config; - - logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Creating Babel Service client"); - - SSLContext ctx = SSLContext.getInstance(SSL_PROTOCOL); - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM); - KeyStore ks = KeyStore.getInstance(KEYSTORE_TYPE); - - String clientCertPassword = config.getBabelKeyStorePassword(); - - char[] pwd = null; - if (clientCertPassword != null) { - pwd = clientCertPassword.toCharArray(); - } - - String clientCertFileName = config.getBabelKeyStorePath(); - if (clientCertFileName != null) { - FileInputStream fin = new FileInputStream(clientCertFileName); - ks.load(fin, pwd); - kmf.init(ks, pwd); - ctx.init(kmf.getKeyManagers(), trustAllCerts, null); - } else { - ctx.init(null, trustAllCerts, null); - } - - logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Initialised context"); - - HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); - HttpsURLConnection.setDefaultHostnameVerifier((host, session) -> true); - - client = Client.create(new DefaultClientConfig()); - - logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Jersey client created"); - } - - /** - * @param artifactPayload - * @param artifactName - * @param artifactVersion - * @param transactionId - * @return - * @throws BabelServiceException - */ - public List postArtifact(byte[] artifactPayload, String artifactName, String artifactVersion, - String transactionId) throws BabelServiceException { - Objects.requireNonNull(artifactPayload); - - String encodedPayload = Base64.getEncoder().encodeToString(artifactPayload); - - JSONObject obj = new JSONObject(); - obj.put("csar", encodedPayload); - obj.put("artifactVersion", artifactVersion); - obj.put("artifactName", artifactName); - - logger.info(ModelLoaderMsgs.BABEL_REST_REQUEST_PAYLOAD, " Artifact Name: " + artifactName - + " Artifact version: " + artifactVersion + " Artifact payload: " + encodedPayload); - - WebResource webResource = client.resource(config.getBabelBaseUrl() + config.getBabelGenerateArtifactsUrl()); - ClientResponse response = webResource.type("application/json") - .header(AaiRestClient.HEADER_TRANS_ID, Collections.singletonList(transactionId)) - .header(AaiRestClient.HEADER_FROM_APP_ID, Collections.singletonList(AaiRestClient.ML_APP_NAME)) - .post(ClientResponse.class, obj.toString()); - String sanitizedJson = JsonSanitizer.sanitize(response.getEntity(String.class)); - logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, - "Babel response " + response.getStatus() + " " + sanitizedJson); +public interface BabelServiceClient { - if (response.getStatus() != Response.Status.OK.getStatusCode()) { - throw new BabelServiceException(sanitizedJson); - } + List postArtifact(byte[] artifactPayload, String artifactName, String artifactVersion, + String transactionId) throws BabelServiceClientException; - return new Gson().fromJson(sanitizedJson, new TypeToken>() {}.getType()); - } } diff --git a/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClientException.java b/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClientException.java new file mode 100644 index 0000000..0ce8037 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClientException.java @@ -0,0 +1,37 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.modelloader.restclient; + +public class BabelServiceClientException extends Exception { + + /** + * Babel Service Client Exception. + */ + private static final long serialVersionUID = 1L; + + public BabelServiceClientException(String message) { + super(message); + } + + public BabelServiceClientException(Exception ex) { + super(ex); + } +} diff --git a/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClientFactory.java b/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClientFactory.java deleted file mode 100644 index 4354710..0000000 --- a/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClientFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aai.modelloader.restclient; - -import java.io.IOException; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; -import org.onap.aai.modelloader.config.ModelLoaderConfig; - -public class BabelServiceClientFactory { - - public BabelServiceClient create(ModelLoaderConfig config) throws UnrecoverableKeyException, KeyManagementException, - NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException { - return new BabelServiceClient(config); - } - -} diff --git a/src/main/java/org/onap/aai/modelloader/restclient/HttpsBabelServiceClient.java b/src/main/java/org/onap/aai/modelloader/restclient/HttpsBabelServiceClient.java new file mode 100644 index 0000000..f07d0d3 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/restclient/HttpsBabelServiceClient.java @@ -0,0 +1,230 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.modelloader.restclient; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.google.json.JsonSanitizer; +import com.sun.jersey.api.client.Client; // NOSONAR +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Base64; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; +import javax.ws.rs.core.Response; +import org.json.JSONException; +import org.json.JSONObject; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.service.ModelLoaderMsgs; + +/** + * HTTPS Client for interfacing with Babel. + * + */ +public class HttpsBabelServiceClient implements BabelServiceClient { + + private static final Logger logger = LoggerFactory.getInstance().getLogger(HttpsBabelServiceClient.class); + + private static final String SSL_PROTOCOL = "TLS"; + private static final String KEYSTORE_ALGORITHM = "SunX509"; + private static final String KEYSTORE_TYPE = "PKCS12"; + + private final ModelLoaderConfig config; + private final Client client; + + /** + * @param config + * @throws NoSuchAlgorithmException + * @throws KeyStoreException + * @throws CertificateException + * @throws IOException + * @throws UnrecoverableKeyException + * @throws KeyManagementException + * @throws BabelServiceClientException + */ + public HttpsBabelServiceClient(ModelLoaderConfig config) + throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, + UnrecoverableKeyException, KeyManagementException, BabelServiceClientException { + this.config = config; + + logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Creating Babel Service client"); + + SSLContext ctx = SSLContext.getInstance(SSL_PROTOCOL); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM); + KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE); + + String clientCertPassword = config.getBabelKeyStorePassword(); + + char[] pwd = null; + if (clientCertPassword != null) { + pwd = clientCertPassword.toCharArray(); + } + + TrustManager[] trustManagers = getTrustManagers(); + + String clientCertFileName = config.getBabelKeyStorePath(); + if (clientCertFileName == null) { + ctx.init(null, trustManagers, null); + } else { + InputStream fin = Files.newInputStream(Paths.get(clientCertFileName)); + keyStore.load(fin, pwd); + kmf.init(keyStore, pwd); + ctx.init(kmf.getKeyManagers(), trustManagers, null); + } + + logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Initialised context"); + + HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); + HttpsURLConnection.setDefaultHostnameVerifier((host, session) -> true); + + client = Client.create(new DefaultClientConfig()); + + logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Jersey client created"); + } + + private TrustManager[] getTrustManagers() throws NoSuchAlgorithmException, KeyStoreException, CertificateException, + IOException, BabelServiceClientException { + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + // Using null here initializes the TMF with the default trust store. + tmf.init((KeyStore) null); + + // Create a new Trust Manager from the local trust store. + String trustStoreFile = config.getBabelTrustStorePath(); + if (trustStoreFile == null) { + throw new BabelServiceClientException("No Babel trust store defined"); + } + try (InputStream myKeys = Files.newInputStream(Paths.get(trustStoreFile))) { + KeyStore myTrustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + myTrustStore.load(myKeys, config.getBabelTrustStorePassword().toCharArray()); + tmf.init(myTrustStore); + } + X509TrustManager localTm = findX509TrustManager(tmf); + + // Create a custom trust manager that wraps both our trust store and the default. + final X509TrustManager finalLocalTm = localTm; + + // Find the default trust manager. + final X509TrustManager defaultTrustManager = findX509TrustManager(tmf); + + return new TrustManager[] {new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return defaultTrustManager.getAcceptedIssuers(); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + try { + finalLocalTm.checkServerTrusted(chain, authType); + } catch (CertificateException e) { + defaultTrustManager.checkServerTrusted(chain, authType); + } + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + defaultTrustManager.checkClientTrusted(chain, authType); + } + }}; + } + + private X509TrustManager findX509TrustManager(TrustManagerFactory tmf) { + X509TrustManager trustManager = null; + for (TrustManager tm : tmf.getTrustManagers()) { + if (tm instanceof X509TrustManager) { + trustManager = (X509TrustManager) tm; + break; + } + } + return trustManager; + } + + /** + * @param artifactPayload + * @param artifactName + * @param artifactVersion + * @param transactionId + * @return + * @throws BabelServiceClientException + * @throws JSONException + */ + @Override + public List postArtifact(byte[] artifactPayload, String artifactName, String artifactVersion, + String transactionId) throws BabelServiceClientException { + Objects.requireNonNull(artifactPayload); + + String encodedPayload = Base64.getEncoder().encodeToString(artifactPayload); + + JSONObject obj = new JSONObject(); + try { + obj.put("csar", encodedPayload); + obj.put("artifactVersion", artifactVersion); + obj.put("artifactName", artifactName); + } catch (JSONException ex) { + throw new BabelServiceClientException(ex); + } + + if (logger.isInfoEnabled()) { + logger.info(ModelLoaderMsgs.BABEL_REST_REQUEST_PAYLOAD, " Artifact Name: " + artifactName + + " Artifact version: " + artifactVersion + " Artifact payload: " + encodedPayload); + } + + WebResource webResource = client.resource(config.getBabelBaseUrl() + config.getBabelGenerateArtifactsUrl()); + ClientResponse response = webResource.type("application/json") + .header(AaiRestClient.HEADER_TRANS_ID, Collections.singletonList(transactionId)) + .header(AaiRestClient.HEADER_FROM_APP_ID, Collections.singletonList(AaiRestClient.ML_APP_NAME)) + .post(ClientResponse.class, obj.toString()); + String sanitizedJson = JsonSanitizer.sanitize(response.getEntity(String.class)); + + if (logger.isDebugEnabled()) { + logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, + "Babel response " + response.getStatus() + " " + sanitizedJson); + } + + if (response.getStatus() != Response.Status.OK.getStatusCode()) { + throw new BabelServiceClientException(sanitizedJson); + } + + return new Gson().fromJson(sanitizedJson, new TypeToken>() {}.getType()); + } +} diff --git a/src/main/java/org/onap/aai/modelloader/service/ArtifactDeploymentManager.java b/src/main/java/org/onap/aai/modelloader/service/ArtifactDeploymentManager.java new file mode 100644 index 0000000..af006f5 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/service/ArtifactDeploymentManager.java @@ -0,0 +1,94 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.modelloader.service; + +import java.util.ArrayList; +import java.util.List; +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.entity.Artifact; +import org.onap.aai.modelloader.entity.catalog.VnfCatalogArtifactHandler; +import org.onap.aai.modelloader.entity.model.ModelArtifactHandler; +import org.onap.aai.modelloader.restclient.AaiRestClient; +import org.onap.sdc.api.notification.INotificationData; + +/** + * This class is responsible for deploying model and catalog artifacts. + */ +public class ArtifactDeploymentManager { + + private ModelLoaderConfig config; + private ModelArtifactHandler modelArtifactHandler; + private VnfCatalogArtifactHandler vnfCatalogArtifactHandler; + + public ArtifactDeploymentManager(ModelLoaderConfig config) { + this.config = config; + } + + /** + * Deploys model and catalog artifacts to A&AI. + * + * @param data data about the notification that is being processed + * @param modelArtifacts collection of artifacts that represent yml files found in a TOSCA_CSAR file that have been + * converted to XML and also those for model query specs + * @param catalogArtifacts collection of artifacts that represent vnf catalog files + * @return boolean true if all deployments were successful otherwise false + */ + public boolean deploy(final INotificationData data, final List modelArtifacts, + final List catalogArtifacts) { + + AaiRestClient aaiClient = new AaiRestClient(config); + String distributionId = data.getDistributionID(); + + List completedArtifacts = new ArrayList<>(); + boolean deploySuccess = + getModelArtifactHandler().pushArtifacts(modelArtifacts, distributionId, completedArtifacts, aaiClient); + + if (!deploySuccess) { + getModelArtifactHandler().rollback(completedArtifacts, distributionId, aaiClient); + } else { + List completedImageData = new ArrayList<>(); + deploySuccess = getVnfCatalogArtifactHandler().pushArtifacts(catalogArtifacts, distributionId, + completedImageData, aaiClient); + if (!deploySuccess) { + getModelArtifactHandler().rollback(completedArtifacts, distributionId, aaiClient); + getVnfCatalogArtifactHandler().rollback(completedImageData, distributionId, aaiClient); + } + } + + return deploySuccess; + } + + private ModelArtifactHandler getModelArtifactHandler() { + if (modelArtifactHandler == null) { + modelArtifactHandler = new ModelArtifactHandler(config); + } + + return modelArtifactHandler; + } + + private VnfCatalogArtifactHandler getVnfCatalogArtifactHandler() { + if (vnfCatalogArtifactHandler == null) { + this.vnfCatalogArtifactHandler = new VnfCatalogArtifactHandler(config); + } + + return vnfCatalogArtifactHandler; + } +} diff --git a/src/main/java/org/onap/aai/modelloader/service/BabelServiceClientFactory.java b/src/main/java/org/onap/aai/modelloader/service/BabelServiceClientFactory.java new file mode 100644 index 0000000..ce690c5 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/service/BabelServiceClientFactory.java @@ -0,0 +1,30 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.modelloader.service; + +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.restclient.BabelServiceClient; +import org.onap.aai.modelloader.restclient.BabelServiceClientException; + +public interface BabelServiceClientFactory { + public BabelServiceClient create(ModelLoaderConfig config) throws BabelServiceClientException; +} diff --git a/src/main/java/org/onap/aai/modelloader/service/HttpsBabelServiceClientFactory.java b/src/main/java/org/onap/aai/modelloader/service/HttpsBabelServiceClientFactory.java new file mode 100644 index 0000000..2414991 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/service/HttpsBabelServiceClientFactory.java @@ -0,0 +1,56 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.modelloader.service; + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.restclient.BabelServiceClient; +import org.onap.aai.modelloader.restclient.BabelServiceClientException; +import org.onap.aai.modelloader.restclient.HttpsBabelServiceClient; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +@Service +@Primary +public class HttpsBabelServiceClientFactory implements BabelServiceClientFactory { + + /* + * (non-Javadoc) + * + * @see org.onap.aai.modelloader.service.BabelServiceClientFactory#create(org.onap.aai.modelloader.config. + * ModelLoaderConfig) + */ + @Override + public BabelServiceClient create(ModelLoaderConfig config) throws BabelServiceClientException { + try { + return new HttpsBabelServiceClient(config); + } catch (UnrecoverableKeyException | KeyManagementException | NoSuchAlgorithmException | KeyStoreException + | CertificateException | IOException ex) { + throw new BabelServiceClientException(ex); + } + } + +} diff --git a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderApplication.java b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderApplication.java deleted file mode 100644 index c0eb5f2..0000000 --- a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderApplication.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aai.modelloader.service; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * Model Loader Spring Boot Application. - */ - -@SpringBootApplication -public class ModelLoaderApplication { - - public static void main(String[] args) { - SpringApplication.run(ModelLoaderApplication.class, args); - } - -} diff --git a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderInterface.java b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderInterface.java index 6796090..e65e02c 100644 --- a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderInterface.java +++ b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderInterface.java @@ -1,5 +1,5 @@ /** - * ============LICENSE_START======================================================= + * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. @@ -31,15 +31,15 @@ public interface ModelLoaderInterface { @RequestMapping(value = "/loadModel/{modelid}", // method = RequestMethod.GET, produces = "application/json") @ResponseBody - public Response loadModel(String modelid); + Response loadModel(String modelid); @RequestMapping(value = "/saveModel/{modelid}/{modelname}", // method = RequestMethod.PUT, produces = "application/json") @ResponseBody - public Response saveModel(String modelid, String modelname); + Response saveModel(String modelid, String modelname); @RequestMapping(value = "/ingestModel/{modelName}/{modelVersion}", // method = RequestMethod.POST, produces = "application/json") @ResponseBody - public Response ingestModel(String modelid, String modelVersion, String payload) throws IOException; + Response ingestModel(String modelid, String modelVersion, String payload) throws IOException; } diff --git a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderService.java b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderService.java index 06d6e30..f8ab60f 100644 --- a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderService.java +++ b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderService.java @@ -1,5 +1,5 @@ /** - * ============LICENSE_START======================================================= + * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. @@ -20,8 +20,9 @@ */ package org.onap.aai.modelloader.service; -import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Base64; import java.util.Date; @@ -30,21 +31,22 @@ import java.util.Properties; import java.util.Timer; import java.util.TimerTask; import javax.annotation.PostConstruct; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; import org.onap.aai.modelloader.config.ModelLoaderConfig; import org.onap.aai.modelloader.entity.Artifact; -import org.onap.aai.modelloader.notification.ArtifactDeploymentManager; import org.onap.aai.modelloader.notification.ArtifactDownloadManager; import org.onap.aai.modelloader.notification.EventCallback; -import org.onap.aai.modelloader.restclient.BabelServiceClientFactory; +import org.onap.aai.modelloader.notification.NotificationDataImpl; +import org.onap.aai.modelloader.notification.NotificationPublisher; import org.onap.sdc.api.IDistributionClient; import org.onap.sdc.api.notification.IArtifactInfo; -import org.onap.sdc.api.notification.INotificationData; import org.onap.sdc.api.results.IDistributionClientResult; import org.onap.sdc.impl.DistributionClientFactory; import org.onap.sdc.utils.DistributionActionResultEnum; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -58,15 +60,14 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("/services/model-loader/v1/model-service") public class ModelLoaderService implements ModelLoaderInterface { - static Logger logger = LoggerFactory.getInstance().getLogger(ModelLoaderService.class.getName()); - - protected static final String FILESEP = - (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator"); + private static Logger logger = LoggerFactory.getInstance().getLogger(ModelLoaderService.class.getName()); @Value("${CONFIG_HOME}") private String configDir; private IDistributionClient client; private ModelLoaderConfig config; + @Autowired + private BabelServiceClientFactory babelClientFactory; /** * Responsible for loading configuration files and calling initialization. @@ -78,7 +79,7 @@ public class ModelLoaderService implements ModelLoaderInterface { ModelLoaderConfig.setConfigHome(configDir); Properties configProperties = new Properties(); try { - configProperties.load(new FileInputStream(configDir + FILESEP + "model-loader.properties")); + configProperties.load(Files.newInputStream(Paths.get(configDir, "model-loader.properties"))); config = new ModelLoaderConfig(configProperties); if (!config.getASDCConnectionDisabled()) { initSdcClient(); @@ -92,7 +93,7 @@ public class ModelLoaderService implements ModelLoaderInterface { /** * Responsible for stopping the connection to the distribution client before the resource is destroyed. */ - protected void preShutdownOperations() { + public void preShutdownOperations() { logger.info(ModelLoaderMsgs.STOPPING_CLIENT); if (client != null) { client.stop(); @@ -110,19 +111,13 @@ public class ModelLoaderService implements ModelLoaderInterface { IDistributionClientResult initResult = client.init(config, callback); - if (initResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - String errorMsg = "Failed to initialize distribution client: " + initResult.getDistributionMessageResult(); - logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); - - // Kick off a timer to retry the SDC connection - Timer timer = new Timer(); - TimerTask task = new SdcConnectionJob(client, config, callback, timer); - timer.schedule(task, new Date(), 60000); - } else { + if (initResult.getDistributionActionResult() == DistributionActionResultEnum.SUCCESS) { // Start distribution client logger.debug(ModelLoaderMsgs.INITIALIZING, "Starting distribution client..."); IDistributionClientResult startResult = client.start(); - if (startResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + if (startResult.getDistributionActionResult() == DistributionActionResultEnum.SUCCESS) { + logger.info(ModelLoaderMsgs.INITIALIZING, "Connection to SDC established"); + } else { String errorMsg = "Failed to start distribution client: " + startResult.getDistributionMessageResult(); logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); @@ -130,10 +125,17 @@ public class ModelLoaderService implements ModelLoaderInterface { Timer timer = new Timer(); TimerTask task = new SdcConnectionJob(client, config, callback, timer); timer.schedule(task, new Date(), 60000); - } else { - logger.info(ModelLoaderMsgs.INITIALIZING, "Connection to SDC established"); } + } else { + String errorMsg = "Failed to initialize distribution client: " + initResult.getDistributionMessageResult(); + logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); + + // Kick off a timer to retry the SDC connection + Timer timer = new Timer(); + TimerTask task = new SdcConnectionJob(client, config, callback, timer); + timer.schedule(task, new Date(), 60000); } + Runtime.getRuntime().addShutdownHook(new Thread(this::preShutdownOperations)); } @@ -160,51 +162,57 @@ public class ModelLoaderService implements ModelLoaderInterface { @Override public Response ingestModel(@PathVariable String modelName, @PathVariable String modelVersion, @RequestBody String payload) throws IOException { - boolean success; + Response response; if (config.getIngestSimulatorEnabled()) { - try { - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Received test artifact"); + response = processTestArtifact(modelName, modelVersion, payload); + } else { + logger.debug("Simulation interface disabled"); + response = Response.serverError().build(); + } - List catalogArtifacts = new ArrayList<>(); - List modelArtifacts = new ArrayList<>(); + return response; + } - IArtifactInfo artifactInfo = new ArtifactInfoImpl(); - ((ArtifactInfoImpl) artifactInfo).setArtifactName(modelName); - ((ArtifactInfoImpl) artifactInfo).setArtifactVersion(modelVersion); + private Response processTestArtifact(String modelName, String modelVersion, String payload) { + IArtifactInfo artifactInfo = new ArtifactInfoImpl(); + ((ArtifactInfoImpl) artifactInfo).setArtifactName(modelName); + ((ArtifactInfoImpl) artifactInfo).setArtifactVersion(modelVersion); - byte[] csarFile = Base64.getDecoder().decode(payload); + Response response; + try { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Received test artifact " + modelName + " " + modelVersion); - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Generating xml models from test artifact"); + byte[] csarFile = Base64.getDecoder().decode(payload); - new ArtifactDownloadManager(client, config, new BabelServiceClientFactory()).processToscaArtifacts( - modelArtifacts, catalogArtifacts, csarFile, artifactInfo, "test-transaction-id", modelVersion); + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Generating XML models from test artifact"); - List artifacts = new ArrayList<>(); - artifacts.add(artifactInfo); - INotificationData notificationData = new NotificationDataImpl(); - ((NotificationDataImpl) notificationData).setDistributionID("TestDistributionID"); + List modelArtifacts = new ArrayList<>(); + List catalogArtifacts = new ArrayList<>(); - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Loading xml models from test artifact"); + new ArtifactDownloadManager(client, config, babelClientFactory).processToscaArtifacts(modelArtifacts, + catalogArtifacts, csarFile, artifactInfo, "test-transaction-id", modelVersion); - success = new ArtifactDeploymentManager(client, config).deploy(notificationData, artifacts, - modelArtifacts, catalogArtifacts); + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Loading xml models from test artifacts: " + + modelArtifacts.size() + " model(s) and " + catalogArtifacts.size() + " catalog(s)"); - } catch (Exception e) { - return Response.serverError().entity(e).build(); + NotificationDataImpl notificationData = new NotificationDataImpl(); + notificationData.setDistributionID("TestDistributionID"); + boolean success = + new ArtifactDeploymentManager(config).deploy(notificationData, modelArtifacts, catalogArtifacts); + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Deployment success was " + success); + response = success ? Response.ok().build() : Response.serverError().build(); + } catch (Exception e) { + String responseMessage = e.getMessage(); + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Exception handled: " + responseMessage); + if (config.getASDCConnectionDisabled()) { + // Make sure the NotificationPublisher logger is invoked as per the standard processing flow. + new NotificationPublisher().publishDeployFailure(client, new NotificationDataImpl(), artifactInfo); + } else { + responseMessage += "\nSDC publishing is enabled but has been bypassed"; } - } else { - logger.debug("Simulation interface disabled"); - success = false; - } - - Response response; - if (success) { - response = Response.ok().build(); - } else { - response = Response.serverError().build(); + response = Response.serverError().entity(responseMessage).type(MediaType.APPLICATION_XML).build(); } - return response; } } diff --git a/src/main/java/org/onap/aai/modelloader/service/NotificationDataImpl.java b/src/main/java/org/onap/aai/modelloader/service/NotificationDataImpl.java deleted file mode 100644 index 536aa4a..0000000 --- a/src/main/java/org/onap/aai/modelloader/service/NotificationDataImpl.java +++ /dev/null @@ -1,117 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aai.modelloader.service; - -import java.util.Collections; -import java.util.List; -import org.onap.sdc.api.notification.IArtifactInfo; -import org.onap.sdc.api.notification.INotificationData; -import org.onap.sdc.api.notification.IResourceInstance; - -public class NotificationDataImpl implements INotificationData { - - private String distributionID; - - @Override - public IArtifactInfo getArtifactMetadataByUUID(String arg0) { - return null; - } - - @Override - public String getDistributionID() { - return distributionID; - } - - public void setDistributionID(String distributionID) { - this.distributionID = distributionID; - } - - @Override - public List getResources() { - return Collections.emptyList(); - } - - @Override - public List getServiceArtifacts() { - return Collections.emptyList(); - } - - @Override - public String getServiceDescription() { - return null; - } - - @Override - public String getServiceInvariantUUID() { - return null; - } - - @Override - public String getServiceName() { - return null; - } - - @Override - public String getServiceUUID() { - return null; - } - - @Override - public String getServiceVersion() { - return null; - } - - @Override - public String getWorkloadContext() { - return null; - } - - @Override - public void setWorkloadContext(String arg0) { - // Unsupported method - not expected to be called - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((distributionID == null) ? 0 : distributionID.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - NotificationDataImpl other = (NotificationDataImpl) obj; - if (distributionID == null) { - if (other.distributionID != null) - return false; - } else if (!distributionID.equals(other.distributionID)) - return false; - return true; - } - -} diff --git a/src/main/java/org/onap/aai/modelloader/service/SdcConnectionJob.java b/src/main/java/org/onap/aai/modelloader/service/SdcConnectionJob.java index 82e0bc6..9a6c6e9 100644 --- a/src/main/java/org/onap/aai/modelloader/service/SdcConnectionJob.java +++ b/src/main/java/org/onap/aai/modelloader/service/SdcConnectionJob.java @@ -1,5 +1,5 @@ /** - * ============LICENSE_START======================================================= + * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. @@ -31,14 +31,15 @@ import org.onap.sdc.api.results.IDistributionClientResult; import org.onap.sdc.utils.DistributionActionResultEnum; public class SdcConnectionJob extends TimerTask { - static Logger logger = LoggerFactory.getInstance().getLogger(SdcConnectionJob.class.getName()); + private static final Logger logger = LoggerFactory.getInstance().getLogger(SdcConnectionJob.class.getName()); - private IDistributionClient client; + private final IDistributionClient client; private ModelLoaderConfig config; private EventCallback callback; private Timer timer; public SdcConnectionJob(IDistributionClient client, ModelLoaderConfig config, EventCallback callback, Timer timer) { + super(); this.client = client; this.timer = timer; this.callback = callback; @@ -48,26 +49,27 @@ public class SdcConnectionJob extends TimerTask { @Override public void run() { if (!config.getASDCConnectionDisabled()) { - - IDistributionClientResult initResult = client.init(config, callback); - - if (initResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - String errorMsg = - "Failed to initialize distribution client: " + initResult.getDistributionMessageResult(); - logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); - return; - } - - IDistributionClientResult startResult = client.start(); - if (startResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - String errorMsg = "Failed to start distribution client: " + startResult.getDistributionMessageResult(); - logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); - return; + final IDistributionClientResult initResult = client.init(config, callback); + if (initResult.getDistributionActionResult() == DistributionActionResultEnum.SUCCESS) { + startClient(); + } else { + logConnectionError("Failed to initialize", initResult); } + } + } - // Success. Cancel the timer job + private void startClient() { + final IDistributionClientResult startResult = client.start(); + if (startResult.getDistributionActionResult() == DistributionActionResultEnum.SUCCESS) { timer.cancel(); logger.info(ModelLoaderMsgs.INITIALIZING, "Connection to SDC established"); + } else { + logConnectionError("Failed to start", startResult); } } + + private void logConnectionError(String msgPrefix, IDistributionClientResult result) { + final String errorMsg = msgPrefix + " distribution client: " + result.getDistributionMessageResult(); + logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); + } } diff --git a/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java b/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java index 48a33b5..87cfdcc 100644 --- a/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java +++ b/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java @@ -1,74 +1,77 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.aai.modelloader.util; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.XML; - -public class JsonXmlConverter { - - private JsonXmlConverter() { - throw new AssertionError("Instantiating utility class."); - } - - /** - * Determines whether or not the supplied text string represents a valid JSON structure or not. - * - * @param text The text to be evaluated. - * @return - true if the string represents a valid JSON object, false, otherwise. - */ - public static boolean isValidJson(String text) { - try { - new JSONObject(text); - } catch (JSONException ex) { - try { - new JSONArray(text); - } catch (JSONException ex1) { - return false; - } - } - - return true; - } - - /** - * Takes a text string representing a valid JSON structure and converts it to an equivalent XML string. - * - * @param jsonText The JSON string to convert to XML. - * @return an XML string representation of the supplied JSON string. - */ - public static String convertJsonToXml(String jsonText) { - return XML.toString(new JSONObject(jsonText)); - } - - /** - * Takes a text string representing a valid XML structure and converts it to an equivalent JSON string. - * - * @param xmlText The XML string to convert to JSON. - * @return a JSON string representation of the supplied XML string. - */ - public static String convertXmlToJson(String xmlText) { - JSONObject jsonObj = XML.toJSONObject(xmlText); - return jsonObj.toString(); - } -} +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 European Software Marketing Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.modelloader.util; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.XML; + +public final class JsonXmlConverter { + + private JsonXmlConverter() { + throw new AssertionError("Instantiating utility class."); + } + + /** + * Determines whether or not the supplied text string represents a valid JSON structure or not. + * + * @param text The text to be evaluated. + * @return - true if the string represents a valid JSON object, false, otherwise. + */ + public static boolean isValidJson(String text) { + boolean isValid; + try { + new JSONObject(text); + isValid = true; + } catch (JSONException ex) { + try { + new JSONArray(text); + isValid = true; + } catch (JSONException ex1) { + isValid = false; + } + } + + return isValid; + } + + /** + * Takes a text string representing a valid JSON structure and converts it to an equivalent XML string. + * + * @param jsonText The JSON string to convert to XML. + * @return an XML string representation of the supplied JSON string. + */ + public static String convertJsonToXml(String jsonText) { + return XML.toString(new JSONObject(jsonText)); + } + + /** + * Takes a text string representing a valid XML structure and converts it to an equivalent JSON string. + * + * @param xmlText The XML string to convert to JSON. + * @return a JSON string representation of the supplied XML string. + */ + public static String convertXmlToJson(String xmlText) { + JSONObject jsonObj = XML.toJSONObject(xmlText); + return jsonObj.toString(); + } +} -- cgit 1.2.3-korg