summaryrefslogtreecommitdiffstats
path: root/plugins/sshapi-call-node/provider/src
diff options
context:
space:
mode:
authorJessica Wagantall <jwagantall@linuxfoundation.org>2020-12-01 11:33:35 -0800
committerJessica Wagantall <jwagantall@linuxfoundation.org>2020-12-01 11:33:35 -0800
commit96a9aafdff7813324bc8a8ba1e743683e251dde6 (patch)
tree644c6837ab58ed21fb05f4bf988dc392875b9f8d /plugins/sshapi-call-node/provider/src
parenta0e97e71a49a8b54fddf8fb004b32f202f114011 (diff)
Migrate files from sli-plugins
Migrate sli-plugins repo into new directory "plugins". Signed-off-by: Jessica Wagantall <jwagantall@linuxfoundation.org>
Diffstat (limited to 'plugins/sshapi-call-node/provider/src')
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java283
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/AuthType.java41
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Format.java39
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java93
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Parameters.java45
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/ParseParam.java275
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlJsonUtil.java389
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlParser.java176
-rw-r--r--plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-context.xml47
-rw-r--r--plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-osgi-context.xml34
-rwxr-xr-xplugins/sshapi-call-node/provider/src/main/resources/OSGI-INF/blueprint/sshapi-call-node-blueprint.xml16
-rwxr-xr-xplugins/sshapi-call-node/provider/src/main/resources/org/opendaylight/blueprint/sshapi-call-node-blueprint.xml16
-rw-r--r--plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestJsonParser.java85
-rw-r--r--plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestSshApiCallNode.java330
-rw-r--r--plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlJsonUtil.java264
-rw-r--r--plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlParser.java123
-rw-r--r--plugins/sshapi-call-node/provider/src/test/resources/invalidlength.xml49
-rw-r--r--plugins/sshapi-call-node/provider/src/test/resources/test-template.json57
-rw-r--r--plugins/sshapi-call-node/provider/src/test/resources/test.json51
-rw-r--r--plugins/sshapi-call-node/provider/src/test/resources/test.xml184
-rw-r--r--plugins/sshapi-call-node/provider/src/test/resources/test3.xml82
21 files changed, 2679 insertions, 0 deletions
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java
new file mode 100644
index 000000000..146188fb9
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java
@@ -0,0 +1,283 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * =============================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ * ================================================================================
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Map;
+
+import org.onap.appc.adapter.ssh.SshAdapter;
+import org.onap.appc.adapter.ssh.SshConnection;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.AuthType;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.Parameters;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.ParseParam;
+
+
+public class SshApiCallNode implements SvcLogicJavaPlugin {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger();
+
+ /**
+ * Output parameter - SSH command execution status.
+ */
+ private String PARAM_OUT_status = "sshApi.call.node.status";
+
+ /**
+ * Output parameter - content of SSH command stdout.
+ */
+ private String PARAM_OUT_stdout = "sshApi.call.node.stdout";
+
+ /**
+ * Output parameter - content of SSH command stderr.
+ */
+ private String PARAM_OUT_stderr = "sshApi.call.node.stderr";
+
+ /**
+ * Testing parameter - content of mocked SSH.
+ */
+ private boolean PARAM_TEST_MODE = false;
+ private String PARAM_OUT_MESSAGE = "TestOut";
+
+
+ /**
+ * Default success status.
+ */
+ private int DEF_SUCCESS_STATUS = 0;
+
+
+
+ private SshAdapter sshAdapter;
+
+ /**
+ * Used for jUnit test and testing interface
+ */
+ public SshApiCallNode(boolean mode) {
+ PARAM_TEST_MODE = mode;
+ }
+
+ public SshApiCallNode() {
+ PARAM_TEST_MODE = false;
+ }
+
+ public void setSshAdapter(SshAdapter sshAdapter) {
+ this.sshAdapter = sshAdapter;
+ }
+
+ /**
+ * Allows Directed Graphs the ability to interact with SSH APIs.
+ * @param params HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
+ * <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
+ * <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
+ * <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
+ * <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
+ * <tr><td>Cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
+ * <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td></tr>
+ * <tr><td>ResponseType</td><td>Optional</td><td>If we know the response is to be in a specific format (supported are JSON, XML and NONE) </td></tr>
+ * <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
+ * <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>AuthType</td><td>Optional</td><td>Type of authentiation to be used BASIC or sshKey based</td><td>true or false</td></tr>
+ * <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
+ * These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
+ * <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
+ * The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
+ * This attribute can be used to generate files that a command may require as part of execution.</td></tr>
+ * </tbody>
+ * </table>
+ * Exec remote command over SSH. Return command execution status.
+ * Command output is written to out or err stream.
+ *
+ * @param ctx Reference to context memory
+ */
+
+ public void execCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ execSshCommand(params, ctx, false);
+ }
+
+ private void execSshCommand(Map<String, String> params, SvcLogicContext ctx, boolean withPty) throws SvcLogicException {
+ ParseParam parser = new ParseParam();
+ Parameters p = parser.getParameters(params);
+ logger.debug("=> Connecting to SSH server...");
+ SshConnection sshConnection = null;
+ int status = -1;
+ ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+ ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+ String stdoutRes = "";
+ String stderrRes = "";
+ try {
+ if (!PARAM_TEST_MODE) {
+ sshConnection = getSshConnection(p);
+ sshConnection.connect();
+ logger.debug("=> Connected to SSH server...");
+ logger.debug("=> Running SSH command...");
+ sshConnection.setExecTimeout(p.sshExecTimeout);
+ if (withPty) {
+ status = sshConnection.execCommandWithPty(parser.makeCommand(params), stdout);
+ stderr = stdout;
+ }
+ else
+ status = sshConnection.execCommand(parser.makeCommand(params), stdout, stderr);
+ stdoutRes = stdout.toString();
+ stderrRes = stderr.toString();
+
+ } else {
+ if (("true").equalsIgnoreCase(params.get("TestFail")))
+ status = 202;
+ else
+ status = DEF_SUCCESS_STATUS;
+ stdoutRes = params.get(PARAM_OUT_MESSAGE);
+ }
+ logger.debug("=> executed SSH command");
+
+ if(status == DEF_SUCCESS_STATUS) {
+ parser.parseOutput(ctx, stdoutRes);
+ }
+ ctx.setAttribute(PARAM_OUT_status, String.format("%01d", status));
+ ctx.setAttribute(PARAM_OUT_stdout, stdoutRes);
+ ctx.setAttribute(PARAM_OUT_stderr, stderrRes);
+ } catch (Exception e){
+ throw new SvcLogicException("Exception in SSH adaptor : " + e.getMessage());
+ } finally {
+ if (sshConnection != null)
+ sshConnection.disconnect();
+ }
+ }
+
+ private SshConnection getSshConnection(Parameters p) throws SvcLogicException {
+ if (p.authtype == AuthType.BASIC)
+ return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshapiUser, p.sshapiPassword);
+ // This is not supported yet in the API, patch has already been added to APPC
+ else if (p.authtype == AuthType.KEY){
+ throw new SvcLogicException("SSH Key based Auth method not supported");
+ }
+ else if (p.authtype == AuthType.NONE){
+ throw new SvcLogicException("SSH Auth type required, BASIC auth in support");
+ }
+ else if (p.authtype == AuthType.UNSPECIFIED){
+ if (p.sshapiUser != null && p.sshapiPassword != null)
+ return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshapiUser, p.sshapiPassword);
+ else if (p.sshKey != null)
+ throw new SvcLogicException("SSH Key based Auth method not supported");
+ }
+ throw new SvcLogicException("SSH Auth type required, BASIC auth in support");
+ }
+
+
+ /**
+ * Allows Directed Graphs the ability to interact with SSH APIs.
+ * @param params HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
+ * <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
+ * <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
+ * <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
+ * <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
+ * <tr><td>Cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
+ * <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td></tr>
+ * <tr><td>ResponseType</td><td>Optional</td><td>If we know the response is to be in a specific format (supported are JSON, XML and NONE) </td></tr>
+ * <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
+ * <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>AuthType</td><td>Optional</td><td>Type of authentiation to be used BASIC or sshKey based</td><td>true or false</td></tr>
+ * <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
+ * These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
+ * <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
+ * The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
+ * This attribute can be used to generate files that a command may require as part of execution.</td></tr>
+ * </tbody>
+ * </table>
+ * Exec remote command over SSH. Return command execution status.
+ * Command output is written to out or err stream.
+ *
+ * @param ctx Reference to context memory
+ */
+
+ public void execWithStatusCheck(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ execCommand(params, ctx);
+ parseResponse(ctx);
+ }
+
+ private void parseResponse (SvcLogicContext ctx) throws SvcLogicException {
+ int status = Integer.parseInt(ctx.getAttribute(PARAM_OUT_status));
+ if(status != DEF_SUCCESS_STATUS) {
+ StringBuilder errmsg = new StringBuilder();
+ errmsg.append("SSH command returned error status [").append(status).append(']');
+ String stderr = ctx.getAttribute(PARAM_OUT_stderr);
+ if((stderr != null) && !stderr.isEmpty()) {
+ errmsg.append(". Error: [").append(stderr).append(']');
+ }
+ throw new SvcLogicException(errmsg.toString());
+ }
+ }
+
+ /**
+ * Allows Directed Graphs the ability to interact with SSH APIs.
+ * @param params HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
+ * <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
+ * <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
+ * <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
+ * <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
+ * <tr><td>Cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
+ * <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td></tr>
+ * <tr><td>ResponseType</td><td>Optional</td><td>If we know the response is to be in a specific format (supported are JSON, XML and NONE) </td></tr>
+ * <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
+ * <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>AuthType</td><td>Optional</td><td>Type of authentiation to be used BASIC or sshKey based</td><td>true or false</td></tr>
+ * <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
+ * These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
+ * <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
+ * The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
+ * This attribute can be used to generate files that a command may require as part of execution.</td></tr>
+ * </tbody>
+ * </table>
+ * Exec remote command over SSH. Return command execution status.
+ * Command output is written to out or err stream.
+ *
+ * @param ctx Reference to context memory
+ */
+ public void execCommandWithPty(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ execSshCommand(params, ctx, true);
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/AuthType.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/AuthType.java
new file mode 100644
index 000000000..806c80890
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/AuthType.java
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+public enum AuthType {
+ NONE, BASIC, KEY, UNSPECIFIED;
+
+ public static AuthType fromString(String s) {
+ if ("basic".equalsIgnoreCase(s))
+ return BASIC;
+ if ("key".equalsIgnoreCase(s))
+ return KEY;
+ if ("unspecified".equalsIgnoreCase(s))
+ return UNSPECIFIED;
+ if ("none".equalsIgnoreCase(s))
+ return NONE;
+ throw new IllegalArgumentException("Invalid value for format: " + s);
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Format.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Format.java
new file mode 100644
index 000000000..43c3c38d6
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Format.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+public enum Format {
+ JSON, XML, NONE;
+
+ public static Format fromString(String s) {
+ if ("json".equalsIgnoreCase(s))
+ return JSON;
+ if ("xml".equalsIgnoreCase(s))
+ return XML;
+ if ("none".equalsIgnoreCase(s))
+ return NONE;
+ throw new IllegalArgumentException("Invalid value for format: " + s);
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java
new file mode 100644
index 000000000..3d48a790f
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class JsonParser {
+
+ private static final Logger log = LoggerFactory.getLogger(JsonParser.class);
+
+ private JsonParser() {
+ // Preventing instantiation of the same.
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Map<String, String> convertToProperties(String s)
+ throws JSONException {
+
+ checkNotNull(s, "Input should not be null.");
+
+ JSONObject json = new JSONObject(s);
+ Map<String, Object> wm = new HashMap<>();
+ Iterator<String> ii = json.keys();
+ while (ii.hasNext()) {
+ String key1 = ii.next();
+ wm.put(key1, json.get(key1));
+ }
+
+ Map<String, String> mm = new HashMap<>();
+
+ while (!wm.isEmpty())
+ for (String key : new ArrayList<>(wm.keySet())) {
+ Object o = wm.get(key);
+ wm.remove(key);
+
+ if (o instanceof Boolean || o instanceof Number || o instanceof String) {
+ mm.put(key, o.toString());
+
+ log.info("Added property: {} : {}", key, o.toString());
+ } else if (o instanceof JSONObject) {
+ JSONObject jo = (JSONObject) o;
+ Iterator<String> i = jo.keys();
+ while (i.hasNext()) {
+ String key1 = i.next();
+ wm.put(key + "." + key1, jo.get(key1));
+ }
+ } else if (o instanceof JSONArray) {
+ JSONArray ja = (JSONArray) o;
+ mm.put(key + "_length", String.valueOf(ja.length()));
+
+ log.info("Added property: {}_length: {}", key, String.valueOf(ja.length()));
+
+ for (int i = 0; i < ja.length(); i++)
+ wm.put(key + '[' + i + ']', ja.get(i));
+ }
+ }
+ return mm;
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Parameters.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Parameters.java
new file mode 100644
index 000000000..fa2371e88
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Parameters.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+import java.util.Set;
+
+public class Parameters {
+ public String sshapiUrl;
+ public int sshapiPort;
+ public String sshapiUser;
+ public String sshapiPassword;
+ public String sshKey;
+ public long sshExecTimeout;
+ public String sshFileParameters;
+ public String sshEnvParameters;
+ public boolean sshWithRetry;
+ public String cmd;
+ public String responsePrefix;
+ public Format responseType;
+
+ public Set<String> listNameList;
+ public boolean convertResponse;
+ public AuthType authtype;
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/ParseParam.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/ParseParam.java
new file mode 100644
index 000000000..35c1087d8
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/ParseParam.java
@@ -0,0 +1,275 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+import com.google.common.base.Strings;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+public class ParseParam {
+ private static final Logger log = LoggerFactory.getLogger(ParseParam.class);
+ /**
+ * Default SSH command timeout
+ */
+ private long dEF_timeout = 12000;
+ /**
+ * Default SSH connection port.
+ */
+ private int dEF_port = 22;
+ /**
+ * Default SSH command timeout
+ */
+ private final String FILE_PARAMETERS_OPT_KEY = "FileParameters";
+ public final String SSH_ResponsePrefix = "ResponsePrefix";
+ /**
+ * Default SSH connection port.
+ */
+ private final String ENV_PARAMETERS_OPT_KEY = "EnvParameters";
+ private Parameters p = new Parameters();
+
+ public Parameters getParameters(Map<String, String> paramMap) throws SvcLogicException {
+ p.sshapiUrl = parseParam(paramMap, "Url", true, null);
+ p.sshapiPort = Integer.parseInt(parseParam(paramMap, "Port", true, Integer.toString(dEF_port)));
+ p.sshapiUser = parseParam(paramMap, "User", false, null);
+ p.sshapiPassword = parseParam(paramMap, "Password", false, null);
+ p.sshKey = parseParam(paramMap, "SshKey", false, null);
+ p.sshExecTimeout = Long.parseLong(parseParam(paramMap, "ExecTimeout", false, Long.toString(dEF_timeout)));
+ p.sshWithRetry = Boolean.valueOf(parseParam(paramMap, "Retry", false, "false"));
+ p.cmd = parseParam(paramMap, "Cmd", true, null);
+ p.responsePrefix = parseParam(paramMap, SSH_ResponsePrefix, false, null);
+ p.responseType = Format.fromString(parseParam(paramMap, "ResponseType", false, "none"));
+ p.listNameList = getListNameList(paramMap);
+ p.convertResponse = Boolean.valueOf(parseParam(paramMap, "ConvertResponse", false, "true"));
+ p.authtype = AuthType.fromString(parseParam(paramMap, "AuthType", false, "unspecified"));
+
+ return p;
+ }
+
+ public String getStringParameters(Map<String, String> paramMap, String paramName) throws SvcLogicException {
+ return parseParam(paramMap, SSH_ResponsePrefix, false, null);
+ }
+
+ public void parseOutput (SvcLogicContext ctx, String outMessage) throws SvcLogicException {
+ if (p.convertResponse) {
+ if (p.responseType == Format.NONE) {
+ classifyOutput(ctx, outMessage);
+ } else if (p.responseType == Format.JSON) {
+ classifyOutput(ctx, outMessage);
+ } else if (p.responseType == Format.XML) {
+ classifyOutput(ctx, outMessage, p.listNameList);
+ }
+ }
+ }
+
+ private void classifyOutput(SvcLogicContext ctx, String outMessage, Set<String> listNameList) throws SvcLogicException {
+ Map<String, String> mm = XmlParser.convertToProperties(outMessage, p.listNameList);
+ toCtx (ctx, mm);
+ }
+
+ private void toCtx (SvcLogicContext ctx, Map<String, String> mm) {
+ if (mm != null) {
+ for (Map.Entry<String, String> entry : mm.entrySet()) {
+ if (p.responsePrefix != null) {
+ ctx.setAttribute(p.responsePrefix + "." + entry.getKey(), entry.getValue());
+ log.info("+++ " + p.responsePrefix + "." + entry.getKey() + ": [" + entry.getValue() + "]");
+ } else {
+ ctx.setAttribute(entry.getKey(), entry.getValue());
+ log.info("+++ " + entry.getKey() + ": [" + entry.getValue() + "]");
+ }
+ }
+ }
+ }
+
+ private void classifyOutput(SvcLogicContext ctx, String outMessage) throws SvcLogicException {
+ try {
+ Map<String, String> mm = JsonParser.convertToProperties(outMessage);
+ toCtx (ctx, mm);
+ } catch (org.codehaus.jettison.json.JSONException e) {
+ log.info("Output not in JSON format");
+ putToProperties(ctx, p.responsePrefix);
+ } catch (Exception e) {
+ throw new SvcLogicException("error parsing response file");
+ }
+ }
+
+ private void putToProperties(SvcLogicContext ctx, String outMessage) throws SvcLogicException {
+
+ try {
+ Properties prop = new Properties();
+ prop.load(new ByteArrayInputStream(outMessage.getBytes(StandardCharsets.UTF_8)));
+ for (Object key : prop.keySet()) {
+ String name = (String) key;
+ String value = prop.getProperty(name);
+ if (value != null && value.trim().length() > 0) {
+ if (p.responsePrefix != null) {
+ ctx.setAttribute(p.responsePrefix + "." + name, value.trim());
+ log.info("+++ " + p.responsePrefix + "." + name + ": [" + value + "]");
+ } else {
+ ctx.setAttribute(name, value.trim());
+ log.info("+++ " + name + ": [" + value + "]");
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw new SvcLogicException( "Error parsing response file.");
+ }
+ }
+
+ public String makeCommand (Map<String, String> params) {
+ JSONObject jsonPayload = new JSONObject();
+ final String[] optionalTestParams = {ENV_PARAMETERS_OPT_KEY, FILE_PARAMETERS_OPT_KEY};
+ parseParam(params, optionalTestParams, jsonPayload);
+ JSONObject envParams = (JSONObject) jsonPayload.remove(ENV_PARAMETERS_OPT_KEY);
+ JSONObject fileParams = (JSONObject) jsonPayload.remove(FILE_PARAMETERS_OPT_KEY);
+
+ StringBuilder constructedCommand = new StringBuilder();
+ constructedCommand.append(parseFileParam(fileParams)).append(p.cmd).append(" ").append(parseEnvParam(envParams));
+
+ return constructedCommand.toString();
+ }
+
+ private String parseEnvParam(JSONObject envParams) {
+ StringBuilder envParamBuilder = new StringBuilder();
+ if (envParams != null) {
+ for (Object key : envParams.keySet()) {
+ if (envParamBuilder.length() > 0) {
+ envParamBuilder.append(", ");
+ }
+ envParamBuilder.append(key + "=" + envParams.get((String) key));
+ }
+ }
+ return envParamBuilder.toString();
+ }
+
+ private String parseFileParam(JSONObject fileParams) {
+ StringBuilder fileParamBuilder = new StringBuilder();
+ if (fileParams != null) {
+ for (Object key : fileParams.keySet()) {
+ fileParamBuilder.append("echo -e \"" + fileParams.get((String) key) + "\" > /srv/salt/" + key).append("; ");
+ }
+ }
+ return fileParamBuilder.toString();
+ }
+
+ private void parseParam(Map<String, String> params, String[] optionalTestParams, JSONObject jsonPayload)
+ throws JSONException {
+
+ Set<String> optionalParamsSet = new HashSet<>();
+ Collections.addAll(optionalParamsSet, optionalTestParams);
+
+ //@formatter:off
+ params.entrySet()
+ .stream()
+ .filter(entry -> optionalParamsSet.contains(entry.getKey()))
+ .filter(entry -> !Strings.isNullOrEmpty(entry.getValue()))
+ .forEach(entry -> parseParam(entry, jsonPayload));
+ //@formatter:on
+ }
+
+ private void parseParam(Map.Entry<String, String> params, JSONObject jsonPayload)
+ throws JSONException {
+ String key = params.getKey();
+ String payload = params.getValue();
+
+ switch (key) {
+ case ENV_PARAMETERS_OPT_KEY:
+ JSONObject paramsJson = new JSONObject(payload);
+ jsonPayload.put(key, paramsJson);
+ break;
+
+ case FILE_PARAMETERS_OPT_KEY:
+ jsonPayload.put(key, getFilePayload(payload));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Return payload with escaped newlines
+ */
+ private JSONObject getFilePayload(String payload) {
+ String formattedPayload = payload.replace("\n", "\\n").replace("\r", "\\r");
+ return new JSONObject(formattedPayload);
+ }
+
+ private Set<String> getListNameList(Map<String, String> paramMap) {
+ Set<String> ll = new HashSet<>();
+ for (Map.Entry<String,String> entry : paramMap.entrySet())
+ if (entry.getKey().startsWith("listName"))
+ ll.add(entry.getValue());
+ return ll;
+ }
+
+ private String parseParam(Map<String, String> paramMap, String name, boolean required, String def)
+ throws SvcLogicException {
+ String s = paramMap.get(name);
+
+ if (s == null || s.trim().length() == 0) {
+ if (!required)
+ return def;
+ throw new SvcLogicException("Parameter " + name + " is required in sshapiCallNode");
+ }
+
+ s = s.trim();
+ StringBuilder value = new StringBuilder();
+ int i = 0;
+ int i1 = s.indexOf('%');
+ while (i1 >= 0) {
+ int i2 = s.indexOf('%', i1 + 1);
+ if (i2 < 0)
+ break;
+
+ String varName = s.substring(i1 + 1, i2);
+ String varValue = System.getenv(varName);
+ if (varValue == null)
+ varValue = "%" + varName + "%";
+
+ value.append(s.substring(i, i1));
+ value.append(varValue);
+
+ i = i2 + 1;
+ i1 = s.indexOf('%', i);
+ }
+ value.append(s.substring(i));
+
+ log.info("Parameter {}: [{}]", name, value);
+ return value.toString();
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlJsonUtil.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlJsonUtil.java
new file mode 100644
index 000000000..d68fbc6ac
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlJsonUtil.java
@@ -0,0 +1,389 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class XmlJsonUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(XmlJsonUtil.class);
+
+ private XmlJsonUtil() {
+ // Preventing instantiation of the same.
+ }
+
+ public static String getXml(Map<String, String> varmap, String var) {
+ boolean escape = true;
+ if (var.startsWith("'")) {
+ var = var.substring(1);
+ escape = false;
+ }
+
+ Object o = createStructure(varmap, var);
+ return generateXml(o, 0, escape);
+ }
+
+ public static String getJson(Map<String, String> varmap, String var) {
+ boolean escape = true;
+ if (var.startsWith("'")) {
+ var = var.substring(1);
+ escape = false;
+ }
+
+ boolean quotes = true;
+ if (var.startsWith("\"")) {
+ var = var.substring(1);
+ quotes = false;
+ }
+
+ Object o = createStructure(varmap, var);
+ return generateJson(o, escape, quotes);
+ }
+
+ private static Object createStructure(Map<String, String> flatmap, String var) {
+ if (flatmap.containsKey(var)) {
+ if (var.endsWith("_length") || var.endsWith("].key"))
+ return null;
+ return flatmap.get(var);
+ }
+
+ Map<String, Object> mm = new HashMap<>();
+ for (String k : flatmap.keySet())
+ if (k.startsWith(var + ".")) {
+ int i1 = k.indexOf('.', var.length() + 1);
+ int i2 = k.indexOf('[', var.length() + 1);
+ int i3 = k.length();
+ if (i1 > 0 && i1 < i3)
+ i3 = i1;
+ if (i2 > 0 && i2 < i3)
+ i3 = i2;
+ String k1 = k.substring(var.length() + 1, i3);
+ String var1 = k.substring(0, i3);
+ if (!mm.containsKey(k1)) {
+ Object str = createStructure(flatmap, var1);
+ if (str != null && (!(str instanceof String) || ((String) str).trim().length() > 0))
+ mm.put(k1, str);
+ }
+ }
+ if (!mm.isEmpty())
+ return mm;
+
+ boolean arrayFound = false;
+ for (String k : flatmap.keySet())
+ if (k.startsWith(var + "[")) {
+ arrayFound = true;
+ break;
+ }
+
+ if (arrayFound) {
+ List<Object> ll = new ArrayList<>();
+
+ int length = Integer.MAX_VALUE;
+ String lengthStr = flatmap.get(var + "_length");
+ if (lengthStr != null) {
+ try {
+ length = Integer.parseInt(lengthStr);
+ } catch (Exception e) {
+ log.warn("Invalid number for {}_length:{}", var, lengthStr, e);
+ }
+ }
+
+ for (int i = 0; i < length; i++) {
+ Object v = createStructure(flatmap, var + '[' + i + ']');
+ if (v == null)
+ break;
+ ll.add(v);
+ }
+
+ if (!ll.isEmpty())
+ return ll;
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static String generateXml(Object o, int indent, boolean escape) {
+ if (o == null)
+ return null;
+
+ if (o instanceof String)
+ return escape ? escapeXml((String) o) : (String) o;;
+
+ if (o instanceof Map) {
+ StringBuilder ss = new StringBuilder();
+ Map<String, Object> mm = (Map<String, Object>) o;
+ for (Map.Entry<String, Object> entry: mm.entrySet()) {
+ Object v = entry.getValue();
+ String key = entry.getKey();
+ if (v instanceof String) {
+ String s = escape ? escapeXml((String) v) : (String) v;
+ ss.append(pad(indent)).append('<').append(key).append('>');
+ ss.append(s);
+ ss.append("</").append(key).append('>').append('\n');
+ } else if (v instanceof Map) {
+ ss.append(pad(indent)).append('<').append(key).append('>').append('\n');
+ ss.append(generateXml(v, indent + 1, escape));
+ ss.append(pad(indent)).append("</").append(key).append('>').append('\n');
+ } else if (v instanceof List) {
+ List<Object> ll = (List<Object>) v;
+ for (Object o1 : ll) {
+ ss.append(pad(indent)).append('<').append(key).append('>').append('\n');
+ ss.append(generateXml(o1, indent + 1, escape));
+ ss.append(pad(indent)).append("</").append(key).append('>').append('\n');
+ }
+ }
+ }
+ return ss.toString();
+ }
+
+ return null;
+ }
+
+ private static String generateJson(Object o, boolean escape, boolean quotes) {
+ if (o == null)
+ return null;
+
+ StringBuilder ss = new StringBuilder();
+ generateJson(ss, o, 0, false, escape, quotes);
+ return ss.toString();
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void generateJson(StringBuilder ss, Object o, int indent, boolean padFirst, boolean escape, boolean quotes) {
+ if (o instanceof String) {
+ String s = escape ? escapeJson((String) o) : (String) o;
+ if (padFirst)
+ ss.append(pad(indent));
+ if (quotes) {
+ ss.append('"').append(s).append('"');
+ } else {
+ ss.append(s);
+ }
+ return;
+ }
+
+ if (o instanceof Map) {
+ Map<String, Object> mm = (Map<String, Object>) o;
+
+ if (padFirst)
+ ss.append(pad(indent));
+ ss.append("{\n");
+
+ boolean first = true;
+ for (Map.Entry<String, Object> entry : mm.entrySet()) {
+ if (!first)
+ ss.append(",\n");
+ first = false;
+ Object v = entry.getValue();
+ String key = entry.getKey();
+ ss.append(pad(indent + 1)).append('"').append(key).append("\": ");
+ generateJson(ss, v, indent + 1, false, escape, true);
+ }
+
+ ss.append("\n");
+ ss.append(pad(indent)).append('}');
+
+ return;
+ }
+
+ if (o instanceof List) {
+ List<Object> ll = (List<Object>) o;
+
+ if (padFirst)
+ ss.append(pad(indent));
+ ss.append("[\n");
+
+ boolean first = true;
+ for (Object o1 : ll) {
+ if (!first)
+ ss.append(",\n");
+ first = false;
+
+ generateJson(ss, o1, indent + 1, true, escape, quotes);
+ }
+
+ ss.append("\n");
+ ss.append(pad(indent)).append(']');
+ }
+ }
+
+ public static String removeLastCommaJson(String s) {
+ StringBuilder sb = new StringBuilder();
+ int k = 0;
+ int start = 0;
+ while (k < s.length()) {
+ int i11 = s.indexOf('}', k);
+ int i12 = s.indexOf(']', k);
+ int i1 = -1;
+ if (i11 < 0)
+ i1 = i12;
+ else if (i12 < 0)
+ i1 = i11;
+ else
+ i1 = i11 < i12 ? i11 : i12;
+ if (i1 < 0)
+ break;
+
+ int i2 = s.lastIndexOf(',', i1);
+ if (i2 < 0) {
+ k = i1 + 1;
+ continue;
+ }
+
+ String between = s.substring(i2 + 1, i1);
+ if (between.trim().length() > 0) {
+ k = i1 + 1;
+ continue;
+ }
+
+ sb.append(s.substring(start, i2));
+ start = i2 + 1;
+ k = i1 + 1;
+ }
+
+ sb.append(s.substring(start, s.length()));
+
+ return sb.toString();
+ }
+
+ public static String removeEmptyStructJson(String s) {
+ int k = 0;
+ while (k < s.length()) {
+ boolean curly = true;
+ int i11 = s.indexOf('{', k);
+ int i12 = s.indexOf('[', k);
+ int i1 = -1;
+ if (i11 < 0) {
+ i1 = i12;
+ curly = false;
+ } else if (i12 < 0)
+ i1 = i11;
+ else
+ if (i11 < i12)
+ i1 = i11;
+ else {
+ i1 = i12;
+ curly = false;
+ }
+
+ if (i1 >= 0) {
+ int i2 = curly ? s.indexOf('}', i1) : s.indexOf(']', i1);
+ if (i2 > 0) {
+ String value = s.substring(i1 + 1, i2);
+ if (value.trim().length() == 0) {
+ int i4 = s.lastIndexOf('\n', i1);
+ if (i4 < 0)
+ i4 = 0;
+ int i5 = s.indexOf('\n', i2);
+ if (i5 < 0)
+ i5 = s.length();
+
+ s = s.substring(0, i4) + s.substring(i5);
+ k = 0;
+ } else
+ k = i1 + 1;
+ } else
+ break;
+ } else
+ break;
+ }
+
+ return s;
+ }
+
+ public static String removeEmptyStructXml(String s) {
+ int k = 0;
+ while (k < s.length()) {
+ int i1 = s.indexOf('<', k);
+ if (i1 < 0 || i1 == s.length() - 1)
+ break;
+
+ char c1 = s.charAt(i1 + 1);
+ if (c1 == '?' || c1 == '!') {
+ k = i1 + 2;
+ continue;
+ }
+
+ int i2 = s.indexOf('>', i1);
+ if (i2 < 0) {
+ k = i1 + 1;
+ continue;
+ }
+
+ String closingTag = "</" + s.substring(i1 + 1, i2 + 1);
+ int i3 = s.indexOf(closingTag, i2 + 1);
+ if (i3 < 0) {
+ k = i2 + 1;
+ continue;
+ }
+
+ String value = s.substring(i2 + 1, i3);
+ if (value.trim().length() > 0) {
+ k = i2 + 1;
+ continue;
+ }
+
+ int i4 = s.lastIndexOf('\n', i1);
+ if (i4 < 0)
+ i4 = 0;
+ int i5 = s.indexOf('\n', i3);
+ if (i5 < 0)
+ i5 = s.length();
+
+ s = s.substring(0, i4) + s.substring(i5);
+ k = 0;
+ }
+
+ return s;
+ }
+
+ private static String escapeXml(String v) {
+ String s = v.replaceAll("&", "&amp;");
+ s = s.replaceAll("<", "&lt;");
+ s = s.replaceAll("'", "&apos;");
+ s = s.replaceAll("\"", "&quot;");
+ s = s.replaceAll(">", "&gt;");
+ return s;
+ }
+
+ private static String escapeJson(String v) {
+ String s = v.replaceAll("\\\\", "\\\\\\\\");
+ s = s.replaceAll("\"", "\\\\\"");
+ return s;
+ }
+
+ private static String pad(int n) {
+ StringBuilder s = new StringBuilder();
+ for (int i = 0; i < n; i++)
+ s.append(Character.toString('\t'));
+ return s.toString();
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlParser.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlParser.java
new file mode 100644
index 000000000..6ea770ad9
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlParser.java
@@ -0,0 +1,176 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright © 2018 IBM.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public final class XmlParser {
+
+ private static final Logger log = LoggerFactory.getLogger(XmlParser.class);
+
+ private XmlParser() {
+ // Preventing instantiation of the same.
+ }
+
+ public static Map<String, String> convertToProperties(String s, Set<String> listNameList)
+ throws SvcLogicException {
+
+ checkNotNull(s, "Input should not be null.");
+
+ Handler handler = new Handler(listNameList);
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ SAXParser saxParser = factory.newSAXParser();
+ InputStream in = new ByteArrayInputStream(s.getBytes());
+ saxParser.parse(in, handler);
+ } catch (ParserConfigurationException | IOException | SAXException | NumberFormatException e) {
+ throw new SvcLogicException("Unable to convert XML to properties" + e.getLocalizedMessage(), e);
+ }
+ return handler.getProperties();
+ }
+
+ private static class Handler extends DefaultHandler {
+
+ private Set<String> listNameList;
+
+ private Map<String, String> properties = new HashMap<>();
+
+ StringBuilder currentName = new StringBuilder();
+ StringBuilder currentValue = new StringBuilder();
+
+ public Handler(Set<String> listNameList) {
+ super();
+ this.listNameList = listNameList;
+ if (this.listNameList == null)
+ this.listNameList = new HashSet<>();
+ }
+
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes)
+ throws SAXException {
+ super.startElement(uri, localName, qName, attributes);
+
+ String name = localName;
+ if (name == null || name.trim().length() == 0)
+ name = qName;
+ int i2 = name.indexOf(':');
+ if (i2 >= 0)
+ name = name.substring(i2 + 1);
+
+ if (currentName.length() > 0)
+ currentName.append(Character.toString('.'));
+ currentName.append(name);
+
+ String listName = removeIndexes(currentName.toString());
+
+ if (listNameList.contains(listName)) {
+ String n = currentName.toString() + "_length";
+ int len = getInt(properties, n);
+ properties.put(n, String.valueOf(len + 1));
+ currentName.append("[").append(len).append("]");
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ super.endElement(uri, localName, qName);
+
+ String name = localName;
+ if (name == null || name.trim().length() == 0)
+ name = qName;
+ int i2 = name.indexOf(':');
+ if (i2 >= 0)
+ name = name.substring(i2 + 1);
+
+ String s = currentValue.toString().trim();
+ if (s.length() > 0) {
+ properties.put(currentName.toString(), s);
+
+ log.info("Added property: {} : {}", currentName, s);
+ currentValue = new StringBuilder();
+ }
+
+ int i1 = currentName.lastIndexOf("." + name);
+ if (i1 <= 0)
+ currentName = new StringBuilder();
+ else
+ currentName = new StringBuilder(currentName.substring(0, i1));
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ super.characters(ch, start, length);
+
+ String value = new String(ch, start, length);
+ currentValue.append(value);
+ }
+
+ private static int getInt(Map<String, String> mm, String name) {
+ String s = mm.get(name);
+ if (s == null)
+ return 0;
+ return Integer.parseInt(s);
+ }
+
+ private String removeIndexes(String currentName) {
+ StringBuilder b = new StringBuilder();
+ boolean add = true;
+ for (int i = 0; i < currentName.length(); i++) {
+ char c = currentName.charAt(i);
+ if (c == '[')
+ add = false;
+ else if (c == ']')
+ add = true;
+ else if (add)
+ b.append(Character.toString(c));
+ }
+ return b.toString();
+ }
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-context.xml b/plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-context.xml
new file mode 100644
index 000000000..50c9b2aa3
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-context.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+ <property name="locations">
+ <list>
+ <value>file:${SDNC_CONFIG_DIR}/ueb.properties</value>
+ <value>file:${SDNC_CONFIG_DIR}/dme2.properties</value>
+ </list>
+ </property>
+ <property name="ignoreResourceNotFound" value="true" />
+ <property name="ignoreUnresolvablePlaceholders" value="true" />
+ </bean>
+
+ <!-- context:property-placeholder location="file:${SDNC_CONFIG_DIR}/ueb.properties" /-->
+
+ <bean id="sshapiCallNode" class="org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode">
+ <property name="uebServers" value="${servers}" />
+ </bean>
+
+</beans>
diff --git a/plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-osgi-context.xml b/plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-osgi-context.xml
new file mode 100644
index 000000000..25631d6af
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-osgi-context.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<beans:beans xmlns="http://www.springframework.org/schema/osgi"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
+ xsi:schemaLocation="http://www.springframework.org/schema/osgi
+ http://www.springframework.org/schema/osgi/spring-osgi.xsd
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <service ref="sshapiCallNode" interface="org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode" />
+
+</beans:beans>
diff --git a/plugins/sshapi-call-node/provider/src/main/resources/OSGI-INF/blueprint/sshapi-call-node-blueprint.xml b/plugins/sshapi-call-node/provider/src/main/resources/OSGI-INF/blueprint/sshapi-call-node-blueprint.xml
new file mode 100755
index 000000000..7a5424329
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/resources/OSGI-INF/blueprint/sshapi-call-node-blueprint.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="sshapiCallNodeProvider" class="org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode" />
+
+
+
+ <service ref="sshapiCallNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/sshapi-call-node/provider/src/main/resources/org/opendaylight/blueprint/sshapi-call-node-blueprint.xml b/plugins/sshapi-call-node/provider/src/main/resources/org/opendaylight/blueprint/sshapi-call-node-blueprint.xml
new file mode 100755
index 000000000..7a5424329
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/resources/org/opendaylight/blueprint/sshapi-call-node-blueprint.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="sshapiCallNodeProvider" class="org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode" />
+
+
+
+ <service ref="sshapiCallNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestJsonParser.java b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestJsonParser.java
new file mode 100644
index 000000000..78f20e327
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestJsonParser.java
@@ -0,0 +1,85 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package jtest.org.onap.ccsdk.sli.plugins.restapicall;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.codehaus.jettison.json.JSONException;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.JsonParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestJsonParser {
+
+ private static final Logger log = LoggerFactory.getLogger(TestJsonParser.class);
+
+ @Test
+ public void test() throws SvcLogicException, IOException {
+ 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 = null;
+ try {
+ mm = JsonParser.convertToProperties(b.toString());
+ } catch (JSONException e){
+ throw new SvcLogicException(e.getMessage());
+ }
+
+ logProperties(mm);
+
+ in.close();
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullString() throws SvcLogicException {
+ Map<String, String> mm = null;
+ try {
+ mm = JsonParser.convertToProperties(null);
+ } catch (JSONException e){
+ throw new SvcLogicException(e.getMessage());
+ }
+ }
+
+ 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/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestSshApiCallNode.java b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestSshApiCallNode.java
new file mode 100644
index 000000000..c0bcdb82a
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestSshApiCallNode.java
@@ -0,0 +1,330 @@
+package jtest.org.onap.ccsdk.sli.plugins.restapicall;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestSshApiCallNode {
+
+ private static final Logger log = LoggerFactory.getLogger(TestSshApiCallNode.class);
+
+ private SshApiCallNode adapter;
+ 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();
+ adapter = new SshApiCallNode();
+
+ 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;
+ adapter = null;
+ params = null;
+ svcContext = null;
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommand_noUrlFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.execCommand(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandPty_noUrlFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.execCommandWithPty(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noUrlFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommand_noPortFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.execCommand(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandPty_noPortFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.execCommandWithPty(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noPortFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommand_noCmdFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ adapter.execCommand(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandPty_noCmdFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ adapter.execCommandWithPty(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noCmdFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noSSHBasicFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("AuthType", "basic");
+ params.put("Cmd", "test");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noSSHKeyFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("AuthType", "key");
+ params.put("Cmd", "test");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noSSHNoneFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("AuthType", "none");
+ params.put("Cmd", "test");
+ params.put("ResponseType", "xml");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noSSHFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("ResponseType", "json");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testExecCommandResponse_noSSHInvalidParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("ResponseType", "txt");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testExecCommandResponse_noSSHInvalidAuthParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("AuthType", "spring");
+ params.put("ResponseType", "json");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test
+ public void testExecCommandResponse_validJSON() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("AuthType", "basic");
+ params.put("ResponseType", "json");
+ params.put("TestOut", "{\"equipment-data\":\"boo\"}");
+ params.put("TestFail", "false");
+ adapter = new SshApiCallNode(true);
+ adapter.execWithStatusCheck(params, svcContext);
+ assertEquals("boo", svcContext.getAttribute("equipment-data"));
+ }
+
+ @Test
+ public void testExecCommandResponse_validXML() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("AuthType", "basic");
+ params.put("ResponseType", "xml");
+ params.put("TestOut", "<modelVersion>4.0.0</modelVersion>");
+ params.put("TestFail", "false");
+ adapter = new SshApiCallNode(true);
+ adapter.execWithStatusCheck(params, svcContext);
+ assertEquals("4.0.0", svcContext.getAttribute("modelVersion"));
+ }
+
+ @Test
+ public void testExecCommandResponse_validJSONPrefix() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("AuthType", "basic");
+ params.put("ResponseType", "json");
+ params.put("TestOut", "{\"equipment-data\":\"boo\"}");
+ params.put("ResponsePrefix", "test");
+ params.put("TestFail", "false");
+ adapter = new SshApiCallNode(true);
+ adapter.execWithStatusCheck(params, svcContext);
+ assertEquals("boo", svcContext.getAttribute("test.equipment-data"));
+ }
+
+ @Test
+ public void testExecCommandResponse_validXMLPrefix() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("AuthType", "basic");
+ params.put("ResponseType", "xml");
+ params.put("TestOut", "<modelVersion>4.0.0</modelVersion>");
+ params.put("ResponsePrefix", "test");
+ params.put("TestFail", "false");
+ adapter = new SshApiCallNode(true);
+ adapter.execWithStatusCheck(params, svcContext);
+ assertEquals("4.0.0", svcContext.getAttribute("test.modelVersion"));
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_validXMLFail() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("AuthType", "basic");
+ params.put("ResponseType", "xml");
+ params.put("TestOut", "<modelVersion>4.0.0</modelVersion>");
+ params.put("TestFail", "true");
+ params.put("ResponsePrefix", "test");
+ adapter = new SshApiCallNode(true);
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_validXMLPrefixKey() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params = new HashMap<>();
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("SshKey", "test");
+ params.put("Cmd", "test");
+ params.put("ResponseType", "xml");
+ params.put("TestOut", "<modelVersion>4.0.0</modelVersion>");
+ params.put("ResponsePrefix", "test");
+ adapter.execWithStatusCheck(params, svcContext);
+ assertEquals("4.0.0", svcContext.getAttribute("test.modelVersion"));
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlJsonUtil.java b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlJsonUtil.java
new file mode 100644
index 000000000..33e0f24dd
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlJsonUtil.java
@@ -0,0 +1,264 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package jtest.org.onap.ccsdk.sli.plugins.restapicall;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.XmlJsonUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class TestXmlJsonUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(TestXmlJsonUtil.class);
+
+ @Test
+ public void test() {
+ Map<String, String> mm = new HashMap<>();
+ mm.put("service-data.vnf-config-parameters-list.vnf-config-parameters[0].vnf-type", "N-SBG");
+ mm.put("service-data.service-information.service-instance-id", "someinstance001");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].dns-server-ip-address", "10.11.12.13");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].escf-domain-name", "hclab.atttest.com");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3_length", "2");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[0].snmp-target-v3-id", "1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[0].snmp-target-ip-address", "127.0.0.1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[0].snmp-security-level", "NO_AUTH_NO_PRIV");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[1].snmp-target-v3-id", "2");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[1].snmp-target-ip-address", "192.168.1.8");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[1].snmp-security-level", "NO_AUTH_NO_PRIV");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].dns-ip-address-1", "2001:1890:1001:2224::1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].dns-ip-address-2", "2001:1890:1001:2424::1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].diameter-rf-realm-name", "uvp.els-an.att.net");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].diameter-rf-peer-ip-address", "192.168.1.66");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].bgf-controller-ip-address", "192.168.1.186");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].bgf-control-link-name", "mg3/69@192.168.1.226");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].rf-interface-nexthop-ip-address", "10.111.108.150");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].rf-mated-pair-ip-address", "10.111.108.146");
+
+ mm.put("service-data.vnf-config-parameters-list.vnf-config-parameters[0].access-net-pcscf_length", "4");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[0].network-name", "UvpbUgnAccess1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[0].sip-pa-termination-ip-address", "10.111.108.146");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[1].network-name", "MIS");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[1].proactive-transcoding-profile",
+ "trinity-transcodingProfile");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[1].next-hop-ip-address", "10.111.108.158");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[1].subnet-mask-length", "10.111.108.154");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[2].network-name", "AVPN1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[2].proactive-transcoding-profile",
+ "trinity-transcodingProfile");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[2].next-hop-ip-address", "10.111.108.166");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[2].subnet-mask-length", "10.111.108.162");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[3].network-name", "AVPN1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[3].proactive-transcoding-profile",
+ "trinity-transcodingProfile");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[3].next-hop-ip-address", "10.129.108.166");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[3].subnet-mask-length", "10.129.108.162");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].core-net-pcscf_length", "1");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].core-net-pcscf[0].network-name", "Core");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].core-net-pcscf[0].next-hop-ip-address", "10.111.108.142");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].core-net-pcscf[0].sip-pa-termination-ip-address", "10.111.108.138");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].mated-pair-fully-qualified-domain-name",
+ "mt1nj01sbg01pyl-mt1nj01sbg02pyl.ar1ga.uvp.els-an.att.net");
+
+ mm.put("service-data.appc-request-header.svc-request-id", "SOMESERVICEREQUEST123451000");
+ mm.put("service-data.vnf-config-information.vnf-host-ip-address", "192.168.13.151");
+ mm.put("service-data.vnf-config-information.vendor", "Netconf");
+
+ mm.put("service-data.vnf-config-information.escape-test",
+ "blah blah \"xxx&nnn<>\\'\"there>blah<&''\"\"123\\\\\\'''blah blah &");
+
+ String ss = XmlJsonUtil.getXml(mm, "service-data.vnf-config-parameters-list");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getXml(mm, "service-data.vnf-config-information");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getJson(mm, "service-data.vnf-config-parameters-list.vnf-config-parameters");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getJson(mm, "service-data.vnf-config-information");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getJson(mm, "service-data.vnf-config-information.vnf-host-ip-address");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getJson(mm, "\"service-data.vnf-config-information.vnf-host-ip-address");
+ log.info(ss);
+ }
+
+ @Test
+ public void testRemoveEmptyStructXml() {
+ String xmlin = "" +
+ "<T1>\n" +
+ " <T2>\n" +
+ " <T3>\n" +
+ " <T4></T4>\n" +
+ " <T5> </T5>\n" +
+ " <T6>\n" +
+ " </T6>\n" +
+ " </T3>\n" +
+ " <T7>blah</T7>\n" +
+ " </T2>\n" +
+ " <T8>\n" +
+ " <T9>\n" +
+ " <T10></T10>\n" +
+ " <T11> </T11>\n" +
+ " <T12>\n" +
+ " </T12>\n" +
+ " </T9>\n" +
+ " <T13>\n" +
+ " <T14></T14>\n" +
+ " <T15> </T15>\n" +
+ " <T16>\n" +
+ " <T17></T17>\n" +
+ " </T16>\n" +
+ " </T13>\n" +
+ " <T17>\n" +
+ " </T17>\n" +
+ " </T8>\n" +
+ " <T18>blah blah</T18>\n" +
+ "</T1>\n";
+
+ String xmloutexpected = "" +
+ "<T1>\n" +
+ " <T2>\n" +
+ " <T7>blah</T7>\n" +
+ " </T2>\n" +
+ " <T18>blah blah</T18>\n" +
+ "</T1>\n";
+
+ String xmlout = XmlJsonUtil.removeEmptyStructXml(xmlin);
+ log.info(xmlout);
+
+ Assert.assertEquals(xmloutexpected, xmlout);
+ }
+
+ @Test
+ public void testRemoveEmptyStructJson() {
+ String xmlin = "{\r\n" +
+ " \"T1\":{\r\n" +
+ " \"T2\":{\r\n" +
+ " \"T3\":[\r\n" +
+ " \r\n" +
+ " ],\r\n" +
+ " \"T4\":{\r\n" +
+ " \"T12\":[\r\n" +
+ " \r\n" +
+ " ],\r\n" +
+ " \"T13\":[ ],\r\n" +
+ " \"T14\":{\r\n" +
+ " \"T15\":{\r\n" +
+ " \r\n" +
+ " },\r\n" +
+ " \"T16\":{\r\n" +
+ " \r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ " },\r\n" +
+ " \"T5\":{\r\n" +
+ " \"T6\":[\r\n" +
+ " \r\n" +
+ " ],\r\n" +
+ " \"T7\":[\r\n" +
+ " \"T8\":{\r\n" +
+ " \r\n" +
+ " },\r\n" +
+ " \"T9\":{ },\r\n" +
+ " \"T10\":\"blah\",\r\n" +
+ " \"T11\":[\r\n" +
+ " \r\n" +
+ " ]\r\n" +
+ " ]\r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ "}\r\n" +
+ "";
+
+ String xmloutexpected = "{\r\n" +
+ " \"T1\":{\r\n" +
+ " \"T2\":{\r\n" +
+ " \"T5\":{\r\n" +
+ " \"T7\":[\r\n" +
+ " \"T10\":\"blah\",\r\n" +
+ " ]\r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ "}\r\n" +
+ "";
+
+ String xmlout = XmlJsonUtil.removeEmptyStructJson(xmlin);
+ log.info(xmlout);
+
+ Assert.assertEquals(xmloutexpected, xmlout);
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlParser.java b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlParser.java
new file mode 100644
index 000000000..ba0ae41de
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlParser.java
@@ -0,0 +1,123 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package jtest.org.onap.ccsdk.sli.plugins.restapicall;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.XmlParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestXmlParser {
+
+ private static final Logger log = LoggerFactory.getLogger(TestXmlParser.class);
+
+ @Test
+ public void test() throws Exception {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(ClassLoader.getSystemResourceAsStream("test3.xml"))
+ );
+ StringBuilder b = new StringBuilder();
+ String line;
+ while ((line = in.readLine()) != null)
+ b.append(line).append('\n');
+
+ Set<String> listNameList = new HashSet<String>();
+ listNameList.add("project.dependencies.dependency");
+ listNameList.add("project.build.plugins.plugin");
+ listNameList.add("project.build.plugins.plugin.executions.execution");
+ listNameList.add("project.build.pluginManagement.plugins.plugin");
+ listNameList.add("project.build.pluginManagement." +
+ "plugins.plugin.configuration.lifecycleMappingMetadata.pluginExecutions.pluginExecution");
+
+ Map<String, String> mm = XmlParser.convertToProperties(b.toString(), listNameList);
+ logProperties(mm);
+ in.close();
+ }
+
+ @Test
+ public void testValidLength() throws Exception {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(ClassLoader.getSystemResourceAsStream("test3.xml"))
+ );
+ StringBuilder b = new StringBuilder();
+ String line;
+ while ((line = in.readLine()) != null)
+ b.append(line).append('\n');
+
+ Set<String> listNameList = new HashSet<String>();
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport");
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport");
+
+ Map<String, String> mm = XmlParser.convertToProperties(b.toString(), listNameList);
+
+ assertThat(mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport[5]"), is("SET_RESET_LP"));
+ assertThat(mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport[0]"), is("SET_BVOIP_IN"));
+
+ logProperties(mm);
+ in.close();
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testInvalidLength() throws Exception {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(ClassLoader.getSystemResourceAsStream("invalidlength.xml"))
+ );
+ StringBuilder b = new StringBuilder();
+ String line;
+ while ((line = in.readLine()) != null)
+ b.append(line).append('\n');
+
+ Set<String> listNameList = new HashSet<String>();
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport");
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport");
+
+ Map<String, String> mm = XmlParser.convertToProperties(b.toString(), listNameList);
+ logProperties(mm);
+ in.close();
+ }
+
+ 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/plugins/sshapi-call-node/provider/src/test/resources/invalidlength.xml b/plugins/sshapi-call-node/provider/src/test/resources/invalidlength.xml
new file mode 100644
index 000000000..b71f6391f
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/resources/invalidlength.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<ApplyGroupResponse xmlns="http://onap.org/vpn/schema/v1"
+ xmlns:ns2="http://onap.org/prov/vpn/schema/v2">
+ <ApplyGroupResponseData>
+ <ServiceInstanceId>ICOREPVC-81114561</ServiceInstanceId>
+ <VrfDetails>
+ <End2EndVpnKey>VPNL811182</End2EndVpnKey>
+ <VpnId>811182</VpnId>
+ <VrfName>21302:811182</VrfName>
+ <VrfImport>SET_BVOIP_IN</VrfImport>
+ <VrfImport>SET6_BVOIP_IN</VrfImport>
+ <VrfExport_length>a</VrfExport_length>
+ <VrfExport>SET6_DSU</VrfExport>
+ <VrfExport>SET_DSU</VrfExport>
+ <VrfExport>SET6_MANAGED</VrfExport>
+ <VrfExport>SET_MANAGED</VrfExport>
+ <VrfExport>SET_LOVRF_COMMUNITY</VrfExport>
+ <VrfExport>SET_RESET_LP</VrfExport>
+ <ApplyGroup>
+ <ns2:ApplyGroup>AG_MAX_MCASTROUTES</ns2:ApplyGroup>
+ </ApplyGroup>
+ </VrfDetails>
+ </ApplyGroupResponseData>
+ <response-code>200</response-code>
+ <response-message>Success</response-message>
+ <ack-final-indicator>Y</ack-final-indicator>
+</ApplyGroupResponse>
+
diff --git a/plugins/sshapi-call-node/provider/src/test/resources/test-template.json b/plugins/sshapi-call-node/provider/src/test/resources/test-template.json
new file mode 100644
index 000000000..cd5e74699
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/resources/test-template.json
@@ -0,0 +1,57 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+ "sdn-circuit-request": [
+ ${repeat:tmp.sdn-circuit-req-row_length:
+ {
+ "request-id": ${tmp.sdn-circuit-req-row[${1}].request-id},
+ "source-uid": ${tmp.sdn-circuit-req-row[${1}].source-uid},
+ "action": ${tmp.sdn-circuit-req-row[${1}].action},
+ "request-timestamp": ${tmp.sdn-circuit-req-row[${1}].request-timestamp},
+ "update-timestamp": ${tmp.sdn-circuit-req-row[${1}].update-timestamp},
+ "request-status": ${tmp.sdn-circuit-req-row[${1}].request-status},
+ "processing-status": ${tmp.sdn-circuit-req-row[${1}].processing-status},
+ "reason-code": ${tmp.sdn-circuit-req-row[${1}].reason-code},
+ "reason-message": ${tmp.sdn-circuit-req-row[${1}].reason-message},
+ "customer-code": ${tmp.sdn-circuit-req-row[${1}].customer-code},
+ "bundle-id": ${tmp.sdn-circuit-req-row[${1}].bundle-id},
+ "router-name-1": ${tmp.sdn-circuit-req-row[${1}].router-name-1},
+ "tail-clfi-1": ${tmp.sdn-circuit-req-row[${1}].tail-clfi-1},
+ "srg-1": ${tmp.sdn-circuit-req-row[${1}].srg-1},
+ "router-name-2": ${tmp.sdn-circuit-req-row[${1}].router-name-2},
+ "tail-clfi-2": ${tmp.sdn-circuit-req-row[${1}].tail-clfi-2},
+ "srg-2": ${tmp.sdn-circuit-req-row[${1}].srg-2},
+ "facility-speed": ${tmp.sdn-circuit-req-row[${1}].facility-speed},
+ "facility-speed-units": ${tmp.sdn-circuit-req-row[${1}].facility-speed-units},
+ "facility-type": ${tmp.sdn-circuit-req-row[${1}].facility-type},
+ "service-clfi": ${tmp.sdn-circuit-req-row[${1}].service-clfi},
+ "clci": ${tmp.sdn-circuit-req-row[${1}].clci},
+ "wavelength-purpose": ${tmp.sdn-circuit-req-row[${1}].wavelength-purpose},
+ "activate-setting": ${tmp.sdn-circuit-req-row[${1}].activate-setting},
+ "apply-date": ${tmp.sdn-circuit-req-row[${1}].apply-date},
+ "run-id": ${tmp.sdn-circuit-req-row[${1}].run-id},
+ "hostname": ${tmp.sdn-circuit-req-row[${1}].hostname},
+ "algo-request-reason": ${tmp.sdn-circuit-req-row[${1}].algo-request-reason}
+ },
+ }
+ ]
+}
diff --git a/plugins/sshapi-call-node/provider/src/test/resources/test.json b/plugins/sshapi-call-node/provider/src/test/resources/test.json
new file mode 100644
index 000000000..e272d457a
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/resources/test.json
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+ "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/plugins/sshapi-call-node/provider/src/test/resources/test.xml b/plugins/sshapi-call-node/provider/src/test/resources/test.xml
new file mode 100644
index 000000000..7645f1992
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/resources/test.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>sshapi-call-node</artifactId>
+ <version>6.0.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>sshapi-call-node-provider</artifactId>
+ <packaging>bundle</packaging>
+ <name>SSHAPI Call Node - Provider</name>
+ <url>http://maven.apache.org</url>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>3.1.4.RELEASE</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli</groupId>
+ <artifactId>sli-provider</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>3.1.4.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>3.1.4.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xerces</artifactId>
+ <version>2.4.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey.contribs.jersey-oauth</groupId>
+ <artifactId>oauth-signature</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey.contribs.jersey-oauth</groupId>
+ <artifactId>oauth-client</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.brocade.developer</groupId>
+ <artifactId>providermodule-plugin</artifactId>
+ <configuration>
+ <packageId>org.onap.ccsdk.sli.plugins</packageId>
+ <appName>sshapi-call-node</appName>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>process-sources</phase>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>org.onap.ccsdk.sli.plugins.sshapicall</Bundle-SymbolicName>
+ <Export-Package>org.onap.ccsdk.sli.plugins.sshapicall</Export-Package>
+ <Import-Package>*</Import-Package>
+ </instructions>
+
+ <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+
+ </configuration>
+
+ </plugin>
+
+
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings
+ only. It has no influence on the Maven build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ com.brocade.developer
+ </groupId>
+ <artifactId>
+ providermodule-plugin
+ </artifactId>
+ <versionRange>
+ [1.2.0.100-SNAPSHOT,)
+ </versionRange>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/plugins/sshapi-call-node/provider/src/test/resources/test3.xml b/plugins/sshapi-call-node/provider/src/test/resources/test3.xml
new file mode 100644
index 000000000..52a7a7d98
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/resources/test3.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<ApplyGroupResponse xmlns="http://onap.org/vpn/schema/v1"
+ xmlns:ns2="http://onap.org/prov/vpn/schema/v2">
+ <ApplyGroupResponseData>
+ <ServiceInstanceId>ICOREPVC-81114561</ServiceInstanceId>
+ <VrfDetails>
+ <End2EndVpnKey>VPNL811182</End2EndVpnKey>
+ <VpnId>811182</VpnId>
+ <VrfName>21302:811182</VrfName>
+ <VrfImport>SET_BVOIP_IN</VrfImport>
+ <VrfImport>SET6_BVOIP_IN</VrfImport>
+ <VrfExport>SET6_DSU</VrfExport>
+ <VrfExport>SET_DSU</VrfExport>
+ <VrfExport>SET6_MANAGED</VrfExport>
+ <VrfExport>SET_MANAGED</VrfExport>
+ <VrfExport>SET_LOVRF_COMMUNITY</VrfExport>
+ <VrfExport>SET_RESET_LP</VrfExport>
+ <ApplyGroup>
+ <ns2:ApplyGroup>AG_MAX_MCASTROUTES</ns2:ApplyGroup>
+ </ApplyGroup>
+ </VrfDetails>
+ <RoutingApplyGroups>
+ <RoutingProtocol>BGP4_PROTOCOL</RoutingProtocol>
+ <Family>v4</Family>
+ <PeerGroupName>gp_21302:811182</PeerGroupName>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG_L3VPN_EBGP</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG_MAX_PREFIX</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG_BGP_UNMANAGED</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG_BFD_BGP_3000</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ </RoutingApplyGroups>
+ <RoutingApplyGroups>
+ <RoutingProtocol>BGP4_PROTOCOL</RoutingProtocol>
+ <Family>v6</Family>
+ <PeerGroupName>gp6_21302:811182</PeerGroupName>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG6_L3VPN_EBGP</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG6_MAX_PREFIX</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG6_BGP_UNMANAGED</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG6_BFD_BGP_3000</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ </RoutingApplyGroups>
+ </ApplyGroupResponseData>
+ <response-code>200</response-code>
+ <response-message>Success</response-message>
+ <ack-final-indicator>Y</ack-final-indicator>
+</ApplyGroupResponse>
+