Added support for external_key and resource_name

Change-Id: Ic44f24c3228e6ffcabb23b3866aaab01cb2f552b
Issue-ID: CCSDK-341
Signed-off-by: Alexis de Talhouët <adetalhouet89@gmail.com>
diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java
index 54700f6..e7b5284 100644
--- a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java
+++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java
@@ -21,6 +21,7 @@
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Map;
+import javax.sql.rowset.CachedRowSet;
 import org.apache.http.HttpResponse;
 import org.apache.http.util.EntityUtils;
 import org.onap.ccsdk.sli.adaptors.netbox.api.NetboxClient;
@@ -38,20 +39,38 @@
 
     private static final Logger LOG = LoggerFactory.getLogger(NetboxClientImpl.class);
 
+    // Netbox URI
+
     private static final String NEXT_AVAILABLE_IP_IN_PREFIX_PATH = "/api/ipam/prefixes/%s/available-ips/";
     private static final String IP_ADDRESS_PATH = "/api/ipam/ip-addresses/%s/";
-    private static final String EMPTY_STRING = "";
+
+    // Netbox Payload
+
+    private static final String ASSIGN_IP_ADDRESS_PAYLOAD = "{\n"
+        + "  \"custom_fields\": {\n"
+        + "    \"external-key\": \"%s\",\n"
+        + "    \"resource-name\": \"%s\"\n"
+        + "  }\n"
+        + "}";
+
+    // Service Logic Context input variables and exception
+
     private static final String SERVICE_INSTANCE_ID_PROP = "service_instance_id";
     private static final String VF_MODULE_ID_PROP = "vf_module_id";
+    private static final String EXTERNAL_KEY_PROP = "external_key";
+    private static final String SQL_EXCEPTION_MESSAGE = "Caught SQL exception";
+
+    // SQL statement
 
     private static final String ASSIGN_IP_SQL_STATEMENT =
-        "INSERT INTO IPAM_IP_ASSIGNEMENT (service_instance_id, vf_module_id, prefix_id, ip_address_id, ip_address, ip_status, ip_response_json) \n"
+        "INSERT INTO IPAM_IP_ASSIGNEMENT (service_instance_id, vf_module_id, prefix_id, ip_address_id, ip_address, ip_status, ip_response_json, external_key) \n"
             + "VALUES (?, ?, ?, ?, ?, ?, ?)";
     private static final String UNASSIGN_IP_SQL_STATEMENT =
-        "UPDATE IPAM_IP_ASSIGNEMENT SET ip_status = ? WHERE service_instance_id = ? AND vf_module_id = ? AND ip_address_id = ?";
+        "UPDATE IPAM_IP_ASSIGNEMENT SET ip_status = ? WHERE service_instance_id = ? AND external_key = ?";
+    private static final String GET_IP_ADDRESS_ID_SQL_STATEMENT =
+        "SELECT ip_address_id FROM IPAM_IP_ASSIGNEMENT WHERE service_instance_id = ? AND external_key = ?";
 
     private final NetboxHttpClient client;
-
     private final DbLibService dbLibService;
 
     public NetboxClientImpl(final NetboxHttpClient client, final DbLibService dbLibService) {
@@ -64,23 +83,24 @@
 
         try {
             SliPluginUtils
-                .checkParameters(parameters, new String[]{SERVICE_INSTANCE_ID_PROP, VF_MODULE_ID_PROP, "prefix_id"},
-                    LOG);
+                .checkParameters(parameters,
+                    new String[]{SERVICE_INSTANCE_ID_PROP, VF_MODULE_ID_PROP, "prefix_id", "resource_name",
+                        EXTERNAL_KEY_PROP}, LOG);
         } catch (SvcLogicException e) {
             return QueryStatus.FAILURE;
         }
 
         final String serviceInstanceId = parameters.get(SERVICE_INSTANCE_ID_PROP);
-        LOG.trace("assignIpAddress: service_instance_id = {}", serviceInstanceId);
         final String vfModuleId = parameters.get(VF_MODULE_ID_PROP);
-        LOG.trace("assignIpAddress: vf_module_id = {}", vfModuleId);
         final String prefixId = parameters.get("prefix_id");
-        LOG.trace("assignIpAddress: prefix_id = {}", prefixId);
+        final String resourceName = parameters.get("resource_name");
+        final String externalKey = parameters.get(EXTERNAL_KEY_PROP);
 
         HttpResponse httpResp;
         try {
             httpResp = client
-                .post(String.format(NEXT_AVAILABLE_IP_IN_PREFIX_PATH, prefixId), EMPTY_STRING);
+                .post(String.format(NEXT_AVAILABLE_IP_IN_PREFIX_PATH, prefixId),
+                    String.format(ASSIGN_IP_ADDRESS_PAYLOAD, externalKey, resourceName));
         } catch (IOException e) {
             LOG.error("Fail to assign IP for Prefix(id={}). {}", prefixId, e.getMessage(), e.getCause());
             return QueryStatus.FAILURE;
@@ -109,18 +129,20 @@
             return QueryStatus.FAILURE;
         }
 
-        ArrayList<String> args = Lists.newArrayList(serviceInstanceId,
+        ArrayList<String> args = Lists.newArrayList(
+            serviceInstanceId,
             vfModuleId,
             String.valueOf(prefixId),
             String.valueOf(ipAddress.getId()),
             ipAddress.getAddress(),
             IPStatus.ASSIGNED.name(),
-            ipamRespJson);
+            ipamRespJson,
+            externalKey);
 
         try {
             dbLibService.writeData(ASSIGN_IP_SQL_STATEMENT, args, null);
         } catch (SQLException e) {
-            LOG.error("Caught SQL exception", e);
+            LOG.error(SQL_EXCEPTION_MESSAGE, e);
             return QueryStatus.FAILURE;
         }
 
@@ -133,18 +155,26 @@
     public QueryStatus unassignIpAddress(final Map<String, String> parameters, final SvcLogicContext ctx) {
         try {
             SliPluginUtils
-                .checkParameters(parameters, new String[]{SERVICE_INSTANCE_ID_PROP, VF_MODULE_ID_PROP, "ip_address_id"},
+                .checkParameters(parameters, new String[]{SERVICE_INSTANCE_ID_PROP, EXTERNAL_KEY_PROP},
                     LOG);
         } catch (SvcLogicException e) {
             return QueryStatus.FAILURE;
         }
 
         final String serviceInstanceId = parameters.get(SERVICE_INSTANCE_ID_PROP);
-        LOG.trace("assignIpAddress: service_instance_id = {}", serviceInstanceId);
-        final String vfModuleId = parameters.get(VF_MODULE_ID_PROP);
-        LOG.trace("assignIpAddress: vf_module_id = {}", vfModuleId);
-        final String ipAddressId = parameters.get("ip_address_id");
-        LOG.trace("assignIpAddress: ip_address_id = {}", ipAddressId);
+        final String externalKey = parameters.get(EXTERNAL_KEY_PROP);
+
+        String ipAddressId;
+        ArrayList<String> args = Lists.newArrayList(
+            serviceInstanceId,
+            externalKey);
+        try (CachedRowSet row = dbLibService.getData(GET_IP_ADDRESS_ID_SQL_STATEMENT, args, null)) {
+            ipAddressId = row.getString("ip_address_id");
+        } catch (SQLException e) {
+            LOG.error(SQL_EXCEPTION_MESSAGE, e);
+            return QueryStatus.FAILURE;
+        }
+
         HttpResponse httpResp;
         try {
             httpResp = client.delete(String.format(IP_ADDRESS_PATH, ipAddressId));
@@ -160,15 +190,16 @@
             return QueryStatus.FAILURE;
         }
 
-        ArrayList<String> args = Lists.newArrayList(
-            IPStatus.UNASSIGNED.name(),
+        args.clear();
+        args = Lists.newArrayList(
+            IPStatus.DELETED.name(),
             serviceInstanceId,
-            vfModuleId,
-            String.valueOf(ipAddressId));
+            externalKey);
+
         try {
             dbLibService.writeData(UNASSIGN_IP_SQL_STATEMENT, args, null);
         } catch (SQLException e) {
-            LOG.error("Caught SQL exception", e);
+            LOG.error(SQL_EXCEPTION_MESSAGE, e);
             return QueryStatus.FAILURE;
         }
 
diff --git a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPStatus.java b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPStatus.java
index 05cc1ea..f3a7438 100644
--- a/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPStatus.java
+++ b/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPStatus.java
@@ -1,5 +1,5 @@
 package org.onap.ccsdk.sli.adaptors.netbox.model;
 
 public enum IPStatus {
-    ASSIGNED, UNASSIGNED, PENDING_ASSIGN, PENDING_UNASSIGN
+    ASSIGNED, DELETED
 }
diff --git a/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImplTest.java b/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImplTest.java
index 0f887a6..bc81f0b 100644
--- a/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImplTest.java
+++ b/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImplTest.java
@@ -32,7 +32,9 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 
 import ch.qos.logback.classic.spi.ILoggingEvent;
@@ -48,6 +50,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
+import javax.sql.rowset.CachedRowSet;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -89,7 +92,8 @@
         .of("service_instance_id", serviceInstanceId,
             "vf_module_id", vfModuleId,
             "prefix_id", "3",
-            "ip_address_id", "3"
+            "external_key", "3",
+            "resource_name", "3"
         );
 
     private NetboxHttpClient httpClient;
@@ -133,12 +137,18 @@
     public void unassignIpAddressTestNoParams() {
         QueryStatus status = netboxClient.unassignIpAddress(ImmutableMap.of(), svcLogicContext);
         Assert.assertEquals(QueryStatus.FAILURE, status);
-        verifyLogEntry("This method requires the parameters [service_instance_id,vf_module_id,ip_address_id], but no parameters were passed in");
+        verifyLogEntry(
+            "This method requires the parameters [service_instance_id,external_key], but no parameters were passed in.");
     }
 
     @Test
-    public void unassignIpAddressFailedRequest() throws IOException {
+    public void unassignIpAddressFailedRequest() throws IOException, SQLException {
         doThrow(new IOException("Failed request")).when(httpClientMock).delete(anyString());
+
+        CachedRowSet crs = mock(CachedRowSet.class);
+        doReturn("3").when(crs).getString(eq("ip_address_id"));
+        doReturn(crs).when(dbLib).getData(anyString(), any(ArrayList.class), eq(null));
+
         QueryStatus status = netboxClientMock
             .unassignIpAddress(params, svcLogicContext);
 
@@ -147,11 +157,15 @@
     }
 
     @Test
-    public void unassignIpAddressServerError() {
+    public void unassignIpAddressServerError() throws SQLException {
 
         String expectedUrl = "/api/ipam/ip-addresses/3/";
         givenThat(delete(urlEqualTo(expectedUrl)).willReturn(serverError()));
 
+        CachedRowSet crs = mock(CachedRowSet.class);
+        doReturn("3").when(crs).getString(eq("ip_address_id"));
+        doReturn(crs).when(dbLib).getData(anyString(), any(ArrayList.class), eq(null));
+
         QueryStatus status = netboxClient.unassignIpAddress(params, svcLogicContext);
 
         Assert.assertEquals(QueryStatus.FAILURE, status);
@@ -166,6 +180,10 @@
         String expectedUrl = "/api/ipam/ip-addresses/3/";
         givenThat(delete(urlEqualTo(expectedUrl)).willReturn(created().withBody(response)));
 
+        CachedRowSet crs = mock(CachedRowSet.class);
+        doReturn("3").when(crs).getString(eq("ip_address_id"));
+        doReturn(crs).when(dbLib).getData(anyString(), any(ArrayList.class), eq(null));
+
         doThrow(new SQLException("Failed")).when(dbLib).writeData(anyString(), any(ArrayList.class), eq(null));
 
         QueryStatus status = netboxClient.unassignIpAddress(params, svcLogicContext);
@@ -181,6 +199,10 @@
         String expectedUrl = "/api/ipam/ip-addresses/3/";
         givenThat(delete(urlEqualTo(expectedUrl)).willReturn(created().withBody(response)));
 
+        CachedRowSet crs = mock(CachedRowSet.class);
+        doReturn("3").when(crs).getString(eq("ip_address_id"));
+        doReturn(crs).when(dbLib).getData(anyString(), any(ArrayList.class), eq(null));
+
         QueryStatus status = netboxClient.unassignIpAddress(params, svcLogicContext);
 
         verify(deleteRequestedFor(urlEqualTo(expectedUrl))
@@ -197,7 +219,8 @@
     public void nextAvailableIpInPrefixTestNoId() {
         QueryStatus status = netboxClient.assignIpAddress(ImmutableMap.of(), svcLogicContext);
         Assert.assertEquals(QueryStatus.FAILURE, status);
-        verifyLogEntry("This method requires the parameters [service_instance_id,vf_module_id,prefix_id], but no parameters were passed in");
+        verifyLogEntry(
+            "This method requires the parameters [service_instance_id,vf_module_id,prefix_id,resource_name,external_key], but no parameters were passed in.");
     }
 
     @Test