ChefAdapterImpl JUnits
[appc.git] / appc-adapters / appc-chef-adapter / appc-chef-adapter-bundle / src / main / java / org / onap / appc / adapter / chef / impl / ChefAdapterImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * =============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  * ============LICENSE_END=========================================================
23  */
24 package org.onap.appc.adapter.chef.impl;
25
26 import java.io.File;
27 import java.util.Arrays;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Properties;
31 import org.apache.commons.lang.StringUtils;
32 import org.apache.http.HttpEntity;
33 import org.apache.http.HttpResponse;
34 import org.apache.http.client.methods.HttpGet;
35 import org.apache.http.impl.client.CloseableHttpClient;
36 import org.apache.http.impl.client.HttpClients;
37 import org.apache.http.util.EntityUtils;
38 import org.json.JSONException;
39 import org.json.JSONObject;
40 import org.onap.appc.adapter.chef.ChefAdapter;
41 import org.onap.appc.adapter.chef.chefclient.api.ChefApiClient;
42 import org.onap.appc.adapter.chef.chefclient.ChefApiClientFactory;
43 import org.onap.appc.adapter.chef.chefclient.api.ChefResponse;
44 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
45 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
46 import com.att.eelf.configuration.EELFLogger;
47 import com.att.eelf.configuration.EELFManager;
48
49 /**
50  * This class implements the {@link ChefAdapter} interface. This interface defines the behaviors that our service
51  * provides.
52  */
53 public class ChefAdapterImpl implements ChefAdapter {
54
55     // chef server Initialize variable
56     private String username = StringUtils.EMPTY;
57     private String clientPrivatekey = StringUtils.EMPTY;
58     private String chefserver = StringUtils.EMPTY;
59     private String serverAddress = StringUtils.EMPTY;
60     private String organizations = StringUtils.EMPTY;
61
62     @SuppressWarnings("nls")
63     public static final String MDC_ADAPTER = "adapter";
64
65     @SuppressWarnings("nls")
66     public static final String MDC_SERVICE = "service";
67
68     @SuppressWarnings("nls")
69     public static final String OUTCOME_FAILURE = "failure";
70
71     @SuppressWarnings("nls")
72     public static final String OUTCOME_SUCCESS = "success";
73
74     @SuppressWarnings("nls")
75     public static final String PROPERTY_PROVIDER = "provider";
76
77     @SuppressWarnings("nls")
78     public static final String PROPERTY_PROVIDER_IDENTITY = "identity";
79
80     @SuppressWarnings("nls")
81     public static final String PROPERTY_PROVIDER_NAME = "name";
82
83     @SuppressWarnings("nls")
84     public static final String PROPERTY_PROVIDER_TENANT = "tenant";
85
86     @SuppressWarnings("nls")
87     public static final String PROPERTY_PROVIDER_TENANT_NAME = "name";
88
89     @SuppressWarnings("nls")
90     public static final String PROPERTY_PROVIDER_TENANT_PASSWORD = "password"; // NOSONAR
91
92     @SuppressWarnings("nls")
93     public static final String PROPERTY_PROVIDER_TENANT_USERID = "userid";
94
95     @SuppressWarnings("nls")
96     public static final String PROPERTY_PROVIDER_TYPE = "type";
97
98
99     private static final EELFLogger logger = EELFManager.getInstance().getLogger(ChefAdapterImpl.class);
100
101     private static final String CANNOT_FIND_PRIVATE_KEY_STR =
102         "Cannot find the private key in the APPC file system, please load the private key to ";
103
104     private static final String POSTING_REQUEST_JSON_ERROR_STR = "Error posting request due to invalid JSON block: ";
105     private static final String POSTING_REQUEST_ERROR_STR = "Error posting request: ";
106     private static final String CHEF_CLIENT_RESULT_CODE_STR = "chefClientResult.code";
107     private static final String CHEF_SERVER_RESULT_CODE_STR = "chefServerResult.code";
108     private static final String CHEF_CLIENT_RESULT_MSG_STR = "chefClientResult.message";
109     private static final String CHEF_SERVER_RESULT_MSG_STR = "chefServerResult.message";
110     private static final String CHEF_ACTION_STR = "chefAction";
111     private static final String NODE_LIST_STR = "NodeList";
112     private ChefApiClientFactory chefApiClientFactory = new ChefApiClientFactory();
113
114     /**
115      * This default constructor is used as a work around because the activator wasnt getting called
116      */
117     public ChefAdapterImpl() {
118         logger.info("Initialize Chef Adapter");
119     }
120
121     @SuppressWarnings("nls")
122     @Override
123     public void vnfcEnvironment(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
124         int code;
125         try {
126             logger.info("environment of VNF-C");
127             chefInfo(params, ctx);
128             RequestContext rc = new RequestContext(ctx);
129             logger.info("Context" + ctx);
130             rc.isAlive();
131             String env = params.get("Environment");
132             logger.info("Environmnet" + env);
133             if (env.equals(StringUtils.EMPTY)) {
134                 chefServerResult(rc, 200, "Skip Environment block ");
135             } else {
136                 JSONObject envJ = new JSONObject(env);
137                 String envName = envJ.getString("name");
138                 String message;
139                 if (privateKeyCheck()) {
140                     // update the details of an environment on the Chef server.
141                     ChefApiClient chefApiClient = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
142                     ChefResponse chefResponse = chefApiClient.put("/environments/" + envName, env);
143                     code = chefResponse.getStatusCode();
144                     message = chefResponse.getBody();
145                     if (code == 404) {
146                         // need create a new environment
147                         chefResponse = chefApiClient.post("/environments", env);
148                         code = chefResponse.getStatusCode();
149                         message = chefResponse.getBody();
150                         logger.info("requestbody {}", chefResponse.getBody());
151                     }
152
153                 } else {
154                     code = 500;
155                     message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
156                     doFailure(ctx, code, message);
157                 }
158                 chefServerResult(rc, code, message);
159             }
160         } catch (JSONException e) {
161             code = 401;
162             logger.error(POSTING_REQUEST_JSON_ERROR_STR, e);
163             doFailure(ctx, code, POSTING_REQUEST_JSON_ERROR_STR + e.getMessage());
164         } catch (Exception e) {
165             code = 401;
166             logger.error(POSTING_REQUEST_ERROR_STR, e);
167             doFailure(ctx, code, POSTING_REQUEST_ERROR_STR + e.getMessage());
168         }
169     }
170
171     @SuppressWarnings("nls")
172     @Override
173     public void vnfcNodeobjects(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
174         logger.info("update the nodeObjects of VNF-C");
175         int code;
176         try {
177             chefInfo(params, ctx);
178             String nodeListS = params.get(NODE_LIST_STR);
179             String nodeS = params.get("Node");
180             if (StringUtils.isNotBlank(nodeListS) && StringUtils.isNotBlank(nodeS)) {
181                 nodeListS = nodeListS.replace("[", StringUtils.EMPTY);
182                 nodeListS = nodeListS.replace("]", StringUtils.EMPTY);
183                 nodeListS = nodeListS.replace("\"", StringUtils.EMPTY);
184                 nodeListS = nodeListS.replace(" ", StringUtils.EMPTY);
185                 List<String> nodes = Arrays.asList(nodeListS.split("\\s*,\\s*"));
186                 RequestContext rc = new RequestContext(ctx);
187                 rc.isAlive();
188                 code = 200;
189                 String message = null;
190                 if (privateKeyCheck()) {
191                     ChefApiClient cac = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
192
193                     for (String nodeName: nodes) {
194                         JSONObject nodeJ = new JSONObject(nodeS);
195                         nodeJ.remove("name");
196                         nodeJ.put("name", nodeName);
197                         String nodeObject = nodeJ.toString();
198                         logger.info(nodeObject);
199                         ChefResponse chefResponse = cac.put("/nodes/" + nodeName, nodeObject);
200                         code = chefResponse.getStatusCode();
201                         message = chefResponse.getBody();
202                         if (code != 200) {
203                             break;
204                         }
205                     }
206                 } else {
207                     code = 500;
208                     message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
209                     doFailure(ctx, code, message);
210                 }
211                 chefServerResult(rc, code, message);
212             } else {
213                 throw new SvcLogicException("Missing Mandatory param(s) Node , NodeList ");
214             }
215         } catch (JSONException e) {
216             code = 401;
217             logger.error(POSTING_REQUEST_JSON_ERROR_STR, e);
218             doFailure(ctx, code, POSTING_REQUEST_JSON_ERROR_STR + e.getMessage());
219         } catch (Exception e) {
220             code = 401;
221             logger.error(POSTING_REQUEST_ERROR_STR, e);
222             doFailure(ctx, code, POSTING_REQUEST_ERROR_STR + e.getMessage());
223         }
224     }
225
226     @Override
227     public void vnfcPushJob(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
228         int code;
229         try {
230             chefInfo(params, ctx);
231             String nodeList = params.get(NODE_LIST_STR);
232             if (StringUtils.isNotBlank(nodeList)) {
233                 String isCallback = params.get("CallbackCapable");
234                 String chefAction = "/pushy/jobs";
235                 // need work on this
236                 String pushRequest;
237                 if ("true".equals(isCallback)) {
238                     String requestId = params.get("RequestId");
239                     String callbackUrl = params.get("CallbackUrl");
240                     pushRequest = "{" + "\"command\": \"chef-client\"," + "\"run_timeout\": 300," + "\"nodes\":"
241                         + nodeList + "," + "\"env\": {\"RequestId\": \"" + requestId + "\", \"CallbackUrl\": \""
242                         + callbackUrl + "\"}," + "\"capture_output\": true" + "}";
243                 } else {
244                     pushRequest = "{" + "\"command\": \"chef-client\"," + "\"run_timeout\": 300," + "\"nodes\":"
245                         + nodeList + "," + "\"env\": {}," + "\"capture_output\": true" + "}";
246                 }
247                 RequestContext rc = new RequestContext(ctx);
248
249                 rc.isAlive();
250                 SvcLogicContext svcLogic = rc.getSvcLogicContext();
251                 ChefApiClient cac = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
252                 ChefResponse chefResponse = cac.post(chefAction, pushRequest);
253                 code = chefResponse.getStatusCode();
254                 logger.info("pushRequest:" + pushRequest);
255                 logger.info("requestbody: {}", chefResponse.getBody());
256                 String message = chefResponse.getBody();
257                 if (code == 201) {
258                     int startIndex = message.indexOf("jobs") + 5;
259                     int endIndex = message.length() - 2;
260                     String jobID = message.substring(startIndex, endIndex);
261                     svcLogic.setAttribute("jobID", jobID);
262                     logger.info(jobID);
263                 }
264                 chefServerResult(rc, code, message);
265             } else {
266                 throw new SvcLogicException("Missing Mandatory param(s)  NodeList ");
267             }
268         } catch (JSONException e) {
269             code = 401;
270             logger.error(POSTING_REQUEST_JSON_ERROR_STR, e);
271             doFailure(ctx, code, POSTING_REQUEST_JSON_ERROR_STR + e.getMessage());
272         } catch (Exception e) {
273             code = 401;
274             logger.error(POSTING_REQUEST_ERROR_STR, e);
275             doFailure(ctx, code, POSTING_REQUEST_ERROR_STR + e.getMessage());
276         }
277     }
278
279     @SuppressWarnings("nls")
280     @Override
281     public void fetchResults(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
282         int code = 200;
283         try {
284             chefInfo(params, ctx);
285             String nodeListS = params.get(NODE_LIST_STR);
286             if (StringUtils.isNotBlank(nodeListS)) {
287                 nodeListS = nodeListS.replace("[", StringUtils.EMPTY);
288                 nodeListS = nodeListS.replace("]", StringUtils.EMPTY);
289                 nodeListS = nodeListS.replace("\"", StringUtils.EMPTY);
290                 nodeListS = nodeListS.replace(" ", StringUtils.EMPTY);
291                 List<String> nodes = Arrays.asList(nodeListS.split("\\s*,\\s*"));
292                 JSONObject result = new JSONObject();
293                 String returnMessage = StringUtils.EMPTY;
294
295                 for (String node : nodes) {
296                     String chefAction = "/nodes/" + node;
297                     String message;
298                     if (privateKeyCheck()) {
299                         ChefResponse chefResponse = getApiMethod(chefAction);
300                         code = chefResponse.getStatusCode();
301                         message = chefResponse.getBody();
302                     } else {
303                         code = 500;
304                         message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
305                         doFailure(ctx, code, message);
306                     }
307                     if (code == 200) {
308                         JSONObject nodeResult = new JSONObject();
309                         JSONObject allNodeData = new JSONObject(message);
310                         allNodeData = allNodeData.getJSONObject("normal");
311                         String attribute = "PushJobOutput";
312
313                         String resultData = allNodeData.optString(attribute);
314                         if (resultData == null) {
315                             resultData = allNodeData.optJSONObject(attribute).toString();
316
317                             if (resultData == null) {
318                                 resultData = allNodeData.optJSONArray(attribute).toString();
319
320                                 if (resultData == null) {
321                                     code = 500;
322                                     returnMessage = "Cannot find " + attribute;
323                                     break;
324                                 }
325                             }
326                         }
327                         nodeResult.put(attribute, resultData);
328                         result.put(node, nodeResult);
329                         returnMessage = result.toString();
330                     } else {
331                         code = 500;
332                         returnMessage = message + " Cannot access: " + node;
333                         doFailure(ctx, code, message);
334                         break;
335                     }
336                 }
337
338                 RequestContext rc = new RequestContext(ctx);
339                 rc.isAlive();
340                 chefServerResult(rc, code, returnMessage);
341             } else {
342                 throw new SvcLogicException("Missing Mandatory param(s)  NodeList ");
343             }
344         } catch (JSONException e) {
345             code = 401;
346             logger.error(POSTING_REQUEST_JSON_ERROR_STR, e);
347             doFailure(ctx, code, POSTING_REQUEST_JSON_ERROR_STR + e.getMessage());
348         } catch (Exception e) {
349             code = 401;
350             logger.error(POSTING_REQUEST_ERROR_STR , e);
351             doFailure(ctx, code, POSTING_REQUEST_ERROR_STR + e.getMessage());
352         }
353     }
354
355     private ChefResponse getApiMethod(String chefAction) {
356         ChefApiClient cac = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
357         return cac.get(chefAction);
358     }
359
360     /**
361      * build node object
362      */
363     @SuppressWarnings("nls")
364     @Override
365     public void nodeObejctBuilder(Map<String, String> params, SvcLogicContext ctx) {
366         logger.info("nodeObejctBuilder");
367         String name = params.get("nodeobject.name");
368         String normal = params.get("nodeobject.normal");
369         String overrides = params.get("nodeobject.overrides");
370         String defaults = params.get("nodeobject.defaults");
371         String runList = params.get("nodeobject.run_list");
372         String chefEnvironment = params.get("nodeobject.chef_environment");
373         String nodeObject = "{\"json_class\":\"Chef::Node\",\"default\":{" + defaults
374             + "},\"chef_type\":\"node\",\"run_list\":[" + runList + "],\"override\":{" + overrides
375             + "},\"normal\": {" + normal + "},\"automatic\":{},\"name\":\"" + name + "\",\"chef_environment\":\""
376             + chefEnvironment + "\",}";
377         logger.info(nodeObject);
378         ctx.setAttribute("chef.nodeObject", nodeObject);
379     }
380
381     /**
382      * send get request to chef server
383      */
384     private void chefInfo(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
385
386         username = params.get("username");
387         serverAddress = params.get("serverAddress");
388         organizations = params.get("organizations");
389         if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(serverAddress)
390             && StringUtils.isNotBlank(organizations)) {
391             chefserver = "https://" + serverAddress + "/organizations/" + organizations;
392             clientPrivatekey = "/opt/onap/appc/chef/" + serverAddress + "/" + organizations + "/" + username + ".pem";
393             logger.info(" clientPrivatekey  " + clientPrivatekey);
394         } else {
395             doFailure(ctx, 401, "Missing mandatory param(s) such as username, serverAddress, organizations");
396         }
397     }
398
399     private Boolean privateKeyCheck() {
400         File f = new File(clientPrivatekey);
401         if (f.exists()) {
402             logger.info("Key exists");
403             return true;
404         } else {
405             logger.info("Key doesn't exists");
406             return false;
407         }
408     }
409
410     @SuppressWarnings("nls")
411     @Override
412     public void retrieveData(Map<String, String> params, SvcLogicContext ctx) {
413         String allConfigData = params.get("allConfig");
414         String key = params.get("key");
415         String dgContext = params.get("dgContext");
416         JSONObject jsonConfig = new JSONObject(allConfigData);
417         String contextData = fetchContextData(key, jsonConfig);
418
419         ctx.setAttribute(dgContext, contextData);
420     }
421
422     private String fetchContextData(String key, JSONObject jsonConfig) {
423         try {
424             return jsonConfig.getString(key);
425         } catch (Exception e) {
426             logger.error("Failed getting string value corresponding to " + key + ". Trying to fetch nested json object", e);
427             try {
428                 return jsonConfig.getJSONObject(key).toString();
429             } catch (Exception ex) {
430                 logger.error("Failed getting json object corresponding to " + key + ". Trying to fetch array", ex);
431                 return jsonConfig.getJSONArray(key).toString();
432             }
433         }
434     }
435
436     @SuppressWarnings("nls")
437     @Override
438     public void combineStrings(Map<String, String> params, SvcLogicContext ctx) {
439         String string1 = params.get("String1");
440         String string2 = params.get("String2");
441         String dgContext = params.get("dgContext");
442         String contextData = string1 + string2;
443         ctx.setAttribute(dgContext, contextData);
444     }
445
446     /**
447      * Send GET request to chef server
448      */
449     @SuppressWarnings("nls")
450
451     @Override
452     public void chefGet(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
453         logger.info("chef get method");
454         chefInfo(params, ctx);
455         String chefAction = params.get(CHEF_ACTION_STR);
456         RequestContext rc = new RequestContext(ctx);
457         rc.isAlive();
458         int code;
459         String message;
460
461         if (privateKeyCheck()) {
462             ChefResponse chefResponse = getApiMethod(chefAction);
463             code = chefResponse.getStatusCode();
464             message = chefResponse.getBody();
465         } else {
466             code = 500;
467             message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
468         }
469         chefServerResult(rc, code, message);
470     }
471
472     /**
473      * Send PUT request to chef server
474      */
475     @SuppressWarnings("nls")
476
477     @Override
478     public void chefPut(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
479         chefInfo(params, ctx);
480         String chefAction = params.get(CHEF_ACTION_STR);
481         String chefNodeStr = params.get("chefRequestBody");
482         RequestContext rc = new RequestContext(ctx);
483         rc.isAlive();
484         int code;
485         String message;
486         if (privateKeyCheck()) {
487             ChefApiClient chefApiClient = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
488
489             ChefResponse chefResponse = chefApiClient.put(chefAction, chefNodeStr);
490             code = chefResponse.getStatusCode();
491             message = chefResponse.getBody();
492         } else {
493             code = 500;
494             message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
495         }
496         logger.info(code + "   " + message);
497         chefServerResult(rc, code, message);
498     }
499
500     /**
501      * send Post request to chef server
502      */
503     @Override
504     public void chefPost(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
505         chefInfo(params, ctx);
506         logger.info("chef Post method");
507         logger.info(username + " " + clientPrivatekey + " " + chefserver + " " + organizations);
508         String chefNodeStr = params.get("chefRequestBody");
509         String chefAction = params.get(CHEF_ACTION_STR);
510
511         RequestContext rc = new RequestContext(ctx);
512         rc.isAlive();
513         int code;
514         String message;
515         // should load pem from somewhere else
516         if (privateKeyCheck()) {
517             ChefApiClient chefApiClient = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
518
519             // need pass path into it
520             // "/nodes/testnode"
521             ChefResponse chefResponse = chefApiClient.post(chefAction, chefNodeStr);
522             code = chefResponse.getStatusCode();
523             message = chefResponse.getBody();
524         } else {
525             code = 500;
526             message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
527         }
528         logger.info(code + "   " + message);
529         chefServerResult(rc, code, message);
530     }
531
532     /**
533      * send delete request to chef server
534      */
535     @Override
536     public void chefDelete(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
537         logger.info("chef delete method");
538         chefInfo(params, ctx);
539         String chefAction = params.get(CHEF_ACTION_STR);
540         RequestContext rc = new RequestContext(ctx);
541         rc.isAlive();
542         int code;
543         String message;
544         if (privateKeyCheck()) {
545             ChefApiClient chefApiClient = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
546             ChefResponse chefResponse = chefApiClient.delete(chefAction);
547             code = chefResponse.getStatusCode();
548             message = chefResponse.getBody();
549         } else {
550             code = 500;
551             message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
552         }
553         logger.info(code + "   " + message);
554         chefServerResult(rc, code, message);
555     }
556
557     /**
558      * Trigger target vm run chef
559      */
560     @Override
561     public void trigger(Map<String, String> params, SvcLogicContext ctx) {
562         logger.info("Run trigger method");
563         String tVmIp = params.get("ip");
564         RequestContext rc = new RequestContext(ctx);
565         rc.isAlive();
566
567         try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
568             HttpGet httpGet = new HttpGet(tVmIp);
569             HttpResponse response = httpClient.execute(httpGet);
570             int responseCode = response.getStatusLine().getStatusCode();
571             HttpEntity entity = response.getEntity();
572             String responseOutput = EntityUtils.toString(entity);
573             chefClientResult(rc, responseCode, responseOutput);
574             doSuccess(rc);
575         } catch (Exception e) {
576             logger.error("An error occurred when executing trigger method", e);
577             doFailure(rc, 500, e.toString());
578         }
579     }
580
581     @SuppressWarnings("nls")
582     @Override
583     public void checkPushJob(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
584         int code;
585         try {
586             chefInfo(params, ctx);
587             String jobID = params.get("jobid");
588             String retry = params.get("retryTimes");
589             String intrva = params.get("retryInterval");
590             if (StringUtils.isNotBlank(retry) && StringUtils.isNotBlank(intrva)) {
591
592                 int retryTimes = Integer.parseInt(params.get("retryTimes"));
593                 int retryInterval = Integer.parseInt(params.get("retryInterval"));
594
595                 String chefAction = "/pushy/jobs/" + jobID;
596
597                 RequestContext rc = new RequestContext(ctx);
598                 rc.isAlive();
599                 SvcLogicContext svcLogic = rc.getSvcLogicContext();
600                 String message = StringUtils.EMPTY;
601                 String status = StringUtils.EMPTY;
602                 for (int i = 0; i < retryTimes; i++) {
603                     sleepFor(retryInterval);
604                     ChefResponse chefResponse = getApiMethod(chefAction);
605                     code = chefResponse.getStatusCode();
606                     message = chefResponse.getBody();
607                     JSONObject obj = new JSONObject(message);
608                     status = obj.getString("status");
609                     if (!"running".equals(status)) {
610                         logger.info(i + " time " + code + "   " + status);
611                         break;
612                     }
613                 }
614                 resolveSvcLogicAttributes(svcLogic, message, status);
615             } else {
616                 throw new SvcLogicException("Missing Mandatory param(s) retryTimes , retryInterval ");
617             }
618         } catch (Exception e) {
619             code = 401;
620             logger.error("An error occurred when executing checkPushJob method", e);
621             doFailure(ctx, code, e.getMessage());
622         }
623     }
624
625     private void resolveSvcLogicAttributes(SvcLogicContext svcLogic, String message, String status) {
626         if ("complete".equals(status)) {
627             svcLogic.setAttribute(CHEF_SERVER_RESULT_CODE_STR, "200");
628             svcLogic.setAttribute(CHEF_SERVER_RESULT_MSG_STR, message);
629         } else {
630             if ("running".equals(status)) {
631                 svcLogic.setAttribute(CHEF_SERVER_RESULT_CODE_STR, "202");
632                 svcLogic.setAttribute(CHEF_SERVER_RESULT_MSG_STR, "chef client runtime out");
633             } else {
634                 svcLogic.setAttribute(CHEF_SERVER_RESULT_CODE_STR, "500");
635                 svcLogic.setAttribute(CHEF_SERVER_RESULT_MSG_STR, message);
636             }
637         }
638     }
639
640     private void sleepFor(int retryInterval) {
641         try {
642             Thread.sleep(retryInterval); // 1000 milliseconds is one second.
643         } catch (InterruptedException ex) {
644             Thread.currentThread().interrupt();
645         }
646     }
647
648     @SuppressWarnings("nls")
649     @Override
650     public void pushJob(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
651         int code;
652         try {
653             chefInfo(params, ctx);
654             String pushRequest = params.get("pushRequest");
655             String chefAction = "/pushy/jobs";
656             RequestContext rc = new RequestContext(ctx);
657             rc.isAlive();
658             SvcLogicContext svcLogic = rc.getSvcLogicContext();
659             ChefApiClient chefApiClient = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
660             ChefResponse chefResponse = chefApiClient.post(chefAction, pushRequest);
661
662             code = chefResponse.getStatusCode();
663             String message = chefResponse.getBody();
664             if (code == 201) {
665                 int startIndex = message.indexOf("jobs") + 6;
666                 int endIndex = message.length() - 2;
667                 String jobID = message.substring(startIndex, endIndex);
668                 svcLogic.setAttribute("jobID", jobID);
669                 logger.info(jobID);
670             }
671             chefServerResult(rc, code, message);
672         } catch (Exception e) {
673             code = 401;
674             logger.error("An error occurred when executing pushJob method", e);
675             doFailure(ctx, code, e.getMessage());
676         }
677     }
678
679     @SuppressWarnings("static-method")
680     private void doFailure(RequestContext rc, int code, String message) {
681         SvcLogicContext svcLogic = rc.getSvcLogicContext();
682         String msg = (message == null) ? Integer.toString(code) : message;
683         if (msg.contains("\n")) {
684             msg = msg.substring(msg.indexOf('\n'));
685         }
686
687         String status;
688         try {
689             status = Integer.toString(code);
690         } catch (Exception e) {
691             status = "500";
692             logger.error("Parsing status code failed. Setting it to \"500\"", e);
693         }
694         svcLogic.setAttribute("chefAgent.code", status);
695         svcLogic.setAttribute("chefAgent.message", msg);
696     }
697
698     /**
699      * @param rc The request context that manages the state and recovery of the request for the life of its processing.
700      */
701     @SuppressWarnings("static-method")
702     private void doSuccess(RequestContext rc) {
703         SvcLogicContext svcLogic = rc.getSvcLogicContext();
704         svcLogic.setAttribute("chefAgent.code", "200");
705     }
706
707     @SuppressWarnings("static-method")
708     private void chefServerResult(RequestContext rc, int code, String message) {
709         initSvcLogic(rc, code, message, "server");
710     }
711
712     @SuppressWarnings("static-method")
713     private void chefClientResult(RequestContext rc, int code, String message) {
714         initSvcLogic(rc, code, message, "client");
715     }
716
717     private void initSvcLogic(RequestContext rc, int code, String message, String target) {
718
719         SvcLogicContext svcLogic = rc.getSvcLogicContext();
720         String codeStr = "server".equals(target) ? CHEF_SERVER_RESULT_CODE_STR : CHEF_CLIENT_RESULT_CODE_STR;
721         String messageStr = "client".equals(target) ? CHEF_SERVER_RESULT_MSG_STR : CHEF_CLIENT_RESULT_MSG_STR;
722
723         svcLogic.setStatus(OUTCOME_SUCCESS);
724         svcLogic.setAttribute(codeStr, Integer.toString(code));
725         svcLogic.setAttribute(messageStr, message);
726         logger.info(codeStr + ": " + svcLogic.getAttribute(codeStr));
727         logger.info(messageStr + ": " + svcLogic.getAttribute(messageStr));
728     }
729
730     @SuppressWarnings("static-method")
731     private void doFailure(SvcLogicContext svcLogic, int code, String message) throws SvcLogicException {
732
733         String cutMessage = message.contains("\n") ? message.substring(message.indexOf('\n')) : message;
734
735         svcLogic.setStatus(OUTCOME_FAILURE);
736         svcLogic.setAttribute(CHEF_SERVER_RESULT_CODE_STR, Integer.toString(code));
737         svcLogic.setAttribute(CHEF_SERVER_RESULT_MSG_STR, cutMessage);
738
739         throw new SvcLogicException("Chef Adapter error:" + cutMessage);
740     }
741 }