diff options
4 files changed, 383 insertions, 111 deletions
diff --git a/vid-app-common/pom.xml b/vid-app-common/pom.xml index 6ae5056ac..b8fbd853a 100755 --- a/vid-app-common/pom.xml +++ b/vid-app-common/pom.xml @@ -250,7 +250,14 @@ <artifactId>opencsv</artifactId>
<version>4.1</version>
</dependency>
-
+
+ <!-- HTTP client -->
+ <dependency>
+ <groupId>com.xebialabs.restito</groupId>
+ <artifactId>restito</artifactId>
+ <version>0.9.3</version>
+ <scope>test</scope>
+ </dependency>
<!-- SDK overlay war -->
@@ -502,5 +509,11 @@ <artifactId>togglz-spring-core</artifactId>
<version>2.5.0.Final</version>
</dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>3.10.0</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/vid-app-common/src/main/java/org/onap/vid/scheduler/SchedulerRestInterface.java b/vid-app-common/src/main/java/org/onap/vid/scheduler/SchedulerRestInterface.java index abd03f3e0..9a7522b52 100644 --- a/vid-app-common/src/main/java/org/onap/vid/scheduler/SchedulerRestInterface.java +++ b/vid-app-common/src/main/java/org/onap/vid/scheduler/SchedulerRestInterface.java @@ -18,123 +18,134 @@ import javax.ws.rs.client.Client; import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.Response; import java.util.Collections; +import java.util.function.Function; import static org.onap.vid.utils.Logging.REQUEST_ID_HEADER_KEY; @Service public class SchedulerRestInterface implements SchedulerRestInterfaceIfc { - private Client client = null; - - @Autowired - HttpsAuthClient httpsAuthClient; - - private MultivaluedHashMap<String, Object> commonHeaders; - - /** The logger. */ - private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SchedulerRestInterface.class); - final private static EELFLogger outgoingRequestsLogger = Logging.getRequestsLogger("scheduler"); - - public void initRestClient() { - logger.info("Starting to initialize rest client "); - - final String username; - final String password; - + private Client client = null; + private Function<String, String> propertyGetter; + + @Autowired + HttpsAuthClient httpsAuthClient; + + private MultivaluedHashMap<String, Object> commonHeaders; + + /** The logger. */ + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SchedulerRestInterface.class); + final private static EELFLogger outgoingRequestsLogger = Logging.getRequestsLogger("scheduler"); + + @Autowired + public SchedulerRestInterface(){ + this.propertyGetter = SystemProperties::getProperty; + } + + public SchedulerRestInterface(Function<String, String> propertyGetter){ + this.propertyGetter = propertyGetter; + } + + public void initRestClient() { + logger.info("Starting to initialize rest client "); + + final String username; + final String password; + /*Setting user name based on properties*/ - String retrievedUsername = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_USER_NAME_VAL); - if(retrievedUsername.isEmpty()) { - username = ""; - } else { - username = retrievedUsername; - } - + String retrievedUsername = propertyGetter.apply(SchedulerProperties.SCHEDULER_USER_NAME_VAL); + if(retrievedUsername.isEmpty()) { + username = ""; + } else { + username = retrievedUsername; + } + /*Setting password based on properties*/ - String retrievedPassword = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_PASSWORD_VAL); - if(retrievedPassword.isEmpty()) { - password = ""; - } else { - if (retrievedPassword.contains("OBF:")) { - password = Password.deobfuscate(retrievedPassword); - } else { - password = retrievedPassword; - } - } - - String authString = username + ":" + password; - - byte[] authEncBytes = Base64.encodeBase64(authString.getBytes()); - String authStringEnc = new String(authEncBytes); - - commonHeaders = new MultivaluedHashMap<String, Object> (); - commonHeaders.put("Authorization", Collections.singletonList("Basic " + authStringEnc)); - - try { - if ( !username.isEmpty() ) { - client = httpsAuthClient.getClient(HttpClientMode.WITHOUT_KEYSTORE); - } - else { - - client = HttpBasicClient.getClient(); - } - } catch (Exception e) { - logger.error(" <== Unable to initialize rest client ", e); - } - - logger.info("\t<== Client Initialized \n"); - } - - public <T> void Get (T t, String sourceId, String path, org.onap.vid.scheduler.RestObject<T> restObject ) { - - String methodName = "Get"; - String url = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_SERVER_URL_VAL) + path; - initRestClient(); - Logging.logRequest(outgoingRequestsLogger, HttpMethod.GET, url); - final Response cres = client.target(url) - .request() - .accept("application/json") - .headers(commonHeaders) - .header(REQUEST_ID_HEADER_KEY, Logging.extractOrGenerateRequestId()) - .get(); - Logging.logResponse(outgoingRequestsLogger, HttpMethod.GET, url, cres); - int status = cres.getStatus(); - restObject.setStatusCode (status); - - if (status == 200) { - t = (T) cres.readEntity(t.getClass()); - restObject.set(t); - - } else { - throw new GenericUncheckedException(methodName + " with status="+ status + ", url= " + url ); - } - - } - - public <T> void Delete(T t, String sourceID, String path, org.onap.vid.scheduler.RestObject<T> restObject) { - - initRestClient(); - - String url = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_SERVER_URL_VAL) + path; - Logging.logRequest(outgoingRequestsLogger, HttpMethod.DELETE, url); - Response cres = client.target(url) - .request() - .accept("application/json") - .headers(commonHeaders) - .header(REQUEST_ID_HEADER_KEY, Logging.extractOrGenerateRequestId()) - .delete(); - Logging.logResponse(outgoingRequestsLogger, HttpMethod.DELETE, url, cres); - - int status = cres.getStatus(); - restObject.setStatusCode(status); - - t = (T) cres.readEntity(t.getClass()); - restObject.set(t); - - } - - public <T> T getInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException - { - return clazz.newInstance(); - } + String retrievedPassword = propertyGetter.apply(SchedulerProperties.SCHEDULER_PASSWORD_VAL); + if(retrievedPassword.isEmpty()) { + password = ""; + } else { + if (retrievedPassword.contains("OBF:")) { + password = Password.deobfuscate(retrievedPassword); + } else { + password = retrievedPassword; + } + } + + String authString = username + ":" + password; + + byte[] authEncBytes = Base64.encodeBase64(authString.getBytes()); + String authStringEnc = new String(authEncBytes); + + commonHeaders = new MultivaluedHashMap<> (); + commonHeaders.put("Authorization", Collections.singletonList("Basic " + authStringEnc)); + + try { + if ( !username.isEmpty() ) { + client = httpsAuthClient.getClient(HttpClientMode.WITHOUT_KEYSTORE); + } + else { + + client = HttpBasicClient.getClient(); + } + } catch (Exception e) { + logger.error(" <== Unable to initialize rest client ", e); + } + + logger.info("\t<== Client Initialized \n"); + } + + public <T> void Get (T t, String sourceId, String path, org.onap.vid.scheduler.RestObject<T> restObject ) { + + String methodName = "Get"; + String url = String.format("%s%s",propertyGetter.apply(SchedulerProperties.SCHEDULER_SERVER_URL_VAL), path); + initRestClient(); + Logging.logRequest(outgoingRequestsLogger, HttpMethod.GET, url); + final Response cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + .header(REQUEST_ID_HEADER_KEY, Logging.extractOrGenerateRequestId()) + .get(); + Logging.logResponse(outgoingRequestsLogger, HttpMethod.GET, url, cres); + int status = cres.getStatus(); + restObject.setStatusCode (status); + + if (status == 200) { + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + + } else { + throw new GenericUncheckedException(String.format("%s with status=%d, url=%s", methodName, status,url)); + } + + } + + public <T> void Delete(T t, String sourceID, String path, org.onap.vid.scheduler.RestObject<T> restObject) { + + initRestClient(); + + String url = String.format( "%s%s",propertyGetter.apply(SchedulerProperties.SCHEDULER_SERVER_URL_VAL), path); + Logging.logRequest(outgoingRequestsLogger, HttpMethod.DELETE, url); + Response cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + .header(REQUEST_ID_HEADER_KEY, Logging.extractOrGenerateRequestId()) + .delete(); + Logging.logResponse(outgoingRequestsLogger, HttpMethod.DELETE, url, cres); + + int status = cres.getStatus(); + restObject.setStatusCode(status); + + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + + } + + public <T> T getInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException + { + return clazz.newInstance(); + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/scheduler/SchedulerRestInterfaceTest.java b/vid-app-common/src/test/java/org/onap/vid/scheduler/SchedulerRestInterfaceTest.java new file mode 100644 index 000000000..7becf8b7e --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/scheduler/SchedulerRestInterfaceTest.java @@ -0,0 +1,158 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2018 Nokia 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. + * ============LICENSE_END========================================================= + */ + + +package org.onap.vid.scheduler; + +import com.xebialabs.restito.semantics.Action; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.*; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.vid.aai.util.HttpClientMode; +import org.onap.vid.aai.util.HttpsAuthClient; +import org.onap.vid.testUtils.StubServerUtil; +import org.testng.annotations.BeforeMethod; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.Collections; +import java.util.function.Function; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + + +@RunWith(MockitoJUnitRunner.class) +public class SchedulerRestInterfaceTest { + + private static final String USR_PWD_AUTH_STRING = "c2FtcGxlOnBhUyR3MFJk"; + private static final String APPLICATION_JSON = "application/json"; + private static MultivaluedHashMap<String, Object> commonHeaders = new MultivaluedHashMap<>(); + private static StubServerUtil serverUtil; + private String sampleBaseUrl; + @Mock + private HttpsAuthClient mockedHttpsAuthClient; + @Mock + private Client mockedClient; + @Mock + private Invocation.Builder mockedBuilder; + @Mock + private Response mockedResponse; + @Mock + private WebTarget mockedWebTarget; + + @Mock + private Function<String, String> propertyGetter; + + @InjectMocks + private SchedulerRestInterface schedulerInterface = new SchedulerRestInterface(); + + @BeforeClass + public static void setUpClass() { + serverUtil = new StubServerUtil(); + serverUtil.runServer(); + commonHeaders.put("Authorization", Collections.singletonList("Basic " + USR_PWD_AUTH_STRING)); + } + + @AfterClass + public static void tearDownClass() { + serverUtil.stopServer(); + } + + @BeforeMethod + public void setUp() { + MockitoAnnotations.initMocks(this); + + sampleBaseUrl = serverUtil.constructTargetUrl("http", ""); + } + + @Test + public void testShouldGetOKWhenStringIsExpected() throws IOException, GeneralSecurityException { + String sampleSourceId = "AAI"; + RestObject<String> sampleRestObj = new RestObject<>(); + String resultHolder = ""; + + String responseContent = "sample : SAMPLE RESULT STRING"; + Mockito.doReturn(mockedClient).when(mockedHttpsAuthClient).getClient(HttpClientMode.WITHOUT_KEYSTORE); + Mockito.doReturn("sample").when(propertyGetter).apply(SchedulerProperties.SCHEDULER_USER_NAME_VAL); + Mockito.doReturn("paS$w0Rd").when(propertyGetter).apply(SchedulerProperties.SCHEDULER_PASSWORD_VAL); + Mockito.doReturn(sampleBaseUrl).when(propertyGetter).apply(SchedulerProperties.SCHEDULER_SERVER_URL_VAL); + Mockito.doReturn(200).when(mockedResponse).getStatus(); + Mockito.doReturn(responseContent).when(mockedResponse).readEntity(String.class); + Mockito.doReturn(mockedResponse).when(mockedBuilder).get(); + Mockito.when(mockedBuilder.header(Matchers.any(), Matchers.any())).thenReturn(mockedBuilder); + Mockito.doReturn(mockedBuilder).when(mockedBuilder).headers(commonHeaders); + Mockito.doReturn(mockedBuilder).when(mockedBuilder).accept(APPLICATION_JSON); + Mockito.doReturn(mockedBuilder).when(mockedWebTarget).request(); + Mockito.doReturn(mockedWebTarget).when(mockedClient).target(sampleBaseUrl + "test"); + + serverUtil.prepareGetCall("/test", responseContent, Action.ok()); + + schedulerInterface.Get(resultHolder, sampleSourceId, "test", sampleRestObj); + + assertResponseData(sampleRestObj, responseContent, 200); + } + + + @Test + public void testShouldDeleteSuccessfully() throws IOException, GeneralSecurityException { + String sampleTargetUrl = serverUtil.constructTargetUrl("http", ""); + String sampleSourceId = "AAI"; + RestObject<String> sampleRestObj = new RestObject<>(); + String resultHolder = ""; + + String responseContent = "sample : SAMPLE RESULT STRING"; + Mockito.doReturn(mockedClient).when(mockedHttpsAuthClient).getClient(HttpClientMode.WITHOUT_KEYSTORE); + Mockito.doReturn("sample").when(propertyGetter).apply(SchedulerProperties.SCHEDULER_USER_NAME_VAL); + Mockito.doReturn("paS$w0Rd").when(propertyGetter).apply(SchedulerProperties.SCHEDULER_PASSWORD_VAL); + Mockito.doReturn(sampleTargetUrl).when(propertyGetter).apply(SchedulerProperties.SCHEDULER_SERVER_URL_VAL); + Mockito.doReturn(200).when(mockedResponse).getStatus(); + Mockito.doReturn(responseContent).when(mockedResponse).readEntity(String.class); + Mockito.doReturn(mockedResponse).when(mockedBuilder).delete(); + Mockito.when(mockedBuilder.header(Matchers.any(), Matchers.any())).thenReturn(mockedBuilder); + Mockito.doReturn(mockedBuilder).when(mockedBuilder).headers(commonHeaders); + Mockito.doReturn(mockedBuilder).when(mockedBuilder).accept(APPLICATION_JSON); + Mockito.doReturn(mockedBuilder).when(mockedWebTarget).request(); + Mockito.doReturn(mockedWebTarget).when(mockedClient).target(sampleTargetUrl + "test"); + + serverUtil.prepareDeleteCall("/test", responseContent, Action.ok()); + + schedulerInterface.Delete(resultHolder, sampleSourceId, "test", sampleRestObj); + + assertResponseData(sampleRestObj, responseContent, 200); + } + + + private void assertResponseData(RestObject<String> sampleRestObj, String expectedResponse, int expectedStatusCode) { + + assertThat(sampleRestObj.getStatusCode()).isEqualTo(expectedStatusCode); + assertThat(sampleRestObj.get()).isInstanceOf(String.class).isEqualTo(expectedResponse); + assertThat(sampleRestObj.getUUID()).isNull(); + + } + +} diff --git a/vid-app-common/src/test/java/org/onap/vid/testUtils/StubServerUtil.java b/vid-app-common/src/test/java/org/onap/vid/testUtils/StubServerUtil.java new file mode 100644 index 000000000..e84655f7e --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/testUtils/StubServerUtil.java @@ -0,0 +1,90 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2018 Nokia 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.testUtils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.xebialabs.restito.semantics.Action; +import com.xebialabs.restito.semantics.Condition; +import com.xebialabs.restito.server.StubServer; + +import static com.xebialabs.restito.builder.stub.StubHttp.whenHttp; +import static com.xebialabs.restito.semantics.Action.contentType; +import static com.xebialabs.restito.semantics.Action.stringContent; + +public class StubServerUtil { + + private static final String APPLICATION_JSON = "application/json"; + private ObjectMapper objectMapper; + + + private StubServer stubServer; + + public StubServerUtil() { + this.objectMapper = new ObjectMapper(); + this.stubServer = new StubServer(); + } + + + public void runServer() { + stubServer.run(); + } + + public void stopServer() { + stubServer.stop(); + } + + + public String constructTargetUrl(String protocol, String relativePath) { + return String.format("%s://localhost:%s/%s", protocol, stubServer.getPort(), relativePath); + } + + public void prepareGetCall(String path, Object returnObj, Action expectedAction) throws JsonProcessingException { + whenHttp(stubServer) + .match(Condition.get(path)) + .then(expectedAction, jsonContent(returnObj), contentType(APPLICATION_JSON)); + } + + public void prepareDeleteCall(String path, Object returnObj, Action expectedAction) throws JsonProcessingException { + whenHttp(stubServer) + .match(Condition.delete(path)) + .then(expectedAction, jsonContent(returnObj), contentType(APPLICATION_JSON)); + } + + public void preparePostCall(String path, Object returnObj, Action expectedAction) throws JsonProcessingException { + whenHttp(stubServer) + .match(Condition.post(path), + Condition.withPostBodyContaining(objectMapper.writeValueAsString(returnObj))) + .then(expectedAction, jsonContent(returnObj), contentType(APPLICATION_JSON)); + } + + public void preparePutCall(String path, Object returnObj, Action expectedStatus) throws JsonProcessingException { + whenHttp(stubServer) + .match(Condition.put(path), + Condition.withPostBodyContaining(objectMapper.writeValueAsString(returnObj))) + .then(expectedStatus, jsonContent(returnObj), contentType(APPLICATION_JSON)); + } + + private Action jsonContent(Object returnObj) throws JsonProcessingException { + return stringContent(objectMapper.writeValueAsString(returnObj)); + } + +} |