@@ -78,6 +78,10 @@ public class TaskAction implements CeWsAction { | |||
.setRequired(true) | |||
.setDescription("Id of task") | |||
.setExampleValue(Uuids.UUID_EXAMPLE_01); | |||
action.createParam(PARAM_ADDITIONAL_FIELDS) | |||
.setSince("6.1") | |||
.setDescription("Comma-separated list of the optional fields to be returned in response.") | |||
.setPossibleValues(AdditionalField.possibleValues()); | |||
} | |||
@Override | |||
@@ -93,14 +97,15 @@ public class TaskAction implements CeWsAction { | |||
} else { | |||
Optional<CeActivityDto> activityDto = dbClient.ceActivityDao().selectByUuid(dbSession, taskUuid); | |||
if (activityDto.isPresent()) { | |||
checkPermission(activityDto.get().getComponentUuid()); | |||
wsTaskResponse.setTask(wsTaskFormatter.formatActivity(dbSession, activityDto.get())); | |||
CeActivityDto ceActivityDto = activityDto.get(); | |||
checkPermission(ceActivityDto.getComponentUuid()); | |||
maskErrorStacktrace(wsRequest, ceActivityDto); | |||
wsTaskResponse.setTask(wsTaskFormatter.formatActivity(dbSession, ceActivityDto)); | |||
} else { | |||
throw new NotFoundException(); | |||
} | |||
} | |||
writeProtobuf(wsTaskResponse.build(), wsRequest, wsResponse); | |||
} finally { | |||
dbClient.closeSession(dbSession); | |||
} | |||
@@ -113,4 +118,40 @@ public class TaskAction implements CeWsAction { | |||
throw insufficientPrivilegesException(); | |||
} | |||
} | |||
private static void maskErrorStacktrace(Request wsRequest, CeActivityDto ceActivityDto) { | |||
Set<AdditionalField> fromRequest = TaskAction.AdditionalField.getFromRequest(wsRequest); | |||
if (!fromRequest.contains(TaskAction.AdditionalField.STACKTRACE)) { | |||
ceActivityDto.setErrorStacktrace(null); | |||
} | |||
} | |||
private enum AdditionalField { | |||
STACKTRACE; | |||
public static Set<AdditionalField> getFromRequest(Request wsRequest) { | |||
List<String> strings = wsRequest.paramAsStrings(PARAM_ADDITIONAL_FIELDS); | |||
if (strings == null) { | |||
return Collections.emptySet(); | |||
} | |||
return strings.stream() | |||
.map(s -> { | |||
for (AdditionalField field : AdditionalField.values()) { | |||
if (field.name().equalsIgnoreCase(s)) { | |||
return field; | |||
} | |||
} | |||
return null; | |||
}) | |||
.filter(Objects::nonNull) | |||
.collect(Collectors.toSet()); | |||
} | |||
public static Collection<String> possibleValues() { | |||
return Arrays.stream(values()) | |||
.map(Enum::name) | |||
.map(s -> s.toLowerCase(Locale.ENGLISH)) | |||
.collect(Collectors.toList(values().length)); | |||
} | |||
} | |||
} |
@@ -129,7 +129,9 @@ public class TaskFormatter { | |||
if (dto.getErrorMessage() != null) { | |||
builder.setErrorMessage(dto.getErrorMessage()); | |||
} | |||
builder.setHasErrorStacktrace(dto.isHasErrorStacktrace()); | |||
if (dto.getErrorStacktrace() != null) { | |||
builder.setErrorStacktrace(dto.getErrorStacktrace()); | |||
} | |||
return builder.build(); | |||
} | |||
@@ -12,7 +12,8 @@ | |||
"startedAt": "2015-10-02T11:32:16+0200", | |||
"executedAt": "2015-10-02T11:32:22+0200", | |||
"executionTimeMs": 5286, | |||
"errorMessage": "Failed to unzip analysis report", | |||
"hasErrorStacktrace": true | |||
"errorMessage": "Fail to extract report AVaXuGAi_te3Ldc_YItm from database", | |||
"hasErrorStacktrace": true, | |||
"errorStacktrace": "java.lang.IllegalStateException: Fail to extract report AVaXuGAi_te3Ldc_YItm from database\\n\tat org.sonar.server.computation.task.projectanalysis.step.ExtractReportStep.execute(ExtractReportStep.java:50)" | |||
} | |||
} |
@@ -45,7 +45,6 @@ import static org.mockito.Mockito.mock; | |||
import static org.sonar.core.permission.GlobalPermissions.PROVISIONING; | |||
import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; | |||
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; | |||
import static org.sonar.db.ce.CeActivityDtoTestHelper.setHasErrorStacktrace; | |||
import static org.sonarqube.ws.MediaTypes.PROTOBUF; | |||
public class TaskActionTest { | |||
@@ -133,7 +132,6 @@ public class TaskActionTest { | |||
CeActivityDto activityDto = createActivityDto("TASK_1") | |||
.setErrorMessage("error msg") | |||
.setErrorStacktrace("error stack"); | |||
setHasErrorStacktrace(activityDto, true); | |||
persist(activityDto); | |||
TestResponse wsResponse = ws.newRequest() | |||
@@ -146,8 +144,8 @@ public class TaskActionTest { | |||
WsCe.Task task = taskResponse.getTask(); | |||
assertThat(task.getId()).isEqualTo("TASK_1"); | |||
assertThat(task.getErrorMessage()).isEqualTo(activityDto.getErrorMessage()); | |||
assertThat(task.hasHasErrorStacktrace()).isTrue(); | |||
assertThat(task.getHasErrorStacktrace()).isTrue(); | |||
assertThat(task.hasErrorStacktrace()).isTrue(); | |||
assertThat(task.getErrorStacktrace()).isEqualTo(activityDto.getErrorStacktrace()); | |||
} | |||
@Test | |||
@@ -157,7 +155,6 @@ public class TaskActionTest { | |||
CeActivityDto activityDto = createActivityDto("TASK_1") | |||
.setErrorMessage("error msg") | |||
.setErrorStacktrace("error stack"); | |||
setHasErrorStacktrace(activityDto, true); | |||
persist(activityDto); | |||
TestResponse wsResponse = ws.newRequest() | |||
@@ -169,8 +166,7 @@ public class TaskActionTest { | |||
WsCe.Task task = taskResponse.getTask(); | |||
assertThat(task.getId()).isEqualTo("TASK_1"); | |||
assertThat(task.getErrorMessage()).isEqualTo(activityDto.getErrorMessage()); | |||
assertThat(task.hasHasErrorStacktrace()).isTrue(); | |||
assertThat(task.getHasErrorStacktrace()).isTrue(); | |||
assertThat(task.hasErrorStacktrace()).isFalse(); | |||
} | |||
@Test | |||
@@ -190,8 +186,7 @@ public class TaskActionTest { | |||
WsCe.Task task = taskResponse.getTask(); | |||
assertThat(task.getId()).isEqualTo("TASK_1"); | |||
assertThat(task.getErrorMessage()).isEqualTo(activityDto.getErrorMessage()); | |||
assertThat(task.hasHasErrorStacktrace()).isTrue(); | |||
assertThat(task.getHasErrorStacktrace()).isFalse(); | |||
assertThat(task.hasErrorStacktrace()).isFalse(); | |||
} | |||
@Test |
@@ -20,6 +20,7 @@ | |||
package org.sonar.server.ce.ws; | |||
import java.io.IOException; | |||
import java.util.Collections; | |||
import java.util.Date; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
@@ -185,6 +186,40 @@ public class TaskFormatterTest { | |||
assertThat(wsTasks).extracting("id").containsExactly("UUID1", "UUID2"); | |||
} | |||
@Test | |||
public void formatActivity_with_both_error_message_and_stacktrace() { | |||
CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED) | |||
.setErrorMessage("error msg") | |||
.setErrorStacktrace("error stacktrace"); | |||
WsCe.Task task = underTest.formatActivity(db.getSession(), Collections.singletonList(dto)).iterator().next(); | |||
assertThat(task.getErrorMessage()).isEqualTo(dto.getErrorMessage()); | |||
assertThat(task.getErrorStacktrace()).isEqualTo(dto.getErrorStacktrace()); | |||
} | |||
@Test | |||
public void formatActivity_with_both_error_message_only() { | |||
CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED) | |||
.setErrorMessage("error msg"); | |||
WsCe.Task task = underTest.formatActivity(db.getSession(), Collections.singletonList(dto)).iterator().next(); | |||
assertThat(task.getErrorMessage()).isEqualTo(dto.getErrorMessage()); | |||
assertThat(task.hasErrorStacktrace()).isFalse(); | |||
} | |||
@Test | |||
public void formatActivity_with_both_error_message_and_only_stacktrace_flag() { | |||
CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED) | |||
.setErrorMessage("error msg"); | |||
WsCe.Task task = underTest.formatActivity(db.getSession(), Collections.singletonList(dto)).iterator().next(); | |||
assertThat(task.getErrorMessage()).isEqualTo(dto.getErrorMessage()); | |||
assertThat(task.hasErrorStacktrace()).isFalse(); | |||
} | |||
private CeActivityDto newActivity(String taskUuid, String componentUuid, CeActivityDto.Status status) { | |||
CeQueueDto queueDto = new CeQueueDto(); | |||
queueDto.setCreatedAt(1_450_000_000_000L); |
@@ -78,7 +78,7 @@ message Task { | |||
optional int64 executionTimeMs = 14; | |||
optional bool logs = 15; | |||
optional string errorMessage = 16; | |||
optional bool hasErrorStacktrace = 17; | |||
optional string errorStacktrace = 17; | |||
} | |||
enum TaskStatus { |