This is an automated email from the ASF dual-hosted git repository.
weizhouapache pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new 158fe4fad53 DNS Provider URL Validation (#13821)
158fe4fad53 is described below
commit 158fe4fad5328d5a6f42fabf30b9b2e0738d3949
Author: dahn <[email protected]>
AuthorDate: Tue Aug 25 10:08:47 2026 +0200
DNS Provider URL Validation (#13821)
* validate DNS server URLs in provider framework
* fixes
* Apply suggestion from @DaanHoogland
* address (some) review comments
* restrict pvt/site-local urls to root admin only
* trim url before passing to validation method
* fix minor comment
* restrict Add/Update/Delete Dns server api for root admin
* fix minor comment
* fix unit test
* address review comments
* fix build error
* server: optimize DnsProviderManagerImplTest
---------
Co-authored-by: Daan Hoogland <[email protected]>
Co-authored-by: Manoj Kumar <[email protected]>
Co-authored-by: Wei Zhou <[email protected]>
---
.../api/command/user/dns/AddDnsServerCmd.java | 2 +-
.../api/command/user/dns/DeleteDnsServerCmd.java | 2 +-
.../api/command/user/dns/UpdateDnsServerCmd.java | 2 +-
.../{nic_dns_view.sql => cloud.nic_dns_view.sql} | 0
.../cloudstack/dns/DnsProviderManagerImpl.java | 54 ++-
.../cloudstack/dns/DnsProviderManagerImplTest.java | 395 ++++++++++++---------
6 files changed, 274 insertions(+), 181 deletions(-)
diff --git
a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java
b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java
index 298ddd64a31..21279b8719f 100644
---
a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java
+++
b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java
@@ -46,7 +46,7 @@ import com.cloud.utils.EnumUtils;
requestHasSensitiveInfo = true,
responseHasSensitiveInfo = false,
since = "4.23.0",
- authorized = {RoleType.Admin, RoleType.ResourceAdmin,
RoleType.DomainAdmin, RoleType.User})
+ authorized = {RoleType.Admin})
public class AddDnsServerCmd extends BaseCmd {
/////////////////////////////////////////////////////
diff --git
a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/DeleteDnsServerCmd.java
b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/DeleteDnsServerCmd.java
index 099fc62f354..cb001f69523 100644
---
a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/DeleteDnsServerCmd.java
+++
b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/DeleteDnsServerCmd.java
@@ -40,7 +40,7 @@ import com.cloud.user.Account;
entityType = {DnsServer.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
since = "4.23.0",
- authorized = {RoleType.Admin, RoleType.ResourceAdmin,
RoleType.DomainAdmin, RoleType.User})
+ authorized = {RoleType.Admin})
public class DeleteDnsServerCmd extends BaseAsyncCmd {
/////////////////////////////////////////////////////
diff --git
a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/UpdateDnsServerCmd.java
b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/UpdateDnsServerCmd.java
index 6b790fa8ade..7a84c54dc66 100644
---
a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/UpdateDnsServerCmd.java
+++
b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/UpdateDnsServerCmd.java
@@ -41,7 +41,7 @@ import com.cloud.utils.EnumUtils;
entityType = {DnsServer.class},
requestHasSensitiveInfo = true, responseHasSensitiveInfo = false,
since = "4.23.0",
- authorized = {RoleType.Admin, RoleType.ResourceAdmin,
RoleType.DomainAdmin, RoleType.User})
+ authorized = {RoleType.Admin})
public class UpdateDnsServerCmd extends BaseCmd {
/////////////////////////////////////////////////////
diff --git
a/engine/schema/src/main/resources/META-INF/db/views/nic_dns_view.sql
b/engine/schema/src/main/resources/META-INF/db/views/cloud.nic_dns_view.sql
similarity index 100%
rename from engine/schema/src/main/resources/META-INF/db/views/nic_dns_view.sql
rename to
engine/schema/src/main/resources/META-INF/db/views/cloud.nic_dns_view.sql
diff --git
a/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java
b/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java
index e1ace5d7a3c..ef55eaf66c1 100644
--- a/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java
@@ -96,6 +96,7 @@ import com.cloud.user.User;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
+import com.cloud.utils.UriUtils;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.component.PluggableService;
import com.cloud.utils.db.Filter;
@@ -107,9 +108,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.Nic;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineManager;
-import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.NicDetailsDao;
-import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
@Component
@@ -126,10 +125,6 @@ public class DnsProviderManagerImpl extends ManagerBase
implements DnsProviderMa
@Inject
DnsZoneNetworkMapDao dnsZoneNetworkMapDao;
@Inject
- UserVmDao userVmDao;
- @Inject
- NicDao nicDao;
- @Inject
DomainDao domainDao;
@Inject
DnsZoneJoinDao dnsZoneJoinDao;
@@ -162,14 +157,36 @@ public class DnsProviderManagerImpl extends ManagerBase
implements DnsProviderMa
throw new CloudRuntimeException("No plugin found for DNS provider
type: " + type);
}
+ /**
+ * Rejects a DNS provider URL that resolves to an illegal address before
any provider client
+ * is given the chance to connect to it. See {@link
UriUtils#validateUrl(String)} for the exact rules
+ * enforced (including the requirement that the URL declares an {@code
http}/{@code https} scheme).
+ *
+ * @throws InvalidParameterValueException if the URL is blank, fails
validation
+ */
+ private void validateDnsServerUrl(String trimmedUrl) {
+ if (StringUtils.isBlank(trimmedUrl)) {
+ throw new InvalidParameterValueException("URL cannot be blank.");
+ }
+ try {
+ UriUtils.validateUrl(trimmedUrl);
+ } catch (IllegalArgumentException e) {
+ throw new InvalidParameterValueException(e.getMessage());
+ }
+ }
+
@Override
@ActionEvent(eventType = EventTypes.EVENT_DNS_SERVER_ADD, eventDescription
= "Adding a DNS Server")
public DnsServer addDnsServer(AddDnsServerCmd cmd) {
Account caller = CallContext.current().getCallingAccount();
- DnsServer existing = dnsServerDao.findByUrlAndAccount(cmd.getUrl(),
caller.getId());
+ enforceRootAdminOnly(caller.getId());
+
+ String dnsUrl = StringUtils.trim(cmd.getUrl());
+ validateDnsServerUrl(dnsUrl);
+ DnsServer existing = dnsServerDao.findByUrlAndAccount(dnsUrl,
caller.getId());
if (existing != null) {
throw new InvalidParameterValueException(
- "This Account already has a DNS server integration for
URL: " + cmd.getUrl());
+ "This Account already has a DNS server integration for
URL: " + dnsUrl);
}
boolean isDnsPublic = cmd.isPublic();
@@ -190,7 +207,7 @@ public class DnsProviderManagerImpl extends ManagerBase
implements DnsProviderMa
}
DnsProviderType type = cmd.getProvider();
- DnsServerVO server = new DnsServerVO(cmd.getName(), cmd.getUrl(),
cmd.getPort(), type,
+ DnsServerVO server = new DnsServerVO(cmd.getName(), dnsUrl,
cmd.getPort(), type,
cmd.getDnsUserName(), cmd.getDnsApiKey(), isDnsPublic,
publicDomainSuffix, cmd.getNameServers(),
caller.getAccountId(), caller.getDomainId());
@@ -245,6 +262,8 @@ public class DnsProviderManagerImpl extends ManagerBase
implements DnsProviderMa
}
Account caller = CallContext.current().getCallingAccount();
+ enforceRootAdminOnly(caller.getId());
+
accountMgr.checkAccess(caller, null, true, dnsServer);
boolean validationRequired = false;
@@ -255,13 +274,15 @@ public class DnsProviderManagerImpl extends ManagerBase
implements DnsProviderMa
dnsServer.setName(cmd.getName());
}
- if (cmd.getUrl() != null) {
- if (!cmd.getUrl().equals(originalUrl)) {
- DnsServer duplicate =
dnsServerDao.findByUrlAndAccount(cmd.getUrl(), dnsServer.getAccountId());
+ if (StringUtils.isNotBlank(cmd.getUrl())) {
+ String dnsUrl = StringUtils.trim(cmd.getUrl());
+ if (!dnsUrl.equals(originalUrl)) {
+ validateDnsServerUrl(dnsUrl);
+ DnsServer duplicate = dnsServerDao.findByUrlAndAccount(dnsUrl,
dnsServer.getAccountId());
if (duplicate != null && duplicate.getId() !=
dnsServer.getId()) {
throw new InvalidParameterValueException("Another DNS
server with this URL already exists.");
}
- dnsServer.setUrl(cmd.getUrl());
+ dnsServer.setUrl(dnsUrl);
validationRequired = true;
}
}
@@ -330,6 +351,7 @@ public class DnsProviderManagerImpl extends ManagerBase
implements DnsProviderMa
throw new InvalidParameterValueException(String.format("DNS server
with ID: %s not found.", dnsServerId));
}
Account caller = CallContext.current().getCallingAccount();
+ enforceRootAdminOnly(caller.getId());
accountMgr.checkAccess(caller, null, true, dnsServer);
return Transaction.execute((TransactionCallback<Boolean>) status -> {
if (cmd.getCleanup()) {
@@ -1263,4 +1285,10 @@ public class DnsProviderManagerImpl extends ManagerBase
implements DnsProviderMa
provider.addRecord(dnsServer, dnsZone, recordIpv6);
}
}
+
+ void enforceRootAdminOnly(Long callerId) {
+ if (!accountMgr.isRootAdmin(callerId)) {
+ throw new PermissionDeniedException("This API can only be called
by root admin");
+ }
+ }
}
diff --git
a/server/src/test/java/org/apache/cloudstack/dns/DnsProviderManagerImplTest.java
b/server/src/test/java/org/apache/cloudstack/dns/DnsProviderManagerImplTest.java
index 8ce31d4e7c7..f70d5915a65 100644
---
a/server/src/test/java/org/apache/cloudstack/dns/DnsProviderManagerImplTest.java
+++
b/server/src/test/java/org/apache/cloudstack/dns/DnsProviderManagerImplTest.java
@@ -42,11 +42,20 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.cloudstack.acl.SecurityChecker;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd;
+import org.apache.cloudstack.api.command.user.dns.AssociateDnsZoneToNetworkCmd;
+import org.apache.cloudstack.api.command.user.dns.CreateDnsRecordCmd;
import org.apache.cloudstack.api.command.user.dns.CreateDnsZoneCmd;
+import org.apache.cloudstack.api.command.user.dns.DeleteDnsRecordCmd;
import org.apache.cloudstack.api.command.user.dns.DeleteDnsServerCmd;
import
org.apache.cloudstack.api.command.user.dns.DisassociateDnsZoneFromNetworkCmd;
import org.apache.cloudstack.api.command.user.dns.ListDnsRecordsCmd;
+import org.apache.cloudstack.api.command.user.dns.ListDnsServersCmd;
+import org.apache.cloudstack.api.command.user.dns.ListDnsZonesCmd;
+import org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd;
import org.apache.cloudstack.api.command.user.dns.UpdateDnsZoneCmd;
import org.apache.cloudstack.api.response.DnsRecordResponse;
import org.apache.cloudstack.api.response.DnsServerResponse;
@@ -83,6 +92,8 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
import com.cloud.domain.dao.DomainDao;
+import com.cloud.event.ActionEventUtils;
+import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.network.dao.NetworkDao;
@@ -90,9 +101,13 @@ import com.cloud.network.dao.NetworkVO;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.Pair;
+import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.NicDetailsDao;
@@ -174,7 +189,9 @@ public class DnsProviderManagerImplTest {
manager.setDnsProviders(Collections.singletonList(dnsProviderMock));
doNothing().when(accountMgr).checkAccess(any(Account.class),
-
nullable(org.apache.cloudstack.acl.SecurityChecker.AccessType.class), eq(true),
any());
+ nullable(SecurityChecker.AccessType.class), eq(true), any());
+
+ when(accountMgr.isRootAdmin(callerMock.getId())).thenReturn(true);
}
@After
@@ -424,7 +441,7 @@ public class DnsProviderManagerImplTest {
when(cmd.getCleanup()).thenReturn(true);
when(dnsServerDao.findById(SERVER_ID)).thenReturn(serverVO);
doNothing().when(accountMgr).checkAccess(any(Account.class),
-
nullable(org.apache.cloudstack.acl.SecurityChecker.AccessType.class), eq(true),
any());
+ nullable(SecurityChecker.AccessType.class), eq(true), any());
List<Long> zones = Collections.singletonList(ZONE_ID);
when(dnsZoneDao.findDnsZoneIdsByServerId(SERVER_ID)).thenReturn(zones);
@@ -451,7 +468,7 @@ public class DnsProviderManagerImplTest {
when(dnsZoneDao.findById(ZONE_ID)).thenReturn(zoneVO);
when(dnsServerDao.findById(anyLong())).thenReturn(serverVO);
doNothing().when(accountMgr).checkAccess(any(Account.class),
-
nullable(org.apache.cloudstack.acl.SecurityChecker.AccessType.class), eq(true),
any());
+ nullable(SecurityChecker.AccessType.class), eq(true), any());
when(dnsZoneNetworkMapDao.findByZoneId(ZONE_ID)).thenReturn(null);
when(dnsZoneDao.remove(ZONE_ID)).thenReturn(true);
@@ -615,8 +632,8 @@ public class DnsProviderManagerImplTest {
Mockito.doReturn(true).when(serverVO).getPublicServer();
when(serverOwner.getDomainId()).thenReturn(20L);
when(callerMock.getDomainId()).thenReturn(DOMAIN_ID);
- ReflectionTestUtils.setField(manager, "accountDao",
Mockito.mock(com.cloud.user.dao.AccountDao.class));
- com.cloud.user.dao.AccountDao accountDaoMock =
(com.cloud.user.dao.AccountDao) ReflectionTestUtils
+ ReflectionTestUtils.setField(manager, "accountDao",
Mockito.mock(AccountDao.class));
+ AccountDao accountDaoMock = (AccountDao) ReflectionTestUtils
.getField(manager, "accountDao");
when(accountDaoMock.findByIdIncludingRemoved(ACCOUNT_ID)).thenReturn(serverOwner);
when(domainDao.isChildDomain(20L, DOMAIN_ID)).thenReturn(false);
@@ -659,8 +676,7 @@ public class DnsProviderManagerImplTest {
@Test(expected = InvalidParameterValueException.class)
public void testAssociateZoneToNetworkZoneNotFound() {
-
org.apache.cloudstack.api.command.user.dns.AssociateDnsZoneToNetworkCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.AssociateDnsZoneToNetworkCmd.class);
+ AssociateDnsZoneToNetworkCmd cmd =
mock(AssociateDnsZoneToNetworkCmd.class);
when(cmd.getDnsZoneId()).thenReturn(ZONE_ID);
when(dnsZoneDao.findById(ZONE_ID)).thenReturn(null);
manager.associateZoneToNetwork(cmd);
@@ -668,8 +684,7 @@ public class DnsProviderManagerImplTest {
@Test(expected = InvalidParameterValueException.class)
public void testAssociateZoneToNetworkNetworkNotFound() {
-
org.apache.cloudstack.api.command.user.dns.AssociateDnsZoneToNetworkCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.AssociateDnsZoneToNetworkCmd.class);
+ AssociateDnsZoneToNetworkCmd cmd =
mock(AssociateDnsZoneToNetworkCmd.class);
when(cmd.getDnsZoneId()).thenReturn(ZONE_ID);
when(cmd.getNetworkId()).thenReturn(NETWORK_ID);
when(dnsZoneDao.findById(ZONE_ID)).thenReturn(zoneVO);
@@ -680,8 +695,7 @@ public class DnsProviderManagerImplTest {
@Test(expected = CloudRuntimeException.class)
public void testAssociateZoneToNetworkNonSharedNetwork() {
-
org.apache.cloudstack.api.command.user.dns.AssociateDnsZoneToNetworkCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.AssociateDnsZoneToNetworkCmd.class);
+ AssociateDnsZoneToNetworkCmd cmd =
mock(AssociateDnsZoneToNetworkCmd.class);
when(cmd.getDnsZoneId()).thenReturn(ZONE_ID);
when(cmd.getNetworkId()).thenReturn(NETWORK_ID);
when(dnsZoneDao.findById(ZONE_ID)).thenReturn(zoneVO);
@@ -694,8 +708,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testAssociateZoneToNetworkSuccess() {
-
org.apache.cloudstack.api.command.user.dns.AssociateDnsZoneToNetworkCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.AssociateDnsZoneToNetworkCmd.class);
+ AssociateDnsZoneToNetworkCmd cmd =
mock(AssociateDnsZoneToNetworkCmd.class);
when(cmd.getDnsZoneId()).thenReturn(ZONE_ID);
when(cmd.getNetworkId()).thenReturn(NETWORK_ID);
@@ -715,8 +728,7 @@ public class DnsProviderManagerImplTest {
@Test(expected = InvalidParameterValueException.class)
public void testAssociateZoneToNetworkAlreadyAssociated() {
-
org.apache.cloudstack.api.command.user.dns.AssociateDnsZoneToNetworkCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.AssociateDnsZoneToNetworkCmd.class);
+ AssociateDnsZoneToNetworkCmd cmd =
mock(AssociateDnsZoneToNetworkCmd.class);
when(cmd.getDnsZoneId()).thenReturn(ZONE_ID);
when(cmd.getNetworkId()).thenReturn(NETWORK_ID);
when(dnsZoneDao.findById(ZONE_ID)).thenReturn(zoneVO);
@@ -731,8 +743,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testCreateDnsRecordSuccess() throws Exception {
- org.apache.cloudstack.api.command.user.dns.CreateDnsRecordCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.CreateDnsRecordCmd.class);
+ CreateDnsRecordCmd cmd = mock(CreateDnsRecordCmd.class);
when(cmd.getName()).thenReturn("www");
when(cmd.getDnsZoneId()).thenReturn(ZONE_ID);
when(cmd.getType()).thenReturn(DnsRecord.RecordType.A);
@@ -748,8 +759,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testDeleteDnsRecordSuccess() throws Exception {
- org.apache.cloudstack.api.command.user.dns.DeleteDnsRecordCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.DeleteDnsRecordCmd.class);
+ DeleteDnsRecordCmd cmd = mock(DeleteDnsRecordCmd.class);
when(cmd.getDnsZoneId()).thenReturn(ZONE_ID);
when(cmd.getName()).thenReturn("www");
when(dnsZoneDao.findById(ZONE_ID)).thenReturn(zoneVO);
@@ -769,10 +779,8 @@ public class DnsProviderManagerImplTest {
@Test
public void testAddDnsServerSuccess() throws Exception {
- org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd cmd = mock(
-
org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd.class);
- when(accountMgr.isRootAdmin(callerMock.getId())).thenReturn(true);
- when(cmd.getUrl()).thenReturn("http://newpdns:8081");
+ AddDnsServerCmd cmd = mock(AddDnsServerCmd.class);
+ when(cmd.getUrl()).thenReturn("http://192.0.2.1:8081");
when(cmd.getProvider()).thenReturn(DnsProviderType.PowerDNS);
when(dnsServerDao.findByUrlAndAccount(anyString(),
anyLong())).thenReturn(null);
when(dnsProviderMock.validateAndResolveServer(any())).thenReturn("resolved-id");
@@ -784,11 +792,10 @@ public class DnsProviderManagerImplTest {
@Test
public void testListDnsServers() {
- org.apache.cloudstack.api.command.user.dns.ListDnsServersCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.ListDnsServersCmd.class);
+ ListDnsServersCmd cmd = mock(ListDnsServersCmd.class);
when(domainDao.getDomainParentIds(anyLong())).thenReturn(Collections.emptySet());
List<DnsServerVO> servers = Collections.singletonList(serverVO);
- com.cloud.utils.Pair<List<DnsServerVO>, Integer> searchPair = new
com.cloud.utils.Pair<>(servers, 1);
+ Pair<List<DnsServerVO>, Integer> searchPair = new Pair<>(servers, 1);
when(dnsServerDao.searchDnsServer(any(), anyLong(), any(), any(),
any(), any())).thenReturn(searchPair);
DnsServerJoinVO joinVO = mock(DnsServerJoinVO.class);
@@ -802,8 +809,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testUpdateDnsServer() throws Exception {
- org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd.class);
+ UpdateDnsServerCmd cmd = mock(UpdateDnsServerCmd.class);
when(cmd.getId()).thenReturn(SERVER_ID);
when(cmd.getName()).thenReturn("updated-name");
when(dnsServerDao.findById(SERVER_ID)).thenReturn(serverVO);
@@ -815,13 +821,12 @@ public class DnsProviderManagerImplTest {
@Test
public void testListDnsZones() {
- org.apache.cloudstack.api.command.user.dns.ListDnsZonesCmd cmd = mock(
-
org.apache.cloudstack.api.command.user.dns.ListDnsZonesCmd.class);
+ ListDnsZonesCmd cmd = mock(ListDnsZonesCmd.class);
when(cmd.getId()).thenReturn(null);
when(cmd.getDnsServerId()).thenReturn(null);
when(dnsServerDao.listDnsServerIdsByAccountId(anyLong())).thenReturn(Collections.emptyList());
List<DnsZoneVO> zones = Collections.singletonList(zoneVO);
- com.cloud.utils.Pair<List<DnsZoneVO>, Integer> searchPair = new
com.cloud.utils.Pair<>(zones, 1);
+ Pair<List<DnsZoneVO>, Integer> searchPair = new Pair<>(zones, 1);
when(dnsZoneDao.searchZones(any(), anyLong(), any(), any(), any(),
any())).thenReturn(searchPair);
DnsZoneJoinVO joinVO = mock(DnsZoneJoinVO.class);
@@ -833,39 +838,60 @@ public class DnsProviderManagerImplTest {
@Test(expected = InvalidParameterValueException.class)
public void testAddDnsServerAlreadyExists() {
- org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd cmd = mock(
-
org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd.class);
- when(cmd.getUrl()).thenReturn("http://newpdns:8081");
+ AddDnsServerCmd cmd = mock(AddDnsServerCmd.class);
+ when(cmd.getUrl()).thenReturn("http://192.0.2.1:8081");
when(dnsServerDao.findByUrlAndAccount(anyString(),
anyLong())).thenReturn(serverVO);
manager.addDnsServer(cmd);
}
@Test
- public void testAddDnsServerNormalUser() throws Exception {
- org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd cmd = mock(
-
org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd.class);
- when(accountMgr.isRootAdmin(callerMock.getId())).thenReturn(false);
- when(accountMgr.isDomainAdmin(callerMock.getId())).thenReturn(false);
- when(cmd.getUrl()).thenReturn("http://newpdns:8081");
+ public void testAddDnsServerTrimsUrlBeforeDuplicateCheckAndPersistence()
throws Exception {
+ AddDnsServerCmd cmd = mock(AddDnsServerCmd.class);
+ when(cmd.getUrl()).thenReturn(" http://192.0.2.1:8081 ");
+ when(cmd.getProvider()).thenReturn(DnsProviderType.PowerDNS);
+ when(dnsServerDao.findByUrlAndAccount(anyString(),
anyLong())).thenReturn(null);
+
when(dnsProviderMock.validateAndResolveServer(any())).thenReturn("resolved-id");
+ when(dnsServerDao.persist(any())).thenReturn(serverVO);
+
+ manager.addDnsServer(cmd);
+
+ verify(dnsServerDao).findByUrlAndAccount(eq("http://192.0.2.1:8081"),
anyLong());
+ verify(dnsServerDao).persist(Mockito.argThat(s ->
"http://192.0.2.1:8081".equals(((DnsServerVO) s).getUrl())));
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void testAddDnsServerRejectsLoopbackUrl() {
+ AddDnsServerCmd cmd = mock(AddDnsServerCmd.class);
+ when(cmd.getUrl()).thenReturn("http://127.0.0.1:8081");
+ manager.addDnsServer(cmd);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void testAddDnsServerRejectsUrlWithoutScheme() {
+ AddDnsServerCmd cmd = mock(AddDnsServerCmd.class);
+ when(cmd.getUrl()).thenReturn("192.0.2.1:8081");
+ manager.addDnsServer(cmd);
+ }
+
+ @Test
+ public void testAddDnsServerAllowsPrivateAddressForRootAdmin() throws
Exception {
+ AddDnsServerCmd cmd = mock(AddDnsServerCmd.class);
+ when(cmd.getUrl()).thenReturn("http://192.168.1.1:8081");
when(cmd.getProvider()).thenReturn(DnsProviderType.PowerDNS);
- when(cmd.getNameServers()).thenReturn(Collections.emptyList());
- when(cmd.isPublic()).thenReturn(true);
- when(cmd.getPublicDomainSuffix()).thenReturn("example.com");
when(dnsServerDao.findByUrlAndAccount(anyString(),
anyLong())).thenReturn(null);
when(dnsProviderMock.validateAndResolveServer(any())).thenReturn("resolved-id");
when(dnsServerDao.persist(any())).thenReturn(serverVO);
+
DnsServer result = manager.addDnsServer(cmd);
assertNotNull(result);
- verify(dnsServerDao).persist(Mockito.argThat(
- s -> !((DnsServerVO) s).getPublicServer() && ((DnsServerVO)
s).getPublicDomainSuffix() == null));
+ verify(dnsServerDao).persist(any());
}
@Test(expected = InvalidParameterValueException.class)
public void testAddDnsServerPublicWithoutSuffixRejected() {
- org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd cmd = mock(
-
org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd.class);
+ AddDnsServerCmd cmd = mock(AddDnsServerCmd.class);
when(accountMgr.isRootAdmin(callerMock.getId())).thenReturn(true);
- when(cmd.getUrl()).thenReturn("http://newpdns:8081");
+ when(cmd.getUrl()).thenReturn("http://192.0.2.1:8081");
when(cmd.isPublic()).thenReturn(true);
when(dnsServerDao.findByUrlAndAccount(anyString(),
anyLong())).thenReturn(null);
manager.addDnsServer(cmd);
@@ -873,8 +899,7 @@ public class DnsProviderManagerImplTest {
@Test(expected = InvalidParameterValueException.class)
public void testUpdateDnsServerPublicWithoutSuffixRejected() {
- org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd.class);
+ UpdateDnsServerCmd cmd = mock(UpdateDnsServerCmd.class);
when(cmd.getId()).thenReturn(SERVER_ID);
when(cmd.isPublic()).thenReturn(true);
when(accountMgr.isRootAdmin(callerMock.getId())).thenReturn(true);
@@ -884,10 +909,8 @@ public class DnsProviderManagerImplTest {
@Test(expected = CloudRuntimeException.class)
public void testAddDnsServerValidationFailure() throws Exception {
- org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd cmd = mock(
-
org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd.class);
- when(accountMgr.isRootAdmin(callerMock.getId())).thenReturn(true);
- when(cmd.getUrl()).thenReturn("http://newpdns:8081");
+ AddDnsServerCmd cmd = mock(AddDnsServerCmd.class);
+ when(cmd.getUrl()).thenReturn("http://192.0.2.1:8081");
when(cmd.getProvider()).thenReturn(DnsProviderType.PowerDNS);
when(cmd.getNameServers()).thenReturn(Collections.emptyList());
when(dnsServerDao.findByUrlAndAccount(anyString(),
anyLong())).thenReturn(null);
@@ -895,12 +918,18 @@ public class DnsProviderManagerImplTest {
manager.addDnsServer(cmd);
}
+ @Test(expected = PermissionDeniedException.class)
+ public void testAddDnsServerNormalUser() throws Exception {
+ AddDnsServerCmd cmd = mock(AddDnsServerCmd.class);
+ when(accountMgr.isRootAdmin(callerMock.getId())).thenReturn(false);
+ manager.addDnsServer(cmd);
+ }
+
@Test(expected = InvalidParameterValueException.class)
public void testUpdateDnsServerUrlDuplicate() {
- org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd.class);
+ UpdateDnsServerCmd cmd = mock(UpdateDnsServerCmd.class);
when(cmd.getId()).thenReturn(SERVER_ID);
- when(cmd.getUrl()).thenReturn("http://duplicate:8081");
+ when(cmd.getUrl()).thenReturn("http://192.0.2.1:8081");
DnsServerVO existingServer = mock(DnsServerVO.class);
when(existingServer.getId()).thenReturn(SERVER_ID + 1); // Different
ID implies duplicate
@@ -911,12 +940,56 @@ public class DnsProviderManagerImplTest {
manager.updateDnsServer(cmd);
}
+ @Test(expected = InvalidParameterValueException.class)
+ public void testUpdateDnsServerRejectsLoopbackUrl() {
+ UpdateDnsServerCmd cmd = mock(UpdateDnsServerCmd.class);
+ when(cmd.getId()).thenReturn(SERVER_ID);
+ when(cmd.getUrl()).thenReturn("http://127.0.0.1:8081");
+ when(dnsServerDao.findById(SERVER_ID)).thenReturn(serverVO);
+ Mockito.doReturn("http://original:8081").when(serverVO).getUrl();
+
+ manager.updateDnsServer(cmd);
+ }
+
+ @Test
+ public void testUpdateDnsServerAllowsPrivateAddressForRootAdmin() throws
Exception {
+ UpdateDnsServerCmd cmd = mock(UpdateDnsServerCmd.class);
+ when(cmd.getId()).thenReturn(SERVER_ID);
+ when(cmd.getUrl()).thenReturn("http://192.168.1.1:8081");
+ when(dnsServerDao.findById(SERVER_ID)).thenReturn(serverVO);
+ Mockito.doReturn("http://original:8081").when(serverVO).getUrl();
+
Mockito.doReturn(DnsProviderType.PowerDNS).when(serverVO).getProviderType();
+ when(dnsServerDao.findByUrlAndAccount(anyString(),
anyLong())).thenReturn(null);
+ doNothing().when(dnsProviderMock).validate(any());
+ when(dnsServerDao.update(anyLong(), any())).thenReturn(true);
+
+ DnsServer result = manager.updateDnsServer(cmd);
+ assertNotNull(result);
+ verify(dnsProviderMock).validate(any());
+ }
+
+ @Test
+ public void testUpdateDnsServerTreatsWhitespaceOnlyUrlChangeAsUnchanged()
throws Exception {
+ UpdateDnsServerCmd cmd = mock(UpdateDnsServerCmd.class);
+ Integer unchangedPort = serverVO.getPort();
+ when(cmd.getId()).thenReturn(SERVER_ID);
+ when(cmd.getUrl()).thenReturn(" http://192.0.2.1:8081 ");
+ when(cmd.getPort()).thenReturn(unchangedPort);
+ when(dnsServerDao.findById(SERVER_ID)).thenReturn(serverVO);
+ Mockito.doReturn("http://192.0.2.1:8081").when(serverVO).getUrl();
+ when(dnsServerDao.update(anyLong(), any())).thenReturn(true);
+
+ DnsServer result = manager.updateDnsServer(cmd);
+ assertNotNull(result);
+ verify(dnsProviderMock, never()).validate(any());
+ verify(serverVO, never()).setUrl(anyString());
+ }
+
@Test
public void testUpdateDnsServerUrlValid() throws Exception {
- org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd.class);
+ UpdateDnsServerCmd cmd = mock(UpdateDnsServerCmd.class);
when(cmd.getId()).thenReturn(SERVER_ID);
- when(cmd.getUrl()).thenReturn("http://new-url:8081");
+ when(cmd.getUrl()).thenReturn("http://192.0.2.1:8081");
when(dnsServerDao.findById(SERVER_ID)).thenReturn(serverVO);
Mockito.doReturn("http://original:8081").when(serverVO).getUrl();
@@ -932,8 +1005,7 @@ public class DnsProviderManagerImplTest {
@Test(expected = InvalidParameterValueException.class)
public void testUpdateDnsServerValidationException() throws Exception {
- org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd.class);
+ UpdateDnsServerCmd cmd = mock(UpdateDnsServerCmd.class);
when(cmd.getId()).thenReturn(SERVER_ID);
when(cmd.getDnsApiKey()).thenReturn("new-api-key");
@@ -950,10 +1022,10 @@ public class DnsProviderManagerImplTest {
@Test
public void testVmLifecycleSubscriberStateUnchanged() {
DnsProviderManagerImpl.VmLifecycleSubscriber subscriber = manager.new
VmLifecycleSubscriber();
- java.util.Map<String, Object> event = new java.util.HashMap<>();
- event.put(org.apache.cloudstack.api.ApiConstants.OLD_STATE,
com.cloud.vm.VirtualMachine.State.Running);
- event.put(org.apache.cloudstack.api.ApiConstants.NEW_STATE,
com.cloud.vm.VirtualMachine.State.Running);
- event.put(org.apache.cloudstack.api.ApiConstants.INSTANCE_ID, 10L);
+ Map<String, Object> event = new HashMap<>();
+ event.put(ApiConstants.OLD_STATE, VirtualMachine.State.Running);
+ event.put(ApiConstants.NEW_STATE, VirtualMachine.State.Running);
+ event.put(ApiConstants.INSTANCE_ID, 10L);
subscriber.onPublishMessage("sender", "subject", event);
verify(vmInstanceDao, never()).findByIdIncludingRemoved(anyLong());
@@ -962,10 +1034,10 @@ public class DnsProviderManagerImplTest {
@Test
public void testVmLifecycleSubscriberRunning() {
DnsProviderManagerImpl.VmLifecycleSubscriber subscriber = manager.new
VmLifecycleSubscriber();
- java.util.Map<String, Object> event = new java.util.HashMap<>();
- event.put(org.apache.cloudstack.api.ApiConstants.OLD_STATE,
com.cloud.vm.VirtualMachine.State.Starting);
- event.put(org.apache.cloudstack.api.ApiConstants.NEW_STATE,
com.cloud.vm.VirtualMachine.State.Running);
- event.put(org.apache.cloudstack.api.ApiConstants.INSTANCE_ID, 12L);
+ Map<String, Object> event = new HashMap<>();
+ event.put(ApiConstants.OLD_STATE, VirtualMachine.State.Starting);
+ event.put(ApiConstants.NEW_STATE, VirtualMachine.State.Running);
+ event.put(ApiConstants.INSTANCE_ID, 12L);
// Expect handleVmEvent to be called, which accesses
// vmInstanceDao.findByIdIncludingRemoved
@@ -978,10 +1050,10 @@ public class DnsProviderManagerImplTest {
@Test
public void testVmLifecycleSubscriberDestroyed() {
DnsProviderManagerImpl.VmLifecycleSubscriber subscriber = manager.new
VmLifecycleSubscriber();
- java.util.Map<String, Object> event = new java.util.HashMap<>();
- event.put(org.apache.cloudstack.api.ApiConstants.OLD_STATE,
com.cloud.vm.VirtualMachine.State.Running);
- event.put(org.apache.cloudstack.api.ApiConstants.NEW_STATE,
VirtualMachine.State.Destroyed);
- event.put(org.apache.cloudstack.api.ApiConstants.INSTANCE_ID, 15L);
+ Map<String, Object> event = new HashMap<>();
+ event.put(ApiConstants.OLD_STATE, VirtualMachine.State.Running);
+ event.put(ApiConstants.NEW_STATE, VirtualMachine.State.Destroyed);
+ event.put(ApiConstants.INSTANCE_ID, 15L);
when(nicDnsJoinDao.listIncludingRemovedByVmId(15L)).thenReturn(null);
subscriber.onPublishMessage("sender", "subject", event);
verify(nicDnsJoinDao, times(1)).listIncludingRemovedByVmId(15L);
@@ -990,10 +1062,10 @@ public class DnsProviderManagerImplTest {
@Test
public void testVmLifecycleSubscriberUnsupportedState() {
DnsProviderManagerImpl.VmLifecycleSubscriber subscriber = manager.new
VmLifecycleSubscriber();
- java.util.Map<String, Object> event = new java.util.HashMap<>();
- event.put(org.apache.cloudstack.api.ApiConstants.OLD_STATE,
com.cloud.vm.VirtualMachine.State.Running);
- event.put(org.apache.cloudstack.api.ApiConstants.NEW_STATE,
com.cloud.vm.VirtualMachine.State.Starting);
- event.put(org.apache.cloudstack.api.ApiConstants.INSTANCE_ID, 20L);
+ Map<String, Object> event = new HashMap<>();
+ event.put(ApiConstants.OLD_STATE, VirtualMachine.State.Running);
+ event.put(ApiConstants.NEW_STATE, VirtualMachine.State.Starting);
+ event.put(ApiConstants.INSTANCE_ID, 20L);
subscriber.onPublishMessage("sender", "subject", event);
verify(vmInstanceDao, never()).findByIdIncludingRemoved(anyLong());
@@ -1011,10 +1083,10 @@ public class DnsProviderManagerImplTest {
@Test
public void testNicLifecycleSubscriberCreate() {
DnsProviderManagerImpl.NicLifecycleSubscriber subscriber = manager.new
NicLifecycleSubscriber();
- java.util.Map<String, Object> event = new java.util.HashMap<>();
- event.put(org.apache.cloudstack.api.ApiConstants.EVENT_TYPE,
com.cloud.event.EventTypes.EVENT_NIC_CREATE);
- event.put(org.apache.cloudstack.api.ApiConstants.NIC_ID, 100L);
- event.put(org.apache.cloudstack.api.ApiConstants.INSTANCE_ID, 200L);
+ Map<String, Object> event = new HashMap<>();
+ event.put(ApiConstants.EVENT_TYPE, EventTypes.EVENT_NIC_CREATE);
+ event.put(ApiConstants.NIC_ID, 100L);
+ event.put(ApiConstants.INSTANCE_ID, 200L);
when(vmInstanceDao.findById(200L)).thenReturn(null); // Short circuits
handleNicEvent
@@ -1025,10 +1097,10 @@ public class DnsProviderManagerImplTest {
@Test
public void testNicLifecycleSubscriberDelete() {
DnsProviderManagerImpl.NicLifecycleSubscriber subscriber = manager.new
NicLifecycleSubscriber();
- java.util.Map<String, Object> event = new java.util.HashMap<>();
- event.put(org.apache.cloudstack.api.ApiConstants.EVENT_TYPE,
com.cloud.event.EventTypes.EVENT_NIC_DELETE);
- event.put(org.apache.cloudstack.api.ApiConstants.NIC_ID, 101L);
- event.put(org.apache.cloudstack.api.ApiConstants.INSTANCE_ID, 201L);
+ Map<String, Object> event = new HashMap<>();
+ event.put(ApiConstants.EVENT_TYPE, EventTypes.EVENT_NIC_DELETE);
+ event.put(ApiConstants.NIC_ID, 101L);
+ event.put(ApiConstants.INSTANCE_ID, 201L);
when(nicDnsJoinDao.findByIdIncludingRemoved(101L)).thenReturn(null);
subscriber.onPublishMessage("sender", "subject", event);
verify(nicDnsJoinDao, times(1)).findByIdIncludingRemoved(101L);
@@ -1037,8 +1109,8 @@ public class DnsProviderManagerImplTest {
@Test
public void testNicLifecycleSubscriberMissingData() {
DnsProviderManagerImpl.NicLifecycleSubscriber subscriber = manager.new
NicLifecycleSubscriber();
- java.util.Map<String, Object> event = new java.util.HashMap<>();
- event.put(org.apache.cloudstack.api.ApiConstants.EVENT_TYPE,
com.cloud.event.EventTypes.EVENT_NIC_CREATE);
+ Map<String, Object> event = new HashMap<>();
+ event.put(ApiConstants.EVENT_TYPE, EventTypes.EVENT_NIC_CREATE);
// Missing NIC_ID and INSTANCE_ID
subscriber.onPublishMessage("sender", "subject", event);
@@ -1048,10 +1120,10 @@ public class DnsProviderManagerImplTest {
@Test
public void testNicLifecycleSubscriberUnsupportedEvent() {
DnsProviderManagerImpl.NicLifecycleSubscriber subscriber = manager.new
NicLifecycleSubscriber();
- java.util.Map<String, Object> event = new java.util.HashMap<>();
- event.put(org.apache.cloudstack.api.ApiConstants.EVENT_TYPE,
"unsupported-event");
- event.put(org.apache.cloudstack.api.ApiConstants.NIC_ID, 102L);
- event.put(org.apache.cloudstack.api.ApiConstants.INSTANCE_ID, 202L);
+ Map<String, Object> event = new HashMap<>();
+ event.put(ApiConstants.EVENT_TYPE, "unsupported-event");
+ event.put(ApiConstants.NIC_ID, 102L);
+ event.put(ApiConstants.INSTANCE_ID, 202L);
subscriber.onPublishMessage("sender", "subject", event);
verify(vmInstanceDao, never()).findById(anyLong());
@@ -1085,8 +1157,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testCreateDnsRecordAlreadyExistsThrowsCloudRuntimeException()
throws Exception {
- org.apache.cloudstack.api.command.user.dns.CreateDnsRecordCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.CreateDnsRecordCmd.class);
+ CreateDnsRecordCmd cmd = mock(CreateDnsRecordCmd.class);
when(cmd.getName()).thenReturn("www");
when(cmd.getDnsZoneId()).thenReturn(ZONE_ID);
when(cmd.getType()).thenReturn(DnsRecord.RecordType.A);
@@ -1105,8 +1176,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testDeleteDnsRecordProviderReturnsNullReturnsFalse() throws
Exception {
- org.apache.cloudstack.api.command.user.dns.DeleteDnsRecordCmd cmd =
mock(
-
org.apache.cloudstack.api.command.user.dns.DeleteDnsRecordCmd.class);
+ DeleteDnsRecordCmd cmd = mock(DeleteDnsRecordCmd.class);
when(cmd.getDnsZoneId()).thenReturn(ZONE_ID);
when(cmd.getName()).thenReturn("www");
when(dnsZoneDao.findById(ZONE_ID)).thenReturn(zoneVO);
@@ -1151,7 +1221,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testHandleVmCreateEventFoundButNoActiveNics() throws
DnsProviderException {
- com.cloud.vm.VMInstanceVO instanceMock =
mock(com.cloud.vm.VMInstanceVO.class);
+ VMInstanceVO instanceMock = mock(VMInstanceVO.class);
when(vmInstanceDao.findById(30L)).thenReturn(instanceMock);
when(nicDnsJoinDao.listActiveByVmId(30L)).thenReturn(Collections.emptyList());
@@ -1163,8 +1233,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testHandleVmDestroyEventNicWithNullDnsUrlIsSkipped() throws
DnsProviderException {
- NicDnsJoinVO nicMock =
- mock(NicDnsJoinVO.class);
+ NicDnsJoinVO nicMock = mock(NicDnsJoinVO.class);
when(nicMock.getNicDnsName()).thenReturn(null);
when(nicDnsJoinDao.listIncludingRemovedByVmId(31L))
.thenReturn(Collections.singletonList(nicMock));
@@ -1176,8 +1245,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testHandleVmDestroyEventWithValidDnsUrlTriggersCleanup()
throws Exception {
- NicDnsJoinVO nicMock =
- mock(NicDnsJoinVO.class);
+ NicDnsJoinVO nicMock = mock(NicDnsJoinVO.class);
when(nicMock.getNicDnsName()).thenReturn("myvm.example.com");
when(nicMock.getDnsZoneId()).thenReturn(ZONE_ID);
when(nicDnsJoinDao.listIncludingRemovedByVmId(32L))
@@ -1188,12 +1256,12 @@ public class DnsProviderManagerImplTest {
when(nicDnsJoinDao.listActiveByVmIdZoneAndDnsRecord(eq(32L),
eq(ZONE_ID), anyString()))
.thenReturn(Collections.emptyList());
- try (MockedStatic<com.cloud.utils.db.Transaction> txMock =
- Mockito.mockStatic(com.cloud.utils.db.Transaction.class)) {
- txMock.when(() -> com.cloud.utils.db.Transaction.execute(
-
any(com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn.class)))
+ try (MockedStatic<Transaction> txMock =
+ Mockito.mockStatic(Transaction.class)) {
+ txMock.when(() -> Transaction.execute(
+ any(TransactionCallbackWithExceptionNoReturn.class)))
.thenAnswer(invocation -> {
-
com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn<?> cb =
+ TransactionCallbackWithExceptionNoReturn<?> cb =
invocation.getArgument(0);
try {
cb.doInTransactionWithoutResult(null);
@@ -1205,14 +1273,14 @@ public class DnsProviderManagerImplTest {
manager.handleVmDestroyEvent(32L);
- verify(nicDetailsDao).removeDetail(nicMock.getId(),
org.apache.cloudstack.api.ApiConstants.NIC_DNS_NAME);
+ verify(nicDetailsDao).removeDetail(nicMock.getId(),
ApiConstants.NIC_DNS_NAME);
verify(dnsProviderMock, times(2)).deleteRecord(eq(serverVO),
eq(zoneVO), any(DnsRecord.class));
}
}
@Test
public void testHandleNicPlugVmNotRunningExitsEarly() throws
DnsProviderException {
- com.cloud.vm.VMInstanceVO instanceMock =
mock(com.cloud.vm.VMInstanceVO.class);
+ VMInstanceVO instanceMock = mock(VMInstanceVO.class);
when(instanceMock.getState()).thenReturn(VirtualMachine.State.Destroyed);
when(vmInstanceDao.findById(33L)).thenReturn(instanceMock);
manager.handleNicPlug(33L, 500L);
@@ -1222,8 +1290,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testHandleNicUnplugNicHasValidDnsUrlTriggersSyncCleanup()
throws Exception {
- NicDnsJoinVO nicMock =
- mock(NicDnsJoinVO.class);
+ NicDnsJoinVO nicMock = mock(NicDnsJoinVO.class);
when(nicMock.getNicDnsName()).thenReturn("myvm.example.com");
when(nicMock.getDnsZoneId()).thenReturn(ZONE_ID);
when(nicDnsJoinDao.findByIdIncludingRemoved(600L)).thenReturn(nicMock);
@@ -1233,12 +1300,12 @@ public class DnsProviderManagerImplTest {
when(nicDnsJoinDao.listActiveByVmIdZoneAndDnsRecord(eq(34L),
eq(ZONE_ID), anyString()))
.thenReturn(Collections.emptyList());
- try (MockedStatic<com.cloud.utils.db.Transaction> txMock =
- Mockito.mockStatic(com.cloud.utils.db.Transaction.class)) {
- txMock.when(() -> com.cloud.utils.db.Transaction.execute(
-
any(com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn.class)))
+ try (MockedStatic<Transaction> txMock =
+ Mockito.mockStatic(Transaction.class)) {
+ txMock.when(() -> Transaction.execute(
+ any(TransactionCallbackWithExceptionNoReturn.class)))
.thenAnswer(invocation -> {
-
com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn<?> cb =
+ TransactionCallbackWithExceptionNoReturn<?> cb =
invocation.getArgument(0);
try {
cb.doInTransactionWithoutResult(null);
@@ -1250,14 +1317,14 @@ public class DnsProviderManagerImplTest {
manager.handleNicUnplug(34L, 600L);
- verify(nicDetailsDao).removeDetail(600L,
org.apache.cloudstack.api.ApiConstants.NIC_DNS_NAME);
+ verify(nicDetailsDao).removeDetail(600L,
ApiConstants.NIC_DNS_NAME);
verify(dnsProviderMock, times(2)).deleteRecord(eq(serverVO),
eq(zoneVO), any(DnsRecord.class));
}
}
@Test
public void testHandleVmHostnameChangedVmFoundButNoActiveNicsExitsEarly()
throws DnsProviderException {
- com.cloud.vm.VMInstanceVO instanceMock =
mock(com.cloud.vm.VMInstanceVO.class);
+ VMInstanceVO instanceMock = mock(VMInstanceVO.class);
when(vmInstanceDao.findById(35L)).thenReturn(instanceMock);
when(nicDnsJoinDao.listActiveByVmId(35L)).thenReturn(Collections.emptyList());
@@ -1269,14 +1336,13 @@ public class DnsProviderManagerImplTest {
@Test
public void testIsDnsCollisionReturnsTrueForDifferentInstance() {
- NicDnsJoinVO existing =
- mock(NicDnsJoinVO.class);
+ NicDnsJoinVO existing = mock(NicDnsJoinVO.class);
when(existing.getInstanceId()).thenReturn(99L);
when(nicDnsJoinDao.findActiveByDnsRecordAndZone(ZONE_ID,
"vm.example.com")).thenReturn(existing);
- try (MockedStatic<com.cloud.event.ActionEventUtils> aeMock =
- Mockito.mockStatic(com.cloud.event.ActionEventUtils.class)) {
- aeMock.when(() -> com.cloud.event.ActionEventUtils.onActionEvent(
+ try (MockedStatic<ActionEventUtils> aeMock =
+ Mockito.mockStatic(ActionEventUtils.class)) {
+ aeMock.when(() -> ActionEventUtils.onActionEvent(
anyLong(), anyLong(), anyLong(), anyString(), anyString(),
anyLong(), anyString()))
.thenReturn(1L);
boolean result = (boolean) ReflectionTestUtils.invokeMethod(
@@ -1306,8 +1372,8 @@ public class DnsProviderManagerImplTest {
@Test
public void testHandleNicPlugRunningVmNicFoundButZoneNullExitsGracefully()
throws DnsProviderException {
- com.cloud.vm.VMInstanceVO instanceMock =
mock(com.cloud.vm.VMInstanceVO.class);
-
when(instanceMock.getState()).thenReturn(com.cloud.vm.VirtualMachine.State.Running);
+ VMInstanceVO instanceMock = mock(VMInstanceVO.class);
+ when(instanceMock.getState()).thenReturn(VirtualMachine.State.Running);
when(vmInstanceDao.findById(40L)).thenReturn(instanceMock);
NicDnsJoinVO nicMock =
@@ -1325,7 +1391,7 @@ public class DnsProviderManagerImplTest {
@Test
public void
testHandleVmHostnameChangedNonEmptyNicsAllZonesMissingSkipsTransactions()
throws DnsProviderException {
- com.cloud.vm.VMInstanceVO instanceMock =
mock(com.cloud.vm.VMInstanceVO.class);
+ VMInstanceVO instanceMock = mock(VMInstanceVO.class);
when(vmInstanceDao.findById(41L)).thenReturn(instanceMock);
NicDnsJoinVO nicMock =
@@ -1342,7 +1408,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testHandleVmCreateEventNonEmptyNicsAllZonesMissingSkipsSync()
throws DnsProviderException {
- com.cloud.vm.VMInstanceVO instanceMock =
mock(com.cloud.vm.VMInstanceVO.class);
+ VMInstanceVO instanceMock = mock(VMInstanceVO.class);
when(vmInstanceDao.findById(42L)).thenReturn(instanceMock);
NicDnsJoinVO nicMock =
@@ -1369,11 +1435,10 @@ public class DnsProviderManagerImplTest {
public void testVmRenameSubscriberMissingInstanceIdSwallowsNpe() {
DnsProviderManagerImpl.VmRenameActionSubscriber subscriber =
manager.new VmRenameActionSubscriber();
- java.util.Map<String, Object> event = new java.util.HashMap<>();
- event.put(org.apache.cloudstack.api.ApiConstants.EVENT_TYPE,
- com.cloud.event.EventTypes.EVENT_VM_UPDATE);
- event.put(org.apache.cloudstack.api.ApiConstants.HOST_NAME, "newvm");
- event.put(org.apache.cloudstack.api.ApiConstants.OLD_HOST_NAME,
"oldvm");
+ Map<String, Object> event = new HashMap<>();
+ event.put(ApiConstants.EVENT_TYPE, EventTypes.EVENT_VM_UPDATE);
+ event.put(ApiConstants.HOST_NAME, "newvm");
+ event.put(ApiConstants.OLD_HOST_NAME, "oldvm");
// INSTANCE_ID intentionally absent → (long) null →
NullPointerException → caught internally
subscriber.onPublishMessage("sender", "topic", event);
verify(vmInstanceDao, never()).findById(anyLong());
@@ -1390,7 +1455,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testHandleVmCreateEventFullSyncNoCollision() throws Exception {
- com.cloud.vm.VMInstanceVO instanceMock =
mock(com.cloud.vm.VMInstanceVO.class);
+ VMInstanceVO instanceMock = mock(VMInstanceVO.class);
when(instanceMock.getHostName()).thenReturn("myvm");
when(vmInstanceDao.findById(51L)).thenReturn(instanceMock);
@@ -1408,12 +1473,12 @@ public class DnsProviderManagerImplTest {
when(nicDnsJoinDao.listActiveByVmIdZoneAndDnsRecord(eq(51L),
eq(ZONE_ID), anyString()))
.thenReturn(Collections.emptyList());
- try (MockedStatic<com.cloud.utils.db.Transaction> txMock =
- Mockito.mockStatic(com.cloud.utils.db.Transaction.class)) {
- txMock.when(() -> com.cloud.utils.db.Transaction.execute(
-
any(com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn.class)))
+ try (MockedStatic<Transaction> txMock =
+ Mockito.mockStatic(Transaction.class)) {
+ txMock.when(() -> Transaction.execute(
+ any(TransactionCallbackWithExceptionNoReturn.class)))
.thenAnswer(invocation -> {
-
com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn<?> cb =
+ TransactionCallbackWithExceptionNoReturn<?> cb =
invocation.getArgument(0);
try { cb.doInTransactionWithoutResult(null); }
catch (Exception e) { throw new RuntimeException(e); }
@@ -1423,14 +1488,14 @@ public class DnsProviderManagerImplTest {
manager.handleVmCreateEvent(51L);
verify(nicDetailsDao).addDetail(anyLong(),
- eq(org.apache.cloudstack.api.ApiConstants.NIC_DNS_NAME),
anyString(), eq(true));
+ eq(ApiConstants.NIC_DNS_NAME), anyString(), eq(true));
verify(dnsProviderMock, times(2)).deleteRecord(eq(serverVO),
eq(zoneVO), any(DnsRecord.class));
}
}
@Test
public void testHandleVmCreateEventCollisionSkipsAddDetail() throws
Exception {
- com.cloud.vm.VMInstanceVO instanceMock =
mock(com.cloud.vm.VMInstanceVO.class);
+ VMInstanceVO instanceMock = mock(VMInstanceVO.class);
when(instanceMock.getHostName()).thenReturn("myvm");
when(vmInstanceDao.findById(52L)).thenReturn(instanceMock);
@@ -1447,17 +1512,17 @@ public class DnsProviderManagerImplTest {
when(colliding.getInstanceId()).thenReturn(999L);
when(nicDnsJoinDao.findActiveByDnsRecordAndZone(eq(ZONE_ID),
anyString())).thenReturn(colliding);
- try (MockedStatic<com.cloud.utils.db.Transaction> txMock =
- Mockito.mockStatic(com.cloud.utils.db.Transaction.class);
- MockedStatic<com.cloud.event.ActionEventUtils> aeMock =
- Mockito.mockStatic(com.cloud.event.ActionEventUtils.class)) {
- aeMock.when(() -> com.cloud.event.ActionEventUtils.onActionEvent(
+ try (MockedStatic<Transaction> txMock =
+ Mockito.mockStatic(Transaction.class);
+ MockedStatic<ActionEventUtils> aeMock =
+ Mockito.mockStatic(ActionEventUtils.class)) {
+ aeMock.when(() -> ActionEventUtils.onActionEvent(
anyLong(), anyLong(), anyLong(), anyString(), anyString(),
anyLong(), anyString()))
.thenReturn(1L);
- txMock.when(() -> com.cloud.utils.db.Transaction.execute(
-
any(com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn.class)))
+ txMock.when(() -> Transaction.execute(
+ any(TransactionCallbackWithExceptionNoReturn.class)))
.thenAnswer(invocation -> {
-
com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn<?> cb =
+ TransactionCallbackWithExceptionNoReturn<?> cb =
invocation.getArgument(0);
try { cb.doInTransactionWithoutResult(null); }
catch (Exception e) { throw new RuntimeException(e); }
@@ -1482,7 +1547,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testHandleVmHostnameChangedFqdnUnchangedSkipsNic() throws
DnsProviderException {
- com.cloud.vm.VMInstanceVO instanceMock =
mock(com.cloud.vm.VMInstanceVO.class);
+ VMInstanceVO instanceMock = mock(VMInstanceVO.class);
when(vmInstanceDao.findById(61L)).thenReturn(instanceMock);
NicDnsJoinVO nicMock =
@@ -1503,7 +1568,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testHandleVmHostnameChangedFullRenamePath() throws Exception {
- com.cloud.vm.VMInstanceVO instanceMock =
mock(com.cloud.vm.VMInstanceVO.class);
+ VMInstanceVO instanceMock = mock(VMInstanceVO.class);
when(vmInstanceDao.findById(62L)).thenReturn(instanceMock);
NicDnsJoinVO nicMock =
@@ -1521,12 +1586,12 @@ public class DnsProviderManagerImplTest {
when(nicDnsJoinDao.listActiveByVmIdZoneAndDnsRecord(eq(62L),
eq(ZONE_ID), anyString()))
.thenReturn(Collections.emptyList());
- try (MockedStatic<com.cloud.utils.db.Transaction> txMock =
- Mockito.mockStatic(com.cloud.utils.db.Transaction.class)) {
- txMock.when(() -> com.cloud.utils.db.Transaction.execute(
-
any(com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn.class)))
+ try (MockedStatic<Transaction> txMock =
+ Mockito.mockStatic(Transaction.class)) {
+ txMock.when(() -> Transaction.execute(
+ any(TransactionCallbackWithExceptionNoReturn.class)))
.thenAnswer(invocation -> {
-
com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn<?> cb =
+ TransactionCallbackWithExceptionNoReturn<?> cb =
invocation.getArgument(0);
try { cb.doInTransactionWithoutResult(null); }
catch (Exception e) { throw new RuntimeException(e); }
@@ -1537,10 +1602,10 @@ public class DnsProviderManagerImplTest {
// Tx1: old URL removed from nic_details
verify(nicDetailsDao).removeDetail(anyLong(),
- eq(org.apache.cloudstack.api.ApiConstants.NIC_DNS_NAME));
+ eq(ApiConstants.NIC_DNS_NAME));
// Tx2: new URL written to nic_details
verify(nicDetailsDao).addDetail(anyLong(),
- eq(org.apache.cloudstack.api.ApiConstants.NIC_DNS_NAME),
anyString(), eq(true));
+ eq(ApiConstants.NIC_DNS_NAME), anyString(), eq(true));
// deleteRecord called for both old-sync (A+AAAA) and new-sync
(A+AAAA) = 4 total
verify(dnsProviderMock, times(4)).deleteRecord(eq(serverVO),
eq(zoneVO), any(DnsRecord.class));
}
@@ -1548,7 +1613,7 @@ public class DnsProviderManagerImplTest {
@Test
public void testHandleVmHostnameChangedCollisionOnNewUrlSkipsAddDetail() {
- com.cloud.vm.VMInstanceVO instanceMock =
mock(com.cloud.vm.VMInstanceVO.class);
+ VMInstanceVO instanceMock = mock(VMInstanceVO.class);
when(vmInstanceDao.findById(63L)).thenReturn(instanceMock);
NicDnsJoinVO nicMock =
@@ -1568,17 +1633,17 @@ public class DnsProviderManagerImplTest {
when(nicDnsJoinDao.listActiveByVmIdZoneAndDnsRecord(eq(63L),
eq(ZONE_ID), anyString()))
.thenReturn(Collections.emptyList());
- try (MockedStatic<com.cloud.utils.db.Transaction> txMock =
- Mockito.mockStatic(com.cloud.utils.db.Transaction.class);
- MockedStatic<com.cloud.event.ActionEventUtils> aeMock =
- Mockito.mockStatic(com.cloud.event.ActionEventUtils.class)) {
- aeMock.when(() -> com.cloud.event.ActionEventUtils.onActionEvent(
+ try (MockedStatic<Transaction> txMock =
+ Mockito.mockStatic(Transaction.class);
+ MockedStatic<ActionEventUtils> aeMock =
+ Mockito.mockStatic(ActionEventUtils.class)) {
+ aeMock.when(() -> ActionEventUtils.onActionEvent(
anyLong(), anyLong(), anyLong(), anyString(), anyString(),
anyLong(), anyString()))
.thenReturn(1L);
- txMock.when(() -> com.cloud.utils.db.Transaction.execute(
-
any(com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn.class)))
+ txMock.when(() -> Transaction.execute(
+ any(TransactionCallbackWithExceptionNoReturn.class)))
.thenAnswer(invocation -> {
-
com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn<?> cb =
+ TransactionCallbackWithExceptionNoReturn<?> cb =
invocation.getArgument(0);
try { cb.doInTransactionWithoutResult(null); }
catch (Exception e) { throw new RuntimeException(e); }