vfmodule tenant and region are dictated by parent VNF values 33/101233/2
authorIttay Stern <ittay.stern@att.com>
Wed, 5 Feb 2020 16:51:21 +0000 (18:51 +0200)
committerIttay Stern <ittay.stern@att.com>
Thu, 6 Feb 2020 11:13:47 +0000 (13:13 +0200)
Issue-ID: VID-758

Change-Id: Ie48240442e5b2f858e530858d2e25827e799e4c2
Signed-off-by: Ittay Stern <ittay.stern@att.com>
vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt
vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java
vid-app-common/src/main/java/org/onap/vid/utils/KotlinUtils.kt
vid-app-common/src/test/java/org/onap/vid/job/command/VnfCommandTest.kt [new file with mode: 0644]
vid-app-common/src/test/java/org/onap/vid/model/serviceInstantiation/VfModuleTest.java [new file with mode: 0644]
vid-app-common/src/test/java/org/onap/vid/testUtils/TestUtils.java

index 48ff7b7..b008c13 100644 (file)
@@ -12,6 +12,7 @@ import org.onap.vid.model.serviceInstantiation.Vnf
 import org.onap.vid.mso.RestMsoImplementation
 import org.onap.vid.properties.Features
 import org.onap.vid.services.AsyncInstantiationBusinessLogic
+import org.onap.vid.utils.isNotActive
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.beans.factory.config.ConfigurableBeanFactory
 import org.springframework.context.annotation.Scope
@@ -59,9 +60,9 @@ class VnfCommand @Autowired constructor(
             val vfModules:List<VfModule> = request.vfModules.values.stream().flatMap { vfKey -> vfKey.values.stream() }.collect(Collectors.toList<VfModule>())
 
             try {
-                childJobs = pushChildrenJobsToBroker(vfModules.filter { filterModuleByNeedToCreateBase(it) }, dataForChild, JobType.VolumeGroupInstantiation)
+                childJobs = pushChildrenJobsToBroker(vfModulesForChildrenJobs(vfModules), dataForChild, JobType.VolumeGroupInstantiation)
             } catch (e: AsdcCatalogException) {
-                LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to retrieve service definitions from SDC, for VfModule is BaseModule.. Error: " + e.message , e)
+                LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to retrieve service definitions from SDC, for VfModule is BaseModule.. Error: " + e.message, e)
                 //return Job.JobStatus.FAILED
                 throw e;
             }
@@ -70,11 +71,26 @@ class VnfCommand @Autowired constructor(
         return Job.JobStatus.COMPLETED_WITH_NO_ACTION
     }
 
-    private fun filterModuleByNeedToCreateBase(it: VfModule):Boolean {
+    private fun vfModulesForChildrenJobs(vfModules: List<VfModule>): List<VfModule> =
+            vfModules
+                    .filter { filterModuleByNeedToCreateBase(it) }
+                    .map { childVfModuleWithVnfRegionAndTenant(it) }
+
+    internal fun childVfModuleWithVnfRegionAndTenant(vfModule: VfModule): VfModule {
+        if (featureManager.isNotActive(Features.FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF)) {
+            return vfModule
+        }
+
+        val vnfLcpCloudRegionId = getRequest().lcpCloudRegionId
+        val vnfTenantId = getRequest().tenantId
+        return vfModule.cloneWith(vnfLcpCloudRegionId, vnfTenantId)
+    }
+
+    private fun filterModuleByNeedToCreateBase(vfModule: VfModule): Boolean {
         return needToCreateBaseModule ==
-            commandUtils.isVfModuleBaseModule(
-                    serviceModelInfoFromRequest().modelVersionId,
-                    it.modelInfo.modelVersionId)
+                commandUtils.isVfModuleBaseModule(
+                        serviceModelInfoFromRequest().modelVersionId,
+                        vfModule.modelInfo.modelVersionId)
     }
 
     override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan {
index 0b9a2a7..79ea7f1 100644 (file)
@@ -140,4 +140,28 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest
                            this.getOriginalName()
                );
        }
+
+       public VfModule cloneWith(String lcpCloudRegionId, String tenantId) {
+               return new VfModule(
+                       this.getModelInfo(),
+                       this.getInstanceName(),
+                       this.getVolumeGroupInstanceName(),
+                       this.getAction().toString(),
+                       lcpCloudRegionId,
+                       lcpCloudRegionId,
+                       tenantId,
+                       this.getInstanceParams(),
+                       this.getSupplementaryParams(),
+                       this.isRollbackOnFailure(),
+                       this.isUsePreload(),
+                       this.getInstanceId(),
+                       this.getTrackById(),
+                       this.getIsFailed(),
+                       this.getStatusMessage(),
+                       this.isRetainAssignments(),
+                       this.isRetainVolumeGroups(),
+                       this.getPosition(),
+                       this.getOriginalName()
+               );
+       }
 }
\ No newline at end of file
index 81afe29..83077f2 100644 (file)
@@ -23,11 +23,15 @@ package org.onap.vid.utils
 import com.fasterxml.jackson.databind.ObjectMapper
 import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
 import org.apache.commons.lang3.StringUtils.isEmpty
+import org.togglz.core.Feature
+import org.togglz.core.manager.FeatureManager
 
 inline fun <reified E: Enum<E>> getEnumFromMapOfStrings(map: Map<String, Any>, key:String, defaultValue:E): E {
     return java.lang.Enum.valueOf(E::class.java, (map.getOrDefault(key, defaultValue.name) as String))
 }
 
+fun FeatureManager.isNotActive(feature: Feature) = this.isActive(feature).not()
+
 @JvmField val JACKSON_OBJECT_MAPPER: ObjectMapper = jacksonObjectMapper()
 
 class JoshworksJacksonObjectMapper: io.joshworks.restclient.http.mapper.ObjectMapper {
diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/VnfCommandTest.kt b/vid-app-common/src/test/java/org/onap/vid/job/command/VnfCommandTest.kt
new file mode 100644 (file)
index 0000000..660abe4
--- /dev/null
@@ -0,0 +1,90 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2020 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.onap.vid.job.command
+
+import net.javacrumbs.jsonunit.JsonMatchers.jsonPartEquals
+import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.core.AllOf.allOf
+import org.mockito.Answers
+import org.mockito.InjectMocks
+import org.mockito.Mock
+import org.onap.vid.job.JobAdapter
+import org.onap.vid.job.JobsBrokerService
+import org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator
+import org.onap.vid.job.impl.JobSharedData
+import org.onap.vid.model.Action
+import org.onap.vid.mso.RestMsoImplementation
+import org.onap.vid.properties.Features
+import org.onap.vid.services.AsyncInstantiationBusinessLogic
+import org.onap.vid.testUtils.TestUtils
+import org.onap.vid.testUtils.TestUtils.initMockitoMocks
+import org.testng.annotations.BeforeMethod
+import org.testng.annotations.Test
+import org.togglz.core.manager.FeatureManager
+import org.mockito.Mockito.`when` as _when
+
+class VnfCommandTest {
+
+    @Mock lateinit var asyncInstantiationBL: AsyncInstantiationBusinessLogic
+    @Mock lateinit var restMso: RestMsoImplementation
+    @Mock lateinit var msoRequestBuilder: MsoRequestBuilder
+    @Mock lateinit var msoResultHandlerService: MsoResultHandlerService
+    @Mock lateinit var inProgressStatusService:InProgressStatusService
+    @Mock lateinit var watchChildrenJobsBL: WatchChildrenJobsBL
+    @Mock lateinit var jobsBrokerService: JobsBrokerService
+    @Mock lateinit var jobAdapter: JobAdapter
+    @Mock lateinit var featureManager: FeatureManager
+
+    @Mock lateinit var jobSharedData: JobSharedData
+    @Mock(answer = Answers.RETURNS_MOCKS) lateinit var vnfJobRequest: org.onap.vid.model.serviceInstantiation.Vnf
+
+    @InjectMocks lateinit var vnfCommand: VnfCommand;
+
+    @BeforeMethod
+    fun initMocks() {
+        initMockitoMocks(this)
+    }
+
+    @Test(dataProvider = "trueAndFalse", dataProviderClass = TestUtils::class)
+    fun `childVfModuleWithVnfRegionAndTenant -- given vfmodule -- tenant and region are copied from vnf`(featureToggleOn: Boolean) {
+
+        val vfModule = FakeResourceCreator.createVfModule(Action.Create)
+                        .cloneWith("vfmodule-lcp-cloud-region-id", "vfmodule-tenant-id")
+
+        _when(featureManager.isActive(Features.FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF)).thenReturn(featureToggleOn)
+
+        _when(vnfJobRequest.lcpCloudRegionId).thenReturn("vnf-lcp-cloud-region-id")
+        _when(vnfJobRequest.tenantId).thenReturn("vnf-tenant-id")
+        _when(jobSharedData.request).thenReturn(vnfJobRequest)
+
+        vnfCommand.init(jobSharedData, mapOf())
+
+        val expectedSource = if (featureToggleOn) "vnf" else "vfmodule"
+
+        assertThat(vnfCommand.childVfModuleWithVnfRegionAndTenant(vfModule),
+                allOf(
+                        jsonPartEquals("lcpCloudRegionId", "${expectedSource}-lcp-cloud-region-id"),
+                        jsonPartEquals("tenantId", "${expectedSource}-tenant-id")
+                )
+        )
+    }
+
+}
diff --git a/vid-app-common/src/test/java/org/onap/vid/model/serviceInstantiation/VfModuleTest.java b/vid-app-common/src/test/java/org/onap/vid/model/serviceInstantiation/VfModuleTest.java
new file mode 100644 (file)
index 0000000..a1c78c4
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2020 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.onap.vid.model.serviceInstantiation;
+
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
+import static org.hamcrest.core.AllOf.allOf;
+import static org.onap.vid.testUtils.TestUtils.setStringsInStringProperties;
+
+import org.onap.vid.mso.model.ModelInfo;
+import org.testng.annotations.Test;
+
+public class VfModuleTest {
+
+    @Test
+    public void cloneWithLcpCloudRegionIdAndTenantId() {
+        String targetLcpCloudRegionId = "dictated lcpCloudRegionId";
+        String targetTenantId = "dictated tenantId";
+
+        VfModule originVfModule = createVfModule();
+
+        assertThat(originVfModule.cloneWith(targetLcpCloudRegionId, targetTenantId), allOf(
+            hasProperty("lcpCloudRegionId", equalTo(targetLcpCloudRegionId)),
+            hasProperty("tenantId", equalTo(targetTenantId)),
+            jsonEquals(originVfModule).whenIgnoringPaths("lcpCloudRegionId", "tenantId")
+        ));
+
+        // verify vfModule did not mutate
+        assertThat(originVfModule, jsonEquals(createVfModule()));
+    }
+
+    private VfModule createVfModule() {
+        VfModule vfModule = new VfModule(
+            setStringsInStringProperties(new ModelInfo()),
+            null, null, null, null, null,
+            null, null, null, true, true,
+            null, null, true, null, true,
+            true, null, null);
+
+        return setStringsInStringProperties(vfModule);
+    }
+}
\ No newline at end of file
index 862b8db..71f7ee0 100644 (file)
@@ -21,9 +21,7 @@
 package org.onap.vid.testUtils;
 
 import static com.fasterxml.jackson.module.kotlin.ExtensionsKt.jacksonObjectMapper;
-import static java.util.function.Function.identity;
 import static java.util.stream.Collectors.toList;
-import static java.util.stream.Collectors.toMap;
 import static org.apache.commons.beanutils.PropertyUtils.getPropertyDescriptors;
 import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
 import static org.apache.commons.text.CharacterPredicates.DIGITS;
@@ -52,7 +50,9 @@ import java.lang.reflect.Field;
 import java.net.URI;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.function.Predicate;
 import javax.ws.rs.client.Client;
@@ -61,7 +61,6 @@ import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.GenericType;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-import org.apache.commons.beanutils.BeanUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.commons.lang3.reflect.FieldUtils;
@@ -174,15 +173,27 @@ public class TestUtils {
     }
 
     public static String[] allPropertiesOf(Class<?> aClass) {
-        return Arrays.stream(getPropertyDescriptors(aClass))
+        return getPropertyDescriptorsRecursively(aClass).stream()
             .map(PropertyDescriptor::getDisplayName)
+            .distinct()
             .toArray(String[]::new);
     }
 
+    private static List<PropertyDescriptor> getPropertyDescriptorsRecursively(Class<?> aClass) {
+        List<PropertyDescriptor> result = new LinkedList<>();
+
+        for (Class<?> i = aClass; i != null && i != Object.class; i = i.getSuperclass()) {
+            Collections.addAll(result, getPropertyDescriptors(i));
+        }
+
+        return result;
+    }
+
     private static <T> List<String> allStringPropertiesOf(T object) {
-        return Arrays.stream(getPropertyDescriptors(object.getClass()))
+        return getPropertyDescriptorsRecursively(object.getClass()).stream()
             .filter(descriptor -> descriptor.getPropertyType().isAssignableFrom(String.class))
             .map(PropertyDescriptor::getDisplayName)
+            .distinct()
             .collect(toList());
     }
 
@@ -221,16 +232,15 @@ public class TestUtils {
      * @return The modified object
      */
     public static <T> T setStringsInStringProperties(T object) {
-        try {
-            final List<String> stringFields = allStringPropertiesOf(object);
-
-            BeanUtils.populate(object, stringFields.stream()
-                .collect(toMap(identity(), identity())));
+        allStringPropertiesOf(object).forEach(it -> {
+            try {
+                FieldUtils.writeField(object, it, it, true);
+            } catch (IllegalAccessException e) {
+                // YOLO
+            }
+        });
 
-            return object;
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
+        return object;
     }
 
     public static void registerCloudConfigurationValueGenerator() {