accept a la carte create instance group request

Updated postBPELRequest to accept RequestClientParameter
Switched to using .toString rather than .name for enum
Added source to fix failing test
Added action to fix failing apih tests
Removed unused headers from test
Removed unused import from RequestClientParameter
Updated to use instanceGroupId constant
Removed defaulting source in requestInfo
Added validation for mandatory headers
Added test case for modelVersionId in service related instance
Added relatedInstance validation for create instanceGroup
Added unit test cases for MembersValidation
Added test cases for relatedInstances validation
Added tests for add/remove member validation
Added updates for deleteInstanceGroups
Removed serviceProxy from test resource file
Removed ServiceProxy as it is no longer needed
Changed action to be removeMembers in endpoint
Added removeMembers endpoint and validation
Updated validation for create instanceGroups
...

Change-Id: I12b14d6d81dd0690eea33dfcbf1be17c509f9832
Issue-ID: SO-1207
Signed-off-by: Benjamin, Max (mb388a) <mb388a@us.att.com>
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/java/org/onap/so/apihandlerinfra/MsoRequestTest.java b/mso-api-handlers/mso-api-handler-infra/src/test/java/org/onap/so/apihandlerinfra/MsoRequestTest.java
index a9d848f..aa51704 100644
--- a/mso-api-handlers/mso-api-handler-infra/src/test/java/org/onap/so/apihandlerinfra/MsoRequestTest.java
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/java/org/onap/so/apihandlerinfra/MsoRequestTest.java
@@ -179,6 +179,7 @@
 		this.version = "v" + reqVersion;
 		this.instanceIdMapTest.put("serviceInstanceId", "ff305d54-75b4-431b-adb2-eb6b9e5ff000");
 		this.instanceIdMapTest.put("vnfInstanceId", "ff305d54-75b4-431b-adb2-eb6b9e5ff000");
+		this.instanceIdMapTest.put("instanceGroupId", "ff305d54-75b4-431b-adb2-eb6b9e5ff000");
 		thrown.expect(ValidationException.class);
 		thrown.expectMessage(expectedException);
 		this.msoRequest = new MsoRequest();
@@ -243,6 +244,7 @@
 			{"No valid modelVersionId is specified", mapper.readValue(inputStream("/ModelInfo/v5ActivateModelVersionId.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.activateInstance, 5},
 			{"No valid modelVersionId is specified", mapper.readValue(inputStream("/ModelInfo/ScaleOutNoModelVersionId.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.scaleOut, 7},
 			{"No valid modelVersionId is specified", mapper.readValue(inputStream("/ModelInfo/VnfRecreateModelVersionId.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.recreateInstance, 7},
+			{"No valid modelVersionId is specified", mapper.readValue(inputStream("/ModelInfo/CreateInstanceGroupNoModelVersionId.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.createInstance, 7},
 			//ValidationException for Platform and LineOfBusiness
 			{"No valid lineOfBusinessName is specified", mapper.readValue(inputStream("/PlatformAndLineOfBusiness/EmptyLineOfBusiness.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.createInstance, 5},
 			{"No valid platform is specified", mapper.readValue(inputStream("/PlatformAndLineOfBusiness/Platform.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.createInstance, 6},
@@ -286,6 +288,9 @@
 			{"No valid source vnf relatedInstance for Port Configuration is specified", mapper.readValue(inputStream("/RelatedInstances/v5CreateNoSourceRelatedInstance.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.createInstance, 5},
 			{"No valid vnfInstanceId matching the vnfInstanceId in request URI is specified", mapper.readValue(inputStream("/RelatedInstances/RelatedInstancesVnfInstanceId.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.activateInstance, 5},
 			{"No valid instanceName format is specified", mapper.readValue(inputStream("/RelatedInstances/InvalidInstanceName.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.createInstance, 2},
+			{"No valid relatedInstanceList is specified", mapper.readValue(inputStream("/RelatedInstances/CreateInstanceGroupNoRelatedInstances.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.createInstance, 7},
+			{"No valid related service instance for instanceGroup request is specified", mapper.readValue(inputStream("/RelatedInstances/CreateInstanceGroupService.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.createInstance, 7},
+			{"No valid modelVersionId in relatedInstance is specified", mapper.readValue(inputStream("/RelatedInstances/CreateInstanceGroupRelatedInstanceModelVersionId.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.createInstance, 7},
 			//ValidationException for RequestInfo
 			{"No valid requestInfo is specified", mapper.readValue(inputStream("/RequestInfo/RequestInfoNull.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.createInstance, 5},
 			{"No valid requestInfo is specified", mapper.readValue(inputStream("/RequestInfo/RequestInfo.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.applyUpdatedConfig, 6},
@@ -328,7 +333,15 @@
 			{"No valid modelCustomizationId in userParams vnf resources is specified", mapper.readValue(inputStream("/RequestParameters/VnfModelCustomizationId.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.assignInstance, 7},
 			{"No valid modelCustomizationId in userParams network resources is specified", mapper.readValue(inputStream("/RequestParameters/NetworkModelCustomizationId.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.assignInstance, 7},
 			//Validation for ConfigurationParameters
-			{"No valid configuration parameters is specified", mapper.readValue(inputStream("/ConfigurationParameters/NoConfigurationParameters.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.scaleOut, 7}
+			{"No valid configuration parameters is specified", mapper.readValue(inputStream("/ConfigurationParameters/NoConfigurationParameters.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.scaleOut, 7},
+			//Validation for Add and Remove Members
+			{"No valid vnf relatedInstance is specified", mapper.readValue(inputStream("/MembersValidation/RelatedInstancesVnf.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.addMembers, 7},
+			{"No valid related instances is specified", mapper.readValue(inputStream("/MembersValidation/RelatedInstances.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.addMembers, 7},
+			{"No valid requestInfo is specified", mapper.readValue(inputStream("/MembersValidation/MembersRequestInfo.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.addMembers, 7},
+			{"No valid requestorId is specified", mapper.readValue(inputStream("/MembersValidation/MembersRequestorId.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.addMembers, 7},
+			{"No valid source is specified", mapper.readValue(inputStream("/MembersValidation/AddMembersSource.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.addMembers, 7},
+			{"No valid instanceId in relatedInstances is specified", mapper.readValue(inputStream("/MembersValidation/AddMembersInstanceId.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.addMembers, 7},
+			{"No valid modelType in relatedInstance is specified", mapper.readValue(inputStream("/MembersValidation/DeleteMembersModelType.json"), ServiceInstancesRequest.class), instanceIdMapTest, Action.removeMembers, 7}
 		});
 	}
 	@Test
@@ -415,6 +428,18 @@
 		this.msoRequest.parse(sir, instanceIdMapTest, action, version, originalRequestJSON, reqVersion, false);
 	}
 	@Test
+	public void instanceGroupIdHashMapFailureTest() throws JsonParseException, JsonMappingException, IOException, ValidationException{
+		this.sir = mapper.readValue(inputStream("/SuccessfulValidation/InstanceIdHashMap.json"), ServiceInstancesRequest.class);
+		this.instanceIdMapTest.put("instanceGroupId", "test");
+		this.action = Action.createInstance;
+		thrown.expect(ValidationException.class);
+		this.reqVersion = 7;
+		this.version = "v" + reqVersion;
+		thrown.expectMessage("No valid instanceGroupId is specified");
+		this.msoRequest = new MsoRequest();
+		this.msoRequest.parse(sir, instanceIdMapTest, action, version, originalRequestJSON, reqVersion, false);
+	}
+	@Test
 	public void testVfModuleV4UsePreLoad() throws JsonParseException, JsonMappingException, IOException, ValidationException {
 		this.requestJSON = inputStream("/SuccessfulValidation/v4CreateVfModule.json");
 		this.instanceIdMapTest.put("serviceInstanceId", "3eecada1-83a4-4f33-9ed2-7937e7b8dbbc");
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/java/org/onap/so/apihandlerinfra/ServiceInstancesTest.java b/mso-api-handlers/mso-api-handler-infra/src/test/java/org/onap/so/apihandlerinfra/ServiceInstancesTest.java
index 9371c7e..8d3649a 100644
--- a/mso-api-handlers/mso-api-handler-infra/src/test/java/org/onap/so/apihandlerinfra/ServiceInstancesTest.java
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/java/org/onap/so/apihandlerinfra/ServiceInstancesTest.java
@@ -52,7 +52,6 @@
 import org.onap.so.db.catalog.beans.Service;
 import org.onap.so.db.catalog.beans.ServiceRecipe;
 import org.onap.so.db.request.beans.InfraActiveRequests;
-import org.onap.so.logger.LogConstants;
 import org.onap.so.logger.MsoLogger;
 import org.onap.so.serviceinstancebeans.CloudConfiguration;
 import org.onap.so.serviceinstancebeans.ModelInfo;
@@ -61,7 +60,6 @@
 import org.onap.so.serviceinstancebeans.RequestReferences;
 import org.onap.so.serviceinstancebeans.ServiceInstancesRequest;
 import org.onap.so.serviceinstancebeans.ServiceInstancesResponse;
-import org.slf4j.MDC;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.HttpEntity;
@@ -2435,4 +2433,153 @@
         ServiceInstancesResponse realResponse = mapper.readValue(response.getBody(), ServiceInstancesResponse.class);
         assertThat(realResponse, sameBeanAs(expectedResponse).ignoring("requestReferences.requestId"));	
     }
+    @Test
+    public void createInstanceGroup() throws IOException{
+    	stubFor(post(urlPathEqualTo("/mso/async/services/WorkflowActionBB"))
+                .willReturn(aResponse().withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
+                        .withBodyFile("Camunda/TestResponse.json").withStatus(org.apache.http.HttpStatus.SC_OK)));
+    	
+        HttpHeaders headers = new HttpHeaders();
+        //expect
+        ServiceInstancesResponse expectedResponse = new ServiceInstancesResponse();
+        RequestReferences requestReferences = new RequestReferences();
+        requestReferences.setInstanceId("1882939");
+        expectedResponse.setRequestReferences(requestReferences);
+        uri = servInstanceuri + "/v7/instanceGroups";
+        ResponseEntity<String> response = sendRequest(inputStream("/CreateInstanceGroup.json"), uri, HttpMethod.POST, headers);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+        //then		
+        assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatusCode().value());
+        ServiceInstancesResponse realResponse = mapper.readValue(response.getBody(), ServiceInstancesResponse.class);
+        assertThat(realResponse, sameBeanAs(expectedResponse).ignoring("requestReferences.requestId"));	
+    }
+    @Test
+    public void deleteInstanceGroup() throws IOException{
+    	stubFor(post(urlPathEqualTo("/mso/async/services/WorkflowActionBB"))
+                .willReturn(aResponse().withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
+                        .withBodyFile("Camunda/TestResponse.json").withStatus(org.apache.http.HttpStatus.SC_OK)));
+    	
+        HttpHeaders headers = new HttpHeaders();
+        headers.set(ONAPLogConstants.Headers.REQUEST_ID, "eca3a1b1-43ab-457e-ab1c-367263d148b4");
+        headers.set(ONAPLogConstants.Headers.PARTNER_NAME, "test_name");
+        headers.set(MsoLogger.REQUESTOR_ID, "xxxxxx");
+        //expect
+        ServiceInstancesResponse expectedResponse = new ServiceInstancesResponse();
+        RequestReferences requestReferences = new RequestReferences();
+        requestReferences.setInstanceId("1882939");
+        expectedResponse.setRequestReferences(requestReferences);
+        uri = servInstanceuri + "/v7/instanceGroups/e05864f0-ab35-47d0-8be4-56fd9619ba3c";
+        ResponseEntity<String> response = sendRequest(null, uri, HttpMethod.DELETE, headers);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+        //then		
+        assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatusCode().value());
+        ServiceInstancesResponse realResponse = mapper.readValue(response.getBody(), ServiceInstancesResponse.class);
+        assertThat(realResponse, sameBeanAs(expectedResponse).ignoring("requestReferences.requestId"));	
+    }
+    @Test
+    public void deleteInstanceGroupNoRequestIdHeader() throws IOException{
+        HttpHeaders headers = new HttpHeaders();
+        headers.set(ONAPLogConstants.Headers.PARTNER_NAME, "test_name");
+        headers.set(MsoLogger.REQUESTOR_ID, "xxxxxx");
+        uri = servInstanceuri + "/v7/instanceGroups/e05864f0-ab35-47d0-8be4-56fd9619ba3c";
+        ResponseEntity<String> response = sendRequest(null, uri, HttpMethod.DELETE, headers);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
+
+        //then		
+        assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode().value());
+        RequestError realResponse = mapper.readValue(response.getBody(), RequestError.class);
+        assertEquals(realResponse.getServiceException().getText(), "No valid X-ONAP-RequestID header is specified");	
+    }
+    @Test
+    public void deleteInstanceGroupNoPartnerNameHeader() throws IOException{
+        HttpHeaders headers = new HttpHeaders();
+        headers.set(ONAPLogConstants.Headers.REQUEST_ID, "eca3a1b1-43ab-457e-ab1c-367263d148b4");
+        headers.set(MsoLogger.REQUESTOR_ID, "xxxxxx");
+        uri = servInstanceuri + "/v7/instanceGroups/e05864f0-ab35-47d0-8be4-56fd9619ba3c";
+        ResponseEntity<String> response = sendRequest(null, uri, HttpMethod.DELETE, headers);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
+
+        //then		
+        assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode().value());
+        RequestError realResponse = mapper.readValue(response.getBody(), RequestError.class);
+        assertEquals(realResponse.getServiceException().getText(), "No valid X-ONAP-PartnerName header is specified");	
+    }
+    @Test
+    public void deleteInstanceGroupNoRquestorIdHeader() throws IOException{
+        HttpHeaders headers = new HttpHeaders();
+        headers.set(ONAPLogConstants.Headers.REQUEST_ID, "eca3a1b1-43ab-457e-ab1c-367263d148b4");
+        headers.set(ONAPLogConstants.Headers.PARTNER_NAME, "eca3a1b1-43ab-457e-ab1c-367263d148b4");
+        //expect
+        ServiceInstancesResponse expectedResponse = new ServiceInstancesResponse();
+        RequestReferences requestReferences = new RequestReferences();
+        requestReferences.setInstanceId("1882939");
+        expectedResponse.setRequestReferences(requestReferences);
+        uri = servInstanceuri + "/v7/instanceGroups/e05864f0-ab35-47d0-8be4-56fd9619ba3c";
+        ResponseEntity<String> response = sendRequest(null, uri, HttpMethod.DELETE, headers);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
+
+        //then		
+        assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode().value());
+        RequestError realResponse = mapper.readValue(response.getBody(), RequestError.class);
+        assertEquals(realResponse.getServiceException().getText(), "No valid X-RequestorID header is specified");	
+    }
+    @Test
+    public void addMembers() throws IOException{
+    	stubFor(post(urlPathEqualTo("/mso/async/services/WorkflowActionBB"))
+                .willReturn(aResponse().withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
+                        .withBodyFile("Camunda/TestResponse.json").withStatus(org.apache.http.HttpStatus.SC_OK)));
+    	HttpHeaders headers = new HttpHeaders();
+        //expect 
+        ServiceInstancesResponse expectedResponse = new ServiceInstancesResponse();
+        RequestReferences requestReferences = new RequestReferences();
+        requestReferences.setInstanceId("1882939");
+        expectedResponse.setRequestReferences(requestReferences);
+        uri = servInstanceuri + "/v7/instanceGroups/e05864f0-ab35-47d0-8be4-56fd9619ba3c/addMembers";
+        ResponseEntity<String> response = sendRequest(inputStream("/AddMembers.json"), uri, HttpMethod.POST, headers);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+        //then		
+        assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatusCode().value());
+        ServiceInstancesResponse realResponse = mapper.readValue(response.getBody(), ServiceInstancesResponse.class);
+        assertThat(realResponse, sameBeanAs(expectedResponse).ignoring("requestReferences.requestId"));	
+    }
+    @Test
+    public void removeMembers() throws IOException{
+    	stubFor(post(urlPathEqualTo("/mso/async/services/WorkflowActionBB"))
+                .willReturn(aResponse().withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
+                        .withBodyFile("Camunda/TestResponse.json").withStatus(org.apache.http.HttpStatus.SC_OK)));
+    	HttpHeaders headers = new HttpHeaders();
+        //expect
+        ServiceInstancesResponse expectedResponse = new ServiceInstancesResponse();
+        RequestReferences requestReferences = new RequestReferences();
+        requestReferences.setInstanceId("1882939");
+        expectedResponse.setRequestReferences(requestReferences);
+        uri = servInstanceuri + "/v7/instanceGroups/e05864f0-ab35-47d0-8be4-56fd9619ba3c/removeMembers";
+        ResponseEntity<String> response = sendRequest(inputStream("/RemoveMembers.json"), uri, HttpMethod.POST, headers);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+        //then		
+        assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatusCode().value());
+        ServiceInstancesResponse realResponse = mapper.readValue(response.getBody(), ServiceInstancesResponse.class);
+        assertThat(realResponse, sameBeanAs(expectedResponse).ignoring("requestReferences.requestId"));	
+    }
 }
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/AddMembersInstanceId.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/AddMembersInstanceId.json
new file mode 100644
index 0000000..1080513
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/AddMembersInstanceId.json
@@ -0,0 +1,17 @@
+{
+  "requestDetails": {
+    "requestInfo": {
+      "source": "VID",
+      "requestorId": "xxxxxx"
+    },
+    "relatedInstanceList": [
+      {
+        "relatedInstance": {
+          "modelInfo": {
+            "modelType": "vnf"
+          }
+        }
+      }
+    ]
+  }
+}
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/AddMembersSource.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/AddMembersSource.json
new file mode 100644
index 0000000..ca4798e
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/AddMembersSource.json
@@ -0,0 +1,17 @@
+{
+  "requestDetails": {
+    "requestInfo": {
+      "requestorId": "xxxxxx"
+    },
+    "relatedInstanceList": [
+      {
+        "relatedInstance": {
+          "instanceId": "{the to be related vnf-id}",
+          "modelInfo": {
+            "modelType": "vnf"
+          }
+        }
+      }
+    ]
+  }
+}
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/DeleteMembersModelType.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/DeleteMembersModelType.json
new file mode 100644
index 0000000..d3afee1
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/DeleteMembersModelType.json
@@ -0,0 +1,17 @@
+{
+  "requestDetails": {
+    "requestInfo": {
+      "source": "VID",
+      "requestorId": "xxxxxx"
+    },
+    "relatedInstanceList": [
+      {
+        "relatedInstance": {
+          "instanceId": "{the to be related vnf-id}",
+          "modelInfo": {
+          }
+        }
+      }
+    ]
+  }
+}
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/MembersRequestInfo.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/MembersRequestInfo.json
new file mode 100644
index 0000000..c4240a8
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/MembersRequestInfo.json
@@ -0,0 +1,14 @@
+{
+  "requestDetails": {
+    "relatedInstanceList": [
+      {
+        "relatedInstance": {
+          "instanceId": "{the to be related vnf-id}",
+          "modelInfo": {
+            "modelType": "vnf"
+          }
+        }
+      }
+    ]
+  }
+}
\ No newline at end of file
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/MembersRequestorId.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/MembersRequestorId.json
new file mode 100644
index 0000000..8564b60
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/MembersRequestorId.json
@@ -0,0 +1,17 @@
+{
+	"requestDetails": {
+	    "requestInfo": {
+	      "source": "VID"
+	    },
+	    "relatedInstanceList": [
+	      {
+	        "relatedInstance": {
+	          "instanceId": "{the to be removed as member vnf-id}",
+	          "modelInfo": {
+	            "modelType": "vnf"
+	          }
+	        }
+	      }
+	    ]
+	  }
+}
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/RelatedInstances.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/RelatedInstances.json
new file mode 100644
index 0000000..616f79b
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/RelatedInstances.json
@@ -0,0 +1,15 @@
+{
+  "requestDetails": {
+    "modelInfo": {
+      "modelType": "instanceGroup",
+      "modelVersionId": "ddcbbf3d-f2c1-4ca0-8852-76a807285efc"
+    },
+    "requestInfo": {
+      "source": "VID",
+      "requestorId": "xxxxxx"
+    },
+    "requestParameters": {
+      "userParams": []
+    }
+  }
+}
\ No newline at end of file
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/RelatedInstancesVnf.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/RelatedInstancesVnf.json
new file mode 100644
index 0000000..0d33964
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/MembersValidation/RelatedInstancesVnf.json
@@ -0,0 +1,25 @@
+{
+  "requestDetails": {
+    "modelInfo": {
+      "modelType": "instanceGroup",
+      "modelVersionId": "ddcbbf3d-f2c1-4ca0-8852-76a807285efc"
+    },
+    "requestInfo": {
+      "source": "VID",
+      "requestorId": "xxxxxx"
+    },
+    "relatedInstanceList": [
+      {
+        "relatedInstance": {
+          "instanceId": "96f40d14-705d-40d9-b829-3dab90811321",
+          "modelInfo": {
+            "modelType": "vfModule"
+          }
+        }
+      }
+    ],
+    "requestParameters": {
+      "userParams": []
+    }
+  }
+}
\ No newline at end of file
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/ModelInfo/CreateInstanceGroupNoModelVersionId.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/ModelInfo/CreateInstanceGroupNoModelVersionId.json
new file mode 100644
index 0000000..0bac9ce
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/ModelInfo/CreateInstanceGroupNoModelVersionId.json
@@ -0,0 +1,25 @@
+{
+  "requestDetails": {
+    "modelInfo": {
+      "modelType": "instanceGroup"
+    },
+    "requestInfo": {
+      "source": "VID",
+      "requestorId": "xxxxxx"
+    },
+    "relatedInstanceList": [
+      {
+        "relatedInstance": {
+          "instanceId": "96f40d14-705d-40d9-b829-3dab90811321",
+          "modelInfo": {
+            "modelType": "service"
+          }
+        }
+      }
+    ],
+    "requestParameters": {
+      "userParams": []
+    }
+  }
+}
+
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/RelatedInstances/CreateInstanceGroupNoModelCustomizationId.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/RelatedInstances/CreateInstanceGroupNoModelCustomizationId.json
new file mode 100644
index 0000000..058daf2
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/RelatedInstances/CreateInstanceGroupNoModelCustomizationId.json
@@ -0,0 +1,33 @@
+{
+  "requestDetails": {
+    "modelInfo": {
+      "modelType": "instanceGroup",
+      "modelVersionId": "ddcbbf3d-f2c1-4ca0-8852-76a807285efc"
+    },
+    "requestInfo": {
+      "source": "VID",
+      "requestorId": "xxxxxx"
+    },
+    "relatedInstanceList": [
+      {
+        "relatedInstance": {
+          "instanceId": "96f40d14-705d-40d9-b829-3dab90811321",
+          "modelInfo": {
+            "modelType": "service"
+          }
+        }
+      },
+      {
+        "relatedInstance": {
+          "modelInfo": {
+            "modelType": "service"
+          }
+        }
+      }
+    ],
+    "requestParameters": {
+      "userParams": []
+    }
+  }
+}
+
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/RelatedInstances/CreateInstanceGroupNoRelatedInstances.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/RelatedInstances/CreateInstanceGroupNoRelatedInstances.json
new file mode 100644
index 0000000..5827c52
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/RelatedInstances/CreateInstanceGroupNoRelatedInstances.json
@@ -0,0 +1,16 @@
+{
+  "requestDetails": {
+    "modelInfo": {
+      "modelType": "instanceGroup",
+      "modelVersionId": "ddcbbf3d-f2c1-4ca0-8852-76a807285efc"
+    },
+    "requestInfo": {
+      "source": "VID",
+      "requestorId": "xxxxxx"
+    },
+    "requestParameters": {
+      "userParams": []
+    }
+  }
+}
+
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/RelatedInstances/CreateInstanceGroupRelatedInstanceModelVersionId.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/RelatedInstances/CreateInstanceGroupRelatedInstanceModelVersionId.json
new file mode 100644
index 0000000..d855078
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/RelatedInstances/CreateInstanceGroupRelatedInstanceModelVersionId.json
@@ -0,0 +1,25 @@
+{
+  "requestDetails": {
+    "modelInfo": {
+      "modelType": "instanceGroup",
+      "modelVersionId": "ddcbbf3d-f2c1-4ca0-8852-76a807285efc"
+    },
+    "requestInfo": {
+      "source": "VID",
+      "requestorId": "xxxxxx"
+    },
+    "relatedInstanceList": [
+      {
+        "relatedInstance": {
+          "instanceId": "ddcbbf3d-f2c1-4ca0-8852-76a807285efc",
+          "modelInfo": {
+            "modelType": "service"
+          }
+        }
+      }
+    ],
+    "requestParameters": {
+      "userParams": []
+    }
+  }
+}
\ No newline at end of file
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/RelatedInstances/CreateInstanceGroupService.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/RelatedInstances/CreateInstanceGroupService.json
new file mode 100644
index 0000000..0d33964
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/MsoRequestTest/RelatedInstances/CreateInstanceGroupService.json
@@ -0,0 +1,25 @@
+{
+  "requestDetails": {
+    "modelInfo": {
+      "modelType": "instanceGroup",
+      "modelVersionId": "ddcbbf3d-f2c1-4ca0-8852-76a807285efc"
+    },
+    "requestInfo": {
+      "source": "VID",
+      "requestorId": "xxxxxx"
+    },
+    "relatedInstanceList": [
+      {
+        "relatedInstance": {
+          "instanceId": "96f40d14-705d-40d9-b829-3dab90811321",
+          "modelInfo": {
+            "modelType": "vfModule"
+          }
+        }
+      }
+    ],
+    "requestParameters": {
+      "userParams": []
+    }
+  }
+}
\ No newline at end of file
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/ServiceInstanceTest/AddMembers.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/ServiceInstanceTest/AddMembers.json
new file mode 100644
index 0000000..e9d056c
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/ServiceInstanceTest/AddMembers.json
@@ -0,0 +1,18 @@
+{
+  "requestDetails": {
+    "requestInfo": {
+      "source": "VID",
+      "requestorId": "xxxxxx"
+    },
+    "relatedInstanceList": [
+      {
+        "relatedInstance": {
+          "instanceId": "{the to be related vnf-id}",
+          "modelInfo": {
+            "modelType": "vnf"
+          }
+        }
+      }
+    ]
+  }
+}
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/ServiceInstanceTest/CreateInstanceGroup.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/ServiceInstanceTest/CreateInstanceGroup.json
new file mode 100644
index 0000000..474c801
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/ServiceInstanceTest/CreateInstanceGroup.json
@@ -0,0 +1,26 @@
+{
+  "requestDetails": {
+    "modelInfo": {
+      "modelType": "instanceGroup",
+      "modelVersionId": "ddcbbf3d-f2c1-4ca0-8852-76a807285efc"
+    },
+    "requestInfo": {
+      "source": "VID",
+      "requestorId": "xxxxxx"
+    },
+    "relatedInstanceList": [
+      {
+        "relatedInstance": {
+          "instanceId": "ddcbbf3d-f2c1-4ca0-8852-76a807285efc",
+          "modelInfo": {
+            "modelType": "service",
+            "modelVersionId": "ddcbbf3d-f2c1-4ca0-8852-76a807285efc"
+          }
+        }
+      }
+    ],
+    "requestParameters": {
+      "userParams": []
+    }
+  }
+}
\ No newline at end of file
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/ServiceInstanceTest/MembersRequestInfo.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/ServiceInstanceTest/MembersRequestInfo.json
new file mode 100644
index 0000000..58f83ef
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/ServiceInstanceTest/MembersRequestInfo.json
@@ -0,0 +1,17 @@
+{
+  "requestDetails": {
+  "requestInfo": {
+      "source": "VID"
+    },
+    "relatedInstanceList": [
+      {
+        "relatedInstance": {
+          "instanceId": "{the to be related vnf-id}",
+          "modelInfo": {
+            "modelType": "vnf"
+          }
+        }
+      }
+    ]
+  }
+}
diff --git a/mso-api-handlers/mso-api-handler-infra/src/test/resources/ServiceInstanceTest/RemoveMembers.json b/mso-api-handlers/mso-api-handler-infra/src/test/resources/ServiceInstanceTest/RemoveMembers.json
new file mode 100644
index 0000000..437f19d
--- /dev/null
+++ b/mso-api-handlers/mso-api-handler-infra/src/test/resources/ServiceInstanceTest/RemoveMembers.json
@@ -0,0 +1,18 @@
+{
+	"requestDetails": {
+	    "requestInfo": {
+	      "source": "VID",
+	      "requestorId": "xxxxxx"
+	    },
+	    "relatedInstanceList": [
+	      {
+	        "relatedInstance": {
+	          "instanceId": "{the to be removed as member vnf-id}",
+	          "modelInfo": {
+	            "modelType": "vnf"
+	          }
+	        }
+	      }
+	    ]
+	  }
+}