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