diff options
Diffstat (limited to 'saltstack-adapter/saltstack-adapter-provider')
20 files changed, 1805 insertions, 324 deletions
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapter.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapter.java index 2f70a79a..1cbb495c 100644 --- a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapter.java +++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapter.java @@ -24,14 +24,14 @@ package org.onap.ccsdk.sli.adaptors.saltstack; -import java.util.Map; import org.onap.ccsdk.sli.core.sli.SvcLogicContext; import org.onap.ccsdk.sli.core.sli.SvcLogicException; import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin; +import java.util.Map; + /** * This interface defines the operations that the Saltstack adapter exposes. - * */ public interface SaltstackAdapter extends SvcLogicJavaPlugin { /** @@ -46,11 +46,16 @@ public interface SaltstackAdapter extends SvcLogicJavaPlugin { * to context for DGs access, with a certain prefix*/ void reqExecCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException; + /* Method for execution of saltstack SLS command on SaltState server + * The response from Saltstack comes in json format and it is automatically put + * to context for DGs access, with a certain prefix*/ + void reqExecSLS(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException; + /* When SLS file is created/available then this Method can be used to post * the file to saltstack server and execute the SLS file on SaltState server * The response from Saltstack comes in json format and it is automatically put * to context for DGs access, with a certain prefix*/ - void reqExecSLS(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException; + void reqExecSLSFile(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException; /* Method to get log of a saltState execution request * The response from Saltstack comes in json format and it is automatically put @@ -59,6 +64,7 @@ public interface SaltstackAdapter extends SvcLogicJavaPlugin { /** * Set the command execution timeout + * * @param timeout time in milliseconds */ void setExecTimeout(long timeout); diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java index 5dee9f5e..65ab598d 100644 --- a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java +++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java @@ -24,7 +24,13 @@ package org.onap.ccsdk.sli.adaptors.saltstack.impl; -import java.io.BufferedOutputStream; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.RandomStringUtils; +import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult; +import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes; + import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -32,15 +38,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.StringWriter; -import java.util.List; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.RandomStringUtils; -import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult; -import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes; -import org.onap.ccsdk.sli.core.sli.SvcLogicException; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; /** * Returns a custom SSH client @@ -88,7 +85,7 @@ public class ConnectionBuilder { * @return command execution status */ public SaltstackResult connectNExecute(String cmd) { - return connectNExecute(cmd,-1,-1); + return connectNExecute(cmd, -1, -1); } /** @@ -96,7 +93,7 @@ public class ConnectionBuilder { * 2. Exec remote command over SSH. Return command execution status. * Command output is written to out or err stream. * - * @param cmd Commands to execute + * @param cmd Commands to execute * @param retryDelay delay between retry to make a SSH connection. * @param retryCount number of count retry to make a SSH connection. * @return command execution status @@ -113,8 +110,8 @@ public class ConnectionBuilder { if (result.getStatusCode() != SaltstackResultCodes.SUCCESS.getValue()) { return result; } - String outFilePath = "/tmp/"+ RandomStringUtils.random(5,true,true); - String errFilePath = "/tmp/"+ RandomStringUtils.random(5,true,true); + String outFilePath = "/tmp/" + RandomStringUtils.random(5, true, true); + String errFilePath = "/tmp/" + RandomStringUtils.random(5, true, true); OutputStream out = new FileOutputStream(outFilePath); OutputStream errs = new FileOutputStream(errFilePath); result = sshConnection.execCommand(cmd, out, errs); @@ -137,40 +134,42 @@ public class ConnectionBuilder { return result; } - public SaltstackResult sortExitStatus (int exitStatus, String errFilePath, String cmd) { + public SaltstackResult sortExitStatus(int exitStatus, String errFilePath, String cmd) { SaltstackResult result = new SaltstackResult(); - String err; + String err = ""; StringWriter writer = new StringWriter(); try { IOUtils.copy(new FileInputStream(new File(errFilePath)), writer, "UTF-8"); err = writer.toString(); - } catch (Exception e){ - err = ""; + } catch (FileNotFoundException e){ + logger.info("Error stream file doesn't exist"); + } catch (IOException e){ + logger.info("Error stream file doesn't exist"); } if (exitStatus == 255 || exitStatus == 1) { String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString() + "]. Exit Code " + exitStatus + " and Error message : " + - "Malformed configuration. "+ err; + "Malformed configuration. " + err; logger.error(errMessage); result.setStatusCode(SaltstackResultCodes.INVALID_COMMAND.getValue()); result.setStatusMessage(errMessage); } else if (exitStatus == 5 || exitStatus == 65) { String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString() + "]. Exit Code " + exitStatus + " and Error message : " + - "Host not allowed to connect. "+ err; + "Host not allowed to connect. " + err; logger.error(errMessage); result.setStatusCode(SaltstackResultCodes.USER_UNAUTHORIZED.getValue()); result.setStatusMessage(errMessage); } else if (exitStatus == 67 || exitStatus == 73) { String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString() + "]. Exit Code " + exitStatus + " and Error message : " + - "Key exchange failed. "+ err; + "Key exchange failed. " + err; logger.error(errMessage); result.setStatusCode(SaltstackResultCodes.CERTIFICATE_ERROR.getValue()); result.setStatusMessage(errMessage); } else { String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString() - + "]. Exit Code " + exitStatus + " and Error message : "+ err; + + "]. Exit Code " + exitStatus + " and Error message : " + err; logger.error(errMessage); result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue()); result.setStatusMessage(errMessage); @@ -183,7 +182,7 @@ public class ConnectionBuilder { * 2. Exec remote command over SSH. Return command execution status. * Command output is written to out or err stream. * - * @param commands list of commands to execute + * @param commands list of commands to execute * @param payloadSLS has the SLS file location that is to be sent to server * @param retryDelay delay between retry to make a SSH connection. * @param retryCount number of count retry to make a SSH connection. @@ -205,7 +204,7 @@ public class ConnectionBuilder { /** * Disconnect from SSH server. */ - public SaltstackResult disConnect(){ + public SaltstackResult disConnect() { SaltstackResult result = new SaltstackResult(); try { @@ -225,7 +224,7 @@ public class ConnectionBuilder { * @param cmd command to execute * @return command execution status */ - public SaltstackResult execute(String cmd) { + public SaltstackResult connectNExecuteLog(String cmd) { SaltstackResult result = new SaltstackResult(); diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterImpl.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterImpl.java index 5fe130fc..84e5d4f1 100644 --- a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterImpl.java +++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterImpl.java @@ -24,11 +24,8 @@ package org.onap.ccsdk.sli.adaptors.saltstack.impl; -import java.util.Map; -import java.util.Properties; -import org.apache.commons.lang.StringUtils; -import org.json.JSONException; -import org.json.JSONObject; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapter; import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapterPropertiesProvider; import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackMessageParser; @@ -37,8 +34,14 @@ import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes; import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackServerEmulator; import org.onap.ccsdk.sli.core.sli.SvcLogicContext; import org.onap.ccsdk.sli.core.sli.SvcLogicException; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.Properties; /** * This class implements the {@link SaltstackAdapter} interface. This interface defines the behaviors @@ -46,56 +49,45 @@ import com.att.eelf.configuration.EELFManager; */ public class SaltstackAdapterImpl implements SaltstackAdapter { - private static final long EXEC_TIMEOUT = 120000; - private long timeout = EXEC_TIMEOUT; - /** * The constant used to define the service name in the mapped diagnostic context */ @SuppressWarnings("nls") public static final String MDC_SERVICE = "service"; - /** * The constant for the status code for a failed outcome */ @SuppressWarnings("nls") public static final String OUTCOME_FAILURE = "failure"; - /** * The constant for the status code for a successful outcome */ @SuppressWarnings("nls") public static final String OUTCOME_SUCCESS = "success"; - + public static final String CONNECTION_RETRY_DELAY = "retryDelay"; + public static final String CONNECTION_RETRY_COUNT = "retryCount"; + private static final long EXEC_TIMEOUT = 120000; /** * Adapter Name */ private static final String ADAPTER_NAME = "Saltstack Adapter"; private static final String APPC_EXCEPTION_CAUGHT = "APPCException caught"; - private static final String RESULT_CODE_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.result.code"; private static final String MESSAGE_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.message"; private static final String RESULTS_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.results"; private static final String ID_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.Id"; private static final String LOG_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.log"; - - public static final String CONNECTION_RETRY_DELAY = "retryDelay"; - public static final String CONNECTION_RETRY_COUNT = "retryCount"; - private static final String CLIENT_TYPE_PROPERTY_NAME = "org.onap.appc.adapter.saltstack.clientType"; private static final String SS_SERVER_HOSTNAME = "org.onap.appc.adapter.saltstack.host"; private static final String SS_SERVER_PORT = "org.onap.appc.adapter.saltstack.port"; private static final String SS_SERVER_USERNAME = "org.onap.appc.adapter.saltstack.userName"; private static final String SS_SERVER_PASSWORD = "org.onap.appc.adapter.saltstack.userPasswd"; private static final String SS_SERVER_SSH_KEY = "org.onap.appc.adapter.saltstack.sshKey"; - - /** * The logger to be used */ private static final EELFLogger logger = EELFManager.getInstance().getLogger(SaltstackAdapterImpl.class); - - + private long timeout = EXEC_TIMEOUT; /** * Connection object **/ @@ -119,10 +111,11 @@ public class SaltstackAdapterImpl implements SaltstackAdapter { /** * This default constructor is used as a work around because the activator wasn't getting called */ - public SaltstackAdapterImpl() { + public SaltstackAdapterImpl() throws SvcLogicException{ initialize(new SaltstackAdapterPropertiesProviderImpl()); } - public SaltstackAdapterImpl(SaltstackAdapterPropertiesProvider propProvider) { + + public SaltstackAdapterImpl(SaltstackAdapterPropertiesProvider propProvider) throws SvcLogicException{ initialize(propProvider); } @@ -150,9 +143,10 @@ public class SaltstackAdapterImpl implements SaltstackAdapter { public void setExecTimeout(long timeout) { this.timeout = timeout; } + /** - * Method posts info to Context memory in case of an error and throws a - * SvcLogicException causing SLI to register this as a failure + * Method posts info to Context memory in case of an error and throws a + * SvcLogicException causing SLI to register this as a failure */ @SuppressWarnings("static-method") private void doFailure(SvcLogicContext svcLogic, int code, String message) throws SvcLogicException { @@ -160,14 +154,13 @@ public class SaltstackAdapterImpl implements SaltstackAdapter { svcLogic.setStatus(OUTCOME_FAILURE); svcLogic.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(code)); svcLogic.setAttribute(MESSAGE_ATTRIBUTE_NAME, message); - throw new SvcLogicException("Saltstack Adapter Error = " + message); } /** * initialize the Saltstack adapter based on default and over-ride configuration data */ - private void initialize(SaltstackAdapterPropertiesProvider propProvider) { + private void initialize(SaltstackAdapterPropertiesProvider propProvider) throws SvcLogicException{ Properties props = propProvider.getProperties(); @@ -211,27 +204,26 @@ public class SaltstackAdapterImpl implements SaltstackAdapter { String sshPort = props.getProperty(SS_SERVER_PORT); logger.info("Creating ssh client with ssh KEY from " + sshKey); sshClient = new ConnectionBuilder(sshHost, sshPort, sshUserName, sshPassword, sshKey); + } else if ("NONE".equalsIgnoreCase(clientType)) { + logger.info("No saltstack-adapter.properties defined so reading from DG props"); + sshClient = null; } else { logger.info("No saltstack-adapter.properties defined so reading from DG props"); sshClient = null; } + } catch (NumberFormatException e) { + logger.error("Error Initializing Saltstack Adapter due to Unknown Exception", e); + throw new SvcLogicException("Saltstack Adapter Property file parsing Error = port in property file has to be an integer."); } catch (Exception e) { logger.error("Error Initializing Saltstack Adapter due to Unknown Exception", e); + throw new SvcLogicException("Saltstack Adapter Property file parsing Error = " + e.getMessage()); } logger.info("Initialized Saltstack Adapter"); } - // Public Method to post single command request to execute saltState. Posts the following back - // to Svc context memory - // org.onap.appc.adapter.saltstack.req.code : 100 if successful - // org.onap.appc.adapter.saltstack.req.messge : any message - // org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request - @Override - public void reqExecCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException { - String reqID; - SaltstackResult testResult; - if (sshClient == null){ + private void setSSHClient(Map<String, String> params) throws SvcLogicException { + if (sshClient == null) { logger.info("saltstack-adapter.properties not defined so reading saltstack host and " + "auth details from DG's parameters"); String sshHost = messageProcessor.reqHostNameResult(params); @@ -239,59 +231,148 @@ public class SaltstackAdapterImpl implements SaltstackAdapter { String sshUserName = messageProcessor.reqUserNameResult(params); String sshPassword = messageProcessor.reqPasswordResult(params); logger.info("Creating ssh client with BASIC Auth"); - if(!testMode) + if (!testMode) { sshClient = new ConnectionBuilder(sshHost, sshPort, sshUserName, sshPassword); + } } + } + + private String putToCommands(SvcLogicContext ctx, String slsFileName, + String applyTo) throws SvcLogicException { + String constructedCommand = ""; try { - reqID = params.get("Id"); - String commandToExecute = params.get("cmd"); - testResult = execCommand(params, commandToExecute); - testResult = messageProcessor.parseResponse(ctx, reqID, testResult); - - // Check status of test request returned by Agent - if (testResult.getStatusCode() == SaltstackResultCodes.FINAL_SUCCESS.getValue()) { - logger.info(String.format("Execution of request-ID : %s successful.", reqID)); - testResult.setResults("Success"); - } else { - doFailure(ctx, testResult.getStatusCode(), "Request for execution of command failed. Reason = " + testResult.getStatusMessage()); - return; + 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"); } - } catch (SvcLogicException e) { - logger.error(APPC_EXCEPTION_CAUGHT, e); - doFailure(ctx, SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue(), - "Request for execution of command failed. Reason = " - + e.getMessage()); - return; - } catch (Exception e) { - logger.error("Exception caught", e); - doFailure(ctx, SaltstackResultCodes.INVALID_COMMAND.getValue(), - "Request for execution of command failed. Reason = " - + e.getMessage()); + InputStream in = new FileInputStream(file); + byte[] data = new byte[(int) file.length()]; + in.read(data); + String str = new String(data, "UTF-8"); + in.close(); + String slsWithoutExtn = stripExtension(slsFile); + constructedCommand = "echo -e \""+str+"\" > /srv/salt/"+slsFile+"; cd /srv/salt/; salt '"+ + applyTo+"' state.apply "+slsWithoutExtn+" --out=json --static"; + } catch (FileNotFoundException e) { + doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(), "Input SLS file " + + "not found in path : " + slsFileName+". "+ e.getMessage()); + } catch (IOException e) { + doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(), "Input SLS file " + + "error in path : " + slsFileName +". "+ e.getMessage()); + } catch (StringIndexOutOfBoundsException e) { + doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(), "Input file " + + "is not of type .sls"); + } + logger.info("Command to be executed on server : " + constructedCommand); + return constructedCommand; + } + + 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) { + String + constructedCommand = "cd /srv/salt/; salt '"+applyTo+"' state.apply "+slsName+" --out=json --static"; + + logger.info("Command to be executed on server : " + constructedCommand); + return constructedCommand; + } + + private void checkResponseStatus(SaltstackResult testResult, SvcLogicContext ctx, String reqID, boolean slsExec) + throws SvcLogicException { + + // Check status of test request returned by Agent + if (testResult.getStatusCode() != SaltstackResultCodes.FINAL_SUCCESS.getValue()) { + ctx.setAttribute(ID_ATTRIBUTE_NAME, reqID); + doFailure(ctx, testResult.getStatusCode(), "Request for execution of command failed. Reason = " + testResult.getStatusMessage()); return; + } else { + logger.info(String.format("Execution of request : successful.")); + if (slsExec) { + ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(testResult.getStatusCode())); + ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, "success"); + } else { + ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(SaltstackResultCodes.CHECK_CTX_FOR_CMD_SUCCESS.getValue())); + ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, "check context for execution status"); + } + ctx.setAttribute(ID_ATTRIBUTE_NAME, reqID); } - ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(testResult.getStatusCode())); - ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, testResult.getResults()); - ctx.setAttribute(ID_ATTRIBUTE_NAME, reqID); + } + + // Public Method to post single command request to execute saltState. Posts the following back + // to Svc context memory + // org.onap.appc.adapter.saltstack.req.code : 100 if successful + // org.onap.appc.adapter.saltstack.req.messge : any message + // org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request + @Override + public void reqExecCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException { + String reqID; + boolean slsExec; + SaltstackResult testResult; + setSSHClient(params); + reqID = messageProcessor.reqId(params); + String commandToExecute = messageProcessor.reqCmd(params); + slsExec = messageProcessor.reqIsSLSExec(params); + testResult = execCommand(params, commandToExecute); + testResult = messageProcessor.parseResponse(ctx, reqID, testResult, slsExec); + checkResponseStatus(testResult, ctx, reqID, slsExec); } /** - * Public Method to post SLS file request to execute saltState. Posts the following back + * Public Method to post SLS command request to execute saltState on server. Posts the following back * to Svc context memory - * - * org.onap.appc.adapter.saltstack.req.code : 100 if successful + * <p> + * org.onap.appc.adapter.saltstack.req.code : 200 if successful * org.onap.appc.adapter.saltstack.req.messge : any message * org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request */ @Override public void reqExecSLS(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException { - //TODO: to implement + String reqID; + SaltstackResult testResult; + setSSHClient(params); + reqID = messageProcessor.reqId(params); + String slsName = messageProcessor.reqSlsName(params); + String applyTo = messageProcessor.reqApplyToDevices(params); + String commandToExecute = putToCommands(slsName, applyTo); + testResult = execCommand(params, commandToExecute); + testResult = messageProcessor.parseResponse(ctx, reqID, testResult, true); + checkResponseStatus(testResult, ctx, reqID, true); + } + /** + * Public Method to post SLS file request to execute saltState. Posts the following back + * to Svc context memory + * <p> + * org.onap.appc.adapter.saltstack.req.code : 100 if successful + * org.onap.appc.adapter.saltstack.req.messge : any message + * org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request + */ + @Override + public void reqExecSLSFile(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException { + String reqID; + SaltstackResult testResult; + setSSHClient(params); + reqID = messageProcessor.reqId(params); + String slsFile = messageProcessor.reqSlsFile(params); + String applyTo = messageProcessor.reqApplyToDevices(params); + String commandToExecute = putToCommands(ctx, slsFile, applyTo); + testResult = execCommand(params, commandToExecute); + testResult = messageProcessor.parseResponse(ctx, reqID, testResult, true); + checkResponseStatus(testResult, ctx, reqID, true); } /** * Public method to get logs from saltState execution for a specific request Posts the following back * to Svc context memory - * + * <p> * It blocks till the Saltstack Server responds or the session times out very similar to * reqExecResult logs are returned in the DG context variable org.onap.appc.adapter.saltstack.log */ @@ -301,20 +382,20 @@ public class SaltstackAdapterImpl implements SaltstackAdapter { } - public SaltstackResult execCommand(Map<String, String> params, String commandToExecute){ + public SaltstackResult execCommand(Map<String, String> params, String commandToExecute) { SaltstackResult testResult; if (params.get(CONNECTION_RETRY_DELAY) != null && params.get(CONNECTION_RETRY_COUNT) != null) { int retryDelay = Integer.parseInt(params.get(CONNECTION_RETRY_DELAY)); int retryCount = Integer.parseInt(params.get(CONNECTION_RETRY_COUNT)); - if(!testMode) + if (!testMode) { testResult = sshClient.connectNExecute(commandToExecute, retryCount, retryDelay); - else { + } else { testResult = testServer.MockReqExec(params); } } else { - if(!testMode) + if (!testMode) { testResult = sshClient.connectNExecute(commandToExecute); - else { + } else { testResult = testServer.MockReqExec(params); } } diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterPropertiesProviderImpl.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterPropertiesProviderImpl.java index 24308851..a4156558 100755 --- a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterPropertiesProviderImpl.java +++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterPropertiesProviderImpl.java @@ -20,13 +20,6 @@ package org.onap.ccsdk.sli.adaptors.saltstack.impl; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Optional; -import java.util.Properties; -import java.util.Vector; import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapterPropertiesProvider; import org.onap.ccsdk.sli.core.sli.ConfigurationException; import org.onap.ccsdk.sli.core.utils.JREFileResolver; @@ -37,11 +30,19 @@ import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Optional; +import java.util.Properties; +import java.util.Vector; + /** * Responsible for determining the properties file to use and instantiating the * <code>SqlResource</code> Service. The priority for properties file * resolution is as follows: - * + * <p> * <ol> * <li>A directory identified by the system environment variable * <code>SDNC_CONFIG_DIR</code></li> @@ -93,8 +94,8 @@ public class SaltstackAdapterPropertiesProviderImpl implements SaltstackAdapterP properties.load(fileInputStream); } catch (final IOException e) { LOG.error("Failed to load properties for file: {}", propertiesFile.toString(), - new ConfigurationException("Failed to load properties for file: " + propertiesFile.toString(), - e)); + new ConfigurationException("Failed to load properties for file: " + propertiesFile.toString(), + e)); } } else { // Try to read properties as resource @@ -124,22 +125,11 @@ public class SaltstackAdapterPropertiesProviderImpl implements SaltstackAdapterP } /** - * Extract svclogic config properties. - * - * @return the svclogic config properties - */ - public Properties getProperties() { - return properties; - } - - /** * Reports the method chosen for properties resolution to the * <code>Logger</code>. * - * @param message - * Some user friendly message - * @param fileOptional - * The file location of the chosen properties file + * @param message Some user friendly message + * @param fileOptional The file location of the chosen properties file * @return the file location of the chosen properties file */ private static File reportSuccess(final String message, final Optional<File> fileOptional) { @@ -155,10 +145,8 @@ public class SaltstackAdapterPropertiesProviderImpl implements SaltstackAdapterP * Reports fatal errors. This is the case in which no properties file could be * found. * - * @param message - * An appropriate fatal error message - * @param configurationException - * An exception describing what went wrong during resolution + * @param message An appropriate fatal error message + * @param configurationException An exception describing what went wrong during resolution */ private static void reportFailure(final String message, final ConfigurationException configurationException) { @@ -166,6 +154,15 @@ public class SaltstackAdapterPropertiesProviderImpl implements SaltstackAdapterP } /** + * 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 diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java index 41e6102d..96ed7d2d 100644 --- a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java +++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java @@ -9,22 +9,23 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. * ============LICENSE_END========================================================= */ package org.onap.ccsdk.sli.adaptors.saltstack.impl; -import org.onap.appc.encryption.EncryptionTool; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; import org.apache.sshd.ClientChannel; import org.apache.sshd.ClientSession; import org.apache.sshd.SshClient; @@ -33,12 +34,9 @@ import org.apache.sshd.client.future.AuthFuture; import org.apache.sshd.client.future.OpenFuture; import org.apache.sshd.common.KeyPairProvider; import org.apache.sshd.common.keyprovider.FileKeyPairProvider; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; +import org.onap.appc.encryption.EncryptionTool; import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult; import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes; -import org.onap.ccsdk.sli.core.sli.SvcLogicException; import java.io.OutputStream; import java.security.KeyPair; @@ -48,11 +46,11 @@ import java.security.KeyPair; */ class SshConnection { + public static final int DEFAULT_CONNECTION_RETRY_DELAY = 60; + public static final int DEFAULT_CONNECTION_RETRY_COUNT = 5; private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger(); - private static final long AUTH_TIMEOUT = 60000; private static final long EXEC_TIMEOUT = 120000; - private String host; private int port; private String username; @@ -62,9 +60,6 @@ class SshConnection { private SshClient sshClient; private ClientSession clientSession; - public static final int DEFAULT_CONNECTION_RETRY_DELAY = 60; - public static final int DEFAULT_CONNECTION_RETRY_COUNT = 5; - public SshConnection(String host, int port, String username, String password, String keyFile) { this.host = host; this.port = port; @@ -87,13 +82,13 @@ class SshConnection { sshClient.start(); try { clientSession = - sshClient.connect(EncryptionTool.getInstance().decrypt(username), host, port).await().getSession(); + sshClient.connect(EncryptionTool.getInstance().decrypt(username), host, port).await().getSession(); if (password != null) { clientSession.addPasswordIdentity(EncryptionTool.getInstance().decrypt(password)); } if (keyFile != null) { - KeyPairProvider keyPairProvider = new FileKeyPairProvider(new String[] { - keyFile + KeyPairProvider keyPairProvider = new FileKeyPairProvider(new String[]{ + keyFile }); KeyPair keyPair = keyPairProvider.loadKeys().iterator().next(); clientSession.addPublicKeyIdentity(keyPair); @@ -102,18 +97,18 @@ class SshConnection { authFuture.await(AUTH_TIMEOUT); if (!authFuture.isSuccess()) { String errMessage = "Error establishing ssh connection to [" + username + "@" + host + ":" + port - + "]. Authentication failed."; + + "]. Authentication failed."; result.setStatusCode(SaltstackResultCodes.USER_UNAUTHORIZED.getValue()); result.setStatusMessage(errMessage); } } catch (RuntimeException e) { String errMessage = "Error establishing ssh connection to [" + username + "@" + host + ":" + port + "]." + - "Runtime Exception : "+ e.getMessage(); + "Runtime Exception : " + e.getMessage(); result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue()); result.setStatusMessage(errMessage); } catch (Exception e) { String errMessage = "Error establishing ssh connection to [" + username + "@" + host + ":" + port + "]." + - "Host Unknown : " + e.getMessage(); + "Host Unknown : " + e.getMessage(); result.setStatusCode(SaltstackResultCodes.HOST_UNKNOWN.getValue()); result.setStatusMessage(errMessage); } @@ -127,10 +122,12 @@ class SshConnection { public SaltstackResult connectWithRetry(int retryCount, int retryDelay) { int retriesLeft; SaltstackResult result = new SaltstackResult(); - if(retryCount == 0) - retryCount = DEFAULT_CONNECTION_RETRY_COUNT; - if(retryDelay == 0) - retryDelay = DEFAULT_CONNECTION_RETRY_DELAY; + if (retryCount == 0) { + retryCount = DEFAULT_CONNECTION_RETRY_COUNT; + } + if (retryDelay == 0) { + retryDelay = DEFAULT_CONNECTION_RETRY_DELAY; + } retriesLeft = retryCount + 1; do { try { @@ -142,11 +139,11 @@ class SshConnection { waitForConnection(retryDelay); retriesLeft--; logger.debug("Retrying SSH connection. Attempt [" + Integer.toString(retryCount - retriesLeft + 1) - + "] out of [" + retryCount + "]"); + + "] out of [" + retryCount + "]"); } else { throw e; } - } + } } while (retriesLeft > 0); return result; } @@ -207,12 +204,12 @@ class SshConnection { return result; } catch (RuntimeException e) { String errMessage = "Error establishing ssh connection to [" + username + "@" + host + ":" + port + "]." + - "Runtime Exception : "+ e.getMessage(); + "Runtime Exception : " + e.getMessage(); result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue()); result.setStatusMessage(errMessage); } catch (Exception e1) { String errMessage = "Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" + - port + "]"+ e1.getMessage(); + port + "]" + e1.getMessage(); result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue()); result.setStatusMessage(errMessage); } diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java index f33799fd..be1fa574 100644 --- a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java +++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java @@ -8,9 +8,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -44,46 +44,46 @@ public final class JsonParser { @SuppressWarnings("unchecked") public static Map<String, String> convertToProperties(String s) - throws JSONException { + throws JSONException { checkNotNull(s, "Input should not be null."); - JSONObject json = new JSONObject(s); - Map<String, Object> wm = new HashMap<>(); - Iterator<String> ii = json.keys(); - while (ii.hasNext()) { - String key1 = ii.next(); - wm.put(key1, json.get(key1)); - } - - Map<String, String> mm = new HashMap<>(); - - while (!wm.isEmpty()) - for (String key : new ArrayList<>(wm.keySet())) { - Object o = wm.get(key); - wm.remove(key); - - if (o instanceof Boolean || o instanceof Number || o instanceof String) { - mm.put(key, o.toString()); - - log.info("Added property: {} : {}", key, o.toString()); - } else if (o instanceof JSONObject) { - JSONObject jo = (JSONObject) o; - Iterator<String> i = jo.keys(); - while (i.hasNext()) { - String key1 = i.next(); - wm.put(key + "." + key1, jo.get(key1)); - } - } else if (o instanceof JSONArray) { - JSONArray ja = (JSONArray) o; - mm.put(key + "_length", String.valueOf(ja.length())); + JSONObject json = new JSONObject(s); + Map<String, Object> wm = new HashMap<>(); + Iterator<String> ii = json.keys(); + while (ii.hasNext()) { + String key1 = ii.next(); + wm.put(key1, json.get(key1)); + } + + Map<String, String> mm = new HashMap<>(); + + while (!wm.isEmpty()) + for (String key : new ArrayList<>(wm.keySet())) { + Object o = wm.get(key); + wm.remove(key); + + if (o instanceof Boolean || o instanceof Number || o instanceof String) { + mm.put(key, o.toString()); + + log.info("Added property: {} : {}", key, o.toString()); + } else if (o instanceof JSONObject) { + JSONObject jo = (JSONObject) o; + Iterator<String> i = jo.keys(); + while (i.hasNext()) { + String key1 = i.next(); + wm.put(key + "." + key1, jo.get(key1)); + } + } else if (o instanceof JSONArray) { + JSONArray ja = (JSONArray) o; + mm.put(key + "_length", String.valueOf(ja.length())); - log.info("Added property: {}_length: {}", key, String.valueOf(ja.length())); + log.info("Added property: {}_length: {}", key, String.valueOf(ja.length())); - for (int i = 0; i < ja.length(); i++) - wm.put(key + '[' + i + ']', ja.get(i)); - } + for (int i = 0; i < ja.length(); i++) + wm.put(key + '[' + i + ']', ja.get(i)); } - return mm; + } + return mm; } } diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java index 1ea31516..f282a338 100644 --- a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java +++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java @@ -28,6 +28,16 @@ package org.onap.ccsdk.sli.adaptors.saltstack.model; * This module implements the APP-C/Saltstack Server interface * based on the REST API specifications */ + +import com.google.common.base.Strings; +import org.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.json.JSONObject; +import org.onap.ccsdk.sli.core.sli.SvcLogicContext; +import org.onap.ccsdk.sli.core.sli.SvcLogicException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -39,14 +49,6 @@ import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.UUID; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.onap.ccsdk.sli.core.sli.SvcLogicContext; -import org.onap.ccsdk.sli.core.sli.SvcLogicException; -import com.google.common.base.Strings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Class that validates and constructs requests sent/received from @@ -63,6 +65,12 @@ public class SaltstackMessageParser { private static final String SS_AGENT_PORT_KEY = "Port"; private static final String PASS_KEY = "Password"; private static final String USER_KEY = "User"; + private static final String CMD_EXEC = "cmd"; + private static final String IS_SLS_EXEC = "slsExec"; + private static final String SS_REQ_ID = "Id"; + private static final String SLS_FILE_LOCATION = "slsFile"; + private static final String SLS_NAME = "slsName"; + private static final String MINION_TO_APPLY = "applyTo"; private static final String LOCAL_PARAMETERS_OPT_KEY = "LocalParameters"; private static final String FILE_PARAMETERS_OPT_KEY = "FileParameters"; @@ -78,12 +86,11 @@ public class SaltstackMessageParser { * Accepts a map of strings and * a) validates if all parameters are appropriate (else, throws an exception) and * b) if correct returns a JSON object with appropriate key-value pairs to send to the server. - * + * <p> * Mandatory parameters, that must be in the supplied information to the Saltstack Adapter * 1. URL to connect to * 2. credentials for URL (assume username password for now) * 3. SaltState name - * */ public JSONObject reqMessage(Map<String, String> params) throws SvcLogicException { final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SALTSTATE_NAME_KEY, USER_KEY, PASS_KEY}; @@ -113,7 +120,8 @@ public class SaltstackMessageParser { */ public String reqPortResult(Map<String, String> params) throws SvcLogicException { - final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY, PASS_KEY}; + final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY, + PASS_KEY}; for (String key : mandatoryTestParams) { throwIfMissingMandatoryParam(params, key); @@ -128,7 +136,8 @@ public class SaltstackMessageParser { */ public String reqHostNameResult(Map<String, String> params) throws SvcLogicException { - final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY, PASS_KEY}; + final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY, + PASS_KEY}; for (String key : mandatoryTestParams) { throwIfMissingMandatoryParam(params, key); @@ -139,11 +148,119 @@ public class SaltstackMessageParser { /** * Method that validates that the Map has enough information * to query Saltstack server for a result. If so, it returns + * the appropriate request ID. + */ + public String reqId(Map<String, String> params) { + + if (params.get(SaltstackMessageParser.SS_REQ_ID) == null) { + return UUID.randomUUID().toString(); + } else if (params.get(SaltstackMessageParser.SS_REQ_ID).equalsIgnoreCase("")) { + return UUID.randomUUID().toString(); + } + return params.get(SaltstackMessageParser.SS_REQ_ID); + } + + /** + * Method that validates that the Map has enough information + * to query Saltstack server for a result. If so, it returns + * the appropriate command to execute. + */ + public String reqCmd(Map<String, String> params) throws SvcLogicException { + + final String[] mandatoryTestParams = {CMD_EXEC, IS_SLS_EXEC}; + + for (String key : mandatoryTestParams) { + throwIfMissingMandatoryParam(params, key); + } + + return params.get(SaltstackMessageParser.CMD_EXEC); + } + + /** + * Method that validates that the Map has enough information + * to query Saltstack server for a result. If so, it returns + * the appropriate SLS file location to execute. + */ + public String reqSlsFile(Map<String, String> params) throws SvcLogicException { + + final String[] mandatoryTestParams = {SLS_FILE_LOCATION}; + + for (String key : mandatoryTestParams) { + throwIfMissingMandatoryParam(params, key); + } + + return params.get(SaltstackMessageParser.SLS_FILE_LOCATION); + } + + /** + * Method that validates that the Map has enough information + * to query Saltstack server for a result. If so, it returns + * the appropriate SLS file location to execute. + */ + public String reqSlsName(Map<String, String> params) throws SvcLogicException { + + final String[] mandatoryTestParams = {SLS_NAME}; + + for (String key : mandatoryTestParams) { + throwIfMissingMandatoryParam(params, key); + } + String slsName = params.get(SaltstackMessageParser.SLS_NAME); + 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 to. + */ + public String reqApplyToDevices(Map<String, String> params) { + + if (params.get(SaltstackMessageParser.MINION_TO_APPLY) == null) { + return "*"; + } else if (params.get(SaltstackMessageParser.MINION_TO_APPLY).equalsIgnoreCase("")) { + return "*"; + } + return params.get(SaltstackMessageParser.MINION_TO_APPLY); + } + + /** + * Method that validates that the Map has enough information + * to query Saltstack server for a result. If so, it returns + * the appropriate IsSLSExec true or false. + */ + public boolean reqIsSLSExec(Map<String, String> params) throws SvcLogicException { + + final String[] mandatoryTestParams = {CMD_EXEC, IS_SLS_EXEC}; + + for (String key : mandatoryTestParams) { + throwIfMissingMandatoryParam(params, key); + } + + return params.get(SaltstackMessageParser.IS_SLS_EXEC).equalsIgnoreCase("true"); + } + + /** + * Method that validates that the Map has enough information + * to query Saltstack server for a result. If so, it returns * the appropriate Saltstack server login user name. */ public String reqUserNameResult(Map<String, String> params) throws SvcLogicException { - final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY, PASS_KEY}; + final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY, + PASS_KEY}; for (String key : mandatoryTestParams) { throwIfMissingMandatoryParam(params, key); @@ -158,7 +275,8 @@ public class SaltstackMessageParser { */ public String reqPasswordResult(Map<String, String> params) throws SvcLogicException { - final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY, PASS_KEY}; + final String[] mandatoryTestParams = {SS_AGENT_HOSTNAME_KEY, SS_AGENT_PORT_KEY, USER_KEY, + PASS_KEY}; for (String key : mandatoryTestParams) { throwIfMissingMandatoryParam(params, key); @@ -170,8 +288,10 @@ public class SaltstackMessageParser { * This method parses response from the Saltstack Server when we do a post * and returns an SaltstackResult object. */ - public SaltstackResult parseResponse(SvcLogicContext ctx, String pfx, SaltstackResult saltstackResult) { + public SaltstackResult parseResponse(SvcLogicContext ctx, String pfx, + SaltstackResult saltstackResult, boolean slsExec) { int code = saltstackResult.getStatusCode(); + boolean executionStatus = true, retCodeFound = false; if (code != SaltstackResultCodes.SUCCESS.getValue()) { return saltstackResult; } @@ -184,20 +304,34 @@ public class SaltstackMessageParser { in.close(); Map<String, String> mm = JsonParser.convertToProperties(str); if (mm != null) { - for (Map.Entry<String,String> entry : mm.entrySet()) { - ctx.setAttribute(pfx + entry.getKey(), entry.getValue()); - LOGGER.info("+++ " + pfx + entry.getKey() + ": [" + entry.getValue() + "]"); + for (Map.Entry<String, String> entry : mm.entrySet()) { + if (entry.getKey().contains("retcode")) { + retCodeFound = true; + if (!entry.getValue().equalsIgnoreCase("0")) { + executionStatus = false; + } + } + ctx.setAttribute(pfx + "." + entry.getKey(), entry.getValue()); + LOGGER.info("+++ " + pfx + "." + entry.getKey() + ": [" + entry.getValue() + "]"); } } - } catch (FileNotFoundException e){ - return new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "Error parsing response file = " - + saltstackResult.getOutputFileName() + ". Error = " + e.getMessage()); + } catch (FileNotFoundException e) { + return new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "error parsing response file " + + saltstackResult.getOutputFileName() + " : " + e.getMessage()); } catch (JSONException e) { LOGGER.info("Output not in JSON format"); return putToProperties(ctx, pfx, saltstackResult); } catch (Exception e) { - return new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "Error parsing response file = " - + saltstackResult.getOutputFileName() + ". Error = " + e.getMessage()); + return new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "error parsing response file " + + saltstackResult.getOutputFileName() + " : " + e.getMessage()); + } + if (slsExec) { + if (!retCodeFound) + return new SaltstackResult(SaltstackResultCodes.COMMAND_EXEC_FAILED_STATUS.getValue(), + "error in parsing response Json after SLS file execution in server"); + if (!executionStatus) + return new SaltstackResult(SaltstackResultCodes.COMMAND_EXEC_FAILED_STATUS.getValue(), + "error in parsing response Json after SLS file execution in server"); } saltstackResult.setStatusCode(SaltstackResultCodes.FINAL_SUCCESS.getValue()); return saltstackResult; @@ -222,8 +356,10 @@ public class SaltstackMessageParser { saltstackResult = new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "Error parsing response file = " + saltstackResult.getOutputFileName() + ". Error = " + e.getMessage()); } + saltstackResult.setStatusCode(SaltstackResultCodes.FINAL_SUCCESS.getValue()); return saltstackResult; } + /** * This method parses response from an Saltstack server when we do a GET for a result * and returns an SaltstackResult object. @@ -235,14 +371,14 @@ public class SaltstackMessageParser { try { JSONObject postResponse = new JSONObject(input); saltstackResult = parseGetResponseNested(saltstackResult, postResponse); - } catch (JSONException e) { + } catch (Exception e) { saltstackResult = new SaltstackResult(SaltstackResultCodes.INVALID_COMMAND.getValue(), - "Error parsing response = " + input + ". Error = " + e.getMessage(), "", -1); + "Error parsing response = " + input + ". Error = " + e.getMessage(), "", -1); } return saltstackResult; } - private SaltstackResult parseGetResponseNested(SaltstackResult saltstackResult, JSONObject postRsp) throws SvcLogicException { + private SaltstackResult parseGetResponseNested(SaltstackResult saltstackResult, JSONObject postRsp) throws SvcLogicException { int codeStatus = postRsp.getInt(STATUS_CODE_KEY); String messageStatus = postRsp.getString(STATUS_MESSAGE_KEY); @@ -253,7 +389,7 @@ public class SaltstackMessageParser { if (!valCode) { throw new SvcLogicException("Invalid FinalResponse code = " + codeStatus + " received. MUST be one of " - + SaltstackResultCodes.CODE.getValidCodes(SaltstackResultCodes.FINALRESPONSE.getValue())); + + SaltstackResultCodes.CODE.getValidCodes(SaltstackResultCodes.FINALRESPONSE.getValue())); } saltstackResult.setStatusCode(codeStatus); @@ -285,7 +421,7 @@ public class SaltstackMessageParser { if (subCode != 200 || !message.equals("SUCCESS")) { finalCode = SaltstackResultCodes.REQ_FAILURE.getValue(); } - } catch (JSONException e) { + } catch (Exception e) { saltstackResult.setStatusCode(SaltstackResultCodes.INVALID_RESPONSE.getValue()); saltstackResult.setStatusMessage(String.format( "Error processing response message = %s from host %s", results.getString(host), host)); @@ -312,10 +448,10 @@ public class SaltstackMessageParser { //@formatter:off params.entrySet() - .stream() - .filter(entry -> optionalParamsSet.contains(entry.getKey())) - .filter(entry -> !Strings.isNullOrEmpty(entry.getValue())) - .forEach(entry -> parseOptionalParam(entry, jsonPayload)); + .stream() + .filter(entry -> optionalParamsSet.contains(entry.getKey())) + .filter(entry -> !Strings.isNullOrEmpty(entry.getValue())) + .forEach(entry -> parseOptionalParam(entry, jsonPayload)); //@formatter:on } diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java index 05873024..f6ea0b42 100644 --- a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java +++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java @@ -24,10 +24,8 @@ package org.onap.ccsdk.sli.adaptors.saltstack.model; -import java.io.OutputStream; - /** - * Simple class to store code and message returned by POST/GET to an Saltstack Server + * Simple class to store code and message returned by POST/GET to an Saltstack Server */ public class SaltstackResult { @@ -54,44 +52,44 @@ public class SaltstackResult { sshExitStatus = sshCode; } - public void setStatusCode(int code) { - this.statusCode = code; - } - - public void setStatusMessage(String message) { - this.statusMessage = message; - } - - public void setResults(String results) { - this.results = results; - } - void set(int code, String message, String results) { this.statusCode = code; this.statusMessage = message; this.results = results; } - public void setOutputFileName (String out) { - this.out = out; - } - public String getOutputFileName() { return out; } + public void setOutputFileName(String out) { + this.out = out; + } + public int getStatusCode() { return this.statusCode; } + public void setStatusCode(int code) { + this.statusCode = code; + } + public String getStatusMessage() { return this.statusMessage; } + public void setStatusMessage(String message) { + this.statusMessage = message; + } + public String getResults() { return this.results; } + public void setResults(String results) { + this.results = results; + } + public int getSshExitStatus() { return sshExitStatus; } diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java index ab88c212..32871ff0 100644 --- a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java +++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java @@ -52,6 +52,8 @@ public enum SaltstackResultCodes { PENDING(100), REJECTED(101), FINAL_SUCCESS(200), + CHECK_CTX_FOR_CMD_SUCCESS(250), + COMMAND_EXEC_FAILED_STATUS(670), REQ_FAILURE(401), MESSAGE(1), CODE(0), @@ -67,7 +69,9 @@ public enum SaltstackResultCodes { SaltstackResultCodes(int value) { this.value = value; - }; + } + + ; public int getValue() { return value; diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java index 9737efd3..ecb36fb8 100644 --- a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java +++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java @@ -32,23 +32,21 @@ package org.onap.ccsdk.sli.adaptors.saltstack.model; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.apache.commons.lang.StringUtils; +import org.json.JSONObject; + import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; -import org.json.JSONException; -import org.json.JSONObject; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; public class SaltstackServerEmulator { - private final EELFLogger logger = EELFManager.getInstance().getLogger(SaltstackServerEmulator.class); - - private static final String SALTSTATE_NAME = "SaltStateName"; + private static final String SALTSTATE_FILE_NAME = "fileName"; private static final String STATUS_CODE = "StatusCode"; private static final String STATUS_MESSAGE = "StatusMessage"; - + private final EELFLogger logger = EELFManager.getInstance().getLogger(SaltstackServerEmulator.class); private String saltStateName = "test_saltState.yaml"; /** @@ -62,9 +60,13 @@ public class SaltstackServerEmulator { try { if (params.get("Test") == "fail") { - result = rejectRequest(result, "Must provide a valid Id"); + result = rejectRequest(result, "Mocked: Fail"); } else { - result = acceptRequest(result); + String fileName = params.get(SALTSTATE_FILE_NAME); + if (fileName == null) + result = acceptRequest(result, ""); + else + result = acceptRequest(result, fileName); } } catch (Exception e) { logger.error("JSONException caught", e); @@ -74,41 +76,10 @@ public class SaltstackServerEmulator { } /** - * Method that emulates the response from an Saltstack Server - * when presented with a request to execute a saltState - * Returns an saltstack object result. The response code is always the ssh code 200 (i.e connection successful) - * payload is json string as would be sent back by Saltstack Server - **/ - //TODO: This class is to be altered completely based on the SALTSTACK server communicaiton. - public SaltstackResult Connect(Map<String, String> params) { - SaltstackResult result = new SaltstackResult(); - - try { - // Request must be a JSON object - - JSONObject message = new JSONObject(); - if (message.isNull("Id")) { - rejectRequest(result, "Must provide a valid Id"); - } else if (message.isNull(SALTSTATE_NAME)) { - rejectRequest(result, "Must provide a saltState Name"); - } else if (!message.getString(SALTSTATE_NAME).equals(saltStateName)) { - rejectRequest(result, "SaltState " + message.getString(SALTSTATE_NAME) + " not found in catalog"); - } else { - acceptRequest(result); - } - } catch (JSONException e) { - logger.error("JSONException caught", e); - rejectRequest(result, e.getMessage()); - } - return result; - } - - /** * Method to emulate response from an Saltstack * Server when presented with a GET request * Returns an saltstack object result. The response code is always the ssh code 200 (i.e connection successful) * payload is json string as would be sent back by Saltstack Server - * **/ public SaltstackResult Execute(String agentUrl) { @@ -149,9 +120,10 @@ public class SaltstackServerEmulator { return result; } - private SaltstackResult acceptRequest(SaltstackResult result) { + private SaltstackResult acceptRequest(SaltstackResult result, String fileName) { result.setStatusCode(SaltstackResultCodes.SUCCESS.getValue()); result.setStatusMessage("Success"); + result.setOutputFileName(fileName); return result; } }
\ No newline at end of file diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestConnectionBuilder.java b/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestConnectionBuilder.java new file mode 100644 index 00000000..d9a38414 --- /dev/null +++ b/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestConnectionBuilder.java @@ -0,0 +1,174 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.impl; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.ccsdk.sli.adaptors.saltstack.impl.ConnectionBuilder; +import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult; +import org.onap.ccsdk.sli.core.sli.SvcLogicContext; +import org.onap.ccsdk.sli.core.sli.SvcLogicException; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + + +public class TestConnectionBuilder { + + private final String PENDING = "100"; + private final String SUCCESS = "400"; + private String message = "{\"Results\":{\"192.168.1.10\":{\"Id\":\"101\",\"StatusCode\":200,\"StatusMessage\":\"SUCCESS\"}},\"StatusCode\":200,\"StatusMessage\":\"FINISHED\"}"; + + private ConnectionBuilder connBuilder; + private String TestId; + private boolean testMode = true; + private Map<String, String> params; + private SvcLogicContext svcContext; + + + @Before + public void setup() throws IllegalArgumentException { + testMode = true; + svcContext = new SvcLogicContext(); + String HostName = "test"; + String Port = "10"; + String User = "test"; + String Password = "test"; + connBuilder = new ConnectionBuilder(HostName, Port, User, Password); + + params = new HashMap<>(); + params.put("AgentUrl", "https://192.168.1.1"); + params.put("User", "test"); + params.put("Password", "test"); + } + + @After + public void tearDown() { + testMode = false; + connBuilder = null; + params = null; + svcContext = null; + } + + @Test + public void reqExecCommand_exitStatus255() { + + int exitStatus = 255; + String errFilePath = "src/test/resources/test.json"; + String command = "test"; + + SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command); + int status = result.getStatusCode(); + assertEquals(698, status); + } + + @Test + public void reqExecCommand_exitStatus1() { + + int exitStatus = 1; + String errFilePath = "src/test/resources/test.json"; + String command = "test"; + + SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command); + int status = result.getStatusCode(); + assertEquals(698, status); + } + + @Test + public void reqExecCommand_exitStatus5() { + + int exitStatus = 5; + String errFilePath = "src/test/resources/test.json"; + String command = "test"; + + SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command); + int status = result.getStatusCode(); + assertEquals(613, status); + } + + @Test + public void reqExecCommand_exitStatus65() { + + int exitStatus = 65; + String errFilePath = "src/test/resources/test.json"; + String command = "test"; + + SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command); + int status = result.getStatusCode(); + assertEquals(613, status); + } + + @Test + public void reqExecCommand_exitStatus67() { + + int exitStatus = 5; + String errFilePath = "src/test/resources/test.json"; + String command = "test"; + + SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command); + int status = result.getStatusCode(); + assertEquals(613, status); + } + + @Test + public void reqExecCommand_exitStatus73() { + + int exitStatus = 65; + String errFilePath = "src/test/resources/test.json"; + String command = "test"; + + SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command); + int status = result.getStatusCode(); + assertEquals(613, status); + } + + @Test + public void reqExecCommand_exitStatusUnknown() { + + int exitStatus = 5121; + String errFilePath = "src/test/resources/test.json"; + String command = "test"; + + SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command); + int status = result.getStatusCode(); + assertEquals(699, status); + } + + @Test + public void reqExecCommand_exitStatusNoFile() { + + int exitStatus = 65; + String errFilePath = "src/test/resource/test.json"; + String command = "test"; + + SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command); + int status = result.getStatusCode(); + assertEquals(613, status); + } +} diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestSaltstackAdapterImpl.java b/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestSaltstackAdapterImpl.java index d7b33038..d60059e4 100644 --- a/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestSaltstackAdapterImpl.java +++ b/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestSaltstackAdapterImpl.java @@ -80,10 +80,10 @@ public class TestSaltstackAdapterImpl { params.put("User", "test"); params.put("Password", "test"); params.put("Test", "fail"); - adapter.reqExecCommand(params, svcContext); - String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); - TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id"); - assertEquals("101", status); + adapter.reqExecCommand(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("101", status); } @Test(expected = SvcLogicException.class) @@ -96,7 +96,7 @@ public class TestSaltstackAdapterImpl { params.put("Test", "fail"); adapter.reqExecCommand(params, svcContext); String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); - TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); assertEquals("101", status); } @@ -110,7 +110,7 @@ public class TestSaltstackAdapterImpl { params.put("Test", "fail"); adapter.reqExecCommand(params, svcContext); String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); - TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); assertEquals("101", status); } @@ -124,7 +124,7 @@ public class TestSaltstackAdapterImpl { params.put("Test", "fail"); adapter.reqExecCommand(params, svcContext); String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); - TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); assertEquals("101", status); } @@ -138,7 +138,7 @@ public class TestSaltstackAdapterImpl { params.put("Test", "fail"); adapter.reqExecCommand(params, svcContext); String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); - TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); assertEquals("101", status); } @@ -149,24 +149,25 @@ public class TestSaltstackAdapterImpl { params.put("Test", "fail"); adapter.reqExecCommand(params, svcContext); String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); - TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); assertEquals("101", status); } @Test(expected = SvcLogicException.class) - public void reqExecCommand_shouldSetSuccess() throws SvcLogicException, + public void reqExecCommand_NoResponseFile() throws SvcLogicException, IllegalStateException, IllegalArgumentException { - params.put("PlaybookName", "test_playbook.yaml"); params.put("HostName", "test"); params.put("Port", "10"); params.put("User", "test"); params.put("Password", "test"); params.put("Test", "success"); + params.put("cmd", "test"); + params.put("slsExec", "false"); try { adapter.reqExecCommand(params, svcContext); String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); - TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); assertEquals("400", status); } catch (NullPointerException e) { fail(e.getMessage() + " Unknown exception encountered "); @@ -174,10 +175,9 @@ public class TestSaltstackAdapterImpl { } @Test(expected = SvcLogicException.class) - public void reqExecCommand_shouldSetSuccessWithRetry() throws SvcLogicException, + public void reqExecCommand_NoResponseFileWithRetry() throws SvcLogicException, IllegalStateException, IllegalArgumentException { - params.put("PlaybookName", "test_playbook.yaml"); params.put("HostName", "test"); params.put("Port", "10"); params.put("User", "test"); @@ -185,10 +185,12 @@ public class TestSaltstackAdapterImpl { params.put("Test", "success"); params.put("retryDelay", "10"); params.put("retryCount", "10"); + params.put("cmd", "test"); + params.put("slsExec", "false"); try { adapter.reqExecCommand(params, svcContext); String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); - TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); assertEquals("400", status); } catch (NullPointerException e) { fail(e.getMessage() + " Unknown exception encountered "); @@ -196,10 +198,9 @@ public class TestSaltstackAdapterImpl { } @Test(expected = SvcLogicException.class) - public void reqExecCommand_shouldSetSuccessWithRetryZero() throws SvcLogicException, + public void reqExecCommand_NoResponseFileWithRetryZero() throws SvcLogicException, IllegalStateException, IllegalArgumentException { - params.put("PlaybookName", "test_playbook.yaml"); params.put("HostName", "test"); params.put("Port", "10"); params.put("User", "test"); @@ -207,10 +208,12 @@ public class TestSaltstackAdapterImpl { params.put("Test", "success"); params.put("retryDelay", "0"); params.put("retryCount", "0"); + params.put("cmd", "test"); + params.put("slsExec", "false"); try { adapter.reqExecCommand(params, svcContext); String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); - TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); assertEquals("400", status); } catch (NullPointerException e) { fail(e.getMessage() + " Unknown exception encountered "); @@ -218,10 +221,9 @@ public class TestSaltstackAdapterImpl { } @Test(expected = SvcLogicException.class) - public void reqExecCommand_shouldSetSuccessWithNoRetry() throws SvcLogicException, + public void reqExecCommand_NoResponseFileWithNoRetry() throws SvcLogicException, IllegalStateException, IllegalArgumentException { - params.put("PlaybookName", "test_playbook.yaml"); params.put("HostName", "test"); params.put("Port", "10"); params.put("User", "test"); @@ -229,38 +231,572 @@ public class TestSaltstackAdapterImpl { params.put("Test", "success"); params.put("retryDelay", "-1"); params.put("retryCount", "-1"); + params.put("cmd", "test"); + params.put("slsExec", "false"); + try { adapter.reqExecCommand(params, svcContext); String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); - TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.Id"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); assertEquals("400", status); } catch (NullPointerException e) { fail(e.getMessage() + " Unknown exception encountered "); } } - @Test - public void reqExecSLS_shouldSetSuccess() throws IllegalStateException, IllegalArgumentException { - - params.put("Id", "100"); - for (String ukey : params.keySet()) { - System.out.println(String.format("Saltstack Parameter %s = %s", ukey, params.get(ukey))); - } + @Test(expected = SvcLogicException.class) + public void reqExecCommand_shouldSetFailure() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("cmd", "test"); + params.put("slsExec", "test"); + params.put("Test", "fail"); try { - adapter.reqExecSLS(params, svcContext); - String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); - //assertEquals(SUCCESS, status); - assertEquals(null, status); - } catch (SvcLogicException e) { + adapter.reqExecCommand(params, svcContext); String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); - fail(e.getMessage() + " Code = " + status); - } catch (Exception e) { + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("400", status); + } catch (NullPointerException e) { fail(e.getMessage() + " Unknown exception encountered "); } } @Test + public void reqExecCommand_shouldSetSuccessNoSLS() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("fileName", "src/test/resources/test.json"); + params.put("Id", "test1"); + params.put("cmd", "test"); + params.put("slsExec", "false"); + + adapter.reqExecCommand(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("250", status); + assertEquals(TestId, "test1"); + } + + @Test + public void reqExecCommand_shouldSetSuccessExecSLS() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("fileName", "src/test/resources/test-sls.json"); + params.put("Id", "test1"); + params.put("cmd", "test"); + params.put("slsExec", "true"); + + adapter.reqExecCommand(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("200", status); + assertEquals(TestId, "test1"); + } + + @Test(expected = SvcLogicException.class) + public void reqExecCommand_shouldSetFailExecSLS() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("fileName", "src/test/resources/test.json"); + params.put("Id", "test1"); + params.put("cmd", "test"); + params.put("slsExec", "true"); + + adapter.reqExecCommand(params, svcContext); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals(TestId, "test1"); + } + + @Test + public void reqExecCommand_shouldSetSuccessFileTxt() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("fileName", "src/test/resources/test.txt"); + params.put("Id", "txt"); + params.put("cmd", "test"); + params.put("slsExec", "false"); + + adapter.reqExecCommand(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("250", status); + assertEquals(TestId, "txt"); + } + + @Test + public void reqExecCommand_shouldSetSuccessFileNoExtension() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("fileName", "src/test/resources/test"); + params.put("Id", "txt"); + params.put("cmd", "test"); + params.put("slsExec", "false"); + + adapter.reqExecCommand(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("250", status); + assertEquals(TestId, "txt"); + } + + @Test + public void reqExecCommand_shouldSetSuccessFileInvalidJson() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("fileName", "src/test/resources/test-invalid.json"); + params.put("Id", "test1"); + params.put("cmd", "test"); + params.put("slsExec", "false"); + + adapter.reqExecCommand(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("250", status); + } + + @Test(expected = SvcLogicException.class) + public void reqExecCommand_shouldSetFailFileInvalidFile() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("fileName", "src/test/resources/test-none.json"); + params.put("Id", "test1"); + + adapter.reqExecCommand(params, svcContext); + } + + @Test + public void reqExecCommand_shouldSetSuccessFileJsonNoReqID() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("fileName", "src/test/resources/test.json"); + params.put("cmd", "test"); + params.put("slsExec", "false"); + + adapter.reqExecCommand(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("250", status); + } + + @Test + public void reqExecSLSFile_shouldSetSuccessJson() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("slsFile", "src/test/resources/test.sls"); + params.put("fileName", "src/test/resources/test-sls.json"); + params.put("Id", "test1"); + params.put("cmd", "test"); + + adapter.reqExecSLSFile(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("200", status); + assertEquals(TestId, "test1"); + } + + @Test(expected = SvcLogicException.class) + public void reqExecSLSFile_NoSLSfile() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("slsFile", "src/test/resources/test-none.sls"); + params.put("fileName", "src/test/resources/test-sls.json"); + params.put("Id", "test1"); + + adapter.reqExecSLSFile(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals(TestId, "test1"); + } + + @Test(expected = SvcLogicException.class) + public void reqExecSLSFile_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"); + + adapter.reqExecSLSFile(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals(TestId, "test1"); + } + + @Test(expected = SvcLogicException.class) + public void reqExecSLSFile_NoResponsefile() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("slsFile", "src/test/resources/test.json"); + params.put("fileName", "src/test/resources/test-none.json"); + params.put("Id", "test1"); + + adapter.reqExecSLSFile(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals(TestId, "test1"); + } + + @Test(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("applyTo", "minion1"); + + adapter.reqExecSLSFile(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("200", status); + assertEquals(TestId, "test1"); + } + + @Test + 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("applyTo", "minion1"); + + adapter.reqExecSLSFile(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("200", status); + assertEquals(TestId, "test1"); + } + + @Test(expected = SvcLogicException.class) + public void reqExecSLSFile_WithMinionNoSLSfile() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("slsFile", "src/test/resources/test-none.json"); + params.put("fileName", "src/test/resources/test-sls.json"); + params.put("Id", "test1"); + params.put("applyTo", "minion1"); + + adapter.reqExecSLSFile(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals(TestId, "test1"); + } + + @Test(expected = SvcLogicException.class) + public void reqExecSLSFile_WithMinionNoResponsefile() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("slsFile", "src/test/resources/test.json"); + params.put("fileName", "src/test/resources/test-none.json"); + params.put("Id", "test1"); + params.put("applyTo", "minion1"); + + adapter.reqExecSLSFile(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals(TestId, "test1"); + } + + @Test + public void reqExecSLSFile_WithAllMinionSetSuccessJson() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("slsFile", "src/test/resources/test.sls"); + params.put("fileName", "src/test/resources/test-sls.json"); + params.put("Id", "test1"); + params.put("cmd", "test"); + params.put("applyTo", "*"); + + adapter.reqExecSLSFile(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("200", status); + assertEquals(TestId, "test1"); + } + + @Test(expected = SvcLogicException.class) + public void reqExecSLSFile_WithAllMinionNoSLSfile() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("slsFile", "src/test/resources/test-none.json"); + params.put("fileName", "src/test/resources/test-sls.json"); + params.put("Id", "test1"); + params.put("applyTo", "*"); + + adapter.reqExecSLSFile(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals(TestId, "test1"); + } + + @Test(expected = SvcLogicException.class) + public void reqExecSLSFile_WithAllMinionNoResponsefile() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + + params.put("HostName", "test"); + params.put("Port", "10"); + params.put("User", "test"); + params.put("Password", "test"); + params.put("Test", "success"); + params.put("slsFile", "src/test/resources/test.json"); + params.put("fileName", "src/test/resources/test-none.json"); + params.put("Id", "test1"); + params.put("applyTo", "*"); + + adapter.reqExecSLSFile(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals(TestId, "test1"); + } + + + @Test + public void 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"); + + adapter.reqExecSLS(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("200", status); + assertEquals(TestId, "test1"); + } + + @Test + 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"); + + adapter.reqExecSLS(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("200", status); + assertEquals(TestId, "test1"); + } + + @Test(expected = SvcLogicException.class) + public void 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"); + + adapter.reqExecSLS(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals(TestId, "test1"); + } + + + @Test + public void 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("applyTo", "minion1"); + + adapter.reqExecSLS(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("200", status); + assertEquals(TestId, "test1"); + } + + + @Test(expected = SvcLogicException.class) + public void 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("applyTo", "minion1"); + + adapter.reqExecSLS(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals(TestId, "test1"); + } + + @Test + public void 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("applyTo", "*"); + + adapter.reqExecSLS(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals("200", status); + assertEquals(TestId, "test1"); + } + + + @Test(expected = SvcLogicException.class) + public void 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("applyTo", "*"); + + adapter.reqExecSLS(params, svcContext); + String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code"); + TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id"); + assertEquals(TestId, "test1"); + } + + + @Test public void reqExecLog_shouldSetMessage() throws IllegalStateException, IllegalArgumentException { params.put("Id", "101"); diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestSaltstackAdapterPropertiesProviderImpl.java b/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestSaltstackAdapterPropertiesProviderImpl.java new file mode 100644 index 00000000..92759183 --- /dev/null +++ b/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/impl/TestSaltstackAdapterPropertiesProviderImpl.java @@ -0,0 +1,323 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.impl; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapterPropertiesProvider; +import org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdapterImpl; +import org.onap.ccsdk.sli.core.sli.SvcLogicContext; +import org.onap.ccsdk.sli.core.sli.SvcLogicException; + +import java.util.Properties; + +import static org.junit.Assert.assertEquals; + +public class TestSaltstackAdapterPropertiesProviderImpl { + private final String PENDING = "100"; + private final String SUCCESS = "400"; + private String message = "{\"Results\":{\"192.168.1.10\":{\"Id\":\"101\",\"StatusCode\":200,\"StatusMessage\":\"SUCCESS\"}},\"StatusCode\":200,\"StatusMessage\":\"FINISHED\"}"; + + private SaltstackAdapterImpl adapter; + private Properties params; + private SvcLogicContext svcContext; + + + @Before + public void setup() throws IllegalArgumentException { + params = new Properties(); + } + + @After + public void tearDown() { + adapter = null; + params = null; + svcContext = null; + } + + @Test(expected = SvcLogicException.class) + public void reqExecCommand_setPropertiesBasicPortNull() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.clientType", "BASIC"); + params.put("User", "test"); + params.put("Password", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test(expected = SvcLogicException.class) + public void reqExecCommand_setPropertiesBasicPortString() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.clientType", "BASIC"); + params.put("org.onap.appc.adapter.saltstack.host", "test"); + params.put("org.onap.appc.adapter.saltstack.port", "test"); + params.put("org.onap.appc.adapter.saltstack.userName", "test"); + params.put("org.onap.appc.adapter.saltstack.userPasswd", "test"); + params.put("org.onap.appc.adapter.saltstack.sshKey", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test + public void reqExecCommand_setPropertiesBasicSuccess() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.clientType", "BASIC"); + params.put("org.onap.appc.adapter.saltstack.host", "test"); + params.put("org.onap.appc.adapter.saltstack.port", "10"); + params.put("org.onap.appc.adapter.saltstack.userName", "test"); + params.put("org.onap.appc.adapter.saltstack.userPasswd", "test"); + params.put("org.onap.appc.adapter.saltstack.sshKey", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test(expected = SvcLogicException.class) + public void reqExecCommand_setPropertiesSSH_CERTPortNull() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.clientType", "SSH_CERT"); + params.put("User", "test"); + params.put("Password", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test(expected = SvcLogicException.class) + public void reqExecCommand_setPropertiesSSH_CERTPortString() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.clientType", "SSH_CERT"); + params.put("org.onap.appc.adapter.saltstack.host", "test"); + params.put("org.onap.appc.adapter.saltstack.port", "test"); + params.put("org.onap.appc.adapter.saltstack.userName", "test"); + params.put("org.onap.appc.adapter.saltstack.userPasswd", "test"); + params.put("org.onap.appc.adapter.saltstack.sshKey", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test + public void reqExecCommand_setPropertiesSSH_CERTSuccess() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.clientType", "SSH_CERT"); + params.put("org.onap.appc.adapter.saltstack.host", "test"); + params.put("org.onap.appc.adapter.saltstack.port", "10"); + params.put("org.onap.appc.adapter.saltstack.userName", "test"); + params.put("org.onap.appc.adapter.saltstack.userPasswd", "test"); + params.put("org.onap.appc.adapter.saltstack.sshKey", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test(expected = SvcLogicException.class) + public void reqExecCommand_setPropertiesBOTHPortNull() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.clientType", "BOTH"); + params.put("User", "test"); + params.put("Password", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test(expected = SvcLogicException.class) + public void reqExecCommand_setPropertiesBOTHPortString() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.clientType", "BOTH"); + params.put("org.onap.appc.adapter.saltstack.host", "test"); + params.put("org.onap.appc.adapter.saltstack.port", "test"); + params.put("org.onap.appc.adapter.saltstack.userName", "test"); + params.put("org.onap.appc.adapter.saltstack.userPasswd", "test"); + params.put("org.onap.appc.adapter.saltstack.sshKey", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test + public void reqExecCommand_setPropertiesBOTHSuccess() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.clientType", "BOTH"); + params.put("org.onap.appc.adapter.saltstack.host", "test"); + params.put("org.onap.appc.adapter.saltstack.port", "10"); + params.put("org.onap.appc.adapter.saltstack.userName", "test"); + params.put("org.onap.appc.adapter.saltstack.userPasswd", "test"); + params.put("org.onap.appc.adapter.saltstack.sshKey", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test + public void reqExecCommand_setPropertiesNonePortNull() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.clientType", "NONE"); + params.put("User", "test"); + params.put("Password", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test + public void reqExecCommand_setPropertiesNonePortString() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.clientType", "NONE"); + params.put("org.onap.appc.adapter.saltstack.host", "test"); + params.put("org.onap.appc.adapter.saltstack.port", "test"); + params.put("org.onap.appc.adapter.saltstack.userName", "test"); + params.put("org.onap.appc.adapter.saltstack.userPasswd", "test"); + params.put("org.onap.appc.adapter.saltstack.sshKey", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test + public void reqExecCommand_setPropertiesNoneSuccess() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.clientType", "NONE"); + params.put("org.onap.appc.adapter.saltstack.host", "test"); + params.put("org.onap.appc.adapter.saltstack.port", "10"); + params.put("org.onap.appc.adapter.saltstack.userName", "test"); + params.put("org.onap.appc.adapter.saltstack.userPasswd", "test"); + params.put("org.onap.appc.adapter.saltstack.sshKey", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + + + @Test + public void reqExecCommand_setPropertiesElsePortNull() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("User", "test"); + params.put("Password", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test + public void reqExecCommand_setPropertiesElsePortString() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.host", "test"); + params.put("org.onap.appc.adapter.saltstack.port", "test"); + params.put("org.onap.appc.adapter.saltstack.userName", "test"); + params.put("org.onap.appc.adapter.saltstack.userPasswd", "test"); + params.put("org.onap.appc.adapter.saltstack.sshKey", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + } + + @Test + public void reqExecCommand_setPropertiesElseSuccess() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + params.put("org.onap.appc.adapter.saltstack.host", "test"); + params.put("org.onap.appc.adapter.saltstack.port", "10"); + params.put("org.onap.appc.adapter.saltstack.userName", "test"); + params.put("org.onap.appc.adapter.saltstack.userPasswd", "test"); + params.put("org.onap.appc.adapter.saltstack.sshKey", "test"); + SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() { + @Override + public Properties getProperties() { + return params; + } + }; + adapter = new SaltstackAdapterImpl(propProvider); + String adaptorName = adapter.getAdapterName(); + assertEquals("Saltstack Adapter", adaptorName); + adapter.setExecTimeout(10); + } + + @Test + public void reqExecCommand_setPropertiesDefault() throws SvcLogicException, + IllegalStateException, IllegalArgumentException { + adapter = new SaltstackAdapterImpl(); + } +} diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/model/TestJsonParser.java b/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/model/TestJsonParser.java new file mode 100644 index 00000000..ae13da6c --- /dev/null +++ b/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/appc/adapter/model/TestJsonParser.java @@ -0,0 +1,74 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.model; + +import org.codehaus.jettison.json.JSONException; +import org.junit.Test; +import org.onap.ccsdk.sli.core.sli.SvcLogicException; +import org.onap.ccsdk.sli.adaptors.saltstack.model.JsonParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class TestJsonParser { + + private static final Logger log = LoggerFactory.getLogger(TestJsonParser.class); + + @Test + public void test() throws SvcLogicException, IOException, JSONException { + BufferedReader in = new BufferedReader( + new InputStreamReader(ClassLoader.getSystemResourceAsStream("test.json")) + ); + StringBuilder b = new StringBuilder(); + String line; + while ((line = in.readLine()) != null) + b.append(line).append('\n'); + + Map<String, String> mm = JsonParser.convertToProperties(b.toString()); + + logProperties(mm); + + in.close(); + } + + @Test(expected = NullPointerException.class) + public void testNullString() throws SvcLogicException, JSONException { + JsonParser.convertToProperties(null); + } + + private void logProperties(Map<String, String> mm) { + List<String> ll = new ArrayList<>(); + for (Object o : mm.keySet()) + ll.add((String) o); + Collections.sort(ll); + log.info("Properties:"); + for (String name : ll) + log.info("--- {}: {}", name, mm.get(name)); + } +} diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test new file mode 100644 index 00000000..dec578bd --- /dev/null +++ b/saltstack-adapter/saltstack-adapter-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/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-invalid.json b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-invalid.json new file mode 100644 index 00000000..53158cad --- /dev/null +++ b/saltstack-adapter/saltstack-adapter-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/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-sls.json b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-sls.json new file mode 100644 index 00000000..bc1c10c8 --- /dev/null +++ b/saltstack-adapter/saltstack-adapter-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/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.json b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.json new file mode 100644 index 00000000..cd76486a --- /dev/null +++ b/saltstack-adapter/saltstack-adapter-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/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.sls b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.sls new file mode 100644 index 00000000..cd76486a --- /dev/null +++ b/saltstack-adapter/saltstack-adapter-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/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.txt b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.txt new file mode 100644 index 00000000..dec578bd --- /dev/null +++ b/saltstack-adapter/saltstack-adapter-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 |