From d7b9a92193d96826ae63200a6625ea26679fc811 Mon Sep 17 00:00:00 2001 From: prathamesh morde Date: Thu, 9 May 2019 11:30:34 -0400 Subject: Fixed the parsing path for CBA archive - Added the parsing path as per the new requirements. - Error handling logic if the parser fails to find the CBA archive or fails to store/read cba or csar archive Change-Id: I33de939cb39f7d9afb68230b226f8ee6d7544fe4 Issue-ID:CCSDK-1318 Signed-off-by: prathamesh morde --- .../SdcListenerNotificationCallback.java | 24 +++++----- .../cds/sdclistener/service/ListenerService.java | 2 +- .../sdclistener/service/ListenerServiceImpl.java | 49 ++++++++++++++------- .../onap/ccsdk/cds/sdclistener/util/FileUtil.java | 13 +++--- .../service/ListenerServiceImplTest.java | 46 ++++++++++++++++++- .../resources/service-ServicePnfTest-csar.csar | Bin 0 -> 58715 bytes .../src/test/resources/service-Testsvc140.csar | Bin 116298 -> 0 bytes .../src/test/resources/wrong_csar_pattern.csar | Bin 0 -> 29302 bytes 8 files changed, 95 insertions(+), 39 deletions(-) create mode 100644 ms/sdclistener/application/src/test/resources/service-ServicePnfTest-csar.csar delete mode 100644 ms/sdclistener/application/src/test/resources/service-Testsvc140.csar create mode 100644 ms/sdclistener/application/src/test/resources/wrong_csar_pattern.csar diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerNotificationCallback.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerNotificationCallback.java index eb339aef7..67db02e77 100644 --- a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerNotificationCallback.java +++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerNotificationCallback.java @@ -21,7 +21,6 @@ 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.sdclistener.dto.SdcListenerDto; import org.onap.ccsdk.cds.sdclistener.service.ListenerService; import org.onap.ccsdk.cds.sdclistener.status.SdcListenerStatus; @@ -102,26 +101,23 @@ public class SdcListenerNotificationCallback implements INotificationCallback { } } - public void processCsarArtifact(IDistributionClientDownloadResult result) { + private 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()); + listenerService.extractCsarAndStore(result, csarArchivePath); - Optional> csarFiles = FileUtil.getFilesFromDisk(csarArchivePath); + List csarFiles = FileUtil.getFilesFromDisk(csarArchivePath); - if (csarFiles.isPresent()) { - //Extract CBA archive from CSAR package and store it into local disk. - List files = csarFiles.get(); + if (!csarFiles.isEmpty()) { + final String archivePath = cbaArchivePath.toString(); - if (!files.isEmpty()) { - final String archivePath = cbaArchivePath.toString(); - files.forEach(file -> listenerService.extractBluePrint(file.getAbsolutePath(), archivePath)); - files.forEach(file -> FileUtil.deleteFile(file, archivePath)); - } else { - LOGGER.error("The CSAR file is not present at this location {}", csarArchivePath); - } + //Extract CBA archive from CSAR package and store it into local disk + csarFiles.forEach(file -> listenerService.extractBluePrint(file.getAbsolutePath(), archivePath)); + csarFiles.forEach(file -> FileUtil.deleteFile(file, csarArchivePath.toString())); + } else { + LOGGER.error("Could not able to read CSAR files from this location {}", csarArchivePath); } listenerService.saveBluePrintToCdsDatabase(cbaArchivePath, sdcListenerDto.getManagedChannelForGrpc()); diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/service/ListenerService.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/service/ListenerService.java index 446c3e621..bc72c8f98 100644 --- a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/service/ListenerService.java +++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/service/ListenerService.java @@ -43,5 +43,5 @@ public interface ListenerService { * @param result - IDistributionClientDownloadResult contains payload. * @param csarArchivePath The destination path where CSAR will be stored. */ - void extractCsarAndStore(IDistributionClientDownloadResult result, String csarArchivePath); + void extractCsarAndStore(IDistributionClientDownloadResult result, Path csarArchivePath); } diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/service/ListenerServiceImpl.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/service/ListenerServiceImpl.java index daab4de71..d1aac9704 100644 --- a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/service/ListenerServiceImpl.java +++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/service/ListenerServiceImpl.java @@ -35,14 +35,14 @@ 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.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.ccsdk.cds.sdclistener.client.SdcListenerAuthClientInterceptor; import org.onap.ccsdk.cds.sdclistener.dto.SdcListenerDto; import org.onap.ccsdk.cds.sdclistener.handler.BluePrintProcesssorHandler; import org.onap.ccsdk.cds.sdclistener.status.SdcListenerStatus; import org.onap.ccsdk.cds.sdclistener.util.FileUtil; -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; @@ -73,12 +73,14 @@ public class ListenerServiceImpl implements ListenerService { @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 String CBA_ZIP_PATH = "Artifacts/[a-zA-Z0-9-_.]+/Deployment/CONTROLLER_BLUEPRINT_ARCHIVE/[a-zA-Z0-9-_.()]+[.]zip"; private static final int SUCCESS_CODE = 200; private static final Logger LOGGER = LoggerFactory.getLogger(ListenerServiceImpl.class); @Override public void extractBluePrint(String csarArchivePath, String cbaArchivePath) { + int validPathCount = 0; + final String distributionId = sdcListenerDto.getDistributionId(); Path cbaStorageDir = getStorageDirectory(cbaArchivePath); try (ZipFile zipFile = new ZipFile(csarArchivePath)) { Enumeration entries = zipFile.entries(); @@ -86,14 +88,24 @@ public class ListenerServiceImpl implements ListenerService { ZipEntry entry = entries.nextElement(); String fileName = entry.getName(); if (Pattern.matches(CBA_ZIP_PATH, fileName)) { + validPathCount++; final String cbaArchiveName = Paths.get(fileName).getFileName().toString(); LOGGER.info("Storing the CBA archive {}", cbaArchiveName); storeBluePrint(zipFile, cbaArchiveName, cbaStorageDir, entry); } } + if (validPathCount == 0) { + final String errorMessage = String + .format("The CBA Archive doesn't exist as per this given regex %s", CBA_ZIP_PATH); + listenerStatus.sendResponseStatusBackToSDC(distributionId, COMPONENT_DONE_ERROR, errorMessage); + LOGGER.error(errorMessage); + } + } catch (Exception e) { - LOGGER.error("Failed to extract blueprint {}", e); + final String errorMessage = String.format("Failed to extract blueprint %s", e.getMessage()); + listenerStatus.sendResponseStatusBackToSDC(distributionId, COMPONENT_DONE_ERROR, errorMessage); + LOGGER.error(errorMessage); } } @@ -119,15 +131,20 @@ public class ListenerServiceImpl implements ListenerService { @Override public void saveBluePrintToCdsDatabase(Path cbaArchivePath, ManagedChannel channel) { - Optional> zipFiles = FileUtil.getFilesFromDisk(cbaArchivePath); - zipFiles.ifPresent(files -> prepareRequestForCdsBackend(files, channel, cbaArchivePath.toString())); + List zipFiles = FileUtil.getFilesFromDisk(cbaArchivePath); + if (!zipFiles.isEmpty()) { + zipFiles.forEach(file -> FileUtil.deleteFile(file, cbaArchivePath.toString())); + prepareRequestForCdsBackend(zipFiles, channel, cbaArchivePath.toString()); + } else { + LOGGER.error("Could not able to read CBA archives from this location {}", cbaArchivePath); + } } @Override - public void extractCsarAndStore(IDistributionClientDownloadResult result, String csarArchivePath) { + public void extractCsarAndStore(IDistributionClientDownloadResult result, Path csarArchivePath) { // Create CSAR storage directory - Path csarStorageDir = getStorageDirectory(csarArchivePath); + Path csarStorageDir = getStorageDirectory(csarArchivePath.toString()); byte[] payload = result.getArtifactPayload(); String csarFileName = result.getArtifactFilename(); Path targetLocation = csarStorageDir.resolve(csarFileName); @@ -138,8 +155,11 @@ public class ListenerServiceImpl implements ListenerService { try (FileOutputStream outFile = new FileOutputStream(targetCsarFile)) { outFile.write(payload, 0, payload.length); + if (!csarArchivePath.toFile().exists()) { + LOGGER.error("Could not able to store the CSAR at this location {}", csarArchivePath); + } } catch (Exception e) { - LOGGER.error("Failed to put CSAR file into target location {}, {}", targetLocation, e); + LOGGER.error("Fail to write the data into FileOutputStream {}, {}", targetLocation, e); } } @@ -169,20 +189,17 @@ public class ListenerServiceImpl implements ListenerService { if (responseStatus.getCode() != SUCCESS_CODE) { final String errorMessage = String.format("Failed to store the CBA archive into CDS DB due to %s", responseStatus.getErrorMessage()); - listenerStatus.sendResponseStatusBackToSDC(distributionId, - COMPONENT_DONE_ERROR, errorMessage); + listenerStatus.sendResponseStatusBackToSDC(distributionId, COMPONENT_DONE_ERROR, errorMessage); LOGGER.error(errorMessage); - } else { LOGGER.info(responseStatus.getMessage()); - listenerStatus.sendResponseStatusBackToSDC(distributionId, - COMPONENT_DONE_OK, null); + listenerStatus.sendResponseStatusBackToSDC(distributionId, COMPONENT_DONE_OK, null); } } catch (Exception e) { final String errorMessage = String.format("Failure due to %s", e.getMessage()); listenerStatus.sendResponseStatusBackToSDC(distributionId, COMPONENT_DONE_ERROR, errorMessage); - LOGGER.error("Failure due to {}", e); + LOGGER.error(errorMessage); } finally { FileUtil.deleteFile(zipFile, path); } diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/util/FileUtil.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/util/FileUtil.java index f2e679ecf..b6d0e4809 100644 --- a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/util/FileUtil.java +++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/util/FileUtil.java @@ -20,8 +20,8 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.io.FileUtils; @@ -54,15 +54,16 @@ public final class FileUtil { * @param path where files reside. * @return list of files. */ - public static Optional> getFilesFromDisk(Path path) { + public static List 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())); + return fileTree.filter(Files::isRegularFile) + .map(Path::toFile) + .collect(Collectors.toList()); } catch (IOException e) { LOGGER.error("Failed to find the file due to", e); } - return Optional.empty(); + return new ArrayList<>(); } } diff --git a/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/service/ListenerServiceImplTest.java b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/service/ListenerServiceImplTest.java index f5ff2bdb8..aed4b8b30 100644 --- a/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/service/ListenerServiceImplTest.java +++ b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/service/ListenerServiceImplTest.java @@ -16,17 +16,25 @@ package org.onap.ccsdk.cds.sdclistener.service; import static junit.framework.TestCase.assertTrue; +import static org.onap.sdc.utils.DistributionStatusEnum.COMPONENT_DONE_ERROR; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import mockit.Mock; import org.apache.commons.io.FileUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.internal.junit.JUnitRule; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.MockitoRule; import org.onap.ccsdk.cds.sdclistener.SdcListenerConfiguration; import org.onap.ccsdk.cds.sdclistener.client.SdcListenerAuthClientInterceptor; import org.onap.ccsdk.cds.sdclistener.dto.SdcListenerDto; @@ -34,9 +42,11 @@ import org.onap.ccsdk.cds.sdclistener.handler.BluePrintProcesssorHandler; import org.onap.ccsdk.cds.sdclistener.status.SdcListenerStatus; import org.onap.sdc.api.results.IDistributionClientDownloadResult; import org.onap.sdc.impl.mock.DistributionClientResultStubImpl; +import org.onap.sdc.utils.DistributionStatusEnum; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @@ -46,23 +56,39 @@ import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest(classes = {ListenerServiceImplTest.class}) public class ListenerServiceImplTest { - private static final String CSAR_SAMPLE = "src/test/resources/service-Testsvc140.csar"; + private static final String CSAR_SAMPLE = "src/test/resources/service-ServicePnfTest-csar.csar"; + private static final String WRONG_CSAR_SAMPLE = "src/test/resources/wrong_csar_pattern.csar"; + private static final String CBA_ZIP_PATH = "Artifacts/[a-zA-Z0-9-_.]+/Deployment/CONTROLLER_BLUEPRINT_ARCHIVE/[a-zA-Z0-9-_.()]+[.]zip"; private static final String ZIP_FILE = ".zip"; private static final String CSAR_FILE = ".csar"; + private static final String DISTRIBUTION_ID = "1"; + + private String csarArchivePath; private Path tempDirectoryPath; @Rule public TemporaryFolder folder = new TemporaryFolder(); + @Rule + public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Autowired private ListenerServiceImpl listenerService; + @MockBean + SdcListenerStatus status; + + @MockBean + SdcListenerDto listenerDto; + @Before public void setup() { + MockitoAnnotations.initMocks(this); csarArchivePath = folder.getRoot().toString(); tempDirectoryPath = Paths.get(csarArchivePath, "cds-sdc-listener-test"); } + @Test public void extractBluePrintSuccessfully() throws IOException { // Act @@ -73,13 +99,29 @@ public class ListenerServiceImplTest { assertTrue(result.contains(ZIP_FILE)); } + @Test + public void extractBluePrintFailure() { + // Arrange + final String errorMessage = String + .format("The CBA Archive doesn't exist as per this given regex %s", CBA_ZIP_PATH); + Mockito.when(listenerDto.getDistributionId()).thenReturn(DISTRIBUTION_ID); + Mockito.doCallRealMethod().when(status) + .sendResponseStatusBackToSDC(DISTRIBUTION_ID, COMPONENT_DONE_ERROR, errorMessage); + + // Act + listenerService.extractBluePrint(WRONG_CSAR_SAMPLE, tempDirectoryPath.toString()); + + // Verify + Mockito.verify(status).sendResponseStatusBackToSDC(DISTRIBUTION_ID, COMPONENT_DONE_ERROR, errorMessage); + } + @Test public void storeCsarArtifactToFileSuccessfully() throws IOException { // Arrange DistributionClientDownloadResultStubImpl resultStub = new DistributionClientDownloadResultStubImpl(); // Act - listenerService.extractCsarAndStore(resultStub, tempDirectoryPath.toString()); + listenerService.extractCsarAndStore(resultStub, tempDirectoryPath); // Verify String result = checkFileExists(tempDirectoryPath); diff --git a/ms/sdclistener/application/src/test/resources/service-ServicePnfTest-csar.csar b/ms/sdclistener/application/src/test/resources/service-ServicePnfTest-csar.csar new file mode 100644 index 000000000..62a77dcaf Binary files /dev/null and b/ms/sdclistener/application/src/test/resources/service-ServicePnfTest-csar.csar differ diff --git a/ms/sdclistener/application/src/test/resources/service-Testsvc140.csar b/ms/sdclistener/application/src/test/resources/service-Testsvc140.csar deleted file mode 100644 index 4aa0de72b..000000000 Binary files a/ms/sdclistener/application/src/test/resources/service-Testsvc140.csar and /dev/null differ diff --git a/ms/sdclistener/application/src/test/resources/wrong_csar_pattern.csar b/ms/sdclistener/application/src/test/resources/wrong_csar_pattern.csar new file mode 100644 index 000000000..ee18b580d Binary files /dev/null and b/ms/sdclistener/application/src/test/resources/wrong_csar_pattern.csar differ -- cgit 1.2.3-korg