From 3d8fc9a77081886599cc93acd26105b433770b43 Mon Sep 17 00:00:00 2001 From: rameshiyer27 Date: Fri, 5 Nov 2021 14:24:02 +0000 Subject: Add health check, metrics and prometheus endpoints for CL participants Issue-ID: POLICY-3747 Signed-off-by: zrrmmua Change-Id: I9cb1ffcc2f9996c5b0e9f67fec9c706e48cfa800 --- .../participant/http/config/SecurityConfig.java | 45 ++++++ .../src/main/resources/config/application.yaml | 16 +++ .../test/java/handler/ClElementHandlerTest.java | 77 ----------- .../http/handler/ClElementHandlerTest.java | 78 +++++++++++ .../http/rest/ActuatorControllerTest.java | 92 +++++++++++++ .../http/utils/CommonActuatorController.java | 114 ++++++++++++++++ .../participant/http/utils/CommonTestData.java | 152 +++++++++++++++++++++ .../participant/http/utils/ToscaUtils.java | 51 +++++++ .../http/webclient/ClHttpClientTest.java | 129 +++++++++++++++++ .../src/test/java/utils/CommonTestData.java | 152 --------------------- .../src/test/java/utils/ToscaUtils.java | 51 ------- .../src/test/java/webclient/ClHttpClientTest.java | 129 ----------------- .../src/test/resources/application_test.properties | 24 ++++ .../src/main/resources/config/application.yaml | 6 +- .../kubernetes/rest/ActuatorControllerTest.java | 92 +++++++++++++ .../kubernetes/utils/CommonActuatorController.java | 114 ++++++++++++++++ .../src/test/resources/application_test.properties | 5 +- .../participant/policy/config/SecurityConfig.java | 45 ++++++ .../src/main/resources/config/application.yaml | 16 ++- .../policy/main/rest/ActuatorControllerTest.java | 92 +++++++++++++ .../main/utils/CommonActuatorController.java | 114 ++++++++++++++++ .../src/test/resources/application_test.properties | 6 +- participant/pom.xml | 11 ++ 23 files changed, 1193 insertions(+), 418 deletions(-) create mode 100644 participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/config/SecurityConfig.java delete mode 100644 participant/participant-impl/participant-impl-http/src/test/java/handler/ClElementHandlerTest.java create mode 100644 participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/handler/ClElementHandlerTest.java create mode 100644 participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/rest/ActuatorControllerTest.java create mode 100644 participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/utils/CommonActuatorController.java create mode 100644 participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/utils/CommonTestData.java create mode 100644 participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/utils/ToscaUtils.java create mode 100644 participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/webclient/ClHttpClientTest.java delete mode 100644 participant/participant-impl/participant-impl-http/src/test/java/utils/CommonTestData.java delete mode 100644 participant/participant-impl/participant-impl-http/src/test/java/utils/ToscaUtils.java delete mode 100644 participant/participant-impl/participant-impl-http/src/test/java/webclient/ClHttpClientTest.java create mode 100644 participant/participant-impl/participant-impl-http/src/test/resources/application_test.properties create mode 100644 participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/controlloop/participant/kubernetes/rest/ActuatorControllerTest.java create mode 100644 participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/controlloop/participant/kubernetes/utils/CommonActuatorController.java create mode 100644 participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/controlloop/participant/policy/config/SecurityConfig.java create mode 100644 participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/rest/ActuatorControllerTest.java create mode 100644 participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/utils/CommonActuatorController.java (limited to 'participant') diff --git a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/config/SecurityConfig.java b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/config/SecurityConfig.java new file mode 100644 index 000000000..499bbe153 --- /dev/null +++ b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/config/SecurityConfig.java @@ -0,0 +1,45 @@ +/*- + * ========================LICENSE_START================================= + * Copyright (C) 2021 Nordix Foundation. All rights reserved. + * ====================================================================== + * 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. + * ========================LICENSE_END=================================== + */ + +package org.onap.policy.clamp.controlloop.participant.http.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Value("${security.enable-csrf:true}") + private boolean csrfEnabled = true; + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers().authenticated() + .anyRequest().authenticated() + .and().httpBasic(); + // @formatter:on + + if (!csrfEnabled) { + http.csrf().disable(); + } + } +} diff --git a/participant/participant-impl/participant-impl-http/src/main/resources/config/application.yaml b/participant/participant-impl/participant-impl-http/src/main/resources/config/application.yaml index 664c6e878..df0ad7df3 100644 --- a/participant/participant-impl/participant-impl-http/src/main/resources/config/application.yaml +++ b/participant/participant-impl/participant-impl-http/src/main/resources/config/application.yaml @@ -1,3 +1,10 @@ +spring: + security: + user: + name: participantUser + password: zb!XztG34 +security: + enable-csrf: false participant: intermediaryParameters: reportingTimeIntervalMs: 120000 @@ -20,3 +27,12 @@ participant: servers: - ${topicServer:message-router} topicCommInfrastructure: dmaap +management: + endpoints: + web: + exposure: + include: health, metrics, prometheus +server: + port: 8084 + servlet: + context-path: /onap/httpparticipant diff --git a/participant/participant-impl/participant-impl-http/src/test/java/handler/ClElementHandlerTest.java b/participant/participant-impl/participant-impl-http/src/test/java/handler/ClElementHandlerTest.java deleted file mode 100644 index d1556ea08..000000000 --- a/participant/participant-impl/participant-impl-http/src/test/java/handler/ClElementHandlerTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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 handler; - -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; - -import java.util.Map; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement; -import org.onap.policy.clamp.controlloop.participant.http.main.handler.ControlLoopElementHandler; -import org.onap.policy.clamp.controlloop.participant.intermediary.api.ParticipantIntermediaryApi; -import org.onap.policy.common.utils.coder.CoderException; -import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; -import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import utils.CommonTestData; -import utils.ToscaUtils; - -@ExtendWith(SpringExtension.class) -class ClElementHandlerTest { - - @InjectMocks - @Spy - private ControlLoopElementHandler controlLoopElementHandler = new ControlLoopElementHandler(); - - @Mock - private ParticipantIntermediaryApi participantIntermediaryApi; - - private CommonTestData commonTestData = new CommonTestData(); - - private static ToscaServiceTemplate serviceTemplate; - private static final String HTTP_CONTROL_LOOP_ELEMENT = - "org.onap.domain.database.Http_PMSHMicroserviceControlLoopElement"; - - @BeforeAll - static void init() throws CoderException { - serviceTemplate = ToscaUtils.readControlLoopFromTosca(); - } - - @Test - void test_ControlLoopElementUpdate() { - doNothing().when(controlLoopElementHandler).invokeHttpClient(any()); - ControlLoopElement element = commonTestData.getControlLoopElement(); - - Map nodeTemplatesMap = - serviceTemplate.getToscaTopologyTemplate().getNodeTemplates(); - - assertDoesNotThrow(() -> controlLoopElementHandler - .controlLoopElementUpdate(commonTestData.getControlLoopId(), element, - nodeTemplatesMap.get(HTTP_CONTROL_LOOP_ELEMENT))); - } -} diff --git a/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/handler/ClElementHandlerTest.java b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/handler/ClElementHandlerTest.java new file mode 100644 index 000000000..d80436ef3 --- /dev/null +++ b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/handler/ClElementHandlerTest.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.clamp.controlloop.participant.http.handler; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; + +import java.util.Map; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement; +import org.onap.policy.clamp.controlloop.participant.http.main.handler.ControlLoopElementHandler; +import org.onap.policy.clamp.controlloop.participant.http.utils.CommonTestData; +import org.onap.policy.clamp.controlloop.participant.http.utils.ToscaUtils; +import org.onap.policy.clamp.controlloop.participant.intermediary.api.ParticipantIntermediaryApi; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; +import org.springframework.test.context.junit.jupiter.SpringExtension; + + +@ExtendWith(SpringExtension.class) +class ClElementHandlerTest { + + @InjectMocks + @Spy + private ControlLoopElementHandler controlLoopElementHandler = new ControlLoopElementHandler(); + + @Mock + private ParticipantIntermediaryApi participantIntermediaryApi; + + private CommonTestData commonTestData = new CommonTestData(); + + private static ToscaServiceTemplate serviceTemplate; + private static final String HTTP_CONTROL_LOOP_ELEMENT = + "org.onap.domain.database.Http_PMSHMicroserviceControlLoopElement"; + + @BeforeAll + static void init() throws CoderException { + serviceTemplate = ToscaUtils.readControlLoopFromTosca(); + } + + @Test + void test_ControlLoopElementUpdate() { + doNothing().when(controlLoopElementHandler).invokeHttpClient(any()); + ControlLoopElement element = commonTestData.getControlLoopElement(); + + Map nodeTemplatesMap = + serviceTemplate.getToscaTopologyTemplate().getNodeTemplates(); + + assertDoesNotThrow(() -> controlLoopElementHandler + .controlLoopElementUpdate(commonTestData.getControlLoopId(), element, + nodeTemplatesMap.get(HTTP_CONTROL_LOOP_ELEMENT))); + } +} diff --git a/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/rest/ActuatorControllerTest.java b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/rest/ActuatorControllerTest.java new file mode 100644 index 000000000..8efff8f6a --- /dev/null +++ b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/rest/ActuatorControllerTest.java @@ -0,0 +1,92 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.clamp.controlloop.participant.http.rest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.Response; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.onap.policy.clamp.controlloop.participant.http.utils.CommonActuatorController; +import org.springframework.boot.test.autoconfigure.actuate.metrics.AutoConfigureMetrics; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@AutoConfigureMetrics +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@TestPropertySource(locations = {"classpath:application_test.properties"}) +class ActuatorControllerTest extends CommonActuatorController { + + private static final String HEALTH_ENDPOINT = "health"; + private static final String METRICS_ENDPOINT = "metrics"; + private static final String PROMETHEUS_ENDPOINT = "prometheus"; + + @LocalServerPort + private int randomServerPort; + + @BeforeEach + public void setUpPort() { + super.setHttpPrefix(randomServerPort); + } + + @Test + void testGetHealth_Unauthorized() throws Exception { + assertUnauthorizedActGet(HEALTH_ENDPOINT); + } + + @Test + void testGetMetrics_Unauthorized() throws Exception { + assertUnauthorizedActGet(METRICS_ENDPOINT); + } + + @Test + void testGetPrometheus_Unauthorized() throws Exception { + assertUnauthorizedActGet(PROMETHEUS_ENDPOINT); + } + + @Test + void testGetHealth() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(HEALTH_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + + @Test + void testGetMetrics() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(METRICS_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + + @Test + void testGePrometheus() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(PROMETHEUS_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + +} diff --git a/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/utils/CommonActuatorController.java b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/utils/CommonActuatorController.java new file mode 100644 index 000000000..5ebce8126 --- /dev/null +++ b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/utils/CommonActuatorController.java @@ -0,0 +1,114 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.clamp.controlloop.participant.http.utils; + +import static org.junit.Assert.assertEquals; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; +import org.onap.policy.common.gson.GsonMessageBodyHandler; +import org.onap.policy.common.utils.network.NetworkUtil; + +/** + * Class to perform Rest unit tests. + * + */ +public class CommonActuatorController { + + public static final String SELF = NetworkUtil.getHostname(); + public static final String CONTEXT_PATH = "onap/httpparticipant"; + public static final String ACTUATOR_ENDPOINT = CONTEXT_PATH + "/actuator/"; + + private static String httpPrefix; + + /** + * Sends a request to an actuator endpoint. + * + * @param endpoint the target endpoint + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendActRequest(final String endpoint) throws Exception { + return sendFqeRequest(httpPrefix + ACTUATOR_ENDPOINT + endpoint, true); + } + + /** + * Sends a request to an actuator endpoint, without any authorization header. + * + * @param endpoint the target endpoint + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendNoAuthActRequest(final String endpoint) throws Exception { + return sendFqeRequest(httpPrefix + ACTUATOR_ENDPOINT + endpoint, false); + } + + /** + * Sends a request to a fully qualified endpoint. + * + * @param fullyQualifiedEndpoint the fully qualified target endpoint + * @param includeAuth if authorization header should be included + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendFqeRequest(final String fullyQualifiedEndpoint, boolean includeAuth) + throws Exception { + final Client client = ClientBuilder.newBuilder().build(); + + client.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true"); + client.register(GsonMessageBodyHandler.class); + + if (includeAuth) { + client.register(HttpAuthenticationFeature.basic("participantUser", "zb!XztG34")); + } + + final WebTarget webTarget = client.target(fullyQualifiedEndpoint); + + return webTarget.request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN); + } + + /** + * Assert that GET call to actuator endpoint is Unauthorized. + * + * @param endPoint the endpoint + * @throws Exception if an error occurs + */ + protected void assertUnauthorizedActGet(final String endPoint) throws Exception { + Response rawresp = sendNoAuthActRequest(endPoint).buildGet().invoke(); + assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + } + + /** + * Set Up httpPrefix. + * + * @param port the port + */ + protected void setHttpPrefix(int port) { + httpPrefix = "http://" + SELF + ":" + port + "/"; + } + +} diff --git a/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/utils/CommonTestData.java b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/utils/CommonTestData.java new file mode 100644 index 000000000..1f92a86e0 --- /dev/null +++ b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/utils/CommonTestData.java @@ -0,0 +1,152 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.clamp.controlloop.participant.http.utils; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState; +import org.onap.policy.clamp.controlloop.participant.http.main.models.ConfigurationEntity; +import org.onap.policy.clamp.controlloop.participant.http.main.models.RestParams; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +public class CommonTestData { + + private static final String TEST_KEY_NAME = "org.onap.domain.database.Http_PMSHMicroserviceControlLoopElement"; + + + /** + * Get a controlLoop Element. + * @return controlLoopElement object + */ + public ControlLoopElement getControlLoopElement() { + ControlLoopElement element = new ControlLoopElement(); + element.setId(UUID.randomUUID()); + element.setDefinition(new ToscaConceptIdentifier(TEST_KEY_NAME, "1.0.1")); + element.setOrderedState(ControlLoopOrderedState.PASSIVE); + return element; + } + + /** + * Get query params. + * @return Map of query params + */ + public Map getQueryParams() { + return Map.of("name", "dummy", "version", "1.0"); + } + + /** + * Get path params. + * @return Map of path params + */ + public Map getPathParams() { + return Map.of("id", "123", "name", "dummy"); + } + + /** + * Rest params with GET request. + * @return RestParams obj + */ + public RestParams restParamsWithGet() { + return new RestParams( + new ToscaConceptIdentifier("getRequest", "1.0"), + "GET", + "get", + 200, + null, + getQueryParams(), + null + ); + } + + /** + * Rest params with POST request. + * @return RestParams obj + */ + public RestParams restParamsWithPost() { + return new RestParams( + new ToscaConceptIdentifier("postRequest", "1.0"), + "POST", + "post", + 200, + null, + getQueryParams(), + "Test body" + ); + } + + /** + * Rest params with POST request. + * @return RestParams obj + */ + public RestParams restParamsWithInvalidPost() { + return new RestParams( + new ToscaConceptIdentifier("postRequest", "1.0"), + "POST", + "post/{id}/{name}", + 200, + getPathParams(), + getQueryParams(), + "Test body" + ); + } + + /** + * Get invalid configuration entity. + * @return ConfigurationEntity obj + */ + public ConfigurationEntity getInvalidConfigurationEntity() { + return new ConfigurationEntity( + new ToscaConceptIdentifier("config1", "1.0.1"), + List.of(restParamsWithGet(), restParamsWithInvalidPost()) + ); + } + + /** + * Get configuration entity. + * @return ConfigurationEntity obj + */ + public ConfigurationEntity getConfigurationEntity() { + return new ConfigurationEntity( + new ToscaConceptIdentifier("config1", "1.0.1"), + List.of(restParamsWithGet(), restParamsWithPost()) + ); + } + + /** + * Get controlloop id. + * @return ToscaConceptIdentifier controlLoopId + */ + public ToscaConceptIdentifier getControlLoopId() { + return new ToscaConceptIdentifier("PMSHInstance0", "1.0.0"); + } + + /** + * Get headers for config request. + * @return Map of headers + */ + public Map getHeaders() { + return Map.of("Content-Type", "application/json", "Accept", "application/json"); + } + +} diff --git a/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/utils/ToscaUtils.java b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/utils/ToscaUtils.java new file mode 100644 index 000000000..fdba28c0e --- /dev/null +++ b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/utils/ToscaUtils.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.clamp.controlloop.participant.http.utils; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.onap.policy.common.utils.coder.YamlJsonTranslator; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; + +/** + * Util class for Test scope. + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class ToscaUtils { + + private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator(); + private static final String TOSCA_TEMPLATE_YAML = "src/test/resources/HttpParticipantConfig.yaml"; + + + /** + * Read a service template yaml. + * @return ToscaServiceTemplate + */ + public static ToscaServiceTemplate readControlLoopFromTosca() { + return serializeControlLoopYaml(TOSCA_TEMPLATE_YAML); + } + + private static ToscaServiceTemplate serializeControlLoopYaml(String controlLoopFilePath) { + String controlLoopString = ResourceUtils.getResourceAsString(controlLoopFilePath); + return yamlTranslator.fromYaml(controlLoopString, ToscaServiceTemplate.class); + } +} diff --git a/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/webclient/ClHttpClientTest.java b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/webclient/ClHttpClientTest.java new file mode 100644 index 000000000..e3ff9dbba --- /dev/null +++ b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/controlloop/participant/http/webclient/ClHttpClientTest.java @@ -0,0 +1,129 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.clamp.controlloop.participant.http.webclient; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.MediaType; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.Parameter; +import org.onap.policy.clamp.controlloop.participant.http.main.models.ConfigRequest; +import org.onap.policy.clamp.controlloop.participant.http.main.models.ConfigurationEntity; +import org.onap.policy.clamp.controlloop.participant.http.main.webclient.ClHttpClient; +import org.onap.policy.clamp.controlloop.participant.http.utils.CommonTestData; +import org.onap.policy.common.utils.network.NetworkUtil; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +class ClHttpClientTest { + + private static CommonTestData commonTestData; + + private static int mockServerPort; + + private String testMockUrl = "http://localhost"; + + private Map> responseMap = new HashMap<>(); + + private static ClientAndServer mockServer; + + /** + * Set up Mock server. + */ + @BeforeAll + static void setUpMockServer() throws IOException { + mockServerPort = NetworkUtil.allocPort(); + mockServer = ClientAndServer.startClientAndServer(mockServerPort); + commonTestData = new CommonTestData(); + List queryParams = new ArrayList<>(); + commonTestData.getQueryParams().forEach((k, v) -> queryParams.add(new Parameter(k, v))); + + mockServer.when(request().withMethod("GET").withPath("/get") + .withHeader("Content-type", MediaType.APPLICATION_JSON) + .withHeader("Accept", MediaType.APPLICATION_JSON).withQueryStringParameters(queryParams)) + .respond(response().withBody("dummy body").withStatusCode(200) + .withHeader("Content-Type", MediaType.APPLICATION_JSON)); + + mockServer.when(request().withMethod("POST").withPath("/post") + .withHeader("Content-type", MediaType.APPLICATION_JSON) + .withHeader("Accept", MediaType.APPLICATION_JSON).withQueryStringParameters(queryParams) + .withBody("Test body")) + .respond(response().withStatusCode(200)); + } + + @AfterAll + public static void stopServer() { + mockServer.stop(); + mockServer = null; + } + + + @Test + void test_validRequest() { + //Add valid rest requests POST, GET + ConfigurationEntity configurationEntity = commonTestData.getConfigurationEntity(); + + Map headers = commonTestData.getHeaders(); + ConfigRequest configRequest = new ConfigRequest(testMockUrl + ":" + mockServerPort, headers, + List.of(configurationEntity), 10); + + ClHttpClient client = new ClHttpClient(configRequest, responseMap); + assertDoesNotThrow(client::run); + assertThat(responseMap).hasSize(2).containsKey(commonTestData + .restParamsWithGet().getRestRequestId()); + + Pair restResponseMap = responseMap.get(commonTestData + .restParamsWithGet().getRestRequestId()); + assertThat(restResponseMap.getKey()).isEqualTo(200); + } + + @Test + void test_invalidRequest() { + //Add rest requests Invalid POST, Valid GET + ConfigurationEntity configurationEntity = commonTestData.getInvalidConfigurationEntity(); + + Map headers = commonTestData.getHeaders(); + ConfigRequest configRequest = new ConfigRequest(testMockUrl + ":" + mockServerPort, headers, + List.of(configurationEntity), 10); + + ClHttpClient client = new ClHttpClient(configRequest, responseMap); + assertDoesNotThrow(client::run); + assertThat(responseMap).hasSize(2).containsKey(commonTestData + .restParamsWithGet().getRestRequestId()); + Pair response = responseMap + .get(commonTestData.restParamsWithInvalidPost().getRestRequestId()); + assertThat(response.getKey()).isEqualTo(404); + } +} diff --git a/participant/participant-impl/participant-impl-http/src/test/java/utils/CommonTestData.java b/participant/participant-impl/participant-impl-http/src/test/java/utils/CommonTestData.java deleted file mode 100644 index 0ebf9212a..000000000 --- a/participant/participant-impl/participant-impl-http/src/test/java/utils/CommonTestData.java +++ /dev/null @@ -1,152 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation. - * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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 utils; - -import java.util.List; -import java.util.Map; -import java.util.UUID; -import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement; -import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState; -import org.onap.policy.clamp.controlloop.participant.http.main.models.ConfigurationEntity; -import org.onap.policy.clamp.controlloop.participant.http.main.models.RestParams; -import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; - -public class CommonTestData { - - private static final String TEST_KEY_NAME = "org.onap.domain.database.Http_PMSHMicroserviceControlLoopElement"; - - - /** - * Get a controlLoop Element. - * @return controlLoopElement object - */ - public ControlLoopElement getControlLoopElement() { - ControlLoopElement element = new ControlLoopElement(); - element.setId(UUID.randomUUID()); - element.setDefinition(new ToscaConceptIdentifier(TEST_KEY_NAME, "1.0.1")); - element.setOrderedState(ControlLoopOrderedState.PASSIVE); - return element; - } - - /** - * Get query params. - * @return Map of query params - */ - public Map getQueryParams() { - return Map.of("name", "dummy", "version", "1.0"); - } - - /** - * Get path params. - * @return Map of path params - */ - public Map getPathParams() { - return Map.of("id", "123", "name", "dummy"); - } - - /** - * Rest params with GET request. - * @return RestParams obj - */ - public RestParams restParamsWithGet() { - return new RestParams( - new ToscaConceptIdentifier("getRequest", "1.0"), - "GET", - "get", - 200, - null, - getQueryParams(), - null - ); - } - - /** - * Rest params with POST request. - * @return RestParams obj - */ - public RestParams restParamsWithPost() { - return new RestParams( - new ToscaConceptIdentifier("postRequest", "1.0"), - "POST", - "post", - 200, - null, - getQueryParams(), - "Test body" - ); - } - - /** - * Rest params with POST request. - * @return RestParams obj - */ - public RestParams restParamsWithInvalidPost() { - return new RestParams( - new ToscaConceptIdentifier("postRequest", "1.0"), - "POST", - "post/{id}/{name}", - 200, - getPathParams(), - getQueryParams(), - "Test body" - ); - } - - /** - * Get invalid configuration entity. - * @return ConfigurationEntity obj - */ - public ConfigurationEntity getInvalidConfigurationEntity() { - return new ConfigurationEntity( - new ToscaConceptIdentifier("config1", "1.0.1"), - List.of(restParamsWithGet(), restParamsWithInvalidPost()) - ); - } - - /** - * Get configuration entity. - * @return ConfigurationEntity obj - */ - public ConfigurationEntity getConfigurationEntity() { - return new ConfigurationEntity( - new ToscaConceptIdentifier("config1", "1.0.1"), - List.of(restParamsWithGet(), restParamsWithPost()) - ); - } - - /** - * Get controlloop id. - * @return ToscaConceptIdentifier controlLoopId - */ - public ToscaConceptIdentifier getControlLoopId() { - return new ToscaConceptIdentifier("PMSHInstance0", "1.0.0"); - } - - /** - * Get headers for config request. - * @return Map of headers - */ - public Map getHeaders() { - return Map.of("Content-Type", "application/json", "Accept", "application/json"); - } - -} diff --git a/participant/participant-impl/participant-impl-http/src/test/java/utils/ToscaUtils.java b/participant/participant-impl/participant-impl-http/src/test/java/utils/ToscaUtils.java deleted file mode 100644 index 0bad5ed96..000000000 --- a/participant/participant-impl/participant-impl-http/src/test/java/utils/ToscaUtils.java +++ /dev/null @@ -1,51 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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 utils; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.onap.policy.common.utils.coder.YamlJsonTranslator; -import org.onap.policy.common.utils.resources.ResourceUtils; -import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; - -/** - * Util class for Test scope. - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public final class ToscaUtils { - - private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator(); - private static final String TOSCA_TEMPLATE_YAML = "src/test/resources/HttpParticipantConfig.yaml"; - - - /** - * Read a service template yaml. - * @return ToscaServiceTemplate - */ - public static ToscaServiceTemplate readControlLoopFromTosca() { - return serializeControlLoopYaml(TOSCA_TEMPLATE_YAML); - } - - private static ToscaServiceTemplate serializeControlLoopYaml(String controlLoopFilePath) { - String controlLoopString = ResourceUtils.getResourceAsString(controlLoopFilePath); - return yamlTranslator.fromYaml(controlLoopString, ToscaServiceTemplate.class); - } -} diff --git a/participant/participant-impl/participant-impl-http/src/test/java/webclient/ClHttpClientTest.java b/participant/participant-impl/participant-impl-http/src/test/java/webclient/ClHttpClientTest.java deleted file mode 100644 index cf9619d41..000000000 --- a/participant/participant-impl/participant-impl-http/src/test/java/webclient/ClHttpClientTest.java +++ /dev/null @@ -1,129 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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 webclient; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.ws.rs.core.MediaType; -import org.apache.commons.lang3.tuple.Pair; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockserver.integration.ClientAndServer; -import org.mockserver.model.Parameter; -import org.onap.policy.clamp.controlloop.participant.http.main.models.ConfigRequest; -import org.onap.policy.clamp.controlloop.participant.http.main.models.ConfigurationEntity; -import org.onap.policy.clamp.controlloop.participant.http.main.webclient.ClHttpClient; -import org.onap.policy.common.utils.network.NetworkUtil; -import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import utils.CommonTestData; - -@ExtendWith(SpringExtension.class) -class ClHttpClientTest { - - private static CommonTestData commonTestData; - - private static int mockServerPort; - - private String testMockUrl = "http://localhost"; - - private Map> responseMap = new HashMap<>(); - - private static ClientAndServer mockServer; - - /** - * Set up Mock server. - */ - @BeforeAll - static void setUpMockServer() throws IOException { - mockServerPort = NetworkUtil.allocPort(); - mockServer = ClientAndServer.startClientAndServer(mockServerPort); - commonTestData = new CommonTestData(); - List queryParams = new ArrayList<>(); - commonTestData.getQueryParams().forEach((k, v) -> queryParams.add(new Parameter(k, v))); - - mockServer.when(request().withMethod("GET").withPath("/get") - .withHeader("Content-type", MediaType.APPLICATION_JSON) - .withHeader("Accept", MediaType.APPLICATION_JSON).withQueryStringParameters(queryParams)) - .respond(response().withBody("dummy body").withStatusCode(200) - .withHeader("Content-Type", MediaType.APPLICATION_JSON)); - - mockServer.when(request().withMethod("POST").withPath("/post") - .withHeader("Content-type", MediaType.APPLICATION_JSON) - .withHeader("Accept", MediaType.APPLICATION_JSON).withQueryStringParameters(queryParams) - .withBody("Test body")) - .respond(response().withStatusCode(200)); - } - - @AfterAll - public static void stopServer() { - mockServer.stop(); - mockServer = null; - } - - - @Test - void test_validRequest() { - //Add valid rest requests POST, GET - ConfigurationEntity configurationEntity = commonTestData.getConfigurationEntity(); - - Map headers = commonTestData.getHeaders(); - ConfigRequest configRequest = new ConfigRequest(testMockUrl + ":" + mockServerPort, headers, - List.of(configurationEntity), 10); - - ClHttpClient client = new ClHttpClient(configRequest, responseMap); - assertDoesNotThrow(client::run); - assertThat(responseMap).hasSize(2).containsKey(commonTestData - .restParamsWithGet().getRestRequestId()); - - Pair restResponseMap = responseMap.get(commonTestData - .restParamsWithGet().getRestRequestId()); - assertThat(restResponseMap.getKey()).isEqualTo(200); - } - - @Test - void test_invalidRequest() { - //Add rest requests Invalid POST, Valid GET - ConfigurationEntity configurationEntity = commonTestData.getInvalidConfigurationEntity(); - - Map headers = commonTestData.getHeaders(); - ConfigRequest configRequest = new ConfigRequest(testMockUrl + ":" + mockServerPort, headers, - List.of(configurationEntity), 10); - - ClHttpClient client = new ClHttpClient(configRequest, responseMap); - assertDoesNotThrow(client::run); - assertThat(responseMap).hasSize(2).containsKey(commonTestData - .restParamsWithGet().getRestRequestId()); - Pair response = responseMap - .get(commonTestData.restParamsWithInvalidPost().getRestRequestId()); - assertThat(response.getKey()).isEqualTo(404); - } -} diff --git a/participant/participant-impl/participant-impl-http/src/test/resources/application_test.properties b/participant/participant-impl/participant-impl-http/src/test/resources/application_test.properties new file mode 100644 index 000000000..698a965b8 --- /dev/null +++ b/participant/participant-impl/participant-impl-http/src/test/resources/application_test.properties @@ -0,0 +1,24 @@ +spring.security.user.name=participantUser +spring.security.user.password=zb!XztG34 + +server.servlet.context-path=/onap/httpparticipant +server.error.path=/error +server.http-port=8084 + +participant.name=ControlLoopParticipant Http Test +participant.intermediaryParameters.name=Participant parameters +participant.intermediaryParameters.reportingTimeInterval=120000 +participant.intermediaryParameters.description=Participant Description +participant.intermediaryParameters.participantId.name=HttpParticipant0 +participant.intermediaryParameters.participantId.version=1.0.0 +participant.intermediaryParameters.participantType.name=org.onap.k8s.controlloop.HttpControlLoopParticipant +participant.intermediaryParameters.participantType.version=2.3.4 +participant.intermediaryParameters.clampControlLoopTopics.name=ControlLoop Topics +participant.intermediaryParameters.clampControlLoopTopics.topicSources[0].topic=POLICY-CLRUNTIME-PARTICIPANT +participant.intermediaryParameters.clampControlLoopTopics.topicSources[0].servers[0]=localhost +participant.intermediaryParameters.clampControlLoopTopics.topicSources[0].topicCommInfrastructure=dmaap +participant.intermediaryParameters.clampControlLoopTopics.topicSources[0].fetchTimeout=15000 +participant.intermediaryParameters.clampControlLoopTopics.topicSinks[0].topic=POLICY-CLRUNTIME-PARTICIPANT +participant.intermediaryParameters.clampControlLoopTopics.topicSinks[0].servers[0]=localhost +participant.intermediaryParameters.clampControlLoopTopics.topicSinks[0].topicCommInfrastructure=dmaap +management.endpoints.web.exposure.include=health,metrics,prometheus diff --git a/participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml b/participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml index e1693318e..f77153a25 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml +++ b/participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml @@ -1,7 +1,7 @@ spring: security: user: - name: healthcheck + name: participantUser password: zb!XztG34 security: enable-csrf: false @@ -37,10 +37,8 @@ management: endpoints: web: exposure: - include: "loggers,logfile,health,info,metrics,threaddump,heapdump" + include: health, metrics, prometheus server: - # Configuration of the HTTP/REST server. The parameters are defined and handled by the springboot framework. - # See springboot documentation. port: 8083 servlet: context-path: /onap/k8sparticipant diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/controlloop/participant/kubernetes/rest/ActuatorControllerTest.java b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/controlloop/participant/kubernetes/rest/ActuatorControllerTest.java new file mode 100644 index 000000000..1442e9f1f --- /dev/null +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/controlloop/participant/kubernetes/rest/ActuatorControllerTest.java @@ -0,0 +1,92 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.clamp.controlloop.participant.kubernetes.rest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.Response; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.onap.policy.clamp.controlloop.participant.kubernetes.utils.CommonActuatorController; +import org.springframework.boot.test.autoconfigure.actuate.metrics.AutoConfigureMetrics; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@AutoConfigureMetrics +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@TestPropertySource(locations = {"classpath:application_test.properties"}) +class ActuatorControllerTest extends CommonActuatorController { + + private static final String HEALTH_ENDPOINT = "health"; + private static final String METRICS_ENDPOINT = "metrics"; + private static final String PROMETHEUS_ENDPOINT = "prometheus"; + + @LocalServerPort + private int randomServerPort; + + @BeforeEach + public void setUpPort() { + super.setHttpPrefix(randomServerPort); + } + + @Test + void testGetHealth_Unauthorized() throws Exception { + assertUnauthorizedActGet(HEALTH_ENDPOINT); + } + + @Test + void testGetMetrics_Unauthorized() throws Exception { + assertUnauthorizedActGet(METRICS_ENDPOINT); + } + + @Test + void testGetPrometheus_Unauthorized() throws Exception { + assertUnauthorizedActGet(PROMETHEUS_ENDPOINT); + } + + @Test + void testGetHealth() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(HEALTH_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + + @Test + void testGetMetrics() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(METRICS_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + + @Test + void testGePrometheus() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(PROMETHEUS_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + +} diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/controlloop/participant/kubernetes/utils/CommonActuatorController.java b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/controlloop/participant/kubernetes/utils/CommonActuatorController.java new file mode 100644 index 000000000..35ffbb5e9 --- /dev/null +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/controlloop/participant/kubernetes/utils/CommonActuatorController.java @@ -0,0 +1,114 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.clamp.controlloop.participant.kubernetes.utils; + +import static org.junit.Assert.assertEquals; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; +import org.onap.policy.common.gson.GsonMessageBodyHandler; +import org.onap.policy.common.utils.network.NetworkUtil; + +/** + * Class to perform Rest unit tests. + * + */ +public class CommonActuatorController { + + public static final String SELF = NetworkUtil.getHostname(); + public static final String CONTEXT_PATH = "onap/k8sparticipant"; + public static final String ACTUATOR_ENDPOINT = CONTEXT_PATH + "/actuator/"; + + private static String httpPrefix; + + /** + * Sends a request to an actuator endpoint. + * + * @param endpoint the target endpoint + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendActRequest(final String endpoint) throws Exception { + return sendFqeRequest(httpPrefix + ACTUATOR_ENDPOINT + endpoint, true); + } + + /** + * Sends a request to an actuator endpoint, without any authorization header. + * + * @param endpoint the target endpoint + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendNoAuthActRequest(final String endpoint) throws Exception { + return sendFqeRequest(httpPrefix + ACTUATOR_ENDPOINT + endpoint, false); + } + + /** + * Sends a request to a fully qualified endpoint. + * + * @param fullyQualifiedEndpoint the fully qualified target endpoint + * @param includeAuth if authorization header should be included + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendFqeRequest(final String fullyQualifiedEndpoint, boolean includeAuth) + throws Exception { + final Client client = ClientBuilder.newBuilder().build(); + + client.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true"); + client.register(GsonMessageBodyHandler.class); + + if (includeAuth) { + client.register(HttpAuthenticationFeature.basic("participantUser", "zb!XztG34")); + } + + final WebTarget webTarget = client.target(fullyQualifiedEndpoint); + + return webTarget.request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN); + } + + /** + * Assert that GET call to actuator endpoint is Unauthorized. + * + * @param endPoint the endpoint + * @throws Exception if an error occurs + */ + protected void assertUnauthorizedActGet(final String endPoint) throws Exception { + Response rawresp = sendNoAuthActRequest(endPoint).buildGet().invoke(); + assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + } + + /** + * Set Up httpPrefix. + * + * @param port the port + */ + protected void setHttpPrefix(int port) { + httpPrefix = "http://" + SELF + ":" + port + "/"; + } + +} diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/resources/application_test.properties b/participant/participant-impl/participant-impl-kubernetes/src/test/resources/application_test.properties index 5c61535a7..b5b209fd1 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/test/resources/application_test.properties +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/resources/application_test.properties @@ -1,7 +1,7 @@ -spring.security.user.name=healthcheck +spring.security.user.name=participantUser spring.security.user.password=zb!XztG34 -server.servlet.context-path=/onap/participantsim +server.servlet.context-path=/onap/k8sparticipant server.error.path=/error server.http-port=8083 @@ -21,3 +21,4 @@ participant.intermediaryParameters.clampControlLoopTopics.topicSources[0].fetchT participant.intermediaryParameters.clampControlLoopTopics.topicSinks[0].topic=POLICY-CLRUNTIME-PARTICIPANT participant.intermediaryParameters.clampControlLoopTopics.topicSinks[0].servers[0]=localhost participant.intermediaryParameters.clampControlLoopTopics.topicSinks[0].topicCommInfrastructure=dmaap +management.endpoints.web.exposure.include=health,metrics,prometheus diff --git a/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/controlloop/participant/policy/config/SecurityConfig.java b/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/controlloop/participant/policy/config/SecurityConfig.java new file mode 100644 index 000000000..4ee8c41b0 --- /dev/null +++ b/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/controlloop/participant/policy/config/SecurityConfig.java @@ -0,0 +1,45 @@ +/*- + * ========================LICENSE_START================================= + * Copyright (C) 2021 Nordix Foundation. All rights reserved. + * ====================================================================== + * 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. + * ========================LICENSE_END=================================== + */ + +package org.onap.policy.clamp.controlloop.participant.policy.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Value("${security.enable-csrf:true}") + private boolean csrfEnabled = true; + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers().authenticated() + .anyRequest().authenticated() + .and().httpBasic(); + // @formatter:on + + if (!csrfEnabled) { + http.csrf().disable(); + } + } +} diff --git a/participant/participant-impl/participant-impl-policy/src/main/resources/config/application.yaml b/participant/participant-impl/participant-impl-policy/src/main/resources/config/application.yaml index e5b2b2ab1..a2236226e 100644 --- a/participant/participant-impl/participant-impl-policy/src/main/resources/config/application.yaml +++ b/participant/participant-impl/participant-impl-policy/src/main/resources/config/application.yaml @@ -1,5 +1,8 @@ -server: - port: 8082 +spring: + security: + user: + name: participantUser + password: zb!XztG34 participant: pdpGroup: defaultGroup @@ -43,3 +46,12 @@ participant: servers: - ${topicServer:localhost} topicCommInfrastructure: dmaap +management: + endpoints: + web: + exposure: + include: health, metrics, prometheus +server: + port: 8085 + servlet: + context-path: /onap/policyparticipant diff --git a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/rest/ActuatorControllerTest.java b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/rest/ActuatorControllerTest.java new file mode 100644 index 000000000..9cc16e287 --- /dev/null +++ b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/rest/ActuatorControllerTest.java @@ -0,0 +1,92 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.clamp.controlloop.participant.policy.main.rest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.Response; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.onap.policy.clamp.controlloop.participant.policy.main.utils.CommonActuatorController; +import org.springframework.boot.test.autoconfigure.actuate.metrics.AutoConfigureMetrics; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@AutoConfigureMetrics +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@TestPropertySource(locations = {"classpath:application_test.properties"}) +class ActuatorControllerTest extends CommonActuatorController { + + private static final String HEALTH_ENDPOINT = "health"; + private static final String METRICS_ENDPOINT = "metrics"; + private static final String PROMETHEUS_ENDPOINT = "prometheus"; + + @LocalServerPort + private int randomServerPort; + + @BeforeEach + public void setUpPort() { + super.setHttpPrefix(randomServerPort); + } + + @Test + void testGetHealth_Unauthorized() throws Exception { + assertUnauthorizedActGet(HEALTH_ENDPOINT); + } + + @Test + void testGetMetrics_Unauthorized() throws Exception { + assertUnauthorizedActGet(METRICS_ENDPOINT); + } + + @Test + void testGetPrometheus_Unauthorized() throws Exception { + assertUnauthorizedActGet(PROMETHEUS_ENDPOINT); + } + + @Test + void testGetHealth() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(HEALTH_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + + @Test + void testGetMetrics() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(METRICS_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + + @Test + void testGePrometheus() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(PROMETHEUS_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + +} diff --git a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/utils/CommonActuatorController.java b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/utils/CommonActuatorController.java new file mode 100644 index 000000000..ec6e30918 --- /dev/null +++ b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/utils/CommonActuatorController.java @@ -0,0 +1,114 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.clamp.controlloop.participant.policy.main.utils; + +import static org.junit.Assert.assertEquals; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; +import org.onap.policy.common.gson.GsonMessageBodyHandler; +import org.onap.policy.common.utils.network.NetworkUtil; + +/** + * Class to perform Rest unit tests. + * + */ +public class CommonActuatorController { + + public static final String SELF = NetworkUtil.getHostname(); + public static final String CONTEXT_PATH = "onap/policyparticipant"; + public static final String ACTUATOR_ENDPOINT = CONTEXT_PATH + "/actuator/"; + + private static String httpPrefix; + + /** + * Sends a request to an actuator endpoint. + * + * @param endpoint the target endpoint + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendActRequest(final String endpoint) throws Exception { + return sendFqeRequest(httpPrefix + ACTUATOR_ENDPOINT + endpoint, true); + } + + /** + * Sends a request to an actuator endpoint, without any authorization header. + * + * @param endpoint the target endpoint + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendNoAuthActRequest(final String endpoint) throws Exception { + return sendFqeRequest(httpPrefix + ACTUATOR_ENDPOINT + endpoint, false); + } + + /** + * Sends a request to a fully qualified endpoint. + * + * @param fullyQualifiedEndpoint the fully qualified target endpoint + * @param includeAuth if authorization header should be included + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendFqeRequest(final String fullyQualifiedEndpoint, boolean includeAuth) + throws Exception { + final Client client = ClientBuilder.newBuilder().build(); + + client.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true"); + client.register(GsonMessageBodyHandler.class); + + if (includeAuth) { + client.register(HttpAuthenticationFeature.basic("participantUser", "zb!XztG34")); + } + + final WebTarget webTarget = client.target(fullyQualifiedEndpoint); + + return webTarget.request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN); + } + + /** + * Assert that GET call to actuator endpoint is Unauthorized. + * + * @param endPoint the endpoint + * @throws Exception if an error occurs + */ + protected void assertUnauthorizedActGet(final String endPoint) throws Exception { + Response rawresp = sendNoAuthActRequest(endPoint).buildGet().invoke(); + assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + } + + /** + * Set Up httpPrefix. + * + * @param port the port + */ + protected void setHttpPrefix(int port) { + httpPrefix = "http://" + SELF + ":" + port + "/"; + } + +} diff --git a/participant/participant-impl/participant-impl-policy/src/test/resources/application_test.properties b/participant/participant-impl/participant-impl-policy/src/test/resources/application_test.properties index 70d52b413..f857704d3 100644 --- a/participant/participant-impl/participant-impl-policy/src/test/resources/application_test.properties +++ b/participant/participant-impl/participant-impl-policy/src/test/resources/application_test.properties @@ -1,5 +1,8 @@ -server.servlet.context-path=/onap/participantsim +spring.security.user.name=participantUser +spring.security.user.password=zb!XztG34 +server.servlet.context-path=/onap/policyparticipant server.error.path=/error +server.http-port=8085 participant.policyApiParameters.clientName=api participant.policyApiParameters.hostname=localhost @@ -22,3 +25,4 @@ participant.intermediaryParameters.clampControlLoopTopics.topicSources[0].fetchT participant.intermediaryParameters.clampControlLoopTopics.topicSinks[0].topic=POLICY-CLRUNTIME-PARTICIPANT participant.intermediaryParameters.clampControlLoopTopics.topicSinks[0].servers[0]=localhost participant.intermediaryParameters.clampControlLoopTopics.topicSinks[0].topicCommInfrastructure=dmaap +management.endpoints.web.exposure.include=health,metrics,prometheus diff --git a/participant/pom.xml b/participant/pom.xml index fcfbe0c90..72701f1a4 100644 --- a/participant/pom.xml +++ b/participant/pom.xml @@ -94,6 +94,17 @@ policy-clamp-models ${project.version} + + + org.springframework.boot + spring-boot-starter-actuator + ${version.springboot} + + + io.micrometer + micrometer-registry-prometheus + ${version.io.micrometer} + -- cgit 1.2.3-korg