diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java index ccf186dfe4f..a785ed2ac98 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java @@ -205,7 +205,7 @@ public class NetworkResponse extends BaseResponseWithAssociatedNetwork implement @SerializedName(ApiConstants.VPC_ACCESS) @Param(description = "Whether the calling account has access to this network's VPC", since = "4.20") - private boolean vpcAccess; + private Boolean vpcAccess; @SerializedName(ApiConstants.VPC_ID) @Param(description = "VPC the Network belongs to") @@ -531,7 +531,7 @@ public class NetworkResponse extends BaseResponseWithAssociatedNetwork implement this.vpcAccess = vpcAccess; } - public boolean getVpcAccess() { + public Boolean getVpcAccess() { return vpcAccess; } diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index 3257f90d091..6bf8fd51d4c 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -1242,7 +1242,7 @@ public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport { return ipResponse; } - private void setVpcIdInResponse(Long vpcId, Consumer vpcUuidSetter, Consumer vpcNameSetter, Consumer vpcAccessSetter) { + protected void setVpcIdInResponse(Long vpcId, Consumer vpcUuidSetter, Consumer vpcNameSetter, Consumer vpcAccessSetter) { if (vpcId == null) { return; } @@ -1262,7 +1262,7 @@ public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport { vpcUuidSetter.accept(vpc.getUuid()); } - private void setAclIdInResponse(Network network, NetworkResponse response) { + protected void setAclIdInResponse(Network network, NetworkResponse response) { if (network.getNetworkACLId() == null) { return; } @@ -1272,7 +1272,7 @@ public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport { return; } - if (!response.getVpcAccess() && acl.getVpcId() != 0) { + if (Boolean.FALSE.equals(response.getVpcAccess()) && acl.getVpcId() != 0) { logger.debug("[{}] not set in response, since caller does not have access to it.", acl); return; } diff --git a/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java b/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java index c0c019f6dbd..a69ee26720c 100644 --- a/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java +++ b/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java @@ -29,6 +29,47 @@ import java.util.Set; import java.util.TimeZone; import java.util.UUID; +import com.cloud.capacity.Capacity; +import com.cloud.configuration.Resource; +import com.cloud.domain.DomainVO; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.network.Network; +import com.cloud.network.PublicIpQuarantine; +import com.cloud.network.as.AutoScaleVmGroup; +import com.cloud.network.as.AutoScaleVmGroupVO; +import com.cloud.network.as.AutoScaleVmProfileVO; +import com.cloud.network.as.dao.AutoScaleVmGroupVmMapDao; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.LoadBalancerVO; +import com.cloud.network.dao.NetworkServiceMapDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.VpcVO; +import com.cloud.storage.VMTemplateVO; +import com.cloud.usage.UsageVO; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +import com.cloud.user.User; +import com.cloud.user.UserData; +import com.cloud.user.UserDataVO; +import com.cloud.user.UserVO; +import com.cloud.user.dao.UserDataDao; +import com.cloud.utils.net.Ip; +import com.cloud.vm.NicSecondaryIp; +import org.apache.cloudstack.annotation.dao.AnnotationDao; +import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse; +import org.apache.cloudstack.api.response.AutoScaleVmProfileResponse; +import org.apache.cloudstack.api.response.DirectDownloadCertificateResponse; +import org.apache.cloudstack.api.response.IpQuarantineResponse; +import org.apache.cloudstack.api.response.NetworkResponse; +import org.apache.cloudstack.api.response.NicSecondaryIpResponse; +import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; +import org.apache.cloudstack.api.response.UsageRecordResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.usage.UsageService; +import org.apache.cloudstack.vm.UnmanagedInstanceTO; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -149,6 +190,11 @@ public class ApiResponseHelperTest { private HostVO hostVOMock; @Mock private VMInstanceVO vmInstanceVOMock; + VpcVO vpcVOMock; + + @Mock + NetworkACL networkACLMock; + @Spy @InjectMocks @@ -168,6 +214,9 @@ public class ApiResponseHelperTest { static long autoScaleUserId = 7L; + static final String A_NAME = "name"; + static final String A_UUID = "021f94d4-73f9-4a9a-b003-1df9dd968a09"; + @Before public void injectMocks() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { @@ -800,4 +849,135 @@ public class ApiResponseHelperTest { Assert.assertEquals(expected.getVmName(), response.getVmName()); } } + + @Test + public void setVpcIdInResponseTestNullVpcIdReturnNull() { + NetworkResponse networkResponse = new NetworkResponse(); + + apiResponseHelper.setVpcIdInResponse(null, networkResponse::setVpcId, networkResponse::setVpcName, networkResponse::setVpcAccess); + Assert.assertNull(networkResponse.getVpcId()); + Assert.assertNull(networkResponse.getVpcName()); + Assert.assertNull(networkResponse.getVpcAccess()); + } + + @Test + public void setVpcIdInResponseTestNullVpcReturnNull() { + NetworkResponse networkResponse = new NetworkResponse(); + + try (MockedStatic utils = Mockito.mockStatic(ApiDBUtils.class)) { + utils.when(() -> ApiDBUtils.findVpcById(1L)).thenReturn(null); + apiResponseHelper.setVpcIdInResponse(1L, networkResponse::setVpcId, networkResponse::setVpcName, networkResponse::setVpcAccess); + } + Assert.assertNull(networkResponse.getVpcId()); + Assert.assertNull(networkResponse.getVpcName()); + Assert.assertNull(networkResponse.getVpcAccess()); + } + + @Test + public void setVpcIdInResponseCallerHasAccessReturnVpcAccessTrueAndVpcIdAndVpcName() { + NetworkResponse networkResponse = new NetworkResponse(); + Mockito.when(vpcVOMock.getName()).thenReturn(A_NAME); + Mockito.when(vpcVOMock.getUuid()).thenReturn(A_UUID); + + try (MockedStatic utils = Mockito.mockStatic(ApiDBUtils.class)) { + utils.when(() -> ApiDBUtils.findVpcById(1L)).thenReturn(vpcVOMock); + apiResponseHelper.setVpcIdInResponse(1L, networkResponse::setVpcId, networkResponse::setVpcName, networkResponse::setVpcAccess); + }; + Assert.assertEquals(A_UUID, networkResponse.getVpcId()); + Assert.assertEquals(A_NAME, networkResponse.getVpcName()); + Assert.assertTrue(networkResponse.getVpcAccess()); + } + + @Test + public void setVpcIdInResponseCallerDoesNotHaveAccessReturnVpcAccessFalseAndVpcIdAndVpcName() { + NetworkResponse networkResponse = new NetworkResponse(); + Mockito.when(vpcVOMock.getName()).thenReturn(A_NAME); + Mockito.when(vpcVOMock.getUuid()).thenReturn(A_UUID); + + try (MockedStatic utils = Mockito.mockStatic(ApiDBUtils.class)) { + utils.when(() -> ApiDBUtils.findVpcById(1L)).thenReturn(vpcVOMock); + Mockito.doThrow(PermissionDeniedException.class).when(accountManagerMock).checkAccess(Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any()); + apiResponseHelper.setVpcIdInResponse(1L, networkResponse::setVpcId, networkResponse::setVpcName, networkResponse::setVpcAccess); + }; + Assert.assertEquals(A_UUID, networkResponse.getVpcId()); + Assert.assertEquals(A_NAME, networkResponse.getVpcName()); + Assert.assertFalse(networkResponse.getVpcAccess()); + } + + @Test + public void setAclIdInResponseTestNullNetworkAclIdReturnNull() { + NetworkResponse networkResponse = new NetworkResponse(); + Network networkMock = Mockito.mock(Network.class); + Mockito.when(networkMock.getNetworkACLId()).thenReturn(null); + + apiResponseHelper.setAclIdInResponse(networkMock, networkResponse); + Assert.assertNull(networkResponse.getAclId()); + Assert.assertNull(networkResponse.getAclName()); + } + + @Test + public void setAclIdInResponseTestNullAclReturnNull() { + NetworkResponse networkResponse = new NetworkResponse(); + Network networkMock = Mockito.mock(Network.class); + Mockito.when(networkMock.getNetworkACLId()).thenReturn(1L); + + try (MockedStatic utils = Mockito.mockStatic(ApiDBUtils.class)) { + utils.when(() -> ApiDBUtils.findByNetworkACLId(1L)).thenReturn(null); + apiResponseHelper.setAclIdInResponse(networkMock, networkResponse); + } + Assert.assertNull(networkResponse.getAclId()); + Assert.assertNull(networkResponse.getAclName()); + } + + @Test + public void setAclIdInResponseTestCallerDoesNotHaveAccessReturnNull() { + NetworkResponse networkResponse = new NetworkResponse(); + networkResponse.setVpcAccess(false); + Network networkMock = Mockito.mock(Network.class); + Mockito.when(networkMock.getNetworkACLId()).thenReturn(1L); + Mockito.when(networkACLMock.getVpcId()).thenReturn(2L); + + try (MockedStatic utils = Mockito.mockStatic(ApiDBUtils.class)) { + utils.when(() -> ApiDBUtils.findByNetworkACLId(1L)).thenReturn(networkACLMock); + apiResponseHelper.setAclIdInResponse(networkMock, networkResponse); + } + Assert.assertNull(networkResponse.getAclId()); + Assert.assertNull(networkResponse.getAclName()); + } + + @Test + public void setAclIdInResponseTestCallerDoesNotHaveAccessButAclIsGlobalReturnAclIdAndAclName() { + NetworkResponse networkResponse = new NetworkResponse(); + networkResponse.setVpcAccess(false); + Network networkMock = Mockito.mock(Network.class); + Mockito.when(networkMock.getNetworkACLId()).thenReturn(1L); + Mockito.when(networkACLMock.getVpcId()).thenReturn(0L); + Mockito.when(networkACLMock.getName()).thenReturn(A_NAME); + Mockito.when(networkACLMock.getUuid()).thenReturn(A_UUID); + + try (MockedStatic utils = Mockito.mockStatic(ApiDBUtils.class)) { + utils.when(() -> ApiDBUtils.findByNetworkACLId(1L)).thenReturn(networkACLMock); + apiResponseHelper.setAclIdInResponse(networkMock, networkResponse); + } + Assert.assertEquals(A_UUID, networkResponse.getAclId()); + Assert.assertEquals(A_NAME, networkResponse.getAclName()); + } + + @Test + public void setAclIdInResponseTestCallerHasAccessReturnAclIdAndAclName() { + NetworkResponse networkResponse = new NetworkResponse(); + networkResponse.setVpcAccess(true); + Network networkMock = Mockito.mock(Network.class); + Mockito.when(networkMock.getNetworkACLId()).thenReturn(1L); + Mockito.lenient().when(networkACLMock.getVpcId()).thenReturn(2L); + Mockito.when(networkACLMock.getName()).thenReturn(A_NAME); + Mockito.when(networkACLMock.getUuid()).thenReturn(A_UUID); + + try (MockedStatic utils = Mockito.mockStatic(ApiDBUtils.class)) { + utils.when(() -> ApiDBUtils.findByNetworkACLId(1L)).thenReturn(networkACLMock); + apiResponseHelper.setAclIdInResponse(networkMock, networkResponse); + } + Assert.assertEquals(A_UUID, networkResponse.getAclId()); + Assert.assertEquals(A_NAME, networkResponse.getAclName()); + } }