From 4140b0716234e7540d57b8a746944018fa591d69 Mon Sep 17 00:00:00 2001 From: prathamesh morde Date: Mon, 1 Apr 2019 23:19:42 -0400 Subject: CDS-SDC Listener application Things done -Implementation of GRPC client to store CBA archive using CDS Backend -Unit test coverage. -Tested locally. -Minor bug fix, performance improvement, more logging and make use of BluePrintProcessorHandler api in ListenerServiceImpl class. -Extract csar artifact from IDistributionClientResult and store it into local file(disk). Change-Id: I08b0de017396bb76d5bc13ddb9e7b430990e8df0 Issue-ID: CCSDK-1184 Signed-off-by: prathamesh morde --- ms/cds-sdc-listener/application/pom.xml | 45 +++++++ .../cds/cdssdclistener/CdsSdcListenerClient.java | 81 ------------ .../cds/cdssdclistener/CdsSdcListenerDto.java | 23 ---- .../CdsSdcListenerNotificationCallback.java | 41 ++++++- .../CdsSdcListenerAuthClientInterceptor.java | 46 +++++++ .../client/CdsSdcListenerClient.java | 86 +++++++++++++ .../cds/cdssdclistener/dto/CdsSdcListenerDto.java | 25 ++++ .../handler/BluePrintProcesssorHandler.java | 57 +++++++++ .../cdssdclistener/service/ListenerService.java | 15 ++- .../service/ListenerServiceImpl.java | 136 +++++++++++++++++++-- .../application/src/main/resources/application.yml | 6 +- .../cdssdclistener/CdsSdcListenerClientTest.java | 2 + .../handler/BluePrintProcessorHandlerTest.java | 106 ++++++++++++++++ .../service/ListenerServiceImplTest.java | 47 ++++++- .../application/src/test/resources/testcba.zip | Bin 0 -> 15123 bytes 15 files changed, 589 insertions(+), 127 deletions(-) delete mode 100644 ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerClient.java delete mode 100644 ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerDto.java create mode 100644 ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/client/CdsSdcListenerAuthClientInterceptor.java create mode 100644 ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/client/CdsSdcListenerClient.java create mode 100644 ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/dto/CdsSdcListenerDto.java create mode 100644 ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/handler/BluePrintProcesssorHandler.java create mode 100644 ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/handler/BluePrintProcessorHandlerTest.java create mode 100644 ms/cds-sdc-listener/application/src/test/resources/testcba.zip diff --git a/ms/cds-sdc-listener/application/pom.xml b/ms/cds-sdc-listener/application/pom.xml index 899d173ef..c2ec8b98c 100644 --- a/ms/cds-sdc-listener/application/pom.xml +++ b/ms/cds-sdc-listener/application/pom.xml @@ -20,6 +20,11 @@ cds-sdc-listener-application CDS-SDC Listener Application + + 1.17.1 + 3.6.1 + + @@ -51,6 +56,46 @@ test + + + io.grpc + grpc-netty + ${grpc.version} + + + io.grpc + grpc-protobuf + ${grpc.version} + + + io.grpc + grpc-stub + ${grpc.version} + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + io.grpc + grpc-testing + ${grpc.version} + test + + + org.onap.ccsdk.cds.components + proto-definition + 0.4.2-SNAPSHOT + + + + + org.onap.sdc.sdc-distribution-client + sdc-distribution-client + 1.3.0 + + diff --git a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerClient.java b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerClient.java deleted file mode 100644 index 76295bacb..000000000 --- a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerClient.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2019 Bell Canada. All rights reserved. - * - * NOTICE: All the intellectual and technical concepts contained herein are - * proprietary to Bell Canada and are protected by trade secret or copyright law. - * Unauthorized copying of this file, via any medium is strictly prohibited. - */ -package org.onap.ccsdk.cds.cdssdclistener; - -import java.util.Optional; -import org.onap.ccsdk.cds.cdssdclistener.exceptions.CdsSdcListenerException; -import org.onap.sdc.api.IDistributionClient; -import org.onap.sdc.api.results.IDistributionClientResult; -import org.onap.sdc.impl.DistributionClientFactory; -import org.onap.sdc.utils.DistributionActionResultEnum; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.event.EventListener; -import org.springframework.stereotype.Component; - -@Component -public class CdsSdcListenerClient { - - private static Logger LOG = LoggerFactory.getLogger(CdsSdcListenerClient.class); - - @Autowired - private CdsSdcListenerConfiguration configuration; - - @Autowired - private CdsSdcListenerNotificationCallback notification; - - @Autowired - private CdsSdcListenerDto listenerDto; - - private IDistributionClient distributionClient; - - /** - * This method initializes the SDC Distribution client. - */ - @EventListener(ApplicationReadyEvent.class) - public void initSdcClient() throws CdsSdcListenerException { - LOG.info("Initialize the SDC distribution client"); - - distributionClient = Optional.of(DistributionClientFactory.createDistributionClient()) - .orElseThrow(() -> new CdsSdcListenerException("Could not able to create SDC Distribution client")); - - listenerDto.setDistributionClient(distributionClient); - - IDistributionClientResult result = distributionClient.init(configuration, notification); - - startSdcClientBasedOnTheResult(result); - } - - private void startSdcClientBasedOnTheResult(IDistributionClientResult result) throws CdsSdcListenerException { - if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) { - throw new CdsSdcListenerException( - "SDC distribution client init failed with reason:" + result.getDistributionMessageResult()); - } - - // Start the client. - result = this.distributionClient.start(); - - if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) { - throw new CdsSdcListenerException( - "Startup of the SDC distribution client failed with reason: " + result.getDistributionMessageResult()); - } - } - - private void closeSdcDistributionclient() throws CdsSdcListenerException { - - IDistributionClientResult status = this.distributionClient.stop(); - - LOG.info("Closing SDC distribution client"); - if (status.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) { - throw new CdsSdcListenerException( - "Failed to close the SDC distribution client due to : " + status.getDistributionMessageResult()); - } - } -} diff --git a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerDto.java b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerDto.java deleted file mode 100644 index 7d154da42..000000000 --- a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerDto.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2019 Bell Canada. All rights reserved. - * - * NOTICE: All the intellectual and technical concepts contained herein are - * proprietary to Bell Canada and are protected by trade secret or copyright law. - * Unauthorized copying of this file, via any medium is strictly prohibited. - */ -package org.onap.ccsdk.cds.cdssdclistener; - -import org.onap.sdc.api.IDistributionClient; - -public class CdsSdcListenerDto { - - private IDistributionClient distributionClient; - - public IDistributionClient getDistributionClient() { - return distributionClient; - } - - public void setDistributionClient(IDistributionClient distributionClient) { - this.distributionClient = distributionClient; - } -} diff --git a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerNotificationCallback.java b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerNotificationCallback.java index aaab8d81f..e2aae9654 100644 --- a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerNotificationCallback.java +++ b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerNotificationCallback.java @@ -9,7 +9,13 @@ package org.onap.ccsdk.cds.cdssdclistener; import static org.onap.sdc.utils.DistributionActionResultEnum.SUCCESS; +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; import java.util.Objects; +import java.util.Optional; +import org.onap.ccsdk.cds.cdssdclistener.dto.CdsSdcListenerDto; import org.onap.ccsdk.cds.cdssdclistener.service.ListenerServiceImpl; import org.onap.sdc.api.IDistributionClient; import org.onap.sdc.api.consumer.INotificationCallback; @@ -19,9 +25,14 @@ import org.onap.sdc.api.results.IDistributionClientDownloadResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; import org.springframework.stereotype.Component; +@ConfigurationProperties("listenerservice") @Component +@ComponentScan("org.onap.ccsdk.cds.cdssdclistener.dto") public class CdsSdcListenerNotificationCallback implements INotificationCallback { @Autowired @@ -30,6 +41,9 @@ public class CdsSdcListenerNotificationCallback implements INotificationCallback @Autowired private ListenerServiceImpl listenerService; + @Value("${listenerservice.config.archivePath}") + private String pathToStoreArchives; + private static final Logger LOGGER = LoggerFactory.getLogger(CdsSdcListenerNotificationCallback.class); @Override @@ -45,7 +59,7 @@ public class CdsSdcListenerNotificationCallback implements INotificationCallback } /** - * Download the TOSCA CSAR artifact. + * Download the TOSCA CSAR artifact and process it. * * @param info - Artifact information * @param distributionClient - SDC distribution client @@ -53,6 +67,7 @@ public class CdsSdcListenerNotificationCallback implements INotificationCallback private void downloadCsarArtifacts(IArtifactInfo info, IDistributionClient distributionClient) { final String url = info.getArtifactURL(); final String id = info.getArtifactUUID(); + if (Objects.equals(info.getArtifactType(), CdsSdcListenerConfiguration.TOSCA_CSAR)) { LOGGER.info("Trying to download the artifact from : {} and UUID is {} ", url, id); @@ -63,8 +78,30 @@ public class CdsSdcListenerNotificationCallback implements INotificationCallback LOGGER.error("Failed to download the artifact from : {} due to {} ", url, result.getDistributionActionResult()); } else { - // TODO Store the CSAR into CSARArchive path and extract the Blueprint using ListenerServiceImpl.extractBluePrint + LOGGER.info("Trying to write CSAR artifact to file with URL {} and UUID {}", url, id); + processCsarArtifact(result); } } } + + public void processCsarArtifact(IDistributionClientDownloadResult result) { + Path cbaArchivePath = Paths.get(pathToStoreArchives, "cba-archive"); + Path csarArchivePath = Paths.get(pathToStoreArchives, "csar-archive"); + + // extract and store the CSAR archive into local disk. + listenerService.extractCsarAndStore(result, csarArchivePath.toString()); + + Optional> csarFiles = listenerService.getFilesFromDisk(csarArchivePath); + + if (csarFiles.isPresent()) { + + //Extract CBA archive from CSAR package and and store it into CDS Database. + csarFiles.get() + .forEach(file -> listenerService.extractBluePrint(file.getAbsolutePath(), cbaArchivePath.toString())); + + listenerService.saveBluePrintToCdsDatabase(cbaArchivePath); + } else { + LOGGER.error("The CSAR file is not present at this location {}", csarArchivePath); + } + } } diff --git a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/client/CdsSdcListenerAuthClientInterceptor.java b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/client/CdsSdcListenerAuthClientInterceptor.java new file mode 100644 index 000000000..528fbe2f3 --- /dev/null +++ b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/client/CdsSdcListenerAuthClientInterceptor.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 Bell Canada. All rights reserved. + * + * NOTICE: All the intellectual and technical concepts contained herein are + * proprietary to Bell Canada and are protected by trade secret or copyright law. + * Unauthorized copying of this file, via any medium is strictly prohibited. + */ + +package org.onap.ccsdk.cds.cdssdclistener.client; + +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptor; +import io.grpc.ForwardingClientCall; +import io.grpc.Metadata; +import io.grpc.Metadata.Key; +import io.grpc.MethodDescriptor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * To provide authentication with GRPC server. + */ +@ConfigurationProperties("listenerservice") +@Component +public class CdsSdcListenerAuthClientInterceptor implements ClientInterceptor { + + @Value("${listenerservice.config.authHeader}") + private String basicAuth; + + @Override + public ClientCall interceptCall(MethodDescriptor methodDescriptor, + CallOptions callOptions, Channel channel) { + Key authHeader = Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER); + return new ForwardingClientCall.SimpleForwardingClientCall( + channel.newCall(methodDescriptor, callOptions)) { + @Override + public void start(Listener responseListener, Metadata headers) { + headers.put(authHeader, basicAuth); + super.start(responseListener, headers); + } + }; + } +} diff --git a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/client/CdsSdcListenerClient.java b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/client/CdsSdcListenerClient.java new file mode 100644 index 000000000..6f888dd0b --- /dev/null +++ b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/client/CdsSdcListenerClient.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2019 Bell Canada. All rights reserved. + * + * NOTICE: All the intellectual and technical concepts contained herein are + * proprietary to Bell Canada and are protected by trade secret or copyright law. + * Unauthorized copying of this file, via any medium is strictly prohibited. + */ +package org.onap.ccsdk.cds.cdssdclistener.client; + +import java.util.Optional; +import org.onap.ccsdk.cds.cdssdclistener.CdsSdcListenerConfiguration; +import org.onap.ccsdk.cds.cdssdclistener.dto.CdsSdcListenerDto; +import org.onap.ccsdk.cds.cdssdclistener.CdsSdcListenerNotificationCallback; +import org.onap.ccsdk.cds.cdssdclistener.exceptions.CdsSdcListenerException; +import org.onap.sdc.api.IDistributionClient; +import org.onap.sdc.api.results.IDistributionClientResult; +import org.onap.sdc.impl.DistributionClientFactory; +import org.onap.sdc.utils.DistributionActionResultEnum; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +@Component +@ComponentScan("org.onap.ccsdk.cds.cdssdclistener.dto") +public class CdsSdcListenerClient { + + private static Logger LOG = LoggerFactory.getLogger(CdsSdcListenerClient.class); + + @Autowired + private CdsSdcListenerConfiguration configuration; + + @Autowired + private CdsSdcListenerNotificationCallback notification; + + @Autowired + private CdsSdcListenerDto listenerDto; + + private IDistributionClient distributionClient; + + /** + * This method initializes the SDC Distribution client. + */ + @EventListener(ApplicationReadyEvent.class) + public void initSdcClient() throws CdsSdcListenerException { + LOG.info("Initialize the SDC distribution client"); + + distributionClient = Optional.of(DistributionClientFactory.createDistributionClient()) + .orElseThrow(() -> new CdsSdcListenerException("Could not able to create SDC Distribution client")); + + listenerDto.setDistributionClient(distributionClient); + + IDistributionClientResult result = distributionClient.init(configuration, notification); + + startSdcClientBasedOnTheResult(result); + } + + private void startSdcClientBasedOnTheResult(IDistributionClientResult result) throws CdsSdcListenerException { + if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) { + throw new CdsSdcListenerException( + "SDC distribution client init failed with reason:" + result.getDistributionMessageResult()); + } + + // Start the client. + result = this.distributionClient.start(); + + if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) { + throw new CdsSdcListenerException( + "Startup of the SDC distribution client failed with reason: " + result.getDistributionMessageResult()); + } + } + + private void closeSdcDistributionclient() throws CdsSdcListenerException { + + IDistributionClientResult status = this.distributionClient.stop(); + + LOG.info("Closing SDC distribution client"); + if (status.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) { + throw new CdsSdcListenerException( + "Failed to close the SDC distribution client due to : " + status.getDistributionMessageResult()); + } + } +} diff --git a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/dto/CdsSdcListenerDto.java b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/dto/CdsSdcListenerDto.java new file mode 100644 index 000000000..41039eb28 --- /dev/null +++ b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/dto/CdsSdcListenerDto.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2019 Bell Canada. All rights reserved. + * + * NOTICE: All the intellectual and technical concepts contained herein are + * proprietary to Bell Canada and are protected by trade secret or copyright law. + * Unauthorized copying of this file, via any medium is strictly prohibited. + */ +package org.onap.ccsdk.cds.cdssdclistener.dto; + +import org.onap.sdc.api.IDistributionClient; +import org.springframework.stereotype.Component; + +@Component +public class CdsSdcListenerDto { + + private IDistributionClient distributionClient; + + public IDistributionClient getDistributionClient() { + return distributionClient; + } + + public void setDistributionClient(IDistributionClient distributionClient) { + this.distributionClient = distributionClient; + } +} diff --git a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/handler/BluePrintProcesssorHandler.java b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/handler/BluePrintProcesssorHandler.java new file mode 100644 index 000000000..6b03b6da2 --- /dev/null +++ b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/handler/BluePrintProcesssorHandler.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 Bell Canada. All rights reserved. + * + * NOTICE: All the intellectual and technical concepts contained herein are + * proprietary to Bell Canada and are protected by trade secret or copyright law. + * Unauthorized copying of this file, via any medium is strictly prohibited. + */ + +package org.onap.ccsdk.cds.cdssdclistener.handler; + +import io.grpc.ManagedChannel; +import org.onap.ccsdk.cds.controllerblueprints.common.api.Status; +import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementOutput; +import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementServiceGrpc; +import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementServiceGrpc.BluePrintManagementServiceBlockingStub; +import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintUploadInput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@ConfigurationProperties("listenerservice") +@Component +public class BluePrintProcesssorHandler implements AutoCloseable { + + private static final Logger LOGGER = LoggerFactory.getLogger(BluePrintProcesssorHandler.class); + + private ManagedChannel channel; + + /** + * Sending CBA archive to CDS backend to store into its Database. + * + * @param request BluePrintManagementInput object holds CBA archive, its version and blueprints. + * @param managedChannel - ManagedChannel object helps to access the server or application end point. + * @return A response object + */ + public Status sendRequest(BluePrintUploadInput request, ManagedChannel managedChannel) { + LOGGER.info("Sending request to blueprint processor"); + + this.channel = managedChannel; + + final BluePrintManagementServiceBlockingStub syncStub = BluePrintManagementServiceGrpc.newBlockingStub(channel); + + // Send the request to CDS backend. + final BluePrintManagementOutput response = syncStub.uploadBlueprint(request); + + return response.getStatus(); + } + + @Override + public void close() { + if (channel != null) { + channel.shutdown(); + } + LOGGER.info("Stopping GRPC connection to CDS backend"); + } +} diff --git a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerService.java b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerService.java index 5dc0c2194..1efbe8f33 100644 --- a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerService.java +++ b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerService.java @@ -8,7 +8,8 @@ package org.onap.ccsdk.cds.cdssdclistener.service; -import java.util.zip.ZipFile; +import java.nio.file.Path; +import org.onap.sdc.api.results.IDistributionClientDownloadResult; public interface ListenerService { @@ -23,7 +24,15 @@ public interface ListenerService { /** * Store the Zip file into CDS database. * - * @param file The file to be stored. + * @param path path where zip file exists. */ - void saveBluePrintToCdsDatabase(ZipFile file); + void saveBluePrintToCdsDatabase(Path path); + + /** + * Extract and store CSAR to file. + * + * @param result - IDistributionClientDownloadResult contains payload. + * @param csarArchivePath The destination path where CSAR will be stored. + */ + void extractCsarAndStore(IDistributionClientDownloadResult result, String csarArchivePath); } diff --git a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImpl.java b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImpl.java index 4ff2a6ea8..37052082a 100644 --- a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImpl.java +++ b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImpl.java @@ -8,6 +8,10 @@ package org.onap.ccsdk.cds.cdssdclistener.service; +import static java.nio.file.Files.walk; +import com.google.protobuf.ByteString; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -17,12 +21,24 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Enumeration; +import java.util.List; +import java.util.Optional; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import org.apache.commons.io.FileUtils; import org.apache.tomcat.util.http.fileupload.IOUtils; +import org.onap.ccsdk.cds.cdssdclistener.client.CdsSdcListenerAuthClientInterceptor; +import org.onap.ccsdk.cds.cdssdclistener.handler.BluePrintProcesssorHandler; +import org.onap.ccsdk.cds.controllerblueprints.common.api.Status; +import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintUploadInput; +import org.onap.ccsdk.cds.controllerblueprints.management.api.FileChunk; +import org.onap.sdc.api.results.IDistributionClientDownloadResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @@ -31,13 +47,21 @@ import org.springframework.stereotype.Component; @ConfigurationProperties("listenerservice") public class ListenerServiceImpl implements ListenerService { - @Value("${listenerservice.config.csarArchive}") - private String csarArchivePath; + @Autowired + private BluePrintProcesssorHandler bluePrintProcesssorHandler; - @Value("${listenerservice.config.cbaArchive}") - private String cbaArchivePath; + @Autowired + private CdsSdcListenerAuthClientInterceptor cdsSdcListenerAuthClientInterceptor; + + @Value("${listenerservice.config.grpcAddress}") + private String grpcAddress; + + @Value("${listenerservice.config.grpcPort}") + private int grpcPort; private static final String CBA_ZIP_PATH = "Artifacts/Resources/[a-zA-Z0-9-_]+/Deployment/CONTROLLER_BLUEPRINT_ARCHIVE/[a-zA-Z0-9-_]+[.]zip"; + private static final int SUCCESS_CODE = 200; + private static final String CSAR_FILE_EXTENSION = ".csar"; private static final Logger LOGGER = LoggerFactory.getLogger(ListenerServiceImpl.class); @Override @@ -50,6 +74,7 @@ public class ListenerServiceImpl implements ListenerService { String fileName = entry.getName(); if (Pattern.matches(CBA_ZIP_PATH, fileName)) { final String cbaArchiveName = Paths.get(fileName).getFileName().toString(); + LOGGER.info("Storing the CBA archive {}", cbaArchiveName); storeBluePrint(zipFile, cbaArchiveName, cbaStorageDir, entry); } } @@ -59,13 +84,12 @@ public class ListenerServiceImpl implements ListenerService { } private void storeBluePrint(ZipFile zipFile, String fileName, Path cbaArchivePath, ZipEntry entry) { - final String changedFileName = fileName + ".zip"; - Path targetLocation = cbaArchivePath.resolve(changedFileName); + Path targetLocation = cbaArchivePath.resolve(fileName); + LOGGER.info("The target location for zip file is {}", targetLocation); File targetZipFile = new File(targetLocation.toString()); try { targetZipFile.createNewFile(); - } catch (IOException e) { LOGGER.error("Could not able to create file {}", targetZipFile, e); } @@ -73,15 +97,43 @@ public class ListenerServiceImpl implements ListenerService { try (InputStream inputStream = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream( targetZipFile)) { IOUtils.copy(inputStream, out); + LOGGER.info("Succesfully store the CBA archive {} at this location", targetZipFile); + } catch (Exception e) { + LOGGER.error("Failed to put zip file into target location {}, {}", targetLocation, e); + } + } + + @Override + public void saveBluePrintToCdsDatabase(Path cbaArchivePath) { + Optional> zipFiles = getFilesFromDisk(cbaArchivePath); + zipFiles.ifPresent(this::prepareRequestForCdsBackend); + } + + @Override + public void extractCsarAndStore(IDistributionClientDownloadResult result, String csarArchivePath) { + + // Create CSAR storage directory + Path csarStorageDir = getStorageDirectory(csarArchivePath); + + byte[] payload = result.getArtifactPayload(); + String csarFileName = result.getArtifactFilename() + CSAR_FILE_EXTENSION; + Path targetLocation = csarStorageDir.resolve(csarFileName); + + LOGGER.info("The target location for the CSAR file is {}", targetLocation); + + File targetCsarFile = new File(targetLocation.toString()); + + try (FileOutputStream outFile = new FileOutputStream(targetCsarFile)) { + outFile.write(payload, 0, payload.length); } catch (Exception e) { - LOGGER.error("Failed to put zip file into target location {}", targetLocation, e); + LOGGER.error("Failed to put CSAR file into target location {}, {}", targetLocation, e); } } private Path getStorageDirectory(String path) { Path fileStorageLocation = Paths.get(path).toAbsolutePath().normalize(); - if (!Files.exists(fileStorageLocation)) { + if (!fileStorageLocation.toFile().exists()) { try { return Files.createDirectories(fileStorageLocation); } catch (IOException e) { @@ -91,8 +143,68 @@ public class ListenerServiceImpl implements ListenerService { return fileStorageLocation; } - @Override - public void saveBluePrintToCdsDatabase(ZipFile file) { - //TODO + private void prepareRequestForCdsBackend(List files) { + final ManagedChannel channel = getManagedChannel(); + + files.forEach(zipFile -> { + try { + final BluePrintUploadInput request = generateBluePrintUploadInputBuilder(zipFile); + + // Send request to CDS Backend. + final Status responseStatus = bluePrintProcesssorHandler.sendRequest(request, channel); + + if (responseStatus.getCode() != SUCCESS_CODE) { + LOGGER.error("Failed to store the CBA archive into CDS DB due to {}", + responseStatus.getErrorMessage()); + } else { + LOGGER.info(responseStatus.getMessage()); + } + + } catch (Exception e) { + LOGGER.error("Failure due to", e); + } finally { + //Delete the file from the local disk. + boolean fileDeleted = zipFile.delete(); + + if (!fileDeleted) { + LOGGER.error("Could not able to delete the zip file {}", zipFile.toString()); + } + } + }); + } + + private ManagedChannel getManagedChannel() { + return ManagedChannelBuilder.forAddress(grpcAddress, grpcPort) + .usePlaintext() + .intercept(cdsSdcListenerAuthClientInterceptor) + .build(); + } + + private BluePrintUploadInput generateBluePrintUploadInputBuilder(File file) throws IOException { + byte[] bytes = FileUtils.readFileToByteArray(file); + FileChunk fileChunk = FileChunk.newBuilder().setChunk(ByteString.copyFrom(bytes)).build(); + + return BluePrintUploadInput.newBuilder() + .setFileChunk(fileChunk) + .build(); + } + + /** + * Extract files from the given path + * + * @param path where files reside. + * @return list of files. + */ + public Optional> getFilesFromDisk(Path path) { + try (Stream fileTree = walk(path)) { + // Get the list of files from the path + return Optional.of(fileTree.filter(Files::isRegularFile) + .map(Path::toFile) + .collect(Collectors.toList())); + } catch (IOException e) { + LOGGER.error("Failed to find the file", e); + } + + return Optional.empty(); } } diff --git a/ms/cds-sdc-listener/application/src/main/resources/application.yml b/ms/cds-sdc-listener/application/src/main/resources/application.yml index 88de3b182..657ea9e80 100644 --- a/ms/cds-sdc-listener/application/src/main/resources/application.yml +++ b/ms/cds-sdc-listener/application/src/main/resources/application.yml @@ -14,6 +14,8 @@ listenerservice: keyStorePath: activateServerTLSAuth : false isUseHttpsWithDmaap: false - csarArchive: /opt/app/onap/cds-sdc-listener/csar-archive - cbaArchive: /opt/app/onap/cds/sdc-listener/cba-archive + archivePath: opt/app/onap/cds-sdc-listener/ + grpcAddress: localhost + grpcPort: 9111 + authHeader: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw== diff --git a/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerClientTest.java b/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerClientTest.java index 4d0631f96..948631462 100644 --- a/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerClientTest.java +++ b/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerClientTest.java @@ -17,6 +17,8 @@ import mockit.VerificationsInOrder; import mockit.integration.junit4.JMockit; import org.junit.Test; import org.junit.runner.RunWith; +import org.onap.ccsdk.cds.cdssdclistener.client.CdsSdcListenerClient; +import org.onap.ccsdk.cds.cdssdclistener.dto.CdsSdcListenerDto; import org.onap.ccsdk.cds.cdssdclistener.exceptions.CdsSdcListenerException; import org.onap.sdc.api.IDistributionClient; import org.onap.sdc.api.results.IDistributionClientResult; diff --git a/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/handler/BluePrintProcessorHandlerTest.java b/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/handler/BluePrintProcessorHandlerTest.java new file mode 100644 index 000000000..0d38decdf --- /dev/null +++ b/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/handler/BluePrintProcessorHandlerTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2019 Bell Canada. All rights reserved. + * + * NOTICE: All the intellectual and technical concepts contained herein are + * proprietary to Bell Canada and are protected by trade secret or copyright law. + * Unauthorized copying of this file, via any medium is strictly prohibited. + */ + +package org.onap.ccsdk.cds.cdssdclistener.handler; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import com.google.protobuf.ByteString; +import io.grpc.ManagedChannel; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.inprocess.InProcessServerBuilder; +import io.grpc.stub.StreamObserver; +import io.grpc.testing.GrpcCleanupRule; +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import org.apache.commons.io.FileUtils; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.ccsdk.cds.cdssdclistener.client.CdsSdcListenerAuthClientInterceptor; +import org.onap.ccsdk.cds.controllerblueprints.common.api.Status; +import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementOutput; +import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementServiceGrpc.BluePrintManagementServiceImplBase; +import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintUploadInput; +import org.onap.ccsdk.cds.controllerblueprints.management.api.FileChunk; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + + +@RunWith(SpringRunner.class) +@EnableConfigurationProperties({BluePrintProcesssorHandler.class, CdsSdcListenerAuthClientInterceptor.class}) +@SpringBootTest(classes = {BluePrintProcessorHandlerTest.class}) +public class BluePrintProcessorHandlerTest { + + @Autowired + private BluePrintProcesssorHandler bluePrintProcesssorHandler; + + @Autowired + private CdsSdcListenerAuthClientInterceptor cdsSdcListenerAuthClientInterceptor; + + @Rule + public GrpcCleanupRule grpcCleanup = new GrpcCleanupRule(); + + private static final String CBA_ARCHIVE = "src/test/resources/testcba.zip"; + private static final String SUCCESS_MSG = "Successfully uploaded CBA"; + private static final int SUCCESS_CODE = 200; + private ManagedChannel channel; + + @Before + public void setUp() throws IOException { + final BluePrintManagementServiceImplBase serviceImplBase = new BluePrintManagementServiceImplBase() { + @Override + public void uploadBlueprint(BluePrintUploadInput request, + StreamObserver responseObserver) { + responseObserver.onNext(getBluePrintManagementOutput()); + responseObserver.onCompleted(); + } + }; + + // Generate server name. + String serverName = InProcessServerBuilder.generateName(); + + // Create a server, add service, start, and register. + grpcCleanup.register( + InProcessServerBuilder.forName(serverName).addService(serviceImplBase).directExecutor().build().start()); + + // Create a client channel. + channel = grpcCleanup.register(InProcessChannelBuilder.forName(serverName).directExecutor().build()); + } + + @Test + public void testApplicationEndPointSucess() throws IOException { + // Arrange + BluePrintUploadInput request = generateRequest(); + + // Act + Status output = bluePrintProcesssorHandler.sendRequest(request, channel); + + // Verify + assertEquals(SUCCESS_CODE, output.getCode()); + assertTrue(output.getMessage().contains(SUCCESS_MSG)); + } + + private BluePrintUploadInput generateRequest() throws IOException { + File file = Paths.get(CBA_ARCHIVE).toFile(); + byte[] bytes = FileUtils.readFileToByteArray(file); + FileChunk fileChunk = FileChunk.newBuilder().setChunk(ByteString.copyFrom(bytes)).build(); + + return BluePrintUploadInput.newBuilder().setFileChunk(fileChunk).build(); + } + + private BluePrintManagementOutput getBluePrintManagementOutput() { + return BluePrintManagementOutput.newBuilder() + .setStatus(Status.newBuilder().setMessage(SUCCESS_MSG).setCode(200).build()) + .build(); + } +} diff --git a/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImplTest.java b/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImplTest.java index 05e1ffdec..e33fbcdcc 100644 --- a/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImplTest.java +++ b/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImplTest.java @@ -8,23 +8,34 @@ package org.onap.ccsdk.cds.cdssdclistener.service; +import static junit.framework.TestCase.assertTrue; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; +import org.onap.ccsdk.cds.cdssdclistener.client.CdsSdcListenerAuthClientInterceptor; +import org.onap.ccsdk.cds.cdssdclistener.handler.BluePrintProcesssorHandler; +import org.onap.sdc.impl.mock.DistributionClientDownloadResultStubImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) -@EnableConfigurationProperties(ListenerServiceImpl.class) +@EnableConfigurationProperties({ListenerServiceImpl.class, CdsSdcListenerAuthClientInterceptor.class, + BluePrintProcesssorHandler.class}) @SpringBootTest(classes = {ListenerServiceImplTest.class}) public class ListenerServiceImplTest { private static final String CSAR_SAMPLE = "src/test/resources/service-Testsvc140.csar"; + private static final String ZIP_FILE = ".zip"; + private static final String CSAR_FILE = ".csar"; + private String csarArchivePath; private Path tempDirectoryPath; @Rule @@ -33,12 +44,40 @@ public class ListenerServiceImplTest { @Autowired private ListenerServiceImpl listenerService; + @Before + public void setup() { + csarArchivePath = folder.getRoot().toString(); + tempDirectoryPath = Paths.get(csarArchivePath, "cds-sdc-listener-test"); + } @Test - public void extractBluePrintSuccessfully() { + public void extractBluePrintSuccessfully() throws IOException { + // Act + listenerService.extractBluePrint(CSAR_SAMPLE, tempDirectoryPath.toString()); + + // Verify + String result = checkFileExists(tempDirectoryPath); + assertTrue(result.contains(ZIP_FILE)); + } + + @Test + public void storeCsarArtifactToFileSuccessfully() throws IOException { // Arrange - tempDirectoryPath = Paths.get(folder.getRoot().toString(), "cds-sdc-listener-test"); + DistributionClientDownloadResultStubImpl resultStub = new DistributionClientDownloadResultStubImpl(); // Act - listenerService.extractBluePrint(CSAR_SAMPLE, tempDirectoryPath.toString()); + listenerService.extractCsarAndStore(resultStub, tempDirectoryPath.toString()); + + // Verify + String result = checkFileExists(tempDirectoryPath); + assertTrue(result.contains(CSAR_FILE)); + } + + private String checkFileExists(Path path) throws IOException { + return Files.walk(path) + .filter(Files::isRegularFile) + .map(Path::toFile) + .findAny() + .get() + .getName(); } } diff --git a/ms/cds-sdc-listener/application/src/test/resources/testcba.zip b/ms/cds-sdc-listener/application/src/test/resources/testcba.zip new file mode 100644 index 000000000..c886fe6bc Binary files /dev/null and b/ms/cds-sdc-listener/application/src/test/resources/testcba.zip differ -- cgit 1.2.3-korg