summaryrefslogtreecommitdiffstats
path: root/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src
diff options
context:
space:
mode:
Diffstat (limited to 'adaptors/saltstack-adaptor/saltstack-adaptor-provider/src')
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdaptor.java59
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdaptorPropertiesProvider.java32
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java172
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdaptorImpl.java446
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdaptorPropertiesProviderImpl.java192
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java217
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/Constants.java93
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java89
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java412
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java102
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java100
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java93
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SshException.java37
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/resources/org/opendaylight/blueprint/saltstack-adaptor-blueprint.xml42
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/resources/saltstack-adaptor.properties43
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/TestConnectionBuilder.java184
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/TestSaltstackAdaptorImpl.java1051
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/TestSaltstackAdaptorPropertiesProviderImpl.java310
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/model/TestJsonParser.java76
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/config.sls2
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/org/onap/ccsdk/default.properties102
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test30
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test-invalid.json29
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test-sls.json35
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test.json30
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test.sls30
-rw-r--r--adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test.txt30
27 files changed, 4038 insertions, 0 deletions
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdaptor.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdaptor.java
new file mode 100644
index 000000000..dda333852
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdaptor.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.sli.adaptors.saltstack;
+
+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 adaptor exposes.
+ */
+public interface SaltstackAdaptor extends SvcLogicJavaPlugin {
+ /**
+ * Returns the symbolic name of the adaptor
+ *
+ * @return The adaptor name
+ */
+ String getAdaptorName();
+
+ /* Method to post a single command request for execution 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 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 reqExecSLSFile(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdaptorPropertiesProvider.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdaptorPropertiesProvider.java
new file mode 100644
index 000000000..fdfc79e66
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdaptorPropertiesProvider.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.sli.adaptors.saltstack;
+
+import java.util.Properties;
+
+public interface SaltstackAdaptorPropertiesProvider {
+
+ public Properties getProperties();
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java
new file mode 100644
index 000000000..48469fdd5
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java
@@ -0,0 +1,172 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.sli.adaptors.saltstack.impl;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SshException;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Returns a custom SSH client
+ * - based on options
+ * - can create one with ssl using an X509 certificate that does NOT have a known CA
+ * - create one which trusts ALL SSL certificates
+ * - return default sshclient (which only trusts known CAs from default cacerts file for process) this is the default
+ * option
+ **/
+public class ConnectionBuilder {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(ConnectionBuilder.class);
+ SshConnection sshConnection;
+
+ /**
+ * Constructor that initializes an ssh client based on username and password
+ **/
+ public ConnectionBuilder(String host, String port, String userName, String userPasswd) {
+ sshConnection = new SshConnection(host, Integer.parseInt(port), userName, userPasswd);
+ }
+
+ /**
+ * Constructor that initializes an ssh client based on ssh certificate
+ * This is still not supported in 1.3.0 version
+ **/
+ public ConnectionBuilder(String host, String port, String certFile) {
+ sshConnection = new SshConnection(host, Integer.parseInt(port), certFile);
+ }
+
+
+ /**
+ * 1. Connect to SSH server.
+ * 2. Exec remote command over SSH. Return command execution status.
+ * Command output is written to out or err stream.
+ *
+ * @param cmd Commands to execute
+ * @return command execution status
+ */
+ public SaltstackResult connectNExecute(String cmd, long execTimeout) throws IOException {
+ return connectNExecute(cmd, false, execTimeout);
+ }
+
+ /**
+ * 1. Connect to SSH server with retry enabled.
+ * 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 withRetry make a SSH connection with default retry.
+ * @return command execution status
+ */
+ public SaltstackResult connectNExecute(String cmd, boolean withRetry, long execTimeout)
+ throws IOException {
+
+ SaltstackResult result = new SaltstackResult();
+ ByteArrayOutputStream out = null;
+ ByteArrayOutputStream errs = null;
+ if (execTimeout >= 0) {
+ sshConnection.setExecTimeout(execTimeout);
+ }
+
+ try {
+ if (withRetry) {
+ sshConnection.connectWithRetry();
+ } else {
+ sshConnection.connect();
+ }
+ out = new ByteArrayOutputStream();
+ errs = new ByteArrayOutputStream();
+ int resultCode = sshConnection.execCommand(cmd, out, errs);
+ sshConnection.disconnect();
+ if (resultCode != 0) {
+ return sortExitStatus(resultCode, errs.toString(), cmd);
+ }
+ result.setStatusCode(SaltstackResultCodes.SUCCESS.getValue());
+ result.setStatusMessage("Success");
+ result.setOutputMessage(out);
+ } catch (SshException io) {
+ if (io.toString().equalsIgnoreCase("Authentication failed")) {
+ logger.error(io.toString());
+ result.setStatusCode(SaltstackResultCodes.USER_UNAUTHORIZED.getValue());
+ result.setStatusMessage(io.toString());
+ return result;
+ }
+ logger.error("Caught Exception", io);
+ result.setStatusCode(SaltstackResultCodes.SSH_EXCEPTION.getValue());
+ result.setStatusMessage(io.getMessage());
+ } catch (Exception io) {
+ logger.error("Caught Exception", io);
+ result.setStatusCode(SaltstackResultCodes.SSH_EXCEPTION.getValue());
+ result.setStatusMessage(io.getMessage());
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ if (errs != null) {
+ errs.close();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Print Reasonable error messages based on SSH Exit status code
+ * */
+ public SaltstackResult sortExitStatus(int exitStatus, String errMess, String cmd) {
+ SaltstackResult result = new SaltstackResult();
+ if (exitStatus == 255 || exitStatus == 1) {
+ String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
+ + "]. Exit Code " + exitStatus + " and Error message : " +
+ "Malformed configuration. " + errMess;
+ 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. " + errMess;
+ 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. " + errMess;
+ 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 : " + errMess;
+ logger.error(errMessage);
+ result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue());
+ result.setStatusMessage(errMessage);
+ }
+ return result;
+ }
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdaptorImpl.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdaptorImpl.java
new file mode 100644
index 000000000..05b1688b6
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdaptorImpl.java
@@ -0,0 +1,446 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.sli.adaptors.saltstack.impl;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdaptor;
+import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdaptorPropertiesProvider;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackMessageParser;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
+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 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 SaltstackAdaptor} interface. This interface defines the behaviors
+ * that our service provides.
+ */
+public class SaltstackAdaptorImpl implements SaltstackAdaptor {
+
+ /**
+ * 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 = "withRetry";
+ private static final String APPC_EXCEPTION_CAUGHT = "APPCException caught";
+ /**
+ * Adaptor Name
+ */
+ private static final String Adaptor_NAME = "Saltstack Adaptor";
+ private static final String RESULT_CODE_ATTRIBUTE_NAME = "org.onap.appc.adaptor.saltstack.result.code";
+ private static final String MESSAGE_ATTRIBUTE_NAME = "org.onap.appc.adaptor.saltstack.message";
+ private static final String ID_ATTRIBUTE_NAME = "org.onap.appc.adaptor.saltstack.Id";
+ private static final String CLIENT_TYPE_PROPERTY_NAME = "org.onap.appc.adaptor.saltstack.clientType";
+ private static final String SS_SERVER_HOSTNAME = "org.onap.appc.adaptor.saltstack.host";
+ private static final String SS_SERVER_PORT = "org.onap.appc.adaptor.saltstack.port";
+ private static final String SS_SERVER_USERNAME = "org.onap.appc.adaptor.saltstack.userName";
+ private static final String SS_SERVER_PASSWD = "org.onap.appc.adaptor.saltstack.userPasswd";
+ private static final String SS_SERVER_SSH_KEY = "org.onap.appc.adaptor.saltstack.sshKey";
+
+ private static final String COMMAND_IN_JSON_OUT = " --out=json --static ";
+ private static final String COMMAND_CHANGE_DEFAULT_DIR = " cd /srv/salt/ ;";
+
+ /**
+ * The logger to be used
+ */
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(SaltstackAdaptorImpl.class);
+ /**
+ * Connection object
+ **/
+ private ConnectionBuilder sshClient;
+
+ /**
+ * Saltstack API Message Handlers
+ **/
+ private SaltstackMessageParser messageProcessor;
+
+ /**
+ * indicator whether in test mode
+ **/
+ private boolean testMode = false;
+
+ /**
+ * server emulator object to be used if in test mode
+ **/
+ private SaltstackServerEmulator testServer;
+
+ /**
+ * This default constructor is used as a work around because the activator wasn't getting called
+ */
+ public SaltstackAdaptorImpl() throws SvcLogicException {
+ initialize(new SaltstackAdaptorPropertiesProviderImpl());
+ }
+
+ public SaltstackAdaptorImpl(SaltstackAdaptorPropertiesProvider propProvider) throws SvcLogicException {
+ initialize(propProvider);
+ }
+
+ /**
+ * Used for jUnit test and testing interface
+ */
+ public SaltstackAdaptorImpl(boolean mode) {
+ testMode = mode;
+ testServer = new SaltstackServerEmulator();
+ messageProcessor = new SaltstackMessageParser();
+ }
+
+ /**
+ * Returns the symbolic name of the adaptor
+ *
+ * @return The adaptor name
+ * @see SaltstackAdaptor#getAdaptorName()
+ */
+ @Override
+ public String getAdaptorName() {
+ return Adaptor_NAME;
+ }
+
+ /**
+ * 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 {
+ logger.error(APPC_EXCEPTION_CAUGHT, message);
+ svcLogic.setStatus(OUTCOME_FAILURE);
+ svcLogic.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(code));
+ svcLogic.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
+ throw new SvcLogicException("Saltstack Adaptor Error = " + message);
+ }
+
+ /**
+ * initialize the Saltstack adaptor based on default and over-ride configuration data
+ */
+ private void initialize(SaltstackAdaptorPropertiesProvider propProvider) throws SvcLogicException {
+
+
+ Properties props = propProvider.getProperties();
+
+ // Create the message processor instance
+ messageProcessor = new SaltstackMessageParser();
+
+ // Create the ssh client instance
+ // type of client is extracted from the property file parameter
+ // org.onap.appc.adaptor.saltstack.clientType
+ // It can be :
+ // 1. BASIC. SSH Connection using username and password
+ // 2. SSH_CERT (trust only those whose certificates have been stored in the SSH KEY file)
+ // 3. DEFAULT SSH Connection without any authentication
+
+ try {
+ String clientType = props.getProperty(CLIENT_TYPE_PROPERTY_NAME);
+ logger.info("Saltstack ssh client type set to " + clientType);
+
+ if ("BASIC".equalsIgnoreCase(clientType)) {
+ logger.info("Creating ssh client connection");
+ // set path to keystore file
+ String sshHost = props.getProperty(SS_SERVER_HOSTNAME);
+ String sshPort = reqServerPort(props);
+ String sshUserName = props.getProperty(SS_SERVER_USERNAME);
+ String sshPassword = props.getProperty(SS_SERVER_PASSWD);
+ sshClient = new ConnectionBuilder(sshHost, sshPort, sshUserName, sshPassword);
+ } else if ("SSH_CERT".equalsIgnoreCase(clientType)) {
+ // set path to keystore file
+ String sshKey = props.getProperty(SS_SERVER_SSH_KEY);
+ String sshHost = props.getProperty(SS_SERVER_HOSTNAME);
+ String sshPort = reqServerPort(props);
+ logger.info("Creating ssh client with ssh KEY from " + sshKey);
+ sshClient = new ConnectionBuilder(sshHost, sshPort, sshKey);
+ } else {
+ logger.info("No saltstack-adaptor.properties defined so reading from DG props");
+ sshClient = null;
+ }
+ } catch (NumberFormatException e) {
+ logger.error("Error Initializing Saltstack Adaptor due to Unknown Exception", e);
+ throw new SvcLogicException("Saltstack Adaptor Property file parsing Error = port in property file has to be an integer.");
+ } catch (Exception e) {
+ logger.error("Error Initializing Saltstack Adaptor due to Exception", e);
+ throw new SvcLogicException("Saltstack Adaptor Property file parsing Error = " + e.getMessage());
+ }
+ logger.info("Initialized Saltstack Adaptor");
+ }
+
+ private String reqServerPort(Properties props) {
+ // use default port if null
+ if (props.getProperty(SS_SERVER_PORT) == null) {
+ return "22";
+ }
+ return props.getProperty(SS_SERVER_PORT);
+ }
+
+ private void setSSHClient(Map<String, String> params) throws SvcLogicException {
+ if (sshClient == null) {
+ logger.info("saltstack-adaptor.properties not defined so reading saltstack host and " +
+ "auth details from DG's parameters");
+ String sshHost = messageProcessor.reqHostNameResult(params);
+ String sshPort = messageProcessor.reqPortResult(params);
+ String sshUserName = messageProcessor.reqUserNameResult(params);
+ String sshPassword = messageProcessor.reqPasswordResult(params);
+ logger.info("Creating ssh client with BASIC Auth");
+ if (!testMode) {
+ sshClient = new ConnectionBuilder(sshHost, sshPort, sshUserName, sshPassword);
+ }
+ }
+ }
+
+ private String parseEnvParam(JSONObject envParams) {
+ StringBuilder envParamBuilder = new StringBuilder();
+ if (envParams != null) {
+ for (Object key : envParams.keySet()) {
+ if (envParamBuilder.length() > 0) {
+ envParamBuilder.append(", ");
+ }
+ envParamBuilder.append(key + "=" + envParams.get((String) key));
+ logger.info("EnvParameters : " + envParamBuilder);
+ }
+ }
+ return envParamBuilder.toString();
+ }
+
+ private String parseFileParam(JSONObject fileParams) {
+ StringBuilder fileParamBuilder = new StringBuilder();
+ if (fileParams != null) {
+ for (Object key : fileParams.keySet()) {
+ fileParamBuilder.append("echo -e \"" + fileParams.get((String) key) + "\" > /srv/salt/" + key).append("; ");
+ logger.info("FileParameters : " + fileParamBuilder);
+ }
+ }
+ return fileParamBuilder.toString();
+ }
+
+ private String putToCommands(SvcLogicContext ctx, String slsFileName,
+ String applyTo, JSONObject envParams, JSONObject fileParams) throws SvcLogicException {
+
+ StringBuilder constructedCommand = new StringBuilder();
+ try {
+ File file = new File(slsFileName);
+ String slsFile = file.getName();
+ if (!slsFile.substring(slsFile.lastIndexOf("."),
+ slsFile.length()).equalsIgnoreCase(".sls")) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(), "Input file " +
+ "is not of type .sls");
+ }
+ try(InputStream in = new FileInputStream(file)){
+ byte[] data = new byte[(int) file.length()];
+ in.read(data);
+ String str = new String(data, "UTF-8");
+ String slsWithoutExtn = stripExtension(slsFile);
+ constructedCommand.append(parseFileParam(fileParams)).append("echo -e \"").append(str).append("\" > /srv/salt/").
+ append(slsFile).append("; ").append(COMMAND_CHANGE_DEFAULT_DIR).append(" salt '").
+ append(applyTo).append("' state.apply ").append(slsWithoutExtn).append(" ").append(parseEnvParam(envParams)).append(COMMAND_IN_JSON_OUT);
+ }
+ logger.info("Command to be executed on server : " + constructedCommand.toString());
+
+ } 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());
+ } catch (StringIndexOutOfBoundsException e) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(), "Input file " +
+ "is not of type .sls");
+ }
+ return constructedCommand.toString();
+ }
+
+ private String stripExtension(String str) {
+ if (str == null) {
+ return null;
+ }
+ int pos = str.lastIndexOf(".");
+ if (pos == -1) {
+ return str;
+ }
+ return str.substring(0, pos);
+ }
+
+ private String putToCommands(String slsName, String applyTo, JSONObject envParams, JSONObject fileParams) {
+
+ StringBuilder constructedCommand = new StringBuilder();
+
+ constructedCommand.append(parseFileParam(fileParams)).append(COMMAND_CHANGE_DEFAULT_DIR).append(" salt '").append(applyTo)
+ .append("' state.apply ").append(slsName).append(" ").append(parseEnvParam(envParams)).append(COMMAND_IN_JSON_OUT);
+
+ logger.info("Command to be executed on server : " + constructedCommand.toString());
+ return constructedCommand.toString();
+ }
+
+ 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()) {
+ ctx.setAttribute(ID_ATTRIBUTE_NAME, reqID);
+ doFailure(ctx, testResult.getStatusCode(), "Request for execution of command failed. Reason = " + testResult.getStatusMessage());
+ } else {
+ logger.info(String.format("Execution of request : successful."));
+ ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(testResult.getStatusCode()));
+ ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, OUTCOME_SUCCESS);
+ 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.adaptor.saltstack.req.code : 100 if successful
+ // org.onap.appc.adaptor.saltstack.req.messge : any message
+ // org.onap.appc.adaptor.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);
+ try {
+ reqID = messageProcessor.reqId(params);
+ String commandToExecute = messageProcessor.reqCmd(params);
+ slsExec = messageProcessor.reqIsSLSExec(params);
+ long execTimeout = messageProcessor.reqExecTimeout(params);
+ testResult = execCommand(ctx, params, commandToExecute, execTimeout);
+ testResult = messageProcessor.parseResponse(ctx, reqID, testResult, slsExec);
+ checkResponseStatus(testResult, ctx, reqID, slsExec);
+ } catch (IOException e) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(),
+ "IOException in file stream : " + e.getMessage());
+ }
+ }
+
+ /**
+ * Public Method to post SLS command request to execute saltState on server. Posts the following back
+ * to Svc context memory
+ * <p>
+ * org.onap.appc.adaptor.saltstack.req.code : 200 if successful
+ * org.onap.appc.adaptor.saltstack.req.messge : any message
+ * org.onap.appc.adaptor.saltstack.req.Id : a unique uuid to reference the request
+ */
+ @Override
+ public void reqExecSLS(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ String reqID;
+ SaltstackResult testResult;
+ setSSHClient(params);
+ try {
+ reqID = messageProcessor.reqId(params);
+ String slsName = messageProcessor.reqSlsName(params);
+ String applyTo = messageProcessor.reqApplyToDevices(params);
+ long execTimeout = messageProcessor.reqExecTimeout(params);
+ JSONObject envParams = messageProcessor.reqEnvParameters(params);
+ JSONObject fileParams = messageProcessor.reqFileParameters(params);
+
+ String commandToExecute = putToCommands(slsName, applyTo, envParams, fileParams);
+ testResult = execCommand(ctx, params, commandToExecute, execTimeout);
+ testResult = messageProcessor.parseResponse(ctx, reqID, testResult, true);
+ checkResponseStatus(testResult, ctx, reqID, true);
+ } catch (IOException e) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(),
+ "IOException in file stream : " + e.getMessage());
+ } catch (JSONException e) {
+ doFailure(ctx, SaltstackResultCodes.INVALID_COMMAND.getValue(), e.getMessage());
+ }
+ }
+
+ /**
+ * Public Method to post SLS file request to execute saltState. Posts the following back
+ * to Svc context memory
+ * <p>
+ * org.onap.appc.adaptor.saltstack.req.code : 100 if successful
+ * org.onap.appc.adaptor.saltstack.req.messge : any message
+ * org.onap.appc.adaptor.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);
+ try {
+ reqID = messageProcessor.reqId(params);
+ String slsFile = messageProcessor.reqSlsFile(params);
+ String applyTo = messageProcessor.reqApplyToDevices(params);
+ long execTimeout = messageProcessor.reqExecTimeout(params);
+ JSONObject envParams = messageProcessor.reqEnvParameters(params);
+ JSONObject fileParams = messageProcessor.reqFileParameters(params);
+
+ String commandToExecute = putToCommands(ctx, slsFile, applyTo, envParams, fileParams);
+ testResult = execCommand(ctx, params, commandToExecute, execTimeout);
+ testResult = messageProcessor.parseResponse(ctx, reqID, testResult, true);
+ checkResponseStatus(testResult, ctx, reqID, true);
+ } catch (IOException e) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(),
+ "IOException in file stream : " + e.getMessage());
+ }
+ }
+
+ public SaltstackResult execCommand(SvcLogicContext ctx, Map<String, String> params, String commandToExecute,
+ long execTimeout)
+ throws SvcLogicException {
+
+ //convert execTimeout to Milliseconds
+ execTimeout = execTimeout * 1000;
+ SaltstackResult testResult = new SaltstackResult();
+ try {
+ if (params.get(CONNECTION_RETRY) == null) {
+ if (!testMode) {
+ testResult = sshClient.connectNExecute(commandToExecute, execTimeout);
+ } else {
+ testResult = testServer.mockReqExec(params);
+ }
+ } else if (params.get(CONNECTION_RETRY).equalsIgnoreCase("true")) {
+ if (!testMode) {
+ testResult = sshClient.connectNExecute(commandToExecute, true, execTimeout);
+ } else {
+ testResult = testServer.mockReqExec(params);
+ }
+ } else {
+ if (!testMode) {
+ testResult = sshClient.connectNExecute(commandToExecute, execTimeout);
+ } else {
+ testResult = testServer.mockReqExec(params);
+ }
+ }
+ } catch (IOException e) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(),
+ "IOException in file stream : " + e.getMessage());
+ }
+ return testResult;
+ }
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdaptorPropertiesProviderImpl.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdaptorPropertiesProviderImpl.java
new file mode 100644
index 000000000..c5e4044fb
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdaptorPropertiesProviderImpl.java
@@ -0,0 +1,192 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.sli.adaptors.saltstack.impl;
+
+import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdaptorPropertiesProvider;
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.utils.JREFileResolver;
+import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver;
+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>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>sql-resource.properties</code></li>
+ * <li>A <code>sql-resource.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+public class SaltstackAdaptorPropertiesProviderImpl implements SaltstackAdaptorPropertiesProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SaltstackAdaptorPropertiesProviderImpl.class);
+
+ /**
+ * The name of the properties file for database configuration
+ */
+ private static final String SALTSTACKAdaptor_PROP_FILE_NAME = "saltstack-adaptor.properties";
+
+ /**
+ * A prioritized list of strategies for resolving sql-resource properties files.
+ */
+ private Vector<PropertiesFileResolver> saltstackAdaptorPropertiesFileResolvers = new Vector<>();
+
+ /**
+ * The configuration properties for the db connection.
+ */
+ private Properties properties;
+
+ /**
+ * Set up the prioritized list of strategies for resolving dblib properties
+ * files.
+ */
+ public SaltstackAdaptorPropertiesProviderImpl() {
+ saltstackAdaptorPropertiesFileResolvers
+ .add(new SdncConfigEnvVarFileResolver("Using property file (1) from environment variable"));
+ saltstackAdaptorPropertiesFileResolvers.add(new CoreDefaultFileResolver("Using property file (2) from default directory"));
+
+ saltstackAdaptorPropertiesFileResolvers.add(
+ new JREFileResolver("Using property file (3) from JRE argument", SaltstackAdaptorPropertiesProviderImpl.class));
+ saltstackAdaptorPropertiesFileResolvers.add(new KarafRootFileResolver("Using property file (4) from karaf root", this));
+
+ // determines properties file as according to the priority described in the
+ // class header comment
+ final File propertiesFile = determinePropertiesFile(this);
+ if (propertiesFile != null) {
+ try (FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
+ properties = new Properties();
+ 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));
+ }
+ } else {
+ // Try to read properties as resource
+
+ InputStream propStr = getClass().getResourceAsStream("/" + SALTSTACKAdaptor_PROP_FILE_NAME);
+ if (propStr != null) {
+ properties = new Properties();
+ try {
+ properties.load(propStr);
+ propStr.close();
+ } catch (IOException e) {
+ properties = null;
+ }
+ }
+
+ }
+
+ if (properties == null) {
+ reportFailure("Missing configuration properties resource(3)", new ConfigurationException(
+ "Missing configuration properties resource(3): " + SALTSTACKAdaptor_PROP_FILE_NAME));
+
+ LOG.info("Defaulting org.onap.appc.adaptor.saltstack.clientType to NONE");
+
+ properties = new Properties();
+ properties.setProperty("org.onap.appc.adaptor.saltstack.clientType", "NONE");
+ }
+ }
+
+ /**
+ * 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
+ * @return the file location of the chosen properties file
+ */
+ private static File reportSuccess(final String message, final Optional<File> fileOptional) {
+ if (fileOptional.isPresent()) {
+ final File file = fileOptional.get();
+ LOG.info("{} {}", message, file.getPath());
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * 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
+ */
+ 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>
+ * <li>A directory identified by the system environment variable
+ * <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>sql-resource.properties</code></li>
+ * <li>A <code>sql-resource.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+ File determinePropertiesFile(final SaltstackAdaptorPropertiesProviderImpl resourceProvider) {
+
+ for (final PropertiesFileResolver sliPropertiesFileResolver : saltstackAdaptorPropertiesFileResolvers) {
+ final Optional<File> fileOptional = sliPropertiesFileResolver.resolveFile(SALTSTACKAdaptor_PROP_FILE_NAME);
+ if (fileOptional.isPresent()) {
+ return reportSuccess(sliPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java
new file mode 100644
index 000000000..25d2d8402
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java
@@ -0,0 +1,217 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.sli.adaptors.saltstack.impl;
+
+import java.io.OutputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.KeyPair;
+import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.channel.ChannelExec;
+import org.apache.sshd.client.future.AuthFuture;
+import org.apache.sshd.client.future.OpenFuture;
+import org.apache.sshd.client.session.ClientSession;
+import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.Constants;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SshException;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+/**
+ * Implementation of SshConnection interface based on Apache MINA SSHD library.
+ */
+class SshConnection {
+
+ 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;
+ private String password;
+ private long timeout = EXEC_TIMEOUT;
+ private String keyFile;
+ private SshClient sshClient;
+ private ClientSession clientSession;
+
+ public SshConnection(String host, int port, String username, String password, String keyFile) {
+ this.host = host;
+ this.port = port;
+ this.username = username;
+ this.password = password;
+ this.keyFile = keyFile;
+ }
+
+ public SshConnection(String host, int port, String username, String password) {
+ this(host, port, username, password, null);
+ }
+
+ public SshConnection(String host, int port, String keyFile) {
+ this(host, port, null, null, keyFile);
+ }
+
+ public void connect() {
+ sshClient = SshClient.setUpDefaultClient();
+ sshClient.start();
+ try {
+ clientSession =
+ sshClient.connect(username, host, port).getSession();
+ if (password != null) {
+ clientSession.addPasswordIdentity(password);
+ } else if (keyFile != null) {
+ Path keyFilePath = Paths.get(keyFile);
+ KeyPairProvider keyPairProvider = new FileKeyPairProvider(keyFilePath);
+ KeyPair keyPair = keyPairProvider.loadKeys().iterator().next();
+ clientSession.addPublicKeyIdentity(keyPair);
+ }
+ AuthFuture authFuture = clientSession.auth();
+ authFuture.await(AUTH_TIMEOUT);
+ if (!authFuture.isSuccess()) {
+ throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port
+ + "]. Authentication failed.");
+ }
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + "].",
+ e);
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("SSH: connected to [" + toString() + "]");
+ }
+ }
+
+ public void connectWithRetry() {
+ int retryCount;
+ int retryDelay;
+ int retriesLeft;
+ retryCount = Constants.DEFAULT_CONNECTION_RETRY_COUNT;
+ retryDelay = Constants.DEFAULT_CONNECTION_RETRY_DELAY;
+ retriesLeft = retryCount + 1;
+ do {
+ try {
+ this.connect();
+ break;
+ } catch (RuntimeException e) {
+ if (retriesLeft > 1) {
+ logger.debug("SSH Connection failed. Waiting for change in server's state.");
+ waitForConnection(retryDelay);
+ retriesLeft--;
+ logger.debug("Retrying SSH connection. Attempt [" + Integer.toString(retryCount - retriesLeft + 1)
+ + "] out of [" + retryCount + "]");
+ } else {
+ throw e;
+ }
+ }
+ } while (retriesLeft > 0);
+ }
+
+ public void disconnect() {
+ try {
+ if (logger.isDebugEnabled()) {
+ logger.debug("SSH: disconnecting from [" + toString() + "]");
+ }
+ clientSession.close(false);
+ } finally {
+ if (sshClient != null) {
+ sshClient.stop();
+ }
+ }
+ }
+
+ public void setExecTimeout(long timeout) {
+ this.timeout = timeout;
+ }
+
+ public int execCommand(String cmd, OutputStream out, OutputStream err) {
+ return execCommand(cmd, out, err, false);
+ }
+
+ public int execCommandWithPty(String cmd, OutputStream out) {
+ return execCommand(cmd, out, out, true);
+ }
+
+ private int execCommand(String cmd, OutputStream out, OutputStream err, boolean usePty) {
+ try {
+ if (logger.isDebugEnabled()) {
+ logger.debug("SSH: executing command");
+ }
+ ChannelExec client = clientSession.createExecChannel(cmd);
+ client.setUsePty(usePty); // use pseudo-tty?
+ client.setOut(out);
+ client.setErr(err);
+ OpenFuture openFuture = client.open();
+ int exitStatus;
+ try {
+ client.wait(timeout);
+ openFuture.verify();
+ Integer exitStatusI = client.getExitStatus();
+ if (exitStatusI == null) {
+ throw new SshException("Error executing command [" + cmd + "] over SSH [" + username + "@" + host
+ + ":" + port + "]. Operation timed out.");
+ }
+ exitStatus = exitStatusI;
+ } finally {
+ client.close(false);
+ }
+ return exitStatus;
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e1) {
+ throw new SshException(
+ "Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" + port + "]", e1);
+ }
+ }
+
+ private void waitForConnection(int retryDelay) {
+ long time = retryDelay * 1000L;
+ long future = System.currentTimeMillis() + time;
+ if (time != 0) {
+ while (System.currentTimeMillis() < future && time > 0) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException e) {
+ /*
+ * This is rare, but it can happen if another thread interrupts us while we are sleeping. In that
+ * case, the thread is resumed before the delay time has actually expired, so re-calculate the
+ * amount of delay time needed and reenter the sleep until we get to the future time.
+ */
+ time = future - System.currentTimeMillis();
+ }
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ String address = host;
+ if (username != null) {
+ address = username + '@' + address + ':' + port;
+ }
+ return address;
+ }
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/Constants.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/Constants.java
new file mode 100644
index 000000000..a1826c4e1
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/Constants.java
@@ -0,0 +1,93 @@
+/*-
+ * ============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.ccsdk.sli.adaptors.saltstack.model;
+
+public class Constants {
+ public static final String NETCONF_SCHEMA = "sdnctl";
+ public static final String SDNCTL_SCHEMA = "sdnctl";
+ public static final String DEVICE_AUTHENTICATION_TABLE_NAME = "DEVICE_AUTHENTICATION";
+ public static final String CONFIGFILES_TABLE_NAME = "CONFIGFILES";
+ public static final String DEVICE_INTERFACE_LOG_TABLE_NAME = "DEVICE_INTERFACE_LOG";
+ public static final String FILE_CONTENT_TABLE_FIELD_NAME = "FILE_CONTENT";
+ public static final String FILE_NAME_TABLE_FIELD_NAME = "FILE_NAME";
+ public static final String USER_NAME_TABLE_FIELD_NAME = "USER_NAME";
+ public static final String PASSWORD_TABLE_FIELD_NAME = "PASSWORD";
+ public static final String PORT_NUMBER_TABLE_FIELD_NAME = "PORT_NUMBER";
+ public static final String VNF_TYPE_TABLE_FIELD_NAME = "VNF_TYPE";
+ public static final String SERVICE_INSTANCE_ID_FIELD_NAME = "SERVICE_INSTANCE_ID";
+ public static final String REQUEST_ID_FIELD_NAME = "REQUEST_ID";
+ public static final String CREATION_DATE_FIELD_NAME = "CREATION_DATE";
+ public static final String LOG_FIELD_NAME = "LOG";
+ public static final String SDC_ARTIFACTS_TABLE_NAME = "ASDC_ARTIFACTS";
+ public static final String PAYLOAD = "payload";
+ public static final String CONNECTION_RETRY_DELAY = "org.onap.appc.ssh.connection.retry.delay";
+ public static final String CONNECTION_RETRY_COUNT = "org.onap.appc.ssh.connection.retry.count";
+ public static final int DEFAULT_CONNECTION_RETRY_DELAY = 60;
+ public static final int DEFAULT_CONNECTION_RETRY_COUNT = 5;
+ public static final int DEFAULT_SSH_COMMAND_RETRY_COUNT = 3;
+ public static final int DEFAULT_CHECKACTIVE_RETRY_COUNT = 3;
+ public static final int DEFAULT_CHECKACTIVE_RETRY_DELAY = 30;
+ public static final int DEFAULT_STOP_RETRY_COUNT = 3;
+ public static final int DEFAULT_STOP_RETRY_DELAY = 30;
+ public static final String PARAM_IN_CONNECTION_DETAILS = "connection-details";
+ public static final String PARAM_IN_NODE_NAME = "node-name";
+ public static final String PARAM_IN_NODE_STATUS = "node-status";
+ public static final String PARAM_IN_VM_URL = "vm-url";
+ public static final String SKIP_EXECUTION_INSTALLER_BIN_FILE = "Skip-execution-installer-bin-file";
+ public static final String SKIP_DEPLOY = "Skip-deploy";
+ public static final String UPGRADE_VERSION = "upgrade-version";
+ public static final String STATE_COMMAND = "/opt/jnetx/skyfall-scp/asp-state.sh | grep -o UP | wc -l";
+ public static final String VNFC_STATE_COMMAND = "/opt/jnetx/skyfall-scp/asp-state.sh";
+ public static final String RESTART_NODE_COMMAND = "/opt/jnetx/skyfall-scp/asp-stop.sh --restart -f --nodes";
+ public static final String START_NODE_COMMAND = "/opt/jnetx/skyfall-scp/asp-start.sh -f --nodes";
+ public static final String STOP_NODE_COMMAND = "/opt/jnetx/skyfall-scp/asp-stop.sh -f --nodes";
+ public static final int STATE_COMMAND_RESULT = 18;
+ public static final String FE_STATE_TRUE_TEST_COMMAND = "ssh -t -q fe1 /opt/omni/bin/swmml -e display-platform-status | grep -o TRUE | wc -l";
+ public static final int FE_STATE_TRUE_TEST_RESULT = 22;
+ public static final String FE_STATE_FALSE_TEST_COMMAND = "ssh -t -q fe1 /opt/omni/bin/swmml -e display-platform-status | grep -o FALSE | wc -l";
+ public static final int FE_STATE_FALSE_TEST_RESULT = 2;
+ public static final String FE_OPERATIONAL_TEST_COMMAND = "ssh -t -q fe1 /opt/omni/bin/swmml -e display-platform-status | grep -o 'NOT FULLY OPERATIONAL' | wc -l";
+ public static final int FE_OPERATIONAL_TEST_RESULT = 2;
+ public static final String SMP_CHECK_ACTIVE_STATE_COMMAND = "cat skyfall-scp/runtime/SCP_SMP_*/smp/log/system.log| grep SSS | tail -1";
+ public static final String SMP_STATE_ACTIVE = "SMP is active";
+ public static final String SMP_STATE_INACTIVE = "SMP is not active";
+ public static final String RSYNC_COMMAND = "yes n | /opt/jnetx/skyfall-scp/asp-rsync.sh --check | grep -o 'is active' | wc -l";
+ public static final int RSYNC_COMMAND_RESULT = 9;
+ public static final String PARAM_IN_TIMEOUT = "timeout";
+ public static final String PARAM_IN_FILE_URL = "source-file-url";
+ public static final String DOWNLOAD_COMMAND = "wget -N %s";
+ public static final String[] VM_NAMES = new String[]{"fe1", "fe2", "be1", "be2", "be3", "be4", "be5", "smp1", "smp2"};
+ public static final String DEFAULT_DISK_SPACE = "10240000";
+ public static final String DF_COMMAND_TEMPLATE = "ssh %s df | grep vda1 | grep -v grep | tr -s ' '|cut -d ' ' -f4";
+ public static final String DG_OUTPUT_STATUS_MESSAGE = "output.status.message";
+ public static final String ATTRIBUTE_ERROR_MESSAGE = "error-message";
+ public static final String CONNECTION_DETAILS_FIELD_NAME = "connection-details";
+ public static final String VNF_HOST_IP_ADDRESS_FIELD_NAME = "vnf-host-ip-address";
+ public static final String VNF_HOST_IP2_ADDRESS_FIELD_NAME = "vnf-host-ip2-address";
+ public static final String DG_ERROR_FIELD_NAME = "org.openecom.appc.dg.error";
+
+ private Constants() {
+ }
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java
new file mode 100644
index 000000000..3eb353a17
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.sli.adaptors.saltstack.model;
+
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public final class JsonParser {
+
+ private static final Logger log = LoggerFactory.getLogger(JsonParser.class);
+
+ private JsonParser() {
+ // Preventing instantiation of the same.
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Map<String, String> convertToProperties(String s)
+ 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()));
+
+ 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));
+ }
+ }
+ return mm;
+ }
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java
new file mode 100644
index 000000000..03b3eebf9
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java
@@ -0,0 +1,412 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017-2018 Samsung Electronics. 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.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.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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Class that validates and constructs requests sent/received from
+ * Saltstack Server
+ */
+public class SaltstackMessageParser {
+
+ private static final String SS_AGENT_HOSTNAME_KEY = "HostName";
+ 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"; //cmd
+ private static final String IS_SLS_EXEC = "SlsExec"; //slsExec
+ private static final String SS_REQ_ID = "Id";
+ private static final String SLS_FILE_LOCATION = "SlsFile"; //slsFile
+ private static final String SLS_NAME = "SlsName"; //slsName
+ private static final String MINION_TO_APPLY = "NodeList"; //applyTo
+ private static final String EXEC_TIMEOUT_TO_APPLY = "Timeout"; //execTimeout
+ private static final String FILE_PARAMETERS_OPT_KEY = "FileParameters";
+ private static final String ENV_PARAMETERS_OPT_KEY = "EnvParameters";
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SaltstackMessageParser.class);
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate PORT number.
+ */
+ public String reqPortResult(Map<String, String> params) throws SvcLogicException {
+ // use default port if null
+ if (params.get(SS_AGENT_PORT_KEY) == null) {
+ return "22";
+ }
+ return params.get(SS_AGENT_PORT_KEY);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate HOST name.
+ */
+ public String reqHostNameResult(Map<String, String> params) throws SvcLogicException {
+
+ throwIfMissingMandatoryParam(params, SS_AGENT_HOSTNAME_KEY);
+ 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 {
+
+ throwIfMissingMandatoryParam(params, CMD_EXEC);
+ 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 {
+
+ throwIfMissingMandatoryParam(params, SLS_FILE_LOCATION);
+ 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 {
+
+ throwIfMissingMandatoryParam(params, SLS_NAME);
+ String slsName = params.get(SaltstackMessageParser.SLS_NAME);
+ try {
+ if (slsName.substring(slsName.lastIndexOf("."), slsName.length()).equalsIgnoreCase(".sls")) {
+ return stripExtension(slsName);
+ }
+ } catch (StringIndexOutOfBoundsException e) {
+ return 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.
+ */
+ 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 minions/vnfc to execute the SLS file.
+ */
+ public long reqExecTimeout(Map<String, String> params) {
+
+ if (params.get(SaltstackMessageParser.EXEC_TIMEOUT_TO_APPLY) == null) {
+ return -1;
+ } else if (params.get(SaltstackMessageParser.EXEC_TIMEOUT_TO_APPLY).equalsIgnoreCase("")) {
+ return -1;
+ }
+ return Long.parseLong(params.get(SaltstackMessageParser.EXEC_TIMEOUT_TO_APPLY));
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate EnvParameters to execute the SLS file.
+ */
+ public JSONObject reqEnvParameters(Map<String, String> params) throws JSONException {
+
+ JSONObject jsonPayload = new JSONObject();
+ final String[] optionalTestParam = {SaltstackMessageParser.ENV_PARAMETERS_OPT_KEY};
+ parseParam(params, optionalTestParam, jsonPayload);
+
+ return (JSONObject) jsonPayload.remove(SaltstackMessageParser.ENV_PARAMETERS_OPT_KEY);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate EnvParameters to execute the SLS file.
+ */
+ public JSONObject reqFileParameters(Map<String, String> params) throws JSONException {
+
+ JSONObject jsonPayload = new JSONObject();
+ final String[] optionalTestParam = {SaltstackMessageParser.FILE_PARAMETERS_OPT_KEY};
+ parseParam(params, optionalTestParam, jsonPayload);
+
+ return (JSONObject) jsonPayload.remove(SaltstackMessageParser.FILE_PARAMETERS_OPT_KEY);
+ }
+
+ private void parseParam(Map<String, String> params, String[] optionalTestParams, JSONObject jsonPayload)
+ throws JSONException {
+
+ Set<String> optionalParamsSet = new HashSet<>();
+ Collections.addAll(optionalParamsSet, optionalTestParams);
+
+ //@formatter:off
+ params.entrySet()
+ .stream()
+ .filter(entry -> optionalParamsSet.contains(entry.getKey()))
+ .filter(entry -> !Strings.isNullOrEmpty(entry.getValue()))
+ .forEach(entry -> parseParam(entry, jsonPayload));
+ //@formatter:on
+ }
+
+ private void parseParam(Map.Entry<String, String> params, JSONObject jsonPayload)
+ throws JSONException {
+ String key = params.getKey();
+ String payload = params.getValue();
+
+ switch (key) {
+ case ENV_PARAMETERS_OPT_KEY:
+ JSONObject paramsJson = new JSONObject(payload);
+ jsonPayload.put(key, paramsJson);
+ break;
+
+ case FILE_PARAMETERS_OPT_KEY:
+ jsonPayload.put(key, getFilePayload(payload));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Return payload with escaped newlines
+ */
+ private JSONObject getFilePayload(String payload) {
+ String formattedPayload = payload.replace("\n", "\\n").replace("\r", "\\r");
+ return new JSONObject(formattedPayload);
+ }
+
+ /**
+ * 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
+ * the appropriate Saltstack server login user name.
+ */
+ public String reqUserNameResult(Map<String, String> params) throws SvcLogicException {
+
+ throwIfMissingMandatoryParam(params, USER_KEY);
+ return params.get(USER_KEY);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate Saltstack server login password.
+ */
+ public String reqPasswordResult(Map<String, String> params) throws SvcLogicException {
+
+ throwIfMissingMandatoryParam(params, PASS_KEY);
+ return params.get(PASS_KEY);
+ }
+
+ /**
+ * 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, boolean slsExec) throws IOException {
+ int code = saltstackResult.getStatusCode();
+ boolean executionStatus = true;
+ boolean retCodeFound = false;
+ if (code != SaltstackResultCodes.SUCCESS.getValue()) {
+ return saltstackResult;
+ }
+ ByteArrayOutputStream outStream = saltstackResult.getOutputMessage();
+ String outMessage = outStream.toString();
+ try {
+ Map<String, String> mm = JsonParser.convertToProperties(outMessage);
+ if (mm != null) {
+ 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 (org.codehaus.jettison.json.JSONException e) {
+ if (slsExec) {
+ return new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE.getValue(), "error parsing response file"
+ + " : Output has to be in JSON format");
+ }
+ 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"
+ + " : " + e.getMessage());
+ } finally {
+ if (outStream != null) {
+ outStream.close();
+ }
+ }
+ if (slsExec) {
+ if (!retCodeFound) {
+ if (outMessage != null && !outMessage.equalsIgnoreCase("")) {
+ return new SaltstackResult(SaltstackResultCodes.COMMAND_EXEC_FAILED_STATUS.getValue(),
+ outMessage);
+ }
+ return new SaltstackResult(SaltstackResultCodes.COMMAND_EXEC_FAILED_STATUS.getValue(),
+ "error in executing configuration at the server, check your command input");
+ }
+ if (!executionStatus) {
+ if (outMessage != null && !outMessage.equalsIgnoreCase("")) {
+ return new SaltstackResult(SaltstackResultCodes.COMMAND_EXEC_FAILED_STATUS.getValue(),
+ outMessage);
+ }
+ return new SaltstackResult(SaltstackResultCodes.COMMAND_EXEC_FAILED_STATUS.getValue(),
+ "error in executing configuration at the server, check your command input");
+ }
+ }
+ saltstackResult.setStatusCode(SaltstackResultCodes.FINAL_SUCCESS.getValue());
+ return saltstackResult;
+ }
+
+ public SaltstackResult putToProperties(SvcLogicContext ctx, String pfx,
+ SaltstackResult saltstackResult) throws IOException {
+
+ ByteArrayOutputStream buffer = saltstackResult.getOutputMessage();
+ InputStream inputStream = null;
+ try {
+ byte[] bytes = buffer.toByteArray();
+ Properties prop = new Properties();
+ inputStream = new ByteArrayInputStream(bytes);
+ prop.load(inputStream);
+ ctx.setAttribute(pfx + "completeResult", prop.toString());
+ for (Object key : prop.keySet()) {
+ String name = (String) key;
+ String value = prop.getProperty(name);
+ if (value != null && value.trim().length() > 0) {
+ ctx.setAttribute(pfx + "." + name, value.trim());
+ LOGGER.info("+++ " + pfx + "." + name + ": [" + value + "]");
+ }
+ }
+ } catch (Exception e) {
+ saltstackResult = new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "Error parsing response file." +
+ " Error = " + e.getMessage());
+ } finally {
+ if (buffer != null && inputStream != null) {
+ buffer.close();
+ inputStream.close();
+ }
+ }
+ saltstackResult.setStatusCode(SaltstackResultCodes.FINAL_SUCCESS.getValue());
+ return saltstackResult;
+ }
+
+ private void throwIfMissingMandatoryParam(Map<String, String> params, String key) throws SvcLogicException {
+ if (!params.containsKey(key)) {
+ throw new SvcLogicException(String.format(
+ "Saltstack: Mandatory SaltstackAdaptor key %s not found in parameters provided by calling agent !",
+ key));
+ }
+ if (Strings.isNullOrEmpty(params.get(key))) {
+ throw new SvcLogicException(String.format(
+ "Saltstack: Mandatory SaltstackAdaptor key %s not found in parameters provided by calling agent !",
+ key));
+ }
+ }
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java
new file mode 100644
index 000000000..727cfe314
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java
@@ -0,0 +1,102 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.sli.adaptors.saltstack.model;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Simple class to store code and message returned by POST/GET to an Saltstack Server
+ */
+public class SaltstackResult {
+
+ private static final String EMPTY_VALUE = "UNKNOWN";
+
+ private int statusCode;
+ private String statusMessage;
+ private String results;
+ private ByteArrayOutputStream out;
+ private int sshExitStatus;
+
+ public SaltstackResult() {
+ this(-1, EMPTY_VALUE, EMPTY_VALUE, -1);
+ }
+
+ public SaltstackResult(int code, String message) {
+ this(code, message, EMPTY_VALUE, -1);
+ }
+
+ public SaltstackResult(int code, String message, String result, int sshCode) {
+ statusCode = code;
+ statusMessage = message;
+ results = result;
+ sshExitStatus = sshCode;
+ }
+
+ void set(int code, String message, String results) {
+ this.statusCode = code;
+ this.statusMessage = message;
+ this.results = results;
+ }
+
+ public ByteArrayOutputStream getOutputMessage() {
+ return out;
+ }
+
+ public void setOutputMessage(ByteArrayOutputStream 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;
+ }
+
+ public void setSshExitStatus(int sshExitStatus) {
+ this.sshExitStatus = sshExitStatus;
+ }
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java
new file mode 100644
index 000000000..932554983
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java
@@ -0,0 +1,100 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.sli.adaptors.saltstack.model;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * enum of the various codes that APP-C uses to resolve different
+ * status of response from Saltstack Server
+ **/
+
+public enum SaltstackResultCodes {
+
+ // @formatter:off
+ SUCCESS(400),
+ KEYSTORE_EXCEPTION(622),
+ CERTIFICATE_ERROR(610),
+ IO_EXCEPTION(611),
+ HOST_UNKNOWN(625),
+ USER_UNAUTHORIZED(613),
+ UNKNOWN_EXCEPTION(699),
+ OPERATION_TIMEOUT(659),
+ SSL_EXCEPTION(697),
+ SSH_EXCEPTION(695),
+ INVALID_COMMAND(698),
+ INVALID_RESPONSE(601),
+ INVALID_RESPONSE_FILE(600),
+ 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),
+ INITRESPONSE(0),
+ FINALRESPONSE(1);
+ // @formatter:on
+
+ private final Set<Integer> initCodes = new HashSet<>(Arrays.asList(100, 101));
+ private final Set<Integer> finalCodes = new HashSet<>(Arrays.asList(200, 500));
+ private final ArrayList<Set<Integer>> codeSets = new ArrayList<>(Arrays.asList(initCodes, finalCodes));
+ private final Set<String> messageSet = new HashSet<>(Arrays.asList("PENDING", "FINISHED", "TERMINATED"));
+ private final int value;
+
+ SaltstackResultCodes(int value) {
+ this.value = value;
+ }
+
+ ;
+
+ public int getValue() {
+ return value;
+ }
+
+ public boolean checkValidCode(int type, int code) {
+ return codeSets.get(type).contains(code);
+ }
+
+ public String getValidCodes(int type) {
+ StringBuilder sb = new StringBuilder("[ ");
+ codeSets.get(type).stream().forEach(s -> sb.append(s).append(","));
+ return sb.append("]").toString();
+ }
+
+ public boolean checkValidMessage(String message) {
+ return messageSet.contains(message);
+ }
+
+ public String getValidMessages() {
+ StringBuilder sb = new StringBuilder("[ ");
+ messageSet.stream().forEach(s -> sb.append(s).append(","));
+ return sb.append("]").toString();
+ }
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java
new file mode 100644
index 000000000..78976562b
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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=========================================================
+ */
+
+
+
+/*
+ * Class to emulate responses from the Saltstack Server that is compliant with the APP-C Saltstack Server
+ * Interface. Used for jUnit tests to verify code is working. In tests it can be used
+ * as a replacement for methods from ConnectionBuilder class
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.model;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Map;
+
+public class SaltstackServerEmulator {
+
+ private static final String SALTSTATE_FILE_NAME = "fileName";
+ private final EELFLogger logger = EELFManager.getInstance().getLogger(SaltstackServerEmulator.class);
+
+ /**
+ * 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
+ **/
+ public SaltstackResult mockReqExec(Map<String, String> params) {
+ SaltstackResult result = new SaltstackResult();
+
+ try {
+ if (params.get("Test") == "fail") {
+ result = rejectRequest(result, "Mocked: Fail");
+ } else {
+ String fileName = params.get(SALTSTATE_FILE_NAME);
+ if (fileName == null) {
+ throw new FileNotFoundException("No response file found");
+ }
+ result = acceptRequest(result, fileName);
+ }
+ } catch (Exception e) {
+ logger.error("Exception caught", e);
+ rejectRequest(result, e.getMessage());
+ }
+ return result;
+ }
+
+ private SaltstackResult rejectRequest(SaltstackResult result, String Message) {
+ result.setStatusCode(SaltstackResultCodes.REJECTED.getValue());
+ result.setStatusMessage("Rejected");
+ return result;
+ }
+
+ private SaltstackResult acceptRequest(SaltstackResult result, String fileName) throws IOException {
+ result.setStatusCode(SaltstackResultCodes.SUCCESS.getValue());
+ result.setStatusMessage("Success");
+ Path path = Paths.get(fileName);
+ byte[] data = Files.readAllBytes(path);
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream(data.length);
+ byteOut.write(data, 0, data.length);
+ result.setOutputMessage(byteOut);
+ return result;
+ }
+} \ No newline at end of file
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SshException.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SshException.java
new file mode 100644
index 000000000..037a1e891
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SshException.java
@@ -0,0 +1,37 @@
+/*-
+ * ============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.ccsdk.sli.adaptors.saltstack.model;
+
+public class SshException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public SshException(String message) {
+ super(message);
+ }
+
+ public SshException(String message, Throwable cause) {
+ super(message, cause);
+ }
+} \ No newline at end of file
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/resources/org/opendaylight/blueprint/saltstack-adaptor-blueprint.xml b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/resources/org/opendaylight/blueprint/saltstack-adaptor-blueprint.xml
new file mode 100644
index 000000000..b614d29bf
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/resources/org/opendaylight/blueprint/saltstack-adaptor-blueprint.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 - 2018 Samsung Electronics. 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=========================================================
+ -->
+
+<blueprint xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propProvider"
+ class="org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdaptorPropertiesProviderImpl"/>
+
+ <bean id="saltstackAdaptorInstance"
+ class="org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdaptorImpl">
+ <argument ref="propProvider"/>
+ </bean>
+
+ <service ref="saltstackAdaptorInstance">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdaptor
+ </value>
+ </interfaces>
+ </service>
+
+</blueprint>
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/resources/saltstack-adaptor.properties b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/resources/saltstack-adaptor.properties
new file mode 100644
index 000000000..b37a593fb
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/main/resources/saltstack-adaptor.properties
@@ -0,0 +1,43 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2018 Samsung Electronics. 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=========================================================
+###
+#
+# Default properties for the APP-C TestService Adaptor
+#
+# -------------------------------------------------------------------------------------------------
+#
+# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded
+# to supply configuration options
+org.onap.appc.bootstrap.file=appc.properties
+org.onap.appc.bootstrap.path=${user.home},/opt/opendaylight/current/properties
+appc.application.name=APPC
+#
+# Define the message resource bundle name to be loaded
+org.onap.appc.resources=org.onap/appc/i18n/MessageResources
+#
+# The name of the adaptor.
+org.onap.appc.provider.adaptor.name=org.onap.appc.appc_saltstack_adaptor
+# Default truststore path and password
+org.onap.appc.adaptor.saltstack.trustStore=/opt/opendaylight/tls-client/mykeystore.js
+org.onap.appc.adaptor.saltstack.trustStore.trustPasswd=changeit
+org.onap.appc.adaptor.saltstack.clientType=TRUST_ALL
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/TestConnectionBuilder.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/TestConnectionBuilder.java
new file mode 100644
index 000000000..fd6e7811e
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/TestConnectionBuilder.java
@@ -0,0 +1,184 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.ali.adaptors.saltstack.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 java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class TestConnectionBuilder {
+
+ private ConnectionBuilder connBuilder;
+ private Map<String, String> params;
+
+
+ @Before
+ public void setup() throws IllegalArgumentException {
+ 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() {
+ connBuilder = null;
+ params = 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_exitStatus67() {
+
+ int exitStatus = 67;
+ String errFilePath = "src/test/resources/test.json";
+ String command = "test";
+
+ SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+ int status = result.getStatusCode();
+ assertEquals(610, status);
+ }
+
+ @Test
+ public void reqExecCommand_exitStatus73() {
+
+ int exitStatus = 73;
+ String errFilePath = "src/test/resources/test.json";
+ String command = "test";
+
+ SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+ int status = result.getStatusCode();
+ assertEquals(610, 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_exitStatus67613() {
+
+ 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_exitStatus65613() {
+
+ 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);
+ }
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/TestSaltstackAdaptorImpl.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/TestSaltstackAdaptorImpl.java
new file mode 100644
index 000000000..1a05d50cb
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/TestSaltstackAdaptorImpl.java
@@ -0,0 +1,1051 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.ali.adaptors.saltstack.impl;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdaptorImpl;
+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 TestSaltstackAdaptorImpl {
+
+ private SaltstackAdaptorImpl adaptor;
+ 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();
+ adaptor = new SaltstackAdaptorImpl(testMode);
+
+ 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;
+ adaptor = null;
+ params = null;
+ svcContext = null;
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("101", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetUserFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("101", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetHostFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("101", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetPortFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("101", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetPasswordFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Test", "fail");
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("101", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetMandatoryFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Test", "fail");
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("101", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_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("Cmd", "test");
+ params.put("SlsExec", "false");
+ try {
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("400", status);
+ } catch (NullPointerException e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_NoResponseFileWithRetry() 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("withRetry", "true");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "false");
+ try {
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("400", status);
+ } catch (NullPointerException e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_NoResponseFileWithRetryZero() 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("withRetry", "0");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "false");
+ try {
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("400", status);
+ } catch (NullPointerException e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_NoResponseFileWithNoRetry() 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("withRetry", "false");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "false");
+
+ try {
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("400", status);
+ } catch (NullPointerException e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+
+ @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 {
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.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");
+
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", 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");
+
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.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");
+
+ adaptor.reqExecCommand(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.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");
+
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", 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");
+
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", 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");
+
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", 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");
+
+ adaptor.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");
+
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", 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.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+
+ adaptor.reqExecSLSFile(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.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.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+
+ adaptor.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLSFile_NoExtn() 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");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+
+ adaptor.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.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");
+
+ adaptor.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLSFile_WithMinionSetNotSLSType() 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("NodeList", "minion1");
+
+ adaptor.reqExecSLSFile(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+ @Test
+ public void reqExecSLSFile_WithMinionSetSuccessSls() 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.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("NodeList", "minion1");
+
+ adaptor.reqExecSLSFile(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.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("NodeList", "minion1");
+
+ adaptor.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.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("NodeList", "minion1");
+
+ adaptor.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.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.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("NodeList", "*");
+
+ adaptor.reqExecSLSFile(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.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("NodeList", "*");
+
+ adaptor.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.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("NodeList", "*");
+
+ adaptor.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+
+ @Test
+ public void reqExecSLS_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("SlsName", "src/test.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+
+ adaptor.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+ @Test
+ public void reqExecSLS_shouldSetNoExtn() 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("SlsName", "src/test");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+
+ adaptor.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLS_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("SlsName", "src/test/resources/test.json");
+ params.put("fileName", "src/test/resources/test-none.json");
+ params.put("Id", "test1");
+
+ adaptor.reqExecSLS(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+
+ @Test
+ public void reqExecSLS_WithMinionSetSuccessSls() 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("SlsName", "src/test/resources/test.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("NodeList", "minion1");
+
+ adaptor.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLS_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("SlsName", "src/test/resources/test.json");
+ params.put("fileName", "src/test/resources/test-none.json");
+ params.put("Id", "test1");
+ params.put("NodeList", "minion1");
+
+ adaptor.reqExecSLS(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+ @Test
+ public void reqExecSLS_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("SlsName", "src/test/resources/test.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("NodeList", "*");
+
+ adaptor.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLS_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("SlsName", "src/test/resources/test.json");
+ params.put("fileName", "src/test/resources/test-none.json");
+ params.put("Id", "test1");
+ params.put("NodeList", "*");
+
+ adaptor.reqExecSLS(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessReal() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "127.0.0.1");
+ params.put("Port", "22");
+ params.put("User", "sdn");
+ params.put("Password", "foo");
+ params.put("Id", "test1");
+ params.put("Cmd", "ls -l");
+ params.put("SlsExec", "false");
+ params.put("Timeout", "120");
+ adaptor = new SaltstackAdaptorImpl();
+ try {
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if local ssh is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessRealSLSCommand() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("Cmd", "salt '*' test.ping --out=json --static");
+ params.put("SlsExec", "false");
+ params.put("Timeout", "120");
+
+ adaptor = new SaltstackAdaptorImpl();
+ try {
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ TestId = svcContext.getAttribute("test1.minion1");
+ assertEquals(TestId, "true");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessRealCommand() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("Cmd", "cd /srv/salt/; salt '*' state.apply vim --out=json --static");
+ params.put("SlsExec", "true");
+ params.put("Timeout", "120");
+
+ adaptor = new SaltstackAdaptorImpl();
+ try {
+ adaptor.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessRealSSL() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("SlsName", "vim");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+
+ adaptor = new SaltstackAdaptorImpl();
+ try {
+ adaptor.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessEnvParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("SlsName", "vim");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+ params.put("EnvParameters", "{\"exclude\": bar*}");
+
+ adaptor = new SaltstackAdaptorImpl();
+ try {
+ adaptor.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessFileParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("SlsName", "vim");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+ params.put("EnvParameters", "{\"exclude\": \"bar,baz\"}");
+ params.put("FileParameters", "{\"config.txt\":\"db_ip=10.1.1.1, sip_timer=10000\"}");
+
+ adaptor = new SaltstackAdaptorImpl();
+ try {
+ adaptor.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessPillarParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("SlsName", "vim");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+ params.put("EnvParameters", "{\"exclude\": \"bar,baz\", \"pillar\":\"'{\\\"foo\\\": \\\"bar\\\"}'\"}");
+ params.put("FileParameters", "{\"config.txt\":\"db_ip=10.1.1.1, sip_timer=10000\"}");
+
+ adaptor = new SaltstackAdaptorImpl();
+ try {
+ adaptor.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessMultiFileParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("SlsName", "vim");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+ params.put("EnvParameters", "{\"exclude\": bar*}");
+ params.put("FileParameters", "{\"config.txt\":\"db_ip=10.1.1.1, sip_timer=10000\" , \"config-tep.txt\":\"db_ip=10.1.1.1, sip_timer=10000\"}");
+
+ adaptor = new SaltstackAdaptorImpl();
+ try {
+ adaptor.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessSSLFile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+ params.put("SlsFile", "src/test/resources/config.sls");
+
+ adaptor = new SaltstackAdaptorImpl();
+ try {
+ adaptor.reqExecSLSFile(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessSSLFileMultiFileParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+ params.put("SlsFile", "src/test/resources/config.sls");
+ params.put("EnvParameters", "{\"exclude\": bar, \"pillar\":\"'{\\\"foo\\\": \\\"bar\\\"}'\"}");
+ params.put("FileParameters", "{\"config.txt\":\"db_ip=10.1.1.1, sip_timer=10000\" , \"config-tep.txt\":\"db_ip=10.1.1.1, sip_timer=10000\"}");
+
+ adaptor = new SaltstackAdaptorImpl();
+ try {
+ adaptor.reqExecSLSFile(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adaptor.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/TestSaltstackAdaptorPropertiesProviderImpl.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/TestSaltstackAdaptorPropertiesProviderImpl.java
new file mode 100644
index 000000000..8d37a0318
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/TestSaltstackAdaptorPropertiesProviderImpl.java
@@ -0,0 +1,310 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.ali.adaptors.saltstack.impl;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdaptorPropertiesProvider;
+import org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdaptorImpl;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class TestSaltstackAdaptorPropertiesProviderImpl {
+
+ private SaltstackAdaptorImpl adaptor;
+ private Properties params;
+
+
+ @Before
+ public void setup() throws IllegalArgumentException {
+ params = new Properties();
+ }
+
+ @After
+ public void tearDown() {
+ adaptor = null;
+ params = null;
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesBasicPortNull() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.clientType", "BASIC");
+ params.put("User", "test");
+ params.put("Password", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_setPropertiesBasicPortString() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.clientType", "BASIC");
+ params.put("org.onap.appc.adaptor.saltstack.host", "test");
+ params.put("org.onap.appc.adaptor.saltstack.port", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userName", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adaptor.saltstack.sshKey", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesBasicSuccess() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.clientType", "BASIC");
+ params.put("org.onap.appc.adaptor.saltstack.host", "test");
+ params.put("org.onap.appc.adaptor.saltstack.port", "10");
+ params.put("org.onap.appc.adaptor.saltstack.userName", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adaptor.saltstack.sshKey", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ assertNotNull(adaptor);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesSSH_CERTPortNull() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.clientType", "SSH_CERT");
+ params.put("User", "test");
+ params.put("Password", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_setPropertiesSSH_CERTPortString() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.clientType", "SSH_CERT");
+ params.put("org.onap.appc.adaptor.saltstack.host", "test");
+ params.put("org.onap.appc.adaptor.saltstack.port", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userName", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adaptor.saltstack.sshKey", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesSSH_CERTSuccess() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.clientType", "SSH_CERT");
+ params.put("org.onap.appc.adaptor.saltstack.host", "test");
+ params.put("org.onap.appc.adaptor.saltstack.port", "10");
+ params.put("org.onap.appc.adaptor.saltstack.userName", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adaptor.saltstack.sshKey", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesBOTHPortNull() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.clientType", "BOTH");
+ params.put("User", "test");
+ params.put("Password", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesBOTHSuccess() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.clientType", "BOTH");
+ params.put("org.onap.appc.adaptor.saltstack.host", "test");
+ params.put("org.onap.appc.adaptor.saltstack.port", "10");
+ params.put("org.onap.appc.adaptor.saltstack.userName", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adaptor.saltstack.sshKey", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesNonePortNull() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.clientType", "NONE");
+ params.put("User", "test");
+ params.put("Password", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesNonePortString() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.clientType", "NONE");
+ params.put("org.onap.appc.adaptor.saltstack.host", "test");
+ params.put("org.onap.appc.adaptor.saltstack.port", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userName", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adaptor.saltstack.sshKey", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesNoneSuccess() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.clientType", "NONE");
+ params.put("org.onap.appc.adaptor.saltstack.host", "test");
+ params.put("org.onap.appc.adaptor.saltstack.port", "10");
+ params.put("org.onap.appc.adaptor.saltstack.userName", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adaptor.saltstack.sshKey", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+
+ @Test
+ public void reqExecCommand_setPropertiesElsePortNull() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("User", "test");
+ params.put("Password", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesElsePortString() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.host", "test");
+ params.put("org.onap.appc.adaptor.saltstack.port", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userName", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adaptor.saltstack.sshKey", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesElseSuccess() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adaptor.saltstack.host", "test");
+ params.put("org.onap.appc.adaptor.saltstack.port", "10");
+ params.put("org.onap.appc.adaptor.saltstack.userName", "test");
+ params.put("org.onap.appc.adaptor.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adaptor.saltstack.sshKey", "test");
+ SaltstackAdaptorPropertiesProvider propProvider = new SaltstackAdaptorPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adaptor = new SaltstackAdaptorImpl(propProvider);
+ String adaptorName = adaptor.getAdaptorName();
+ assertEquals("Saltstack Adaptor", adaptorName);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesDefault() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ adaptor = new SaltstackAdaptorImpl();
+ assertNotNull(adaptor);
+ }
+}
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/model/TestJsonParser.java b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/model/TestJsonParser.java
new file mode 100644
index 000000000..31ccaee9d
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/java/org/onap/ccsdk/sli/adaptors/saltstack/model/TestJsonParser.java
@@ -0,0 +1,76 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.ccsdk.ali.adaptors.saltstack.model;
+
+import org.codehaus.jettison.json.JSONException;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.JsonParser;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+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;
+import static org.junit.Assert.assertNotNull;
+
+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();
+ assertNotNull(mm);
+ }
+
+ @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/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/config.sls b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/config.sls
new file mode 100644
index 000000000..aff05939b
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/config.sls
@@ -0,0 +1,2 @@
+vim:
+ pkg.installed
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/org/onap/ccsdk/default.properties b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/org/onap/ccsdk/default.properties
new file mode 100644
index 000000000..ba54b4a53
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/org/onap/ccsdk/default.properties
@@ -0,0 +1,102 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2018 Samsung Electronics. 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=========================================================
+###
+#
+# Default properties for the APP-C Provider Adaptor
+#
+# -------------------------------------------------------------------------------------------------
+#
+# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded
+# to supply configuration options
+org.onap.appc.bootstrap.file=appc.properties
+org.onap.appc.bootstrap.path=/opt/onap/appc/data/properties,${user.home},.
+appc.application.name=APPC
+#
+# Define the message resource bundle name to be loaded
+org.onap.appc.resources=org/onap/appc/i18n/MessageResources
+#
+# The name of the adaptor.
+org.onap.appc.provider.adaptor.name=org.onap.appc.appc_provider_adaptor
+#
+# Set up the logging environment
+#
+org.onap.appc.logging.file=org/onap/appc/logback.xml
+org.onap.appc.logging.path=${user.home};etc;../etc
+org.onap.appc.logger=org.onap.appc
+org.onap.appc.security.logger=org.onap.appc.security
+#
+# The minimum and maximum provider/tenant context pool sizes. Min=1 means that as soon
+# as the provider/tenant is referenced a Context is opened and added to the pool. Max=0
+# means that the upper bound on the pool is unbounded.
+org.onap.appc.provider.min.pool=1
+org.onap.appc.provider.max.pool=0
+#
+# The following properties are used to configure the retry logic for connection to the
+# IaaS provider(s). The retry delay property is the amount of time, in seconds, the
+# application waits between retry attempts. The retry limit is the number of retries
+# that are allowed before the request is failed.
+org.onap.appc.provider.retry.delay=30
+org.onap.appc.provider.retry.limit=10
+#
+# The trusted hosts list for SSL access when a certificate is not provided.
+#
+provider.trusted.hosts=*
+#
+# The amount of time, in seconds, to wait for a server state change (start->stop, stop->start, etc).
+# If the server does not change state to a valid state within the alloted time, the operation
+# fails.
+org.onap.appc.server.state.change.timeout=300
+#
+# The amount of time to wait, in seconds, between subsequent polls to the OpenStack provider
+# to refresh the status of a resource we are waiting on.
+#
+org.onap.appc.openstack.poll.interval=20
+#
+# The connection information to connect to the provider we are using. These properties
+# are "structured" properties, in that the name is a compound name, where the nodes
+# of the name can be ordered (1, 2, 3, ...). All of the properties with the same ordinal
+# position are defining the same entity. For example, provider1.type and provider1.name
+# are defining the same provider, whereas provider2.name and provider2.type are defining
+# the values for a different provider. Any number of providers can be defined in this
+# way.
+#
+# Don't change these 2 right now since they are hard coded in the DG
+#provider1.type=appc
+#provider1.name=appc
+#These you can change
+#provider1.identity=appc
+#provider1.tenant1.name=appc
+#provider1.tenant1.userid=appc
+#provider1.tenant1.password=appc
+# After a change to the provider make sure to recheck these values with an api call to provider1.identity/tokens
+test.expected-regions=1
+test.expected-endpoints=1
+#Your OpenStack IP
+#test.ip=192.168.1.2
+# Your OpenStack Platform's Keystone Port (default is 5000)
+#test.port=5000
+#test.tenantid=abcde12345fghijk6789lmnopq123rst
+#test.vmid=abc12345-1234-5678-890a-abcdefg12345
+# Port 8774 below is default port for OpenStack's Nova API Service
+#test.url=http://192.168.1.2:8774/v2/abcde12345fghijk6789lmnopq123rst/servers/abc12345-1234-5678-890a-abcdefg12345
+
diff --git a/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test
new file mode 100644
index 000000000..dec578bd9
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test
@@ -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/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test-invalid.json b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test-invalid.json
new file mode 100644
index 000000000..d16bfccdf
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test-invalid.json
@@ -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/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test-sls.json b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test-sls.json
new file mode 100644
index 000000000..bc1c10c8d
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test-sls.json
@@ -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/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test.json b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test.json
new file mode 100644
index 000000000..81131d6f4
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test.json
@@ -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/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test.sls b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test.sls
new file mode 100644
index 000000000..cd76486aa
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test.sls
@@ -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/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test.txt b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test.txt
new file mode 100644
index 000000000..dec578bd9
--- /dev/null
+++ b/adaptors/saltstack-adaptor/saltstack-adaptor-provider/src/test/resources/test.txt
@@ -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