From f46af3394f85598eaa718f22312f9b7a6485c636 Mon Sep 17 00:00:00 2001 From: "a.sreekumar" Date: Fri, 20 Mar 2020 18:30:43 +0000 Subject: Adding example for APEX gRPC plugin for CDS interaction Change-Id: I8361eb0cbe74c3548ca98f3005bc37f5a1f91747 Issue-ID: POLICY-2436 Signed-off-by: a.sreekumar --- .../examples/grpc/GrpcTestDummyGrpcServer.java | 95 ++++++++++++++++++++++ .../examples/grpc/GrpcTestRestSimEndpoint.java | 93 +++++++++++++++++++++ .../apex/examples/grpc/GrpcTestServerSim.java | 73 +++++++++++++++++ .../apex/examples/grpc/TestApexGrpcExample.java | 85 +++++++++++++++++++ 4 files changed, 346 insertions(+) create mode 100644 examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestDummyGrpcServer.java create mode 100644 examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestRestSimEndpoint.java create mode 100644 examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestServerSim.java create mode 100644 examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java (limited to 'examples/examples-grpc/src/test') diff --git a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestDummyGrpcServer.java b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestDummyGrpcServer.java new file mode 100644 index 000000000..bef0a81c8 --- /dev/null +++ b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestDummyGrpcServer.java @@ -0,0 +1,95 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.policy.apex.examples.grpc; + +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.util.JsonFormat; +import io.grpc.Server; +import io.grpc.netty.NettyServerBuilder; +import io.grpc.stub.StreamObserver; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.Paths; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.BluePrintProcessingServiceGrpc.BluePrintProcessingServiceImplBase; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput.Builder; +import org.onap.policy.apex.service.engine.event.ApexEventRuntimeException; + +/** + * The Class GrpcTestDummyGrpcServer creates a dummy gRPC server to mimic a CDS implementation. + */ +public class GrpcTestDummyGrpcServer { + private Server server; + + public GrpcTestDummyGrpcServer(String host, int port) { + // Implement the dummy gRPC server + BluePrintProcessingServiceImplBase testCdsBlueprintServerImpl = new BluePrintProcessingServiceImplBase() { + @Override + public StreamObserver process( + final StreamObserver responseObserver) { + return new StreamObserver() { + @Override + public void onNext(final ExecutionServiceInput executionServiceInput) { + String responseString = ""; + try { + responseString = Files.readString(Paths.get( + "src/main/resources/examples/events/APEXgRPC/CreateSubscriptionResponseEvent.json")); + } catch (IOException e) { + throw new ApexEventRuntimeException("Cannot read executionServiceOutput from file", e); + } + ExecutionServiceOutput executionServiceOutput; + Builder builder = ExecutionServiceOutput.newBuilder(); + try { + JsonFormat.parser().ignoringUnknownFields().merge(responseString, builder); + executionServiceOutput = builder.build(); + responseObserver.onNext(executionServiceOutput); + } catch (InvalidProtocolBufferException e) { + throw new ApexEventRuntimeException( + "Output string cannot be converted to ExecutionServiceOutput type for gRPC request." + + e); + } + } + + @Override + public void onError(final Throwable throwable) { + responseObserver.onError(throwable); + } + + @Override + public void onCompleted() { + responseObserver.onCompleted(); + } + }; + } + }; + server = NettyServerBuilder.forAddress(new InetSocketAddress(host, port)).addService(testCdsBlueprintServerImpl) + .build(); + } + + public void start() throws IOException { + server.start(); + } + + public void stop() { + server.shutdown(); + } +} diff --git a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestRestSimEndpoint.java b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestRestSimEndpoint.java new file mode 100644 index 000000000..4e88afe83 --- /dev/null +++ b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestRestSimEndpoint.java @@ -0,0 +1,93 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.examples.grpc; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; +import org.slf4j.ext.XLogger; +import org.slf4j.ext.XLoggerFactory; + +/** + * The Class GrpcTestRestSimEndpoint creates rest server endpoints for simulating sending/receiving events on DMaaP. + */ +@Path("/sim") +public class GrpcTestRestSimEndpoint { + private static final XLogger LOGGER = XLoggerFactory.getXLogger(GrpcTestRestSimEndpoint.class); + private static String loggedOutputEvent = null; + private final Object lock = new Object(); + + /** + * DCAE input of events (simulation of DMaaP). This input event triggers the policy + * + * @param timeout the timeout to wait for + * @return the response + * @throws IOException on I/O errors + */ + @Path("events/unauthenticated.DCAE_CL_OUTPUT/APEX/1") + @GET + public Response dcaeClOutput(@QueryParam("timeout") final int timeout) throws IOException { + String createSubscriptionRequest = + Files.readString(Paths.get("src/main/resources/examples/events/APEXgRPC/CreateSubscriptionEvent.json")); + LOGGER.info("Create subscription request received: \n {}", createSubscriptionRequest); + + return Response.status(200).entity(createSubscriptionRequest).build(); + } + + /** + * Post to Policy management log (Simulation of DMaaP). + * + * @param jsonString the json string + * @return the response + */ + @Path("/events/POLICY_CL_MGT") + @POST + public Response policyLogRequest(final String jsonString) { + LOGGER.info("\n*** POLICY LOG ENTRY START ***\n {} \n *** POLICY LOG ENTRY END ***", jsonString); + synchronized (lock) { + loggedOutputEvent = jsonString; + } + return Response.status(200).build(); + } + + /** + * Get the logged event for test verification. + * + * @return the response + */ + @Path("/event/getLoggedEvent") + @GET + public Response getDetails() { + String loggedEvent; + synchronized (lock) { + loggedEvent = loggedOutputEvent; + } + if (null == loggedEvent) { + return Response.status(500).entity("Error: Log event not yet generated.").build(); + } + return Response.status(200).entity(loggedEvent).build(); + } +} diff --git a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestServerSim.java b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestServerSim.java new file mode 100644 index 000000000..ae35d1ff2 --- /dev/null +++ b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestServerSim.java @@ -0,0 +1,73 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.examples.grpc; + +import java.io.IOException; +import org.onap.policy.common.endpoints.http.server.HttpServletServer; +import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; +import org.onap.policy.common.gson.GsonMessageBodyHandler; +import org.onap.policy.common.utils.network.NetworkUtil; + +/** + * The Class GrpcTestServerSim that manages test servers for REST and gRPC requests for the test. + */ +public class GrpcTestServerSim { + private static final String HOST = "localhost"; + private HttpServletServer restServer; + private GrpcTestDummyGrpcServer grpcServer; + + /** + * Instantiates a new REST simulator for DMaaP requests. + * + * @throws InterruptedException interrupted exception + * @throws IOException io exception + */ + public GrpcTestServerSim() throws InterruptedException, IOException { + int restServerPort = 54321; + restServer = HttpServletServerFactoryInstance.getServerFactory().build("GrpcTestRestSimEndpoint", false, HOST, + restServerPort, "/GrpcTestRestSim", false, false); + restServer.addServletClass(null, GrpcTestRestSimEndpoint.class.getName()); + restServer.setSerializationProvider(GsonMessageBodyHandler.class.getName()); + restServer.start(); + if (!NetworkUtil.isTcpPortOpen(HOST, restServerPort, 2000, 1L)) { + throw new IllegalStateException("port " + restServerPort + " is still not in use"); + } + + int grpcServerPort = 54322; + grpcServer = new GrpcTestDummyGrpcServer(HOST, grpcServerPort); + grpcServer.start(); + if (!NetworkUtil.isTcpPortOpen(HOST, grpcServerPort, 2000, 1L)) { + throw new IllegalStateException("port " + grpcServerPort + " is still not in use"); + } + } + + /** + * Tear down. + */ + public void tearDown() { + if (restServer != null) { + restServer.stop(); + } + if (grpcServer != null) { + grpcServer.stop(); + } + } +} diff --git a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java new file mode 100644 index 000000000..06d1d33f9 --- /dev/null +++ b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java @@ -0,0 +1,85 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.policy.apex.examples.grpc; + +import static org.awaitility.Awaitility.await; +import static org.junit.Assert.assertEquals; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.concurrent.TimeUnit; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.Response; +import org.junit.Test; +import org.onap.policy.apex.auth.clieditor.ApexCommandLineEditorMain; +import org.onap.policy.apex.service.engine.main.ApexMain; + +/** + * Test class to run an example policy for APEX-CDS interaction over gRPC. + * Event received on unauthenticated.DCAE_CL_OUTPUT DMaaP topic (dummy REST Endpoint here) triggers the policy + * Based on the event, a create/delete subscription gRPC request is triggered to the CDS (a dummy gRPC server here). + * Response received from CDS is used to send a final output Log event on POLICY_CL_MGT topic. + */ +public class TestApexGrpcExample { + @Test + public void testGrpcExample() throws Exception { + // @formatter:off + final String[] cliArgs = new String[] { + "-c", + "src/main/resources/policy/APEXgRPCPolicy.apex", + "-l", + "target/APEXgRPCPolicyModel.log", + "-o", + "target/classes/APEXgRPCPolicy.json" + }; + // @formatter:on + + new ApexCommandLineEditorMain(cliArgs); + + // @formatter:off + final String[] apexArgs = { + "-rfr", + "target/classes", + "-c", + "src/main/resources/examples/config/APEXgRPC/ApexConfig.json", + "-m", + "target/classes/APEXgRPCPolicy.json" + }; + // @formatter:on + + GrpcTestServerSim sim = new GrpcTestServerSim(); + final Client client = ClientBuilder.newClient(); + String expectedLoggedOutputEvent = Files + .readString(Paths.get("src/main/resources/examples/events/APEXgRPC/LogEvent.json")).replaceAll("\r", ""); + final ApexMain apexMain = new ApexMain(apexArgs); + + String getLoggedEventUrl = "http://localhost:54321/GrpcTestRestSim/sim/event/getLoggedEvent"; + // wait for success response code to be received, until a timeout + await().atMost(5000, TimeUnit.MILLISECONDS).until(() -> { + return 200 == client.target(getLoggedEventUrl).request("application/json").get().getStatus(); + }); + apexMain.shutdown(); + Response response = client.target(getLoggedEventUrl).request("application/json").get(); + sim.tearDown(); + String responseEntity = response.readEntity(String.class); + assertEquals(expectedLoggedOutputEvent, responseEntity); + } +} -- cgit 1.2.3-korg