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