X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=vid-app-common%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Fvid%2Faai%2FAaiClient.java;h=be77e2bc03f04d3fe49e8c78673de45aeb721d70;hb=52670a9e0b450074dfbe0d151925d0133bc8442a;hp=7b78f0712569bb9b9d86ec664b3f782425311f61;hpb=fc62274e8d15964d63c62bf0e2f4abc040252ee9;p=vid.git diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java b/vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java index 7b78f0712..be77e2bc0 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java @@ -20,15 +20,22 @@ package org.onap.vid.aai; +import static com.fasterxml.jackson.module.kotlin.ExtensionsKt.jacksonObjectMapper; import static java.util.Collections.emptyList; +import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toMap; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase; import static org.apache.commons.lang3.StringUtils.isEmpty; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import java.io.IOException; +import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URLEncoder; @@ -37,13 +44,17 @@ import java.util.List; import java.util.Map; import java.util.UUID; import java.util.function.Function; +import java.util.stream.Stream; import javax.inject.Inject; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.http.HttpStatus; import org.apache.http.client.utils.URIBuilder; +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; @@ -65,6 +76,8 @@ import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse; import org.onap.vid.aai.model.CustomQuerySimpleResult; import org.onap.vid.aai.model.GetServiceModelsByDistributionStatusResponse; import org.onap.vid.aai.model.LogicalLinkResponse; +import org.onap.vid.aai.model.ModelVer; +import org.onap.vid.aai.model.ModelVersions; import org.onap.vid.aai.model.OwningEntityResponse; import org.onap.vid.aai.model.PortDetailsTranslator; import org.onap.vid.aai.model.ProjectResponse; @@ -85,14 +98,10 @@ import org.onap.vid.utils.Unchecked; import org.springframework.http.HttpMethod; import org.springframework.web.util.UriUtils; -/** - - * Created by Oren on 7/4/17. - */ public class AaiClient implements AaiClientInterface { - private static final String QUERY_FORMAT_RESOURCE = "query?format=resource"; + public static final String QUERY_FORMAT_RESOURCE = "query?format=resource"; private static final String SERVICE_SUBSCRIPTIONS_PATH = "/service-subscriptions/service-subscription/"; private static final String MODEL_INVARIANT_ID = "&model-invariant-id="; private static final String QUERY_FORMAT_SIMPLE = "query?format=simple"; @@ -108,14 +117,14 @@ public class AaiClient implements AaiClientInterface { private final CacheProvider cacheProvider; - ObjectMapper objectMapper = new ObjectMapper(); + ObjectMapper objectMapper = jacksonObjectMapper(); /** * The logger */ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AaiClient.class); - private static final String GET_SERVICE_MODELS_RESPONSE_BODY = "{\"start\" : \"service-design-and-creation/models/\", \"query\" : \"query/serviceModels-byDistributionStatus?distributionStatus=DISTRIBUTION_COMPLETE_OK\"}"; + private static final String GET_SERVICE_MODELS_REQUEST_BODY = "{\"start\" : \"service-design-and-creation/models/\", \"query\" : \"query/serviceModels-byDistributionStatus?distributionStatus=DISTRIBUTION_COMPLETE_OK\"}"; @Inject public AaiClient(AAIRestInterface restController, PortDetailsTranslator portDetailsTranslator, CacheProvider cacheProvider) { @@ -153,7 +162,7 @@ public class AaiClient implements AaiClientInterface { private AaiResponse getServiceModelsByDistributionStatusNonCached(boolean propagateExceptions) { GetServiceModelsByDistributionStatusResponse response = typedAaiRest(QUERY_FORMAT_RESOURCE, GetServiceModelsByDistributionStatusResponse.class, - GET_SERVICE_MODELS_RESPONSE_BODY, HttpMethod.PUT, propagateExceptions); + GET_SERVICE_MODELS_REQUEST_BODY, HttpMethod.PUT, propagateExceptions); return new AaiResponse(response, "", HttpStatus.SC_OK); } @@ -279,6 +288,60 @@ public class AaiClient implements AaiClientInterface { .collect(toMap(SimpleResult::getNodeType, SimpleResult::getProperties)); } + @Override + public AaiResponse getVnfsByParamsForChangeManagement(String subscriberId, String serviceType, @Nullable String nfRole, + @Nullable String cloudRegion) { + String payloadAsString = ""; + ResponseWithRequestInfo response; + ImmutableMap payload = getMapForAAIQueryByParams(subscriberId, serviceType, + nfRole, cloudRegion); + try { + payloadAsString = JACKSON_OBJECT_MAPPER.writeValueAsString(payload); + } catch (JsonProcessingException e) { + logger.error(e.getMessage()); + ExceptionUtils.rethrow(e); + } + response = doAaiPut(QUERY_FORMAT_SIMPLE, payloadAsString, false, false); + AaiResponseWithRequestInfo aaiResponse = processAaiResponse(response, AaiGetVnfResponse.class, false); + verifyAaiResponseValidityOrThrowExc(aaiResponse, aaiResponse.getAaiResponse().getHttpCode()); + return aaiResponse.getAaiResponse(); + } + + private ImmutableMap getMapForAAIQueryByParams(String subscriberId, + String serviceType, @Nullable String nfRole, @Nullable String cloudRegion) { + // in a case cloudRegion is null using query/vnfs-fromServiceInstance-filter, + // otherwise using query/vnfs-fromServiceInstance-filterByCloudRegion + if (nfRole != null){ + if (cloudRegion != null){ + return ImmutableMap.of( + "start", ImmutableList + .of("/business/customers/customer/" + encodePathSegment(subscriberId) + "/service-subscriptions/service-subscription/" + encodePathSegment(serviceType) + "/service-instances"), + "query", "query/vnfs-fromServiceInstance-filterByCloudRegion?nfRole=" + nfRole + "&cloudRegionID=" + cloudRegion + "" + ); + }else { + return ImmutableMap.of( + "start", ImmutableList + .of("/business/customers/customer/" + encodePathSegment(subscriberId) + "/service-subscriptions/service-subscription/" + encodePathSegment(serviceType) + "/service-instances"), + "query", "query/vnfs-fromServiceInstance-filter?nfRole=" + nfRole + "" + ); + } + } + + if (cloudRegion != null){ + return ImmutableMap.of( + "start", ImmutableList + .of("/business/customers/customer/" + encodePathSegment(subscriberId) + "/service-subscriptions/service-subscription/" + encodePathSegment(serviceType) + "/service-instances"), + "query", "query/vnfs-fromServiceInstance-filterByCloudRegion?cloudRegionID=" + cloudRegion + "" + ); + } + + return ImmutableMap.of( + "start", ImmutableList + .of("/business/customers/customer/" + encodePathSegment(subscriberId) + "/service-subscriptions/service-subscription/" + encodePathSegment(serviceType) + "/service-instances"), + "query", "query/vnfs-fromServiceInstance-filter" + ); + } + private boolean isResourceExistByStatusCode(ResponseWithRequestInfo responseWithRequestInfo) { // 200 - is found // 404 - resource not found @@ -313,19 +376,20 @@ public class AaiClient implements AaiClientInterface { } final AaiResponseWithRequestInfo aaiResponse = processAaiResponse(responseWithRequestInfo, clz, VidObjectMapperType.FASTERXML, true); + verifyAaiResponseValidityOrThrowExc(aaiResponse, responseWithRequestInfo.getResponse().getStatus()); + return aaiResponse.getAaiResponse().getT(); + } + private void verifyAaiResponseValidityOrThrowExc(AaiResponseWithRequestInfo aaiResponse, int httpCode) { if (aaiResponse.getAaiResponse().getHttpCode() > 399 || aaiResponse.getAaiResponse().getT() == null) { throw new ExceptionWithRequestInfo(aaiResponse.getHttpMethod(), - aaiResponse.getRequestedUrl(), - aaiResponse.getRawData(), - responseWithRequestInfo.getResponse().getStatus(), - new InvalidAAIResponseException(aaiResponse.getAaiResponse())); + aaiResponse.getRequestedUrl(), + aaiResponse.getRawData(), + httpCode, + new InvalidAAIResponseException(aaiResponse.getAaiResponse())); } - - return aaiResponse.getAaiResponse().getT(); } - private String getUrlFromLIst(String url, String paramKey, List params){ int i = 0; for(String param: params){ @@ -395,7 +459,7 @@ public class AaiClient implements AaiClientInterface { } @Override - public AaiResponse getVNFData(String globalSubscriberId, String serviceType) { + public AaiResponse getVNFData(String globalSubscriberId, String serviceType) { String payload = "{\"start\": [\"business/customers/customer/" + globalSubscriberId + SERVICE_SUBSCRIPTIONS_PATH + encodePathSegment(serviceType) +"/service-instances\"]," + "\"query\": \"query/vnf-topology-fromServiceInstance\"}"; Response resp = doAaiPut(QUERY_FORMAT_SIMPLE, payload, false); @@ -421,13 +485,52 @@ public class AaiClient implements AaiClientInterface { sb.append(id); } - return doAaiGet("service-design-and-creation/models?depth=2"+ sb.toString(), false); + return doAaiGet("service-design-and-creation/models?depth=2" + sb.toString(), false); } @Override - public AaiResponse getSubscriberData(String subscriberId) { - String depth = "2"; - AaiResponse subscriberDataResponse; + public ModelVer getLatestVersionByInvariantId(String modelInvariantId) { + if (modelInvariantId.isEmpty()) { + throw new GenericUncheckedException("no invariant-id provided to getLatestVersionByInvariantId; request is rejected"); + } + + Response response = doAaiPut("query?format=resource&depth=0", "{\"start\": [\"service-design-and-creation/models/model/" + modelInvariantId + "\"],\"query\": \"query/serviceModels-byDistributionStatus?distributionStatus=DISTRIBUTION_COMPLETE_OK\"}",false); + AaiResponse aaiResponse = processAaiResponse(response, ModelVersions.class, null, VidObjectMapperType.FASTERXML); + + Stream modelVerStream = toModelVerStream(aaiResponse.getT()); + return maxModelVer(modelVerStream); + } + + protected Stream toModelVerStream(ModelVersions modelVersions) { + if (modelVersions == null) + return null; + + if (modelVersions == null) + return null; + + return Stream.of(modelVersions) + .map(ModelVersions::getResults) + .flatMap(java.util.Collection::stream) + .flatMap(map -> map.entrySet().stream()) + .filter(kv -> StringUtils.equals(kv.getKey(), "model-ver")) + .map(Map.Entry::getValue); + + } + + protected ModelVer maxModelVer(Stream modelVerStream) { + if (modelVerStream == null) + return null; + + return modelVerStream + .filter(modelVer -> StringUtils.isNotEmpty(modelVer.getModelVersion())) + .max(comparing(ModelVer::getModelVersion, comparing(DefaultArtifactVersion::new))) + .orElseThrow(() -> new GenericUncheckedException("Could not find any version")); + } + + @Override + public AaiResponse getSubscriberData(String subscriberId, boolean omitServiceInstances) { + String depth = omitServiceInstances ? "1" : "2"; + AaiResponse subscriberDataResponse; Response resp = doAaiGet(BUSINESS_CUSTOMERS_CUSTOMER + subscriberId + "?depth=" + depth, false); subscriberDataResponse = processAaiResponse(resp, Services.class, null); return subscriberDataResponse; @@ -454,7 +557,7 @@ public class AaiClient implements AaiClientInterface { @Override public AaiResponse getTenants(String globalCustomerId, String serviceType) { - if ((globalCustomerId == null || globalCustomerId.isEmpty()) || ((serviceType == null) || (serviceType.isEmpty())) ){ + if ((globalCustomerId == null || globalCustomerId.isEmpty()) || ((serviceType == null) || (serviceType.isEmpty()))){ return buildAaiResponseForGetTenantsFailure(" Failed to retrieve LCP Region & Tenants from A&AI, Subscriber ID or Service Type is missing."); } try { @@ -514,7 +617,7 @@ public class AaiClient implements AaiClientInterface { } } - private AaiResponse processAaiResponse(Response resp, Class classType, String responseBody) { + private AaiResponse processAaiResponse(Response resp, Class classType, String responseBody) { return processAaiResponse(resp, classType, responseBody, VidObjectMapperType.CODEHAUS); } @@ -736,11 +839,7 @@ public class AaiClient implements AaiClientInterface { } private static String encodePathSegment(String segmentToEncode) { - try { - return UriUtils.encodePathSegment(segmentToEncode, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new GenericUncheckedException("URI encoding failed unexpectedly", e); - } + return UriUtils.encodePathSegment(segmentToEncode, "UTF-8"); } @Override