/**
* ============LICENSE_START=======================================================
- * DataRouter
+ * org.onap.aai
* ================================================================================
- * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
* Copyright © 2017 Amdocs
- * 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
+ * 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,
* limitations under the License.
* ============LICENSE_END=========================================================
*
- * ECOMP and OpenECOMP are trademarks
- * and service marks of AT&T Intellectual Property.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
*/
package org.openecomp.datarouter.policy;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectWriter;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.sun.jersey.core.util.MultivaluedMapImpl;
-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.openecomp.datarouter.util.DataRouterConstants;
import org.openecomp.datarouter.util.EntityOxmReferenceHelper;
import org.openecomp.datarouter.util.ExternalOxmModelProcessor;
+import org.openecomp.datarouter.util.NodeUtils;
import org.openecomp.datarouter.util.OxmModelLoader;
import org.openecomp.datarouter.util.RouterServiceUtil;
+import org.openecomp.datarouter.util.SearchServiceAgent;
import org.openecomp.datarouter.util.SearchSuggestionPermutation;
import org.openecomp.datarouter.util.Version;
import org.openecomp.datarouter.util.VersionedOxmEntities;
import org.openecomp.restclient.client.Headers;
import org.openecomp.restclient.client.OperationResult;
import org.openecomp.restclient.client.RestClient;
+import org.openecomp.restclient.enums.RestAuthenticationMode;
import org.openecomp.restclient.rest.HttpUtil;
-import org.openecomp.datarouter.util.NodeUtils;
import org.slf4j.MDC;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
public class EntityEventPolicy implements Processor {
public static final String additionalInfo = "Response of AAIEntityEventPolicy";
private static final String entitySearchSchema = "entitysearch_schema.json";
private static final String topographicalSearchSchema = "topographysearch_schema.json";
private Collection<ExternalOxmModelProcessor> externalOxmModelProcessors;
- RestClient searchClient = null;
private final String EVENT_HEADER = "event-header";
private final String ENTITY_HEADER = "entity";
Map<String, DynamicJAXBContext> oxmVersionContextMap = new HashMap<>();
private String oxmVersion = null;
- private String entityIndexTarget = null;
+ /** Agent for communicating with the Search Service. */
+ private SearchServiceAgent searchAgent = null;
+
+ /** Search index name for storing AAI event entities. */
+ private String entitySearchIndex;
+
+ /** Search index name for storing topographical search data. */
+ private String topographicalSearchIndex;
+
+ /** Search index name for suggestive search data. */
+ private String aggregateGenericVnfIndex;
+
private String entitySearchTarget = null;
- private String topographicalIndexTarget = null;
private String topographicalSearchTarget = null;
private String autoSuggestSearchTarget = null;
private String aggregationSearchVnfTarget = null;
srcDomain = config.getSourceDomain();
- entityIndexTarget =
- EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(), config.getSearchEndpoint(),
- config.getSearchEntitySearchIndex());
+ // Populate the index names.
+ entitySearchIndex = config.getSearchEntitySearchIndex();
+ topographicalSearchIndex = config.getSearchTopographySearchIndex();
+ aggregateGenericVnfIndex = config.getSearchAggregationVnfIndex();
+
+ // Instantiate the agent that we will use for interacting with the Search Service.
+ searchAgent = new SearchServiceAgent(config.getSearchCertName(),
+ config.getSearchKeystore(),
+ config.getSearchKeystorePwd(),
+ EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(),
+ config.getSearchEndpoint()),
+ config.getSearchEndpointDocuments(),
+ logger);
entitySearchTarget =
EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(), config.getSearchEndpoint(),
config.getSearchEntitySearchIndex(), config.getSearchEndpointDocuments());
- topographicalIndexTarget =
- EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(), config.getSearchEndpoint(),
- config.getSearchTopographySearchIndex());
-
topographicalSearchTarget = EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(),
config.getSearchEndpoint(), config.getSearchTopographySearchIndex());
- // Create REST client for search service
- searchClient = new RestClient().validateServerHostname(false).validateServerCertChain(true)
- .clientCertFile(DataRouterConstants.DR_HOME_AUTH + config.getSearchCertName())
- .clientCertPassword(Password.deobfuscate(config.getSearchKeystorePwd()))
- .trustStore(DataRouterConstants.DR_HOME_AUTH + config.getSearchKeystore());
-
autoSuggestSearchTarget =
EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(), config.getSearchEndpoint(),
config.getSearchEntityAutoSuggestIndex(), config.getSearchEndpointDocuments());
public void startup() {
// Create the indexes in the search service if they do not already exist.
- createSearchIndex(entityIndexTarget, entitySearchSchema);
- createSearchIndex(topographicalIndexTarget, topographicalSearchSchema);
+ searchAgent.createSearchIndex(entitySearchIndex, entitySearchSchema);
+ searchAgent.createSearchIndex(topographicalSearchIndex, topographicalSearchSchema);
logger.info(EntityEventPolicyMsgs.ENTITY_EVENT_POLICY_REGISTERED);
}
- /**
- * Creates an index through the search db abstraction
- *
- * @param searchRESTClient
- * the REST client configured to contact the search db
- * abstraction
- * @param searchTarget
- * the URL to attempt to create the search index
- * @param schemaLocation
- * the location of the mappings file for the index
- */
- private void createSearchIndex(String searchTarget, String schemaLocation) {
-
- logger.debug("Creating search index, searchTarget = " + searchTarget + ", schemaLocation = " + schemaLocation);
-
- MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
- headers.put("Accept", Arrays.asList("application/json"));
- headers.put(Headers.FROM_APP_ID, Arrays.asList("DL"));
- headers.put(Headers.TRANSACTION_ID, Arrays.asList(UUID.randomUUID().toString()));
-
- try {
-
- OperationResult result = searchClient.put(searchTarget, loadFileData(schemaLocation), headers,
- MediaType.APPLICATION_JSON_TYPE, null);
-
- if (!HttpUtil.isHttpResponseClassSuccess(result.getResultCode())) {
- logger.error(EntityEventPolicyMsgs.FAIL_TO_CREATE_SEARCH_INDEX, searchTarget, result.getFailureCause());
- } else {
- logger.info(EntityEventPolicyMsgs.SEARCH_INDEX_CREATE_SUCCESS, searchTarget);
- }
-
- } catch (Exception e) {
- logger.error(EntityEventPolicyMsgs.FAIL_TO_CREATE_SEARCH_INDEX, searchTarget, e.getLocalizedMessage());
- }
- }
-
- /**
- * Convenience method to load up all the data from a file into a string
- *
- * @param filename the filename to read from disk
- * @return the data contained within the file
- * @throws Exception
- */
- protected String loadFileData(String filename) throws Exception {
- StringBuilder data = new StringBuilder();
- try {
- BufferedReader in = new BufferedReader(new InputStreamReader(
- EntityEventPolicy.class.getClassLoader().getResourceAsStream("/" + filename),
- StandardCharsets.UTF_8));
- String line;
-
- while ((line = in.readLine()) != null) {
- data.append(line);
- }
- } catch (Exception e) {
- throw new Exception("Failed to read from file = " + filename + ".", e);
- }
-
- return data.toString();
- }
-
/**
* Convert object to json.
}
// Load the UEB payload data, any errors will result in a failure and discard
- JSONObject uebObjHeader = getUebHeaderAsJson(uebPayload);
+ JSONObject uebObjHeader = getUebContentAsJson(uebPayload, EVENT_HEADER);
if (uebObjHeader == null) {
- returnWithError(exchange, uebPayload, "Payload is missing event-header");
+ returnWithError(exchange, uebPayload, "Payload is missing " + EVENT_HEADER);
+ return;
+ }
+
+ JSONObject uebObjEntity = getUebContentAsJson(uebPayload, ENTITY_HEADER);
+ if (uebObjEntity == null) {
+ returnWithError(exchange, uebPayload, "Payload is missing " + ENTITY_HEADER);
return;
}
return;
}
- handleSearchServiceOperation(aaiEventEntity, action, this.entitySearchTarget);
+ handleSearchServiceOperation(aaiEventEntity, action, entitySearchIndex);
handleTopographicalData(uebPayload, action, entityType, oxmEntityType, oxmJaxbContext,
entityPrimaryKeyFieldName, entityPrimaryKeyFieldValue);
Map<String, OxmEntityDescriptor> rootDescriptor =
oxmEntities.getSuggestableEntityDescriptors();
if (!rootDescriptor.isEmpty()) {
- List<String> suggestibleAttributes = extractSuggestableAttr(oxmEntities, entityType);
+ List<String> suggestibleAttrInPayload = new ArrayList<String>();
+ List<String> suggestibleAttrInOxm = extractSuggestableAttr(oxmEntities, entityType);
+ if (suggestibleAttrInOxm != null) {
+ for (String attr: suggestibleAttrInOxm){
+ if ( uebObjEntity.has(attr) ){
+ suggestibleAttrInPayload.add(attr);
+ }
+ }
+ }
- if (suggestibleAttributes == null) {
+ if (suggestibleAttrInPayload.isEmpty()) {
return;
}
ae.setLink(entityLink);
ae.deriveFields(uebAsJson);
- handleSuggestiveSearchData(ae, action, this.aggregationSearchVnfTarget);
+ handleSearchServiceOperation(ae, action, this.aggregationSearchVnfTarget);
/*
* It was decided to silently ignore DELETE requests for resources we don't allow to be
* deleted. e.g. auto-suggestion deletion is not allowed while aggregation deletion is.
*/
if (!ACTION_DELETE.equalsIgnoreCase(action)) {
- SearchSuggestionPermutation searchSuggestionPermutation =
- new SearchSuggestionPermutation();
- List<ArrayList<String>> permutationsOfStatuses =
- searchSuggestionPermutation.getSuggestionsPermutation(suggestibleAttributes);
-
- // Now we have a list of all possible permutations for the status that are
- // defined for this entity type. Try inserting a document for every combination.
- for (ArrayList<String> permutation : permutationsOfStatuses) {
+ List<ArrayList<String>> listOfValidPowerSetElements =
+ SearchSuggestionPermutation.getNonEmptyUniqueLists(suggestibleAttrInPayload);
+
+ // Now we have a list containing the power-set (minus empty element) for the status that are
+ // available in the payload. Try inserting a document for every combination.
+ for (ArrayList<String> list : listOfValidPowerSetElements) {
SuggestionSearchEntity suggestionSearchEntity = new SuggestionSearchEntity();
suggestionSearchEntity.setEntityType(entityType);
- suggestionSearchEntity.setSuggestableAttr(permutation);
- suggestionSearchEntity.setPayloadFromResponse(uebAsJson);
+ suggestionSearchEntity.setSuggestableAttr(list);
suggestionSearchEntity.setEntityTypeAliases(suggestionAliases);
+ suggestionSearchEntity.setFilterBasedPayloadFromResponse(uebAsJson.get("entity"),
+ suggestibleAttrInOxm, list);
suggestionSearchEntity.setSuggestionInputPermutations(
suggestionSearchEntity.generateSuggestionInputPermutations());
if (suggestionSearchEntity.isSuggestableDoc()) {
try {
- suggestionSearchEntity.deriveFields();
+ suggestionSearchEntity.generateSearchSuggestionDisplayStringAndId();
} catch (NoSuchAlgorithmException e) {
logger.error(EntityEventPolicyMsgs.DISCARD_UPDATING_SEARCH_SUGGESTION_DATA,
"Cannot create unique SHA digest for search suggestion data. Exception: "
+ e.getLocalizedMessage());
}
- handleSuggestiveSearchData(suggestionSearchEntity, action,
+ handleSearchServiceOperation(suggestionSearchEntity, action,
this.autoSuggestSearchTarget);
}
}
/*
* Load the UEB JSON payload, any errors would result to a failure case response.
*/
- private JSONObject getUebHeaderAsJson(String payload) {
+ private JSONObject getUebContentAsJson(String payload, String contentKey) {
JSONObject uebJsonObj;
- JSONObject uebObjHeader;
+ JSONObject uebObjContent;
try {
uebJsonObj = new JSONObject(payload);
return null;
}
- if (uebJsonObj.has(EVENT_HEADER)) {
- uebObjHeader = uebJsonObj.getJSONObject(EVENT_HEADER);
+ if (uebJsonObj.has(contentKey)) {
+ uebObjContent = uebJsonObj.getJSONObject(contentKey);
} else {
- logger.debug(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, EVENT_HEADER);
- logger.error(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, EVENT_HEADER);
+ logger.debug(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, contentKey);
+ logger.error(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, contentKey);
return null;
}
- return uebObjHeader;
+ return uebObjContent;
}
String jsonPayload = aaiEventEntity.getAsJson();
// Run the GET to retrieve the ETAG from the search service
- OperationResult storedEntity =
- searchClient.get(entitySearchTarget+entityId, headers, MediaType.APPLICATION_JSON_TYPE);
+ OperationResult storedEntity = searchAgent.getDocument(entitySearchIndex, entityId);
if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) {
/*
// Do the PUT with new CER
((ObjectNode)node).put("crossEntityReferenceValues", newCer);
jsonPayload = NodeUtils.convertObjectToJson(node, false);
- searchClient.put(entitySearchTarget + entityId, jsonPayload, headers,
- MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+ searchAgent.putDocument(entitySearchIndex, entityId, jsonPayload, headers);
}
}
} else {
if (storedEntity.getResultCode() == 404) {
// entity not found, so attempt to do a PUT
- searchClient.put(entitySearchTarget + entityId, aaiEventEntity.getAsJson(), headers,
- MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+ searchAgent.putDocument(entitySearchIndex, entityId, aaiEventEntity.getAsJson(), headers);
} else {
logger.error(EntityEventPolicyMsgs.FAILED_TO_UPDATE_ENTITY_IN_DOCSTORE,
aaiEventEntity.getId(), "SYNC_ENTITY");
* @param target Resource to perform the operation on
* @param allowDeleteEvent Allow delete operation to be performed on resource
*/
- private void handleSuggestiveSearchData(DocumentStoreDataEntity eventEntity, String action,
- String target) {
- try {
- Map<String, List<String>> headers = new HashMap<>();
- headers.put(Headers.FROM_APP_ID, Arrays.asList("DataLayer"));
- headers.put(Headers.TRANSACTION_ID, Arrays.asList(MDC.get(MdcContext.MDC_REQUEST_ID)));
-
- String entityId = eventEntity.getId();
-
- if ((action.equalsIgnoreCase(ACTION_CREATE) && entityId != null)
- || action.equalsIgnoreCase(ACTION_UPDATE)) {
- // Run the GET to retrieve the ETAG from the search service
- OperationResult storedEntity =
- searchClient.get(target + entityId, headers, MediaType.APPLICATION_JSON_TYPE);
-
- if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) {
- List<String> etag = storedEntity.getHeaders().get(Headers.ETAG);
-
- if (etag != null && etag.size() > 0) {
- headers.put(Headers.IF_MATCH, etag);
- } else {
- logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId,
- entityId);
- }
- }
-
- String eventEntityStr = eventEntity.getAsJson();
-
- if (eventEntityStr != null) {
- searchClient.put(target + entityId, eventEntity.getAsJson(), headers,
- MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
- }
- } else if (action.equalsIgnoreCase(ACTION_CREATE)) {
- String eventEntityStr = eventEntity.getAsJson();
-
- if (eventEntityStr != null) {
- searchClient.post(target, eventEntityStr, headers, MediaType.APPLICATION_JSON_TYPE,
- MediaType.APPLICATION_JSON_TYPE);
- }
- } else if (action.equalsIgnoreCase(ACTION_DELETE)) {
- // Run the GET to retrieve the ETAG from the search service
- OperationResult storedEntity =
- searchClient.get(target + entityId, headers, MediaType.APPLICATION_JSON_TYPE);
-
- if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) {
- List<String> etag = storedEntity.getHeaders().get(Headers.ETAG);
-
- if (etag != null && etag.size() > 0) {
- headers.put(Headers.IF_MATCH, etag);
- } else {
- logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId,
- entityId);
- }
-
- searchClient.delete(target + eventEntity.getId(), headers, null);
- } else {
- logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId,
- entityId);
- }
- } else {
- logger.error(EntityEventPolicyMsgs.ENTITY_OPERATION_NOT_SUPPORTED, action);
- }
- } catch (IOException e) {
- logger.error(EntityEventPolicyMsgs.FAILED_TO_UPDATE_ENTITY_IN_DOCSTORE, eventEntity.getId(),
- action);
- }
- }
-
- private void handleSearchServiceOperation(DocumentStoreDataEntity eventEntity, String action,
- String target) {
+ private void handleSearchServiceOperation(DocumentStoreDataEntity eventEntity,
+ String action,
+ String index) {
try {
Map<String, List<String>> headers = new HashMap<>();
|| action.equalsIgnoreCase(ACTION_UPDATE)) {
// Run the GET to retrieve the ETAG from the search service
- OperationResult storedEntity =
- searchClient.get(target + entityId, headers, MediaType.APPLICATION_JSON_TYPE);
+ OperationResult storedEntity = searchAgent.getDocument(index, entityId);
if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) {
List<String> etag = storedEntity.getHeaders().get(Headers.ETAG);
if (etag != null && etag.size() > 0) {
headers.put(Headers.IF_MATCH, etag);
} else {
- logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId,
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, index,
entityId);
}
}
- searchClient.put(target + entityId, eventEntity.getAsJson(), headers,
- MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+ // Write the entity to the search service.
+ // PUT
+ searchAgent.putDocument(index, entityId, eventEntity.getAsJson(), headers);
} else if (action.equalsIgnoreCase(ACTION_CREATE)) {
- searchClient.post(target, eventEntity.getAsJson(), headers, MediaType.APPLICATION_JSON_TYPE,
- MediaType.APPLICATION_JSON_TYPE);
+ // Write the entry to the search service.
+ searchAgent.postDocument(index, eventEntity.getAsJson(), headers);
+
} else if (action.equalsIgnoreCase(ACTION_DELETE)) {
// Run the GET to retrieve the ETAG from the search service
- OperationResult storedEntity =
- searchClient.get(target + entityId, headers, MediaType.APPLICATION_JSON_TYPE);
+ OperationResult storedEntity = searchAgent.getDocument(index, entityId);
if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) {
List<String> etag = storedEntity.getHeaders().get(Headers.ETAG);
if (etag != null && etag.size() > 0) {
headers.put(Headers.IF_MATCH, etag);
} else {
- logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId,
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, index,
entityId);
}
- searchClient.delete(target + eventEntity.getId(), headers, null);
+ searchAgent.deleteDocument(index, eventEntity.getId(), headers);
} else {
- logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId,
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, index,
entityId);
}
} else {