2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.pap.xacml.rest.elk.client;
23 import io.searchbox.action.Action;
24 import io.searchbox.client.JestClient;
25 import io.searchbox.client.JestClientFactory;
26 import io.searchbox.client.JestResult;
27 import io.searchbox.client.config.HttpClientConfig;
28 import io.searchbox.core.Delete;
29 import io.searchbox.core.Index;
30 import io.searchbox.core.Search;
31 import io.searchbox.core.Search.Builder;
32 import io.searchbox.indices.IndicesExists;
33 import io.searchbox.indices.type.TypeExist;
34 import io.searchbox.params.Parameters;
36 import java.io.IOException;
38 import java.util.Map.Entry;
40 import org.elasticsearch.index.query.QueryBuilders;
41 import org.elasticsearch.index.query.QueryStringQueryBuilder;
42 import org.elasticsearch.search.builder.SearchSourceBuilder;
43 import org.json.JSONObject;
44 import org.onap.policy.common.logging.flexlogger.FlexLogger;
45 import org.onap.policy.common.logging.flexlogger.Logger;
46 import org.onap.policy.rest.adapter.PolicyRestAdapter;
47 import org.onap.policy.xacml.api.XACMLErrorConstants;
49 public class ElkConnectorImpl implements ElkConnector {
51 private static final Logger LOGGER = FlexLogger.getLogger(ElkConnector.class);
53 protected final JestClientFactory jestFactory = new JestClientFactory();
54 protected final JestClient jestClient;
55 protected static int QUERY_MAXRECORDS = 1000;
57 public ElkConnectorImpl() {
58 if (LOGGER.isDebugEnabled()) {
59 LOGGER.debug("ENTER: -");
61 HttpClientConfig jestClientConfig = new HttpClientConfig.Builder(ELK_URL).multiThreaded(true).build();
62 jestFactory.setHttpClientConfig(jestClientConfig);
63 jestClient = jestFactory.getObject();
66 protected boolean isType(PolicyIndexType type) throws IOException {
67 if (LOGGER.isDebugEnabled()) {
68 LOGGER.debug("ENTER: -");
72 Action<JestResult> typeQuery = new TypeExist.Builder(ELK_INDEX_POLICY).addType(type.toString()).build();
73 JestResult result = jestClient.execute(typeQuery);
75 if (LOGGER.isInfoEnabled()) {
76 LOGGER.info("JSON:" + result.getJsonString());
77 LOGGER.info("ERROR:" + result.getErrorMessage());
78 LOGGER.info("PATH:" + result.getPathToResult());
79 LOGGER.info(result.getJsonObject());
81 return result.isSucceeded();
82 } catch (IOException e) {
83 LOGGER.warn("Error checking type existance of " + type.toString() + ": " + e.getMessage(), e);
88 protected boolean isIndex() throws IOException {
90 Action<JestResult> indexQuery = new IndicesExists.Builder(ELK_INDEX_POLICY).build();
92 JestResult result = jestClient.execute(indexQuery);
93 if (LOGGER.isInfoEnabled()) {
94 LOGGER.info("JSON:" + result.getJsonString());
95 LOGGER.info("ERROR:" + result.getErrorMessage());
96 LOGGER.info("PATH:" + result.getPathToResult());
97 LOGGER.info(result.getJsonObject());
99 return result.isSucceeded();
100 } catch (IOException e) {
101 LOGGER.warn("Error checking index existance of " + ELK_INDEX_POLICY + ": " + e.getMessage(), e);
106 private boolean isAlphaNumeric(String query) {
107 return query.matches("[a-zA-Z_0-9]+");
111 public JestResult search(PolicyIndexType type, String text) throws IllegalStateException, IllegalArgumentException {
112 if (LOGGER.isTraceEnabled()) {
113 LOGGER.trace("ENTER: " + text);
116 if (text == null || text.isEmpty()) {
117 throw new IllegalArgumentException("No search string provided");
120 if (!isAlphaNumeric(text)) {
121 throw new IllegalArgumentException("Search must be alpha numeric");
124 QueryStringQueryBuilder mQ = QueryBuilders.queryStringQuery("*" + text + "*");
125 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(mQ);
127 Builder searchBuilder = new Search.Builder(searchSourceBuilder.toString()).addIndex(ELK_INDEX_POLICY)
128 .setParameter(Parameters.SIZE, ElkConnectorImpl.QUERY_MAXRECORDS);
130 if (type == null || type == PolicyIndexType.all) {
131 for (PolicyIndexType pT : PolicyIndexType.values()) {
132 if (pT != PolicyIndexType.all) {
133 searchBuilder.addType(pT.toString());
137 searchBuilder.addType(type.toString());
140 Search search = searchBuilder.build();
143 result = jestClient.execute(search);
144 } catch (IOException ioe) {
145 LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + ":" + search + ": " + ioe.getMessage(), ioe);
146 throw new IllegalStateException(ioe);
149 if (result.isSucceeded()) {
150 if (LOGGER.isInfoEnabled()) {
151 LOGGER.info("OK:" + result.getResponseCode() + ":" + search + ": " + result.getPathToResult() + ":"
152 + System.lineSeparator() + result.getJsonString());
155 /* Unsuccessful search */
156 if (LOGGER.isWarnEnabled()) {
157 LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW + ":" + result.getResponseCode() + ": "
158 + search.getURI() + ":" + result.getPathToResult() + ":" + result.getJsonString() + ":"
159 + result.getErrorMessage());
162 String errorMessage = result.getErrorMessage();
163 if (errorMessage != null && !errorMessage.isEmpty()) {
165 if (errorMessage.contains("TokenMgrError")) {
166 int indexError = errorMessage.lastIndexOf("TokenMgrError");
167 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
168 } else if (errorMessage.contains("QueryParsingException")) {
169 int indexError = errorMessage.lastIndexOf("QueryParsingException");
170 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
171 } else if (errorMessage.contains("JsonParseException")) {
172 int indexError = errorMessage.lastIndexOf("JsonParseException");
173 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
174 } else if (errorMessage.contains("Parse Failure")) {
175 int indexError = errorMessage.lastIndexOf("Parse Failure");
176 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
177 } else if (errorMessage.contains("SearchParseException")) {
178 int indexError = errorMessage.lastIndexOf("SearchParseException");
179 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
181 xMessage = result.getErrorMessage();
183 throw new IllegalStateException(xMessage);
191 public JestResult search(PolicyIndexType type, String text, Map<String, String> filter_s)
192 throws IllegalStateException, IllegalArgumentException {
193 if (LOGGER.isTraceEnabled()) {
194 LOGGER.trace("ENTER: " + text);
197 if (filter_s == null || filter_s.size() == 0) {
198 return search(type, text);
201 if (!isAlphaNumeric(text)) {
202 throw new IllegalArgumentException("Search must be alpha numeric");
205 String matches_s = "";
206 matches_s = "{\n" + " \"size\" : " + ElkConnectorImpl.QUERY_MAXRECORDS + ",\n" + " \"query\": {\n"
207 + " \"bool\" : {\n" + " \"must\" : [";
209 String match_params = "";
210 boolean first = true;
211 for (Entry<String, String> entry : filter_s.entrySet()) {
212 String key = entry.getKey();
213 String value = entry.getValue();
215 match_params = "\"match\" : {\"" + key + "\" : \"" + value + "\" }},";
218 match_params = match_params + "{\"match\" : { \"" + key + "\" : \"" + value + "\" } },";
221 if (match_params.endsWith(",")) {
222 match_params = match_params.substring(0, match_params.length() - 2);
225 matches_s = matches_s + "{\n" + match_params + "\n}";
227 boolean query = false;
228 String query_String = "";
231 query_String = "{\n \"query_string\" : {\n \"query\" : \"*" + text + "*\"\n} \n}";
235 matches_s = matches_s + "," + query_String + "]\n}\n}\n}";
237 matches_s = matches_s + "]\n}\n}\n}";
240 Builder searchBuilder = new Search.Builder(matches_s).addIndex(ELK_INDEX_POLICY);
242 if (type == null || type == PolicyIndexType.all) {
243 for (PolicyIndexType pT : PolicyIndexType.values()) {
244 if (pT != PolicyIndexType.all) {
245 searchBuilder.addType(pT.toString());
249 searchBuilder.addType(type.toString());
252 Search search = searchBuilder.build();
256 result = jestClient.execute(search);
257 } catch (IOException ioe) {
258 LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + ":" + search + ": " + ioe.getMessage(), ioe);
259 throw new IllegalStateException(ioe);
262 if (result.isSucceeded()) {
263 if (LOGGER.isInfoEnabled()) {
264 LOGGER.info("OK:" + result.getResponseCode() + ":" + search + ": " + result.getPathToResult() + ":"
265 + System.lineSeparator() + result.getJsonString());
268 /* Unsuccessful search */
269 if (LOGGER.isWarnEnabled()) {
270 LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW + ":" + result.getResponseCode() + ": "
271 + search.getURI() + ":" + result.getPathToResult() + ":" + result.getJsonString() + ":"
272 + result.getErrorMessage());
275 String errorMessage = result.getErrorMessage();
276 if (errorMessage != null && !errorMessage.isEmpty()) {
277 String xMessage = errorMessage;
278 if (errorMessage.contains("TokenMgrError")) {
279 int indexError = errorMessage.lastIndexOf("TokenMgrError");
280 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
281 } else if (errorMessage.contains("QueryParsingException")) {
282 int indexError = errorMessage.lastIndexOf("QueryParsingException");
283 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
284 } else if (errorMessage.contains("JsonParseException")) {
285 int indexError = errorMessage.lastIndexOf("JsonParseException");
286 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
287 } else if (errorMessage.contains("Parse Failure")) {
288 int indexError = errorMessage.lastIndexOf("Parse Failure");
289 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
290 } else if (errorMessage.contains("SearchParseException")) {
291 int indexError = errorMessage.lastIndexOf("SearchParseException");
292 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
294 xMessage = result.getErrorMessage();
296 throw new IllegalStateException(xMessage);
303 public boolean put(PolicyRestAdapter policyData) throws IOException, IllegalStateException {
304 if (LOGGER.isTraceEnabled())
305 LOGGER.trace("ENTER");
307 PolicyIndexType indexType;
309 String policyName = policyData.getNewFileName();
310 if (policyName.contains("Config_")) {
311 policyName = policyName.replace(".Config_", ":Config_");
312 } else if (policyName.contains("Action_")) {
313 policyName = policyName.replace(".Action_", ":Action_");
314 } else if (policyName.contains("Decision_")) {
315 policyName = policyName.replace(".Decision_", ":Decision_");
318 String[] splitPolicyName = policyName.split(":");
319 indexType = ElkConnector.toPolicyIndexType(splitPolicyName[1]);
320 } catch (IllegalArgumentException e) {
322 throw new IllegalStateException("ELK: Index: " + ELK_INDEX_POLICY + e.getMessage());
324 PolicyElasticData elasticData = new PolicyElasticData(policyData);
325 JSONObject jsonObj = new JSONObject(elasticData);
326 Index elkPut = new Index.Builder(jsonObj.toString()).index(ELK_INDEX_POLICY).type(indexType.name())
327 .id(elasticData.getPolicyName()).refresh(true).build();
329 JestResult result = jestClient.execute(elkPut);
331 if (result.isSucceeded()) {
332 if (LOGGER.isInfoEnabled())
333 LOGGER.info("ElkConnector: OK: PUT operation of " + "->" + ": " + "success=" + result.isSucceeded()
334 + "[" + result.getResponseCode() + ":" + result.getPathToResult() + "]" + System.lineSeparator()
335 + result.getJsonString());
337 if (LOGGER.isWarnEnabled())
338 LOGGER.warn("ElkConnector: FAILURE: PUT operation of " + "->" + ": " + "success=" + result.isSucceeded()
339 + "[" + result.getResponseCode() + ":" + result.getPathToResult() + "]" + System.lineSeparator()
340 + result.getJsonString());
344 return result.isSucceeded();
348 public boolean delete(PolicyRestAdapter policyData) throws IllegalStateException {
349 PolicyIndexType indexType = null;
352 String policyName = policyData.getNewFileName();
353 if (policyName.contains("Config_")) {
354 policyName = policyName.replace(".Config_", ":Config_");
355 } else if (policyName.contains("Action_")) {
356 policyName = policyName.replace(".Action_", ":Action_");
357 } else if (policyName.contains("Decision_")) {
358 policyName = policyName.replace(".Decision_", ":Decision_");
361 String[] splitPolicyName = policyName.split(":");
362 indexType = ElkConnector.toPolicyIndexType(splitPolicyName[1]);
363 if (!isType(indexType)) {
364 throw new IllegalStateException(
365 "ELK: Index: " + ELK_INDEX_POLICY + " Type: " + indexType + " is not configured");
367 PolicyElasticData elasticData = new PolicyElasticData(policyData);
368 Delete deleteRequest = new Delete.Builder(elasticData.getPolicyName()).index(ELK_INDEX_POLICY)
369 .type(indexType.name()).build();
370 result = jestClient.execute(deleteRequest);
371 } catch (IllegalArgumentException | IOException e) {
372 LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + ": delete:" + indexType + ": null" + ":"
373 + policyData.getNewFileName() + ": " + e.getMessage(), e);
374 throw new IllegalStateException(e);
377 if (result.isSucceeded()) {
378 if (LOGGER.isInfoEnabled())
379 LOGGER.info("OK: DELETE operation of " + indexType + ":" + policyData.getNewFileName() + ": "
380 + "success=" + result.isSucceeded() + "[" + result.getResponseCode() + ":"
381 + result.getPathToResult() + "]" + System.lineSeparator() + result.getJsonString());
383 if (LOGGER.isWarnEnabled())
384 LOGGER.warn("FAILURE: DELETE operation of " + indexType + ":" + policyData.getNewFileName() + ": "
385 + "success=" + result.isSucceeded() + "[" + result.getResponseCode() + ":"
386 + result.getPathToResult() + "]" + System.lineSeparator() + result.getJsonString());
389 return result.isSucceeded();
393 public boolean update(PolicyRestAdapter policyData) throws IllegalStateException {
394 if (LOGGER.isDebugEnabled()) {
395 LOGGER.debug("ENTER");
398 boolean success = put(policyData);
400 } catch (Exception e) {
401 LOGGER.warn(XACMLErrorConstants.ERROR_UNKNOWN + ":" + "cannot test and update", e);
402 throw new IllegalStateException(e);