From 2bd5e9339b6255eb8d9cbeae183c1728984d5a88 Mon Sep 17 00:00:00 2001 From: Eylon Malin Date: Thu, 15 Aug 2019 17:23:44 +0300 Subject: probe sdc by retrieving service model if uuid configured If system.properties has value for probe.sdc.model.uuid then usd this value for retrieving service model otherwise probe only sdc connectivity with sdc2/rest/healthCheck Issue-ID: VID-378 Signed-off-by: Eylon Malin Change-Id: Icd1c31217e56a8c0cfa5c2f2bc5f11e0c8dd7ff8 Signed-off-by: Eylon Malin --- .../org/onap/vid/aai/ResponseWithRequestInfo.java | 49 ----- .../org/onap/vid/aai/ResponseWithRequestInfo.kt | 34 +++ .../main/java/org/onap/vid/asdc/AsdcClient.java | 7 +- .../org/onap/vid/asdc/local/LocalAsdcClient.java | 226 -------------------- .../java/org/onap/vid/asdc/rest/SdcRestClient.java | 60 +++--- .../onap/vid/model/probes/HttpRequestMetadata.java | 17 +- .../java/org/onap/vid/services/VidServiceImpl.java | 79 ++++++- .../test/java/org/onap/vid/aai/AaiClientTest.java | 1 + .../org/onap/vid/asdc/local/LocalAsdcClient.java | 232 +++++++++++++++++++++ .../org/onap/vid/services/VidServiceImplTest.java | 155 +++++++++++++- 10 files changed, 544 insertions(+), 316 deletions(-) delete mode 100644 vid-app-common/src/main/java/org/onap/vid/aai/ResponseWithRequestInfo.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/aai/ResponseWithRequestInfo.kt delete mode 100644 vid-app-common/src/main/java/org/onap/vid/asdc/local/LocalAsdcClient.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/asdc/local/LocalAsdcClient.java (limited to 'vid-app-common') diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/ResponseWithRequestInfo.java b/vid-app-common/src/main/java/org/onap/vid/aai/ResponseWithRequestInfo.java deleted file mode 100644 index 567099c81..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/aai/ResponseWithRequestInfo.java +++ /dev/null @@ -1,49 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.vid.aai; - -import org.springframework.http.HttpMethod; - -import javax.ws.rs.core.Response; - -public class ResponseWithRequestInfo { - private String requestUrl; - private HttpMethod requestHttpMethod; - private Response response; - - public ResponseWithRequestInfo(Response response, String requestUrl, HttpMethod requestHttpMethod) { - this.response = response; - this.requestUrl = requestUrl; - this.requestHttpMethod = requestHttpMethod; - } - - public String getRequestUrl() { - return requestUrl; - } - - public HttpMethod getRequestHttpMethod() { - return requestHttpMethod; - } - - public Response getResponse() { - return response; - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/ResponseWithRequestInfo.kt b/vid-app-common/src/main/java/org/onap/vid/aai/ResponseWithRequestInfo.kt new file mode 100644 index 000000000..aaa41c2d3 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/aai/ResponseWithRequestInfo.kt @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.aai + +import io.joshworks.restclient.http.HttpResponse +import org.springframework.http.HttpMethod + +import javax.ws.rs.core.Response + +open class BaseResponseWithRequestInfo(val requestUrl: String?, val requestHttpMethod: HttpMethod) + +class HttpResponseWithRequestInfo(val response: HttpResponse?, requestUrl: String?, requestHttpMethod: HttpMethod) : + BaseResponseWithRequestInfo(requestUrl, requestHttpMethod) + +class ResponseWithRequestInfo(val response: Response?, requestUrl: String?, requestHttpMethod: HttpMethod) : + BaseResponseWithRequestInfo(requestUrl, requestHttpMethod) diff --git a/vid-app-common/src/main/java/org/onap/vid/asdc/AsdcClient.java b/vid-app-common/src/main/java/org/onap/vid/asdc/AsdcClient.java index fc04080d9..44257a62e 100644 --- a/vid-app-common/src/main/java/org/onap/vid/asdc/AsdcClient.java +++ b/vid-app-common/src/main/java/org/onap/vid/asdc/AsdcClient.java @@ -22,10 +22,11 @@ package org.onap.vid.asdc; import io.joshworks.restclient.http.HttpResponse; -import org.onap.vid.asdc.beans.Service; - +import java.io.InputStream; import java.nio.file.Path; import java.util.UUID; +import org.onap.vid.aai.HttpResponseWithRequestInfo; +import org.onap.vid.asdc.beans.Service; /** * The Interface AsdcClient. @@ -55,6 +56,8 @@ public interface AsdcClient { Path getServiceToscaModel(UUID uuid) throws AsdcCatalogException; + HttpResponseWithRequestInfo getServiceInputStream(UUID serviceUuid, boolean warpException); + HttpResponse checkSDCConnectivity(); String getBaseUrl(); diff --git a/vid-app-common/src/main/java/org/onap/vid/asdc/local/LocalAsdcClient.java b/vid-app-common/src/main/java/org/onap/vid/asdc/local/LocalAsdcClient.java deleted file mode 100644 index ce1bbe930..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/asdc/local/LocalAsdcClient.java +++ /dev/null @@ -1,226 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2019 Nokia. 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.asdc.local; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.joshworks.restclient.http.HttpResponse; -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.UUID; -import org.json.JSONArray; -import org.json.JSONObject; -import org.onap.vid.asdc.AsdcCatalogException; -import org.onap.vid.asdc.AsdcClient; -import org.onap.vid.asdc.beans.Service; -import org.onap.vid.exceptions.GenericUncheckedException; - -/** - * The Class LocalAsdcClient. - */ -public class LocalAsdcClient implements AsdcClient { - - - public static final String SERVICES = "services"; - /** - * The catalog. - */ - private final JSONObject catalog; - - /** - * The mapper. - */ - private final ObjectMapper mapper; - - /** - * Instantiates a new in local sdc client. - * - * @param builder the builder - */ - public LocalAsdcClient(org.onap.vid.asdc.local.LocalAsdcClient.Builder builder) { - catalog = builder.catalog; - mapper = builder.mapper; - } - - /** - * Gets the catalog. - * - * @return the catalog - */ - private JSONObject getCatalog() { - return catalog; - } - - /** - * Gets the mapper. - * - * @return the mapper - */ - private ObjectMapper getMapper() { - return mapper; - } - - /** - * Convert. - * - * @param the generic type - * @param json the json - * @param clazz the clazz - * @return the t - * @throws AsdcCatalogException the sdc catalog exception - */ - private T convert(JSONObject json, Class clazz) throws AsdcCatalogException { - try { - return getMapper().readValue(json.toString(), clazz); - } catch (JsonParseException e) { - throw new AsdcCatalogException("Failed to parse SDC response (bad data)", e); - } catch (JsonMappingException e) { - throw new AsdcCatalogException("Failed to map SDC response to internal VID data structure(s)", e); - } catch (IOException e) { - throw new AsdcCatalogException("Failed to get a response from SDC", e); - } - } - - /* (non-Javadoc) - * @see org.onap.vid.asdc.AsdcClient#getService(java.util.UUID) - */ - public Service getService(UUID uuid) throws AsdcCatalogException { - - JSONObject serviceJsonObject = null; - final JSONArray categoryJsonArray = getCatalog().getJSONArray(SERVICES); - - for (int i = 0; i < categoryJsonArray.length(); i++) { - JSONObject jsonServiceObject = categoryJsonArray.getJSONObject(i); - if (jsonServiceObject.get("uuid").equals(uuid.toString())) { - serviceJsonObject = jsonServiceObject; - break; - } - } - - if (serviceJsonObject != null) - return convert(serviceJsonObject, Service.class); - else return null; - } - - /* (non-Javadoc) - * @see org.onap.vid.asdc.AsdcClient#getServiceToscaModel(java.util.UUID) - */ - public Path getServiceToscaModel(UUID serviceUuid) { - - String toscaModelURL = null; - - final JSONArray categoryJsonArray = getCatalog().getJSONArray(SERVICES); - - for (int i = 0; i < categoryJsonArray.length(); i++) { - - JSONObject jsonServiceObject = categoryJsonArray.getJSONObject(i); - if (jsonServiceObject.get("uuid").equals(serviceUuid.toString())) { - toscaModelURL = jsonServiceObject.getString("toscaModelURL"); - } - } - if (toscaModelURL == null) { - return null; - } - ClassLoader classLoader = getClass().getClassLoader(); - - try { - File file = new File(classLoader.getResource(toscaModelURL).getFile()); - //using URLDecoder.decode to convert special characters from %XX to real character - //see https://stackoverflow.com/questions/32251251/java-classloader-getresource-with-special-characters-in-path - return Paths.get(URLDecoder.decode(file.getPath(), "UTF-8")); - } catch (RuntimeException | UnsupportedEncodingException e) { - throw new GenericUncheckedException("Can't find " + toscaModelURL, e); - } - } - - @Override - public HttpResponse checkSDCConnectivity() { - return HttpResponse.fallback(""); - } - - - @Override - public String getBaseUrl(){ - return ""; - } - - /** - * The Class Builder. - */ - public static class Builder { - - /** - * The catalog. - */ - private JSONObject catalog = new JSONObject() - .put("resources", new JSONObject()) - .put(SERVICES, new JSONObject()); - - /** - * The mapper. - */ - private ObjectMapper mapper = new ObjectMapper(); - - /** - * Instantiates a new builder. - */ - public Builder() { - } - - /** - * Catalog. - * - * @param catalog the catalog - * @return the builder - */ - public org.onap.vid.asdc.local.LocalAsdcClient.Builder catalog(JSONObject catalog) { - this.catalog = catalog; - return this; - } - - /** - * Mapper. - * - * @param mapper the mapper - * @return the builder - */ - public org.onap.vid.asdc.local.LocalAsdcClient.Builder mapper(ObjectMapper mapper) { - this.mapper = mapper; - return this; - } - - /** - * Builds the. - * - * @return the in local sdc client - */ - public org.onap.vid.asdc.local.LocalAsdcClient build() { - return new org.onap.vid.asdc.local.LocalAsdcClient(this); - } - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/asdc/rest/SdcRestClient.java b/vid-app-common/src/main/java/org/onap/vid/asdc/rest/SdcRestClient.java index a82110744..decf446d6 100644 --- a/vid-app-common/src/main/java/org/onap/vid/asdc/rest/SdcRestClient.java +++ b/vid-app-common/src/main/java/org/onap/vid/asdc/rest/SdcRestClient.java @@ -20,11 +20,32 @@ package org.onap.vid.asdc.rest; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM; +import static org.onap.portalsdk.core.util.SystemProperties.APP_DISPLAY_NAME; +import static org.onap.vid.asdc.AsdcClient.URIS.METADATA_URL_TEMPLATE; +import static org.onap.vid.asdc.AsdcClient.URIS.TOSCA_MODEL_URL_TEMPLATE; +import static org.onap.vid.client.SyncRestClientInterface.HEADERS.AUTHORIZATION; +import static org.onap.vid.client.SyncRestClientInterface.HEADERS.CONTENT_TYPE; +import static org.onap.vid.client.SyncRestClientInterface.HEADERS.X_ECOMP_INSTANCE_ID; +import static org.onap.vid.utils.Logging.REQUEST_ID_HEADER_KEY; +import static org.onap.vid.utils.Logging.logRequest; + import com.att.eelf.configuration.EELFLogger; import com.google.common.collect.ImmutableMap; import io.joshworks.restclient.http.HttpResponse; import io.vavr.control.Try; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Collections; +import java.util.Map; +import java.util.UUID; import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.vid.aai.ExceptionWithRequestInfo; +import org.onap.vid.aai.HttpResponseWithRequestInfo; import org.onap.vid.asdc.AsdcCatalogException; import org.onap.vid.asdc.AsdcClient; import org.onap.vid.asdc.beans.Service; @@ -34,26 +55,6 @@ import org.onap.vid.properties.VidProperties; import org.onap.vid.utils.Logging; import org.springframework.http.HttpMethod; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.util.Collections; -import java.util.Map; -import java.util.UUID; - -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM; -import static org.onap.portalsdk.core.util.SystemProperties.APP_DISPLAY_NAME; -import static org.onap.vid.asdc.AsdcClient.URIS.METADATA_URL_TEMPLATE; -import static org.onap.vid.asdc.AsdcClient.URIS.TOSCA_MODEL_URL_TEMPLATE; -import static org.onap.vid.client.SyncRestClientInterface.HEADERS.AUTHORIZATION; -import static org.onap.vid.client.SyncRestClientInterface.HEADERS.CONTENT_TYPE; -import static org.onap.vid.client.SyncRestClientInterface.HEADERS.X_ECOMP_INSTANCE_ID; -import static org.onap.vid.utils.Logging.REQUEST_ID_HEADER_KEY; -import static org.onap.vid.utils.Logging.logRequest; - public class SdcRestClient implements AsdcClient { private String baseUrl; @@ -86,17 +87,28 @@ public class SdcRestClient implements AsdcClient { @Override public Path getServiceToscaModel(UUID uuid) throws AsdcCatalogException { - String finalUrl = String.format(TOSCA_MODEL_URL_TEMPLATE, baseUrl, path, uuid); - logRequest(LOGGER, HttpMethod.GET, finalUrl); - InputStream inputStream = Try - .of(() -> syncRestClient.getStream(finalUrl, prepareHeaders(auth, APPLICATION_OCTET_STREAM), Collections.emptyMap())) + .of(() -> getServiceInputStream(uuid, false)) .getOrElseThrow(AsdcCatalogException::new) + .getResponse() .getBody(); return createTmpFile(inputStream); } + @Override + public HttpResponseWithRequestInfo getServiceInputStream(UUID serviceUuid, boolean warpException) { + String finalUrl = String.format(TOSCA_MODEL_URL_TEMPLATE, baseUrl, path, serviceUuid); + logRequest(LOGGER, HttpMethod.GET, finalUrl); + try { + HttpResponse httpResponse = syncRestClient.getStream(finalUrl, prepareHeaders(auth, APPLICATION_OCTET_STREAM), Collections.emptyMap()); + return new HttpResponseWithRequestInfo<>(httpResponse, finalUrl, HttpMethod.GET); + } + catch (RuntimeException exception) { + throw warpException ? new ExceptionWithRequestInfo(HttpMethod.GET, finalUrl, exception) : exception; + } + } + @Override public HttpResponse checkSDCConnectivity() { diff --git a/vid-app-common/src/main/java/org/onap/vid/model/probes/HttpRequestMetadata.java b/vid-app-common/src/main/java/org/onap/vid/model/probes/HttpRequestMetadata.java index 1638a376c..b284b01d9 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/probes/HttpRequestMetadata.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/probes/HttpRequestMetadata.java @@ -22,9 +22,11 @@ package org.onap.vid.model.probes; import com.google.common.base.MoreObjects; -import io.joshworks.restclient.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.onap.vid.aai.ExceptionWithRequestInfo; +import org.onap.vid.aai.HttpResponseWithRequestInfo; import org.onap.vid.aai.ResponseWithRequestInfo; import org.onap.vid.mso.RestObjectWithRequestInfo; import org.onap.vid.utils.Logging; @@ -81,6 +83,19 @@ public class HttpRequestMetadata extends StatusMetadata { duration); } + public HttpRequestMetadata(HttpResponseWithRequestInfo response, String description, long duration, boolean readRawData) { + super(description, duration); + this.httpMethod = response.getRequestHttpMethod(); + this.url = response.getRequestUrl(); + this.httpCode = response.getResponse().getStatus(); + if (readRawData) { + try { + this.rawData = IOUtils.toString(response.getResponse().getRawBody(), StandardCharsets.UTF_8.name()); + } catch (Exception e) { + //Nothing to do here + } + } + } public HttpMethod getHttpMethod() { diff --git a/vid-app-common/src/main/java/org/onap/vid/services/VidServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/VidServiceImpl.java index 9d6f74def..a5988a156 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/VidServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/VidServiceImpl.java @@ -20,12 +20,22 @@ */ package org.onap.vid.services; +import static org.onap.vid.model.probes.ExternalComponentStatus.Component.SDC; +import static org.onap.vid.properties.Features.FLAG_SERVICE_MODEL_CACHE; + import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import io.joshworks.restclient.http.HttpResponse; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; +import org.onap.vid.aai.ExceptionWithRequestInfo; +import org.onap.vid.aai.HttpResponseWithRequestInfo; import org.onap.vid.asdc.AsdcCatalogException; import org.onap.vid.asdc.AsdcClient; import org.onap.vid.asdc.beans.Service; @@ -34,20 +44,16 @@ import org.onap.vid.asdc.parser.ToscaParserImpl; import org.onap.vid.asdc.parser.ToscaParserImpl2; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.ServiceModel; +import org.onap.vid.model.probes.ErrorMetadata; import org.onap.vid.model.probes.ExternalComponentStatus; import org.onap.vid.model.probes.HttpRequestMetadata; +import org.onap.vid.model.probes.StatusMetadata; +import org.onap.vid.properties.VidProperties; import org.onap.vid.utils.Logging; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.togglz.core.manager.FeatureManager; -import java.nio.file.Path; -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - -import static org.onap.vid.properties.Features.FLAG_SERVICE_MODEL_CACHE; - /** * The Class VidController. */ @@ -150,6 +156,20 @@ public class VidServiceImpl implements VidService { @Override public ExternalComponentStatus probeComponent() { + UUID modelUUID; + try { + modelUUID = UUID.fromString(VidProperties.getPropertyWithDefault( + VidProperties.PROBE_SDC_MODEL_UUID,"")); + } + //in case of no such PROBE_SDC_MODEL_UUID property or non uuid there we check only sdc connectivity + catch (Exception e) { + return probeComponentBySdcConnectivity(); + } + + return probeSdcByGettingModel(modelUUID); + } + + public ExternalComponentStatus probeComponentBySdcConnectivity() { long startTime = System.currentTimeMillis(); ExternalComponentStatus externalComponentStatus; try { @@ -158,10 +178,49 @@ public class VidServiceImpl implements VidService { System.currentTimeMillis() - startTime); externalComponentStatus = new ExternalComponentStatus(ExternalComponentStatus.Component.SDC, stringHttpResponse.isSuccessful(), httpRequestMetadata); } catch (Exception e) { - HttpRequestMetadata httpRequestMetadata = new HttpRequestMetadata(HttpMethod.GET, 0, - AsdcClient.URIS.HEALTH_CHECK_ENDPOINT, "", Logging.exceptionToDescription(e), System.currentTimeMillis() - startTime); - externalComponentStatus = new ExternalComponentStatus(ExternalComponentStatus.Component.SDC, false, httpRequestMetadata); + ErrorMetadata errorMetadata = new ErrorMetadata(Logging.exceptionToDescription(e), System.currentTimeMillis() - startTime); + externalComponentStatus = new ExternalComponentStatus(ExternalComponentStatus.Component.SDC, false, errorMetadata); } return externalComponentStatus; } + + protected ExternalComponentStatus probeSdcByGettingModel(UUID modelUUID) { + final long startTime = System.currentTimeMillis(); + + HttpResponseWithRequestInfo response = null; + try { + response = asdcClient.getServiceInputStream(modelUUID, true); + int responseStatusCode = response.getResponse().getStatus(); + + if (responseStatusCode == 404) { + return errorStatus(response, startTime, "model " + modelUUID + " not found in SDC" + + " (consider updating vid probe configuration '" + VidProperties.PROBE_SDC_MODEL_UUID + "')"); + } else if (responseStatusCode >= 400) { + return errorStatus(response, startTime, "error while retrieving model " + modelUUID + " from SDC"); + } else { + InputStream inputStreamEntity = response.getResponse().getRawBody();//validate we can read the input steam from the response + if (inputStreamEntity.read() <= 0) { + return errorStatus(response, startTime, "error reading model " + modelUUID + " from SDC"); + } else { + // RESPONSE IS SUCCESS + return new ExternalComponentStatus(SDC, true, + new HttpRequestMetadata(response, "OK", startTime, false)); + } + } + } catch (ExceptionWithRequestInfo e) { + return new ExternalComponentStatus(SDC, false, + new HttpRequestMetadata(e, System.currentTimeMillis() - startTime)); + } catch (Exception e) { + return errorStatus(response, startTime, Logging.exceptionToDescription(e)); + } + } + + private ExternalComponentStatus errorStatus(HttpResponseWithRequestInfo response, long startTime, String description) { + final long duration = System.currentTimeMillis() - startTime; + StatusMetadata statusMetadata = (response == null) ? + new ErrorMetadata(description, duration) : + new HttpRequestMetadata(response, description, duration, true); + + return new ExternalComponentStatus(SDC, false, statusMetadata); + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/AaiClientTest.java b/vid-app-common/src/test/java/org/onap/vid/aai/AaiClientTest.java index b2d8e85fa..9793862ca 100644 --- a/vid-app-common/src/test/java/org/onap/vid/aai/AaiClientTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/aai/AaiClientTest.java @@ -56,6 +56,7 @@ import java.net.URI; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Map; +import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.stream.Stream; diff --git a/vid-app-common/src/test/java/org/onap/vid/asdc/local/LocalAsdcClient.java b/vid-app-common/src/test/java/org/onap/vid/asdc/local/LocalAsdcClient.java new file mode 100644 index 000000000..2f5853e47 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/asdc/local/LocalAsdcClient.java @@ -0,0 +1,232 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 Nokia. 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.asdc.local; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.joshworks.restclient.http.HttpResponse; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.UUID; +import org.json.JSONArray; +import org.json.JSONObject; +import org.onap.vid.aai.HttpResponseWithRequestInfo; +import org.onap.vid.asdc.AsdcCatalogException; +import org.onap.vid.asdc.AsdcClient; +import org.onap.vid.asdc.beans.Service; +import org.onap.vid.exceptions.GenericUncheckedException; + +/** + * The Class LocalAsdcClient. + */ +public class LocalAsdcClient implements AsdcClient { + + + public static final String SERVICES = "services"; + /** + * The catalog. + */ + private final JSONObject catalog; + + /** + * The mapper. + */ + private final ObjectMapper mapper; + + /** + * Instantiates a new in local sdc client. + * + * @param builder the builder + */ + public LocalAsdcClient(org.onap.vid.asdc.local.LocalAsdcClient.Builder builder) { + catalog = builder.catalog; + mapper = builder.mapper; + } + + /** + * Gets the catalog. + * + * @return the catalog + */ + private JSONObject getCatalog() { + return catalog; + } + + /** + * Gets the mapper. + * + * @return the mapper + */ + private ObjectMapper getMapper() { + return mapper; + } + + /** + * Convert. + * + * @param the generic type + * @param json the json + * @param clazz the clazz + * @return the t + * @throws AsdcCatalogException the sdc catalog exception + */ + private T convert(JSONObject json, Class clazz) throws AsdcCatalogException { + try { + return getMapper().readValue(json.toString(), clazz); + } catch (JsonParseException e) { + throw new AsdcCatalogException("Failed to parse SDC response (bad data)", e); + } catch (JsonMappingException e) { + throw new AsdcCatalogException("Failed to map SDC response to internal VID data structure(s)", e); + } catch (IOException e) { + throw new AsdcCatalogException("Failed to get a response from SDC", e); + } + } + + /* (non-Javadoc) + * @see org.onap.vid.asdc.AsdcClient#getService(java.util.UUID) + */ + public Service getService(UUID uuid) throws AsdcCatalogException { + + JSONObject serviceJsonObject = null; + final JSONArray categoryJsonArray = getCatalog().getJSONArray(SERVICES); + + for (int i = 0; i < categoryJsonArray.length(); i++) { + JSONObject jsonServiceObject = categoryJsonArray.getJSONObject(i); + if (jsonServiceObject.get("uuid").equals(uuid.toString())) { + serviceJsonObject = jsonServiceObject; + break; + } + } + + if (serviceJsonObject != null) + return convert(serviceJsonObject, Service.class); + else return null; + } + + /* (non-Javadoc) + * @see org.onap.vid.asdc.AsdcClient#getServiceToscaModel(java.util.UUID) + */ + public Path getServiceToscaModel(UUID serviceUuid) { + + String toscaModelURL = null; + + final JSONArray categoryJsonArray = getCatalog().getJSONArray(SERVICES); + + for (int i = 0; i < categoryJsonArray.length(); i++) { + + JSONObject jsonServiceObject = categoryJsonArray.getJSONObject(i); + if (jsonServiceObject.get("uuid").equals(serviceUuid.toString())) { + toscaModelURL = jsonServiceObject.getString("toscaModelURL"); + } + } + if (toscaModelURL == null) { + return null; + } + ClassLoader classLoader = getClass().getClassLoader(); + + try { + File file = new File(classLoader.getResource(toscaModelURL).getFile()); + //using URLDecoder.decode to convert special characters from %XX to real character + //see https://stackoverflow.com/questions/32251251/java-classloader-getresource-with-special-characters-in-path + return Paths.get(URLDecoder.decode(file.getPath(), "UTF-8")); + } catch (RuntimeException | UnsupportedEncodingException e) { + throw new GenericUncheckedException("Can't find " + toscaModelURL, e); + } + } + + @Override + public HttpResponse checkSDCConnectivity() { + return HttpResponse.fallback(""); + } + + @Override + public HttpResponseWithRequestInfo getServiceInputStream(UUID serviceUuid, boolean warpException) { + return null; + } + + @Override + public String getBaseUrl(){ + return ""; + } + + /** + * The Class Builder. + */ + public static class Builder { + + /** + * The catalog. + */ + private JSONObject catalog = new JSONObject() + .put("resources", new JSONObject()) + .put(SERVICES, new JSONObject()); + + /** + * The mapper. + */ + private ObjectMapper mapper = new ObjectMapper(); + + /** + * Instantiates a new builder. + */ + public Builder() { + } + + /** + * Catalog. + * + * @param catalog the catalog + * @return the builder + */ + public org.onap.vid.asdc.local.LocalAsdcClient.Builder catalog(JSONObject catalog) { + this.catalog = catalog; + return this; + } + + /** + * Mapper. + * + * @param mapper the mapper + * @return the builder + */ + public org.onap.vid.asdc.local.LocalAsdcClient.Builder mapper(ObjectMapper mapper) { + this.mapper = mapper; + return this; + } + + /** + * Builds the. + * + * @return the in local sdc client + */ + public org.onap.vid.asdc.local.LocalAsdcClient build() { + return new org.onap.vid.asdc.local.LocalAsdcClient(this); + } + } + +} diff --git a/vid-app-common/src/test/java/org/onap/vid/services/VidServiceImplTest.java b/vid-app-common/src/test/java/org/onap/vid/services/VidServiceImplTest.java index ff6b7f0b1..65712b423 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/VidServiceImplTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/VidServiceImplTest.java @@ -21,27 +21,44 @@ package org.onap.vid.services; import static java.util.stream.Collectors.toMap; +import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.IsSame.sameInstance; import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.testng.AssertJUnit.assertTrue; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.joshworks.restclient.http.HttpResponse; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.util.Map; import java.util.UUID; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.ws.rs.ProcessingException; +import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.reflect.FieldUtils; +import org.apache.commons.lang3.tuple.Triple; import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; +import org.onap.vid.aai.ExceptionWithRequestInfo; +import org.onap.vid.aai.HttpResponseWithRequestInfo; import org.onap.vid.asdc.AsdcCatalogException; import org.onap.vid.asdc.AsdcClient; import org.onap.vid.asdc.beans.Service; @@ -50,7 +67,10 @@ import org.onap.vid.model.ServiceModel; import org.onap.vid.model.probes.ExternalComponentStatus; import org.onap.vid.model.probes.HttpRequestMetadata; import org.onap.vid.properties.Features; +import org.onap.vid.testUtils.TestUtils; +import org.springframework.http.HttpMethod; import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.togglz.core.manager.FeatureManager; @@ -151,10 +171,7 @@ public class VidServiceImplTest { @Test public void shouldCheckConnectionToSdc() { - when(asdcClientMock.checkSDCConnectivity()).thenReturn(httpResponse); - when(httpResponse.isSuccessful()).thenReturn(true); - when(httpResponse.getBody()).thenReturn("sampleBody"); - + mockGoodSdcConnectivityResponse(); ExternalComponentStatus externalComponentStatus = vidService.probeComponent(); @@ -164,6 +181,12 @@ public class VidServiceImplTest { assertThat(metadata.getRawData(), is("sampleBody")); } + private void mockGoodSdcConnectivityResponse() { + when(asdcClientMock.checkSDCConnectivity()).thenReturn(httpResponse); + when(httpResponse.isSuccessful()).thenReturn(true); + when(httpResponse.getBody()).thenReturn("sampleBody"); + } + @Test public void shouldProperlyHandleNotWorkingSDCConnection(){ when(asdcClientMock.checkSDCConnectivity()).thenThrow(new RuntimeException("not working")); @@ -173,5 +196,129 @@ public class VidServiceImplTest { assertThat(externalComponentStatus.isAvailable(), is(false)); assertThat(externalComponentStatus.getMetadata().getDescription(),containsString("not working")); } + + @Test + public void shouldNotProbeBySdcConnectionIfProbeUuidConfigured() throws Exception { + TestUtils.testWithSystemProperty( + "probe.sdc.model.uuid", + UUID.randomUUID().toString(), + ()->{ + mockGoodSdcConnectivityResponse(); //no mocking for probeSdcByGettingModel + ExternalComponentStatus externalComponentStatus = vidService.probeComponent(); + assertThat(externalComponentStatus.isAvailable(), is(false)); + } + ); + } + + + @Test + public void givenProbeUUID_whenAsdcClientReturnNormal_thenProbeComponentReturnAvailableAnswer() throws Exception { + + final UUID uuidForProbe = UUID.randomUUID(); + final HttpResponse mockResponse = mock(HttpResponse.class); + responseSetupper(mockResponse, 200, new ByteArrayInputStream(RandomUtils.nextBytes(66000))); + when(asdcClientMock.getServiceInputStream(eq(uuidForProbe), eq(true))).thenReturn( + new HttpResponseWithRequestInfo(mockResponse, "my pretty url", HttpMethod.GET) + ); + + TestUtils.testWithSystemProperty( + "probe.sdc.model.uuid", + uuidForProbe.toString(), + ()-> { + + ExternalComponentStatus sdcComponentStatus = vidService.probeComponent(); + assertTrue(sdcComponentStatus.isAvailable()); + assertThat(sdcComponentStatus.getComponent(), is(ExternalComponentStatus.Component.SDC)); + assertThat(sdcComponentStatus.getMetadata().getDescription(), equalTo("OK")); + assertThat(sdcComponentStatus.getMetadata(), instanceOf(HttpRequestMetadata.class)); + + HttpRequestMetadata componentStatusMetadata = ((HttpRequestMetadata) sdcComponentStatus.getMetadata()); + assertThat(componentStatusMetadata.getHttpMethod(), equalTo(HttpMethod.GET)); + assertThat(componentStatusMetadata.getHttpCode(), equalTo(200)); + assertThat(componentStatusMetadata.getUrl(), equalTo("my pretty url")); + } + ); + } + + private static void responseSetupper(HttpResponse r, Integer httpCode, InputStream body) { + when(r.getStatus()).thenReturn(httpCode); + when(r.getRawBody()).thenReturn(body); + } + + @DataProvider + public static Object[][] executionResults() { + final BiConsumer> defaultClientSetup = (c, r) -> + when(c.getServiceInputStream(any(), eq(true))).thenReturn(new HttpResponseWithRequestInfo(r, "foo url", HttpMethod.GET)); + + final ByteArrayInputStream defaultResponseBody = new ByteArrayInputStream(RandomUtils.nextBytes(200)); + + return Stream.>, Consumer>>>of( + + Triple.of( + new HttpRequestMetadata(null, 200, null, null, "IllegalStateException", 0), + defaultClientSetup, + r -> { + when(r.getStatus()).thenReturn(200); + when(r.getRawBody()).thenThrow(new IllegalStateException("good news for people who love bad news")); + } + ), + + Triple.of( + new HttpRequestMetadata(null, 200, null, null, "error reading model", 0), + defaultClientSetup, + r -> responseSetupper(r, 200, new ByteArrayInputStream(new byte[0])) + ), +// + Triple.of( + new HttpRequestMetadata(null, 200, null, null, "NullPointerException", 0), + defaultClientSetup, + r -> responseSetupper(r, 200, null) + ), +// + Triple.of( + new HttpRequestMetadata(null, 0, "bar url", null, "java.net.ConnectException: Connection refused", 0), + (c, r) -> + when(c.getServiceInputStream(any(), eq(true))).thenThrow(new ExceptionWithRequestInfo(HttpMethod.GET, "bar url", + new ProcessingException("java.net.ConnectException: Connection refused: connect"))), + r -> responseSetupper(r, 200, defaultResponseBody) + ), + + Triple.of( + new HttpRequestMetadata(null, 500, null, null, "error while retrieving model", 0), + defaultClientSetup, + r -> responseSetupper(r, 500, defaultResponseBody) + ), + + Triple.of( + new HttpRequestMetadata(null, 404, null, null, "updating vid probe configuration", 0), + defaultClientSetup, + r -> responseSetupper(r, 404, defaultResponseBody) + ) + + ).map(t -> ImmutableList.of(t.getLeft(), t.getMiddle(), t.getRight()).toArray()).collect(Collectors.toList()).toArray(new Object[][]{}); + } + + @Test(dataProvider = "executionResults") + public void whenClientReturnWithError_thenProbeSdcByGettingModelDescribes(HttpRequestMetadata expectedMetadata, + BiConsumer> clientSetup, + Consumer> responseSetup) { + + final HttpResponse mockResponse = mock(HttpResponse.class); + clientSetup.accept(asdcClientMock, mockResponse); + responseSetup.accept(mockResponse); + + ExternalComponentStatus sdcComponentStatus = vidService.probeSdcByGettingModel(UUID.randomUUID()); + assertThat(sdcComponentStatus.getComponent(), is(ExternalComponentStatus.Component.SDC)); + assertThat(sdcComponentStatus.getMetadata(), instanceOf(HttpRequestMetadata.class)); + + HttpRequestMetadata componentStatusMetadata = ((HttpRequestMetadata) sdcComponentStatus.getMetadata()); + assertThat(componentStatusMetadata.getDescription(), containsString(defaultIfNull(expectedMetadata.getDescription(), "OK"))); + assertThat(componentStatusMetadata.getHttpMethod(), equalTo(defaultIfNull(expectedMetadata.getHttpMethod(), HttpMethod.GET))); + assertThat(componentStatusMetadata.getHttpCode(), equalTo(expectedMetadata.getHttpCode())); + assertThat(componentStatusMetadata.getUrl(), equalTo(defaultIfNull(expectedMetadata.getUrl(), "foo url"))); + + assertThat(sdcComponentStatus.isAvailable(), is(false)); + } + } -- cgit 1.2.3-korg