mirror of https://github.com/apache/cloudstack.git
Support list/query async jobs by resource (#12983)
* Add resource filtering to async job query commands * Fix logical condition in AsyncJobDaoImpl and ResourceIdSupport * resource type case-insensitive validation * fix resource type and id search --------- Co-authored-by: mprokopchuk <mprokopchuk@gmail.com> Co-authored-by: mprokopchuk <mprokopchuk@apple.com>
This commit is contained in:
parent
7c7b2ae75d
commit
47c5bb8ee7
|
|
@ -127,8 +127,8 @@ public enum ApiCommandResourceType {
|
|||
}
|
||||
|
||||
public static ApiCommandResourceType fromString(String value) {
|
||||
if (StringUtils.isNotEmpty(value) && EnumUtils.isValidEnum(ApiCommandResourceType.class, value)) {
|
||||
return valueOf(value);
|
||||
if (StringUtils.isNotBlank(value) && EnumUtils.isValidEnumIgnoreCase(ApiCommandResourceType.class, value)) {
|
||||
return EnumUtils.getEnumIgnoreCase(ApiCommandResourceType.class, value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.apache.cloudstack.api.command.user.job;
|
|||
import java.util.Date;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiArgValidator;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseListAccountResourcesCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
|
|
@ -40,6 +41,12 @@ public class ListAsyncJobsCmd extends BaseListAccountResourcesCmd {
|
|||
@Parameter(name = ApiConstants.MANAGEMENT_SERVER_ID, type = CommandType.UUID, entityType = ManagementServerResponse.class, description = "The id of the management server", since="4.19")
|
||||
private Long managementServerId;
|
||||
|
||||
@Parameter(name = ApiConstants.RESOURCE_ID, validations = {ApiArgValidator.UuidString}, type = CommandType.STRING, description = "the ID of the resource associated with the job", since="4.22.1")
|
||||
private String resourceId;
|
||||
|
||||
@Parameter(name = ApiConstants.RESOURCE_TYPE, type = CommandType.STRING, description = "the type of the resource associated with the job", since="4.22.1")
|
||||
private String resourceType;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -52,6 +59,14 @@ public class ListAsyncJobsCmd extends BaseListAccountResourcesCmd {
|
|||
return managementServerId;
|
||||
}
|
||||
|
||||
public String getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return resourceType;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command.user.job;
|
||||
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiArgValidator;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
|
|
@ -34,9 +34,15 @@ public class QueryAsyncJobResultCmd extends BaseCmd {
|
|||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name = ApiConstants.JOB_ID, type = CommandType.UUID, entityType = AsyncJobResponse.class, required = true, description = "The ID of the asynchronous job")
|
||||
@Parameter(name = ApiConstants.JOB_ID, type = CommandType.UUID, entityType = AsyncJobResponse.class, description = "The ID of the asynchronous job")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.RESOURCE_ID, validations = {ApiArgValidator.UuidString}, type = CommandType.STRING, description = "the ID of the resource associated with the job", since="4.22.1")
|
||||
private String resourceId;
|
||||
|
||||
@Parameter(name = ApiConstants.RESOURCE_TYPE, type = CommandType.STRING, description = "the type of the resource associated with the job", since="4.22.1")
|
||||
private String resourceType;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -45,6 +51,14 @@ public class QueryAsyncJobResultCmd extends BaseCmd {
|
|||
return id;
|
||||
}
|
||||
|
||||
public String getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return resourceType;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -23,12 +23,30 @@ import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
|
|||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface AsyncJobDao extends GenericDao<AsyncJobVO, Long> {
|
||||
|
||||
AsyncJobVO findInstancePendingAsyncJob(String instanceType, long instanceId);
|
||||
|
||||
List<AsyncJobVO> findInstancePendingAsyncJobs(String instanceType, Long accountId);
|
||||
|
||||
/**
|
||||
* Finds async job matching the given parameters.
|
||||
* Non-null parameters are added to search criteria.
|
||||
* Returns the most recent job by creation date.
|
||||
* <p>
|
||||
* When searching by resourceId and resourceType, only one active job
|
||||
* is expected per resource, so returning a single result is sufficient.
|
||||
*
|
||||
* @param id job ID
|
||||
* @param resourceId resource ID (instanceId)
|
||||
* @param resourceType resource type (instanceType)
|
||||
* @return matching job or null
|
||||
*/
|
||||
@Nullable
|
||||
AsyncJobVO findJob(Long id, Long resourceId, String resourceType);
|
||||
|
||||
AsyncJobVO findPseudoJob(long threadId, long msid);
|
||||
|
||||
void cleanupPseduoJobs(long msid);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
|
||||
import org.apache.cloudstack.jobs.JobInfo;
|
||||
|
|
@ -45,6 +47,7 @@ public class AsyncJobDaoImpl extends GenericDaoBase<AsyncJobVO, Long> implements
|
|||
private final SearchBuilder<AsyncJobVO> expiringUnfinishedAsyncJobSearch;
|
||||
private final SearchBuilder<AsyncJobVO> expiringCompletedAsyncJobSearch;
|
||||
private final SearchBuilder<AsyncJobVO> failureMsidAsyncJobSearch;
|
||||
private final SearchBuilder<AsyncJobVO> byIdResourceIdResourceTypeSearch;
|
||||
private final GenericSearchBuilder<AsyncJobVO, Long> asyncJobTypeSearch;
|
||||
private final GenericSearchBuilder<AsyncJobVO, Long> pendingNonPseudoAsyncJobsSearch;
|
||||
|
||||
|
|
@ -95,6 +98,12 @@ public class AsyncJobDaoImpl extends GenericDaoBase<AsyncJobVO, Long> implements
|
|||
failureMsidAsyncJobSearch.and("job_cmd", failureMsidAsyncJobSearch.entity().getCmd(), Op.IN);
|
||||
failureMsidAsyncJobSearch.done();
|
||||
|
||||
byIdResourceIdResourceTypeSearch = createSearchBuilder();
|
||||
byIdResourceIdResourceTypeSearch.and("id", byIdResourceIdResourceTypeSearch.entity().getId(), SearchCriteria.Op.EQ);
|
||||
byIdResourceIdResourceTypeSearch.and("instanceId", byIdResourceIdResourceTypeSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
byIdResourceIdResourceTypeSearch.and("instanceType", byIdResourceIdResourceTypeSearch.entity().getInstanceType(), SearchCriteria.Op.EQ);
|
||||
byIdResourceIdResourceTypeSearch.done();
|
||||
|
||||
asyncJobTypeSearch = createSearchBuilder(Long.class);
|
||||
asyncJobTypeSearch.select(null, SearchCriteria.Func.COUNT, asyncJobTypeSearch.entity().getId());
|
||||
asyncJobTypeSearch.and("job_info", asyncJobTypeSearch.entity().getCmdInfo(),Op.LIKE);
|
||||
|
|
@ -140,6 +149,30 @@ public class AsyncJobDaoImpl extends GenericDaoBase<AsyncJobVO, Long> implements
|
|||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncJobVO findJob(Long id, Long resourceId, String resourceType) {
|
||||
SearchCriteria<AsyncJobVO> sc = byIdResourceIdResourceTypeSearch.create();
|
||||
|
||||
if (id == null && resourceId == null && StringUtils.isBlank(resourceType)) {
|
||||
logger.debug("findJob called with all null parameters");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (id != null) {
|
||||
sc.setParameters("id", id);
|
||||
}
|
||||
if (resourceId != null && StringUtils.isNotBlank(resourceType)) {
|
||||
sc.setParameters("instanceType", resourceType);
|
||||
sc.setParameters("instanceId", resourceId);
|
||||
}
|
||||
Filter filter = new Filter(AsyncJobVO.class, "created", false, 0L, 1L);
|
||||
List<AsyncJobVO> result = searchIncludingRemoved(sc, filter, Boolean.FALSE, false);
|
||||
if (CollectionUtils.isNotEmpty(result)) {
|
||||
return result.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncJobVO findPseudoJob(long threadId, long msid) {
|
||||
SearchCriteria<AsyncJobVO> sc = pseudoJobSearch.create();
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import java.util.LinkedHashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.function.Consumer;
|
||||
|
|
@ -39,6 +40,7 @@ import java.util.stream.Collectors;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.api.query.ResourceIdSupport;
|
||||
import com.cloud.bgp.ASNumber;
|
||||
import com.cloud.bgp.ASNumberRange;
|
||||
import com.cloud.configuration.ConfigurationService;
|
||||
|
|
@ -57,6 +59,7 @@ import org.apache.cloudstack.affinity.AffinityGroup;
|
|||
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||
import org.apache.cloudstack.annotation.AnnotationService;
|
||||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiConstants.DomainDetails;
|
||||
import org.apache.cloudstack.api.ApiConstants.HostDetails;
|
||||
|
|
@ -219,6 +222,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.framework.jobs.AsyncJob;
|
||||
import org.apache.cloudstack.framework.jobs.AsyncJobManager;
|
||||
import org.apache.cloudstack.framework.jobs.dao.AsyncJobDao;
|
||||
import org.apache.cloudstack.gui.theme.GuiThemeJoin;
|
||||
import org.apache.cloudstack.management.ManagementServerHost;
|
||||
import org.apache.cloudstack.network.BgpPeerVO;
|
||||
|
|
@ -447,7 +451,7 @@ import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
|||
|
||||
import sun.security.x509.X509CertImpl;
|
||||
|
||||
public class ApiResponseHelper implements ResponseGenerator {
|
||||
public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport {
|
||||
|
||||
protected Logger logger = LogManager.getLogger(ApiResponseHelper.class);
|
||||
private static final DecimalFormat s_percentFormat = new DecimalFormat("##.##");
|
||||
|
|
@ -529,6 +533,8 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
RoutedIpv4Manager routedIpv4Manager;
|
||||
@Inject
|
||||
ResourceIconManager resourceIconManager;
|
||||
@Inject
|
||||
AsyncJobDao asyncJobDao;
|
||||
|
||||
public static String getPrettyDomainPath(String path) {
|
||||
if (path == null) {
|
||||
|
|
@ -2304,16 +2310,26 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
|
||||
@Override
|
||||
public AsyncJobResponse queryJobResult(final QueryAsyncJobResultCmd cmd) {
|
||||
final Account caller = CallContext.current().getCallingAccount();
|
||||
ApiCommandResourceType resourceType = getResourceType(cmd.getResourceType());
|
||||
String resourceTypeName = Optional.ofNullable(resourceType).map(ApiCommandResourceType::name).orElse(null);
|
||||
|
||||
final AsyncJob job = _entityMgr.findByIdIncludingRemoved(AsyncJob.class, cmd.getId());
|
||||
if (job == null) {
|
||||
throw new InvalidParameterValueException("Unable to find a job by id " + cmd.getId());
|
||||
Long resourceId = getResourceId(resourceType, cmd.getResourceId());
|
||||
Long jobId = cmd.getId();
|
||||
if (jobId == null && resourceId == null) {
|
||||
throw new InvalidParameterValueException("Expected parameter job id or parameters resource type and resource id");
|
||||
}
|
||||
|
||||
final AsyncJob job = asyncJobDao.findJob(jobId, resourceId, resourceTypeName);
|
||||
if (job == null) {
|
||||
throw new InvalidParameterValueException("Unable to find a job by id " + jobId + " resource type "
|
||||
+ cmd.getResourceType() + " resource id " + cmd.getResourceId());
|
||||
}
|
||||
jobId = job.getId();
|
||||
|
||||
final User userJobOwner = _accountMgr.getUserIncludingRemoved(job.getUserId());
|
||||
final Account jobOwner = _accountMgr.getAccount(userJobOwner.getAccountId());
|
||||
|
||||
final Account caller = CallContext.current().getCallingAccount();
|
||||
//check permissions
|
||||
if (_accountMgr.isNormalUser(caller.getId())) {
|
||||
//regular users can see only jobs they own
|
||||
|
|
@ -2324,7 +2340,7 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
_accountMgr.checkAccess(caller, null, true, jobOwner);
|
||||
}
|
||||
|
||||
return createAsyncJobResponse(_jobMgr.queryJob(cmd.getId(), true));
|
||||
return createAsyncJobResponse(_jobMgr.queryJob(jobId, true));
|
||||
}
|
||||
|
||||
public AsyncJobResponse createAsyncJobResponse(AsyncJob job) {
|
||||
|
|
@ -5704,4 +5720,14 @@ protected Map<String, ResourceIcon> getResourceIconsUsingOsCategory(List<Templat
|
|||
consoleSessionResponse.setObjectName("consolesession");
|
||||
return consoleSessionResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityManager getEntityManager() {
|
||||
return _entityMgr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountManager getAccountManager() {
|
||||
return _accountMgr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ import java.util.ListIterator;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
|
@ -370,7 +369,7 @@ import com.cloud.vm.dao.VMInstanceDao;
|
|||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
|
||||
@Component
|
||||
public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements QueryService, Configurable {
|
||||
public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements QueryService, Configurable, ResourceIdSupport {
|
||||
|
||||
|
||||
private static final String ID_FIELD = "id";
|
||||
|
|
@ -869,26 +868,14 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||
Integer entryTime = cmd.getEntryTime();
|
||||
Integer duration = cmd.getDuration();
|
||||
Long startId = cmd.getStartId();
|
||||
final String resourceUuid = cmd.getResourceId();
|
||||
final String resourceTypeStr = cmd.getResourceType();
|
||||
final String resourceUuid = getResourceUuid(cmd.getResourceId());
|
||||
final ApiCommandResourceType resourceType = getResourceType(cmd.getResourceType());
|
||||
final String stateStr = cmd.getState();
|
||||
ApiCommandResourceType resourceType = null;
|
||||
Long resourceId = null;
|
||||
if (resourceTypeStr != null) {
|
||||
resourceType = ApiCommandResourceType.fromString(resourceTypeStr);
|
||||
if (resourceType == null) {
|
||||
throw new InvalidParameterValueException(String.format("Invalid %s", ApiConstants.RESOURCE_TYPE));
|
||||
}
|
||||
}
|
||||
if (resourceUuid != null) {
|
||||
if (resourceTypeStr == null) {
|
||||
if (resourceType == null) {
|
||||
throw new InvalidParameterValueException(String.format("%s parameter must be used with %s parameter", ApiConstants.RESOURCE_ID, ApiConstants.RESOURCE_TYPE));
|
||||
}
|
||||
try {
|
||||
UUID.fromString(resourceUuid);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new InvalidParameterValueException(String.format("Invalid %s", ApiConstants.RESOURCE_ID));
|
||||
}
|
||||
Object object = entityManager.findByUuidIncludingRemoved(resourceType.getAssociatedClass(), resourceUuid);
|
||||
if (object instanceof InternalIdentity) {
|
||||
resourceId = ((InternalIdentity)object).getId();
|
||||
|
|
@ -3205,6 +3192,20 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||
sc.setParameters("executingMsid", msHost.getMsid());
|
||||
}
|
||||
|
||||
if (cmd.getResourceType() != null) {
|
||||
ApiCommandResourceType resourceType = getResourceType(cmd.getResourceType());
|
||||
sc.addAnd("instanceType", SearchCriteria.Op.EQ, resourceType.toString());
|
||||
|
||||
final String resourceId = getResourceUuid(cmd.getResourceId());
|
||||
if (resourceId == null) {
|
||||
throw new InvalidParameterValueException("Invalid resource id for the resource type " + resourceType);
|
||||
}
|
||||
|
||||
sc.addAnd("instanceUuid", SearchCriteria.Op.EQ, resourceId);
|
||||
} else if (cmd.getResourceId() != null) {
|
||||
throw new InvalidParameterValueException("Resource type must be specified for the resource id");
|
||||
}
|
||||
|
||||
return _jobJoinDao.searchAndCount(sc, searchFilter);
|
||||
}
|
||||
|
||||
|
|
@ -6288,4 +6289,14 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||
return new ConfigKey<?>[] {AllowUserViewDestroyedVM, UserVMDeniedDetails, UserVMReadOnlyDetails, SortKeyAscending,
|
||||
AllowUserViewAllDomainAccounts, AllowUserViewAllDataCenters, SharePublicTemplatesWithOtherDomains, ReturnVmStatsOnVmList};
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityManager getEntityManager() {
|
||||
return entityManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountManager getAccountManager() {
|
||||
return accountMgr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.api.query;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.utils.db.EntityManager;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import static org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
|
||||
/**
|
||||
* Support interface for converting resource UUIDs to internal IDs
|
||||
* with validation and access control.
|
||||
*
|
||||
* @author mprokopchuk
|
||||
*/
|
||||
public interface ResourceIdSupport {
|
||||
|
||||
EntityManager getEntityManager();
|
||||
|
||||
AccountManager getAccountManager();
|
||||
|
||||
/**
|
||||
* Converts resource UUID to internal database ID with access control checks.
|
||||
*
|
||||
* @param resourceType type of the resource
|
||||
* @param resourceUuid UUID of the resource
|
||||
* @return internal resource ID or null if parameters are null
|
||||
* @throws InvalidParameterValueException if only one parameter provided or resource not found
|
||||
*/
|
||||
default Long getResourceId(ApiCommandResourceType resourceType, String resourceUuid) {
|
||||
String uuid = getResourceUuid(resourceUuid);
|
||||
|
||||
if (resourceType == null && uuid == null) {
|
||||
return null;
|
||||
} else if ((resourceType == null) ^ (uuid == null)) {
|
||||
throw new InvalidParameterValueException(String.format("Both %s and %s required",
|
||||
ApiConstants.RESOURCE_ID, ApiConstants.RESOURCE_TYPE));
|
||||
}
|
||||
|
||||
Object object = getEntityManager().findByUuidIncludingRemoved(resourceType.getAssociatedClass(), resourceUuid);
|
||||
if (!(object instanceof InternalIdentity)) {
|
||||
throw new InvalidParameterValueException(String.format("Invalid %s", ApiConstants.RESOURCE_ID));
|
||||
}
|
||||
Long resourceId = ((InternalIdentity) object).getId();
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
boolean isRootAdmin = getAccountManager().isRootAdmin(caller.getId());
|
||||
|
||||
if (!isRootAdmin && object instanceof ControlledEntity) {
|
||||
ControlledEntity entity = (ControlledEntity) object;
|
||||
boolean sameOwner = entity.getAccountId() == caller.getId();
|
||||
getAccountManager().checkAccess(caller, AccessType.ListEntry, sameOwner, entity);
|
||||
}
|
||||
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and validates resource type string.
|
||||
*
|
||||
* @param resourceType resource type as string
|
||||
* @return parsed resource type or null if not provided
|
||||
* @throws InvalidParameterValueException if provided type is invalid
|
||||
*/
|
||||
default ApiCommandResourceType getResourceType(String resourceType) {
|
||||
Optional<String> resourceTypeOpt = Optional.ofNullable(resourceType).filter(StringUtils::isNotBlank);
|
||||
// return null if resource type was not provided
|
||||
if (resourceTypeOpt.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
// return value or throw exception if provided resource type is invalid
|
||||
return resourceTypeOpt
|
||||
.map(ApiCommandResourceType::fromString)
|
||||
.orElseThrow(() -> new InvalidParameterValueException(String.format("Invalid %s",
|
||||
ApiConstants.RESOURCE_TYPE)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates resource UUID format.
|
||||
*
|
||||
* @param resourceUuid UUID string to validate
|
||||
* @return validated UUID or null if not provided
|
||||
* @throws InvalidParameterValueException if UUID format is invalid
|
||||
*/
|
||||
default String getResourceUuid(String resourceUuid) {
|
||||
if (StringUtils.isBlank(resourceUuid)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
UUID.fromString(resourceUuid);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new InvalidParameterValueException(String.format("Invalid %s", ApiConstants.RESOURCE_ID));
|
||||
}
|
||||
|
||||
return resourceUuid;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -272,7 +272,7 @@ public class QueryManagerImplTest {
|
|||
public void searchForEventsFailResourceIdInvalid() {
|
||||
ListEventsCmd cmd = setupMockListEventsCmd();
|
||||
Mockito.when(cmd.getResourceId()).thenReturn("random");
|
||||
Mockito.when(cmd.getResourceType()).thenReturn(ApiCommandResourceType.VirtualMachine.toString());
|
||||
Mockito.lenient().when(cmd.getResourceType()).thenReturn(ApiCommandResourceType.VirtualMachine.toString());
|
||||
queryManager.searchForEvents(cmd);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue