From a6ef24d1679812c223322b16767baf9faf269bd3 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 9 Oct 2025 13:06:28 +0530 Subject: [PATCH] server: consistent domainpath in api responses (#11589) * server: consistent domainpath in api responses Currently, some APIs return domainpath as 'ROOT/domain1/domain2' while other return it as '/domain1/domain2'. This PR makes the response consistent like "ROOT/domain1/domain2" Signed-off-by: Abhishek Kumar * more changes Signed-off-by: Abhishek Kumar --------- Signed-off-by: Abhishek Kumar --- .../api/command/user/vpn/AddVpnUserCmd.java | 18 +-- .../api/response/UserVmResponse.java | 2 +- .../cluster/KubernetesClusterManagerImpl.java | 15 +-- .../response/KubernetesClusterResponse.java | 2 +- .../java/com/cloud/api/ApiResponseHelper.java | 106 ++++++------------ .../api/query/dao/AccountJoinDaoImpl.java | 5 +- .../api/query/dao/AsyncJobJoinDaoImpl.java | 5 +- .../api/query/dao/DomainJoinDaoImpl.java | 5 +- .../query/dao/DomainRouterJoinDaoImpl.java | 4 - .../query/dao/ProjectAccountJoinDaoImpl.java | 3 +- .../dao/ProjectInvitationJoinDaoImpl.java | 3 +- .../api/query/dao/ResourceTagJoinDaoImpl.java | 4 - .../api/query/dao/TemplateJoinDaoImpl.java | 15 --- .../api/query/dao/UserVmJoinDaoImpl.java | 10 +- 14 files changed, 49 insertions(+), 148 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java index 59ba7e94b04..781edff52e3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.VpnUsersResponse; import org.apache.cloudstack.context.CallContext; -import com.cloud.domain.Domain; import com.cloud.event.EventTypes; import com.cloud.network.VpnUser; import com.cloud.user.Account; @@ -110,7 +109,6 @@ public class AddVpnUserCmd extends BaseAsyncCreateCmd { @Override public void execute() { VpnUser vpnUser = _entityMgr.findById(VpnUser.class, getEntityId()); - Account account = _entityMgr.findById(Account.class, vpnUser.getAccountId()); try { if (!_ravService.applyVpnUsers(vpnUser.getAccountId(), userName)) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add vpn user"); @@ -118,24 +116,10 @@ public class AddVpnUserCmd extends BaseAsyncCreateCmd { } catch (Exception ex) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } - - VpnUsersResponse vpnResponse = new VpnUsersResponse(); - vpnResponse.setId(vpnUser.getUuid()); - vpnResponse.setUserName(vpnUser.getUsername()); - vpnResponse.setAccountName(account.getAccountName()); // re-retrieve the vpnuser, as the call to `applyVpnUsers` might have changed the state vpnUser = _entityMgr.findById(VpnUser.class, getEntityId()); - vpnResponse.setState(vpnUser.getState().toString()); - - Domain domain = _entityMgr.findById(Domain.class, account.getDomainId()); - if (domain != null) { - vpnResponse.setDomainId(domain.getUuid()); - vpnResponse.setDomainName(domain.getName()); - vpnResponse.setDomainPath(domain.getPath()); - } - + VpnUsersResponse vpnResponse = _responseGenerator.createVpnUserResponse(vpnUser); vpnResponse.setResponseName(getCommandName()); - vpnResponse.setObjectName("vpnuser"); setResponseObject(vpnResponse); } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java index ca5bd09a9aa..29681b5e38f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java @@ -41,7 +41,7 @@ import com.google.gson.annotations.SerializedName; @SuppressWarnings("unused") @EntityReference(value = {VirtualMachine.class, UserVm.class, VirtualRouter.class}) -public class UserVmResponse extends BaseResponseWithTagInformation implements ControlledEntityResponse, SetResourceIconResponse { +public class UserVmResponse extends BaseResponseWithTagInformation implements ControlledViewEntityResponse, SetResourceIconResponse { @SerializedName(ApiConstants.ID) @Param(description = "the ID of the virtual machine") private String id; diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java index c46b0c00fa1..a12648c8e84 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java @@ -118,6 +118,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Level; import com.cloud.api.ApiDBUtils; +import com.cloud.api.ApiResponseHelper; import com.cloud.api.query.dao.NetworkOfferingJoinDao; import com.cloud.api.query.dao.TemplateJoinDao; import com.cloud.api.query.dao.UserVmJoinDao; @@ -135,7 +136,6 @@ import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DedicatedResourceDao; import com.cloud.deploy.DeployDestination; -import com.cloud.domain.Domain; import com.cloud.event.ActionEvent; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -814,18 +814,7 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne response.setKubernetesVersionId(version.getUuid()); response.setKubernetesVersionName(version.getName()); } - Account account = ApiDBUtils.findAccountById(kubernetesCluster.getAccountId()); - if (account.getType() == Account.Type.PROJECT) { - Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId()); - response.setProjectId(project.getUuid()); - response.setProjectName(project.getName()); - } else { - response.setAccountName(account.getAccountName()); - } - Domain domain = ApiDBUtils.findDomainById(kubernetesCluster.getDomainId()); - response.setDomainId(domain.getUuid()); - response.setDomainName(domain.getName()); - response.setDomainPath(domain.getPath()); + ApiResponseHelper.populateOwner(response, kubernetesCluster); response.setKeypair(kubernetesCluster.getKeyPair()); response.setState(kubernetesCluster.getState().toString()); response.setCores(String.valueOf(kubernetesCluster.getCores())); diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/response/KubernetesClusterResponse.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/response/KubernetesClusterResponse.java index b811f4f9dcb..b38fdcbc49e 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/response/KubernetesClusterResponse.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/response/KubernetesClusterResponse.java @@ -30,7 +30,7 @@ import com.google.gson.annotations.SerializedName; @SuppressWarnings("unused") @EntityReference(value = {KubernetesCluster.class}) -public class KubernetesClusterResponse extends BaseResponseWithAnnotations implements ControlledEntityResponse { +public class KubernetesClusterResponse extends BaseResponseWithAnnotations implements ControlledViewEntityResponse { @SerializedName(ApiConstants.ID) @Param(description = "the id of the Kubernetes cluster") private String id; diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index c44239b4447..cdb210c6dea 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -530,6 +530,15 @@ public class ApiResponseHelper implements ResponseGenerator { @Inject ResourceIconManager resourceIconManager; + public static String getPrettyDomainPath(String path) { + if (path == null) { + return null; + } + StringBuilder domainPath = new StringBuilder("ROOT"); + (domainPath.append(path)).deleteCharAt(domainPath.length() - 1); + return domainPath.toString(); + } + @Override public UserResponse createUserResponse(User user) { UserAccountJoinVO vUser = ApiDBUtils.newUserView(user); @@ -567,9 +576,7 @@ public class ApiResponseHelper implements ResponseGenerator { if (parentDomain != null) { domainResponse.setParentDomainId(parentDomain.getUuid()); } - StringBuilder domainPath = new StringBuilder("ROOT"); - (domainPath.append(domain.getPath())).deleteCharAt(domainPath.length() - 1); - domainResponse.setPath(domainPath.toString()); + domainResponse.setPath(getPrettyDomainPath(domain.getPath())); if (domain.getParent() != null) { domainResponse.setParentDomainName(ApiDBUtils.findDomainById(domain.getParent()).getName()); } @@ -822,21 +829,6 @@ public class ApiResponseHelper implements ResponseGenerator { } } populateOwner(vmSnapshotResponse, vmSnapshot); - Project project = ApiDBUtils.findProjectByProjectAccountId(vmSnapshot.getAccountId()); - if (project != null) { - vmSnapshotResponse.setProjectId(project.getUuid()); - vmSnapshotResponse.setProjectName(project.getName()); - } - Account account = ApiDBUtils.findAccountById(vmSnapshot.getAccountId()); - if (account != null) { - vmSnapshotResponse.setAccountName(account.getAccountName()); - } - DomainVO domain = ApiDBUtils.findDomainById(vmSnapshot.getDomainId()); - if (domain != null) { - vmSnapshotResponse.setDomainId(domain.getUuid()); - vmSnapshotResponse.setDomainName(domain.getName()); - vmSnapshotResponse.setDomainPath(domain.getPath()); - } List tags = _resourceTagDao.listBy(vmSnapshot.getId(), ResourceObjectType.VMSnapshot); List tagResponses = new ArrayList(); @@ -2350,18 +2342,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setName(securityGroup.getName()); response.setDescription(securityGroup.getDescription()); - Account account = securiytGroupAccounts.get(securityGroup.getAccountId()); - - if (securityGroup.getAccountType() == Account.Type.PROJECT) { - response.setProjectId(securityGroup.getProjectUuid()); - response.setProjectName(securityGroup.getProjectName()); - } else { - response.setAccountName(securityGroup.getAccountName()); - } - - response.setDomainId(securityGroup.getDomainUuid()); - response.setDomainName(securityGroup.getDomainName()); - response.setDomainPath(securityGroup.getDomainPath()); + populateOwner(response, securityGroup); for (SecurityRule securityRule : securityRules) { SecurityGroupRuleResponse securityGroupData = new SecurityGroupRuleResponse(); @@ -2758,32 +2739,18 @@ public class ApiResponseHelper implements ResponseGenerator { // get domain from network_domain table Pair domainNetworkDetails = ApiDBUtils.getDomainNetworkDetails(network.getId()); if (domainNetworkDetails.first() != null) { - Domain domain = ApiDBUtils.findDomainById(domainNetworkDetails.first()); - if (domain != null) { - response.setDomainId(domain.getUuid()); - - StringBuilder domainPath = new StringBuilder("ROOT"); - (domainPath.append(domain.getPath())).deleteCharAt(domainPath.length() - 1); - response.setDomainPath(domainPath.toString()); - } + populateDomain(response, domainNetworkDetails.first()); } response.setSubdomainAccess(domainNetworkDetails.second()); } Long dedicatedDomainId = ApiDBUtils.getDedicatedNetworkDomain(network.getId()); if (dedicatedDomainId != null) { - Domain domain = ApiDBUtils.findDomainById(dedicatedDomainId); - if (domain != null) { - response.setDomainId(domain.getUuid()); - response.setDomainName(domain.getName()); - response.setDomainPath(domain.getPath()); - } - + populateDomain(response, dedicatedDomainId); } response.setSpecifyIpRanges(network.getSpecifyIpRanges()); - setVpcIdInResponse(network.getVpcId(), response::setVpcId, response::setVpcName); setResponseAssociatedNetworkInformation(response, network.getId()); @@ -3045,14 +3012,10 @@ public class ApiResponseHelper implements ResponseGenerator { } else { response.setAccountName(account.getAccountName()); } - - Domain domain = ApiDBUtils.findDomainById(object.getDomainId()); - response.setDomainId(domain.getUuid()); - response.setDomainName(domain.getName()); - response.setDomainPath(domain.getPath()); + populateDomain(response, object.getDomainId()); } - private void populateOwner(ControlledViewEntityResponse response, ControlledEntity object) { + public static void populateOwner(ControlledViewEntityResponse response, ControlledEntity object) { Account account = ApiDBUtils.findAccountById(object.getAccountId()); if (account.getType() == Account.Type.PROJECT) { @@ -3064,10 +3027,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setAccountName(account.getAccountName()); } - Domain domain = ApiDBUtils.findDomainById(object.getDomainId()); - response.setDomainId(domain.getUuid()); - response.setDomainName(domain.getName()); - response.setDomainPath(domain.getPath()); + populateDomain(response, object.getDomainId()); } public static void populateOwner(ControlledViewEntityResponse response, ControlledViewEntity object) { @@ -3081,7 +3041,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setDomainId(object.getDomainUuid()); response.setDomainName(object.getDomainName()); - response.setDomainPath(object.getDomainPath()); + response.setDomainPath(getPrettyDomainPath(object.getDomainPath())); } private void populateAccount(ControlledEntityResponse response, long accountId) { @@ -3105,10 +3065,22 @@ public class ApiResponseHelper implements ResponseGenerator { private void populateDomain(ControlledEntityResponse response, long domainId) { Domain domain = ApiDBUtils.findDomainById(domainId); - + if (domain == null) { + return; + } response.setDomainId(domain.getUuid()); response.setDomainName(domain.getName()); - response.setDomainPath(domain.getPath()); + response.setDomainPath(getPrettyDomainPath(domain.getPath())); + } + + private static void populateDomain(ControlledViewEntityResponse response, long domainId) { + Domain domain = ApiDBUtils.findDomainById(domainId); + if (domain == null) { + return; + } + response.setDomainId(domain.getUuid()); + response.setDomainName(domain.getName()); + response.setDomainPath(getPrettyDomainPath(domain.getPath())); } @Override @@ -4100,12 +4072,7 @@ public class ApiResponseHelper implements ResponseGenerator { usageRecResponse.setAccountName(account.getAccountName()); } - Domain domain = ApiDBUtils.findDomainById(usageRecord.getDomainId()); - if (domain != null) { - usageRecResponse.setDomainId(domain.getUuid()); - usageRecResponse.setDomainName(domain.getName()); - usageRecResponse.setDomainPath(domain.getPath()); - } + populateDomain(usageRecResponse, account.getDomainId()); if (usageRecord.getZoneId() != null) { DataCenter zone = ApiDBUtils.findZoneById(usageRecord.getZoneId()); @@ -4892,18 +4859,11 @@ public class ApiResponseHelper implements ResponseGenerator { AffinityGroupResponse response = new AffinityGroupResponse(); - Account account = ApiDBUtils.findAccountById(group.getAccountId()); response.setId(group.getUuid()); - response.setAccountName(account.getAccountName()); response.setName(group.getName()); response.setType(group.getType()); response.setDescription(group.getDescription()); - Domain domain = ApiDBUtils.findDomainById(account.getDomainId()); - if (domain != null) { - response.setDomainId(domain.getUuid()); - response.setDomainName(domain.getName()); - response.setDomainPath(domain.getPath()); - } + populateOwner(response, group); response.setObjectName("affinitygroup"); return response; diff --git a/server/src/main/java/com/cloud/api/query/dao/AccountJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/AccountJoinDaoImpl.java index 9a301d440a9..de66b80ca55 100644 --- a/server/src/main/java/com/cloud/api/query/dao/AccountJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/AccountJoinDaoImpl.java @@ -32,6 +32,7 @@ import org.apache.cloudstack.api.response.ResourceLimitAndCountResponse; import org.apache.cloudstack.api.response.UserResponse; import com.cloud.api.ApiDBUtils; +import com.cloud.api.ApiResponseHelper; import com.cloud.api.query.ViewResponseHelper; import com.cloud.api.query.vo.AccountJoinVO; import com.cloud.api.query.vo.UserAccountJoinVO; @@ -74,9 +75,7 @@ public class AccountJoinDaoImpl extends GenericDaoBase impl accountResponse.setAccountType(account.getType().ordinal()); accountResponse.setDomainId(account.getDomainUuid()); accountResponse.setDomainName(account.getDomainName()); - StringBuilder domainPath = new StringBuilder("ROOT"); - (domainPath.append(account.getDomainPath())).deleteCharAt(domainPath.length() - 1); - accountResponse.setDomainPath(domainPath.toString()); + accountResponse.setDomainPath(ApiResponseHelper.getPrettyDomainPath(account.getDomainPath())); accountResponse.setState(account.getState().toString()); accountResponse.setCreated(account.getCreated()); accountResponse.setNetworkDomain(account.getNetworkDomain()); diff --git a/server/src/main/java/com/cloud/api/query/dao/AsyncJobJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/AsyncJobJoinDaoImpl.java index 08b896edb17..10ef67bbbea 100644 --- a/server/src/main/java/com/cloud/api/query/dao/AsyncJobJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/AsyncJobJoinDaoImpl.java @@ -28,6 +28,7 @@ import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.response.AsyncJobResponse; import org.apache.cloudstack.framework.jobs.AsyncJob; +import com.cloud.api.ApiResponseHelper; import com.cloud.api.ApiSerializerHelper; import com.cloud.api.SerializationContext; import com.cloud.api.query.vo.AsyncJobJoinVO; @@ -60,9 +61,7 @@ public class AsyncJobJoinDaoImpl extends GenericDaoBase im jobResponse.setAccountId(job.getAccountUuid()); jobResponse.setAccount(job.getAccountName()); jobResponse.setDomainId(job.getDomainUuid()); - StringBuilder domainPath = new StringBuilder("ROOT"); - (domainPath.append(job.getDomainPath())).deleteCharAt(domainPath.length() - 1); - jobResponse.setDomainPath(domainPath.toString()); + jobResponse.setDomainPath(ApiResponseHelper.getPrettyDomainPath(job.getDomainPath())); jobResponse.setUserId(job.getUserUuid()); jobResponse.setCmd(job.getCmd()); jobResponse.setCreated(job.getCreated()); diff --git a/server/src/main/java/com/cloud/api/query/dao/DomainJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/DomainJoinDaoImpl.java index 4a0929744cf..d4865c5550e 100644 --- a/server/src/main/java/com/cloud/api/query/dao/DomainJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/DomainJoinDaoImpl.java @@ -21,6 +21,7 @@ import java.util.EnumSet; import java.util.List; +import com.cloud.api.ApiResponseHelper; import com.cloud.configuration.Resource; import com.cloud.user.AccountManager; import org.apache.cloudstack.annotation.AnnotationService; @@ -79,9 +80,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase implem if (domain.getParentUuid() != null) { domainResponse.setParentDomainId(domain.getParentUuid()); } - StringBuilder domainPath = new StringBuilder("ROOT"); - (domainPath.append(domain.getPath())).deleteCharAt(domainPath.length() - 1); - domainResponse.setPath(domainPath.toString()); + domainResponse.setPath(ApiResponseHelper.getPrettyDomainPath(domain.getPath())); if (domain.getParent() != null) { domainResponse.setParentDomainName(domain.getParentName()); } diff --git a/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java index e7e2295923a..2c6c6481661 100644 --- a/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java @@ -207,10 +207,6 @@ public class DomainRouterJoinDaoImpl extends GenericDaoBase details = new HashMap<>(); @@ -504,11 +494,6 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation