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;
35 import java.io.IOException;
37 import java.util.Map.Entry;
38 import org.elasticsearch.index.query.QueryBuilders;
39 import org.elasticsearch.index.query.QueryStringQueryBuilder;
40 import org.elasticsearch.search.builder.SearchSourceBuilder;
41 import org.json.JSONObject;
42 import org.onap.policy.common.logging.flexlogger.FlexLogger;
43 import org.onap.policy.common.logging.flexlogger.Logger;
44 import org.onap.policy.rest.adapter.PolicyRestAdapter;
45 import org.onap.policy.xacml.api.XACMLErrorConstants;
47 public class ElkConnectorImpl implements ElkConnector {
49 private static final Logger LOGGER = FlexLogger.getLogger(ElkConnector.class);
51 protected final JestClientFactory jestFactory = new JestClientFactory();
52 protected final JestClient jestClient;
53 protected static int QUERY_MAXRECORDS = 1000;
55 public ElkConnectorImpl() {
56 if (LOGGER.isDebugEnabled()) {
57 LOGGER.debug("ENTER: -");
59 HttpClientConfig jestClientConfig =
60 new HttpClientConfig.Builder(ELK_URL).multiThreaded(true).build();
61 jestFactory.setHttpClientConfig(jestClientConfig);
62 jestClient = jestFactory.getObject();
65 protected boolean isType(PolicyIndexType type) throws IOException {
66 if (LOGGER.isDebugEnabled()) {
67 LOGGER.debug("ENTER: -");
71 Action<JestResult> typeQuery =
72 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) {
84 "Error checking type existance of " + type.toString() + ": " + e.getMessage(),
90 protected boolean isIndex() throws IOException {
92 Action<JestResult> indexQuery = new IndicesExists.Builder(ELK_INDEX_POLICY).build();
94 JestResult result = jestClient.execute(indexQuery);
95 if (LOGGER.isInfoEnabled()) {
96 LOGGER.info("JSON:" + result.getJsonString());
97 LOGGER.info("ERROR:" + result.getErrorMessage());
98 LOGGER.info("PATH:" + result.getPathToResult());
99 LOGGER.info(result.getJsonObject());
101 return result.isSucceeded();
102 } catch (IOException e) {
104 "Error checking index existance of " + ELK_INDEX_POLICY + ": " + e.getMessage(),
110 private boolean isAlphaNumeric(String query) {
111 return query.matches("[a-zA-Z_0-9]+");
115 public JestResult search(PolicyIndexType type, String text)
116 throws IllegalStateException, IllegalArgumentException {
117 if (LOGGER.isTraceEnabled()) {
118 LOGGER.trace("ENTER: " + text);
121 if (text == null || text.isEmpty()) {
122 throw new IllegalArgumentException("No search string provided");
125 if (!isAlphaNumeric(text)) {
126 throw new IllegalArgumentException("Search must be alpha numeric");
129 QueryStringQueryBuilder mQ = QueryBuilders.queryStringQuery("*" + text + "*");
130 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(mQ);
132 Builder searchBuilder =
133 new Search.Builder(searchSourceBuilder.toString()).addIndex(ELK_INDEX_POLICY)
134 .setParameter(Parameters.SIZE, ElkConnectorImpl.QUERY_MAXRECORDS);
136 if (type == null || type == PolicyIndexType.all) {
137 for (PolicyIndexType pT : PolicyIndexType.values()) {
138 if (pT != PolicyIndexType.all) {
139 searchBuilder.addType(pT.toString());
143 searchBuilder.addType(type.toString());
146 Search search = searchBuilder.build();
149 result = jestClient.execute(search);
150 } catch (IOException ioe) {
152 XACMLErrorConstants.ERROR_SYSTEM_ERROR + ":" + search + ": " + ioe.getMessage(),
154 throw new IllegalStateException(ioe);
157 if (result.isSucceeded()) {
158 if (LOGGER.isInfoEnabled()) {
159 LOGGER.info("OK:" + result.getResponseCode() + ":" + search + ": "
160 + result.getPathToResult() + ":" + System.lineSeparator()
161 + result.getJsonString());
164 /* Unsuccessful search */
165 if (LOGGER.isWarnEnabled()) {
166 LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW + ":" + result.getResponseCode()
167 + ": " + search.getURI() + ":" + result.getPathToResult() + ":"
168 + result.getJsonString() + ":" + result.getErrorMessage());
171 String errorMessage = result.getErrorMessage();
172 if (errorMessage != null && !errorMessage.isEmpty()) {
174 if (errorMessage.contains("TokenMgrError")) {
175 int indexError = errorMessage.lastIndexOf("TokenMgrError");
176 xMessage = "Invalid Search Expression. Details: "
177 + errorMessage.substring(indexError);
178 } else if (errorMessage.contains("QueryParsingException")) {
179 int indexError = errorMessage.lastIndexOf("QueryParsingException");
180 xMessage = "Invalid Search Expression. Details: "
181 + errorMessage.substring(indexError);
182 } else if (errorMessage.contains("JsonParseException")) {
183 int indexError = errorMessage.lastIndexOf("JsonParseException");
184 xMessage = "Invalid Search Expression. Details: "
185 + errorMessage.substring(indexError);
186 } else if (errorMessage.contains("Parse Failure")) {
187 int indexError = errorMessage.lastIndexOf("Parse Failure");
188 xMessage = "Invalid Search Expression. Details: "
189 + errorMessage.substring(indexError);
190 } else if (errorMessage.contains("SearchParseException")) {
191 int indexError = errorMessage.lastIndexOf("SearchParseException");
192 xMessage = "Invalid Search Expression. Details: "
193 + errorMessage.substring(indexError);
195 xMessage = result.getErrorMessage();
197 throw new IllegalStateException(xMessage);
206 public JestResult search(PolicyIndexType type, String text, Map<String, String> filter_s)
207 throws IllegalStateException, IllegalArgumentException {
208 if (LOGGER.isTraceEnabled()) {
209 LOGGER.trace("ENTER: " + text);
212 if (filter_s == null || filter_s.size() == 0) {
213 return search(type, text);
216 if (!isAlphaNumeric(text)) {
217 throw new IllegalArgumentException("Search must be alpha numeric");
220 String matches_s = "";
221 matches_s = "{\n" + " \"size\" : " + ElkConnectorImpl.QUERY_MAXRECORDS + ",\n"
222 + " \"query\": {\n" + " \"bool\" : {\n" + " \"must\" : [";
224 String match_params = "";
225 boolean first = true;
226 for (Entry<String, String> entry : filter_s.entrySet()) {
227 String key = entry.getKey();
228 String value = entry.getValue();
230 match_params = "\"match\" : {\"" + key + "\" : \"" + value + "\" }},";
234 match_params + "{\"match\" : { \"" + key + "\" : \"" + value + "\" } },";
237 if (match_params.endsWith(",")) {
238 match_params = match_params.substring(0, match_params.length() - 2);
241 matches_s = matches_s + "{\n" + match_params + "\n}";
243 boolean query = false;
244 String query_String = "";
247 query_String = "{\n \"query_string\" : {\n \"query\" : \"*" + text + "*\"\n} \n}";
251 matches_s = matches_s + "," + query_String + "]\n}\n}\n}";
253 matches_s = matches_s + "]\n}\n}\n}";
256 Builder searchBuilder = new Search.Builder(matches_s).addIndex(ELK_INDEX_POLICY);
258 if (type == null || type == PolicyIndexType.all) {
259 for (PolicyIndexType pT : PolicyIndexType.values()) {
260 if (pT != PolicyIndexType.all) {
261 searchBuilder.addType(pT.toString());
265 searchBuilder.addType(type.toString());
268 Search search = searchBuilder.build();
272 result = jestClient.execute(search);
273 } catch (IOException ioe) {
275 XACMLErrorConstants.ERROR_SYSTEM_ERROR + ":" + search + ": " + ioe.getMessage(),
277 throw new IllegalStateException(ioe);
280 if (result.isSucceeded()) {
281 if (LOGGER.isInfoEnabled()) {
282 LOGGER.info("OK:" + result.getResponseCode() + ":" + search + ": "
283 + result.getPathToResult() + ":" + System.lineSeparator()
284 + result.getJsonString());
287 /* Unsuccessful search */
288 if (LOGGER.isWarnEnabled()) {
289 LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW + ":" + result.getResponseCode()
290 + ": " + search.getURI() + ":" + result.getPathToResult() + ":"
291 + result.getJsonString() + ":" + result.getErrorMessage());
294 String errorMessage = result.getErrorMessage();
295 if (errorMessage != null && !errorMessage.isEmpty()) {
296 String xMessage = errorMessage;
297 if (errorMessage.contains("TokenMgrError")) {
298 int indexError = errorMessage.lastIndexOf("TokenMgrError");
299 xMessage = "Invalid Search Expression. Details: "
300 + errorMessage.substring(indexError);
301 } else if (errorMessage.contains("QueryParsingException")) {
302 int indexError = errorMessage.lastIndexOf("QueryParsingException");
303 xMessage = "Invalid Search Expression. Details: "
304 + errorMessage.substring(indexError);
305 } else if (errorMessage.contains("JsonParseException")) {
306 int indexError = errorMessage.lastIndexOf("JsonParseException");
307 xMessage = "Invalid Search Expression. Details: "
308 + errorMessage.substring(indexError);
309 } else if (errorMessage.contains("Parse Failure")) {
310 int indexError = errorMessage.lastIndexOf("Parse Failure");
311 xMessage = "Invalid Search Expression. Details: "
312 + errorMessage.substring(indexError);
313 } else if (errorMessage.contains("SearchParseException")) {
314 int indexError = errorMessage.lastIndexOf("SearchParseException");
315 xMessage = "Invalid Search Expression. Details: "
316 + errorMessage.substring(indexError);
318 xMessage = result.getErrorMessage();
320 throw new IllegalStateException(xMessage);
327 public boolean put(PolicyRestAdapter policyData) throws IOException, IllegalStateException {
328 if (LOGGER.isTraceEnabled())
329 LOGGER.trace("ENTER");
331 PolicyIndexType indexType;
333 String policyName = policyData.getNewFileName();
334 if (policyName.contains("Config_")) {
335 policyName = policyName.replace(".Config_", ":Config_");
336 } else if (policyName.contains("Action_")) {
337 policyName = policyName.replace(".Action_", ":Action_");
338 } else if (policyName.contains("Decision_")) {
339 policyName = policyName.replace(".Decision_", ":Decision_");
342 String[] splitPolicyName = policyName.split(":");
343 indexType = ElkConnector.toPolicyIndexType(splitPolicyName[1]);
344 } catch (IllegalArgumentException e) {
346 throw new IllegalStateException("ELK: Index: " + ELK_INDEX_POLICY + e.getMessage());
348 PolicyElasticData elasticData = new PolicyElasticData(policyData);
349 JSONObject jsonObj = new JSONObject(elasticData);
350 Index elkPut = new Index.Builder(jsonObj.toString()).index(ELK_INDEX_POLICY)
351 .type(indexType.name()).id(elasticData.getPolicyName()).refresh(true).build();
353 JestResult result = jestClient.execute(elkPut);
355 if (result.isSucceeded()) {
356 if (LOGGER.isInfoEnabled())
357 LOGGER.info("ElkConnector: OK: PUT operation of " + "->" + ": " + "success="
358 + result.isSucceeded() + "[" + result.getResponseCode() + ":"
359 + result.getPathToResult() + "]" + System.lineSeparator()
360 + result.getJsonString());
362 if (LOGGER.isWarnEnabled())
363 LOGGER.warn("ElkConnector: FAILURE: PUT operation of " + "->" + ": " + "success="
364 + result.isSucceeded() + "[" + result.getResponseCode() + ":"
365 + result.getPathToResult() + "]" + System.lineSeparator()
366 + result.getJsonString());
370 return result.isSucceeded();
374 public boolean delete(PolicyRestAdapter policyData) throws IllegalStateException {
375 PolicyIndexType indexType = null;
378 String policyName = policyData.getNewFileName();
379 if (policyName.contains("Config_")) {
380 policyName = policyName.replace(".Config_", ":Config_");
381 } else if (policyName.contains("Action_")) {
382 policyName = policyName.replace(".Action_", ":Action_");
383 } else if (policyName.contains("Decision_")) {
384 policyName = policyName.replace(".Decision_", ":Decision_");
387 String[] splitPolicyName = policyName.split(":");
388 indexType = ElkConnector.toPolicyIndexType(splitPolicyName[1]);
389 if (!isType(indexType)) {
390 throw new IllegalStateException("ELK: Index: " + ELK_INDEX_POLICY + " Type: "
391 + indexType + " is not configured");
393 PolicyElasticData elasticData = new PolicyElasticData(policyData);
394 Delete deleteRequest = new Delete.Builder(elasticData.getPolicyName())
395 .index(ELK_INDEX_POLICY).type(indexType.name()).build();
396 result = jestClient.execute(deleteRequest);
397 } catch (IllegalArgumentException | IOException e) {
398 LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + ": delete:" + indexType + ": null"
399 + ":" + policyData.getNewFileName() + ": " + e.getMessage(), e);
400 throw new IllegalStateException(e);
403 if (result.isSucceeded()) {
404 if (LOGGER.isInfoEnabled())
405 LOGGER.info("OK: DELETE operation of " + indexType + ":"
406 + policyData.getNewFileName() + ": " + "success=" + result.isSucceeded()
407 + "[" + result.getResponseCode() + ":" + result.getPathToResult() + "]"
408 + System.lineSeparator() + result.getJsonString());
410 if (LOGGER.isWarnEnabled())
411 LOGGER.warn("FAILURE: DELETE operation of " + indexType + ":"
412 + policyData.getNewFileName() + ": " + "success=" + result.isSucceeded()
413 + "[" + result.getResponseCode() + ":" + result.getPathToResult() + "]"
414 + System.lineSeparator() + result.getJsonString());
417 return result.isSucceeded();
421 public boolean update(PolicyRestAdapter policyData) throws IllegalStateException {
422 if (LOGGER.isDebugEnabled()) {
423 LOGGER.debug("ENTER");
426 boolean success = put(policyData);
428 } catch (Exception e) {
429 LOGGER.warn(XACMLErrorConstants.ERROR_UNKNOWN + ":" + "cannot test and update", e);
430 throw new IllegalStateException(e);