Respect owning-entity-id when searching instances by Subscriber 23/101023/4
authorIttay Stern <ittay.stern@att.com>
Sun, 2 Feb 2020 18:04:18 +0000 (20:04 +0200)
committerIttay Stern <ittay.stern@att.com>
Mon, 3 Feb 2020 13:45:49 +0000 (13:45 +0000)
Issue-ID: VID-758

Change-Id: Ife6d8679b3ea00d4bb9efb24810b5a50652f5d76
Signed-off-by: Ittay Stern <ittay.stern@att.com>
vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java
vid-app-common/src/main/java/org/onap/vid/aai/AaiClientInterface.java
vid-app-common/src/main/java/org/onap/vid/aai/ServiceInstance.java
vid-app-common/src/main/java/org/onap/vid/model/ServiceInstanceSearchResult.java
vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java
vid-app-common/src/test/java/org/onap/vid/services/AaiServiceTest.java
vid-automation/src/test/java/org/onap/vid/api/AaiApiTest.java

index 1594010..be77e2b 100644 (file)
@@ -528,9 +528,9 @@ public class AaiClient implements AaiClientInterface {
     }
 
     @Override
-    public AaiResponse getSubscriberData(String subscriberId, boolean omitServiceInstances) {
+    public AaiResponse<Services> getSubscriberData(String subscriberId, boolean omitServiceInstances) {
         String depth = omitServiceInstances ? "1" : "2";
-        AaiResponse subscriberDataResponse;
+        AaiResponse<Services> subscriberDataResponse;
         Response resp = doAaiGet(BUSINESS_CUSTOMERS_CUSTOMER + subscriberId + "?depth=" + depth, false);
         subscriberDataResponse = processAaiResponse(resp, Services.class, null);
         return subscriberDataResponse;
@@ -617,7 +617,7 @@ public class AaiClient implements AaiClientInterface {
         }
     }
 
-    private AaiResponse processAaiResponse(Response resp, Class classType, String responseBody) {
+    private <T> AaiResponse<T> processAaiResponse(Response resp, Class<? extends T> classType, String responseBody) {
         return processAaiResponse(resp, classType, responseBody, VidObjectMapperType.CODEHAUS);
     }
 
index 2a879e2..5b36828 100644 (file)
@@ -49,7 +49,7 @@ public interface AaiClientInterface extends ProbeInterface {
 
     AaiResponse<SubscriberList> getAllSubscribers();
 
-    AaiResponse getSubscriberData(String subscriberId, boolean omitServiceInstances);
+    AaiResponse<Services> getSubscriberData(String subscriberId, boolean omitServiceInstances);
 
     AaiResponse getServices();
 
index bd1a3ac..a4e7de0 100644 (file)
@@ -22,6 +22,7 @@ package org.onap.vid.aai;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import org.onap.vid.aai.model.RelationshipList;
 
 @JsonIgnoreProperties(ignoreUnknown = true)
 public class ServiceInstance {
@@ -50,4 +51,7 @@ public class ServiceInstance {
        @JsonProperty("model-version-id")
        public String modelVersionId;
 
+       @JsonProperty("relationship-list")
+       public RelationshipList relationshipList;
+
 }
index 2665313..f750279 100644 (file)
@@ -22,9 +22,11 @@ package org.onap.vid.model;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import org.apache.commons.lang3.StringUtils;
+import org.onap.vid.roles.WithPermissionPropertiesOwningEntity;
 import org.onap.vid.roles.WithPermissionPropertiesSubscriberAndServiceType;
 
-public class ServiceInstanceSearchResult implements WithPermissionPropertiesSubscriberAndServiceType {
+public class ServiceInstanceSearchResult
+       implements WithPermissionPropertiesSubscriberAndServiceType, WithPermissionPropertiesOwningEntity {
 
        private final String SUBSCRIBER_ID_FRONTEND_ALIAS = "globalCustomerId";
 
@@ -42,14 +44,16 @@ public class ServiceInstanceSearchResult implements WithPermissionPropertiesSubs
 
        private String aaiModelVersionId;
 
+       private String owningEntityId;
+
        private boolean isPermitted;
 
        public ServiceInstanceSearchResult(){
        }
        
        public ServiceInstanceSearchResult(String serviceInstanceId, String subscriberId, String serviceType,
-                                                                          String serviceInstanceName, String subscriberName, String aaiModelInvariantId,
-                                                                          String aaiModelVersionId, boolean isPermitted) {
+               String serviceInstanceName, String subscriberName, String aaiModelInvariantId,
+               String aaiModelVersionId, String owningEntityId, boolean isPermitted) {
                this.serviceInstanceId = serviceInstanceId;
                this.subscriberId = subscriberId;
                this.serviceType = serviceType;
@@ -57,6 +61,7 @@ public class ServiceInstanceSearchResult implements WithPermissionPropertiesSubs
                this.subscriberName = subscriberName;
                this.aaiModelInvariantId = aaiModelInvariantId;
                this.aaiModelVersionId = aaiModelVersionId;
+               this.owningEntityId = owningEntityId;
                this.isPermitted = isPermitted;
        }
 
@@ -119,6 +124,15 @@ public class ServiceInstanceSearchResult implements WithPermissionPropertiesSubs
                this.aaiModelVersionId = aaiModelVersionId;
        }
 
+       @Override
+       public String getOwningEntityId() {
+               return owningEntityId;
+       }
+
+       public void setOwningEntityId(String owningEntityId) {
+               this.owningEntityId = owningEntityId;
+       }
+
        public boolean getIsPermitted() {
                return isPermitted;
        }
index 696aca5..9db8233 100644 (file)
@@ -21,6 +21,8 @@
 
 package org.onap.vid.services;
 
+import static java.util.Collections.emptyList;
+import static org.apache.commons.collections4.ListUtils.emptyIfNull;
 import static org.onap.vid.aai.AaiClient.QUERY_FORMAT_RESOURCE;
 import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
 
@@ -33,8 +35,10 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import javax.validation.constraints.NotNull;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.StringUtils;
@@ -98,6 +102,7 @@ public class AaiServiceImpl implements AaiService {
     private static final String SERVICE_INSTANCE_ID = "service-instance.service-instance-id";
     private static final String SERVICE_TYPE = "service-subscription.service-type";
     private static final String CUSTOMER_ID = "customer.global-customer-id";
+    private static final String OWNING_ENTITY_ID = "owning-entity.owning-entity-id";
     private static final String SERVICE_INSTANCE_NAME = "service-instance.service-instance-name";
     private static final String TENANT_NODE_TYPE = "tenant";
     private static final String CLOUD_REGION_NODE_TYPE = "cloud-region";
@@ -330,9 +335,11 @@ public class AaiServiceImpl implements AaiService {
 
         if (serviceSubscription.serviceInstances != null) {
             for (ServiceInstance serviceInstance : serviceSubscription.serviceInstances.serviceInstance) {
+
                 ServiceInstanceSearchResult serviceInstanceSearchResult =
-                        new ServiceInstanceSearchResult(serviceInstance.serviceInstanceId, subscriberId, serviceType, serviceInstance.serviceInstanceName,
-                                subscriberName, serviceInstance.modelInvariantId, serviceInstance.modelVersionId, false);
+                        new ServiceInstanceSearchResult(serviceInstance.serviceInstanceId, subscriberId, serviceType,
+                            serviceInstance.serviceInstanceName, subscriberName, serviceInstance.modelInvariantId,
+                            serviceInstance.modelVersionId, relatedOwningEntityId(serviceInstance), false);
 
                 serviceInstanceSearchResult.setIsPermitted(roleValidator.isServicePermitted(serviceInstanceSearchResult));
 
@@ -345,6 +352,43 @@ public class AaiServiceImpl implements AaiService {
         return results;
     }
 
+    protected String relatedOwningEntityId(ServiceInstance serviceInstance) {
+        /*
+        For reference, consider the service-instance structure below. Method will null-safely extract the
+        `relationship-value` where `relationship-key` == `owning-entity.owning-entity-id`.
+
+        {
+          "service-instance-id": "5d521981-33be-4bb5-bb20-5616a9c52a5a",
+          ...
+          "relationship-list": {
+            "relationship": [
+              {
+                "related-to": "owning-entity",
+                "related-link": "/aai/v11/business/owning-entities/owning-entity/4d4ecf59-41f1-40d4-818d-885234680a42",
+                "relationship-data": [
+                  {
+                    "relationship-key": "owning-entity.owning-entity-id",
+                    "relationship-value": "4d4ecf59-41f1-40d4-818d-885234680a42"
+                  }
+                ]
+              }
+            ]
+          }
+        }
+        */
+
+        Stream<RelationshipData> allRelationships =
+            Optional.ofNullable(serviceInstance.relationshipList)
+                .map(it -> it.getRelationship())
+                .map(it -> it.stream().flatMap(r -> emptyIfNull(r.getRelationDataList()).stream()))
+                .orElse(Stream.empty());
+
+        return allRelationships
+            .filter(r -> StringUtils.equals(r.getRelationshipKey(), OWNING_ENTITY_ID))
+            .map(it -> it.getRelationshipValue())
+            .findAny().orElse(null);
+    }
+
     private boolean serviceInstanceMatchesIdentifier(String instanceIdentifier, ServiceInstance serviceInstance) {
         return instanceIdentifier.equals(serviceInstance.serviceInstanceId) || instanceIdentifier.equals(serviceInstance.serviceInstanceName);
     }
@@ -672,7 +716,7 @@ public class AaiServiceImpl implements AaiService {
             return aaiTree.stream().map(VpnBindingKt::from).collect(Collectors.toList());
         } catch (ExceptionWithRequestInfo exception) {
             if (Objects.equals(404, exception.getHttpCode())) {
-                return Collections.emptyList();
+                return emptyList();
             }
             throw exception;
         }
@@ -688,7 +732,7 @@ public class AaiServiceImpl implements AaiService {
             return aaiTree.stream().map(Network::from).collect(Collectors.toList());
         } catch (ExceptionWithRequestInfo exception) {
             if (Objects.equals(404, exception.getHttpCode())) {
-                return Collections.emptyList();
+                return emptyList();
             }
             throw exception;
         }
index 338657b..12774f4 100644 (file)
 
 package org.onap.vid.services;
 
+import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.arrayWithSize;
 import static org.hamcrest.Matchers.equalTo;
-import static org.mockito.ArgumentMatchers.any;
+import static org.hamcrest.Matchers.nullValue;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.withSettings;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.ImmutableMap;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import org.mockito.InjectMocks;
@@ -44,6 +45,7 @@ import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.onap.vid.aai.AaiClientInterface;
 import org.onap.vid.aai.AaiResponse;
+import org.onap.vid.aai.ServiceInstance;
 import org.onap.vid.aai.model.AaiGetPnfResponse;
 import org.onap.vid.aai.model.AaiGetPnfs.Pnf;
 import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse;
@@ -53,7 +55,6 @@ import org.onap.vid.aai.model.RelationshipData;
 import org.onap.vid.aai.model.RelationshipList;
 import org.onap.vid.aai.model.ServiceRelationships;
 import org.onap.vid.model.aaiTree.AAITreeNode;
-import org.onap.vid.roles.Role;
 import org.onap.vid.roles.RoleValidator;
 import org.onap.vid.roles.RoleValidatorFactory;
 import org.testng.annotations.BeforeMethod;
@@ -220,4 +221,59 @@ public class AaiServiceTest {
         assertThat(anyMatch, equalTo(expectedMatch));
     }
 
+    @DataProvider
+    public static Object[][] dataToDestroy() {
+        return new Object[][]{
+            {"nothing"}, {"relationship-list"}, {"relationship"}, {"relationship-data"} ,{"owning-entity-id"}
+        };
+    }
+
+
+    @Test(dataProvider = "dataToDestroy")
+    public void relatedOwningEntityId_givenInstanceAndOptionalError_extractCorrectlyOrReturnNull(String dataToDestroy) throws JsonProcessingException {
+        ServiceInstance serviceInstance = new ObjectMapper().readValue((""
+            + "{ "
+            + "  \"service-instance-id\": \"5d521981-33be-4bb5-bb20-5616a9c52a5a\", "
+            + "  \"service-instance-name\": \"dfgh\", "
+            + "  \"service-type\": \"\", "
+            + "  \"service-role\": \"\", "
+            + "  \"environment-context\": \"null\", "
+            + "  \"workload-context\": \"null\", "
+            + "  \"model-invariant-id\": \"331a194d-9248-4533-88bc-62c812ccb5c1\", "
+            + "  \"model-version-id\": \"171b3887-e73e-479d-8ef8-2690bf74f2aa\", "
+            + "  \"resource-version\": \"1508832105498\", "
+            + "  \"orchestration-status\": \"Active\", "
+            + "  \"relationship-list\": { "
+            + "    \"relationship\": [ "
+            + "      { "
+            + "        \"related-to\": \"project\", "
+            + "        \"related-link\": \"/aai/v11/business/projects/project/Kennedy\", "
+            + "        \"relationship-data\": [ "
+            + "          { "
+            + "            \"relationship-key\": \"project.project-name\", "
+            + "            \"relationship-value\": \"Kennedy\" "
+            + "          } "
+            + "        ] "
+            + "      }, "
+            + "      { "
+            + "        \"related-to\": \"owning-entity\", "
+            + "        \"related-link\": \"/aai/v11/business/owning-entities/owning-entity/4d4ecf59-41f1-40d4-818d-885234680a42\", "
+            + "        \"relationship-data\": [ "
+            + "          { "
+            + "            \"relationship-key\": \"owning-entity.owning-entity-id\", "
+            + "            \"relationship-value\": \"4d4ecf59-41f1-40d4-818d-885234680a42\" "
+            + "          } "
+            + "        ] "
+            + "      } "
+            + "    ] "
+            + "  } "
+            + "}").replace(dataToDestroy, "omitted"), ServiceInstance.class);
+
+        if (dataToDestroy.equals("nothing")) {
+            assertThat(aaiService.relatedOwningEntityId(serviceInstance), is("4d4ecf59-41f1-40d4-818d-885234680a42"));
+        } else {
+            assertThat(aaiService.relatedOwningEntityId(serviceInstance), is(nullValue()));
+        }
+    }
+
 }
index e170c45..ca09d79 100644 (file)
@@ -903,7 +903,7 @@ public class AaiApiTest extends BaseApiAaiTest {
     }
 
     @Test
-    public void searchServiceInstances_serviceInstanceOfAnotherSubscriber_authIsFollwingFeatureToggle() {
+    public void searchServiceInstances_serviceInstanceOfAnotherSubscriber_authIsFollowingFeatureToggle() {
         String craigRobertsSubscriberId = "31739f3e-526b-11e6-beb8-9e71128cae77";
         String aServiceInstanceId = "4ea864f2-b946-473a-b51c-51a7c10b8391";
         String aServiceOwningEntityId = "f160c875-ddd1-4ef5-84d8-d098784daa3a";
@@ -913,6 +913,7 @@ public class AaiApiTest extends BaseApiAaiTest {
 
         SimulatorApi.registerExpectation(GET_SUBSCRIBERS_FOR_CUSTOMER_CRAIG_ROBERTS,
             ImmutableMap.of(aServiceOwningEntityId, currentUserAuthorizedOwningEntityId), CLEAR_THEN_SET);
+        SimulatorApi.registerExpectationFromPreset(new PresetAAIGetSubscribersGet(), APPEND);
 
         JsonNode serviceInstancesResult = restTemplate
             .getForObject(uri + "/search_service_instances?subscriberId=" + craigRobertsSubscriberId, JsonNode.class);