Add CDS client 01/79201/4
authorAlexis de Talhouët <adetalhouet89@gmail.com>
Tue, 26 Feb 2019 16:26:03 +0000 (11:26 -0500)
committerAlexis de Talhouët <adetalhouet89@gmail.com>
Tue, 26 Feb 2019 22:03:45 +0000 (17:03 -0500)
Change-Id: I3f77a2c9e8341239b97675f5897cecf28c7dfb6f
Issue-ID: SO-1483
Signed-off-by: Alexis de Talhouët <adetalhouet89@gmail.com>
12 files changed:
bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/InjectionHelper.java
bpmn/MSOCommonBPMN/src/main/java/org/onap/so/client/restproperties/CDSPropertiesImpl.java [new file with mode: 0644]
bpmn/MSOCommonBPMN/src/main/resources/META-INF/services/org.onap.so.client.RestProperties
common/pom.xml
common/src/main/java/org/onap/so/client/cds/CDSProcessingClient.java [new file with mode: 0644]
common/src/main/java/org/onap/so/client/cds/CDSProcessingHandler.java [new file with mode: 0644]
common/src/main/java/org/onap/so/client/cds/CDSProcessingListener.java [new file with mode: 0644]
common/src/main/java/org/onap/so/client/cds/CDSProperties.java [new file with mode: 0644]
common/src/test/java/org/onap/so/client/cds/CDSProcessingClientTest.java [new file with mode: 0644]
common/src/test/java/org/onap/so/client/cds/TestCDSProcessingListener.java [new file with mode: 0644]
common/src/test/java/org/onap/so/client/cds/TestCDSPropertiesImpl.java [new file with mode: 0644]
common/src/test/resources/META-INF/services/org.onap.so.client.RestProperties [new file with mode: 0644]

index deae46c..adf1dc0 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
@@ -24,6 +24,8 @@ import org.onap.so.client.aai.AAICommonObjectMapperProvider;
 import org.onap.so.client.aai.AAIQueryClient;
 import org.onap.so.client.aai.AAIResourcesClient;
 import org.onap.so.client.aai.entities.AAIResultWrapper;
+import org.onap.so.client.cds.CDSProcessingClient;
+import org.onap.so.client.cds.CDSProcessingListener;
 import org.onap.so.client.policy.PolicyClientImpl;
 import org.onap.so.client.sdno.SDNOValidator;
 import org.onap.so.client.sdno.SDNOValidatorImpl;
@@ -32,14 +34,14 @@ import org.springframework.stereotype.Component;
 /*
  * This object is intended to be a helper for acquiring classes
  * that cannot be acquired via Spring injection.
- * 
+ *
  * It brings two benefits:
- * 
+ *
  * 1) Enforces acquisition of a new copy of these classes every
  *    time to help with picking up properties files changes, etc
  * 2) The classes are exposed in such a way that mocks of them can
  *    still be injected when testing the Spring objects that use
- *    them 
+ *    them
  */
 
 @Component
@@ -47,11 +49,11 @@ public class InjectionHelper {
        public AAIResourcesClient getAaiClient() {
                return new AAIResourcesClient();
        }
-       
+
        public AAIQueryClient getAaiQueryClient() {
                return new AAIQueryClient();
        }
-       
+
        public SDNOValidator getSdnoValidator() {
                return new SDNOValidatorImpl();
        }
@@ -59,12 +61,16 @@ public class InjectionHelper {
        public AAICommonObjectMapperProvider getAaiCommonObjectMapperProvider() {
                return new AAICommonObjectMapperProvider();
        }
-       
+
        public AAIResultWrapper getAaiResultWrapper(String json) {
                return new AAIResultWrapper(json);
        }
-       
+
        public PolicyClientImpl getPolicyClient() {
                return new PolicyClientImpl();
        }
+
+       public CDSProcessingClient getCdsClient(CDSProcessingListener listener) {
+               return new CDSProcessingClient(listener);
+       }
 }
diff --git a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/client/restproperties/CDSPropertiesImpl.java b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/client/restproperties/CDSPropertiesImpl.java
new file mode 100644 (file)
index 0000000..b8ab588
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+package org.onap.so.client.restproperties;
+
+import java.net.URL;
+import java.util.Objects;
+import org.onap.so.bpmn.core.UrnPropertiesReader;
+import org.onap.so.client.cds.CDSProperties;
+
+public class CDSPropertiesImpl implements CDSProperties {
+
+    private static final String ENDPOINT = "cds.endpoint";
+    private static final String PORT = "cds.port";
+
+    public CDSPropertiesImpl() {
+        // Needed for service loader
+    }
+
+    @Override
+    public String getHost() {
+        return Objects.requireNonNull(UrnPropertiesReader.getVariable(ENDPOINT));
+    }
+
+    @Override
+    public int getPort() {
+        return Integer.parseInt(Objects.requireNonNull(UrnPropertiesReader.getVariable(PORT)));
+    }
+
+    @Override
+    public URL getEndpoint() {
+        return null;
+    }
+
+    @Override
+    public String getSystemName() {
+        return "MSO";
+    }
+
+    @Override
+    public Integer getRetries() {
+        return null;
+    }
+
+    @Override
+    public Long getDelayBetweenRetries() {
+        return null;
+    }
+
+    @Override
+    public boolean mapNotFoundToEmpty() {
+        return false;
+    }
+}
index bdc72c8..27da189 100644 (file)
@@ -1,2 +1,3 @@
 org.onap.so.client.restproperties.AAIPropertiesImpl
+org.onap.so.client.restproperties.CDSPropertiesImpl
 org.onap.so.client.restproperties.PolicyRestPropertiesImpl
\ No newline at end of file
index 6bd142d..7772453 100644 (file)
 <?xml version="1.0"?>
-<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>
+<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.so</groupId>
         <artifactId>so</artifactId>
         <version>1.4.0-SNAPSHOT</version>
-       </parent>
-       <artifactId>common</artifactId>
-       <name>MSO Common classes</name>
-       <description>MSO Common classes:- Logger</description>
-       <dependencies>
-               <dependency>
-                       <groupId>org.apache.httpcomponents</groupId>
-                       <artifactId>httpclient</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>javax.servlet</groupId>
-                       <artifactId>javax.servlet-api</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.springframework</groupId>
-                       <artifactId>spring-aspects</artifactId>
-               </dependency>
-               <dependency>
+    </parent>
+    <artifactId>common</artifactId>
+    <name>MSO Common classes</name>
+    <description>MSO Common classes:- Logger</description>
+
+    <properties>
+        <grpc.version>1.17.1</grpc.version>
+        <protobuf.version>3.6.1</protobuf.version>
+        <grpc.netty.version>4.1.30.Final</grpc.netty.version>
+        <ccsdk.version>0.4.1-SNAPSHOT</ccsdk.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aspects</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-security</artifactId>
         </dependency>
-               <dependency>
+        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
         </dependency>
-               <dependency>
-                       <groupId>com.jayway.jsonpath</groupId>
-                       <artifactId>json-path</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.hibernate</groupId>
-                       <artifactId>hibernate-core</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.springframework</groupId>
-                       <artifactId>spring-web</artifactId>
-               </dependency>
-               <dependency>
-               <groupId>org.springframework</groupId>
-               <artifactId>spring-webmvc</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.onap.aai.schema-service</groupId>
-                       <artifactId>aai-schema</artifactId>
-                       <version>1.0.0-SNAPSHOT</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.modelmapper</groupId>
-                       <artifactId>modelmapper</artifactId>
-                       <version>1.1.0</version>
-               </dependency>
-               <dependency>
-                       <groupId>com.google.guava</groupId>
-                       <artifactId>guava</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.apache.commons</groupId>
-                       <artifactId>commons-lang3</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.apache.cxf</groupId>
-                       <artifactId>cxf-rt-rs-client</artifactId>
-                       <version>${cxf.version}</version>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>com.shazam</groupId>
-                       <artifactId>shazamcrest</artifactId>
-                       <version>0.11</version>
-                       <scope>test</scope>
-                       <exclusions>
-                               <exclusion>
-                                       <groupId>com.google.guava</groupId>
-                                       <artifactId>guava</artifactId>
-                               </exclusion>
-                               <exclusion>
-                                       <groupId>org.apache.commons</groupId>
-                                       <artifactId>commons-lang3</artifactId>
-                               </exclusion>
-                       </exclusions>
-               </dependency>
-               <dependency>
-                       <groupId>org.slf4j</groupId>
-                       <artifactId>slf4j-ext</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.slf4j</groupId>
-                       <artifactId>slf4j-api</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.springframework.boot</groupId>
-                       <artifactId>spring-boot-configuration-processor</artifactId>
-                       <optional>true</optional>
-               </dependency>
-               <dependency>
-                       <groupId>net.jodah</groupId>
-                       <artifactId>failsafe</artifactId>
-                       <version>1.1.0</version>
-               </dependency>
+        <dependency>
+            <groupId>com.jayway.jsonpath</groupId>
+            <artifactId>json-path</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.aai.schema-service</groupId>
+            <artifactId>aai-schema</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.modelmapper</groupId>
+            <artifactId>modelmapper</artifactId>
+            <version>1.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-rs-client</artifactId>
+            <version>${cxf.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.shazam</groupId>
+            <artifactId>shazamcrest</artifactId>
+            <version>0.11</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.guava</groupId>
+                    <artifactId>guava</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.commons</groupId>
+                    <artifactId>commons-lang3</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-ext</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>net.jodah</groupId>
+            <artifactId>failsafe</artifactId>
+            <version>1.1.0</version>
+        </dependency>
         <dependency>
             <groupId>org.springframework.security</groupId>
             <artifactId>spring-security-web</artifactId>
         </dependency>
-               <dependency>
-                       <groupId>org.onap.logging-analytics</groupId>
-                       <artifactId>logging-slf4j</artifactId>
-                       <version>1.2.2</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.mockito</groupId>
-                       <artifactId>mockito-core</artifactId>
-               </dependency>
-               <dependency>
-                               <groupId>org.json</groupId>
-                               <artifactId>json</artifactId>
-                       </dependency>
-               <dependency>
-                       <groupId>org.springframework.boot</groupId>
-                       <artifactId>spring-boot-starter-test</artifactId>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.reflections</groupId>
-                       <artifactId>reflections</artifactId>
-                       <version>0.9.11</version>
-               </dependency>
+        <dependency>
+            <groupId>org.onap.logging-analytics</groupId>
+            <artifactId>logging-slf4j</artifactId>
+            <version>1.2.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.json</groupId>
+            <artifactId>json</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.reflections</groupId>
+            <artifactId>reflections</artifactId>
+            <version>0.9.11</version>
+        </dependency>
+
+        <!-- CDS dependencies -->
+        <dependency>
+            <groupId>org.onap.ccsdk.apps.components</groupId>
+            <artifactId>proto-definition</artifactId>
+            <version>${ccsdk.version}</version>
+        </dependency>
+
+        <!-- protobuf dependencies -->
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+            <version>${protobuf.version}</version>
+        </dependency>
+
+        <!-- gRPC dependencies -->
+        <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-protobuf</artifactId>
+            <version>${grpc.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.code.findbugs</groupId>
+                    <artifactId>jsr305</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-stub</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-testing</artifactId>
+            <version>${grpc.version}</version>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
-       <build>
-               <resources>
-                       <resource>
-                               <directory>src/main/resources</directory>
-                               <filtering>true</filtering>
-                       </resource>
-                       <resource>
-                               <directory>src/main/java</directory>
-                               <includes>
-                                       <include>**/*.java</include>
-                               </includes>
-                       </resource>
-               </resources>
-               <plugins>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-surefire-plugin</artifactId>
-                               <executions>
-                                       <execution>
-                                               <id>default-test</id>
-                                               <goals>
-                                                       <goal>test</goal>
-                                               </goals>
-                                               <configuration>
-                                                       <includes>
-                                                               <include>**/NonSpringSuite.java</include>
-                                                       </includes>     
-                                               </configuration>
-                                       </execution>
-                                       <execution>
-                                               <id>spring-tests</id>
-                                               <goals>
-                                                       <goal>test</goal>
-                                               </goals>
-                                               <configuration>
-                                                       <includes>
-                                                               <include>**/SpringSuite.java</include>
-                                                       </includes>     
-                                               </configuration>
-                                       </execution>
-                               </executions>
-                       </plugin>
-               </plugins>      
-       </build>
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+            <resource>
+                <directory>src/main/java</directory>
+                <includes>
+                    <include>**/*.java</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>default-test</id>
+                        <goals>
+                            <goal>test</goal>
+                        </goals>
+                        <configuration>
+                            <includes>
+                                <include>**/NonSpringSuite.java</include>
+                            </includes>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>spring-tests</id>
+                        <goals>
+                            <goal>test</goal>
+                        </goals>
+                        <configuration>
+                            <includes>
+                                <include>**/SpringSuite.java</include>
+                            </includes>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
 </project>
diff --git a/common/src/main/java/org/onap/so/client/cds/CDSProcessingClient.java b/common/src/main/java/org/onap/so/client/cds/CDSProcessingClient.java
new file mode 100644 (file)
index 0000000..0901cf5
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+package org.onap.so.client.cds;
+
+import io.grpc.ManagedChannel;
+import io.grpc.internal.DnsNameResolverProvider;
+import io.grpc.internal.PickFirstLoadBalancerProvider;
+import io.grpc.netty.NettyChannelBuilder;
+import java.util.concurrent.CountDownLatch;
+import org.onap.ccsdk.apps.controllerblueprints.processing.api.ExecutionServiceInput;
+import org.onap.so.client.PreconditionFailedException;
+import org.onap.so.client.RestPropertiesLoader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <p>
+ * The CDS processing client is using gRPC for communication between SO and CDS.
+ * That communication is configured to use a streaming approach, meaning that
+ * client can send an event to which server can reply will multiple sub-responses,
+ * until full completion of the processing.
+ * </p>
+ * <p>
+ * In order for the caller to manage the callback, it is the responsibility of the
+ * caller to implement and provide a {@link CDSProcessingListener} so received messages
+ * can be handled appropriately.
+ * </p>
+ *
+ * Here is an example of implementation of such listener:
+ * <pre>
+ * new CDSProcessingListener {
+ *
+ *     &#64;Override
+ *     public void onMessage(ExecutionServiceOutput message) {
+ *         log.info("Received notification from CDS: {}", message);
+ *     }
+ *
+ *     &#64;Override
+ *     public void onError(Throwable t) {
+ *         Status status = Status.fromThrowable(t);
+ *         log.error("Failed processing blueprint {}", status, t);
+ *     }
+ * }
+ * </pre>
+ */
+public class CDSProcessingClient implements AutoCloseable {
+
+    private static final Logger log = LoggerFactory.getLogger(CDSProcessingClient.class);
+
+    private ManagedChannel channel;
+    private CDSProcessingHandler handler;
+
+    public CDSProcessingClient(final CDSProcessingListener listener) {
+        CDSProperties props = RestPropertiesLoader.getInstance().getNewImpl(CDSProperties.class);
+        if (props == null) {
+            throw new PreconditionFailedException(
+                "No RestProperty.CDSProperties implementation found on classpath, can't create client.");
+        }
+        this.channel = NettyChannelBuilder
+            .forAddress(props.getHost(), props.getPort())
+            .nameResolverFactory(new DnsNameResolverProvider())
+            .loadBalancerFactory(new PickFirstLoadBalancerProvider())
+            .usePlaintext()
+            .build();
+        this.handler = new CDSProcessingHandler(listener);
+        log.info("CDSProcessingClient started");
+    }
+
+    CDSProcessingClient(final ManagedChannel channel, final CDSProcessingHandler handler) {
+        this.channel = channel;
+        this.handler = handler;
+    }
+
+    /**
+     * Sends a request to the CDS backend micro-service.
+     *
+     * The caller will be returned a CountDownLatch that can be used
+     * to define how long the processing can wait. The CountDownLatch is
+     * initiated with just 1 count. When the client receives an #onCompleted callback,
+     * the counter will decrement.
+     *
+     * It is the user responsibility to close the client.
+     *
+     * @param input request to send
+     * @return CountDownLatch instance that can be use to #await for
+     * completeness of processing
+     */
+    public CountDownLatch sendRequest(ExecutionServiceInput input) {
+        return handler.process(input, channel);
+    }
+
+    @Override
+    public void close() {
+        if (channel != null) {
+            channel.shutdown();
+        }
+        log.info("CDSProcessingClient stopped");
+    }
+}
\ No newline at end of file
diff --git a/common/src/main/java/org/onap/so/client/cds/CDSProcessingHandler.java b/common/src/main/java/org/onap/so/client/cds/CDSProcessingHandler.java
new file mode 100644 (file)
index 0000000..244b89a
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+package org.onap.so.client.cds;
+
+import io.grpc.ManagedChannel;
+import io.grpc.stub.StreamObserver;
+import java.util.concurrent.CountDownLatch;
+import org.onap.ccsdk.apps.controllerblueprints.common.api.ActionIdentifiers;
+import org.onap.ccsdk.apps.controllerblueprints.processing.api.BluePrintProcessingServiceGrpc;
+import org.onap.ccsdk.apps.controllerblueprints.processing.api.BluePrintProcessingServiceGrpc.BluePrintProcessingServiceStub;
+import org.onap.ccsdk.apps.controllerblueprints.processing.api.ExecutionServiceInput;
+import org.onap.ccsdk.apps.controllerblueprints.processing.api.ExecutionServiceOutput;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class CDSProcessingHandler {
+
+    private static final Logger log = LoggerFactory.getLogger(CDSProcessingHandler.class);
+
+    private CDSProcessingListener listener;
+
+    CDSProcessingHandler(final CDSProcessingListener listener) {
+        this.listener = listener;
+    }
+
+    CountDownLatch process(ExecutionServiceInput request, ManagedChannel channel) {
+
+        ActionIdentifiers header = request.getActionIdentifiers();
+
+        log.info("Processing blueprint({}:{}) for action({})", header.getBlueprintVersion(), header.getBlueprintName(),
+            header.getBlueprintVersion());
+
+        final CountDownLatch finishLatch = new CountDownLatch(1);
+
+        final BluePrintProcessingServiceStub asyncStub = BluePrintProcessingServiceGrpc.newStub(channel);
+
+        final StreamObserver<ExecutionServiceOutput> responseObserver = new StreamObserver<ExecutionServiceOutput>() {
+            @Override
+            public void onNext(ExecutionServiceOutput output) {
+                listener.onMessage(output);
+            }
+
+            @Override
+            public void onError(Throwable t) {
+                listener.onError(t);
+                finishLatch.countDown();
+            }
+
+            @Override
+            public void onCompleted() {
+                log.info("Completed blueprint({}:{}) for action({})", header.getBlueprintVersion(),
+                    header.getBlueprintName(), header.getBlueprintVersion());
+                finishLatch.countDown();
+            }
+        };
+
+        final StreamObserver<ExecutionServiceInput> requestObserver = asyncStub.process(responseObserver);
+
+        try {
+            // Send our message to CDS backend for processing
+            requestObserver.onNext(request);
+            // Mark the end of requests
+            requestObserver.onCompleted();
+        } catch (RuntimeException e) {
+            requestObserver.onError(e);
+        }
+        return finishLatch;
+    }
+}
\ No newline at end of file
diff --git a/common/src/main/java/org/onap/so/client/cds/CDSProcessingListener.java b/common/src/main/java/org/onap/so/client/cds/CDSProcessingListener.java
new file mode 100644 (file)
index 0000000..2eae4ef
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+package org.onap.so.client.cds;
+
+import org.onap.ccsdk.apps.controllerblueprints.processing.api.ExecutionServiceOutput;
+
+public interface CDSProcessingListener {
+
+    void onMessage(ExecutionServiceOutput message);
+
+    void onError(Throwable t);
+}
diff --git a/common/src/main/java/org/onap/so/client/cds/CDSProperties.java b/common/src/main/java/org/onap/so/client/cds/CDSProperties.java
new file mode 100644 (file)
index 0000000..bb2a54e
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+package org.onap.so.client.cds;
+
+import org.onap.so.client.RestProperties;
+
+
+public interface CDSProperties extends RestProperties {
+
+    String getHost();
+    int getPort();
+}
diff --git a/common/src/test/java/org/onap/so/client/cds/CDSProcessingClientTest.java b/common/src/test/java/org/onap/so/client/cds/CDSProcessingClientTest.java
new file mode 100644 (file)
index 0000000..2bfa754
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+package org.onap.so.client.cds;
+
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import io.grpc.inprocess.InProcessChannelBuilder;
+import io.grpc.inprocess.InProcessServerBuilder;
+import io.grpc.stub.StreamObserver;
+import io.grpc.testing.GrpcCleanupRule;
+import io.grpc.util.MutableHandlerRegistry;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.onap.ccsdk.apps.controllerblueprints.common.api.ActionIdentifiers;
+import org.onap.ccsdk.apps.controllerblueprints.processing.api.BluePrintProcessingServiceGrpc.BluePrintProcessingServiceImplBase;
+import org.onap.ccsdk.apps.controllerblueprints.processing.api.ExecutionServiceInput;
+import org.onap.ccsdk.apps.controllerblueprints.processing.api.ExecutionServiceOutput;
+
+@RunWith(JUnit4.class)
+public class CDSProcessingClientTest {
+
+    @Rule
+    public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
+
+    @Mock
+    private CDSProcessingListener listener = spy(new TestCDSProcessingListener());
+
+    private CDSProcessingHandler handler;
+    private CDSProcessingClient client;
+
+
+    private final MutableHandlerRegistry serviceRegistry = new MutableHandlerRegistry();
+    private final List<String> messagesDelivered = new ArrayList<>();
+    private final CountDownLatch allRequestsDelivered = new CountDownLatch(1);
+    private final AtomicReference<StreamObserver<ExecutionServiceOutput>> responseObserverRef = new AtomicReference<>();
+
+    @Before
+    public void setUp() throws Exception {
+        String serverName = InProcessServerBuilder.generateName();
+        grpcCleanup.register(InProcessServerBuilder.forName(serverName)
+            .fallbackHandlerRegistry(serviceRegistry).directExecutor().build().start());
+
+        handler = new CDSProcessingHandler(listener);
+
+        client =
+            new CDSProcessingClient(InProcessChannelBuilder.forName(serverName).directExecutor().build(), handler);
+
+        final BluePrintProcessingServiceImplBase routeChatImpl =
+            new BluePrintProcessingServiceImplBase() {
+                @Override
+                public StreamObserver<ExecutionServiceInput> process(
+                    StreamObserver<ExecutionServiceOutput> responseObserver) {
+
+                    responseObserverRef.set(responseObserver);
+
+                    StreamObserver<ExecutionServiceInput> requestObserver = new StreamObserver<ExecutionServiceInput>() {
+                        @Override
+                        public void onNext(ExecutionServiceInput message) {
+                            messagesDelivered.add(message.getActionIdentifiers().getActionName());
+                        }
+
+                        @Override
+                        public void onError(Throwable t) {
+
+                        }
+
+                        @Override
+                        public void onCompleted() {
+                            allRequestsDelivered.countDown();
+                        }
+                    };
+
+                    return requestObserver;
+                }
+            };
+
+        serviceRegistry.addService(routeChatImpl);
+    }
+
+    @After
+    public void tearDown() {
+        client.close();
+    }
+
+    @Test
+    public void testClientCst() {
+        new CDSProcessingClient(listener);
+    }
+
+
+    @Test
+    public void testSendMessageFail() throws Exception {
+
+        ExecutionServiceInput fakeRequest1 = ExecutionServiceInput.newBuilder().setActionIdentifiers(
+            ActionIdentifiers.newBuilder().setActionName("request1").build()).build();
+
+        CountDownLatch finishLatch = client.sendRequest(fakeRequest1);
+
+        responseObserverRef.get().onError(new Throwable("fail test"));
+        verify(listener).onError(any(Throwable.class));
+
+        assertTrue(finishLatch.await(1, TimeUnit.SECONDS));
+    }
+
+    @Test
+    public void testSendMessage() throws Exception {
+
+        ExecutionServiceInput fakeRequest1 = ExecutionServiceInput.newBuilder().setActionIdentifiers(
+            ActionIdentifiers.newBuilder().setActionName("request1").build()).build();
+
+        ExecutionServiceOutput fakeResponse1 = ExecutionServiceOutput.newBuilder().setActionIdentifiers(
+            ActionIdentifiers.newBuilder().setActionName("response1").build()).build();
+
+        ExecutionServiceOutput fakeResponse2 = ExecutionServiceOutput.newBuilder().setActionIdentifiers(
+            ActionIdentifiers.newBuilder().setActionName("response2").build()).build();
+
+        CountDownLatch finishLatch = client.sendRequest(fakeRequest1);
+
+        // request message sent and delivered for one time
+        assertTrue(allRequestsDelivered.await(1, TimeUnit.SECONDS));
+        assertEquals(Collections.singletonList("request1"), messagesDelivered);
+
+        // Let the server send out two simple response messages
+        // and verify that the client receives them.
+        responseObserverRef.get().onNext(fakeResponse1);
+        verify(listener).onMessage(fakeResponse1);
+        responseObserverRef.get().onNext(fakeResponse2);
+        verify(listener).onMessage(fakeResponse2);
+
+        // let server complete.
+        responseObserverRef.get().onCompleted();
+
+        assertTrue(finishLatch.await(1, TimeUnit.SECONDS));
+    }
+
+}
\ No newline at end of file
diff --git a/common/src/test/java/org/onap/so/client/cds/TestCDSProcessingListener.java b/common/src/test/java/org/onap/so/client/cds/TestCDSProcessingListener.java
new file mode 100644 (file)
index 0000000..df302f6
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+package org.onap.so.client.cds;
+
+import io.grpc.Status;
+import org.onap.ccsdk.apps.controllerblueprints.processing.api.ExecutionServiceOutput;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestCDSProcessingListener implements CDSProcessingListener {
+
+    private static final Logger log = LoggerFactory.getLogger(TestCDSProcessingListener.class);
+
+    @Override
+    public void onMessage(ExecutionServiceOutput message) {
+        log.info("Received notification from CDS: {}", message);
+    }
+
+    @Override
+    public void onError(Throwable t) {
+        Status status = Status.fromThrowable(t);
+        log.error("Failed processing blueprint {}", status, t);
+    }
+}
diff --git a/common/src/test/java/org/onap/so/client/cds/TestCDSPropertiesImpl.java b/common/src/test/java/org/onap/so/client/cds/TestCDSPropertiesImpl.java
new file mode 100644 (file)
index 0000000..efb9b07
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package org.onap.so.client.cds;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+public class TestCDSPropertiesImpl implements CDSProperties {
+
+    public TestCDSPropertiesImpl() {
+        // Needed for service loader
+    }
+
+    @Override
+    public String getHost() {
+        return "endpoint";
+    }
+
+    @Override
+    public int getPort() {
+        return 9999;
+    }
+
+    @Override
+    public URL getEndpoint() {
+        return null;
+    }
+
+    @Override
+    public String getSystemName() {
+        return "MSO";
+    }
+
+    @Override
+    public Integer getRetries() {
+        return null;
+    }
+
+    @Override
+    public Long getDelayBetweenRetries() {
+        return null;
+    }
+
+    @Override
+    public boolean mapNotFoundToEmpty() {
+        return false;
+    }
+}
diff --git a/common/src/test/resources/META-INF/services/org.onap.so.client.RestProperties b/common/src/test/resources/META-INF/services/org.onap.so.client.RestProperties
new file mode 100644 (file)
index 0000000..6a5105d
--- /dev/null
@@ -0,0 +1 @@
+org.onap.so.client.cds.TestCDSPropertiesImpl
\ No newline at end of file