From 296a26edcc3102602b494d1be9c23e0265b09f66 Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Fri, 5 Feb 2021 11:13:31 -0500 Subject: Give better messages than NPE for missing data When data is not available to actor operations, an NPE is generally thrown. Modified the code to provide more info about what is missing than simply NPE. Issue-ID: POLICY-2913 Change-Id: I37b6eadd966e0693508a6d552b7db4edf5410018 Signed-off-by: Jim Hahn --- .../policy/controlloop/actor/so/ModifyNssi.java | 5 +-- .../policy/controlloop/actor/so/SoOperation.java | 21 +++++++++++-- .../controlloop/actor/so/VfModuleCreate.java | 6 ++-- .../controlloop/actor/so/VfModuleDelete.java | 6 ++-- .../controlloop/actor/so/ModifyNssiTest.java | 13 +++++++- .../controlloop/actor/so/SoOperationTest.java | 36 +++++++++++++++++++++- .../controlloop/actor/so/VfModuleCreateTest.java | 25 +++++++++++++-- .../controlloop/actor/so/VfModuleDeleteTest.java | 25 +++++++++++++-- .../src/test/resources/VfModuleDelete.json | 5 ++- .../src/test/resources/vfModuleCreate.json | 5 ++- 10 files changed, 126 insertions(+), 21 deletions(-) (limited to 'models-interactions/model-actors/actor.so/src') diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/ModifyNssi.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/ModifyNssi.java index 2c5038834..5386d96dd 100644 --- a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/ModifyNssi.java +++ b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/ModifyNssi.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Modifications Copyright (C) 2021 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. @@ -67,9 +68,9 @@ public class ModifyNssi extends SoOperation { return handleResponse(outcome, url, callback -> getClient().put(callback, path, entity, headers)); } - private SoRequest3gpp makeRequest() { + protected SoRequest3gpp makeRequest() { - String payload = getProperty(OperationProperties.EVENT_PAYLOAD); + String payload = getRequiredProperty(OperationProperties.EVENT_PAYLOAD, "event payload"); try { return getCoder().convert(payload, SoRequest3gpp.class); } catch (CoderException e) { diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java index e3328e976..8d3fb59af 100644 --- a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java +++ b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2020 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -324,11 +324,26 @@ public abstract class SoOperation extends HttpOperation { */ protected SoCloudConfiguration constructCloudConfiguration(Tenant tenantItem, CloudRegion cloudRegionItem) { SoCloudConfiguration cloudConfiguration = new SoCloudConfiguration(); - cloudConfiguration.setTenantId(tenantItem.getTenantId()); - cloudConfiguration.setLcpCloudRegionId(cloudRegionItem.getCloudRegionId()); + cloudConfiguration.setTenantId(getRequiredText("tenant ID", tenantItem.getTenantId())); + cloudConfiguration.setLcpCloudRegionId(getRequiredText("cloud region ID", cloudRegionItem.getCloudRegionId())); return cloudConfiguration; } + /** + * Verifies that a value is not {@code null}. + * + * @param name value name + * @param value value to check + * @return the value + */ + protected String getRequiredText(String name, String value) { + if (value == null) { + throw new IllegalArgumentException("missing " + name); + } + + return value; + } + /** * Create simple HTTP headers for unauthenticated requests to SO. * diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleCreate.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleCreate.java index b778c10d7..3d753bb0b 100644 --- a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleCreate.java +++ b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleCreate.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2020 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -197,8 +197,8 @@ public class VfModuleCreate extends SoOperation { buildConfigurationParameters().ifPresent(request.getRequestDetails()::setConfigurationParameters); // compute the path - String path = PATH_PREFIX + vnfServiceItem.getServiceInstanceId() + "/vnfs/" + vnfItem.getVnfId() - + "/vfModules/scaleOut"; + String svcId = getRequiredText("service instance ID", vnfServiceItem.getServiceInstanceId()); + String path = PATH_PREFIX + svcId + "/vnfs/" + vnfItem.getVnfId() + "/vfModules/scaleOut"; return Pair.of(path, request); } diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleDelete.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleDelete.java index b82444049..1881b5c58 100644 --- a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleDelete.java +++ b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleDelete.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2020 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -239,8 +239,8 @@ public class VfModuleDelete extends SoOperation { */ // compute the path - String path = PATH_PREFIX + vnfServiceItem.getServiceInstanceId() + "/vnfs/" + vnfItem.getVnfId() - + "/vfModules/null"; + String svcId = getRequiredText("service instance ID", vnfServiceItem.getServiceInstanceId()); + String path = PATH_PREFIX + svcId + "/vnfs/" + vnfItem.getVnfId() + "/vfModules/null"; return Pair.of(path, request); } diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/ModifyNssiTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/ModifyNssiTest.java index 2ef9caac9..29a7d082a 100644 --- a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/ModifyNssiTest.java +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/ModifyNssiTest.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2020 Wipro Limited. - * Modifications Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2020 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,6 +24,7 @@ package org.onap.policy.controlloop.actor.so; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -102,5 +103,15 @@ public class ModifyNssiTest extends BasicSoOperation { return ResourceUtils.getResourceAsString("src/test/resources/ModifyNSSI.json"); } + /** + * Tests makeRequest() when a property is missing. + */ + @Test + public void testMakeRequestMissingProperty() throws Exception { + oper = new ModifyNssi(params, config); + + assertThatIllegalStateException().isThrownBy(() -> oper.makeRequest()) + .withMessageContaining("missing event payload"); + } } diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperationTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperationTest.java index 6f4ac0ed3..50bbfee2b 100644 --- a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperationTest.java +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperationTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2020 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,6 +37,8 @@ import java.util.List; import java.util.Map; import org.junit.Before; import org.junit.Test; +import org.onap.aai.domain.yang.CloudRegion; +import org.onap.aai.domain.yang.Tenant; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.controlloop.ControlLoopOperation; @@ -205,6 +207,38 @@ public class SoOperationTest extends BasicSoOperation { assertTrue(oper.buildConfigurationParameters().isEmpty()); } + @Test + public void testConstructCloudConfiguration() throws Exception { + Tenant tenantItem = new Tenant(); + tenantItem.setTenantId("my-tenant-id"); + + CloudRegion cloudRegionItem = new CloudRegion(); + cloudRegionItem.setCloudRegionId("my-cloud-id"); + + assertThatCode(() -> oper.constructCloudConfiguration(tenantItem, cloudRegionItem)).doesNotThrowAnyException(); + + tenantItem.setTenantId(null); + assertThatIllegalArgumentException() + .isThrownBy(() -> oper.constructCloudConfiguration(tenantItem, cloudRegionItem)) + .withMessageContaining("missing tenant ID"); + tenantItem.setTenantId("my-tenant-id"); + + cloudRegionItem.setCloudRegionId(null); + assertThatIllegalArgumentException() + .isThrownBy(() -> oper.constructCloudConfiguration(tenantItem, cloudRegionItem)) + .withMessageContaining("missing cloud region ID"); + cloudRegionItem.setCloudRegionId("my-cloud-id"); + } + + @Test + public void testGetRequiredText() throws Exception { + + assertThatCode(() -> oper.getRequiredText("some value", "my value")).doesNotThrowAnyException(); + + assertThatIllegalArgumentException().isThrownBy(() -> oper.getRequiredText("some value", null)) + .withMessageContaining("missing some value"); + } + @Test public void testGetCoder() throws CoderException { Coder opcoder = oper.getCoder(); diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java index dfd5c92f6..7168ec449 100644 --- a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2020 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -212,6 +212,20 @@ public class VfModuleCreateTest extends BasicSoOperation { verifyRequest("vfModuleCreate.json", pair.getRight()); } + /** + * Tests makeRequest() when a property is missing. + */ + @Test + public void testMakeRequestMissingProperty() throws Exception { + loadProperties(); + + ServiceInstance instance = new ServiceInstance(); + oper.setProperty(OperationProperties.AAI_SERVICE, instance); + + assertThatIllegalArgumentException().isThrownBy(() -> oper.makeRequest()) + .withMessageContaining("missing service instance ID"); + } + private void loadProperties() { // set the properties ServiceInstance instance = new ServiceInstance(); @@ -229,8 +243,13 @@ public class VfModuleCreateTest extends BasicSoOperation { vnf.setVnfId(VNF_ID); oper.setProperty(OperationProperties.AAI_VNF, vnf); - oper.setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, new CloudRegion()); - oper.setProperty(OperationProperties.AAI_DEFAULT_TENANT, new Tenant()); + CloudRegion cloudRegion = new CloudRegion(); + cloudRegion.setCloudRegionId("my-cloud-id"); + oper.setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, cloudRegion); + + Tenant tenant = new Tenant(); + tenant.setTenantId("my-tenant-id"); + oper.setProperty(OperationProperties.AAI_DEFAULT_TENANT, tenant); oper.setProperty(OperationProperties.DATA_VF_COUNT, VF_COUNT); } diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleDeleteTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleDeleteTest.java index ce762011a..cc11f952d 100644 --- a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleDeleteTest.java +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleDeleteTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2020 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -351,6 +351,20 @@ public class VfModuleDeleteTest extends BasicSoOperation { assertEquals("Basic " + encoded, valueCaptor.getValue()); } + /** + * Tests makeRequest() when a property is missing. + */ + @Test + public void testMakeRequestMissingProperty() throws Exception { + loadProperties(); + + ServiceInstance instance = new ServiceInstance(); + oper.setProperty(OperationProperties.AAI_SERVICE, instance); + + assertThatIllegalArgumentException().isThrownBy(() -> oper.makeRequest()) + .withMessageContaining("missing service instance ID"); + } + @Test public void testMakeHttpClient() { // must use a real operation to invoke this method @@ -393,8 +407,13 @@ public class VfModuleDeleteTest extends BasicSoOperation { vnf.setVnfId(VNF_ID); oper.setProperty(OperationProperties.AAI_VNF, vnf); - oper.setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, new CloudRegion()); - oper.setProperty(OperationProperties.AAI_DEFAULT_TENANT, new Tenant()); + CloudRegion cloudRegion = new CloudRegion(); + cloudRegion.setCloudRegionId("my-cloud-id"); + oper.setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, cloudRegion); + + Tenant tenant = new Tenant(); + tenant.setTenantId("my-tenant-id"); + oper.setProperty(OperationProperties.AAI_DEFAULT_TENANT, tenant); oper.setProperty(OperationProperties.DATA_VF_COUNT, VF_COUNT); } diff --git a/models-interactions/model-actors/actor.so/src/test/resources/VfModuleDelete.json b/models-interactions/model-actors/actor.so/src/test/resources/VfModuleDelete.json index 5b7cce5f3..f83344dc3 100644 --- a/models-interactions/model-actors/actor.so/src/test/resources/VfModuleDelete.json +++ b/models-interactions/model-actors/actor.so/src/test/resources/VfModuleDelete.json @@ -8,7 +8,10 @@ "modelVersion": "my-model-version", "modelCustomizationId": "my-model-customization-id" }, - "cloudConfiguration": {}, + "cloudConfiguration": { + "lcpCloudRegionId": "my-cloud-id", + "tenantId": "my-tenant-id" + }, "requestInfo": { "source": "POLICY", "suppressRollback": false, diff --git a/models-interactions/model-actors/actor.so/src/test/resources/vfModuleCreate.json b/models-interactions/model-actors/actor.so/src/test/resources/vfModuleCreate.json index 06258f3f3..c28d73efa 100644 --- a/models-interactions/model-actors/actor.so/src/test/resources/vfModuleCreate.json +++ b/models-interactions/model-actors/actor.so/src/test/resources/vfModuleCreate.json @@ -8,7 +8,10 @@ "modelVersion": "my-model-version", "modelCustomizationId": "my-model-customization-id" }, - "cloudConfiguration": {}, + "cloudConfiguration": { + "lcpCloudRegionId": "my-cloud-id", + "tenantId": "my-tenant-id" + }, "requestInfo": { "instanceName": "vfModuleName", "source": "POLICY", -- cgit 1.2.3-korg