use of org.jboss.pnc.spi.executor.BuildExecutionSession in project pnc by project-ncl.
the class TermdBuildDriverTest method shouldStartAndCancelTheExecutionImmediately.
@Test(timeout = 5_000)
public void shouldStartAndCancelTheExecutionImmediately() throws ConfigurationParseException, BuildDriverException, InterruptedException, IOException {
// given
String dirName = "test-workdir";
String logStart = "Running the command...";
String logEnd = "Command completed.";
TermdBuildDriver driver = new TermdBuildDriver(systemConfig, buildDriverModuleConfig, clientFactory);
BuildExecutionSession buildExecution = mock(BuildExecutionSession.class);
BuildExecutionConfiguration buildExecutionConfiguration = mock(BuildExecutionConfiguration.class);
doReturn("echo \"" + logStart + "\"; mvn validate; echo \"" + logEnd + "\";").when(buildExecutionConfiguration).getBuildScript();
doReturn(dirName).when(buildExecutionConfiguration).getName();
doReturn(buildExecutionConfiguration).when(buildExecution).getBuildExecutionConfiguration();
AtomicReference<CompletedBuild> buildResult = new AtomicReference<>();
// when
CountDownLatch latch = new CountDownLatch(1);
Consumer<CompletedBuild> onComplete = (completedBuild) -> {
buildResult.set(completedBuild);
latch.countDown();
};
Consumer<Throwable> onError = (throwable) -> {
logger.error("Error received: ", throwable);
fail(throwable.getMessage());
};
RunningBuild runningBuild = driver.startProjectBuild(buildExecution, localEnvironmentPointer, onComplete, onError);
runningBuild.cancel();
latch.await();
// then
assertThat(buildResult.get().getBuildResult().getBuildLog()).doesNotContain(logEnd);
assertThat(buildResult.get().getBuildResult().getBuildStatus()).isEqualTo(CANCELLED);
}
use of org.jboss.pnc.spi.executor.BuildExecutionSession in project pnc by project-ncl.
the class TermdBuildDriver method startProjectBuild.
public RunningBuild startProjectBuild(BuildExecutionSession buildExecutionSession, RunningEnvironment runningEnvironment, Consumer<CompletedBuild> onComplete, Consumer<Throwable> onError, Optional<Consumer<Status>> onStatusUpdate) throws BuildDriverException {
logger.info("[{}] Starting build for Build Execution Session {}", runningEnvironment.getId(), buildExecutionSession.getId());
TermdRunningBuild termdRunningBuild = new TermdRunningBuild(runningEnvironment, buildExecutionSession.getBuildExecutionConfiguration(), onComplete, onError);
DebugData debugData = runningEnvironment.getDebugData();
String buildScript = prepareBuildScript(termdRunningBuild, debugData);
if (!termdRunningBuild.isCanceled()) {
String terminalUrl = getBuildAgentUrl(runningEnvironment);
final RemoteInvocation remoteInvocation = new RemoteInvocation(clientFactory, terminalUrl, onStatusUpdate, httpCallbackMode, buildExecutionSession.getId(), buildExecutionSession.getAccessToken());
buildExecutionSession.setBuildStatusUpdateConsumer(remoteInvocation.getClientStatusUpdateConsumer());
FileTransfer fileTransfer = new ClientFileTransfer(remoteInvocation.getBuildAgentClient(), MAX_LOG_SIZE);
fileTransferReadTimeout.ifPresent(fileTransfer::setReadTimeout);
CompletableFuture<Void> prepareBuildFuture = CompletableFuture.supplyAsync(() -> {
logger.debug("Uploading build script to build environment ...");
return uploadTask(termdRunningBuild.getRunningEnvironment(), buildScript, fileTransfer);
}, executor).thenApplyAsync(scriptPath -> {
logger.debug("Setting the script path ...");
remoteInvocation.setScriptPath(scriptPath);
return null;
}, executor).thenRunAsync(() -> {
logger.debug("Invoking remote script ...");
invokeRemoteScript(remoteInvocation);
}, executor);
CompletableFuture<RemoteInvocationCompletion> buildLivenessFuture = prepareBuildFuture.thenComposeAsync(nul -> {
logger.debug("Starting liveness monitor ...");
return monitorBuildLiveness(remoteInvocation);
}, executor);
CompletableFuture<RemoteInvocationCompletion> buildCompletionFuture = prepareBuildFuture.thenComposeAsync(nul -> {
logger.debug("Waiting fo remote script to complete...");
return remoteInvocation.getCompletionNotifier();
}, executor);
CompletableFuture<RemoteInvocationCompletion> optionallyEnableDebug = buildCompletionFuture.thenApplyAsync(remoteInvocationCompletion -> {
Status status = remoteInvocationCompletion.getStatus();
if (status.isFinal()) {
logger.debug("Script completionNotifier completed with status {}.", status);
if ((status == FAILED || status == SYSTEM_ERROR) && debugData.isEnableDebugOnFailure()) {
debugData.setDebugEnabled(true);
remoteInvocation.enableSsh();
}
}
return remoteInvocationCompletion;
}, executor);
CompletableFuture<Object> buildFuture = CompletableFuture.anyOf(buildLivenessFuture, optionallyEnableDebug);
buildFuture.handle((result, exception) -> {
RemoteInvocationCompletion completion;
if (result != null) {
// both of combined futures return the same type
RemoteInvocationCompletion remoteInvocationCompletion = (RemoteInvocationCompletion) result;
if (remoteInvocationCompletion.getException() != null) {
logger.warn("Completing build execution.", remoteInvocationCompletion.getException());
} else {
logger.debug("Completing build execution. Status: {};", remoteInvocationCompletion.getStatus());
}
completion = remoteInvocationCompletion;
} else if (exception != null && exception.getCause() instanceof java.util.concurrent.CancellationException) {
// canceled in non build operation (completableFuture cancel), non graceful completion
logger.warn("Completing build execution. Cancelled;");
completion = new RemoteInvocationCompletion(INTERRUPTED, Optional.empty());
} else {
logger.warn("Completing build execution. System error.", exception);
completion = new RemoteInvocationCompletion(new BuildDriverException("System error.", exception));
}
termdRunningBuild.setCancelHook(null);
remoteInvocation.close();
complete(termdRunningBuild, completion, fileTransfer);
return null;
});
termdRunningBuild.setCancelHook(() -> {
// try to cancel remote execution
remoteInvocation.cancel();
ScheduledFuture<?> forceCancel_ = scheduledExecutorService.schedule(() -> {
logger.debug("Force cancelling build ...");
prepareBuildFuture.cancel(true);
}, internalCancelTimeoutMillis, TimeUnit.MILLISECONDS);
remoteInvocation.addPreClose(() -> forceCancel_.cancel(false));
});
} else {
logger.debug("Skipping script uploading (cancel flag) ...");
}
return termdRunningBuild;
}
use of org.jboss.pnc.spi.executor.BuildExecutionSession in project pnc by project-ncl.
the class BuildExecutorTriggerer method getMdcMeta.
public Optional<BuildTaskContext> getMdcMeta(String buildExecutionConfigId, String userId) {
BuildExecutionSession runningExecution = buildExecutor.getRunningExecution(buildExecutionConfigId);
if (runningExecution != null) {
BuildExecutionConfiguration buildExecutionConfiguration = runningExecution.getBuildExecutionConfiguration();
boolean temporaryBuild = buildExecutionConfiguration.isTempBuild();
return Optional.of(new BuildTaskContext(buildExecutionConfiguration.getBuildContentId(), userId, temporaryBuild, ExpiresDate.getTemporaryBuildExpireDate(systemConfig.getTemporaryBuildsLifeSpan(), temporaryBuild)));
} else {
return Optional.empty();
}
}
use of org.jboss.pnc.spi.executor.BuildExecutionSession in project pnc by project-ncl.
the class BuildTaskEndpointImpl method build.
@Override
public Response build(BuildExecutionConfigurationRest buildExecutionConfiguration, String usernameTriggered, String callbackUrl) {
try {
logger.debug("Endpoint /execute-build requested for buildTaskId [{}], from [{}]", buildExecutionConfiguration.getId(), request.getRemoteAddr());
boolean temporaryBuild = buildExecutionConfiguration.isTempBuild();
MDCUtils.addBuildContext(buildExecutionConfiguration.getBuildContentId(), temporaryBuild, ExpiresDate.getTemporaryBuildExpireDate(systemConfig.getTemporaryBuildsLifeSpan(), temporaryBuild), userService.currentUser().getId().toString());
logger.info("Build execution requested.");
logger.debug("Staring new build execution for configuration: {}. Caller requested a callback to {}.", buildExecutionConfiguration.toString(), callbackUrl);
BuildExecutionSession buildExecutionSession = buildExecutorTriggerer.executeBuild(buildExecutionConfiguration.toBuildExecutionConfiguration(), callbackUrl, userService.currentUserToken());
GlobalModuleGroup globalConfig = configuration.getGlobalConfig();
UriBuilder uriBuilder = UriBuilder.fromUri(globalConfig.getExternalPncUrl()).path("/ws/executor/notifications");
AcceptedResponse acceptedResponse = new AcceptedResponse(buildExecutionConfiguration.getId(), uriBuilder.build().toString());
return Response.ok().entity(acceptedResponse).build();
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw new RuntimeException(e);
} finally {
MDCUtils.removeBuildContext();
}
}
use of org.jboss.pnc.spi.executor.BuildExecutionSession in project pnc by project-ncl.
the class BuildTaskEndpointImpl method build.
@Override
public Response build(BuildExecutionConfigurationWithCallbackRest buildExecutionConfiguration) {
try {
String callbackUrl = buildExecutionConfiguration.getCompletionCallbackUrl();
boolean temporaryBuild = buildExecutionConfiguration.isTempBuild();
MDCUtils.addBuildContext(buildExecutionConfiguration.getBuildContentId(), temporaryBuild, ExpiresDate.getTemporaryBuildExpireDate(systemConfig.getTemporaryBuildsLifeSpan(), temporaryBuild), userService.currentUser().getId().toString());
logger.info("Build execution requested.");
logger.debug("Staring new build execution for configuration: {}. Caller requested a callback to {}.", buildExecutionConfiguration.toString(), callbackUrl);
BuildExecutionSession buildExecutionSession = buildExecutorTriggerer.executeBuild(buildExecutionConfiguration.toBuildExecutionConfiguration(), callbackUrl, userService.currentUserToken());
GlobalModuleGroup globalConfig = configuration.getGlobalConfig();
UriBuilder uriBuilder = UriBuilder.fromUri(globalConfig.getExternalPncUrl()).path("/ws/executor/notifications");
AcceptedResponse acceptedResponse = new AcceptedResponse(buildExecutionConfiguration.getId(), uriBuilder.build().toString());
return Response.ok().entity(acceptedResponse).build();
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw new RuntimeException(e);
} finally {
MDCUtils.removeBuildContext();
}
}
Aggregations