Update css file name in conf.py
[policy/engine.git] / ONAP-PAP-REST / src / main / java / org / onap / policy / pap / xacml / rest / elk / client / ElkConnectorImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-PAP-REST
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.policy.pap.xacml.rest.elk.client;
22
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
36 import java.io.IOException;
37 import java.util.Map;
38 import java.util.Map.Entry;
39
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;
48
49 public class ElkConnectorImpl implements ElkConnector {
50
51     private static final Logger LOGGER = FlexLogger.getLogger(ElkConnector.class);
52
53     protected final JestClientFactory jestFactory = new JestClientFactory();
54     protected final JestClient jestClient;
55     protected static int QUERY_MAXRECORDS = 1000;
56
57     public ElkConnectorImpl() {
58         if (LOGGER.isDebugEnabled()) {
59             LOGGER.debug("ENTER: -");
60         }
61         HttpClientConfig jestClientConfig = new HttpClientConfig.Builder(ELK_URL).multiThreaded(true).build();
62         jestFactory.setHttpClientConfig(jestClientConfig);
63         jestClient = jestFactory.getObject();
64     }
65
66     protected boolean isType(PolicyIndexType type) throws IOException {
67         if (LOGGER.isDebugEnabled()) {
68             LOGGER.debug("ENTER: -");
69         }
70
71         try {
72             Action<JestResult> typeQuery = new TypeExist.Builder(ELK_INDEX_POLICY).addType(type.toString()).build();
73             JestResult result = jestClient.execute(typeQuery);
74
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());
80             }
81             return result.isSucceeded();
82         } catch (IOException e) {
83             LOGGER.warn("Error checking type existance of " + type.toString() + ": " + e.getMessage(), e);
84             throw e;
85         }
86     }
87
88     protected boolean isIndex() throws IOException {
89         try {
90             Action<JestResult> indexQuery = new IndicesExists.Builder(ELK_INDEX_POLICY).build();
91
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());
98             }
99             return result.isSucceeded();
100         } catch (IOException e) {
101             LOGGER.warn("Error checking index existance of " + ELK_INDEX_POLICY + ": " + e.getMessage(), e);
102             throw e;
103         }
104     }
105
106     private boolean isAlphaNumeric(String query) {
107         return query.matches("[a-zA-Z_0-9]+");
108     }
109
110     @Override
111     public JestResult search(PolicyIndexType type, String text) throws IllegalStateException, IllegalArgumentException {
112         if (LOGGER.isTraceEnabled()) {
113             LOGGER.trace("ENTER: " + text);
114         }
115
116         if (text == null || text.isEmpty()) {
117             throw new IllegalArgumentException("No search string provided");
118         }
119
120         if (!isAlphaNumeric(text)) {
121             throw new IllegalArgumentException("Search must be alpha numeric");
122         }
123
124         QueryStringQueryBuilder mQ = QueryBuilders.queryStringQuery("*" + text + "*");
125         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(mQ);
126
127         Builder searchBuilder = new Search.Builder(searchSourceBuilder.toString()).addIndex(ELK_INDEX_POLICY)
128                 .setParameter(Parameters.SIZE, ElkConnectorImpl.QUERY_MAXRECORDS);
129
130         if (type == null || type == PolicyIndexType.all) {
131             for (PolicyIndexType pT : PolicyIndexType.values()) {
132                 if (pT != PolicyIndexType.all) {
133                     searchBuilder.addType(pT.toString());
134                 }
135             }
136         } else {
137             searchBuilder.addType(type.toString());
138         }
139
140         Search search = searchBuilder.build();
141         JestResult result;
142         try {
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);
147         }
148
149         if (result.isSucceeded()) {
150             if (LOGGER.isInfoEnabled()) {
151                 LOGGER.info("OK:" + result.getResponseCode() + ":" + search + ": " + result.getPathToResult() + ":"
152                         + System.lineSeparator() + result.getJsonString());
153             }
154         } else {
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());
160             }
161
162             String errorMessage = result.getErrorMessage();
163             if (errorMessage != null && !errorMessage.isEmpty()) {
164                 String xMessage;
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);
180                 } else {
181                     xMessage = result.getErrorMessage();
182                 }
183                 throw new IllegalStateException(xMessage);
184             }
185         }
186
187         return result;
188     }
189
190     @Override
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);
195         }
196
197         if (filter_s == null || filter_s.size() == 0) {
198             return search(type, text);
199         }
200
201         if (!isAlphaNumeric(text)) {
202             throw new IllegalArgumentException("Search must be alpha numeric");
203         }
204
205         String matches_s = "";
206         matches_s = "{\n" + "    \"size\" : " + ElkConnectorImpl.QUERY_MAXRECORDS + ",\n" + "    \"query\": {\n"
207                 + "        \"bool\" : {\n" + "            \"must\" : [";
208
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();
214             if (first) {
215                 match_params = "\"match\" : {\"" + key + "\" : \"" + value + "\" }},";
216                 first = false;
217             } else {
218                 match_params = match_params + "{\"match\" : { \"" + key + "\" : \"" + value + "\" } },";
219             }
220         }
221         if (match_params.endsWith(",")) {
222             match_params = match_params.substring(0, match_params.length() - 2);
223         }
224
225         matches_s = matches_s + "{\n" + match_params + "\n}";
226
227         boolean query = false;
228         String query_String = "";
229         if (text != null) {
230             query = true;
231             query_String = "{\n \"query_string\" : {\n \"query\" : \"*" + text + "*\"\n} \n}";
232         }
233
234         if (query) {
235             matches_s = matches_s + "," + query_String + "]\n}\n}\n}";
236         } else {
237             matches_s = matches_s + "]\n}\n}\n}";
238         }
239
240         Builder searchBuilder = new Search.Builder(matches_s).addIndex(ELK_INDEX_POLICY);
241
242         if (type == null || type == PolicyIndexType.all) {
243             for (PolicyIndexType pT : PolicyIndexType.values()) {
244                 if (pT != PolicyIndexType.all) {
245                     searchBuilder.addType(pT.toString());
246                 }
247             }
248         } else {
249             searchBuilder.addType(type.toString());
250         }
251
252         Search search = searchBuilder.build();
253
254         JestResult result;
255         try {
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);
260         }
261
262         if (result.isSucceeded()) {
263             if (LOGGER.isInfoEnabled()) {
264                 LOGGER.info("OK:" + result.getResponseCode() + ":" + search + ": " + result.getPathToResult() + ":"
265                         + System.lineSeparator() + result.getJsonString());
266             }
267         } else {
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());
273             }
274
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);
293                 } else {
294                     xMessage = result.getErrorMessage();
295                 }
296                 throw new IllegalStateException(xMessage);
297             }
298         }
299
300         return result;
301     }
302
303     public boolean put(PolicyRestAdapter policyData) throws IOException, IllegalStateException {
304         if (LOGGER.isTraceEnabled())
305             LOGGER.trace("ENTER");
306
307         PolicyIndexType indexType;
308         try {
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_");
316             }
317
318             String[] splitPolicyName = policyName.split(":");
319             indexType = ElkConnector.toPolicyIndexType(splitPolicyName[1]);
320         } catch (IllegalArgumentException e) {
321             LOGGER.error(e);
322             throw new IllegalStateException("ELK: Index: " + ELK_INDEX_POLICY + e.getMessage());
323         }
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();
328
329         JestResult result = jestClient.execute(elkPut);
330
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());
336         } else {
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());
341
342         }
343
344         return result.isSucceeded();
345     }
346
347     @Override
348     public boolean delete(PolicyRestAdapter policyData) throws IllegalStateException {
349         PolicyIndexType indexType = null;
350         JestResult result;
351         try {
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_");
359             }
360
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");
366             }
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);
375         }
376
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());
382         } else {
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());
387         }
388
389         return result.isSucceeded();
390     }
391
392     @Override
393     public boolean update(PolicyRestAdapter policyData) throws IllegalStateException {
394         if (LOGGER.isDebugEnabled()) {
395             LOGGER.debug("ENTER");
396         }
397         try {
398             boolean success = put(policyData);
399             return success;
400         } catch (Exception e) {
401             LOGGER.warn(XACMLErrorConstants.ERROR_UNKNOWN + ":" + "cannot test and update", e);
402             throw new IllegalStateException(e);
403         }
404     }
405 }