summaryrefslogtreecommitdiffstats
path: root/ms/sdclistener
diff options
context:
space:
mode:
authorOleg Mitsura <oleg.mitsura@amdocs.com>2019-04-22 17:47:33 -0400
committerOleg Mitsura <oleg.mitsura@amdocs.com>2019-04-23 11:07:55 -0400
commitd5339481d3c3f24dd5faccb44dccd4addfd58499 (patch)
treedacae59a21608341fcce9cc0060399b15d487f47 /ms/sdclistener
parentf332e6ecd2c0a9f26451f977c941f03ed8ab84dc (diff)
SDC Listner Docker touchup
1.Reworked Dockerization of SDC Listener to follow application/distribution+parent style; 2.Renamed CDS-SDClistener to just SDCListener Issue-ID: CCSDK-1145 Change-Id: I007373d3a48fb8eb7042150bdbb37fc7fec346b3 Signed-off-by: Oleg Mitsura <oleg.mitsura@amdocs.com>
Diffstat (limited to 'ms/sdclistener')
-rw-r--r--ms/sdclistener/application/pom.xml89
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerApplication.java28
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfiguration.java143
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerNotificationCallback.java129
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/client/SdcListenerAuthClientInterceptor.java54
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/client/SdcListenerClient.java95
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/controller/HealthCheck.java35
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/dto/SdcListenerDto.java70
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/exceptions/SdcListenerException.java34
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/handler/BluePrintProcesssorHandler.java64
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/service/ListenerService.java47
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/service/ListenerServiceImpl.java202
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/status/DistributionStatusMessage.java55
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/status/SdcListenerStatus.java82
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/util/BuilderUtil.java33
-rw-r--r--ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/util/FileUtil.java61
-rw-r--r--ms/sdclistener/application/src/main/resources/application.yml27
-rw-r--r--ms/sdclistener/application/src/main/resources/logback.xml33
-rw-r--r--ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerClientTest.java80
-rw-r--r--ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfigurationTest.java48
-rw-r--r--ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/handler/BluePrintProcessorHandlerTest.java112
-rw-r--r--ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/service/ListenerServiceImplTest.java126
-rw-r--r--ms/sdclistener/application/src/test/resources/service-Testsvc140.csarbin0 -> 116298 bytes
-rw-r--r--ms/sdclistener/application/src/test/resources/testcba.zipbin0 -> 15123 bytes
-rwxr-xr-xms/sdclistener/distribution/pom.xml183
-rwxr-xr-xms/sdclistener/distribution/src/main/dc/docker-compose.yaml29
-rwxr-xr-xms/sdclistener/distribution/src/main/docker/Dockerfile16
-rwxr-xr-xms/sdclistener/distribution/src/main/docker/distribution.xml47
-rw-r--r--ms/sdclistener/distribution/src/main/docker/startService.sh12
-rwxr-xr-xms/sdclistener/parent/pom.xml246
-rw-r--r--ms/sdclistener/pom.xml49
31 files changed, 2229 insertions, 0 deletions
diff --git a/ms/sdclistener/application/pom.xml b/ms/sdclistener/application/pom.xml
new file mode 100644
index 000000000..5513279cc
--- /dev/null
+++ b/ms/sdclistener/application/pom.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.ccsdk.cds.sdclistener</groupId>
+ <artifactId>parent</artifactId>
+ <version>0.4.2-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+
+ <artifactId>application</artifactId>
+ <packaging>jar</packaging>
+ <version>0.4.2-SNAPSHOT</version>
+ <name>SDC Listener Application</name>
+
+ <properties>
+ <protobuf.version>3.6.1</protobuf.version>
+ <project.version>${parent.version}</project.version>
+ </properties>
+
+ <dependencies>
+ <!-- Spring boot -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- SDC Distribution client dependency -->
+ <dependency>
+ <groupId>org.onap.sdc.sdc-distribution-client</groupId>
+ <artifactId>sdc-distribution-client</artifactId>
+ <version>1.3.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jmockit</groupId>
+ <artifactId>jmockit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- GRPC Dependencies -->
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-netty</artifactId>
+ <version>${grpc.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-protobuf</artifactId>
+ <version>${grpc.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-stub</artifactId>
+ <version>${grpc.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-testing</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.components</groupId>
+ <artifactId>proto-definition</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.projectreactor</groupId>
+ <artifactId>reactor-core</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerApplication.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerApplication.java
new file mode 100644
index 000000000..253b576d2
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerApplication.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+
+@SpringBootApplication
+@EnableConfigurationProperties(SdcListenerConfiguration.class)
+public class SdcListenerApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(SdcListenerApplication.class, args);
+ }
+}
diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfiguration.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfiguration.java
new file mode 100644
index 000000000..06e2a0342
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfiguration.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener;
+
+import java.util.List;
+import org.onap.sdc.api.consumer.IConfiguration;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * In order to initiate a SDC distribution client we need to supply some pre-configuration values that
+ * distribution client needs.
+ */
+@ConfigurationProperties("listenerservice")
+public class SdcListenerConfiguration implements IConfiguration {
+
+ public static final String TOSCA_CSAR = "TOSCA_CSAR";
+
+ @Value("${listenerservice.config.asdcAddress}")
+ private String asdcAddress;
+
+ @Value("${listenerservice.config.messageBusAddress}")
+ private List<String> messageBusAddress;
+
+ @Value("${listenerservice.config.user}")
+ private String user;
+
+ @Value("${listenerservice.config.password}")
+ private String password;
+
+ @Value("${listenerservice.config.pollingTimeout}")
+ private int pollingTimeout;
+
+ @Value("${listenerservice.config.pollingInterval}")
+ private int pollingInterval;
+
+ @Value("${listenerservice.config.relevantArtifactTypes}")
+ private List<String> relevantArtifactTypes;
+
+ @Value("${listenerservice.config.consumerGroup}")
+ private String consumerGroup;
+
+ @Value("${listenerservice.config.environmentName}")
+ private String envName;
+
+ @Value("${listenerservice.config.consumerId}")
+ private String consumerId;
+
+ @Value("${listenerservice.config.activateServerTLSAuth}")
+ private boolean activateServerTLSAuth;
+
+ @Value("${listenerservice.config.isUseHttpsWithDmaap}")
+ private boolean isUseHttpsWithDmaap;
+
+ @Override
+ public String getAsdcAddress() {
+ return asdcAddress;
+ }
+
+ @Override
+ public List<String> getMsgBusAddress() {
+ return messageBusAddress;
+ }
+
+ @Override
+ public String getUser() {
+ return user;
+ }
+
+ @Override
+ public String getPassword() {
+ return password;
+ }
+
+ @Override
+ public int getPollingInterval() {
+ return pollingInterval;
+ }
+
+ @Override
+ public int getPollingTimeout() {
+ return pollingTimeout;
+ }
+
+ @Override
+ public List<String> getRelevantArtifactTypes() {
+ return relevantArtifactTypes;
+ }
+
+ @Override
+ public String getConsumerGroup() {
+ return consumerGroup;
+ }
+
+ @Override
+ public String getEnvironmentName() {
+ return envName;
+ }
+
+ @Override
+ public String getConsumerID() {
+ return consumerId;
+ }
+
+ @Override
+ public String getKeyStorePath() {
+ return null;
+ }
+
+ @Override
+ public String getKeyStorePassword() {
+ return null;
+ }
+
+ @Override
+ public boolean activateServerTLSAuth() {
+ return activateServerTLSAuth;
+ }
+
+ @Override
+ public boolean isFilterInEmptyResources() {
+ return false;
+ }
+
+ @Override
+ public Boolean isUseHttpsWithDmaap() {
+ return isUseHttpsWithDmaap;
+ }
+}
+
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
new file mode 100644
index 000000000..eb339aef7
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/SdcListenerNotificationCallback.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener;
+
+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.sdclistener.dto.SdcListenerDto;
+import org.onap.ccsdk.cds.sdclistener.service.ListenerService;
+import org.onap.ccsdk.cds.sdclistener.status.SdcListenerStatus;
+import org.onap.ccsdk.cds.sdclistener.util.FileUtil;
+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.onap.sdc.api.results.IDistributionClientDownloadResult;
+import org.onap.sdc.utils.DistributionStatusEnum;
+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 SdcListenerNotificationCallback implements INotificationCallback {
+
+ @Autowired
+ private SdcListenerDto sdcListenerDto;
+
+ @Autowired
+ private ListenerService listenerService;
+
+ @Value("${listenerservice.config.archivePath}")
+ private String pathToStoreArchives;
+
+ @Autowired
+ private SdcListenerStatus listenerStatus;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SdcListenerNotificationCallback.class);
+
+ @Override
+ public void activateCallback(INotificationData notificationData) {
+ final String distributionId = notificationData.getDistributionID();
+ sdcListenerDto.setDistributionId(distributionId);
+ LOGGER.info("Received service distribution from SDC with the id {}", distributionId);
+ processNotification(notificationData);
+ }
+
+ private void processNotification(INotificationData notificationData) {
+ final IDistributionClient distributionClient = sdcListenerDto.getDistributionClient();
+ notificationData.getServiceArtifacts()
+ .forEach(artifactInfo -> downloadCsarArtifacts(artifactInfo, distributionClient));
+ }
+
+ /**
+ * Download the TOSCA CSAR artifact and process it.
+ *
+ * @param info - Artifact information
+ * @param distributionClient - SDC distribution client
+ */
+ private void downloadCsarArtifacts(IArtifactInfo info, IDistributionClient distributionClient) {
+ final String url = info.getArtifactURL();
+ final String id = info.getArtifactUUID();
+
+ if (Objects.equals(info.getArtifactType(), SdcListenerConfiguration.TOSCA_CSAR)) {
+ LOGGER.info("Trying to download the artifact from : {} and UUID is {} ", url, id);
+
+ // Download the artifact
+ IDistributionClientDownloadResult result = distributionClient.download(info);
+
+ if (!Objects.equals(result.getDistributionActionResult(), SUCCESS)) {
+ String errorMessage = String.format("Failed to download the artifact from : %s due to %s ", url,
+ result.getDistributionActionResult());
+ listenerStatus.sendResponseStatusBackToSDC(sdcListenerDto.getDistributionId(),
+ DistributionStatusEnum.COMPONENT_DONE_ERROR, errorMessage);
+ LOGGER.error(errorMessage);
+ } else {
+ 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<List<File>> csarFiles = FileUtil.getFilesFromDisk(csarArchivePath);
+
+ if (csarFiles.isPresent()) {
+ //Extract CBA archive from CSAR package and store it into local disk.
+ List<File> files = csarFiles.get();
+
+ 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);
+ }
+ }
+
+ listenerService.saveBluePrintToCdsDatabase(cbaArchivePath, sdcListenerDto.getManagedChannelForGrpc());
+ }
+}
diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/client/SdcListenerAuthClientInterceptor.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/client/SdcListenerAuthClientInterceptor.java
new file mode 100644
index 000000000..6f782d10a
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/client/SdcListenerAuthClientInterceptor.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.sdclistener.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 SdcListenerAuthClientInterceptor implements ClientInterceptor {
+
+ @Value("${listenerservice.config.authHeader}")
+ private String basicAuth;
+
+ @Override
+ public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> methodDescriptor,
+ CallOptions callOptions, Channel channel) {
+ Key<String> authHeader = Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER);
+ return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(
+ channel.newCall(methodDescriptor, callOptions)) {
+ @Override
+ public void start(Listener<RespT> responseListener, Metadata headers) {
+ headers.put(authHeader, basicAuth);
+ super.start(responseListener, headers);
+ }
+ };
+ }
+}
diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/client/SdcListenerClient.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/client/SdcListenerClient.java
new file mode 100644
index 000000000..973f950bc
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/client/SdcListenerClient.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener.client;
+
+import java.util.Optional;
+import org.onap.ccsdk.cds.sdclistener.SdcListenerConfiguration;
+import org.onap.ccsdk.cds.sdclistener.dto.SdcListenerDto;
+import org.onap.ccsdk.cds.sdclistener.SdcListenerNotificationCallback;
+import org.onap.ccsdk.cds.sdclistener.exceptions.SdcListenerException;
+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 SdcListenerClient {
+
+ private static Logger LOG = LoggerFactory.getLogger(SdcListenerClient.class);
+
+ @Autowired
+ private SdcListenerConfiguration configuration;
+
+ @Autowired
+ private SdcListenerNotificationCallback notification;
+
+ @Autowired
+ private SdcListenerDto listenerDto;
+
+ private IDistributionClient distributionClient;
+
+ /**
+ * This method initializes the SDC Distribution client.
+ */
+ @EventListener(ApplicationReadyEvent.class)
+ public void initSdcClient() throws SdcListenerException {
+ LOG.info("Initialize the SDC distribution client");
+
+ distributionClient = Optional.of(DistributionClientFactory.createDistributionClient())
+ .orElseThrow(() -> new SdcListenerException("Could not able to create SDC Distribution client"));
+
+ listenerDto.setManagedChannelForGrpc();
+
+ listenerDto.setDistributionClient(distributionClient);
+
+ IDistributionClientResult result = distributionClient.init(configuration, notification);
+ startSdcClientBasedOnTheResult(result);
+ }
+
+ private void startSdcClientBasedOnTheResult(IDistributionClientResult result) throws SdcListenerException {
+ if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ throw new SdcListenerException(
+ "SDC distribution client init failed with reason:" + result.getDistributionMessageResult());
+ }
+
+ LOG.info("Initialization of the SDC distribution client is complete");
+
+ // Start the client.
+ result = this.distributionClient.start();
+
+ if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ throw new SdcListenerException(
+ "Startup of the SDC distribution client failed with reason: " + result.getDistributionMessageResult());
+ }
+ }
+
+ private void closeSdcDistributionclient() throws SdcListenerException {
+ LOG.info("Closing SDC distribution client");
+ IDistributionClientResult status = this.distributionClient.stop();
+ if (status.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ throw new SdcListenerException(
+ "Failed to close the SDC distribution client due to : " + status.getDistributionMessageResult());
+ }
+ }
+}
diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/controller/HealthCheck.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/controller/HealthCheck.java
new file mode 100644
index 000000000..a9e51ac12
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/controller/HealthCheck.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.sdclistener.controller;
+
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Mono;
+
+@RestController
+@RequestMapping("/api/v1/sdclistener")
+public class HealthCheck {
+
+ @RequestMapping(path = "/healthcheck", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public @ResponseBody
+ Mono<String> ping() {
+ return Mono.just("{\"status\":\"UP\"}");
+ }
+}
diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/dto/SdcListenerDto.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/dto/SdcListenerDto.java
new file mode 100644
index 000000000..c7c3d4829
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/dto/SdcListenerDto.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener.dto;
+
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import org.onap.ccsdk.cds.sdclistener.client.SdcListenerAuthClientInterceptor;
+import org.onap.sdc.api.IDistributionClient;
+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;
+
+@Component
+@ConfigurationProperties("listenerservice")
+public class SdcListenerDto {
+
+ @Value("${listenerservice.config.grpcAddress}")
+ private String grpcAddress;
+
+ @Value("${listenerservice.config.grpcPort}")
+ private int grpcPort;
+
+ @Autowired
+ private SdcListenerAuthClientInterceptor sdcListenerAuthClientInterceptor;
+
+ private IDistributionClient distributionClient;
+ private ManagedChannel managedChannel;
+ private String distributionId;
+
+ public IDistributionClient getDistributionClient() {
+ return distributionClient;
+ }
+
+ public void setDistributionClient(IDistributionClient distributionClient) {
+ this.distributionClient = distributionClient;
+ }
+
+ public void setDistributionId(String id) {
+ this.distributionId = id;
+ }
+
+ public String getDistributionId() {
+ return distributionId;
+ }
+
+ public void setManagedChannelForGrpc() {
+ managedChannel = ManagedChannelBuilder.forAddress(grpcAddress, grpcPort)
+ .usePlaintext()
+ .intercept(sdcListenerAuthClientInterceptor)
+ .build();
+ }
+
+ public ManagedChannel getManagedChannelForGrpc() {
+ return managedChannel;
+ }
+}
diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/exceptions/SdcListenerException.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/exceptions/SdcListenerException.java
new file mode 100644
index 000000000..23f669f1e
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/exceptions/SdcListenerException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener.exceptions;
+
+public class SdcListenerException extends Exception {
+
+ /**
+ * @param message The message to dump
+ */
+ public SdcListenerException(final String message) {
+ super(message);
+ }
+
+ /**
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public SdcListenerException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/handler/BluePrintProcesssorHandler.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/handler/BluePrintProcesssorHandler.java
new file mode 100644
index 000000000..96b2ff081
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/handler/BluePrintProcesssorHandler.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener.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/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
new file mode 100644
index 000000000..446c3e621
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/service/ListenerService.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener.service;
+
+import io.grpc.ManagedChannel;
+import java.nio.file.Path;
+import org.onap.sdc.api.results.IDistributionClientDownloadResult;
+
+public interface ListenerService {
+
+ /**
+ * Get the controller blueprint archive from CSAR package.
+ *
+ * @param csarArchivePath The path where CSAR archive is stored.
+ * @param cbaArchivePath The destination path where CBA will be stored.
+ */
+ void extractBluePrint(String csarArchivePath, String cbaArchivePath);
+
+ /**
+ * Store the Zip file into CDS database.
+ *
+ * @param path path where zip file exists.
+ * @param managedChannel To access the blueprint processor application end point
+ */
+ void saveBluePrintToCdsDatabase(Path path, ManagedChannel managedChannel);
+
+ /**
+ * Extract and store the csar package to local disk.
+ *
+ * @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/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
new file mode 100644
index 000000000..9a6ae8779
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/service/ListenerServiceImpl.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright © 2017-2019 AT&T, Bell Canada
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.sdclistener.service;
+
+import static java.nio.file.Files.walk;
+import static org.onap.sdc.utils.DistributionStatusEnum.COMPONENT_DONE_ERROR;
+import static org.onap.sdc.utils.DistributionStatusEnum.COMPONENT_DONE_OK;
+import com.google.protobuf.ByteString;
+import io.grpc.ManagedChannel;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+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.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.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;
+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;
+
+@Component
+@ConfigurationProperties("listenerservice")
+public class ListenerServiceImpl implements ListenerService {
+
+ @Autowired
+ private BluePrintProcesssorHandler bluePrintProcesssorHandler;
+
+ @Autowired
+ private SdcListenerAuthClientInterceptor sdcListenerAuthClientInterceptor;
+
+ @Autowired
+ private SdcListenerStatus listenerStatus;
+
+ @Autowired
+ private SdcListenerDto sdcListenerDto;
+
+ @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 Logger LOGGER = LoggerFactory.getLogger(ListenerServiceImpl.class);
+
+ @Override
+ public void extractBluePrint(String csarArchivePath, String cbaArchivePath) {
+ Path cbaStorageDir = getStorageDirectory(cbaArchivePath);
+ try (ZipFile zipFile = new ZipFile(csarArchivePath)) {
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ 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);
+ }
+ }
+
+ } catch (Exception e) {
+ LOGGER.error("Failed to extract blueprint {}", e);
+ }
+ }
+
+ private void storeBluePrint(ZipFile zipFile, String fileName, Path cbaArchivePath, ZipEntry entry) {
+ 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);
+ }
+
+ try (InputStream inputStream = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream(
+ targetZipFile)) {
+ IOUtils.copy(inputStream, out);
+ LOGGER.info("Successfully 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, ManagedChannel channel) {
+ Optional<List<File>> zipFiles = FileUtil.getFilesFromDisk(cbaArchivePath);
+ zipFiles.ifPresent(files -> prepareRequestForCdsBackend(files, channel, cbaArchivePath.toString()));
+ }
+
+ @Override
+ public void extractCsarAndStore(IDistributionClientDownloadResult result, String csarArchivePath) {
+
+ // Create CSAR storage directory
+ Path csarStorageDir = getStorageDirectory(csarArchivePath);
+ byte[] payload = result.getArtifactPayload();
+ String csarFileName = result.getArtifactFilename();
+ 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 CSAR file into target location {}, {}", targetLocation, e);
+ }
+ }
+
+ private Path getStorageDirectory(String path) {
+ Path fileStorageLocation = Paths.get(path).toAbsolutePath().normalize();
+
+ if (!fileStorageLocation.toFile().exists()) {
+ try {
+ return Files.createDirectories(fileStorageLocation);
+ } catch (IOException e) {
+ LOGGER.error("Fail to create directory {}, {}", e, fileStorageLocation);
+ }
+ }
+ return fileStorageLocation;
+ }
+
+ private void prepareRequestForCdsBackend(List<File> files, ManagedChannel managedChannel, String path) {
+ final String distributionId = sdcListenerDto.getDistributionId();
+
+ files.forEach(zipFile -> {
+ try {
+ final BluePrintUploadInput request = generateBluePrintUploadInputBuilder(zipFile);
+
+ // Send request to CDS Backend.
+ final Status responseStatus = bluePrintProcesssorHandler.sendRequest(request, managedChannel);
+
+ 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);
+ LOGGER.error(errorMessage);
+
+ } else {
+ LOGGER.info(responseStatus.getMessage());
+ 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);
+ } finally {
+ FileUtil.deleteFile(zipFile, path);
+ }
+ });
+ }
+
+ 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();
+ }
+}
diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/status/DistributionStatusMessage.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/status/DistributionStatusMessage.java
new file mode 100644
index 000000000..60463762b
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/status/DistributionStatusMessage.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener.status;
+
+import org.onap.sdc.api.consumer.IFinalDistrStatusMessage;
+import org.onap.sdc.utils.DistributionStatusEnum;
+
+public class DistributionStatusMessage implements IFinalDistrStatusMessage {
+
+ public String componentName;
+
+ public String consumerID;
+
+ public String distributionID;
+
+ public DistributionStatusEnum status;
+
+ @Override
+ public String getDistributionID() {
+ return distributionID;
+ }
+
+ @Override
+ public long getTimestamp() {
+ return 0;
+ }
+
+ @Override
+ public DistributionStatusEnum getStatus() {
+ return status;
+ }
+
+ @Override
+ public String getConsumerID() {
+ return consumerID;
+ }
+
+ @Override
+ public String getComponentName() {
+ return componentName;
+ }
+}
diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/status/SdcListenerStatus.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/status/SdcListenerStatus.java
new file mode 100644
index 000000000..ff64c0d0c
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/status/SdcListenerStatus.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener.status;
+
+import static org.onap.sdc.utils.DistributionActionResultEnum.SUCCESS;
+import java.util.Objects;
+import org.onap.ccsdk.cds.sdclistener.dto.SdcListenerDto;
+import org.onap.ccsdk.cds.sdclistener.util.BuilderUtil;
+import org.onap.sdc.api.IDistributionClient;
+import org.onap.sdc.api.consumer.IFinalDistrStatusMessage;
+import org.onap.sdc.api.results.IDistributionClientResult;
+import org.onap.sdc.utils.DistributionStatusEnum;
+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;
+
+@Component
+@ConfigurationProperties("listenerservice")
+@ComponentScan("org.onap.ccsdk.cds.cdssdclistener.dto")
+public class SdcListenerStatus {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SdcListenerStatus.class);
+ private static final String COMPONENT_NAME = "cds";
+
+ @Value("${listenerservice.config.consumerId}")
+ private String consumerId;
+
+ @Autowired
+ private SdcListenerDto sdcListenerDto;
+
+ /**
+ * Send the response back to SDC.
+ *
+ * @param distributionID SDC Distribution ID
+ * @param status Distribution status
+ * @param errorReason Reason of failure
+ */
+ public void sendResponseStatusBackToSDC(String distributionID, DistributionStatusEnum status, String errorReason) {
+
+ final IDistributionClient distributionClient = sdcListenerDto.getDistributionClient();
+
+ IFinalDistrStatusMessage finalDistribution = new BuilderUtil<>(new DistributionStatusMessage())
+ .build(builder -> {
+ builder.distributionID = distributionID;
+ builder.status = status;
+ builder.consumerID = consumerId;
+ builder.componentName = COMPONENT_NAME;
+ }).create();
+
+ if (errorReason == null) {
+ checkResponseStatusFromSdc(distributionClient.sendFinalDistrStatus(finalDistribution));
+ } else {
+ checkResponseStatusFromSdc(distributionClient.sendFinalDistrStatus(finalDistribution, errorReason));
+ }
+ }
+
+ private void checkResponseStatusFromSdc(IDistributionClientResult result) {
+ if (!Objects.equals(result.getDistributionActionResult(), SUCCESS)) {
+ LOGGER.error("SDC failed to receive the response from cds-sdc listener due to {}",
+ result.getDistributionMessageResult());
+ } else {
+ LOGGER.info("SDC successfully received the response");
+ }
+ }
+}
diff --git a/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/util/BuilderUtil.java b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/util/BuilderUtil.java
new file mode 100644
index 000000000..1f546d107
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/util/BuilderUtil.java
@@ -0,0 +1,33 @@
+/*
+ * 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.sdclistener.util;
+
+import java.util.function.Consumer;
+
+/**
+ * A generic builder for constructing an object.
+ *
+ * @param <T> - Any object
+ */
+public class BuilderUtil<T> {
+
+ private final T object;
+
+ public BuilderUtil(T instance) {
+ this.object = instance;
+ }
+
+ public BuilderUtil<T> build(Consumer<T> consumer) {
+ consumer.accept(object);
+ return this;
+ }
+
+ public T create() {
+ return object;
+ }
+}
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
new file mode 100644
index 000000000..967e854d7
--- /dev/null
+++ b/ms/sdclistener/application/src/main/java/org/onap/ccsdk/cds/sdclistener/util/FileUtil.java
@@ -0,0 +1,61 @@
+/*
+ * 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.sdclistener.util;
+
+import static java.nio.file.Files.walk;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class FileUtil {
+ private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class);
+
+ private FileUtil() {
+
+ }
+
+ /**
+ * Delete the file.
+ *
+ * @param file - Given file
+ * @param path - Given path
+ */
+ public static void deleteFile(File file, String path) {
+ boolean value = file.delete();
+ if (!value) {
+ LOGGER.error("Failed to delete the file {} at the location {}", file, path);
+ }
+ }
+
+ /**
+ * Extract files from the given path
+ *
+ * @param path where files reside.
+ * @return list of files.
+ */
+ public static Optional<List<File>> getFilesFromDisk(Path path) {
+ try (Stream<Path> 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 due to", e);
+ }
+ return Optional.empty();
+ }
+}
diff --git a/ms/sdclistener/application/src/main/resources/application.yml b/ms/sdclistener/application/src/main/resources/application.yml
new file mode 100644
index 000000000..b3f8443eb
--- /dev/null
+++ b/ms/sdclistener/application/src/main/resources/application.yml
@@ -0,0 +1,27 @@
+listenerservice:
+ config:
+ asdcAddress: ${asdcAddress:localhost:8443}
+ messageBusAddress: ${messageBusAddress:localhost}
+ user: ${sdcusername:vid}
+ password: ${password:Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U}
+ pollingInterval: ${pollingInterval:15}
+ pollingTimeout: ${pollingTimeout:60}
+ relevantArtifactTypes: ${relevantArtifactTypes:TOSCA_CSAR}
+ consumerGroup: ${consumerGroup:cds-id-local}
+ environmentName: ${environmentName:AUTO}
+ consumerId: ${consumerId:cds-id-local}
+ keyStorePassword: ${keyStorePassword}
+ keyStorePath: ${keyStorePath}
+ activateServerTLSAuth : ${activateServerTLSAuth:false}
+ isUseHttpsWithDmaap: ${isUseHttpsWithDmaap:false}
+ archivePath: ${archivePath:/opt/app/onap/cds-sdc-listener/}
+ grpcAddress: ${grpcAddress:localhost}
+ grpcPort: ${grpcPort:9111}
+ authHeader: ${authHeader:Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==}
+#port needed by Liveness probe
+server:
+ port: ${healthcheckPort:9000}
+#set spring.main.web-environment=false if you want to NOT to open a port for healthcheck.
+spring:
+ main:
+ web-environment: ${sprintWebListenerEnabled:true}
diff --git a/ms/sdclistener/application/src/main/resources/logback.xml b/ms/sdclistener/application/src/main/resources/logback.xml
new file mode 100644
index 000000000..b26cbcbe4
--- /dev/null
+++ b/ms/sdclistener/application/src/main/resources/logback.xml
@@ -0,0 +1,33 @@
+<!--
+Copyright (C) 2019 Bell Canada
+
+Unless otherwise specified, all software contained herein is licensed
+under the Apache License, Version 2.0 (the License);
+you may not use this software 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.
+-->
+
+<configuration>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <root level="info">
+ <appender-ref ref="STDOUT"/>
+ </root>
+
+ <logger name="org.springframework" level="info"/>
+ <logger name="org.springframework.web" level="info"/>
+ <logger name="org.onap.ccsdk.cds" level="info"/>
+
+</configuration>
diff --git a/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerClientTest.java b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerClientTest.java
new file mode 100644
index 000000000..c9f2c5a39
--- /dev/null
+++ b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerClientTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener;
+
+import mockit.Expectations;
+import mockit.Injectable;
+import mockit.Mock;
+import mockit.MockUp;
+import mockit.Tested;
+import mockit.VerificationsInOrder;
+import mockit.integration.junit4.JMockit;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.ccsdk.cds.sdclistener.client.SdcListenerClient;
+import org.onap.ccsdk.cds.sdclistener.dto.SdcListenerDto;
+import org.onap.ccsdk.cds.sdclistener.exceptions.SdcListenerException;
+import org.onap.sdc.api.IDistributionClient;
+import org.onap.sdc.api.results.IDistributionClientResult;
+import org.onap.sdc.impl.DistributionClientFactory;
+import org.onap.sdc.impl.DistributionClientResultImpl;
+import org.onap.sdc.utils.DistributionActionResultEnum;
+
+@RunWith(JMockit.class)
+public class SdcListenerClientTest {
+
+ @Tested
+ private SdcListenerClient sdcListenerClient;
+
+ @Test
+ public void testInitCdsClientSuccesfully(@Injectable IDistributionClient distributionClient,
+ @Injectable SdcListenerConfiguration configuration,
+ @Injectable SdcListenerNotificationCallback notification,
+ @Injectable SdcListenerDto sdcListenerDto) throws SdcListenerException {
+
+ //Arrange
+ new MockUp<DistributionClientFactory>() {
+ @Mock
+ public IDistributionClient createDistributionClient() {
+ return distributionClient;
+ }
+ };
+
+ new Expectations() {{
+ distributionClient.init(configuration, notification);
+ result = getResult();
+ }};
+
+ new Expectations() {{
+ distributionClient.start();
+ result = getResult();
+ }};
+
+ // Act
+ sdcListenerClient.initSdcClient();
+
+ // Verify
+ new VerificationsInOrder() {{
+ distributionClient.init(configuration, notification);
+ distributionClient.start();
+ }};
+ }
+
+ public IDistributionClientResult getResult() {
+ return new DistributionClientResultImpl(DistributionActionResultEnum.SUCCESS,
+ DistributionActionResultEnum.SUCCESS.name());
+ }
+}
diff --git a/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfigurationTest.java b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfigurationTest.java
new file mode 100644
index 000000000..01ffe1ba9
--- /dev/null
+++ b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfigurationTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+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(SdcListenerConfiguration.class)
+@SpringBootTest(classes = {SdcListenerConfigurationTest.class})
+public class SdcListenerConfigurationTest {
+
+ @Autowired
+ private SdcListenerConfiguration listenerConfiguration;
+
+ @Test
+ public void testCdsSdcListenerConfiguration() {
+ assertEquals(listenerConfiguration.getAsdcAddress(), "localhost:8443");
+ assertEquals(listenerConfiguration.getMsgBusAddress().stream().findFirst().get(), "localhost");
+ assertEquals(listenerConfiguration.getUser(), "vid");
+ assertEquals(listenerConfiguration.getPassword(), "Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U");
+ assertEquals(listenerConfiguration.getPollingInterval(), 15);
+ assertEquals(listenerConfiguration.getPollingTimeout(), 60);
+ assertEquals(listenerConfiguration.getRelevantArtifactTypes().stream().findFirst().get(), "TOSCA_CSAR");
+ assertEquals(listenerConfiguration.getConsumerGroup(), "cds-id-local");
+ assertEquals(listenerConfiguration.getEnvironmentName(), "AUTO");
+ assertEquals(listenerConfiguration.getConsumerID(), "cds-id-local");
+ assertEquals(listenerConfiguration.activateServerTLSAuth(), false);
+ }
+}
diff --git a/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/handler/BluePrintProcessorHandlerTest.java b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/handler/BluePrintProcessorHandlerTest.java
new file mode 100644
index 000000000..ee20f8771
--- /dev/null
+++ b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/handler/BluePrintProcessorHandlerTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener.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.sdclistener.client.SdcListenerAuthClientInterceptor;
+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, SdcListenerAuthClientInterceptor.class})
+@SpringBootTest(classes = {BluePrintProcessorHandlerTest.class})
+public class BluePrintProcessorHandlerTest {
+
+ @Autowired
+ private BluePrintProcesssorHandler bluePrintProcesssorHandler;
+
+ @Autowired
+ private SdcListenerAuthClientInterceptor sdcListenerAuthClientInterceptor;
+
+ @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<BluePrintManagementOutput> 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/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
new file mode 100644
index 000000000..f5ff2bdb8
--- /dev/null
+++ b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/service/ListenerServiceImplTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.sdclistener.service;
+
+import static junit.framework.TestCase.assertTrue;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+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.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.onap.ccsdk.cds.sdclistener.SdcListenerConfiguration;
+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.sdc.api.results.IDistributionClientDownloadResult;
+import org.onap.sdc.impl.mock.DistributionClientResultStubImpl;
+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({SdcListenerAuthClientInterceptor.class,
+ BluePrintProcesssorHandler.class, SdcListenerDto.class, ListenerServiceImpl.class, SdcListenerStatus.class,
+ SdcListenerConfiguration.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
+ public TemporaryFolder folder = new TemporaryFolder();
+
+ @Autowired
+ private ListenerServiceImpl listenerService;
+
+ @Before
+ public void setup() {
+ csarArchivePath = folder.getRoot().toString();
+ tempDirectoryPath = Paths.get(csarArchivePath, "cds-sdc-listener-test");
+ }
+ @Test
+ 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
+ DistributionClientDownloadResultStubImpl resultStub = new DistributionClientDownloadResultStubImpl();
+
+ // Act
+ 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();
+ }
+
+ public byte[] convertFileToByteArray(File file) {
+ try {
+ return FileUtils.readFileToByteArray(file);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public class DistributionClientDownloadResultStubImpl extends DistributionClientResultStubImpl implements
+ IDistributionClientDownloadResult {
+
+ public DistributionClientDownloadResultStubImpl() {
+ }
+
+ public byte[] getArtifactPayload() {
+ File file = Paths.get(CSAR_SAMPLE).toFile();
+ return convertFileToByteArray(file);
+ }
+
+ public String getArtifactName() {
+ return "MackArtifactName";
+ }
+
+ public String getArtifactFilename() {
+ return "MackArtifactName.csar";
+ }
+ }
+}
diff --git a/ms/sdclistener/application/src/test/resources/service-Testsvc140.csar b/ms/sdclistener/application/src/test/resources/service-Testsvc140.csar
new file mode 100644
index 000000000..4aa0de72b
--- /dev/null
+++ b/ms/sdclistener/application/src/test/resources/service-Testsvc140.csar
Binary files differ
diff --git a/ms/sdclistener/application/src/test/resources/testcba.zip b/ms/sdclistener/application/src/test/resources/testcba.zip
new file mode 100644
index 000000000..c886fe6bc
--- /dev/null
+++ b/ms/sdclistener/application/src/test/resources/testcba.zip
Binary files differ
diff --git a/ms/sdclistener/distribution/pom.xml b/ms/sdclistener/distribution/pom.xml
new file mode 100755
index 000000000..a79a14c52
--- /dev/null
+++ b/ms/sdclistener/distribution/pom.xml
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright © 2019 IBM, Bell Canada.
+ ~
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.ccsdk.cds.sdclistener</groupId>
+ <artifactId>parent</artifactId>
+ <version>0.4.2-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+ <artifactId>distribution</artifactId>
+ <packaging>pom</packaging>
+ <name>SDC Listener Distribution</name>
+ <properties>
+ <assembly.id>maven</assembly.id>
+ <name.space>org.onap.ccsdk.cds</name.space>
+ <serviceArtifactName>sdclistener</serviceArtifactName>
+ <image.name>onap/ccsdk-sdclistener</image.name>
+ <!--disabled for now to mirror #85964 https://gerrit.onap.org/r/#/c/85964/2/ms/command-executor/pom.xml-->
+ <!--<docker.buildArg.https_proxy>${https_proxy}</docker.buildArg.https_proxy>-->
+ <docker.push.phase>deploy</docker.push.phase>
+ <docker.verbose>true</docker.verbose>
+ <ccsdk.project.version>${project.version}</ccsdk.project.version>
+ <ccsdk.build.timestamp>${maven.build.timestamp}</ccsdk.build.timestamp>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.sdclistener</groupId>
+ <artifactId>application</artifactId>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-dockerfile</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/docker-stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/docker</directory>
+ <includes>
+ <include>*</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>ant-test</id>
+ <phase>package</phase>
+ <configuration>
+ <tasks>
+ <fixcrlf srcdir="${basedir}" eol="unix" includes="**/*.sh, **/*.source"/>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <!--build the final artifact for docker deployment -->
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>3.1.0</version>
+ <configuration>
+ <!-- <skipAssembly>${skip.assembly}</skipAssembly> -->
+ <outputDirectory>${basedir}/target/docker-stage</outputDirectory>
+ <descriptors>
+ <descriptor>src/main/docker/distribution.xml</descriptor>
+ </descriptors>
+ <tarLongFileMode>posix</tarLongFileMode>
+ </configuration>
+ <executions>
+ <execution>
+ <id>${assembly.id}</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.groovy.maven</groupId>
+ <artifactId>gmaven-plugin</artifactId>
+ <version>1.0</version>
+ <executions>
+ <execution>
+ <phase>validate</phase>
+ <goals>
+ <goal>execute</goal>
+ </goals>
+ <configuration>
+ <source>${basedir}/../../../TagVersion.groovy</source>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>docker</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <version>0.26.1</version>
+ <inherited>false</inherited>
+ <configuration>
+ <images>
+ <image>
+ <name>${image.name}</name>
+ <build>
+ <cleanup>try</cleanup>
+ <dockerFileDir>${basedir}/target/docker-stage</dockerFileDir>
+ <tags>
+ <tag>${project.docker.latestminortag.version}</tag>
+ <tag>${project.docker.latestfulltag.version}</tag>
+ <tag>${project.docker.latesttagtimestamp.version}</tag>
+ </tags>
+ </build>
+ </image>
+ </images>
+ <verbose>true</verbose>
+ </configuration>
+ <executions>
+ <execution>
+ <id>generate-images</id>
+ <phase>package</phase>
+ <goals>
+ <goal>build</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>push-images</id>
+ <phase>${docker.push.phase}</phase>
+ <goals>
+ <goal>build</goal>
+ <goal>push</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/ms/sdclistener/distribution/src/main/dc/docker-compose.yaml b/ms/sdclistener/distribution/src/main/dc/docker-compose.yaml
new file mode 100755
index 000000000..1c68f6cf3
--- /dev/null
+++ b/ms/sdclistener/distribution/src/main/dc/docker-compose.yaml
@@ -0,0 +1,29 @@
+version: '3.3'
+
+services:
+ cds-sdc-listener:
+ image: onap/ccsdk-sdclistener:latest
+ container_name: cdssdclistener
+ restart: always
+ environment:
+ asdcAddress: localhost:8443
+ messageBusAddress: localhost
+ sdcusername: vid
+ password: Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U
+ pollingInterval: 15
+ pollingTimeout: 15
+ relevantArtifactTypes: TOSCA_CSAR
+ consumerGroup: cds-id-local
+ environmentName: AUTO
+ consumerId: cds-id-local
+ keyStorePassword:
+ keyStorePath:
+ activateServerTLSAuth: "false"
+ isUseHttpsWithDmaap: "false"
+ archivePath: /opt/app/onap/cds-sdc-listener/
+ grpcAddress: localhost
+ grpcPort: 9111
+ authHeader: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==
+ #port needed by Liveness probe
+ healthcheckPort: "9000"
+ sprintWebListenerEnabled: "true"
diff --git a/ms/sdclistener/distribution/src/main/docker/Dockerfile b/ms/sdclistener/distribution/src/main/docker/Dockerfile
new file mode 100755
index 000000000..e945188a8
--- /dev/null
+++ b/ms/sdclistener/distribution/src/main/docker/Dockerfile
@@ -0,0 +1,16 @@
+FROM openjdk:8-jdk-alpine
+
+ENV HTTP_PROXY ${HTTP_PROXY}
+ENV HTTPS_PROXY ${HTTPS_PROXY}
+
+# add entrypoint
+COPY startService.sh /startService.sh
+RUN chmod 751 /startService.sh
+# add application
+COPY @project.build.finalName@-@assembly.id@.tar.gz /source.tar.gz
+RUN tar -xzf /source.tar.gz -C /tmp \
+ && cp -rf /tmp/@project.build.finalName@/opt / \
+ && rm -rf /source.tar.gz \
+ && rm -rf /tmp/@project.build.finalName@
+
+ENTRYPOINT /startService.sh
diff --git a/ms/sdclistener/distribution/src/main/docker/distribution.xml b/ms/sdclistener/distribution/src/main/docker/distribution.xml
new file mode 100755
index 000000000..e9e8eefa5
--- /dev/null
+++ b/ms/sdclistener/distribution/src/main/docker/distribution.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright © 2018-2019 Bell Canada.
+ ~
+ ~ 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.
+ -->
+
+<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
+ <!-- create a tar.gz file containing the projects dependencies -->
+ <id>${assembly.id}</id>
+ <formats>
+ <format>tar.gz</format>
+ </formats>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>/opt/app/onap/lib</outputDirectory>
+ <outputFileNameMapping>${artifact.groupId}-${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
+ <excludes>
+ <exclude>org.slf4j:slf4j-simple</exclude>
+ </excludes>
+ </dependencySet>
+ </dependencySets>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}/../application/src/main/resources</directory>
+ <includes>
+ <include>application.properties</include>
+ <include>application.yml</include>
+ <include>logback.xml</include>
+ </includes>
+ <outputDirectory>/opt/app/onap/config</outputDirectory>
+ <useDefaultExcludes>true</useDefaultExcludes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/ms/sdclistener/distribution/src/main/docker/startService.sh b/ms/sdclistener/distribution/src/main/docker/startService.sh
new file mode 100644
index 000000000..7ad6171b8
--- /dev/null
+++ b/ms/sdclistener/distribution/src/main/docker/startService.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+echo "Starting SDC Listener"
+
+export APP_HOME=/opt/app/onap
+export APP_CONFIG_HOME=${APP_HOME}/config
+echo "APP Config HOME : ${APP_CONFIG_HOME}"
+
+java -classpath "/etc:${APP_HOME}/lib/*:/lib/*:/src:/schema:/generated-sources:${APP_CONFIG_HOME}:${APP_HOME}" \
+-Dlogging.config=${APP_CONFIG_HOME}/logback.xml \
+-Djava.security.egd=file:/dev/./urandom \
+-Dspring.config.location=${APP_CONFIG_HOME}/ \
+org.onap.ccsdk.cds.sdclistener.SdcListenerApplication
diff --git a/ms/sdclistener/parent/pom.xml b/ms/sdclistener/parent/pom.xml
new file mode 100755
index 000000000..fabdc2530
--- /dev/null
+++ b/ms/sdclistener/parent/pom.xml
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright © 2017-2018 AT&T Intellectual Property.
+ ~
+ ~ Modifications Copyright © 2018 - 2019 IBM, Bell Canada
+ ~
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.ccsdk.cds</groupId>
+ <artifactId>sdclistener</artifactId>
+ <version>0.4.2-SNAPSHOT</version>
+ </parent>
+ <groupId>org.onap.ccsdk.cds.sdclistener</groupId>
+ <artifactId>parent</artifactId>
+ <packaging>pom</packaging>
+ <name>SDC Listener Parent</name>
+ <description>SDC Listener Parent</description>
+ <properties>
+ <spring.boot.version>2.1.3.RELEASE</spring.boot.version>
+ <spring.version>5.1.5.RELEASE</spring.version>
+ <grpc.version>1.18.0</grpc.version>
+ <protobuff.java.utils.version>3.6.1</protobuff.java.utils.version>
+ <eelf.version>1.0.0</eelf.version>
+ <sli.version>0.4.2-SNAPSHOT</sli.version>
+ <guava.version>27.0.1-jre</guava.version>
+ <onap.logger.slf4j>1.2.2</onap.logger.slf4j>
+ <powermock.version>1.7.4</powermock.version>
+ <mockk.version>1.9</mockk.version>
+ <dmaap.client.version>1.1.5</dmaap.client.version>
+ <mockkserver.version>5.5.1</mockkserver.version>
+ <sdc-distribution-client.version>1.3.0</sdc-distribution-client.version>
+ <jmockit.version>1.19</jmockit.version>
+ <reactorcore.version>3.2.6.RELEASE</reactorcore.version>
+ </properties>
+ <dependencyManagement>
+ <dependencies>
+ <!-- Spring Boot -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-parent</artifactId>
+ <version>${spring.boot.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+
+ <!-- Common Utils Dependencies -->
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ <version>3.2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-compress</artifactId>
+ <version>1.15</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ </dependency>
+
+ <!-- GRPC Dependencies -->
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-core</artifactId>
+ <version>${grpc.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-netty</artifactId>
+ <version>${grpc.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-protobuf</artifactId>
+ <version>${grpc.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-stub</artifactId>
+ <version>${grpc.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java</artifactId>
+ <version>${protobuff.java.utils.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.components</groupId>
+ <artifactId>proto-definition</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.projectreactor</groupId>
+ <artifactId>reactor-core</artifactId>
+ <version>${reactorcore.version}</version>
+ </dependency>
+
+ <!-- Blueprint Processor Application Module Dependencies -->
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+ <artifactId>processor-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+ <artifactId>db-lib</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+ <artifactId>rest-lib</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+ <artifactId>dmaap-lib</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+ <artifactId>grpc-lib</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+ <artifactId>execution-service</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+ <artifactId>workflow-service</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+ <artifactId>resource-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+ <artifactId>selfservice-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+ <artifactId>application</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ <!-- Controller Blueprints Application Dependency -->
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
+ <artifactId>resource-dict</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
+ <artifactId>blueprint-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
+ <artifactId>blueprint-scripts</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
+ <artifactId>db-resources</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
+ <artifactId>blueprint-validation</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Test Dependency -->
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-testing</artifactId>
+ <version>${grpc.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jmockit</groupId>
+ <artifactId>jmockit</artifactId>
+ <version>${jmockit.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- SDC Distribution client dependency -->
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.sdclistener</groupId>
+ <artifactId>application</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.sdc.sdc-distribution-client</groupId>
+ <artifactId>sdc-distribution-client</artifactId>
+ <version>${sdc-distribution-client.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.5.1</version>
+ <configuration>
+ <source>${maven.compiler.source}</source>
+ <target>${maven.compiler.target}</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ms/sdclistener/pom.xml b/ms/sdclistener/pom.xml
new file mode 100644
index 000000000..70e8529f6
--- /dev/null
+++ b/ms/sdclistener/pom.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Copyright (C) 2019 Bell Canada
+ *
+ * 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.ccsdk.cds</groupId>
+ <artifactId>ms</artifactId>
+ <version>0.4.2-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <artifactId>sdclistener</artifactId>
+ <name>SDC Listener Root</name>
+ <description>SDC Listener Root</description>
+ <packaging>pom</packaging>
+
+ <properties>
+ <service.name>sdclistener</service.name>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format>
+ <build.number>${maven.build.timestamp}</build.number>
+ <java.version>1.8</java.version>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <ccsdk.project.version>${project.version}</ccsdk.project.version>
+ </properties>
+
+ <modules>
+ <module>parent</module>
+ <module>application</module>
+ <module>distribution</module>
+ </modules>
+
+</project>