import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
-import java.util.Map;
import java.util.stream.Collectors;
-import org.onap.aai.babel.service.data.BabelArtifact;
-import org.onap.aai.babel.service.data.BabelArtifact.ArtifactType;
+import java.util.stream.Stream;
+
+import org.onap.aai.babel.service.data.BabelRequest;
import org.onap.aai.cl.api.Logger;
import org.onap.aai.cl.eelf.LoggerFactory;
import org.onap.aai.cl.mdc.MdcContext;
import org.onap.aai.cl.mdc.MdcOverride;
-import org.onap.aai.modelloader.config.ModelLoaderConfig;
+import org.onap.aai.modelloader.babel.BabelArtifactService;
import org.onap.aai.modelloader.entity.Artifact;
+import org.onap.aai.modelloader.entity.ArtifactType;
+import org.onap.aai.modelloader.entity.catalog.VnfCatalogArtifact;
import org.onap.aai.modelloader.entity.model.BabelArtifactParsingException;
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.extraction.VnfCatalogExtractor;
-import org.onap.aai.modelloader.restclient.BabelServiceClient;
-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;
import org.onap.sdc.api.results.IDistributionClientDownloadResult;
import org.onap.sdc.utils.ArtifactTypeEnum;
import org.onap.sdc.utils.DistributionActionResultEnum;
+import org.springframework.stereotype.Component;
/**
* This class is responsible for downloading the artifacts from the ASDC.
*
* TOSCA_CSAR file artifacts will be converted into XML and returned as model artifacts.
*/
+@Component
public class ArtifactDownloadManager {
private static Logger logger = LoggerFactory.getInstance().getLogger(ArtifactDownloadManager.class);
- private IDistributionClient client;
- private NotificationPublisher notificationPublisher;
- private BabelArtifactConverter babelArtifactConverter;
- private ModelLoaderConfig config;
- private BabelServiceClientFactory clientFactory;
- private VnfCatalogExtractor vnfCatalogExtractor;
+ private final IDistributionClient client;
+ private final NotificationPublisher notificationPublisher;
+ private final VnfCatalogExtractor vnfCatalogExtractor;
+ private final BabelArtifactService babelArtifactService;
- public ArtifactDownloadManager(IDistributionClient client, ModelLoaderConfig config,
- BabelServiceClientFactory clientFactory) {
+ public ArtifactDownloadManager(IDistributionClient client,
+ NotificationPublisher notificationPublisher, VnfCatalogExtractor vnfCatalogExtractor, BabelArtifactService babelArtifactService) {
this.client = client;
- this.config = config;
- this.clientFactory = clientFactory;
+ this.notificationPublisher = notificationPublisher;
+ this.vnfCatalogExtractor = vnfCatalogExtractor;
+ this.babelArtifactService = babelArtifactService;
}
/**
* @param modelArtifacts collection of artifacts for model query specs
* @param catalogArtifacts collection of artifacts that represent vnf catalog files
* @return boolean <code>true</code> if the download process was successful otherwise <code>false</code>
+ * @throws Exception
*/
- boolean downloadArtifacts(INotificationData data, List<IArtifactInfo> artifacts, List<Artifact> modelArtifacts,
- List<Artifact> catalogArtifacts) {
- boolean success = true;
+ List<Artifact> downloadArtifacts(INotificationData data, List<IArtifactInfo> artifacts) throws Exception {
+ List<Artifact> allArtifacts = new ArrayList<>();
for (IArtifactInfo artifact : artifacts) {
try {
IDistributionClientDownloadResult downloadResult = downloadIndividualArtifacts(data, artifact);
- processDownloadedArtifacts(modelArtifacts, catalogArtifacts, artifact, downloadResult, data);
+ List<Artifact> processedArtifacts = processDownloadedArtifacts(artifact, downloadResult, data);
+ allArtifacts.addAll(processedArtifacts);
} catch (DownloadFailureException e) {
- getNotificationPublisher().publishDownloadFailure(client, data, artifact, e.getMessage());
- success = false;
- } catch (Exception e) {
- getNotificationPublisher().publishDeployFailure(client, data, artifact);
- success = false;
- }
-
- if (!success) {
- break;
+ notificationPublisher.publishDownloadFailure(client, data, artifact, e.getMessage());
+ throw e;
+ } catch (ProcessToscaArtifactsException | InvalidArchiveException | BabelArtifactParsingException e) {
+ notificationPublisher.publishDeployFailure(client, data, artifact);
+ throw e;
}
}
-
- return success;
+ return allArtifacts;
}
private IDistributionClientDownloadResult downloadIndividualArtifacts(INotificationData data,
if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Downloaded artifact: " + artifact.getArtifactName());
- getNotificationPublisher().publishDownloadSuccess(client, data, artifact);
+ notificationPublisher.publishDownloadSuccess(client, data, artifact);
} else {
throw new DownloadFailureException(downloadResult.getDistributionMessageResult());
}
return downloadResult;
}
- private void processDownloadedArtifacts(List<Artifact> modelArtifacts, List<Artifact> catalogArtifacts,
+ private List<Artifact> processDownloadedArtifacts(
IArtifactInfo artifactInfo, IDistributionClientDownloadResult downloadResult, INotificationData data)
throws ProcessToscaArtifactsException, InvalidArchiveException, BabelArtifactParsingException {
+ List<Artifact> artifacts = new ArrayList<>();
+ List<Artifact> querySpecArtifacts = new ArrayList<>();
if ("TOSCA_CSAR".equalsIgnoreCase(artifactInfo.getArtifactType())) {
- processToscaArtifacts(modelArtifacts, catalogArtifacts, downloadResult.getArtifactPayload(), artifactInfo,
+ artifacts = processToscaArtifacts(downloadResult.getArtifactPayload(), artifactInfo,
data.getDistributionID(), data.getServiceVersion());
+
} else if (ArtifactTypeEnum.MODEL_QUERY_SPEC.toString().equalsIgnoreCase(artifactInfo.getArtifactType())) {
- processModelQuerySpecArtifact(modelArtifacts, downloadResult);
+ querySpecArtifacts = processModelQuerySpecArtifact(downloadResult);
} else {
logger.info(ModelLoaderMsgs.UNSUPPORTED_ARTIFACT_TYPE, artifactInfo.getArtifactName(),
artifactInfo.getArtifactType());
throw new InvalidArchiveException("Unsupported artifact type: " + artifactInfo.getArtifactType());
}
+ return Stream
+ .concat(artifacts.stream(), querySpecArtifacts.stream())
+ .collect(Collectors.toList());
}
- public void processToscaArtifacts(List<Artifact> modelArtifacts, List<Artifact> catalogArtifacts, byte[] payload,
- IArtifactInfo artifactInfo, String distributionId, String serviceVersion)
+ public List<Artifact> processToscaArtifacts(byte[] payload, IArtifactInfo artifactInfo, String distributionId, String serviceVersion)
throws ProcessToscaArtifactsException, InvalidArchiveException {
// Get translated artifacts from Babel Service
- invokeBabelService(modelArtifacts, catalogArtifacts, payload, artifactInfo, distributionId, serviceVersion);
+ BabelRequest babelRequest = new BabelRequest();
+ babelRequest.setArtifactName(artifactInfo.getArtifactName());
+ babelRequest.setCsar(Base64.getEncoder().encodeToString(payload));
+ babelRequest.setArtifactVersion(serviceVersion);
+ List<Artifact> artifacts = babelArtifactService.invokeBabelService(babelRequest, distributionId);
// Get VNF Catalog artifacts directly from CSAR
- List<Artifact> csarCatalogArtifacts = getVnfCatalogExtractor().extract(payload, artifactInfo.getArtifactName());
+ List<Artifact> csarCatalogArtifacts = vnfCatalogExtractor.extract(payload, artifactInfo.getArtifactName());
// Throw an error if VNF Catalog data is present in the Babel payload and directly in the CSAR
- if (!catalogArtifacts.isEmpty() && !csarCatalogArtifacts.isEmpty()) {
+ if (isDuplicateVnfCatalogData(artifacts, csarCatalogArtifacts)) {
logger.error(ModelLoaderMsgs.DUPLICATE_VNFC_DATA_ERROR, artifactInfo.getArtifactName());
throw new InvalidArchiveException("CSAR: " + artifactInfo.getArtifactName()
+ " contains VNF Catalog data in the format of both TOSCA and XML files. Only one format can be used for each CSAR file.");
- } else if (!csarCatalogArtifacts.isEmpty()) {
- catalogArtifacts.addAll(csarCatalogArtifacts);
}
- }
-
- public void invokeBabelService(List<Artifact> modelArtifacts, List<Artifact> catalogArtifacts, byte[] payload,
- IArtifactInfo artifactInfo, String distributionId, String serviceVersion)
- throws ProcessToscaArtifactsException {
- try {
- BabelServiceClient babelClient = createBabelServiceClient(artifactInfo, serviceVersion);
-
- logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT,
- "Posting artifact: " + artifactInfo.getArtifactName() + ", service version: " + serviceVersion
- + ", artifact version: " + artifactInfo.getArtifactVersion());
-
- List<BabelArtifact> babelArtifacts =
- babelClient.postArtifact(payload, artifactInfo.getArtifactName(), serviceVersion, distributionId);
+ return Stream
+ .concat(artifacts.stream(), csarCatalogArtifacts.stream())
+ .collect(Collectors.toList());
- // Sort Babel artifacts based on type
- Map<ArtifactType, List<BabelArtifact>> artifactMap =
- babelArtifacts.stream().collect(Collectors.groupingBy(BabelArtifact::getType));
-
- if (artifactMap.containsKey(BabelArtifact.ArtifactType.MODEL)) {
- modelArtifacts.addAll(
- getBabelArtifactConverter().convertToModel(artifactMap.get(BabelArtifact.ArtifactType.MODEL)));
- artifactMap.remove(BabelArtifact.ArtifactType.MODEL);
- }
-
- if (artifactMap.containsKey(BabelArtifact.ArtifactType.VNFCATALOG)) {
- catalogArtifacts.addAll(getBabelArtifactConverter()
- .convertToCatalog(artifactMap.get(BabelArtifact.ArtifactType.VNFCATALOG)));
- artifactMap.remove(BabelArtifact.ArtifactType.VNFCATALOG);
- }
-
- // Log unexpected artifact types
- if (!artifactMap.isEmpty()) {
- logger.warn(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR,
- artifactInfo.getArtifactName() + " " + serviceVersion
- + ". Unexpected artifact types returned by the babel service: "
- + artifactMap.keySet().toString());
- }
-
- } catch (BabelArtifactParsingException e) {
- logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR,
- "Error for artifact " + artifactInfo.getArtifactName() + " " + serviceVersion + e);
- throw new ProcessToscaArtifactsException(
- "An error occurred while trying to parse the Babel artifacts: " + e.getLocalizedMessage());
- } catch (Exception e) {
- logger.error(ModelLoaderMsgs.BABEL_REST_REQUEST_ERROR, e, "POST", config.getBabelBaseUrl(),
- "Error posting artifact " + artifactInfo.getArtifactName() + " " + serviceVersion + " to Babel: "
- + e.getLocalizedMessage());
- throw new ProcessToscaArtifactsException(
- "An error occurred while calling the Babel service: " + e.getLocalizedMessage());
- }
}
- BabelServiceClient createBabelServiceClient(IArtifactInfo artifact, String serviceVersion)
- throws ProcessToscaArtifactsException {
- BabelServiceClient babelClient;
- try {
- logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Creating Babel client");
- babelClient = clientFactory.create(config);
- } catch (BabelServiceClientException e) {
- logger.error(ModelLoaderMsgs.BABEL_REST_REQUEST_ERROR, e, "POST", config.getBabelBaseUrl(),
- "Error posting artifact " + artifact.getArtifactName() + " " + serviceVersion + " to Babel: "
- + e.getLocalizedMessage());
- throw new ProcessToscaArtifactsException(
- "An error occurred tyring to convert the tosca artifacts to xml artifacts: "
- + e.getLocalizedMessage());
- }
-
- return babelClient;
+ private boolean isDuplicateVnfCatalogData(List<Artifact> babelArtifacts, List<Artifact> csarCatalogArtifacts) {
+ boolean babelIsEmpty = babelArtifacts.stream()
+ .filter(VnfCatalogArtifact.class::isInstance)
+ .findAny().isEmpty();
+ return !csarCatalogArtifacts.isEmpty() && !babelIsEmpty;
}
- private void processModelQuerySpecArtifact(List<Artifact> modelArtifacts,
- IDistributionClientDownloadResult downloadResult) throws BabelArtifactParsingException {
+ private List<Artifact> processModelQuerySpecArtifact(IDistributionClientDownloadResult downloadResult) throws BabelArtifactParsingException {
logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Processing named query artifact.");
IModelParser parser = new NamedQueryArtifactParser();
List<Artifact> parsedArtifacts =
parser.parse(new String(downloadResult.getArtifactPayload()), downloadResult.getArtifactFilename());
- if (parsedArtifactsExist(parsedArtifacts)) {
- modelArtifacts.addAll(parsedArtifacts);
+ if (parsedArtifacts != null && !parsedArtifacts.isEmpty()) {
+ return parsedArtifacts;
} else {
throw new BabelArtifactParsingException(
"Could not parse generated XML: " + new String(downloadResult.getArtifactPayload()));
}
}
-
- private boolean parsedArtifactsExist(List<Artifact> parsedArtifacts) {
- return parsedArtifacts != null && !parsedArtifacts.isEmpty();
- }
-
- private NotificationPublisher getNotificationPublisher() {
- if (notificationPublisher == null) {
- notificationPublisher = new NotificationPublisher();
- }
-
- return notificationPublisher;
- }
-
- private BabelArtifactConverter getBabelArtifactConverter() {
- if (babelArtifactConverter == null) {
- babelArtifactConverter = new BabelArtifactConverter();
- }
-
- return babelArtifactConverter;
- }
-
- private VnfCatalogExtractor getVnfCatalogExtractor() {
- if (vnfCatalogExtractor == null) {
- vnfCatalogExtractor = new VnfCatalogExtractor();
- }
-
- return vnfCatalogExtractor;
- }
}