saltstack reqExecSls implemented as adaptor 59/56059/2
authorGanesh Chandrasekaran <ganesh.c@samsung.com>
Tue, 10 Jul 2018 09:27:17 +0000 (18:27 +0900)
committerGanesh Chandrasekaran <ganesh.c@samsung.com>
Tue, 10 Jul 2018 09:33:52 +0000 (18:33 +0900)
Issue-ID: CCSDK-330

Change-Id: Icdb2c70d94d4901f1b18713b8b33666169a2b6d9
Signed-off-by: Ganesh Chandrasekaran <ganesh.c@samsung.com>
21 files changed:
features/ccsdk-sli-adaptors-all/pom.xml
saltstack-adapter/README.md
saltstack-adapter/saltstack-adapter-features/ccsdk-saltstack-adapter/pom.xml
saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapter.java
saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java
saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterImpl.java
saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterPropertiesProviderImpl.java
saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java
saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java
saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java
saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java
saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java
saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java
saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestConnectionBuilder.java [new file with mode: 0644]
saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestSaltstackAdapterImpl.java
saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/model/TestJsonParser.java [new file with mode: 0644]
saltstack-adapter/saltstack-adapter-provider/src/test/resources/test [new file with mode: 0644]
saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-invalid.json [new file with mode: 0644]
saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-sls.json [new file with mode: 0644]
saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.json [new file with mode: 0644]
saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.txt [new file with mode: 0644]

index 3a9f034..871f3bb 100644 (file)
                        <type>xml</type>
                        <classifier>features</classifier>
                </dependency>
+               <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>ccsdk-saltstack-adapter</artifactId>
+                       <version>${project.version}</version>
+                       <type>xml</type>
+                       <classifier>features</classifier>
+               </dependency>
                <dependency>
                        <groupId>${project.groupId}</groupId>
                        <artifactId>ccsdk-mdsal-resource</artifactId>
index cf21e10..8e989a8 100644 (file)
@@ -51,12 +51,45 @@ Create an Adaptor to communicate with the SaltStack server:
   Note: SSH_CERT based Auth is not supported in this method.
   
 ***Using Saltstack Adaptor Commands and params to pass in:*** reqExecCommand:
-Method to execute a single command on SaltState server. The command entered should request the output in JSON format, this can be done by appending json-out outputter as specified in https://docs.saltstack.com/en/latest/ref/output/all/salt.output.json_out.html#module-salt.output.json_out and https://docs.saltstack.com/en/2017.7/ref/cli/salt-call.html The response from Saltstack comes in json format and it is automatically put to context for DGs access, with a certain request-ID as prefix.
-Example command will look like: 
-1) Command to test if all VNFC are running: "salt * test.ping --out=json --static"
-2) To check Network interfaces on your minions: "salt '*' network.interfaces --out=json --static"
-3) Restart Minion service after upgrade process: "salt minion1 service.restart salt-minion --out=json --static"
+Method to execute a single command on SaltState server and execute a SLS file located on the server. The command entered should request the output in JSON format, this can be done by appending json-out outputter as specified in https://docs.saltstack.com/en/latest/ref/output/all/salt.output.json_out.html#module-salt.output.json_out and https://docs.saltstack.com/en/2017.7/ref/cli/salt-call.html 
+The response from Saltstack comes in json format and it is automatically put to context for DGs access, with a certain request-ID as prefix.
+If Id is not passed as part of input param, then a random Id will be generated and put to properties in "org.onap.appc.adapter.saltstack.Id" field. All the output message from the execution will be appended with reqId. 
+1) Execute a single command on SaltState server : Example command will look like: 
+1.1) Command to test if all VNFC are running: "salt '*' test.ping --out=json --static"
+1.2) To check Network interfaces on your minions: "salt '*' network.interfaces --out=json --static"
+1.3) Restart Minion service after upgrade process: "salt minion1 service.restart salt-minion --out=json --static"
 Note: If using --out=json, you will probably want --static as well. Without the static option, you will get a separate JSON string per minion which makes JSON output invalid as a whole. This is due to using an iterative outputter. So if you want to feed it to a JSON parser, use --static as well.
 
-This "reqExecCommand" method gives the Operator/Directed Graphs to execute commands in a fine-tuned manner, which also means the operator/DG-creator should know what to expect as output as a result of command execution. By this way using DGs, the operator can check for success/failure of the executed comment. 
-If the output is not in JSON format, then the adaptor still tries to convert it into properties, in addition "reqID.completeResult" param will have the whole result for DG access. 
+This "reqExecCommand" method gives the Operator/Directed Graphs to execute commands in a fine-tuned manner, which also means the operator/DG-creator should know what to expect as output as a result of command execution (for both success/failure case). 
+By this way using DGs, the operator can check for success/failure of the executed comment. 
+If the output is not in JSON format, then the adaptor still tries to convert it into properties, in addition, params that will hold the command execution result for DG access are (note: this is just to check if the command was executed successfully on the server, this doesn't check the status of the command on saltstack server): 
+Result code at: org.onap.appc.adapter.saltstack.result.code (On success: This will be always be 250, means command execution was success but the result of the execution is unknown and is to be checked from ctx using DGs)
+Message at: org.onap.appc.adapter.saltstack.message
+Both user inputted/auto generated req Id at:  org.onap.appc.adapter.saltstack.Id
+To check the status of the command configuration on saltstack server: the user should exactly know what to look for in the context 
+so the user can identify if the configuration execution on the saltstack server succeded or not. 
+here for instance, in 1.1) the user should check if $reqId.<minion-name> is set to true in the context memory using DGs. 
+
+2) Execute a SLS file located on the server : Example command will look like:
+Knowing the saltstack server has vim.sls file located at "/srv/salt" directory then user can execute the following commands:
+1.1) Command to run the vim.sls file on saltstack server: "salt '*' state.apply vim --out=json --static"
+1.2) Command to run the nettools.sls file on saltstack server: "salt '*' state.apply nettools --out=json --static"
+Important thing to note: If the reqExecCommand is used to execute sls file then along with following, 
+    "HostName";  ->  Saltstack server's host name IP address.
+    "Port"; ->  Saltstack server's port to make SSH connection to.
+    "Password"; ->  Saltstack server's SSH UserName.
+    "User"; ->  Saltstack server's SSH Password.
+the param should contain,
+    "slsExec"; ->  this variable should be set to true.
+
+In this case, params that will hold the command execution result for DG access are
+Result code at: org.onap.appc.adapter.saltstack.result.code (On success: This will be 200, this means the command was executed successfully and also configuration change made using the SLS file was also successful) 
+Message at: org.onap.appc.adapter.saltstack.message
+Both user inputted/auto generated req Id at:  org.onap.appc.adapter.saltstack.Id
+The result code here will be the execution of configuration SLS file on the server. 
+NOTE: It would be better to use reqExecSLS, where you will only have to specify SLS file name on server.
+***Using Saltstack Adaptor Commands and params to pass in:*** reqExecSLS:
+Method to execute a single sls on SaltState server and execute a SLS file located on the server. The command entered should request the output in JSON format, this can be done by appending json-out outputter as specified in https://docs.saltstack.com/en/latest/ref/output/all/salt.output.json_out.html#module-salt.output.json_out and https://docs.saltstack.com/en/2017.7/ref/cli/salt-call.html 
+The response from Saltstack comes in json format and it is automatically put to context for DGs access, with a certain request-ID as prefix.
+If Id is not passed as part of input param, then a random Id will be generated and put to properties in "org.onap.appc.adapter.saltstack.Id" field. All the output message from the execution will be appended with reqId. 
+1) Execute a single command on SaltState server : Example command will look like: 
index 92f404e..01b330e 100644 (file)
             </dependency>
         </dependencies>
     </dependencyManagement>
- <!--   <dependencies>
-        <dependency>
-            <groupId>org.onap.ccsdk.sli.core</groupId>
-            <artifactId>ccsdk-sli</artifactId>
-            <type>xml</type>
-            <classifier>features</classifier>
-        </dependency>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>saltstack-adapter-provider</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-    </dependencies>
-    -->
-</project>
+    <!--   <dependencies>
+           <dependency>
+               <groupId>org.onap.ccsdk.sli.core</groupId>
+               <artifactId>ccsdk-sli</artifactId>
+               <type>xml</type>
+               <classifier>features</classifier>
+           </dependency>
+           <dependency>
+               <groupId>${project.groupId}</groupId>
+               <artifactId>saltstack-adapter-provider</artifactId>
+               <version>${project.version}</version>
+           </dependency>
+       </dependencies>
+       -->
+</project>
\ No newline at end of file
index 2f70a79..1cbb495 100644 (file)
 
 package org.onap.ccsdk.sli.adaptors.saltstack;
 
-import java.util.Map;
 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
 import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
 
+import java.util.Map;
+
 /**
  * This interface defines the operations that the Saltstack adapter exposes.
- *
  */
 public interface SaltstackAdapter extends SvcLogicJavaPlugin {
     /**
@@ -46,11 +46,16 @@ public interface SaltstackAdapter extends SvcLogicJavaPlugin {
      *  to context for DGs access, with a certain prefix*/
     void reqExecCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
 
+    /* Method for execution of saltstack SLS command on SaltState server
+     *  The response from Saltstack comes in json format and it is automatically put
+     *  to context for DGs access, with a certain prefix*/
+    void reqExecSLS(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
     /* When SLS file is created/available then this Method can be used to post
      *  the file to saltstack server and execute the SLS file on SaltState server
      *  The response from Saltstack comes in json format and it is automatically put
      *  to context for DGs access, with a certain prefix*/
-    void reqExecSLS(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+    void reqExecSLSFile(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
 
     /* Method to get log of a saltState execution request
      *  The response from Saltstack comes in json format and it is automatically put
@@ -59,6 +64,7 @@ public interface SaltstackAdapter extends SvcLogicJavaPlugin {
 
     /**
      * Set the command execution timeout
+     *
      * @param timeout time in milliseconds
      */
     void setExecTimeout(long timeout);
index 5dee9f5..65ab598 100644 (file)
 
 package org.onap.ccsdk.sli.adaptors.saltstack.impl;
 
-import java.io.BufferedOutputStream;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.RandomStringUtils;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -32,15 +38,6 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.StringWriter;
-import java.util.List;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.RandomStringUtils;
-import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
-import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes;
-import org.onap.ccsdk.sli.core.sli.SvcLogicException;
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
 
 /**
  * Returns a custom SSH client
@@ -88,7 +85,7 @@ public class ConnectionBuilder {
      * @return command execution status
      */
     public SaltstackResult connectNExecute(String cmd) {
-        return connectNExecute(cmd,-1,-1);
+        return connectNExecute(cmd, -1, -1);
     }
 
     /**
@@ -96,7 +93,7 @@ public class ConnectionBuilder {
      * 2. Exec remote command over SSH. Return command execution status.
      * Command output is written to out or err stream.
      *
-     * @param cmd Commands to execute
+     * @param cmd        Commands to execute
      * @param retryDelay delay between retry to make a SSH connection.
      * @param retryCount number of count retry to make a SSH connection.
      * @return command execution status
@@ -113,8 +110,8 @@ public class ConnectionBuilder {
             if (result.getStatusCode() != SaltstackResultCodes.SUCCESS.getValue()) {
                 return result;
             }
-            String outFilePath = "/tmp/"+ RandomStringUtils.random(5,true,true);
-            String errFilePath = "/tmp/"+ RandomStringUtils.random(5,true,true);
+            String outFilePath = "/tmp/" + RandomStringUtils.random(5, true, true);
+            String errFilePath = "/tmp/" + RandomStringUtils.random(5, true, true);
             OutputStream out = new FileOutputStream(outFilePath);
             OutputStream errs = new FileOutputStream(errFilePath);
             result = sshConnection.execCommand(cmd, out, errs);
@@ -137,40 +134,42 @@ public class ConnectionBuilder {
         return result;
     }
 
-    public SaltstackResult sortExitStatus (int exitStatus, String errFilePath, String cmd)  {
+    public SaltstackResult sortExitStatus(int exitStatus, String errFilePath, String cmd) {
         SaltstackResult result = new SaltstackResult();
-        String err;
+        String err = "";
         StringWriter writer = new StringWriter();
         try {
             IOUtils.copy(new FileInputStream(new File(errFilePath)), writer, "UTF-8");
             err = writer.toString();
-        } catch (Exception e){
-            err = "";
+        } catch (FileNotFoundException e){
+            logger.info("Error stream file doesn't exist");
+        } catch (IOException e){
+            logger.info("Error stream file doesn't exist");
         }
         if (exitStatus == 255 || exitStatus == 1) {
             String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
                     + "]. Exit Code " + exitStatus + " and Error message : " +
-                    "Malformed configuration. "+ err;
+                    "Malformed configuration. " + err;
             logger.error(errMessage);
             result.setStatusCode(SaltstackResultCodes.INVALID_COMMAND.getValue());
             result.setStatusMessage(errMessage);
         } else if (exitStatus == 5 || exitStatus == 65) {
             String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
                     + "]. Exit Code " + exitStatus + " and Error message : " +
-                    "Host not allowed to connect. "+ err;
+                    "Host not allowed to connect. " + err;
             logger.error(errMessage);
             result.setStatusCode(SaltstackResultCodes.USER_UNAUTHORIZED.getValue());
             result.setStatusMessage(errMessage);
         } else if (exitStatus == 67 || exitStatus == 73) {
             String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
                     + "]. Exit Code " + exitStatus + " and Error message : " +
-                    "Key exchange failed. "+ err;
+                    "Key exchange failed. " + err;
             logger.error(errMessage);
             result.setStatusCode(SaltstackResultCodes.CERTIFICATE_ERROR.getValue());
             result.setStatusMessage(errMessage);
         } else {
             String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
-                    + "]. Exit Code " + exitStatus + " and Error message : "+ err;
+                    + "]. Exit Code " + exitStatus + " and Error message : " + err;
             logger.error(errMessage);
             result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue());
             result.setStatusMessage(errMessage);
@@ -183,7 +182,7 @@ public class ConnectionBuilder {
      * 2. Exec remote command over SSH. Return command execution status.
      * Command output is written to out or err stream.
      *
-     * @param commands list of commands to execute
+     * @param commands   list of commands to execute
      * @param payloadSLS has the SLS file location that is to be sent to server
      * @param retryDelay delay between retry to make a SSH connection.
      * @param retryCount number of count retry to make a SSH connection.
@@ -205,7 +204,7 @@ public class ConnectionBuilder {
     /**
      * Disconnect from SSH server.
      */
-    public SaltstackResult disConnect(){
+    public SaltstackResult disConnect() {
 
         SaltstackResult result = new SaltstackResult();
         try {
@@ -225,7 +224,7 @@ public class ConnectionBuilder {
      * @param cmd command to execute
      * @return command execution status
      */
-    public SaltstackResult execute(String cmd) {
+    public SaltstackResult connectNExecuteLog(String cmd) {
 
         SaltstackResult result = new SaltstackResult();
 
index 5fe130f..e3046db 100644 (file)
 
 package org.onap.ccsdk.sli.adaptors.saltstack.impl;
 
-import java.util.Map;
-import java.util.Properties;
-import org.apache.commons.lang.StringUtils;
-import org.json.JSONException;
-import org.json.JSONObject;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
 import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapter;
 import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapterPropertiesProvider;
 import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackMessageParser;
@@ -37,8 +34,14 @@ import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes;
 import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackServerEmulator;
 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.Properties;
 
 /**
  * This class implements the {@link SaltstackAdapter} interface. This interface defines the behaviors
@@ -46,56 +49,45 @@ import com.att.eelf.configuration.EELFManager;
  */
 public class SaltstackAdapterImpl implements SaltstackAdapter {
 
-    private static final long EXEC_TIMEOUT = 120000;
-    private long timeout = EXEC_TIMEOUT;
-
     /**
      * The constant used to define the service name in the mapped diagnostic context
      */
     @SuppressWarnings("nls")
     public static final String MDC_SERVICE = "service";
-
     /**
      * The constant for the status code for a failed outcome
      */
     @SuppressWarnings("nls")
     public static final String OUTCOME_FAILURE = "failure";
-
     /**
      * The constant for the status code for a successful outcome
      */
     @SuppressWarnings("nls")
     public static final String OUTCOME_SUCCESS = "success";
-
+    public static final String CONNECTION_RETRY_DELAY = "retryDelay";
+    public static final String CONNECTION_RETRY_COUNT = "retryCount";
+    private static final long EXEC_TIMEOUT = 120000;
     /**
      * Adapter Name
      */
     private static final String ADAPTER_NAME = "Saltstack Adapter";
     private static final String APPC_EXCEPTION_CAUGHT = "APPCException caught";
-
     private static final String RESULT_CODE_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.result.code";
     private static final String MESSAGE_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.message";
     private static final String RESULTS_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.results";
     private static final String ID_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.Id";
     private static final String LOG_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.log";
-
-    public static final String CONNECTION_RETRY_DELAY = "retryDelay";
-    public static final String CONNECTION_RETRY_COUNT = "retryCount";
-
     private static final String CLIENT_TYPE_PROPERTY_NAME = "org.onap.appc.adapter.saltstack.clientType";
     private static final String SS_SERVER_HOSTNAME = "org.onap.appc.adapter.saltstack.host";
     private static final String SS_SERVER_PORT = "org.onap.appc.adapter.saltstack.port";
     private static final String SS_SERVER_USERNAME = "org.onap.appc.adapter.saltstack.userName";
     private static final String SS_SERVER_PASSWORD = "org.onap.appc.adapter.saltstack.userPasswd";
     private static final String SS_SERVER_SSH_KEY = "org.onap.appc.adapter.saltstack.sshKey";
-
-
     /**
      * The logger to be used
      */
     private static final EELFLogger logger = EELFManager.getInstance().getLogger(SaltstackAdapterImpl.class);
-
-
+    private long timeout = EXEC_TIMEOUT;
     /**
      * Connection object
      **/
@@ -122,6 +114,7 @@ public class SaltstackAdapterImpl implements SaltstackAdapter {
     public SaltstackAdapterImpl() {
         initialize(new SaltstackAdapterPropertiesProviderImpl());
     }
+
     public SaltstackAdapterImpl(SaltstackAdapterPropertiesProvider propProvider) {
         initialize(propProvider);
     }
@@ -150,9 +143,10 @@ public class SaltstackAdapterImpl implements SaltstackAdapter {
     public void setExecTimeout(long timeout) {
         this.timeout = timeout;
     }
+
     /**
-     *  Method posts info to Context memory in case of an error and throws a
-     *        SvcLogicException causing SLI to register this as a failure
+     * Method posts info to Context memory in case of an error and throws a
+     * SvcLogicException causing SLI to register this as a failure
      */
     @SuppressWarnings("static-method")
     private void doFailure(SvcLogicContext svcLogic, int code, String message) throws SvcLogicException {
@@ -160,7 +154,6 @@ public class SaltstackAdapterImpl implements SaltstackAdapter {
         svcLogic.setStatus(OUTCOME_FAILURE);
         svcLogic.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(code));
         svcLogic.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
-
         throw new SvcLogicException("Saltstack Adapter Error = " + message);
     }
 
@@ -222,16 +215,8 @@ public class SaltstackAdapterImpl implements SaltstackAdapter {
         logger.info("Initialized Saltstack Adapter");
     }
 
-    // Public Method to post single command request to execute saltState. Posts the following back
-    // to Svc context memory
-    //  org.onap.appc.adapter.saltstack.req.code : 100 if successful
-    //  org.onap.appc.adapter.saltstack.req.messge : any message
-    //  org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request
-    @Override
-    public void reqExecCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
-        String reqID;
-        SaltstackResult testResult;
-        if (sshClient == null){
+    private void setSSHClient(Map<String, String> params) throws SvcLogicException {
+        if (sshClient == null) {
             logger.info("saltstack-adapter.properties not defined so reading saltstack host and " +
                                 "auth details from DG's parameters");
             String sshHost = messageProcessor.reqHostNameResult(params);
@@ -239,59 +224,130 @@ public class SaltstackAdapterImpl implements SaltstackAdapter {
             String sshUserName = messageProcessor.reqUserNameResult(params);
             String sshPassword = messageProcessor.reqPasswordResult(params);
             logger.info("Creating ssh client with BASIC Auth");
-            if(!testMode)
+            if (!testMode) {
                 sshClient = new ConnectionBuilder(sshHost, sshPort, sshUserName, sshPassword);
+            }
         }
+    }
+
+    private String putToCommands(SvcLogicContext ctx, String slsFileName,
+                                 String reqID, String applyTo) throws SvcLogicException {
+        String constructedCommand = "";
         try {
-            reqID = params.get("Id");
-            String commandToExecute = params.get("cmd");
-            testResult = execCommand(params, commandToExecute);
-            testResult = messageProcessor.parseResponse(ctx, reqID, testResult);
-
-            // Check status of test request returned by Agent
-            if (testResult.getStatusCode() == SaltstackResultCodes.FINAL_SUCCESS.getValue()) {
-                logger.info(String.format("Execution of request-ID : %s successful.", reqID));
-                testResult.setResults("Success");
+            File file = new File(slsFileName);
+            InputStream in = new FileInputStream(file);
+            byte[] data = new byte[(int) file.length()];
+            in.read(data);
+            String str = new String(data, "UTF-8");
+            in.close();
+            constructedCommand = "echo "+str+" > /srv/salt/"+reqID+".sls; salt '"+applyTo+"' state.apply "+reqID+" --out=json --static";
+        } catch (FileNotFoundException e) {
+            doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(), "Input SLS file " +
+                    "not found in path : " + slsFileName+". "+ e.getMessage());
+        } catch (IOException e) {
+            doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(), "Input SLS file " +
+                    "error in path : " + slsFileName +". "+ e.getMessage());
+        }
+        logger.info("Command to be executed on server : " + constructedCommand);
+        return constructedCommand;
+    }
+
+    private String putToCommands(String slsName, String applyTo) {
+        String
+            constructedCommand = "cd /srv/salt/; salt '"+applyTo+"' state.apply "+slsName+" --out=json --static";
+
+        logger.info("Command to be executed on server : " + constructedCommand);
+        return constructedCommand;
+    }
+
+    private void checkResponseStatus(SaltstackResult testResult, SvcLogicContext ctx, String reqID, boolean slsExec)
+            throws SvcLogicException {
+
+        // Check status of test request returned by Agent
+        if (testResult.getStatusCode() != SaltstackResultCodes.FINAL_SUCCESS.getValue()) {
+            doFailure(ctx, testResult.getStatusCode(), "Request for execution of command failed. Reason = " + testResult.getStatusMessage());
+            ctx.setAttribute(ID_ATTRIBUTE_NAME, reqID);
+            return;
+        } else {
+            logger.info(String.format("Execution of request : successful."));
+            if (slsExec) {
+                ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(testResult.getStatusCode()));
+                ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, "success");
             } else {
-                doFailure(ctx, testResult.getStatusCode(), "Request for execution of command failed. Reason = " + testResult.getStatusMessage());
-                return;
+                ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(SaltstackResultCodes.CHECK_CTX_FOR_CMD_SUCCESS.getValue()));
+                ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, "check context for execution status");
             }
-        } catch (SvcLogicException e) {
-            logger.error(APPC_EXCEPTION_CAUGHT, e);
-            doFailure(ctx, SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue(),
-                      "Request for execution of command failed. Reason = "
-                              + e.getMessage());
-            return;
-        } catch (Exception e) {
-            logger.error("Exception caught", e);
-            doFailure(ctx, SaltstackResultCodes.INVALID_COMMAND.getValue(),
-                      "Request for execution of command failed. Reason = "
-                              + e.getMessage());
-            return;
+            ctx.setAttribute(ID_ATTRIBUTE_NAME, reqID);
         }
-        ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(testResult.getStatusCode()));
-        ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, testResult.getResults());
-        ctx.setAttribute(ID_ATTRIBUTE_NAME, reqID);
+    }
+
+    // Public Method to post single command request to execute saltState. Posts the following back
+    // to Svc context memory
+    //  org.onap.appc.adapter.saltstack.req.code : 100 if successful
+    //  org.onap.appc.adapter.saltstack.req.messge : any message
+    //  org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request
+    @Override
+    public void reqExecCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+        String reqID;
+        boolean slsExec;
+        SaltstackResult testResult;
+        setSSHClient(params);
+        reqID = messageProcessor.reqId(params);
+        String commandToExecute = messageProcessor.reqCmd(params);
+        slsExec = messageProcessor.reqIsSLSExec(params);
+        testResult = execCommand(params, commandToExecute);
+        testResult = messageProcessor.parseResponse(ctx, reqID, testResult, slsExec);
+        checkResponseStatus(testResult, ctx, reqID, slsExec);
     }
 
     /**
-     * Public Method to post SLS file request to execute saltState. Posts the following back
+     * Public Method to post SLS command request to execute saltState on server. Posts the following back
      * to Svc context memory
-     *
-     * org.onap.appc.adapter.saltstack.req.code : 100 if successful
+     * <p>
+     * org.onap.appc.adapter.saltstack.req.code : 200 if successful
      * org.onap.appc.adapter.saltstack.req.messge : any message
      * org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request
      */
     @Override
     public void reqExecSLS(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
-        //TODO: to implement
+        String reqID;
+        SaltstackResult testResult;
+        setSSHClient(params);
+        reqID = messageProcessor.reqId(params);
+        String slsName = messageProcessor.reqSlsName(params);
+        String applyTo = messageProcessor.reqApplyToDevices(params);
+        String commandToExecute = putToCommands(slsName, applyTo);
+        testResult = execCommand(params, commandToExecute);
+        testResult = messageProcessor.parseResponse(ctx, reqID, testResult, true);
+        checkResponseStatus(testResult, ctx, reqID, true);
+    }
 
+    /**
+     * Public Method to post SLS file request to execute saltState. Posts the following back
+     * to Svc context memory
+     * <p>
+     * org.onap.appc.adapter.saltstack.req.code : 100 if successful
+     * org.onap.appc.adapter.saltstack.req.messge : any message
+     * org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request
+     */
+    @Override
+    public void reqExecSLSFile(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+        String reqID;
+        SaltstackResult testResult;
+        setSSHClient(params);
+        reqID = messageProcessor.reqId(params);
+        String slsFile = messageProcessor.reqSlsFile(params);
+        String applyTo = messageProcessor.reqApplyToDevices(params);
+        String commandToExecute = putToCommands(ctx, slsFile, reqID, applyTo);
+        testResult = execCommand(params, commandToExecute);
+        testResult = messageProcessor.parseResponse(ctx, reqID, testResult, true);
+        checkResponseStatus(testResult, ctx, reqID, true);
     }
 
     /**
      * Public method to get logs from saltState execution for a specific request Posts the following back
      * to Svc context memory
-     *
+     * <p>
      * It blocks till the Saltstack Server responds or the session times out very similar to
      * reqExecResult logs are returned in the DG context variable org.onap.appc.adapter.saltstack.log
      */
@@ -301,20 +357,20 @@ public class SaltstackAdapterImpl implements SaltstackAdapter {
 
     }
 
-    public SaltstackResult execCommand(Map<String, String> params, String commandToExecute){
+    public SaltstackResult execCommand(Map<String, String> params, String commandToExecute) {
         SaltstackResult testResult;
         if (params.get(CONNECTION_RETRY_DELAY) != null && params.get(CONNECTION_RETRY_COUNT) != null) {
             int retryDelay = Integer.parseInt(params.get(CONNECTION_RETRY_DELAY));
             int retryCount = Integer.parseInt(params.get(CONNECTION_RETRY_COUNT));
-            if(!testMode)
+            if (!testMode) {
                 testResult = sshClient.connectNExecute(commandToExecute, retryCount, retryDelay);
-            else {
+            else {
                 testResult = testServer.MockReqExec(params);
             }
         } else {
-            if(!testMode)
+            if (!testMode) {
                 testResult = sshClient.connectNExecute(commandToExecute);
-            else {
+            else {
                 testResult = testServer.MockReqExec(params);
             }
         }
index 2430885..a415655 100755 (executable)
 
 package org.onap.ccsdk.sli.adaptors.saltstack.impl;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Optional;
-import java.util.Properties;
-import java.util.Vector;
 import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapterPropertiesProvider;
 import org.onap.ccsdk.sli.core.sli.ConfigurationException;
 import org.onap.ccsdk.sli.core.utils.JREFileResolver;
@@ -37,11 +30,19 @@ import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Vector;
+
 /**
  * Responsible for determining the properties file to use and instantiating the
  * <code>SqlResource</code> Service. The priority for properties file
  * resolution is as follows:
- *
+ * <p>
  * <ol>
  * <li>A directory identified by the system environment variable
  * <code>SDNC_CONFIG_DIR</code></li>
@@ -93,8 +94,8 @@ public class SaltstackAdapterPropertiesProviderImpl implements SaltstackAdapterP
                 properties.load(fileInputStream);
             } catch (final IOException e) {
                 LOG.error("Failed to load properties for file: {}", propertiesFile.toString(),
-                        new ConfigurationException("Failed to load properties for file: " + propertiesFile.toString(),
-                                e));
+                          new ConfigurationException("Failed to load properties for file: " + propertiesFile.toString(),
+                                                     e));
             }
         } else {
             // Try to read properties as resource
@@ -123,23 +124,12 @@ public class SaltstackAdapterPropertiesProviderImpl implements SaltstackAdapterP
         }
     }
 
-    /**
-     * Extract svclogic config properties.
-     *
-     * @return the svclogic config properties
-     */
-    public Properties getProperties() {
-        return properties;
-    }
-
     /**
      * Reports the method chosen for properties resolution to the
      * <code>Logger</code>.
      *
-     * @param message
-     *            Some user friendly message
-     * @param fileOptional
-     *            The file location of the chosen properties file
+     * @param message      Some user friendly message
+     * @param fileOptional The file location of the chosen properties file
      * @return the file location of the chosen properties file
      */
     private static File reportSuccess(final String message, final Optional<File> fileOptional) {
@@ -155,16 +145,23 @@ public class SaltstackAdapterPropertiesProviderImpl implements SaltstackAdapterP
      * Reports fatal errors. This is the case in which no properties file could be
      * found.
      *
-     * @param message
-     *            An appropriate fatal error message
-     * @param configurationException
-     *            An exception describing what went wrong during resolution
+     * @param message                An appropriate fatal error message
+     * @param configurationException An exception describing what went wrong during resolution
      */
     private static void reportFailure(final String message, final ConfigurationException configurationException) {
 
         LOG.error("{}", message, configurationException);
     }
 
+    /**
+     * Extract svclogic config properties.
+     *
+     * @return the svclogic config properties
+     */
+    public Properties getProperties() {
+        return properties;
+    }
+
     /**
      * Determines the sql-resource properties file to use based on the following priority:
      * <ol>
index 41e6102..96ed7d2 100644 (file)
@@ -9,22 +9,23 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- * 
+ *
  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
  * ============LICENSE_END=========================================================
  */
 
 package org.onap.ccsdk.sli.adaptors.saltstack.impl;
 
-import org.onap.appc.encryption.EncryptionTool;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
 import org.apache.sshd.ClientChannel;
 import org.apache.sshd.ClientSession;
 import org.apache.sshd.SshClient;
@@ -33,12 +34,9 @@ import org.apache.sshd.client.future.AuthFuture;
 import org.apache.sshd.client.future.OpenFuture;
 import org.apache.sshd.common.KeyPairProvider;
 import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
-
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
+import org.onap.appc.encryption.EncryptionTool;
 import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
 import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes;
-import org.onap.ccsdk.sli.core.sli.SvcLogicException;
 
 import java.io.OutputStream;
 import java.security.KeyPair;
@@ -48,11 +46,11 @@ import java.security.KeyPair;
  */
 class SshConnection {
 
+    public static final int DEFAULT_CONNECTION_RETRY_DELAY = 60;
+    public static final int DEFAULT_CONNECTION_RETRY_COUNT = 5;
     private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger();
-
     private static final long AUTH_TIMEOUT = 60000;
     private static final long EXEC_TIMEOUT = 120000;
-
     private String host;
     private int port;
     private String username;
@@ -62,9 +60,6 @@ class SshConnection {
     private SshClient sshClient;
     private ClientSession clientSession;
 
-    public static final int DEFAULT_CONNECTION_RETRY_DELAY = 60;
-    public static final int DEFAULT_CONNECTION_RETRY_COUNT = 5;
-
     public SshConnection(String host, int port, String username, String password, String keyFile) {
         this.host = host;
         this.port = port;
@@ -87,13 +82,13 @@ class SshConnection {
         sshClient.start();
         try {
             clientSession =
-                sshClient.connect(EncryptionTool.getInstance().decrypt(username), host, port).await().getSession();
+                    sshClient.connect(EncryptionTool.getInstance().decrypt(username), host, port).await().getSession();
             if (password != null) {
                 clientSession.addPasswordIdentity(EncryptionTool.getInstance().decrypt(password));
             }
             if (keyFile != null) {
-                KeyPairProvider keyPairProvider = new FileKeyPairProvider(new String[] {
-                    keyFile
+                KeyPairProvider keyPairProvider = new FileKeyPairProvider(new String[]{
+                        keyFile
                 });
                 KeyPair keyPair = keyPairProvider.loadKeys().iterator().next();
                 clientSession.addPublicKeyIdentity(keyPair);
@@ -102,18 +97,18 @@ class SshConnection {
             authFuture.await(AUTH_TIMEOUT);
             if (!authFuture.isSuccess()) {
                 String errMessage = "Error establishing ssh connection to [" + username + "@" + host + ":" + port
-                    + "]. Authentication failed.";
+                        + "]. Authentication failed.";
                 result.setStatusCode(SaltstackResultCodes.USER_UNAUTHORIZED.getValue());
                 result.setStatusMessage(errMessage);
             }
         } catch (RuntimeException e) {
             String errMessage = "Error establishing ssh connection to [" + username + "@" + host + ":" + port + "]." +
-                                                "Runtime Exception : "+ e.getMessage();
+                    "Runtime Exception : " + e.getMessage();
             result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue());
             result.setStatusMessage(errMessage);
         } catch (Exception e) {
             String errMessage = "Error establishing ssh connection to [" + username + "@" + host + ":" + port + "]." +
-                                                "Host Unknown : " + e.getMessage();
+                    "Host Unknown : " + e.getMessage();
             result.setStatusCode(SaltstackResultCodes.HOST_UNKNOWN.getValue());
             result.setStatusMessage(errMessage);
         }
@@ -127,10 +122,12 @@ class SshConnection {
     public SaltstackResult connectWithRetry(int retryCount, int retryDelay) {
         int retriesLeft;
         SaltstackResult result = new SaltstackResult();
-        if(retryCount == 0)
-        retryCount = DEFAULT_CONNECTION_RETRY_COUNT;
-        if(retryDelay == 0)
-        retryDelay = DEFAULT_CONNECTION_RETRY_DELAY;
+        if (retryCount == 0) {
+            retryCount = DEFAULT_CONNECTION_RETRY_COUNT;
+        }
+        if (retryDelay == 0) {
+            retryDelay = DEFAULT_CONNECTION_RETRY_DELAY;
+        }
         retriesLeft = retryCount + 1;
         do {
             try {
@@ -142,11 +139,11 @@ class SshConnection {
                     waitForConnection(retryDelay);
                     retriesLeft--;
                     logger.debug("Retrying SSH connection. Attempt [" + Integer.toString(retryCount - retriesLeft + 1)
-                        + "] out of [" + retryCount + "]");
+                                         + "] out of [" + retryCount + "]");
                 } else {
                     throw e;
                 }
-          }
+            }
         } while (retriesLeft > 0);
         return result;
     }
@@ -207,12 +204,12 @@ class SshConnection {
             return result;
         } catch (RuntimeException e) {
             String errMessage = "Error establishing ssh connection to [" + username + "@" + host + ":" + port + "]." +
-                    "Runtime Exception : "+ e.getMessage();
+                    "Runtime Exception : " + e.getMessage();
             result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue());
             result.setStatusMessage(errMessage);
         } catch (Exception e1) {
             String errMessage = "Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" +
-                    port + "]"+ e1.getMessage();
+                    port + "]" + e1.getMessage();
             result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue());
             result.setStatusMessage(errMessage);
         }
index f33799f..be1fa57 100644 (file)
@@ -8,9 +8,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -44,46 +44,46 @@ public final class JsonParser {
 
     @SuppressWarnings("unchecked")
     public static Map<String, String> convertToProperties(String s)
-        throws JSONException {
+            throws JSONException {
 
         checkNotNull(s, "Input should not be null.");
 
-            JSONObject json = new JSONObject(s);
-            Map<String, Object> wm = new HashMap<>();
-            Iterator<String> ii = json.keys();
-            while (ii.hasNext()) {
-                String key1 = ii.next();
-                wm.put(key1, json.get(key1));
-            }
-
-            Map<String, String> mm = new HashMap<>();
-
-            while (!wm.isEmpty())
-                for (String key : new ArrayList<>(wm.keySet())) {
-                    Object o = wm.get(key);
-                    wm.remove(key);
-
-                    if (o instanceof Boolean || o instanceof Number || o instanceof String) {
-                        mm.put(key, o.toString());
-
-                        log.info("Added property: {} : {}", key, o.toString());
-                    } else if (o instanceof JSONObject) {
-                        JSONObject jo = (JSONObject) o;
-                        Iterator<String> i = jo.keys();
-                        while (i.hasNext()) {
-                            String key1 = i.next();
-                            wm.put(key + "." + key1, jo.get(key1));
-                        }
-                    } else if (o instanceof JSONArray) {
-                        JSONArray ja = (JSONArray) o;
-                        mm.put(key + "_length", String.valueOf(ja.length()));
+        JSONObject json = new JSONObject(s);
+        Map<String, Object> wm = new HashMap<>();
+        Iterator<String> ii = json.keys();
+        while (ii.hasNext()) {
+            String key1 = ii.next();
+            wm.put(key1, json.get(key1));
+        }
+
+        Map<String, String> mm = new HashMap<>();
+
+        while (!wm.isEmpty())
+            for (String key : new ArrayList<>(wm.keySet())) {
+                Object o = wm.get(key);
+                wm.remove(key);
+
+                if (o instanceof Boolean || o instanceof Number || o instanceof String) {
+                    mm.put(key, o.toString());
+
+                    log.info("Added property: {} : {}", key, o.toString());
+                } else if (o instanceof JSONObject) {
+                    JSONObject jo = (JSONObject) o;
+                    Iterator<String> i = jo.keys();
+                    while (i.hasNext()) {
+                        String key1 = i.next();
+                        wm.put(key + "." + key1, jo.get(key1));
+                    }
+                } else if (o instanceof JSONArray) {
+                    JSONArray ja = (JSONArray) o;
+                    mm.put(key + "_length", String.valueOf(ja.length()));
 
-                        log.info("Added property: {}_length: {}", key, String.valueOf(ja.length()));
+                    log.info("Added property: {}_length: {}", key, String.valueOf(ja.length()));
 
-                        for (int i = 0; i < ja.length(); i++)
-                            wm.put(key + '[' + i + ']', ja.get(i));
-                    }
+                    for (int i = 0; i < ja.length(); i++)
+                        wm.put(key + '[' + i + ']', ja.get(i));
                 }
-            return mm;
+            }
+        return mm;
     }
 }
index 1ea3151..372d565 100644 (file)
@@ -28,6 +28,16 @@ package org.onap.ccsdk.sli.adaptors.saltstack.model;
  * This module implements the APP-C/Saltstack Server interface
  * based on the REST API specifications
  */
+
+import com.google.common.base.Strings;
+import org.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.json.JSONObject;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -39,14 +49,6 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 import java.util.UUID;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
-import org.onap.ccsdk.sli.core.sli.SvcLogicException;
-import com.google.common.base.Strings;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Class that validates and constructs requests sent/received from
@@ -63,6 +65,12 @@ public class SaltstackMessageParser {
     private static final String SS_AGENT_PORT_KEY = "Port";
     private static final String PASS_KEY = "Password";
     private static final String USER_KEY = "User";
+    private static final String CMD_EXEC = "cmd";
+    private static final String IS_SLS_EXEC = "slsExec";
+    private static final String SS_REQ_ID = "Id";
+    private static final String SLS_FILE_LOCATION = "slsFile";
+    private static final String SLS_NAME = "slsName";
+    private static final String MINION_TO_APPLY = "applyTo";
 
     private static final String LOCAL_PARAMETERS_OPT_KEY = "LocalParameters";
     private static final String FILE_PARAMETERS_OPT_KEY = "FileParameters";
@@ -78,12 +86,11 @@ public class SaltstackMessageParser {
      * Accepts a map of strings and
      * a) validates if all parameters are appropriate (else, throws an exception) and
      * b) if correct returns a JSON object with appropriate key-value pairs to send to the server.
-     *
+     * <p>
      * Mandatory parameters, that must be in the supplied information to the Saltstack Adapter
      * 1. URL to connect to
      * 2. credentials for URL (assume username password for now)
      * 3. SaltState name
-     *
      */
     public JSONObject reqMessage(Map<String, String> params) throws SvcLogicException {
         final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SALTSTATE_NAME_KEY, USER_KEY, PASS_KEY};
@@ -113,7 +120,8 @@ public class SaltstackMessageParser {
      */
     public String reqPortResult(Map<String, String> params) throws SvcLogicException {
 
-        final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY, PASS_KEY};
+        final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY,
+                PASS_KEY};
 
         for (String key : mandatoryTestParams) {
             throwIfMissingMandatoryParam(params, key);
@@ -128,7 +136,8 @@ public class SaltstackMessageParser {
      */
     public String reqHostNameResult(Map<String, String> params) throws SvcLogicException {
 
-        final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY, PASS_KEY};
+        final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY,
+                PASS_KEY};
 
         for (String key : mandatoryTestParams) {
             throwIfMissingMandatoryParam(params, key);
@@ -136,6 +145,109 @@ public class SaltstackMessageParser {
         return params.get(SS_AGENT_HOSTNAME_KEY);
     }
 
+    /**
+     * Method that validates that the Map has enough information
+     * to query Saltstack server for a result. If so, it returns
+     * the appropriate request ID.
+     */
+    public String reqId(Map<String, String> params) {
+
+        if (params.get(SaltstackMessageParser.SS_REQ_ID) == null) {
+            return UUID.randomUUID().toString();
+        } else if (params.get(SaltstackMessageParser.SS_REQ_ID).equalsIgnoreCase("")) {
+            return UUID.randomUUID().toString();
+        }
+        return params.get(SaltstackMessageParser.SS_REQ_ID);
+    }
+
+    /**
+     * Method that validates that the Map has enough information
+     * to query Saltstack server for a result. If so, it returns
+     * the appropriate command to execute.
+     */
+    public String reqCmd(Map<String, String> params) throws SvcLogicException {
+
+        final String[] mandatoryTestParams = {CMD_EXEC, IS_SLS_EXEC};
+
+        for (String key : mandatoryTestParams) {
+            throwIfMissingMandatoryParam(params, key);
+        }
+
+        return params.get(SaltstackMessageParser.CMD_EXEC);
+    }
+
+    /**
+     * Method that validates that the Map has enough information
+     * to query Saltstack server for a result. If so, it returns
+     * the appropriate SLS file location to execute.
+     */
+    public String reqSlsFile(Map<String, String> params) throws SvcLogicException {
+
+        final String[] mandatoryTestParams = {SLS_FILE_LOCATION};
+
+        for (String key : mandatoryTestParams) {
+            throwIfMissingMandatoryParam(params, key);
+        }
+
+        return params.get(SaltstackMessageParser.SLS_FILE_LOCATION);
+    }
+
+    /**
+     * Method that validates that the Map has enough information
+     * to query Saltstack server for a result. If so, it returns
+     * the appropriate SLS file location to execute.
+     */
+    public String reqSlsName(Map<String, String> params) throws SvcLogicException {
+
+        final String[] mandatoryTestParams = {SLS_NAME};
+
+        for (String key : mandatoryTestParams) {
+            throwIfMissingMandatoryParam(params, key);
+        }
+        String slsName = params.get(SaltstackMessageParser.SLS_NAME);
+        if(slsName.substring(slsName.lastIndexOf("."), slsName.length()).equalsIgnoreCase(".sls"))
+            return stripExtension(slsName);
+        return slsName;
+    }
+
+    private String stripExtension (String str) {
+        if (str == null) return null;
+        int pos = str.lastIndexOf(".");
+        if (pos == -1) return str;
+        return str.substring(0, pos);
+    }
+
+    /**
+     * Method that validates that the Map has enough information
+     * to query Saltstack server for a result. If so, it returns
+     * the appropriate minions/vnfc to execute the SLS file to.
+     */
+    public String reqApplyToDevices(Map<String, String> params) {
+
+        if (params.get(SaltstackMessageParser.MINION_TO_APPLY) == null) {
+            return "*";
+        } else if (params.get(SaltstackMessageParser.MINION_TO_APPLY).equalsIgnoreCase("")) {
+            return "*";
+        }
+        return params.get(SaltstackMessageParser.MINION_TO_APPLY);
+    }
+
+    /**
+     * Method that validates that the Map has enough information
+     * to query Saltstack server for a result. If so, it returns
+     * the appropriate IsSLSExec true or false.
+     */
+    public boolean reqIsSLSExec(Map<String, String> params) throws SvcLogicException {
+
+        final String[] mandatoryTestParams = {CMD_EXEC, IS_SLS_EXEC};
+
+        for (String key : mandatoryTestParams) {
+            throwIfMissingMandatoryParam(params, key);
+        }
+
+        return params.get(SaltstackMessageParser.IS_SLS_EXEC).equalsIgnoreCase("true");
+    }
+
     /**
      * Method that validates that the Map has enough information
      * to query Saltstack server for a result. If so, it returns
@@ -143,7 +255,8 @@ public class SaltstackMessageParser {
      */
     public String reqUserNameResult(Map<String, String> params) throws SvcLogicException {
 
-        final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY, PASS_KEY};
+        final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY,
+                PASS_KEY};
 
         for (String key : mandatoryTestParams) {
             throwIfMissingMandatoryParam(params, key);
@@ -158,7 +271,8 @@ public class SaltstackMessageParser {
      */
     public String reqPasswordResult(Map<String, String> params) throws SvcLogicException {
 
-        final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY, PASS_KEY};
+        final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY,
+                PASS_KEY};
 
         for (String key : mandatoryTestParams) {
             throwIfMissingMandatoryParam(params, key);
@@ -170,8 +284,10 @@ public class SaltstackMessageParser {
      * This method parses response from the Saltstack Server when we do a post
      * and returns an SaltstackResult object.
      */
-    public SaltstackResult parseResponse(SvcLogicContext ctx, String pfx, SaltstackResult saltstackResult) {
+    public SaltstackResult parseResponse(SvcLogicContext ctx, String pfx,
+                                         SaltstackResult saltstackResult, boolean slsExec) {
         int code = saltstackResult.getStatusCode();
+        boolean executionStatus = true, retCodeFound = false;
         if (code != SaltstackResultCodes.SUCCESS.getValue()) {
             return saltstackResult;
         }
@@ -184,20 +300,34 @@ public class SaltstackMessageParser {
             in.close();
             Map<String, String> mm = JsonParser.convertToProperties(str);
             if (mm != null) {
-                for (Map.Entry<String,String> entry : mm.entrySet()) {
-                    ctx.setAttribute(pfx + entry.getKey(), entry.getValue());
-                    LOGGER.info("+++ " + pfx + entry.getKey() + ": [" + entry.getValue() + "]");
+                for (Map.Entry<String, String> entry : mm.entrySet()) {
+                    if (entry.getKey().contains("retcode")) {
+                        retCodeFound = true;
+                        if (!entry.getValue().equalsIgnoreCase("0")) {
+                            executionStatus = false;
+                        }
+                    }
+                    ctx.setAttribute(pfx + "." + entry.getKey(), entry.getValue());
+                    LOGGER.info("+++ " + pfx + "." + entry.getKey() + ": [" + entry.getValue() + "]");
                 }
             }
-        } catch (FileNotFoundException e){
-            return new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "Error parsing response file = "
-                    + saltstackResult.getOutputFileName() + ". Error = " + e.getMessage());
+        } catch (FileNotFoundException e) {
+            return new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "error parsing response file "
+                    + saltstackResult.getOutputFileName() + " : " + e.getMessage());
         } catch (JSONException e) {
             LOGGER.info("Output not in JSON format");
             return putToProperties(ctx, pfx, saltstackResult);
         } catch (Exception e) {
-            return new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "Error parsing response file = "
-                    + saltstackResult.getOutputFileName() + ". Error = " + e.getMessage());
+            return new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "error parsing response file "
+                    + saltstackResult.getOutputFileName() + " : " + e.getMessage());
+        }
+        if (slsExec) {
+            if (!retCodeFound)
+                return new SaltstackResult(SaltstackResultCodes.COMMAND_EXEC_FAILED_STATUS.getValue(),
+                                           "error in parsing response Json after SLS file execution in server");
+            if (!executionStatus)
+                return new SaltstackResult(SaltstackResultCodes.COMMAND_EXEC_FAILED_STATUS.getValue(),
+                                           "error in parsing response Json after SLS file execution in server");
         }
         saltstackResult.setStatusCode(SaltstackResultCodes.FINAL_SUCCESS.getValue());
         return saltstackResult;
@@ -222,8 +352,10 @@ public class SaltstackMessageParser {
             saltstackResult = new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "Error parsing response file = "
                     + saltstackResult.getOutputFileName() + ". Error = " + e.getMessage());
         }
+        saltstackResult.setStatusCode(SaltstackResultCodes.FINAL_SUCCESS.getValue());
         return saltstackResult;
     }
+
     /**
      * This method parses response from an Saltstack server when we do a GET for a result
      * and returns an SaltstackResult object.
@@ -235,14 +367,14 @@ public class SaltstackMessageParser {
         try {
             JSONObject postResponse = new JSONObject(input);
             saltstackResult = parseGetResponseNested(saltstackResult, postResponse);
-        } catch (JSONException e) {
+        } catch (Exception e) {
             saltstackResult = new SaltstackResult(SaltstackResultCodes.INVALID_COMMAND.getValue(),
-                    "Error parsing response = " + input + ". Error = " + e.getMessage(), "", -1);
+                                                  "Error parsing response = " + input + ". Error = " + e.getMessage(), "", -1);
         }
         return saltstackResult;
     }
 
-    private SaltstackResult parseGetResponseNested(SaltstackResult saltstackResult, JSONObject postRsp) throws SvcLogicException  {
+    private SaltstackResult parseGetResponseNested(SaltstackResult saltstackResult, JSONObject postRsp) throws SvcLogicException {
 
         int codeStatus = postRsp.getInt(STATUS_CODE_KEY);
         String messageStatus = postRsp.getString(STATUS_MESSAGE_KEY);
@@ -253,7 +385,7 @@ public class SaltstackMessageParser {
 
         if (!valCode) {
             throw new SvcLogicException("Invalid FinalResponse code  = " + codeStatus + " received. MUST be one of "
-                    + SaltstackResultCodes.CODE.getValidCodes(SaltstackResultCodes.FINALRESPONSE.getValue()));
+                                                + SaltstackResultCodes.CODE.getValidCodes(SaltstackResultCodes.FINALRESPONSE.getValue()));
         }
 
         saltstackResult.setStatusCode(codeStatus);
@@ -285,7 +417,7 @@ public class SaltstackMessageParser {
                     if (subCode != 200 || !message.equals("SUCCESS")) {
                         finalCode = SaltstackResultCodes.REQ_FAILURE.getValue();
                     }
-                } catch (JSONException e) {
+                } catch (Exception e) {
                     saltstackResult.setStatusCode(SaltstackResultCodes.INVALID_RESPONSE.getValue());
                     saltstackResult.setStatusMessage(String.format(
                             "Error processing response message = %s from host %s", results.getString(host), host));
@@ -312,10 +444,10 @@ public class SaltstackMessageParser {
 
         //@formatter:off
         params.entrySet()
-            .stream()
-            .filter(entry -> optionalParamsSet.contains(entry.getKey()))
-            .filter(entry -> !Strings.isNullOrEmpty(entry.getValue()))
-             .forEach(entry -> parseOptionalParam(entry, jsonPayload));
+                .stream()
+                .filter(entry -> optionalParamsSet.contains(entry.getKey()))
+                .filter(entry -> !Strings.isNullOrEmpty(entry.getValue()))
+                .forEach(entry -> parseOptionalParam(entry, jsonPayload));
         //@formatter:on
     }
 
index 0587302..f6ea0b4 100644 (file)
 
 package org.onap.ccsdk.sli.adaptors.saltstack.model;
 
-import java.io.OutputStream;
-
 /**
- *  Simple class to store code and message returned by POST/GET to an Saltstack Server
+ * Simple class to store code and message returned by POST/GET to an Saltstack Server
  */
 public class SaltstackResult {
 
@@ -54,44 +52,44 @@ public class SaltstackResult {
         sshExitStatus = sshCode;
     }
 
-    public void setStatusCode(int code) {
-        this.statusCode = code;
-    }
-
-    public void setStatusMessage(String message) {
-        this.statusMessage = message;
-    }
-
-    public void setResults(String results) {
-        this.results = results;
-    }
-
     void set(int code, String message, String results) {
         this.statusCode = code;
         this.statusMessage = message;
         this.results = results;
     }
 
-    public void setOutputFileName (String out) {
-        this.out = out;
-    }
-
     public String getOutputFileName() {
         return out;
     }
 
+    public void setOutputFileName(String out) {
+        this.out = out;
+    }
+
     public int getStatusCode() {
         return this.statusCode;
     }
 
+    public void setStatusCode(int code) {
+        this.statusCode = code;
+    }
+
     public String getStatusMessage() {
         return this.statusMessage;
     }
 
+    public void setStatusMessage(String message) {
+        this.statusMessage = message;
+    }
+
     public String getResults() {
         return this.results;
     }
 
+    public void setResults(String results) {
+        this.results = results;
+    }
+
     public int getSshExitStatus() {
         return sshExitStatus;
     }
index ab88c21..32871ff 100644 (file)
@@ -52,6 +52,8 @@ public enum SaltstackResultCodes {
     PENDING(100),
     REJECTED(101),
     FINAL_SUCCESS(200),
+    CHECK_CTX_FOR_CMD_SUCCESS(250),
+    COMMAND_EXEC_FAILED_STATUS(670),
     REQ_FAILURE(401),
     MESSAGE(1),
     CODE(0),
@@ -67,7 +69,9 @@ public enum SaltstackResultCodes {
 
     SaltstackResultCodes(int value) {
         this.value = value;
-    };
+    }
+
+    ;
 
     public int getValue() {
         return value;
index 9737efd..ecb36fb 100644 (file)
 
 package org.onap.ccsdk.sli.adaptors.saltstack.model;
 
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.apache.commons.lang.StringUtils;
+import org.json.JSONObject;
+
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import org.apache.commons.lang.StringUtils;
-import org.json.JSONException;
-import org.json.JSONObject;
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
 
 public class SaltstackServerEmulator {
 
-    private final EELFLogger logger = EELFManager.getInstance().getLogger(SaltstackServerEmulator.class);
-
-    private static final String SALTSTATE_NAME = "SaltStateName";
+    private static final String SALTSTATE_FILE_NAME = "fileName";
     private static final String STATUS_CODE = "StatusCode";
     private static final String STATUS_MESSAGE = "StatusMessage";
-
+    private final EELFLogger logger = EELFManager.getInstance().getLogger(SaltstackServerEmulator.class);
     private String saltStateName = "test_saltState.yaml";
 
     /**
@@ -62,9 +60,13 @@ public class SaltstackServerEmulator {
 
         try {
             if (params.get("Test") == "fail") {
-                result = rejectRequest(result, "Must provide a valid Id");
+                result = rejectRequest(result, "Mocked: Fail");
             } else {
-                result = acceptRequest(result);
+                String fileName = params.get(SALTSTATE_FILE_NAME);
+                if (fileName == null)
+                    result = acceptRequest(result, "");
+                else
+                    result = acceptRequest(result, fileName);
             }
         } catch (Exception e) {
             logger.error("JSONException caught", e);
@@ -73,42 +75,11 @@ public class SaltstackServerEmulator {
         return result;
     }
 
-    /**
-     * Method that emulates the response from an Saltstack Server
-     * when presented with a request to execute a saltState
-     * Returns an saltstack object result. The response code is always the ssh code 200 (i.e connection successful)
-     * payload is json string as would be sent back by Saltstack Server
-     **/
-    //TODO: This class is to be altered completely based on the SALTSTACK server communicaiton.
-    public SaltstackResult Connect(Map<String, String> params) {
-        SaltstackResult result = new SaltstackResult();
-
-        try {
-            // Request must be a JSON object
-
-            JSONObject message = new JSONObject();
-            if (message.isNull("Id")) {
-                rejectRequest(result, "Must provide a valid Id");
-            } else if (message.isNull(SALTSTATE_NAME)) {
-                rejectRequest(result, "Must provide a saltState Name");
-            } else if (!message.getString(SALTSTATE_NAME).equals(saltStateName)) {
-                rejectRequest(result, "SaltState " + message.getString(SALTSTATE_NAME) + "  not found in catalog");
-            } else {
-                acceptRequest(result);
-            }
-        } catch (JSONException e) {
-            logger.error("JSONException caught", e);
-            rejectRequest(result, e.getMessage());
-        }
-        return result;
-    }
-
     /**
      * Method to emulate response from an Saltstack
      * Server when presented with a GET request
      * Returns an saltstack object result. The response code is always the ssh code 200 (i.e connection successful)
      * payload is json string as would be sent back by Saltstack Server
-     *
      **/
     public SaltstackResult Execute(String agentUrl) {
 
@@ -149,9 +120,10 @@ public class SaltstackServerEmulator {
         return result;
     }
 
-    private SaltstackResult acceptRequest(SaltstackResult result) {
+    private SaltstackResult acceptRequest(SaltstackResult result, String fileName) {
         result.setStatusCode(SaltstackResultCodes.SUCCESS.getValue());
         result.setStatusMessage("Success");
+        result.setOutputFileName(fileName);
         return result;
     }
 }
\ No newline at end of file
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestConnectionBuilder.java b/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestConnectionBuilder.java
new file mode 100644 (file)
index 0000000..d9a3841
--- /dev/null
@@ -0,0 +1,174 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.appc.adapter.impl;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.saltstack.impl.ConnectionBuilder;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+
+public class TestConnectionBuilder {
+
+    private final String PENDING = "100";
+    private final String SUCCESS = "400";
+    private String message = "{\"Results\":{\"192.168.1.10\":{\"Id\":\"101\",\"StatusCode\":200,\"StatusMessage\":\"SUCCESS\"}},\"StatusCode\":200,\"StatusMessage\":\"FINISHED\"}";
+
+    private ConnectionBuilder connBuilder;
+    private String TestId;
+    private boolean testMode = true;
+    private Map<String, String> params;
+    private SvcLogicContext svcContext;
+
+
+    @Before
+    public void setup() throws IllegalArgumentException {
+        testMode = true;
+        svcContext = new SvcLogicContext();
+        String HostName = "test";
+        String Port = "10";
+        String User = "test";
+        String Password = "test";
+        connBuilder = new ConnectionBuilder(HostName, Port, User, Password);
+
+        params = new HashMap<>();
+        params.put("AgentUrl", "https://192.168.1.1");
+        params.put("User", "test");
+        params.put("Password", "test");
+    }
+
+    @After
+    public void tearDown() {
+        testMode = false;
+        connBuilder = null;
+        params = null;
+        svcContext = null;
+    }
+
+    @Test
+    public void reqExecCommand_exitStatus255() {
+
+        int exitStatus = 255;
+        String errFilePath = "src/test/resources/test.json";
+        String command = "test";
+
+        SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+        int status = result.getStatusCode();
+        assertEquals(698, status);
+    }
+
+    @Test
+    public void reqExecCommand_exitStatus1() {
+
+        int exitStatus = 1;
+        String errFilePath = "src/test/resources/test.json";
+        String command = "test";
+
+        SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+        int status = result.getStatusCode();
+        assertEquals(698, status);
+    }
+
+    @Test
+    public void reqExecCommand_exitStatus5() {
+
+        int exitStatus = 5;
+        String errFilePath = "src/test/resources/test.json";
+        String command = "test";
+
+        SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+        int status = result.getStatusCode();
+        assertEquals(613, status);
+    }
+
+    @Test
+    public void reqExecCommand_exitStatus65() {
+
+        int exitStatus = 65;
+        String errFilePath = "src/test/resources/test.json";
+        String command = "test";
+
+        SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+        int status = result.getStatusCode();
+        assertEquals(613, status);
+    }
+
+    @Test
+    public void reqExecCommand_exitStatus67() {
+
+        int exitStatus = 5;
+        String errFilePath = "src/test/resources/test.json";
+        String command = "test";
+
+        SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+        int status = result.getStatusCode();
+        assertEquals(613, status);
+    }
+
+    @Test
+    public void reqExecCommand_exitStatus73() {
+
+        int exitStatus = 65;
+        String errFilePath = "src/test/resources/test.json";
+        String command = "test";
+
+        SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+        int status = result.getStatusCode();
+        assertEquals(613, status);
+    }
+
+    @Test
+    public void reqExecCommand_exitStatusUnknown() {
+
+        int exitStatus = 5121;
+        String errFilePath = "src/test/resources/test.json";
+        String command = "test";
+
+        SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+        int status = result.getStatusCode();
+        assertEquals(699, status);
+    }
+
+    @Test
+    public void reqExecCommand_exitStatusNoFile() {
+
+        int exitStatus = 65;
+        String errFilePath = "src/test/resource/test.json";
+        String command = "test";
+
+        SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+        int status = result.getStatusCode();
+        assertEquals(613, status);
+    }
+}
index d7b3303..c8776fb 100644 (file)
@@ -82,7 +82,7 @@ public class TestSaltstackAdapterImpl {
         params.put("Test", "fail");
             adapter.reqExecCommand(params, svcContext);
             String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
-            TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id");
+            TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
             assertEquals("101", status);
     }
 
@@ -96,7 +96,7 @@ public class TestSaltstackAdapterImpl {
         params.put("Test", "fail");
         adapter.reqExecCommand(params, svcContext);
         String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
-        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
         assertEquals("101", status);
     }
 
@@ -110,7 +110,7 @@ public class TestSaltstackAdapterImpl {
         params.put("Test", "fail");
         adapter.reqExecCommand(params, svcContext);
         String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
-        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
         assertEquals("101", status);
     }
 
@@ -124,7 +124,7 @@ public class TestSaltstackAdapterImpl {
         params.put("Test", "fail");
         adapter.reqExecCommand(params, svcContext);
         String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
-        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
         assertEquals("101", status);
     }
 
@@ -138,7 +138,7 @@ public class TestSaltstackAdapterImpl {
         params.put("Test", "fail");
         adapter.reqExecCommand(params, svcContext);
         String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
-        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
         assertEquals("101", status);
     }
 
@@ -149,24 +149,25 @@ public class TestSaltstackAdapterImpl {
         params.put("Test", "fail");
         adapter.reqExecCommand(params, svcContext);
         String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
-        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
         assertEquals("101", status);
     }
 
     @Test(expected = SvcLogicException.class)
-    public void reqExecCommand_shouldSetSuccess() throws SvcLogicException,
+    public void reqExecCommand_NoResponseFile() throws SvcLogicException,
             IllegalStateException, IllegalArgumentException {
 
-        params.put("PlaybookName", "test_playbook.yaml");
         params.put("HostName", "test");
         params.put("Port", "10");
         params.put("User", "test");
         params.put("Password", "test");
         params.put("Test", "success");
+        params.put("cmd", "test");
+        params.put("slsExec", "false");
         try {
             adapter.reqExecCommand(params, svcContext);
             String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
-            TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id");
+            TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
             assertEquals("400", status);
         } catch (NullPointerException e) {
             fail(e.getMessage() + " Unknown exception encountered ");
@@ -174,10 +175,9 @@ public class TestSaltstackAdapterImpl {
     }
 
     @Test(expected = SvcLogicException.class)
-    public void reqExecCommand_shouldSetSuccessWithRetry() throws SvcLogicException,
+    public void reqExecCommand_NoResponseFileWithRetry() throws SvcLogicException,
             IllegalStateException, IllegalArgumentException {
 
-        params.put("PlaybookName", "test_playbook.yaml");
         params.put("HostName", "test");
         params.put("Port", "10");
         params.put("User", "test");
@@ -185,10 +185,12 @@ public class TestSaltstackAdapterImpl {
         params.put("Test", "success");
         params.put("retryDelay", "10");
         params.put("retryCount", "10");
+        params.put("cmd", "test");
+        params.put("slsExec", "false");
         try {
             adapter.reqExecCommand(params, svcContext);
             String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
-            TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id");
+            TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
             assertEquals("400", status);
         } catch (NullPointerException e) {
             fail(e.getMessage() + " Unknown exception encountered ");
@@ -196,10 +198,9 @@ public class TestSaltstackAdapterImpl {
     }
 
     @Test(expected = SvcLogicException.class)
-    public void reqExecCommand_shouldSetSuccessWithRetryZero() throws SvcLogicException,
+    public void reqExecCommand_NoResponseFileWithRetryZero() throws SvcLogicException,
             IllegalStateException, IllegalArgumentException {
 
-        params.put("PlaybookName", "test_playbook.yaml");
         params.put("HostName", "test");
         params.put("Port", "10");
         params.put("User", "test");
@@ -207,10 +208,12 @@ public class TestSaltstackAdapterImpl {
         params.put("Test", "success");
         params.put("retryDelay", "0");
         params.put("retryCount", "0");
+        params.put("cmd", "test");
+        params.put("slsExec", "false");
         try {
             adapter.reqExecCommand(params, svcContext);
             String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
-            TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id");
+            TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
             assertEquals("400", status);
         } catch (NullPointerException e) {
             fail(e.getMessage() + " Unknown exception encountered ");
@@ -218,10 +221,9 @@ public class TestSaltstackAdapterImpl {
     }
 
     @Test(expected = SvcLogicException.class)
-    public void reqExecCommand_shouldSetSuccessWithNoRetry() throws SvcLogicException,
+    public void reqExecCommand_NoResponseFileWithNoRetry() throws SvcLogicException,
             IllegalStateException, IllegalArgumentException {
 
-        params.put("PlaybookName", "test_playbook.yaml");
         params.put("HostName", "test");
         params.put("Port", "10");
         params.put("User", "test");
@@ -229,37 +231,381 @@ public class TestSaltstackAdapterImpl {
         params.put("Test", "success");
         params.put("retryDelay", "-1");
         params.put("retryCount", "-1");
+        params.put("cmd", "test");
+        params.put("slsExec", "false");
+
         try {
             adapter.reqExecCommand(params, svcContext);
             String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
-            TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id");
+            TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
             assertEquals("400", status);
         } catch (NullPointerException e) {
             fail(e.getMessage() + " Unknown exception encountered ");
         }
     }
-    @Test
-    public void reqExecSLS_shouldSetSuccess() throws IllegalStateException, IllegalArgumentException {
 
-        params.put("Id", "100");
-
-        for (String ukey : params.keySet()) {
-            System.out.println(String.format("Saltstack Parameter %s = %s", ukey, params.get(ukey)));
-        }
+    @Test(expected = SvcLogicException.class)
+    public void reqExecCommand_shouldSetFailure() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
 
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("cmd", "test");
+        params.put("slsExec", "test");
+        params.put("Test", "fail");
         try {
-            adapter.reqExecSLS(params, svcContext);
-            String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
-            //assertEquals(SUCCESS, status);
-            assertEquals(null, status);
-        } catch (SvcLogicException e) {
+            adapter.reqExecCommand(params, svcContext);
             String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
-            fail(e.getMessage() + " Code = " + status);
-        } catch (Exception e) {
+            TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+            assertEquals("400", status);
+        } catch (NullPointerException e) {
             fail(e.getMessage() + " Unknown exception encountered ");
         }
     }
 
+    @Test
+    public void reqExecCommand_shouldSetSuccessNoSLS() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("fileName", "src/test/resources/test.json");
+        params.put("Id", "test1");
+        params.put("cmd", "test");
+        params.put("slsExec", "false");
+
+        adapter.reqExecCommand(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals("250", status);
+        assertEquals(TestId, "test1");
+    }
+
+    @Test
+    public void reqExecCommand_shouldSetSuccessExecSLS() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("fileName", "src/test/resources/test-sls.json");
+        params.put("Id", "test1");
+        params.put("cmd", "test");
+        params.put("slsExec", "true");
+
+        adapter.reqExecCommand(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals("200", status);
+        assertEquals(TestId, "test1");
+    }
+
+    @Test(expected = SvcLogicException.class)
+    public void reqExecCommand_shouldSetFailExecSLS() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("fileName", "src/test/resources/test.json");
+        params.put("Id", "test1");
+        params.put("cmd", "test");
+        params.put("slsExec", "true");
+
+        adapter.reqExecCommand(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals(TestId, "test1");
+    }
+
+    @Test
+    public void reqExecCommand_shouldSetSuccessFileTxt() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("fileName", "src/test/resources/test.txt");
+        params.put("Id", "txt");
+        params.put("cmd", "test");
+        params.put("slsExec", "false");
+
+        adapter.reqExecCommand(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals("250", status);
+        assertEquals(TestId, "txt");
+    }
+
+    @Test
+    public void reqExecCommand_shouldSetSuccessFileNoExtension() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("fileName", "src/test/resources/test");
+        params.put("Id", "txt");
+        params.put("cmd", "test");
+        params.put("slsExec", "false");
+
+        adapter.reqExecCommand(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals("250", status);
+        assertEquals(TestId, "txt");
+    }
+
+    @Test
+    public void reqExecCommand_shouldSetSuccessFileInvalidJson() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("fileName", "src/test/resources/test-invalid.json");
+        params.put("Id", "test1");
+        params.put("cmd", "test");
+        params.put("slsExec", "false");
+
+        adapter.reqExecCommand(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals("250", status);
+    }
+
+    @Test(expected = SvcLogicException.class)
+    public void reqExecCommand_shouldSetFailFileInvalidFile() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("fileName", "src/test/resources/test-none.json");
+        params.put("Id", "test1");
+
+        adapter.reqExecCommand(params, svcContext);
+    }
+
+    @Test
+    public void reqExecCommand_shouldSetSuccessFileJsonNoReqID() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("fileName", "src/test/resources/test.json");
+        params.put("cmd", "test");
+        params.put("slsExec", "false");
+
+        adapter.reqExecCommand(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals("250", status);
+    }
+
+    @Test
+    public void reqExecSLSFile_shouldSetSuccessJson() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("slsFile", "src/test/resources/test.json");
+        params.put("fileName", "src/test/resources/test-sls.json");
+        params.put("Id", "test1");
+        params.put("cmd", "test");
+
+        adapter.reqExecSLSFile(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals("200", status);
+        assertEquals(TestId, "test1");
+    }
+
+    @Test(expected = SvcLogicException.class)
+    public void reqExecSLSFile_NoSLSfile() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("slsFile", "src/test/resources/test-none.json");
+        params.put("fileName", "src/test/resources/test-sls.json");
+        params.put("Id", "test1");
+
+        adapter.reqExecSLSFile(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals(TestId, "test1");
+    }
+
+    @Test(expected = SvcLogicException.class)
+    public void reqExecSLSFile_NoResponsefile() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("slsFile", "src/test/resources/test.json");
+        params.put("fileName", "src/test/resources/test-none.json");
+        params.put("Id", "test1");
+
+        adapter.reqExecSLSFile(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals(TestId, "test1");
+    }
+
+    @Test
+    public void reqExecSLSFile_WithMinionSetSuccessJson() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("slsFile", "src/test/resources/test.json");
+        params.put("fileName", "src/test/resources/test-sls.json");
+        params.put("Id", "test1");
+        params.put("cmd", "test");
+        params.put("applyTo", "minion1");
+
+        adapter.reqExecSLSFile(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals("200", status);
+        assertEquals(TestId, "test1");
+    }
+
+    @Test(expected = SvcLogicException.class)
+    public void reqExecSLSFile_WithMinionNoSLSfile() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("slsFile", "src/test/resources/test-none.json");
+        params.put("fileName", "src/test/resources/test-sls.json");
+        params.put("Id", "test1");
+        params.put("applyTo", "minion1");
+
+        adapter.reqExecSLSFile(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals(TestId, "test1");
+    }
+
+    @Test(expected = SvcLogicException.class)
+    public void reqExecSLSFile_WithMinionNoResponsefile() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("slsFile", "src/test/resources/test.json");
+        params.put("fileName", "src/test/resources/test-none.json");
+        params.put("Id", "test1");
+        params.put("applyTo", "minion1");
+
+        adapter.reqExecSLSFile(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals(TestId, "test1");
+    }
+
+    @Test
+    public void reqExecSLSFile_WithAllMinionSetSuccessJson() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("slsFile", "src/test/resources/test.json");
+        params.put("fileName", "src/test/resources/test-sls.json");
+        params.put("Id", "test1");
+        params.put("cmd", "test");
+        params.put("applyTo", "*");
+
+        adapter.reqExecSLSFile(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals("200", status);
+        assertEquals(TestId, "test1");
+    }
+
+    @Test(expected = SvcLogicException.class)
+    public void reqExecSLSFile_WithAllMinionNoSLSfile() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("slsFile", "src/test/resources/test-none.json");
+        params.put("fileName", "src/test/resources/test-sls.json");
+        params.put("Id", "test1");
+        params.put("applyTo", "*");
+
+        adapter.reqExecSLSFile(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals(TestId, "test1");
+    }
+
+    @Test(expected = SvcLogicException.class)
+    public void reqExecSLSFile_WithAllMinionNoResponsefile() throws SvcLogicException,
+            IllegalStateException, IllegalArgumentException {
+
+        params.put("HostName", "test");
+        params.put("Port", "10");
+        params.put("User", "test");
+        params.put("Password", "test");
+        params.put("Test", "success");
+        params.put("slsFile", "src/test/resources/test.json");
+        params.put("fileName", "src/test/resources/test-none.json");
+        params.put("Id", "test1");
+        params.put("applyTo", "*");
+
+        adapter.reqExecSLSFile(params, svcContext);
+        String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+        TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+        assertEquals(TestId, "test1");
+    }
+
     @Test
     public void reqExecLog_shouldSetMessage() throws IllegalStateException, IllegalArgumentException {
 
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/model/TestJsonParser.java b/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/model/TestJsonParser.java
new file mode 100644 (file)
index 0000000..ae13da6
--- /dev/null
@@ -0,0 +1,74 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ *                     reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.appc.adapter.model;
+
+import org.codehaus.jettison.json.JSONException;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.JsonParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class TestJsonParser {
+
+    private static final Logger log = LoggerFactory.getLogger(TestJsonParser.class);
+
+    @Test
+    public void test() throws SvcLogicException, IOException, JSONException {
+        BufferedReader in = new BufferedReader(
+                new InputStreamReader(ClassLoader.getSystemResourceAsStream("test.json"))
+        );
+        StringBuilder b = new StringBuilder();
+        String line;
+        while ((line = in.readLine()) != null)
+            b.append(line).append('\n');
+
+        Map<String, String> mm = JsonParser.convertToProperties(b.toString());
+
+        logProperties(mm);
+
+        in.close();
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testNullString() throws SvcLogicException, JSONException {
+        JsonParser.convertToProperties(null);
+    }
+
+    private void logProperties(Map<String, String> mm) {
+        List<String> ll = new ArrayList<>();
+        for (Object o : mm.keySet())
+            ll.add((String) o);
+        Collections.sort(ll);
+        log.info("Properties:");
+        for (String name : ll)
+            log.info("--- {}: {}", name, mm.get(name));
+    }
+}
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test
new file mode 100644 (file)
index 0000000..dec578b
--- /dev/null
@@ -0,0 +1,30 @@
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-egress-class-queueing-policing-codes.cos2v-queueing-code = P
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-egress-class-queueing-policing-codes.cos3-queueing-code = W
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos2-queueing = WRED
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos2v-queueing = QueueLimit
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing = WRED
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos2-shaping = Disable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos2v-shaping = Enable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos3-shaping = Disable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-codes.cos2-shaping-code = W
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-codes.cos2v-shaping-code = P
+service-configuration-notification-input.ack-final-indicator = Y
+service-configuration-notification-input.response-code = 0
+service-configuration-notification-input.response-message = Plc Activation Failed: Device gblond2005me6 Sync-from Failed. Please check device IP address and NCS setup.
+service-configuration-notification-input.service-information.service-instance-id = TEST7
+service-configuration-notification-input.service-information.service-type = AVPN
+service-configuration-notification-input.svc-request-id = TEST7
+service-data.avpn-ip-port-information.avpn-access-information.access-circuit-id = DHEC.54831.170.ATI
+service-data.avpn-ip-port-information.avpn-access-information.access-interface = _1G
+service-data.avpn-ip-port-information.avpn-access-information.access-speed = 10000
+service-data.avpn-ip-port-information.avpn-access-information.access-speed-units = Kbps
+service-data.avpn-ip-port-information.avpn-access-information.l1-customer-handoff = _1000BASELX
+service-data.avpn-ip-port-information.avpn-access-information.managed-ce = N
+service-data.avpn-ip-port-information.avpn-access-information.vlan-tag-control = _1Q
+service-data.avpn-ip-port-information.clli = LONDENEH
+service-data.avpn-ip-port-information.contracted-port-speed = 10000
+service-data.avpn-ip-port-information.contracted-port-speed-units = Kbps
+service-data.avpn-ip-port-information.endpoint-information.bundle-id = 33
+service-data.avpn-ip-port-information.endpoint-information.interface-string = ae0
+service-data.service-information.service-instance-id = ICORESITE-2751508
+service-data.service-information.service-type = AVPN
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-invalid.json b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-invalid.json
new file mode 100644 (file)
index 0000000..53158ca
--- /dev/null
@@ -0,0 +1,29 @@
+"equipment-data": [
+{
+"server-count": "4",
+"max-server-speed": "1600000",
+"number-primary-servers": "2",
+"equipment-id": "Server1",
+"server-model": "Unknown",
+"server-id": "Server1",
+"test-node" : {
+"test-inner-node" : "Test-Value"
+}
+}
+],
+"resource-state": {
+"threshold-value": "1600000",
+"last-added": "1605000",
+"used": "1605000",
+"limit-value": "1920000"
+},
+"resource-rule": {
+"endpoint-position": "VCE-Cust",
+"soft-limit-expression": "0.6 * max-server-speed * number-primary-servers",
+"resource-name": "Bandwidth",
+"service-model": "DUMMY",
+"hard-limit-expression": "max-server-speed * number-primary-servers",
+"equipment-level": "Server"
+},
+"message": "The provisioned access bandwidth is at or exceeds 50% of the total server capacity."
+}
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-sls.json b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-sls.json
new file mode 100644 (file)
index 0000000..bc1c10c
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  "minion1": {
+    "retcode": 0,
+    "pkg_|-install_network_packages_|-install_network_packages_|-installed": {
+      "comment": "The following packages were installed/updated: lftp\nThe following packages were already installed: rsync, curl",
+      "name": "install_network_packages",
+      "start_time": "08:47:16.061765",
+      "result": true,
+      "duration": 11086.334,
+      "__run_num__": 0,
+      "__sls__": "nettools",
+      "changes": {
+        "lftp": {
+          "new": "4.6.3a-1build2",
+          "old": ""
+        }
+      },
+      "__id__": "install_network_packages"
+    }
+  },
+  "minion2": {
+    "retcode": 0,
+    "pkg_|-install_network_packages_|-install_network_packages_|-installed": {
+      "comment": "All specified packages are already installed",
+      "name": "curl",
+      "start_time": "08:47:16.152099",
+      "result": true,
+      "duration": 426.493,
+      "__run_num__": 0,
+      "__sls__": "nettools",
+      "changes": {},
+      "__id__": "install_network_packages"
+    }
+  }
+}
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.json b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.json
new file mode 100644 (file)
index 0000000..cd76486
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "equipment-data": [
+    {
+      "server-count": "4",
+      "max-server-speed": "1600000",
+      "number-primary-servers": "2",
+      "equipment-id": "Server1",
+      "server-model": "Unknown",
+      "server-id": "Server1",
+      "test-node" : {
+        "test-inner-node" : "Test-Value"
+      }
+    }
+  ],
+  "resource-state": {
+    "threshold-value": "1600000",
+    "last-added": "1605000",
+    "used": "1605000",
+    "limit-value": "1920000"
+  },
+  "resource-rule": {
+    "endpoint-position": "VCE-Cust",
+    "soft-limit-expression": "0.6 * max-server-speed * number-primary-servers",
+    "resource-name": "Bandwidth",
+    "service-model": "DUMMY",
+    "hard-limit-expression": "max-server-speed * number-primary-servers",
+    "equipment-level": "Server"
+  },
+  "message": "The provisioned access bandwidth is at or exceeds 50% of the total server capacity."
+}
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.txt b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.txt
new file mode 100644 (file)
index 0000000..dec578b
--- /dev/null
@@ -0,0 +1,30 @@
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-egress-class-queueing-policing-codes.cos2v-queueing-code = P
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-egress-class-queueing-policing-codes.cos3-queueing-code = W
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos2-queueing = WRED
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos2v-queueing = QueueLimit
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing = WRED
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos2-shaping = Disable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos2v-shaping = Enable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos3-shaping = Disable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-codes.cos2-shaping-code = W
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-codes.cos2v-shaping-code = P
+service-configuration-notification-input.ack-final-indicator = Y
+service-configuration-notification-input.response-code = 0
+service-configuration-notification-input.response-message = Plc Activation Failed: Device gblond2005me6 Sync-from Failed. Please check device IP address and NCS setup.
+service-configuration-notification-input.service-information.service-instance-id = TEST7
+service-configuration-notification-input.service-information.service-type = AVPN
+service-configuration-notification-input.svc-request-id = TEST7
+service-data.avpn-ip-port-information.avpn-access-information.access-circuit-id = DHEC.54831.170.ATI
+service-data.avpn-ip-port-information.avpn-access-information.access-interface = _1G
+service-data.avpn-ip-port-information.avpn-access-information.access-speed = 10000
+service-data.avpn-ip-port-information.avpn-access-information.access-speed-units = Kbps
+service-data.avpn-ip-port-information.avpn-access-information.l1-customer-handoff = _1000BASELX
+service-data.avpn-ip-port-information.avpn-access-information.managed-ce = N
+service-data.avpn-ip-port-information.avpn-access-information.vlan-tag-control = _1Q
+service-data.avpn-ip-port-information.clli = LONDENEH
+service-data.avpn-ip-port-information.contracted-port-speed = 10000
+service-data.avpn-ip-port-information.contracted-port-speed-units = Kbps
+service-data.avpn-ip-port-information.endpoint-information.bundle-id = 33
+service-data.avpn-ip-port-information.endpoint-information.interface-string = ae0
+service-data.service-information.service-instance-id = ICORESITE-2751508
+service-data.service-information.service-type = AVPN