use of org.commonjava.indy.promote.model.PathsPromoteResult in project indy by Commonjava.
the class PromoteResource method promotePaths.
@ApiOperation("Promote paths from a source repository into a target repository/group (subject to validation).")
@ApiResponse(code = 200, message = "Promotion operation finished (consult response content for success/failure).", response = PathsPromoteResult.class)
@ApiImplicitParam(name = "body", paramType = "body", value = "JSON request specifying source and target, with other configuration options", allowMultiple = false, required = true, dataType = "org.commonjava.indy.promote.model.PathsPromoteRequest")
@Path("/paths/promote")
@POST
@Consumes(ApplicationContent.application_json)
public Response promotePaths(@Context final HttpServletRequest request, @Context final UriInfo uriInfo) {
PathsPromoteRequest req = null;
Response response = null;
try {
final String json = IOUtils.toString(request.getInputStream());
logger.info("Got promotion request:\n{}", json);
req = mapper.readValue(json, PathsPromoteRequest.class);
} catch (final IOException e) {
response = formatResponse(e, "Failed to read DTO from request body.");
}
if (response != null) {
return response;
}
try {
PackageTypeDescriptor packageTypeDescriptor = PackageTypes.getPackageTypeDescriptor(req.getSource().getPackageType());
final String baseUrl = uriInfo.getBaseUriBuilder().path(packageTypeDescriptor.getContentRestBasePath()).build(req.getSource().getType().singularEndpointName(), req.getSource().getName()).toString();
final PathsPromoteResult result = manager.promotePaths(req, baseUrl);
// TODO: Amend response status code based on presence of error? This would have consequences for client API...
response = formatOkResponseWithJsonEntity(result, mapper);
} catch (PromotionException | IndyWorkflowException e) {
logger.error(e.getMessage(), e);
response = formatResponse(e);
}
return response;
}
use of org.commonjava.indy.promote.model.PathsPromoteResult in project indy by Commonjava.
the class PromoteResource method resumePaths.
@ApiOperation("RESUME promotion of paths from a source repository into a target repository/group (subject to validation), presumably after a previous failure condition has been corrected.")
@ApiResponse(code = 200, message = "Promotion operation finished (consult response content for success/failure).", response = PathsPromoteResult.class)
@ApiImplicitParam(name = "body", paramType = "body", value = "JSON result from previous attempt, specifying source and target, with other configuration options", allowMultiple = false, required = true, dataType = "org.commonjava.indy.promote.model.PathsPromoteResult")
@Path("/paths/resume")
@POST
@Consumes(ApplicationContent.application_json)
public Response resumePaths(@Context final HttpServletRequest request) {
PathsPromoteResult result = null;
Response response = null;
try {
result = mapper.readValue(request.getInputStream(), PathsPromoteResult.class);
} catch (final IOException e) {
response = formatResponse(e, "Failed to read DTO from request body.");
}
if (response != null) {
return response;
}
try {
result = manager.resumePathsPromote(result);
// TODO: Amend response status code based on presence of error? This would have consequences for client API...
response = formatOkResponseWithJsonEntity(result, mapper);
} catch (PromotionException | IndyWorkflowException e) {
logger.error(e.getMessage(), e);
response = formatResponse(e);
}
return response;
}
use of org.commonjava.indy.promote.model.PathsPromoteResult in project indy by Commonjava.
the class PromoteResource method rollbackPaths.
@ApiOperation("Rollback promotion of any completed paths to a source repository from a target repository/group.")
@ApiResponse(code = 200, message = "Promotion operation finished (consult response content for success/failure).", response = PathsPromoteResult.class)
@ApiImplicitParam(name = "body", paramType = "body", value = "JSON result from previous attempt, specifying source and target, with other configuration options", allowMultiple = false, required = true, dataType = "org.commonjava.indy.promote.model.PathsPromoteResult")
@Path("/paths/rollback")
@POST
@Consumes(ApplicationContent.application_json)
public Response rollbackPaths(@Context final HttpServletRequest request, @Context final UriInfo uriInfo) {
PathsPromoteResult result = null;
Response response = null;
try {
result = mapper.readValue(request.getInputStream(), PathsPromoteResult.class);
} catch (final IOException e) {
response = formatResponse(e, "Failed to read DTO from request body.");
}
if (response != null) {
return response;
}
try {
result = manager.rollbackPathsPromote(result);
// TODO: Amend response status code based on presence of error? This would have consequences for client API...
response = formatOkResponseWithJsonEntity(result, mapper);
} catch (PromotionException | IndyWorkflowException e) {
logger.error(e.getMessage(), e);
response = formatResponse(e);
}
return response;
}
use of org.commonjava.indy.promote.model.PathsPromoteResult in project indy by Commonjava.
the class RollbackTwoArtifactsTest method run.
@Test
public void run() throws Exception {
PathsPromoteResult result = client.module(IndyPromoteClientModule.class).promoteByPath(new PathsPromoteRequest(source.getKey(), target.getKey()));
assertThat(result.getRequest().getSource(), equalTo(source.getKey()));
assertThat(result.getRequest().getTarget(), equalTo(target.getKey()));
Set<String> pending = result.getPendingPaths();
assertThat(pending == null || pending.isEmpty(), equalTo(true));
Set<String> completed = result.getCompletedPaths();
assertThat(completed, notNullValue());
assertThat(completed.size(), equalTo(2));
assertThat(result.getError(), nullValue());
result = client.module(IndyPromoteClientModule.class).rollbackPathPromote(result);
assertThat(result.getRequest().getSource(), equalTo(source.getKey()));
assertThat(result.getRequest().getTarget(), equalTo(target.getKey()));
completed = result.getCompletedPaths();
assertThat(completed == null || completed.isEmpty(), equalTo(true));
pending = result.getPendingPaths();
assertThat(pending, notNullValue());
assertThat(pending.size(), equalTo(2));
assertThat(result.getError(), nullValue());
assertThat(client.content().exists(target.getKey().getType(), target.getName(), first), equalTo(false));
assertThat(client.content().exists(target.getKey().getType(), target.getName(), second), equalTo(false));
}
use of org.commonjava.indy.promote.model.PathsPromoteResult in project indy by Commonjava.
the class PromotionManager method rollbackPathsPromote.
/**
* Attempt to rollbackPathsPromote a previously failing {@link PathsPromoteResult}. This is meant to handle cases where an unrecoverable error
* occurs on the server side, and promotion can NOT proceed afterward. All paths in the completed paths set are deleted from the target, if
* possible. The output {@link PathsPromoteResult} contains the previous content, with any successfully removed target paths moved back from the
* completed-paths list to the pending-paths list. If an error occurs during rollbackPathsPromote, the error field will be set...otherwise, it will be null.
*
* @param result The result to rollbackPathsPromote
*
* @return The same result, with any successful deletions moved from the completed to pending paths list, and the error cleared (or set to a
* new error)
*
* @throws PromotionException
* @throws IndyWorkflowException
*/
public PathsPromoteResult rollbackPathsPromote(final PathsPromoteResult result) throws PromotionException, IndyWorkflowException {
StoreKey targetKey = result.getRequest().getTarget();
ReentrantLock lock;
synchronized (byPathTargetLocks) {
lock = byPathTargetLocks.get(targetKey);
if (lock == null) {
lock = new ReentrantLock();
byPathTargetLocks.put(targetKey, lock);
}
}
final List<Transfer> contents = getTransfersForPaths(targetKey, result.getCompletedPaths());
final Set<String> completed = result.getCompletedPaths();
final Set<String> skipped = result.getSkippedPaths();
if (completed == null || completed.isEmpty()) {
result.setError(null);
return result;
}
Set<String> pending = result.getPendingPaths();
pending = pending == null ? new HashSet<String>() : new HashSet<String>(pending);
String error = null;
final boolean copyToSource = result.getRequest().isPurgeSource();
ArtifactStore source = null;
try {
source = storeManager.getArtifactStore(result.getRequest().getSource());
} catch (final IndyDataException e) {
error = String.format("Failed to retrieve artifact store: %s. Reason: %s", result.getRequest().getSource(), e.getMessage());
logger.error(error, e);
}
boolean locked = false;
try {
if (error == null) {
locked = lock.tryLock(config.getLockTimeoutSeconds(), TimeUnit.SECONDS);
if (!locked) {
error = String.format("Failed to acquire promotion lock on target: %s in %d seconds.", targetKey, config.getLockTimeoutSeconds());
logger.warn(error);
}
}
if (error == null) {
for (final Transfer transfer : contents) {
if (transfer != null && transfer.exists()) {
InputStream stream = null;
try {
if (copyToSource) {
stream = transfer.openInputStream(true);
final String path = transfer.getPath();
contentManager.store(source, path, stream, TransferOperation.UPLOAD, new EventMetadata());
stream.close();
}
transfer.delete(true);
completed.remove(transfer.getPath());
pending.add(transfer.getPath());
} catch (final IOException e) {
error = String.format("Failed to rollback path promotion of: %s from: %s. Reason: %s", transfer, result.getRequest().getSource(), e.getMessage());
logger.error(error, e);
} finally {
closeQuietly(stream);
}
}
}
}
} catch (InterruptedException e) {
error = String.format("Interrupted waiting for promotion lock on target: %s", targetKey);
logger.warn(error);
} finally {
if (locked) {
lock.unlock();
}
}
return new PathsPromoteResult(result.getRequest(), pending, completed, skipped, error, new ValidationResult());
}
Aggregations