aboutsummaryrefslogtreecommitdiffstats
path: root/restapi-call-node/provider/src/main
diff options
context:
space:
mode:
authorDan Timoney <dtimoney@att.com>2017-02-15 15:27:41 -0500
committerDan Timoney <dtimoney@att.com>2017-02-15 15:28:46 -0500
commit2750f8c09a37c7cd5ff8678b3d0e5f7dac687376 (patch)
treec77c01c58f326c11434c03a76b34b21a99b5fd70 /restapi-call-node/provider/src/main
parented6b164bda6903ccfbd487f8c52a53bdf046ffd7 (diff)
Initial commit for OpenECOMP SDN-C plugins
Change-Id: I0deb50b4f047c419181bb8c9e4df09c67495aa79 Signed-off-by: Dan Timoney <dtimoney@att.com>
Diffstat (limited to 'restapi-call-node/provider/src/main')
-rw-r--r--restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/JsonParser.java85
-rw-r--r--restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/RestapiCallNode.java701
-rw-r--r--restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/XmlJsonUtil.java372
-rw-r--r--restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/XmlParser.java160
-rw-r--r--restapi-call-node/provider/src/main/resources/META-INF/spring/restapi-call-node-context.xml40
-rw-r--r--restapi-call-node/provider/src/main/resources/META-INF/spring/restapi-call-node-osgi-context.xml32
-rw-r--r--restapi-call-node/provider/src/main/resources/default-ueb-message.json32
-rw-r--r--restapi-call-node/provider/src/main/resources/get-multicast-data.json34
-rw-r--r--restapi-call-node/provider/src/main/resources/northbound-api-template.json43
-rw-r--r--restapi-call-node/provider/src/main/resources/northbound-api-template.xml41
-rw-r--r--restapi-call-node/provider/src/main/resources/service-configuration-notification-northbound-template.json44
-rw-r--r--restapi-call-node/provider/src/main/resources/update-vpe-data-with-apply-group.json53
-rw-r--r--restapi-call-node/provider/src/main/resources/vnf-information-update.json24
-rw-r--r--restapi-call-node/provider/src/main/resources/vpn-allocation-request.json36
-rw-r--r--restapi-call-node/provider/src/main/resources/vpn-information-update.json24
-rw-r--r--restapi-call-node/provider/src/main/resources/vrf-service-configuration-information-template.json37
-rw-r--r--restapi-call-node/provider/src/main/resources/vrf-update-vlan-status-template.json33
-rw-r--r--restapi-call-node/provider/src/main/resources/vrf-update.json77
18 files changed, 1868 insertions, 0 deletions
diff --git a/restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/JsonParser.java b/restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/JsonParser.java
new file mode 100644
index 0000000..c03191a
--- /dev/null
+++ b/restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/JsonParser.java
@@ -0,0 +1,85 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdnc.restapicall;
+
+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 class JsonParser {
+
+ private static final Logger log = LoggerFactory.getLogger(JsonParser.class);
+
+ @SuppressWarnings("unchecked")
+ public static Map<String, String> convertToProperties(String s) throws JSONException {
+ JSONObject json = new JSONObject(s);
+
+ Map<String, Object> wm = new HashMap<String, Object>();
+ Iterator<String> ii = json.keys();
+ while (ii.hasNext()) {
+ String key1 = ii.next();
+ wm.put(key1, json.get(key1));
+ }
+
+ Map<String, String> mm = new HashMap<String, String>();
+
+ 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: " + key + "_length" + ": " + String.valueOf(ja.length()));
+
+ for (int i = 0; i < ja.length(); i++)
+ wm.put(key + '[' + i + ']', ja.get(i));
+ }
+ }
+
+ return mm;
+ }
+}
diff --git a/restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/RestapiCallNode.java b/restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/RestapiCallNode.java
new file mode 100644
index 0000000..d6d3529
--- /dev/null
+++ b/restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/RestapiCallNode.java
@@ -0,0 +1,701 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdnc.restapicall;
+
+import java.io.FileInputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.KeyStore;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.openecomp.sdnc.sli.SvcLogicContext;
+import org.openecomp.sdnc.sli.SvcLogicException;
+import org.openecomp.sdnc.sli.SvcLogicJavaPlugin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
+import com.sun.jersey.client.urlconnection.HTTPSProperties;
+
+public class RestapiCallNode implements SvcLogicJavaPlugin {
+
+ private static final Logger log = LoggerFactory.getLogger(RestapiCallNode.class);
+
+ private String uebServers;
+ private String defaultUebTemplateFileName = "/opt/bvc/restapi/templates/default-ueb-message.json";
+
+ public void sendRequest(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
+ HttpResponse r = null;
+ try {
+ Param p = getParameters(paramMap);
+
+ String pp = p.responsePrefix != null ? p.responsePrefix + '.' : "";
+
+ String req = null;
+ if (p.templateFileName != null) {
+ String reqTemplate = readFile(p.templateFileName);
+ req = buildXmlJsonRequest(ctx, reqTemplate, p.format);
+ }
+ r = sendHttpRequest(req, p);
+ setResponseStatus(ctx, p.responsePrefix, r);
+
+ if (r.body != null && r.body.trim().length() > 0) {
+ ctx.setAttribute(pp + "httpResponse", r.body);
+
+ if (p.convertResponse) {
+ Map<String, String> mm = null;
+ if (p.format == Format.XML)
+ mm = XmlParser.convertToProperties(r.body, p.listNameList);
+ else if (p.format == Format.JSON)
+ mm = JsonParser.convertToProperties(r.body);
+
+ if (mm != null)
+ for (String key : mm.keySet())
+ ctx.setAttribute(pp + key, mm.get(key));
+ }
+ }
+ } catch (Exception e) {
+ log.error("Error sending the request: " + e.getMessage(), e);
+
+ r = new HttpResponse();
+ r.code = 500;
+ r.message = e.getMessage();
+ String prefix = parseParam(paramMap, "responsePrefix", false, null);
+ setResponseStatus(ctx, prefix, r);
+ }
+
+ if (r != null && r.code >= 300)
+ throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message);
+ }
+
+ private Param getParameters(Map<String, String> paramMap) throws SvcLogicException {
+ Param p = new Param();
+ p.templateFileName = parseParam(paramMap, "templateFileName", false, null);
+ p.restapiUrl = parseParam(paramMap, "restapiUrl", true, null);
+ p.restapiUser = parseParam(paramMap, "restapiUser", true, null);
+ p.restapiPassword = parseParam(paramMap, "restapiPassword", true, null);
+ p.format = Format.fromString(parseParam(paramMap, "format", false, "json"));
+ p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", false, "post"));
+ p.responsePrefix = parseParam(paramMap, "responsePrefix", false, null);
+ p.listNameList = getListNameList(paramMap);
+ String skipSendingStr = paramMap.get("skipSending");
+ p.skipSending = skipSendingStr != null && skipSendingStr.equalsIgnoreCase("true");
+ p.convertResponse = Boolean.valueOf(parseParam(paramMap, "convertResponse", false, "true"));
+ p.trustStoreFileName = parseParam(paramMap, "trustStoreFileName", false, null);
+ p.trustStorePassword = parseParam(paramMap, "trustStorePassword", false, null);
+ p.keyStoreFileName = parseParam(paramMap, "keyStoreFileName", false, null);
+ p.keyStorePassword = parseParam(paramMap, "keyStorePassword", false, null);
+ p.ssl = p.trustStoreFileName != null && p.trustStorePassword != null && p.keyStoreFileName != null &&
+ p.keyStorePassword != null;
+ return p;
+ }
+
+ private Set<String> getListNameList(Map<String, String> paramMap) {
+ Set<String> ll = new HashSet<String>();
+ for (String key : paramMap.keySet())
+ if (key.startsWith("listName"))
+ ll.add(paramMap.get(key));
+ 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 RestapiCallNode");
+ }
+
+ s = s.trim();
+ String value = "";
+ 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 += s.substring(i, i1);
+ value += varValue;
+
+ i = i2 + 1;
+ i1 = s.indexOf('%', i);
+ }
+ value += s.substring(i);
+
+ log.info("Parameter " + name + ": [" + value + "]");
+ return value;
+ }
+
+ private static class Param {
+
+ public String templateFileName;
+ public String restapiUrl;
+ public String restapiUser;
+ public String restapiPassword;
+ public Format format;
+ public HttpMethod httpMethod;
+ public String responsePrefix;
+ public Set<String> listNameList;
+ public boolean skipSending;
+ public boolean convertResponse;
+ public String keyStoreFileName;
+ public String keyStorePassword;
+ public String trustStoreFileName;
+ public String trustStorePassword;
+ public boolean ssl;
+ }
+
+ private static enum Format {
+ JSON, XML;
+
+ public static Format fromString(String s) {
+ if (s == null)
+ return null;
+ if (s.equalsIgnoreCase("json"))
+ return JSON;
+ if (s.equalsIgnoreCase("xml"))
+ return XML;
+ throw new IllegalArgumentException("Invalid value for format: " + s);
+ }
+ }
+
+ private static enum HttpMethod {
+ GET, POST, PUT, DELETE;
+
+ public static HttpMethod fromString(String s) {
+ if (s == null)
+ return null;
+ if (s.equalsIgnoreCase("get"))
+ return GET;
+ if (s.equalsIgnoreCase("post"))
+ return POST;
+ if (s.equalsIgnoreCase("put"))
+ return PUT;
+ if (s.equalsIgnoreCase("delete"))
+ return DELETE;
+ throw new IllegalArgumentException("Invalid value for HTTP Method: " + s);
+ }
+ }
+
+ private String buildXmlJsonRequest(SvcLogicContext ctx, String template, Format format) {
+ log.info("Building " + format + " started");
+ long t1 = System.currentTimeMillis();
+
+ template = expandRepeats(ctx, template, 1);
+
+ Map<String, String> mm = new HashMap<>();
+ for (String s : ctx.getAttributeKeySet())
+ mm.put(s, ctx.getAttribute(s));
+
+ StringBuilder ss = new StringBuilder();
+ int i = 0;
+ while (i < template.length()) {
+ int i1 = template.indexOf("${", i);
+ if (i1 < 0) {
+ ss.append(template.substring(i));
+ break;
+ }
+
+ int i2 = template.indexOf('}', i1 + 2);
+ if (i2 < 0)
+ throw new RuntimeException("Template error: Matching } not found");
+
+ String var1 = template.substring(i1 + 2, i2);
+ String value1 = format == Format.XML ? XmlJsonUtil.getXml(mm, var1) : XmlJsonUtil.getJson(mm, var1);
+ // log.info(" " + var1 + ": " + value1);
+ if (value1 == null || value1.trim().length() == 0) {
+ // delete the whole element (line)
+ int i3 = template.lastIndexOf('\n', i1);
+ if (i3 < 0)
+ i3 = 0;
+ int i4 = template.indexOf('\n', i1);
+ if (i4 < 0)
+ i4 = template.length();
+
+ if (i < i3)
+ ss.append(template.substring(i, i3));
+ i = i4;
+ } else {
+ ss.append(template.substring(i, i1)).append(value1);
+ i = i2 + 1;
+ }
+ }
+
+ String req = format == Format.XML
+ ? XmlJsonUtil.removeEmptyStructXml(ss.toString()) : XmlJsonUtil.removeEmptyStructJson(ss.toString());
+
+ if (format == Format.JSON)
+ req = XmlJsonUtil.removeLastCommaJson(req);
+
+ long t2 = System.currentTimeMillis();
+ log.info("Building " + format + " completed. Time: " + (t2 - t1));
+
+ return req;
+ }
+
+ private String expandRepeats(SvcLogicContext ctx, String template, int level) {
+ StringBuilder newTemplate = new StringBuilder();
+ int k = 0;
+ while (k < template.length()) {
+ int i1 = template.indexOf("${repeat:", k);
+ if (i1 < 0) {
+ newTemplate.append(template.substring(k));
+ break;
+ }
+
+ int i2 = template.indexOf(':', i1 + 9);
+ if (i2 < 0)
+ throw new RuntimeException(
+ "Template error: Context variable name followed by : is required after repeat");
+
+ // Find the closing }, store in i3
+ int nn = 1;
+ int i3 = -1;
+ int i = i2;
+ while (nn > 0 && i < template.length()) {
+ i3 = template.indexOf('}', i);
+ if (i3 < 0)
+ throw new RuntimeException("Template error: Matching } not found");
+ int i32 = template.indexOf('{', i);
+ if (i32 >= 0 && i32 < i3) {
+ nn++;
+ i = i32 + 1;
+ } else {
+ nn--;
+ i = i3 + 1;
+ }
+ }
+
+ String var1 = template.substring(i1 + 9, i2);
+ String value1 = ctx.getAttribute(var1);
+ log.info(" " + var1 + ": " + value1);
+ int n = 0;
+ try {
+ n = Integer.parseInt(value1);
+ } catch (Exception e) {
+ n = 0;
+ }
+
+ newTemplate.append(template.substring(k, i1));
+
+ String rpt = template.substring(i2 + 1, i3);
+
+ for (int ii = 0; ii < n; ii++) {
+ String ss = rpt.replaceAll("\\[\\$\\{" + level + "\\}\\]", "[" + ii + "]");
+ if (ii == n - 1 && ss.trim().endsWith(",")) {
+ int i4 = ss.lastIndexOf(',');
+ if (i4 > 0)
+ ss = ss.substring(0, i4) + ss.substring(i4 + 1);
+ }
+ newTemplate.append(ss);
+ }
+
+ k = i3 + 1;
+ }
+
+ if (k == 0)
+ return newTemplate.toString();
+
+ return expandRepeats(ctx, newTemplate.toString(), level + 1);
+ }
+
+ private String readFile(String fileName) throws Exception {
+ byte[] encoded = Files.readAllBytes(Paths.get(fileName));
+ return new String(encoded, "UTF-8");
+ }
+
+ private HttpResponse sendHttpRequest(String request, Param p) throws Exception {
+ ClientConfig config = new DefaultClientConfig();
+ SSLContext ssl = null;
+ if (p.ssl && p.restapiUrl.startsWith("https"))
+ ssl = createSSLContext(p);
+ if (ssl != null) {
+ HostnameVerifier hostnameVerifier = new HostnameVerifier() {
+
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+ };
+
+ config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
+ new HTTPSProperties(hostnameVerifier, ssl));
+ }
+
+ logProperties(config.getProperties());
+
+ Client client = Client.create(config);
+ client.setConnectTimeout(5000);
+ client.addFilter(new HTTPBasicAuthFilter(p.restapiUser, p.restapiPassword));
+ WebResource webResource = client.resource(p.restapiUrl);
+
+ log.info("Sending request:");
+ log.info(request);
+ long t1 = System.currentTimeMillis();
+
+ HttpResponse r = new HttpResponse();
+ r.code = 200;
+
+ if (!p.skipSending) {
+ String tt = p.format == Format.XML ? "application/xml" : "application/json";
+ String tt1 = tt + ";charset=UTF-8";
+
+ ClientResponse response = null;
+ if (p.httpMethod == HttpMethod.GET)
+ response = webResource.accept(tt).type(tt1).get(ClientResponse.class);
+ else if (p.httpMethod == HttpMethod.POST)
+ response = webResource.accept(tt).type(tt1).post(ClientResponse.class, request);
+ else if (p.httpMethod == HttpMethod.PUT)
+ response = webResource.accept(tt).type(tt1).put(ClientResponse.class, request);
+ else if (p.httpMethod == HttpMethod.DELETE)
+ response = webResource.accept(tt).type(tt1).delete(ClientResponse.class, request);
+
+ r.code = response.getStatus();
+ r.headers = response.getHeaders();
+ EntityTag etag = response.getEntityTag();
+ if (etag != null)
+ r.message = etag.getValue();
+ if (response.hasEntity() && r.code != 204)
+ r.body = response.getEntity(String.class);
+ }
+
+ long t2 = System.currentTimeMillis();
+ log.info("Response received. Time: " + (t2 - t1));
+ log.info("HTTP response code: " + r.code);
+ log.info("HTTP response message: " + r.message);
+ logHeaders(r.headers);
+ log.info("HTTP response: " + r.body);
+
+ return r;
+ }
+
+ private SSLContext createSSLContext(Param p) {
+ try {
+ System.setProperty("jsse.enableSNIExtension", "false");
+ System.setProperty("javax.net.ssl.trustStore", p.trustStoreFileName);
+ System.setProperty("javax.net.ssl.trustStorePassword", p.trustStorePassword);
+
+ HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
+
+ @Override
+ public boolean verify(String string, SSLSession ssls) {
+ return true;
+ }
+ });
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ FileInputStream in = new FileInputStream(p.keyStoreFileName);
+ KeyStore ks = KeyStore.getInstance("PKCS12");
+ char[] pwd = p.keyStorePassword.toCharArray();
+ ks.load(in, pwd);
+ kmf.init(ks, pwd);
+
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ ctx.init(kmf.getKeyManagers(), null, null);
+ return ctx;
+ } catch (Exception e) {
+ log.error("Error creating SSLContext: " + e.getMessage(), e);
+ }
+ return null;
+ }
+
+ private static class HttpResponse {
+
+ public int code;
+ public String message;
+ public String body;
+ public MultivaluedMap<String, String> headers;
+ }
+
+ private void setResponseStatus(SvcLogicContext ctx, String prefix, HttpResponse r) {
+ String pp = prefix != null ? prefix + '.' : "";
+ ctx.setAttribute(pp + "response-code", String.valueOf(r.code));
+ ctx.setAttribute(pp + "response-message", r.message);
+ }
+
+ public void sendFile(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
+ HttpResponse r = null;
+ try {
+ FileParam p = getFileParameters(paramMap);
+ byte[] data = Files.readAllBytes(Paths.get(p.fileName));
+
+ r = sendHttpData(data, p);
+ setResponseStatus(ctx, p.responsePrefix, r);
+
+ } catch (Exception e) {
+ log.error("Error sending the request: " + e.getMessage(), e);
+
+ r = new HttpResponse();
+ r.code = 500;
+ r.message = e.getMessage();
+ String prefix = parseParam(paramMap, "responsePrefix", false, null);
+ setResponseStatus(ctx, prefix, r);
+ }
+
+ if (r != null && r.code >= 300)
+ throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message);
+ }
+
+ private static class FileParam {
+
+ public String fileName;
+ public String url;
+ public String user;
+ public String password;
+ public HttpMethod httpMethod;
+ public String responsePrefix;
+ public boolean skipSending;
+ }
+
+ private FileParam getFileParameters(Map<String, String> paramMap) throws SvcLogicException {
+ FileParam p = new FileParam();
+ p.fileName = parseParam(paramMap, "fileName", true, null);
+ p.url = parseParam(paramMap, "url", true, null);
+ p.user = parseParam(paramMap, "user", true, null);
+ p.password = parseParam(paramMap, "password", true, null);
+ p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", false, "post"));
+ p.responsePrefix = parseParam(paramMap, "responsePrefix", false, null);
+ String skipSendingStr = paramMap.get("skipSending");
+ p.skipSending = skipSendingStr != null && skipSendingStr.equalsIgnoreCase("true");
+ return p;
+ }
+
+ private HttpResponse sendHttpData(byte[] data, FileParam p) {
+ Client client = Client.create();
+ client.setConnectTimeout(5000);
+ client.setFollowRedirects(true);
+ client.addFilter(new HTTPBasicAuthFilter(p.user, p.password));
+ WebResource webResource = client.resource(p.url);
+
+ log.info("Sending file");
+ long t1 = System.currentTimeMillis();
+
+ HttpResponse r = new HttpResponse();
+ r.code = 200;
+
+ if (!p.skipSending) {
+ String tt = "application/octet-stream";
+
+ ClientResponse response = null;
+ if (p.httpMethod == HttpMethod.POST)
+ response = webResource.accept(tt).type(tt).post(ClientResponse.class, data);
+ else if (p.httpMethod == HttpMethod.PUT)
+ response = webResource.accept(tt).type(tt).put(ClientResponse.class, data);
+
+ r.code = response.getStatus();
+ r.headers = response.getHeaders();
+ EntityTag etag = response.getEntityTag();
+ if (etag != null)
+ r.message = etag.getValue();
+ if (response.hasEntity() && r.code != 204)
+ r.body = response.getEntity(String.class);
+
+ if (r.code == 301) {
+ String newUrl = response.getHeaders().getFirst("Location");
+
+ log.info("Got response code 301. Sending same request to URL: " + newUrl);
+
+ webResource = client.resource(newUrl);
+
+ if (p.httpMethod == HttpMethod.POST)
+ response = webResource.accept(tt).type(tt).post(ClientResponse.class, data);
+ else if (p.httpMethod == HttpMethod.PUT)
+ response = webResource.accept(tt).type(tt).put(ClientResponse.class, data);
+
+ r.code = response.getStatus();
+ etag = response.getEntityTag();
+ if (etag != null)
+ r.message = etag.getValue();
+ if (response.hasEntity() && r.code != 204)
+ r.body = response.getEntity(String.class);
+ }
+ }
+
+ long t2 = System.currentTimeMillis();
+ log.info("Response received. Time: " + (t2 - t1));
+ log.info("HTTP response code: " + r.code);
+ log.info("HTTP response message: " + r.message);
+ logHeaders(r.headers);
+ log.info("HTTP response: " + r.body);
+
+ return r;
+ }
+
+ public void postMessageOnUeb(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
+ HttpResponse r = null;
+ try {
+ UebParam p = getUebParameters(paramMap);
+
+ String pp = p.responsePrefix != null ? p.responsePrefix + '.' : "";
+
+ String req = null;
+
+ if (p.templateFileName == null) {
+ log.info("No template file name specified. Using default UEB template: " + defaultUebTemplateFileName);
+ p.templateFileName = defaultUebTemplateFileName;
+ }
+
+ String reqTemplate = readFile(p.templateFileName);
+ reqTemplate = reqTemplate.replaceAll("rootVarName", p.rootVarName);
+ req = buildXmlJsonRequest(ctx, reqTemplate, Format.JSON);
+
+ r = postOnUeb(req, p);
+ setResponseStatus(ctx, p.responsePrefix, r);
+ if (r.body != null)
+ ctx.setAttribute(pp + "httpResponse", r.body);
+
+ } catch (Exception e) {
+ log.error("Error sending the request: " + e.getMessage(), e);
+
+ r = new HttpResponse();
+ r.code = 500;
+ r.message = e.getMessage();
+ String prefix = parseParam(paramMap, "responsePrefix", false, null);
+ setResponseStatus(ctx, prefix, r);
+ }
+
+ if (r != null && r.code >= 300)
+ throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message);
+ }
+
+ private static class UebParam {
+
+ public String topic;
+ public String templateFileName;
+ public String rootVarName;
+ public String responsePrefix;
+ public boolean skipSending;
+ }
+
+ private UebParam getUebParameters(Map<String, String> paramMap) throws SvcLogicException {
+ UebParam p = new UebParam();
+ p.topic = parseParam(paramMap, "topic", true, null);
+ p.templateFileName = parseParam(paramMap, "templateFileName", false, null);
+ p.rootVarName = parseParam(paramMap, "rootVarName", false, null);
+ p.responsePrefix = parseParam(paramMap, "responsePrefix", false, null);
+ String skipSendingStr = paramMap.get("skipSending");
+ p.skipSending = skipSendingStr != null && skipSendingStr.equalsIgnoreCase("true");
+ return p;
+ }
+
+ private HttpResponse postOnUeb(String request, UebParam p) throws Exception {
+ String[] urls = uebServers.split(" ");
+ for (int i = 0; i < urls.length; i++) {
+ if (!urls[i].endsWith("/"))
+ urls[i] += "/";
+ urls[i] += "events/" + p.topic;
+ }
+
+ Client client = Client.create();
+ client.setConnectTimeout(5000);
+ WebResource webResource = client.resource(urls[0]);
+
+ log.info("UEB URL: " + urls[0]);
+ log.info("Sending request:");
+ log.info(request);
+ long t1 = System.currentTimeMillis();
+
+ HttpResponse r = new HttpResponse();
+ r.code = 200;
+
+ if (!p.skipSending) {
+ String tt = "application/json";
+ String tt1 = tt + ";charset=UTF-8";
+
+ ClientResponse response = webResource.accept(tt).type(tt1).post(ClientResponse.class, request);
+
+ r.code = response.getStatus();
+ r.headers = response.getHeaders();
+ if (response.hasEntity())
+ r.body = response.getEntity(String.class);
+ }
+
+ long t2 = System.currentTimeMillis();
+ log.info("Response received. Time: " + (t2 - t1));
+ log.info("HTTP response code: " + r.code);
+ logHeaders(r.headers);
+ log.info("HTTP response:\n" + r.body);
+
+ return r;
+ }
+
+ private void logProperties(Map<String, Object> 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 + ": " + String.valueOf(mm.get(name)));
+ }
+
+ private void logHeaders(MultivaluedMap<String, String> mm) {
+ log.info("HTTP response headers:");
+
+ if (mm == null)
+ return;
+
+ List<String> ll = new ArrayList<>();
+ for (Object o : mm.keySet())
+ ll.add((String) o);
+ Collections.sort(ll);
+
+ for (String name : ll)
+ log.info("--- " + name + ": " + String.valueOf(mm.get(name)));
+ }
+
+ public void setUebServers(String uebServers) {
+ this.uebServers = uebServers;
+ }
+
+ public void setDefaultUebTemplateFileName(String defaultUebTemplateFileName) {
+ this.defaultUebTemplateFileName = defaultUebTemplateFileName;
+ }
+}
diff --git a/restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/XmlJsonUtil.java b/restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/XmlJsonUtil.java
new file mode 100644
index 0000000..85175c3
--- /dev/null
+++ b/restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/XmlJsonUtil.java
@@ -0,0 +1,372 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdnc.restapicall;
+
+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 class XmlJsonUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(XmlJsonUtil.class);
+
+ 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;
+ }
+
+ Object o = createStructure(varmap, var);
+ return generateJson(o, escape);
+ }
+
+ 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 " + var + "_length:" + lengthStr);
+ }
+ }
+
+ 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 (String k : mm.keySet()) {
+ Object v = mm.get(k);
+ if (v instanceof String) {
+ String s = escape ? escapeXml((String) v) : (String) v;
+ ss.append(pad(indent)).append('<').append(k).append('>');
+ ss.append(s);
+ ss.append("</").append(k).append('>').append('\n');
+ } else if (v instanceof Map) {
+ ss.append(pad(indent)).append('<').append(k).append('>').append('\n');
+ ss.append(generateXml(v, indent + 1, escape));
+ ss.append(pad(indent)).append("</").append(k).append('>').append('\n');
+ } else if (v instanceof List) {
+ List<Object> ll = (List<Object>) v;
+ for (Object o1 : ll) {
+ ss.append(pad(indent)).append('<').append(k).append('>').append('\n');
+ ss.append(generateXml(o1, indent + 1, escape));
+ ss.append(pad(indent)).append("</").append(k).append('>').append('\n');
+ }
+ }
+ }
+ return ss.toString();
+ }
+
+ return null;
+ }
+
+ private static String generateJson(Object o, boolean escape) {
+ if (o == null)
+ return null;
+
+ StringBuilder ss = new StringBuilder();
+ generateJson(ss, o, 0, false, escape);
+ return ss.toString();
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void generateJson(StringBuilder ss, Object o, int indent, boolean padFirst, boolean escape) {
+ if (o instanceof String) {
+ String s = escape ? escapeJson((String) o) : (String) o;
+ if (padFirst)
+ ss.append(pad(indent));
+ ss.append('"').append(s).append('"');
+ 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 (String k : mm.keySet()) {
+ if (!first)
+ ss.append(",\n");
+ first = false;
+
+ Object v = mm.get(k);
+ ss.append(pad(indent + 1)).append('"').append(k).append("\": ");
+ generateJson(ss, v, indent + 1, false, escape);
+ }
+
+ 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);
+ }
+
+ 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) {
+ String s = "";
+ for (int i = 0; i < n; i++)
+ s += '\t';
+ return s;
+ }
+}
diff --git a/restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/XmlParser.java b/restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/XmlParser.java
new file mode 100644
index 0000000..cf461e9
--- /dev/null
+++ b/restapi-call-node/provider/src/main/java/org/openecomp/sdnc/restapicall/XmlParser.java
@@ -0,0 +1,160 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdnc.restapicall;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+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 class XmlParser {
+
+ private static final Logger log = LoggerFactory.getLogger(XmlParser.class);
+
+ public static Map<String, String> convertToProperties(String s, Set<String> listNameList) {
+ 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 (Exception e) {
+ e.printStackTrace();
+ }
+
+ return handler.getProperties();
+ }
+
+ private static class Handler extends DefaultHandler {
+
+ private Set<String> listNameList;
+
+ private Map<String, String> properties = new HashMap<>();
+
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ public Handler(Set<String> listNameList) {
+ super();
+ this.listNameList = listNameList;
+ if (this.listNameList == null)
+ this.listNameList = new HashSet<String>();
+ }
+
+ String currentName = "";
+ String currentValue = "";
+
+ @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 += '.';
+ currentName += name;
+
+ String listName = removeIndexes(currentName);
+
+ if (listNameList.contains(listName)) {
+ int len = getInt(properties, currentName + "_length");
+ properties.put(currentName + "_length", String.valueOf(len + 1));
+ currentName += "[" + len + "]";
+ }
+ }
+
+ @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);
+
+ if (currentValue.trim().length() > 0) {
+ currentValue = currentValue.trim();
+ properties.put(currentName, currentValue);
+
+ log.info("Added property: " + currentName + ": " + currentValue);
+
+ currentValue = "";
+ }
+
+ int i1 = currentName.lastIndexOf("." + name);
+ if (i1 <= 0)
+ currentName = "";
+ else
+ currentName = 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 += 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) {
+ String s = "";
+ 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)
+ s += c;
+ }
+ return s;
+ }
+ }
+}
diff --git a/restapi-call-node/provider/src/main/resources/META-INF/spring/restapi-call-node-context.xml b/restapi-call-node/provider/src/main/resources/META-INF/spring/restapi-call-node-context.xml
new file mode 100644
index 0000000..7aa4fc5
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/META-INF/spring/restapi-call-node-context.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<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" value="file:${SDNC_CONFIG_DIR}/ueb.properties" />
+ <property name="ignoreResourceNotFound" value="true" />
+ <property name="ignoreUnresolvablePlaceholders" value="true" />
+ </bean>
+
+ <!-- context:property-placeholder location="file:${SDNC_CONFIG_DIR}/ueb.properties" /-->
+
+ <bean id="restapiCallNode" class="org.openecomp.sdnc.restapicall.RestapiCallNode">
+ <property name="uebServers" value="${servers}" />
+ </bean>
+
+</beans>
diff --git a/restapi-call-node/provider/src/main/resources/META-INF/spring/restapi-call-node-osgi-context.xml b/restapi-call-node/provider/src/main/resources/META-INF/spring/restapi-call-node-osgi-context.xml
new file mode 100644
index 0000000..aa12761
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/META-INF/spring/restapi-call-node-osgi-context.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<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="restapiCallNode" interface="org.openecomp.sdnc.restapicall.RestapiCallNode" />
+
+</beans:beans>
diff --git a/restapi-call-node/provider/src/main/resources/default-ueb-message.json b/restapi-call-node/provider/src/main/resources/default-ueb-message.json
new file mode 100644
index 0000000..4b1aa03
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/default-ueb-message.json
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+ "event":{
+ "header":{
+ "eventSource":"sdn-c"
+ },
+ "body":
+
+${rootVarName}
+
+ }
+}
diff --git a/restapi-call-node/provider/src/main/resources/get-multicast-data.json b/restapi-call-node/provider/src/main/resources/get-multicast-data.json
new file mode 100644
index 0000000..f6155ee
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/get-multicast-data.json
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+ "input": {
+ "sdnc-request-header": {
+ "svc-request-id": ${connection-details-notification-input.configuration-response-common.svc-request-id},
+ "svc-action": "updatemulticastvpn"
+ },
+ "service-information": {
+ "service-type": "AVPN",
+ "service-instance-id": ${tmp.ete-vpn-key}
+ }
+ }
+}
+
diff --git a/restapi-call-node/provider/src/main/resources/northbound-api-template.json b/restapi-call-node/provider/src/main/resources/northbound-api-template.json
new file mode 100644
index 0000000..d48c41c
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/northbound-api-template.json
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+"input":
+ {
+ "sdnc-request-header":{
+ "svc-request-id": ${service-topology-operation-input.sdnc-request-header.svc-request-id},
+ "svc-notification-url": ${service-topology-operation-input.sdnc-request-header.svc-notification-url}
+ },
+ "request-information":{
+ "request-id": ${service-topology-operation-input.request-information.request-id},
+ "request-action": ${service-topology-operation-input.request-information.request-action},
+ "request-sub-action": ${service-topology-operation-input.request-information.request-sub-action},
+ "source": ${service-topology-operation-input.request-information.source},
+ "notification-url": ${service-topology-operation-input.request-information.notification-url}
+ },
+ "service-information":{
+ "service-type": ${service-topology-operation-input.service-information.service-type},
+ "service-instance-id": ${service-topology-operation-input.service-information.service-instance-id},
+ "subscriber-name": ${service-topology-operation-input.service-information.subscriber-name},
+ "subscriber-global-id": ${service-topology-operation-input.service-information.subscriber-global-id}
+ }
+}
+
diff --git a/restapi-call-node/provider/src/main/resources/northbound-api-template.xml b/restapi-call-node/provider/src/main/resources/northbound-api-template.xml
new file mode 100644
index 0000000..3738840
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/northbound-api-template.xml
@@ -0,0 +1,41 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+ <input xmlns="${northbound-xmlNS}">
+ <request-information>
+ <notification-url>${service-topology-operation-input.request-information.notification-url}</notification-url>
+ <request-action>${service-topology-operation-input.request-information.request-action}</request-action>
+ <request-id>${service-topology-operation-input.request-information.request-id}</request-id>
+ <request-sub-action>${service-topology-operation-input.request-information.request-sub-action}</request-sub-action>
+ <source>${service-topology-operation-input.request-information.source}</source>
+ </request-information>
+ <sdnc-request-header>
+ <svc-notification-url>${service-topology-operation-input.sdnc-request-header.svc-notification-url}</svc-notification-url>
+ <svc-request-id>${service-topology-operation-input.sdnc-request-header.svc-request-id}</svc-request-id>
+ </sdnc-request-header>
+ <service-information>
+ <service-instance-id>${service-topology-operation-input.service-information.service-instance-id}</service-instance-id>
+ <service-type>${service-topology-operation-input.service-information.service-type}</service-type>
+ <subscriber-global-id>${service-topology-operation-input.service-information.subscriber-global-id}</subscriber-global-id>
+ <subscriber-name>${service-topology-operation-input.service-information.subscriber-name}</subscriber-name>
+ </service-information>
+ ${'northbound-anyData}
+ </input>
diff --git a/restapi-call-node/provider/src/main/resources/service-configuration-notification-northbound-template.json b/restapi-call-node/provider/src/main/resources/service-configuration-notification-northbound-template.json
new file mode 100644
index 0000000..347793f
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/service-configuration-notification-northbound-template.json
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+ "input": {
+ "svc-request-id": ${service-configuration-notification-input.svc-request-id},
+ "response-code": ${service-configuration-notification-input.response-code},
+ "response-message": ${service-configuration-notification-input.response-message},
+ "ack-final-indicator": ${service-configuration-notification-input.ack-final-indicator},
+ "service-information": {
+ "service-type": "SERVICE1",
+ "service-instance-id": ${service-data.service-information.service-instance-id},
+ "subscriber-name": ${service-data.service-information.subscriber-name},
+ "subscriber-global-id": ${service-data.service-information.subscriber-global-id}
+ },
+ "response-parameters": [
+ ${repeat:service-configuration-notification-input.response-parameters_length:
+ {
+ "sequence-number": ${service-configuration-notification-input.response-parameters[${1}].sequence-number},
+ "tag-name": ${service-configuration-notification-input.response-parameters[${1}].tag-name},
+ "tag-value": ${service-configuration-notification-input.response-parameters[${1}].tag-value}
+ }
+ }
+ ]
+ }
+}
diff --git a/restapi-call-node/provider/src/main/resources/update-vpe-data-with-apply-group.json b/restapi-call-node/provider/src/main/resources/update-vpe-data-with-apply-group.json
new file mode 100644
index 0000000..a82a6b4
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/update-vpe-data-with-apply-group.json
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+ "vrf-export-details": [
+ ${repeat:restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.VrfExport_length:
+ {
+ "vrf-export": ${restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.VrfExport[${1}]}
+ }
+ }
+ ],
+ "vrf-import-details": [
+ ${repeat:restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.VrfImport_length:
+ {
+ "vrf-import": ${restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.VrfImport[${1}]}
+ }
+ }
+ ],
+ "apply-group-template": [
+ ${repeat:restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.ApplyGroup_length:
+ {
+ "apply-group": ${restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.ApplyGroup[${1}].ApplyGroup}
+ }
+ }
+ ],
+ "community-list": [
+ ${repeat:restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.CommunityList_length:
+ {
+ "member": ${restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.CommunityList[${1}].member},
+ "name": ${restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.CommunityList[${1}].name}
+ }
+ }
+ ]
+}
+
diff --git a/restapi-call-node/provider/src/main/resources/vnf-information-update.json b/restapi-call-node/provider/src/main/resources/vnf-information-update.json
new file mode 100644
index 0000000..425f0f3
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/vnf-information-update.json
@@ -0,0 +1,24 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+"generic-vnf-service" :${vnf-service.generic-vnf-service}
+}
diff --git a/restapi-call-node/provider/src/main/resources/vpn-allocation-request.json b/restapi-call-node/provider/src/main/resources/vpn-allocation-request.json
new file mode 100644
index 0000000..6c84274
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/vpn-allocation-request.json
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+ "AllocateVpnResourcesRequest": {
+ "message-id": "${service-data.oper-status.modify-timestamp}",
+ "service-instance-id": "${service-data.service-information.service-instance-id}",
+ "vrf-request-type": {
+ "vpn-id": "${service-data.avpn-logicalchannel-information.vpn-id}",
+ "vpn-service": "${service-data.service-information.service-type}",
+ "e2e-vpn-id": "${service-data.avpn-logicalchannel-information.e2e-vpn-id}",
+ "vpe-name": "${service-data.avpn-logicalchannel-information.evc-endpoint-information.vpe-name}",
+ "asn": "${service-data.avpn-logicalchannel-information.carrier-asn}",
+ "route-group-name": "${service-data.avpn-logicalchannel-information.bgp-options.neighbor-address-information.route-group-name}",
+ "hub-or-spoke": "${service-data.avpn-logicalchannel-information.hub-or-spoke}"
+ }
+ }
+}
diff --git a/restapi-call-node/provider/src/main/resources/vpn-information-update.json b/restapi-call-node/provider/src/main/resources/vpn-information-update.json
new file mode 100644
index 0000000..7977066
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/vpn-information-update.json
@@ -0,0 +1,24 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+"vpn-information" :${vpe-vpn-service.vpn-information}
+}
diff --git a/restapi-call-node/provider/src/main/resources/vrf-service-configuration-information-template.json b/restapi-call-node/provider/src/main/resources/vrf-service-configuration-information-template.json
new file mode 100644
index 0000000..f7e8432
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/vrf-service-configuration-information-template.json
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+ "input": {
+
+ "e2e-vpn-key": ${service-data.avpn-logicalchannel-information.e2e-vpn-id},
+ "logical-channel-id": ${service-data.service-information.service-instance-id},
+ "vpe-name": ${service-data.avpn-logicalchannel-information.evc-endpoint-information.vpe-name},
+ "rpc-action": ${tmp.rpc-action},
+
+ "vpn-information": ${vpe-vpn-service.vpn-information},
+ "vrf-details": ${vpe-vpn-service.vpn-information.vrf-details},
+ "vrf-vlan-resources": {
+ "logical-channel-id": ${service-data.service-information.service-instance-id},
+ "logical-channel-status": ${tmp.logical-channel-status}
+ }
+ }
+}
diff --git a/restapi-call-node/provider/src/main/resources/vrf-update-vlan-status-template.json b/restapi-call-node/provider/src/main/resources/vrf-update-vlan-status-template.json
new file mode 100644
index 0000000..7a6cab3
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/vrf-update-vlan-status-template.json
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+ "input": {
+ "e2e-vpn-key": ${service-data.avpn-logicalchannel-information.e2e-vpn-id},
+ "logical-channel-id": ${service-data.service-information.service-instance-id},
+ "vpe-name": ${service-data.avpn-logicalchannel-information.evc-endpoint-information.vpe-name},
+ "rpc-action": ${tmp.rpc-action},
+ "vrf-vlan-resources": {
+ "logical-channel-id": ${service-data.service-information.service-instance-id},
+ "logical-channel-status": ${tmp.logical-channel-status}
+ }
+ }
+}
diff --git a/restapi-call-node/provider/src/main/resources/vrf-update.json b/restapi-call-node/provider/src/main/resources/vrf-update.json
new file mode 100644
index 0000000..778e4b2
--- /dev/null
+++ b/restapi-call-node/provider/src/main/resources/vrf-update.json
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+ "vpn-vame": ${allocate-vpn-resource-notification-input.vpn-data[0].vpn-name},
+ "vpn-id": ${allocate-vpn-resource-notification-input.vpn-data[0].vpn-id},
+ "vrf-details": [
+ ${repeat:allocate-vpn-resource-notification-input.vpn-data[0].vrf-information_length:
+ {
+ "vrf-export-details": [
+ ${repeat:allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].vrf-export-details_length:
+ {
+ "vrf-export": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].vrf-export-details[${2}].vrf-export}
+ }
+ }
+ ],
+ "vrf-name": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].vrf-name},
+ "vpe-name": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].vpe-name},
+ "vrf-import-details": [
+ ${repeat:allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].vrf-import-details_length:
+ {
+ "vrf-import": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].vrf-import-details[${2}].vrf-import}
+ }
+ }
+ ],
+ "apply-group-template": [
+ ${repeat:allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].apply-group-template_length:
+ {
+ "apply-group": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].apply-group-template[${2}].apply-group}
+ }
+ }
+ ],
+ "community-list": [
+ ${repeat:allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].community-list_length:
+ {
+ "member": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].community-list[${2}].name},
+ "name": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].community-list[${2}].member}
+ }
+ }
+ ],
+ "router-distinguisher": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].router-distinguisher}
+ }
+ }
+ ],
+ "spoke-routes": {
+ "route-target": ${allocate-vpn-resource-notification-input.vpn-data[0].spoke-route-target.route-target}
+ },
+
+ "route-target-details": [
+ ${repeat:allocate-vpn-resource-notification-input.vpn-data[0].route-target-details_length:
+ {
+ "route-target": ${allocate-vpn-resource-notification-input.vpn-data[0].route-target-details[${1}].route-target},
+ "route-target-type": ${allocate-vpn-resource-notification-input.vpn-data[0].route-target-details[${1}].route-target-type}
+ }
+ }
+ ],
+
+ "e2e-vpn-key": ${allocate-vpn-resource-notification-input.vpn-data[0].e2e-vpn-id}
+}