List<BundleDeployment> liveDeployments = bundleManager.findBundleDeploymentsByCriteria(subject, bdc);
if (1 != liveDeployments.size()) {
throw new IllegalArgumentException("No live deployment to purge is found for destinationId ["
+ bundleDestinationId + "]");
}
BundleDeployment liveDeployment = liveDeployments.get(0);
List<BundleResourceDeployment> resourceDeploys = liveDeployment.getResourceDeployments();
if (resourceDeploys == null || resourceDeploys.isEmpty()) {
return; // nothing to do
}
// Although they likely will, the actual resource deployments may no longer match the members of the destination's
// resource group (if group membership has changed). We still use the group for authz because that is the more
// intuitive, manageable way to do this. Otherwise the subject would need view perms on each of the previously
// deployed-to resources, and that may be tricky to provide.
checkDeployBundleAuthz(subject, liveDeployment.getBundleVersion().getBundle().getId(), liveDeployment
.getDestination().getGroup().getId());
// we need to obtain the bundle type (the remote plugin container needs it). our first criteria can't fetch this deep, we have to do another query.
BundleVersionCriteria bvc = new BundleVersionCriteria();
bvc.addFilterId(liveDeployment.getBundleVersion().getId());
bvc.fetchBundle(true); // will eagerly fetch the bundle type
PageList<BundleVersion> bvs = bundleManager.findBundleVersionsByCriteria(subject, bvc);
liveDeployment.setBundleVersion(bvs.get(0)); // wire up the full bundle version back into the live deployment
// the bundle type doesn't eagerly load the resource type - the remote plugin container needs that too
ResourceTypeCriteria rtc = new ResourceTypeCriteria();
rtc.addFilterIgnored(null); // we are purging, so we don't care if this returns ignored types or not, just purge anyway
rtc.addFilterBundleTypeId(liveDeployment.getBundleVersion().getBundle().getBundleType().getId());
PageList<ResourceType> rts = resourceTypeManager.findResourceTypesByCriteria(subject, rtc);
liveDeployment.getBundleVersion().getBundle().getBundleType().setResourceType(rts.get(0));
// we need to obtain the resources for all resource deployments - our first criteria can't fetch this deep, we have to do another query.
List<Integer> resourceDeployIds = new ArrayList<Integer>();
for (BundleResourceDeployment resourceDeploy : resourceDeploys) {
resourceDeployIds.add(resourceDeploy.getId());
}
final BundleResourceDeploymentCriteria brdc = new BundleResourceDeploymentCriteria();
brdc.addFilterIds(resourceDeployIds.toArray(new Integer[resourceDeployIds.size()]));
brdc.fetchResource(true);
//Use CriteriaQuery to automatically chunk/page through criteria query results
CriteriaQueryExecutor<BundleResourceDeployment, BundleResourceDeploymentCriteria> queryExecutor = new CriteriaQueryExecutor<BundleResourceDeployment, BundleResourceDeploymentCriteria>() {
@Override
public PageList<BundleResourceDeployment> execute(BundleResourceDeploymentCriteria criteria) {
return bundleManager.findBundleResourceDeploymentsByCriteria(subject, brdc);
}
};
CriteriaQuery<BundleResourceDeployment, BundleResourceDeploymentCriteria> brdResults = new CriteriaQuery<BundleResourceDeployment, BundleResourceDeploymentCriteria>(
brdc, queryExecutor);
// PageList<BundleResourceDeployment> brdResults = bundleManager.findBundleResourceDeploymentsByCriteria(subject,
// brdc);
resourceDeploys.clear();
// resourceDeploys.addAll(brdResults);
// need to wire the live bundle deployment back in - no need for another query or fetch it above because we have it already
for (BundleResourceDeployment brd : brdResults) {
resourceDeploys.add(brd);
brd.setBundleDeployment(liveDeployment);
}
// loop through each deployment and purge it on agent
Map<BundleResourceDeployment, String> failedToPurge = new HashMap<BundleResourceDeployment, String>();
for (BundleResourceDeployment resourceDeploy : resourceDeploys) {
try {
// first put the user name that requested the purge in the audit trail
BundleResourceDeploymentHistory history = new BundleResourceDeploymentHistory(subject.getName(),
"Purge Requested", "User [" + subject.getName() + "] requested to purge this deployment", null,
BundleResourceDeploymentHistory.Status.SUCCESS, null, null);
bundleManager.addBundleResourceDeploymentHistoryInNewTrans(subjectManager.getOverlord(),
resourceDeploy.getId(), history);
// get a connection to the agent and tell it to purge the bundle from the file system
Subject overlord = subjectManager.getOverlord();
AgentClient agentClient = agentManager.getAgentClient(overlord, resourceDeploy.getResource().getId());
BundleAgentService bundleAgentService = agentClient.getBundleAgentService();
BundlePurgeRequest request = new BundlePurgeRequest(resourceDeploy);
BundlePurgeResponse results = bundleAgentService.purge(request);
if (!results.isSuccess()) {
String errorMessage = results.getErrorMessage();
failedToPurge.put(resourceDeploy, errorMessage);
}
} catch (Exception e) {
String errorMessage = ThrowableUtil.getStackAsString(e);
failedToPurge.put(resourceDeploy, errorMessage);
}
}
// marks the live deployment "no longer live"
bundleManager._finalizePurge(subjectManager.getOverlord(), liveDeployment, failedToPurge);
// throw an exception if we failed to purge one or more resource deployments.
// since we are not in a tx context, we lose nothing. All DB updates have already been committed by now
// which is what we want. All this does is inform the caller something went wrong.
if (!failedToPurge.isEmpty()) {
int totalDeployments = liveDeployment.getResourceDeployments().size();
int failedPurges = failedToPurge.size();
throw new Exception("Failed to purge [" + failedPurges + "] of [" + totalDeployments
+ "] remote resource deployments");
}
}