2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2018 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=========================================================
20 package org.onap.policy.pap.xacml.rest.elk.client;
22 import java.io.IOException;
24 import java.util.Map.Entry;
26 import org.elasticsearch.index.query.QueryBuilders;
27 import org.elasticsearch.index.query.QueryStringQueryBuilder;
28 import org.elasticsearch.search.builder.SearchSourceBuilder;
29 import org.json.JSONObject;
30 import org.onap.policy.common.logging.flexlogger.FlexLogger;
31 import org.onap.policy.common.logging.flexlogger.Logger;
32 import org.onap.policy.rest.adapter.PolicyRestAdapter;
33 import org.onap.policy.xacml.api.XACMLErrorConstants;
35 import io.searchbox.action.Action;
36 import io.searchbox.client.JestClient;
37 import io.searchbox.client.JestClientFactory;
38 import io.searchbox.client.JestResult;
39 import io.searchbox.client.config.HttpClientConfig;
40 import io.searchbox.core.Delete;
41 import io.searchbox.core.Index;
42 import io.searchbox.core.Search;
43 import io.searchbox.core.Search.Builder;
44 import io.searchbox.indices.IndicesExists;
45 import io.searchbox.indices.type.TypeExist;
46 import io.searchbox.params.Parameters;
48 public class ElkConnectorImpl implements ElkConnector{
50 private static final Logger LOGGER = FlexLogger.getLogger(ElkConnector.class);
52 protected final JestClientFactory jestFactory = new JestClientFactory();
53 protected final JestClient jestClient;
54 protected static int QUERY_MAXRECORDS = 1000;
56 public ElkConnectorImpl() {
57 if (LOGGER.isDebugEnabled()){
58 LOGGER.debug("ENTER: -");
60 HttpClientConfig jestClientConfig = 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 = new TypeExist.Builder(ELK_INDEX_POLICY).addType(type.toString()).build();
72 JestResult result = jestClient.execute(typeQuery);
74 if (LOGGER.isInfoEnabled()) {
75 LOGGER.info("JSON:" + result.getJsonString());
76 LOGGER.info("ERROR:" + result.getErrorMessage());
77 LOGGER.info("PATH:" + result.getPathToResult());
78 LOGGER.info(result.getJsonObject());
80 return result.isSucceeded();
81 } catch (IOException e) {
82 LOGGER.warn("Error checking type existance of " + type.toString() + ": " + e.getMessage(), e);
87 protected boolean isIndex() throws IOException {
89 Action<JestResult> indexQuery = new IndicesExists.Builder(ELK_INDEX_POLICY).build();
91 JestResult result = jestClient.execute(indexQuery);
92 if (LOGGER.isInfoEnabled()) {
93 LOGGER.info("JSON:" + result.getJsonString());
94 LOGGER.info("ERROR:" + result.getErrorMessage());
95 LOGGER.info("PATH:" + result.getPathToResult());
96 LOGGER.info(result.getJsonObject());
98 return result.isSucceeded();
99 } catch (IOException e) {
100 LOGGER.warn("Error checking index existance of " + ELK_INDEX_POLICY + ": " + e.getMessage(), e);
104 private boolean isAlphaNumeric(String query){
105 return query.matches("[a-zA-Z_0-9]+");
109 public JestResult search(PolicyIndexType type, String text) throws IllegalStateException, IllegalArgumentException {
110 if (LOGGER.isTraceEnabled()){
111 LOGGER.trace("ENTER: " + text);
114 if (text == null || text.isEmpty()) {
115 throw new IllegalArgumentException("No search string provided");
118 if(!isAlphaNumeric(text)){
119 throw new IllegalArgumentException("Search must be alpha numeric");
122 QueryStringQueryBuilder mQ = QueryBuilders.queryStringQuery("*"+text+"*");
123 SearchSourceBuilder searchSourceBuilder =
124 new SearchSourceBuilder().query(mQ);
126 Builder searchBuilder = new Search.Builder(searchSourceBuilder.toString()).
127 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 + ":" +
146 search + ": " + ioe.getMessage(), ioe);
147 throw new IllegalStateException(ioe);
150 if (result.isSucceeded()) {
151 if (LOGGER.isInfoEnabled()){
152 LOGGER.info("OK:" + result.getResponseCode() + ":" + search + ": " +
153 result.getPathToResult() + ":" + System.lineSeparator() +
154 result.getJsonString());
157 /* Unsuccessful search */
158 if (LOGGER.isWarnEnabled()){
159 LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW + ":" +
160 result.getResponseCode() + ": " +
161 search.getURI() + ":" +
162 result.getPathToResult() + ":" +
163 result.getJsonString() + ":" +
164 result.getErrorMessage());
167 String errorMessage = result.getErrorMessage();
168 if (errorMessage != null && !errorMessage.isEmpty()) {
170 if (errorMessage.contains("TokenMgrError")) {
171 int indexError = errorMessage.lastIndexOf("TokenMgrError");
172 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
173 } else if (errorMessage.contains("QueryParsingException")) {
174 int indexError = errorMessage.lastIndexOf("QueryParsingException");
175 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
176 } else if (errorMessage.contains("JsonParseException")) {
177 int indexError = errorMessage.lastIndexOf("JsonParseException");
178 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
179 } else if (errorMessage.contains("Parse Failure")) {
180 int indexError = errorMessage.lastIndexOf("Parse Failure");
181 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
182 } else if (errorMessage.contains("SearchParseException")) {
183 int indexError = errorMessage.lastIndexOf("SearchParseException");
184 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
186 xMessage = result.getErrorMessage();
188 throw new IllegalStateException(xMessage);
197 public JestResult search(PolicyIndexType type, String text,
198 Map<String, String> filter_s)
199 throws IllegalStateException, IllegalArgumentException {
200 if (LOGGER.isTraceEnabled()){
201 LOGGER.trace("ENTER: " + text);
204 if (filter_s == null || filter_s.size() == 0) {
205 return search(type, text);
208 if(!isAlphaNumeric(text)){
209 throw new IllegalArgumentException("Search must be alpha numeric");
212 String matches_s = "";
214 " \"size\" : "+ ElkConnectorImpl.QUERY_MAXRECORDS + ",\n" +
219 String match_params = "";
220 boolean first = true;
221 for(Entry<String, String> entry : filter_s.entrySet()){
222 String key = entry.getKey();
223 String value = entry.getValue();
225 match_params = "\"match\" : {\""+key+"\" : \""+value+"\" }},";
228 match_params = match_params + "{\"match\" : { \""+key+"\" : \""+value+"\" } },";
231 if(match_params.endsWith(",")){
232 match_params = match_params.substring(0, match_params.length()-2);
235 matches_s = matches_s + "{\n" + match_params + "\n}" ;
237 boolean query = false;
238 String query_String = "";
241 query_String = "{\n \"query_string\" : {\n \"query\" : \"*"+text+"*\"\n} \n}";
245 matches_s = matches_s + "," + query_String + "]\n}\n}\n}";
247 matches_s = matches_s + "]\n}\n}\n}";
250 Builder searchBuilder = new Search.Builder(matches_s).addIndex(ELK_INDEX_POLICY);
252 if (type == null || type == PolicyIndexType.all) {
253 for (PolicyIndexType pT: PolicyIndexType.values()) {
254 if (pT != PolicyIndexType.all) {
255 searchBuilder.addType(pT.toString());
259 searchBuilder.addType(type.toString());
262 Search search = searchBuilder.build();
266 result = jestClient.execute(search);
267 } catch (IOException ioe) {
268 LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + ":" +
269 search + ": " + ioe.getMessage(), ioe);
270 throw new IllegalStateException(ioe);
273 if (result.isSucceeded()) {
274 if (LOGGER.isInfoEnabled()){
275 LOGGER.info("OK:" + result.getResponseCode() + ":" + search + ": " +
276 result.getPathToResult() + ":" + System.lineSeparator() +
277 result.getJsonString());
280 /* Unsuccessful search */
281 if (LOGGER.isWarnEnabled()){
282 LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW + ":" +
283 result.getResponseCode() + ": " +
284 search.getURI() + ":" +
285 result.getPathToResult() + ":" +
286 result.getJsonString() + ":" +
287 result.getErrorMessage());
290 String errorMessage = result.getErrorMessage();
291 if (errorMessage != null && !errorMessage.isEmpty()) {
292 String xMessage = errorMessage;
293 if (errorMessage.contains("TokenMgrError")) {
294 int indexError = errorMessage.lastIndexOf("TokenMgrError");
295 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
296 } else if (errorMessage.contains("QueryParsingException")) {
297 int indexError = errorMessage.lastIndexOf("QueryParsingException");
298 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
299 } else if (errorMessage.contains("JsonParseException")) {
300 int indexError = errorMessage.lastIndexOf("JsonParseException");
301 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
302 } else if (errorMessage.contains("Parse Failure")) {
303 int indexError = errorMessage.lastIndexOf("Parse Failure");
304 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
305 } else if (errorMessage.contains("SearchParseException")) {
306 int indexError = errorMessage.lastIndexOf("SearchParseException");
307 xMessage = "Invalid Search Expression. Details: " + errorMessage.substring(indexError);
309 xMessage = result.getErrorMessage();
311 throw new IllegalStateException(xMessage);
318 public boolean put(PolicyRestAdapter policyData)
319 throws IOException, IllegalStateException {
320 if (LOGGER.isTraceEnabled()) LOGGER.trace("ENTER");
322 PolicyIndexType indexType;
324 String policyName = policyData.getNewFileName();
325 if(policyName.contains("Config_")){
326 policyName = policyName.replace(".Config_", ":Config_");
327 }else if(policyName.contains("Action_")){
328 policyName = policyName.replace(".Action_", ":Action_");
329 }else if(policyName.contains("Decision_")){
330 policyName = policyName.replace(".Decision_", ":Decision_");
333 String[] splitPolicyName = policyName.split(":");
334 indexType = ElkConnector.toPolicyIndexType(splitPolicyName[1]);
335 } catch (IllegalArgumentException e) {
337 throw new IllegalStateException("ELK: Index: " + ELK_INDEX_POLICY + e.getMessage());
339 PolicyElasticData elasticData = new PolicyElasticData(policyData);
340 JSONObject jsonObj = new JSONObject(elasticData);
341 Index elkPut = new Index.Builder(jsonObj.toString()).
342 index(ELK_INDEX_POLICY).
343 type(indexType.name()).
344 id(elasticData.getPolicyName()).
348 JestResult result = jestClient.execute(elkPut);
350 if (result.isSucceeded()) {
351 if (LOGGER.isInfoEnabled())
352 LOGGER.info("ElkConnector: OK: PUT operation of " + "->" + ": " +
353 "success=" + result.isSucceeded() + "[" + result.getResponseCode() + ":" +
354 result.getPathToResult() + "]" + System.lineSeparator() +
355 result.getJsonString());
357 if (LOGGER.isWarnEnabled())
358 LOGGER.warn("ElkConnector: FAILURE: PUT operation of "+ "->" + ": " +
359 "success=" + result.isSucceeded() + "[" + result.getResponseCode() + ":" +
360 result.getPathToResult() + "]" + System.lineSeparator() +
361 result.getJsonString());
365 return result.isSucceeded();
369 public boolean delete(PolicyRestAdapter policyData) throws IllegalStateException {
370 PolicyIndexType indexType = null;
373 String policyName = policyData.getNewFileName();
374 if(policyName.contains("Config_")){
375 policyName = policyName.replace(".Config_", ":Config_");
376 }else if(policyName.contains("Action_")){
377 policyName = policyName.replace(".Action_", ":Action_");
378 }else if(policyName.contains("Decision_")){
379 policyName = policyName.replace(".Decision_", ":Decision_");
382 String[] splitPolicyName = policyName.split(":");
383 indexType = ElkConnector.toPolicyIndexType(splitPolicyName[1]);
384 if (!isType(indexType)) {
385 throw new IllegalStateException("ELK: Index: " + ELK_INDEX_POLICY +
386 " Type: " + indexType +
387 " is not configured");
389 PolicyElasticData elasticData = new PolicyElasticData(policyData);
390 Delete deleteRequest = new Delete.Builder(elasticData.getPolicyName()).index(ELK_INDEX_POLICY).
391 type(indexType.name()).build();
392 result = jestClient.execute(deleteRequest);
393 } catch (IllegalArgumentException | IOException e) {
394 LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + ": delete:" +
395 indexType + ": null" + ":" + policyData.getNewFileName() + ": " +
397 throw new IllegalStateException(e);
400 if (result.isSucceeded()) {
401 if (LOGGER.isInfoEnabled())
402 LOGGER.info("OK: DELETE operation of " + indexType + ":" + policyData.getNewFileName() + ": " +
403 "success=" + result.isSucceeded() + "[" + result.getResponseCode() + ":" +
404 result.getPathToResult() + "]" + System.lineSeparator() +
405 result.getJsonString());
407 if (LOGGER.isWarnEnabled())
408 LOGGER.warn("FAILURE: DELETE operation of " + indexType + ":" + policyData.getNewFileName() + ": " +
409 "success=" + result.isSucceeded() + "[" + result.getResponseCode() + ":" +
410 result.getPathToResult() + "]" + System.lineSeparator() +
411 result.getJsonString());
414 return result.isSucceeded();
418 public boolean update(PolicyRestAdapter policyData) throws IllegalStateException {
419 if (LOGGER.isDebugEnabled()){
420 LOGGER.debug("ENTER");
423 boolean success = put(policyData);
425 } catch (Exception e) {
426 LOGGER.warn(XACMLErrorConstants.ERROR_UNKNOWN + ":" + "cannot test and update", e);
427 throw new IllegalStateException(e);