mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-19 21:13:46 +00:00
Fix logic of marking task as failed (#3083)
* Fix logic of markaing task as failed - Do not mark task as failed if it is already in the shutting down state - accumulate errors when setting task error to understand the context - refactor the Error record * fix tests * format * Fix build * Update src/ApiService/ApiService/onefuzzlib/ImageReference.cs Co-authored-by: George Pollard <porges@porg.es> * Update src/ApiService/ApiService/onefuzzlib/ProxyOperations.cs Co-authored-by: Teo Voinea <58236992+tevoinea@users.noreply.github.com> --------- Co-authored-by: George Pollard <porges@porg.es> Co-authored-by: Teo Voinea <58236992+tevoinea@users.noreply.github.com>
This commit is contained in:
@ -35,11 +35,7 @@ public class AgentCanSchedule {
|
|||||||
_log.Warning($"Unable to find {canScheduleRequest.MachineId:Tag:MachineId}");
|
_log.Warning($"Unable to find {canScheduleRequest.MachineId:Tag:MachineId}");
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(ErrorCode.UNABLE_TO_FIND, "unable to find node"),
|
||||||
ErrorCode.UNABLE_TO_FIND,
|
|
||||||
new string[] {
|
|
||||||
"unable to find node"
|
|
||||||
}),
|
|
||||||
canScheduleRequest.MachineId.ToString());
|
canScheduleRequest.MachineId.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public class AgentEvents {
|
|||||||
NodeStateUpdate updateEvent => await OnStateUpdate(envelope.MachineId, updateEvent),
|
NodeStateUpdate updateEvent => await OnStateUpdate(envelope.MachineId, updateEvent),
|
||||||
WorkerEvent workerEvent => await OnWorkerEvent(envelope.MachineId, workerEvent),
|
WorkerEvent workerEvent => await OnWorkerEvent(envelope.MachineId, workerEvent),
|
||||||
NodeEvent nodeEvent => await OnNodeEvent(envelope.MachineId, nodeEvent),
|
NodeEvent nodeEvent => await OnNodeEvent(envelope.MachineId, nodeEvent),
|
||||||
_ => new Error(ErrorCode.INVALID_REQUEST, new string[] { $"invalid node event: {envelope.Event.GetType().Name}" }),
|
_ => Error.Create(ErrorCode.INVALID_REQUEST, $"invalid node event: {envelope.Event.GetType().Name}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (error is Error e) {
|
if (error is Error e) {
|
||||||
@ -114,17 +114,17 @@ public class AgentEvents {
|
|||||||
} else if (ev.State == NodeState.SettingUp) {
|
} else if (ev.State == NodeState.SettingUp) {
|
||||||
if (ev.Data is NodeSettingUpEventData settingUpData) {
|
if (ev.Data is NodeSettingUpEventData settingUpData) {
|
||||||
if (!settingUpData.Tasks.Any()) {
|
if (!settingUpData.Tasks.Any()) {
|
||||||
return new Error(ErrorCode.INVALID_REQUEST, Errors: new string[] {
|
return Error.Create(ErrorCode.INVALID_REQUEST,
|
||||||
$"setup without tasks. machine_id: {machineId}",
|
$"setup without tasks. machine_id: {machineId}"
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var taskId in settingUpData.Tasks) {
|
foreach (var taskId in settingUpData.Tasks) {
|
||||||
var task = await _context.TaskOperations.GetByTaskId(taskId);
|
var task = await _context.TaskOperations.GetByTaskId(taskId);
|
||||||
if (task is null) {
|
if (task is null) {
|
||||||
return new Error(
|
return Error.Create(
|
||||||
ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
Errors: new string[] { $"unable to find task: {taskId}" });
|
$"unable to find task: {taskId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
_log.Info($"node starting task. {machineId:Tag:MachineId} {task.JobId:Tag:JobId} {task.TaskId:Tag:TaskId}");
|
_log.Info($"node starting task. {machineId:Tag:MachineId} {task.JobId:Tag:JobId} {task.TaskId:Tag:TaskId}");
|
||||||
@ -154,7 +154,7 @@ public class AgentEvents {
|
|||||||
if (ev.Data is NodeDoneEventData doneData) {
|
if (ev.Data is NodeDoneEventData doneData) {
|
||||||
if (doneData.Error is not null) {
|
if (doneData.Error is not null) {
|
||||||
var errorText = EntityConverter.ToJsonString(doneData);
|
var errorText = EntityConverter.ToJsonString(doneData);
|
||||||
error = new Error(ErrorCode.TASK_FAILED, Errors: new string[] { errorText });
|
error = Error.Create(ErrorCode.TASK_FAILED, errorText);
|
||||||
_log.Error($"node 'done' {machineId:Tag:MachineId} - {errorText:Tag:Error}");
|
_log.Error($"node 'done' {machineId:Tag:MachineId} - {errorText:Tag:Error}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,9 +178,9 @@ public class AgentEvents {
|
|||||||
return await OnWorkerEventRunning(machineId, ev.Running);
|
return await OnWorkerEventRunning(machineId, ev.Running);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Error(
|
return Error.Create(
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
Errors: new string[] { "WorkerEvent should have either 'done' or 'running' set" });
|
"WorkerEvent should have either 'done' or 'running' set");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Async.Task<Error?> OnWorkerEventRunning(Guid machineId, WorkerRunningEvent running) {
|
private async Async.Task<Error?> OnWorkerEventRunning(Guid machineId, WorkerRunningEvent running) {
|
||||||
@ -189,15 +189,11 @@ public class AgentEvents {
|
|||||||
_context.NodeOperations.GetByMachineId(machineId));
|
_context.NodeOperations.GetByMachineId(machineId));
|
||||||
|
|
||||||
if (task is null) {
|
if (task is null) {
|
||||||
return new Error(
|
return Error.Create(ErrorCode.INVALID_REQUEST, $"unable to find task: {running.TaskId}");
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
|
||||||
Errors: new string[] { $"unable to find task: {running.TaskId}" });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node is null) {
|
if (node is null) {
|
||||||
return new Error(
|
return Error.Create(ErrorCode.INVALID_REQUEST, $"unable to find node: {machineId}");
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
|
||||||
Errors: new string[] { $"unable to find node: {machineId}" });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!node.State.ReadyForReset()) {
|
if (!node.State.ReadyForReset()) {
|
||||||
@ -240,15 +236,11 @@ public class AgentEvents {
|
|||||||
_context.NodeOperations.GetByMachineId(machineId));
|
_context.NodeOperations.GetByMachineId(machineId));
|
||||||
|
|
||||||
if (task is null) {
|
if (task is null) {
|
||||||
return new Error(
|
return Error.Create(ErrorCode.INVALID_REQUEST, $"unable to find task: {done.TaskId}");
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
|
||||||
Errors: new string[] { $"unable to find task: {done.TaskId}" });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node is null) {
|
if (node is null) {
|
||||||
return new Error(
|
return Error.Create(ErrorCode.INVALID_REQUEST, $"unable to find node: {machineId}");
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
|
||||||
Errors: new string[] { $"unable to find node: {machineId}" });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// trim stdout/stderr if too long
|
// trim stdout/stderr if too long
|
||||||
@ -272,13 +264,12 @@ public class AgentEvents {
|
|||||||
} else {
|
} else {
|
||||||
await _context.TaskOperations.MarkFailed(
|
await _context.TaskOperations.MarkFailed(
|
||||||
task,
|
task,
|
||||||
new Error(
|
Error.Create(
|
||||||
Code: ErrorCode.TASK_FAILED,
|
ErrorCode.TASK_FAILED,
|
||||||
Errors: new string[] {
|
$"task failed. exit_status:{done.ExitStatus}",
|
||||||
$"task failed. exit_status:{done.ExitStatus}",
|
done.Stdout,
|
||||||
done.Stdout,
|
done.Stderr
|
||||||
done.Stderr,
|
));
|
||||||
}));
|
|
||||||
|
|
||||||
// keep node if any keep options are set
|
// keep node if any keep options are set
|
||||||
if ((task.Config.Debug?.Contains(TaskDebugFlag.KeepNodeOnFailure) == true)
|
if ((task.Config.Debug?.Contains(TaskDebugFlag.KeepNodeOnFailure) == true)
|
||||||
|
@ -40,9 +40,9 @@ public class AgentRegistration {
|
|||||||
if (machineId == Guid.Empty) {
|
if (machineId == Guid.Empty) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
new string[] { "'machine_id' query parameter must be provided" }),
|
"'machine_id' query parameter must be provided"),
|
||||||
"agent registration");
|
"agent registration");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,9 +50,9 @@ public class AgentRegistration {
|
|||||||
if (agentNode is null) {
|
if (agentNode is null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
new string[] { $"unable to find a registration associated with machine_id '{machineId}'" }),
|
$"unable to find a registration associated with machine_id '{machineId}'"),
|
||||||
"agent registration");
|
"agent registration");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,9 +60,9 @@ public class AgentRegistration {
|
|||||||
if (!pool.IsOk) {
|
if (!pool.IsOk) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
new string[] { "unable to find a pool associated with the provided machine_id" }),
|
"unable to find a pool associated with the provided machine_id"),
|
||||||
"agent registration");
|
"agent registration");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,18 +101,16 @@ public class AgentRegistration {
|
|||||||
if (machineId == Guid.Empty) {
|
if (machineId == Guid.Empty) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST, "'machine_id' query parameter must be provided"),
|
||||||
new string[] { "'machine_id' query parameter must be provided" }),
|
|
||||||
"agent registration");
|
"agent registration");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (poolName is null) {
|
if (poolName is null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST, "'pool_name' query parameter must be provided"),
|
||||||
new string[] { "'pool_name' query parameter must be provided" }),
|
|
||||||
"agent registration");
|
"agent registration");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,9 +122,8 @@ public class AgentRegistration {
|
|||||||
if (!poolResult.IsOk) {
|
if (!poolResult.IsOk) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST, $"unable to find pool '{poolName}'"),
|
||||||
Errors: new[] { $"unable to find pool '{poolName}'" }),
|
|
||||||
"agent registration");
|
"agent registration");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,9 +137,9 @@ public class AgentRegistration {
|
|||||||
if (os != null && pool.Os != os) {
|
if (os != null && pool.Os != os) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
Errors: new[] { $"OS mismatch: pool '{poolName}' is configured for '{pool.Os}', but agent is running '{os}'" }),
|
$"OS mismatch: pool '{poolName}' is configured for '{pool.Os}', but agent is running '{os}'"),
|
||||||
"agent registration");
|
"agent registration");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +39,9 @@ public class ContainersFunction {
|
|||||||
if (container is null) {
|
if (container is null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
Errors: new[] { "invalid container" }),
|
"invalid container"),
|
||||||
context: get.Name.String);
|
context: get.Name.String);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,9 +101,9 @@ public class ContainersFunction {
|
|||||||
if (sas is null) {
|
if (sas is null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
Errors: new[] { "invalid container" }),
|
"invalid container"),
|
||||||
context: post.Name.String);
|
context: post.Name.String);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,9 @@ public class Download {
|
|||||||
if (queryContainer is null || !Container.TryParse(queryContainer, out var container)) {
|
if (queryContainer is null || !Container.TryParse(queryContainer, out var container)) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
new string[] { "'container' query parameter must be provided and valid" }),
|
"'container' query parameter must be provided and valid"),
|
||||||
"download");
|
"download");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,9 +35,9 @@ public class Download {
|
|||||||
if (filename is null) {
|
if (filename is null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
new string[] { "'filename' query parameter must be provided" }),
|
"'filename' query parameter must be provided"),
|
||||||
"download");
|
"download");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +59,7 @@ public class Jobs {
|
|||||||
if (containerSas is null) {
|
if (containerSas is null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(ErrorCode.UNABLE_TO_CREATE_CONTAINER, "unable to create logs container "),
|
||||||
Code: ErrorCode.UNABLE_TO_CREATE_CONTAINER,
|
|
||||||
Errors: new string[] { "unable to create logs container " }),
|
|
||||||
"logs");
|
"logs");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,9 +71,9 @@ public class Jobs {
|
|||||||
_logTracer.WithTag("HttpRequest", "POST").WithHttpStatus(r.ErrorV).Error($"failed to insert job {job.JobId:Tag:JobId}");
|
_logTracer.WithTag("HttpRequest", "POST").WithHttpStatus(r.ErrorV).Error($"failed to insert job {job.JobId:Tag:JobId}");
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
Code: ErrorCode.UNABLE_TO_CREATE,
|
ErrorCode.UNABLE_TO_CREATE,
|
||||||
Errors: new string[] { "unable to create job " }
|
"unable to create job"
|
||||||
),
|
),
|
||||||
"job");
|
"job");
|
||||||
}
|
}
|
||||||
@ -95,9 +93,9 @@ public class Jobs {
|
|||||||
if (job is null) {
|
if (job is null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
Code: ErrorCode.INVALID_JOB,
|
ErrorCode.INVALID_JOB,
|
||||||
Errors: new string[] { "no such job" }),
|
"no such job"),
|
||||||
context: jobId.ToString());
|
context: jobId.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,9 +122,7 @@ public class Jobs {
|
|||||||
if (job is null) {
|
if (job is null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(ErrorCode.INVALID_JOB, "no such job"),
|
||||||
Code: ErrorCode.INVALID_JOB,
|
|
||||||
Errors: new string[] { "no such job" }),
|
|
||||||
context: jobId.ToString());
|
context: jobId.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ public class JinjaToScriban {
|
|||||||
_log.Info($"Migrated notification: {notification.NotificationId} to jinja");
|
_log.Info($"Migrated notification: {notification.NotificationId} to jinja");
|
||||||
} else {
|
} else {
|
||||||
failedNotificationIds.Add(notification.NotificationId);
|
failedNotificationIds.Add(notification.NotificationId);
|
||||||
_log.Error(new Error(ErrorCode.UNABLE_TO_UPDATE, new[] { r.ErrorV.Reason, r.ErrorV.Status.ToString() }));
|
_log.Error(Error.Create(ErrorCode.UNABLE_TO_UPDATE, r.ErrorV.Reason, r.ErrorV.Status.ToString()));
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
failedNotificationIds.Add(notification.NotificationId);
|
failedNotificationIds.Add(notification.NotificationId);
|
||||||
|
@ -38,9 +38,7 @@ public class Node {
|
|||||||
if (node is null) {
|
if (node is null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(ErrorCode.UNABLE_TO_FIND, "unable to find node"),
|
||||||
Code: ErrorCode.UNABLE_TO_FIND,
|
|
||||||
Errors: new string[] { "unable to find node" }),
|
|
||||||
context: machineId.ToString());
|
context: machineId.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,9 +92,7 @@ public class Node {
|
|||||||
if (node is null) {
|
if (node is null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(ErrorCode.UNABLE_TO_FIND, "unable to find node"),
|
||||||
Code: ErrorCode.UNABLE_TO_FIND,
|
|
||||||
Errors: new string[] { "unable to find node" }),
|
|
||||||
context: patch.MachineId.ToString());
|
context: patch.MachineId.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,9 +126,7 @@ public class Node {
|
|||||||
if (node is null) {
|
if (node is null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(ErrorCode.UNABLE_TO_FIND, "unable to find node"),
|
||||||
Code: ErrorCode.UNABLE_TO_FIND,
|
|
||||||
Errors: new string[] { "unable to find node" }),
|
|
||||||
context: post.MachineId.ToString());
|
context: post.MachineId.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,9 +160,7 @@ public class Node {
|
|||||||
if (node is null) {
|
if (node is null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(ErrorCode.UNABLE_TO_FIND, "unable to find node"),
|
||||||
Code: ErrorCode.UNABLE_TO_FIND,
|
|
||||||
new string[] { "unable to find node" }),
|
|
||||||
context: delete.MachineId.ToString());
|
context: delete.MachineId.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ public class NodeAddSshKey {
|
|||||||
if (node == null) {
|
if (node == null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(ErrorCode.UNABLE_TO_FIND, new[] { "unable to find node" }),
|
Error.Create(ErrorCode.UNABLE_TO_FIND, "unable to find node"),
|
||||||
$"{request.OkV.MachineId}");
|
$"{request.OkV.MachineId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,18 +61,18 @@ public class Notifications {
|
|||||||
var entries = await _context.NotificationOperations.SearchByPartitionKeys(new[] { $"{request.OkV.NotificationId}" }).ToListAsync();
|
var entries = await _context.NotificationOperations.SearchByPartitionKeys(new[] { $"{request.OkV.NotificationId}" }).ToListAsync();
|
||||||
|
|
||||||
if (entries.Count == 0) {
|
if (entries.Count == 0) {
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "unable to find notification" }), context: "notification delete");
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.INVALID_REQUEST, "unable to find notification"), context: "notification delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entries.Count > 1) {
|
if (entries.Count > 1) {
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "error identifying Notification" }), context: "notification delete");
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.INVALID_REQUEST, "error identifying Notification"), context: "notification delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await _context.NotificationOperations.Delete(entries[0]);
|
var result = await _context.NotificationOperations.Delete(entries[0]);
|
||||||
|
|
||||||
if (!result.IsOk) {
|
if (!result.IsOk) {
|
||||||
var (status, error) = result.ErrorV;
|
var (status, error) = result.ErrorV;
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.UNABLE_TO_UPDATE, new[] { error }), "notification delete");
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.UNABLE_TO_UPDATE, error), "notification delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = req.CreateResponse(HttpStatusCode.OK);
|
var response = req.CreateResponse(HttpStatusCode.OK);
|
||||||
|
@ -63,9 +63,7 @@ public class Pool {
|
|||||||
if (pool.IsOk) {
|
if (pool.IsOk) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(ErrorCode.INVALID_REQUEST, "pool with that name already exists"),
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
|
||||||
Errors: new string[] { "pool with that name already exists" }),
|
|
||||||
"PoolCreate");
|
"PoolCreate");
|
||||||
}
|
}
|
||||||
var newPool = await _context.PoolOperations.Create(name: create.Name, os: create.Os, architecture: create.Arch, managed: create.Managed, objectId: create.ObjectId);
|
var newPool = await _context.PoolOperations.Create(name: create.Name, os: create.Os, architecture: create.Arch, managed: create.Managed, objectId: create.ObjectId);
|
||||||
@ -89,9 +87,7 @@ public class Pool {
|
|||||||
if (!pool.IsOk) {
|
if (!pool.IsOk) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(ErrorCode.INVALID_REQUEST, "pool with that name does not exist"),
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
|
||||||
Errors: new string[] { "pool with that name does not exist" }),
|
|
||||||
"PoolUpdate");
|
"PoolUpdate");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,9 +96,7 @@ public class Pool {
|
|||||||
if (updatePool.IsOk) {
|
if (updatePool.IsOk) {
|
||||||
return await RequestHandling.Ok(req, await Populate(PoolToPoolResponse(updated), true));
|
return await RequestHandling.Ok(req, await Populate(PoolToPoolResponse(updated), true));
|
||||||
} else {
|
} else {
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.INVALID_REQUEST, updatePool.ErrorV.Reason), "PoolUpdate");
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
|
||||||
Errors: new string[] { updatePool.ErrorV.Reason }), "PoolUpdate");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ public class Proxy {
|
|||||||
machineId: machineId, dstPort: dstPort).ToListAsync();
|
machineId: machineId, dstPort: dstPort).ToListAsync();
|
||||||
|
|
||||||
if (!forwards.Any()) {
|
if (!forwards.Any()) {
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "no forwards for scaleset and node" }), "debug_proxy get");
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.INVALID_REQUEST, "no forwards for scaleset and node"), "debug_proxy get");
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = req.CreateResponse();
|
var response = req.CreateResponse();
|
||||||
@ -78,7 +78,7 @@ public class Proxy {
|
|||||||
await r.WriteAsJsonAsync(new ProxyList(proxies));
|
await r.WriteAsJsonAsync(new ProxyList(proxies));
|
||||||
return r;
|
return r;
|
||||||
default:
|
default:
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "ProxyGet must provide all or none of the following: scaleset_id, machine_id, dst_port" }), "debug_proxy get");
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.INVALID_REQUEST, "ProxyGet must provide all or none of the following: scaleset_id, machine_id, dst_port"), "debug_proxy get");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public class ReproVmss {
|
|||||||
var vm = await _context.ReproOperations.SearchByPartitionKeys(new[] { $"{request.OkV.VmId}" }).FirstOrDefaultAsync();
|
var vm = await _context.ReproOperations.SearchByPartitionKeys(new[] { $"{request.OkV.VmId}" }).FirstOrDefaultAsync();
|
||||||
|
|
||||||
if (vm == null) {
|
if (vm == null) {
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "no such VM" }), $"{request.OkV.VmId}");
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.INVALID_REQUEST, "no such VM"), $"{request.OkV.VmId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = req.CreateResponse(HttpStatusCode.OK);
|
var response = req.CreateResponse(HttpStatusCode.OK);
|
||||||
@ -98,7 +98,7 @@ public class ReproVmss {
|
|||||||
if (request.OkV.VmId == null) {
|
if (request.OkV.VmId == null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(ErrorCode.INVALID_REQUEST, new[] { "missing vm_id" }),
|
Error.Create(ErrorCode.INVALID_REQUEST, "missing vm_id"),
|
||||||
context: "repro delete");
|
context: "repro delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ public class ReproVmss {
|
|||||||
if (vm == null) {
|
if (vm == null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(ErrorCode.INVALID_REQUEST, new[] { "no such vm" }),
|
Error.Create(ErrorCode.INVALID_REQUEST, "no such vm"),
|
||||||
context: "repro delete");
|
context: "repro delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,9 +70,7 @@ public class Scaleset {
|
|||||||
if (!pool.Managed) {
|
if (!pool.Managed) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(ErrorCode.UNABLE_TO_CREATE, "scalesets can only be added to managed pools "),
|
||||||
Code: ErrorCode.UNABLE_TO_CREATE,
|
|
||||||
Errors: new string[] { "scalesets can only be added to managed pools " }),
|
|
||||||
context: "ScalesetCreate");
|
context: "ScalesetCreate");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,9 +94,7 @@ public class Scaleset {
|
|||||||
if (!validRegions.Contains(create.Region)) {
|
if (!validRegions.Contains(create.Region)) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(ErrorCode.UNABLE_TO_CREATE, "invalid region"),
|
||||||
Code: ErrorCode.UNABLE_TO_CREATE,
|
|
||||||
Errors: new string[] { "invalid region" }),
|
|
||||||
context: "ScalesetCreate");
|
context: "ScalesetCreate");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,9 +105,7 @@ public class Scaleset {
|
|||||||
if (!availableSkus.Contains(create.VmSku)) {
|
if (!availableSkus.Contains(create.VmSku)) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(ErrorCode.UNABLE_TO_CREATE, $"The specified VM SKU '{create.VmSku}' is not available in the location ${region}"),
|
||||||
Code: ErrorCode.UNABLE_TO_CREATE,
|
|
||||||
Errors: new string[] { $"The specified VM SKU '{create.VmSku}' is not available in the location ${region}" }),
|
|
||||||
context: "ScalesetCreate");
|
context: "ScalesetCreate");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,9 +136,9 @@ public class Scaleset {
|
|||||||
_log.WithHttpStatus(inserted.ErrorV).Error($"failed to insert new scaleset {scaleset.ScalesetId:Tag:ScalesetId}");
|
_log.WithHttpStatus(inserted.ErrorV).Error($"failed to insert new scaleset {scaleset.ScalesetId:Tag:ScalesetId}");
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
Code: ErrorCode.UNABLE_TO_CREATE,
|
ErrorCode.UNABLE_TO_CREATE,
|
||||||
new string[] { $"unable to insert scaleset: {inserted.ErrorV}" }
|
$"unable to insert scaleset: {inserted.ErrorV}"
|
||||||
),
|
),
|
||||||
context: "ScalesetCreate");
|
context: "ScalesetCreate");
|
||||||
}
|
}
|
||||||
@ -191,9 +185,9 @@ public class Scaleset {
|
|||||||
if (!scaleset.State.CanUpdate()) {
|
if (!scaleset.State.CanUpdate()) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
Errors: new[] { $"scaleset must be in one of the following states to update: {string.Join(", ", ScalesetStateHelper.CanUpdateStates)}" }),
|
$"scaleset must be in one of the following states to update: {string.Join(", ", ScalesetStateHelper.CanUpdateStates)}"),
|
||||||
"ScalesetUpdate");
|
"ScalesetUpdate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,9 +37,9 @@ public class Tasks {
|
|||||||
if (task == null) {
|
if (task == null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
new[] { "unable to find task" }),
|
"unable to find task"),
|
||||||
"task get");
|
"task get");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ public class Tasks {
|
|||||||
if (!checkConfig.IsOk) {
|
if (!checkConfig.IsOk) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(ErrorCode.INVALID_REQUEST, new[] { checkConfig.ErrorV.Error }),
|
Error.Create(ErrorCode.INVALID_REQUEST, checkConfig.ErrorV.Error),
|
||||||
"task create");
|
"task create");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,14 +115,14 @@ public class Tasks {
|
|||||||
if (job == null) {
|
if (job == null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(ErrorCode.INVALID_REQUEST, new[] { "unable to find job" }),
|
Error.Create(ErrorCode.INVALID_REQUEST, "unable to find job"),
|
||||||
cfg.JobId.ToString());
|
cfg.JobId.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (job.State != JobState.Enabled && job.State != JobState.Init) {
|
if (job.State != JobState.Enabled && job.State != JobState.Init) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(ErrorCode.UNABLE_TO_ADD_TASK_TO_JOB, new[] { $"unable to add a job in state {job.State}" }),
|
Error.Create(ErrorCode.UNABLE_TO_ADD_TASK_TO_JOB, $"unable to add a job in state {job.State}"),
|
||||||
cfg.JobId.ToString());
|
cfg.JobId.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ public class Tasks {
|
|||||||
if (prereq == null) {
|
if (prereq == null) {
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(ErrorCode.INVALID_REQUEST, new[] { "unable to find task " }),
|
Error.Create(ErrorCode.INVALID_REQUEST, "unable to find task "),
|
||||||
"task create prerequisite");
|
"task create prerequisite");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,8 +165,8 @@ public class Tasks {
|
|||||||
|
|
||||||
var task = await _context.TaskOperations.GetByTaskId(request.OkV.TaskId);
|
var task = await _context.TaskOperations.GetByTaskId(request.OkV.TaskId);
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "unable to find task"
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.INVALID_REQUEST, "unable to find task"
|
||||||
}), "task delete");
|
), "task delete");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public class WebhookLogs {
|
|||||||
var webhook = await _context.WebhookOperations.GetByWebhookId(request.OkV.WebhookId);
|
var webhook = await _context.WebhookOperations.GetByWebhookId(request.OkV.WebhookId);
|
||||||
|
|
||||||
if (webhook == null) {
|
if (webhook == null) {
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "unable to find webhook" }), "webhook log");
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.INVALID_REQUEST, "unable to find webhook"), "webhook log");
|
||||||
}
|
}
|
||||||
|
|
||||||
_log.Info($"getting webhook logs: {request.OkV.WebhookId:Tag:WebhookId}");
|
_log.Info($"getting webhook logs: {request.OkV.WebhookId:Tag:WebhookId}");
|
||||||
|
@ -36,7 +36,7 @@ public class WebhookPing {
|
|||||||
var webhook = await _context.WebhookOperations.GetByWebhookId(request.OkV.WebhookId);
|
var webhook = await _context.WebhookOperations.GetByWebhookId(request.OkV.WebhookId);
|
||||||
|
|
||||||
if (webhook == null) {
|
if (webhook == null) {
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "unable to find webhook" }), "webhook ping");
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.INVALID_REQUEST, "unable to find webhook"), "webhook ping");
|
||||||
}
|
}
|
||||||
|
|
||||||
_log.Info($"pinging webhook : {request.OkV.WebhookId:Tag:WebhookId}");
|
_log.Info($"pinging webhook : {request.OkV.WebhookId:Tag:WebhookId}");
|
||||||
|
@ -40,7 +40,7 @@ public class Webhooks {
|
|||||||
var webhook = await _context.WebhookOperations.GetByWebhookId(request.OkV.WebhookId.Value);
|
var webhook = await _context.WebhookOperations.GetByWebhookId(request.OkV.WebhookId.Value);
|
||||||
|
|
||||||
if (webhook == null) {
|
if (webhook == null) {
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "unable to find webhook" }), "webhook get");
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.INVALID_REQUEST, "unable to find webhook"), "webhook get");
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = req.CreateResponse(HttpStatusCode.OK);
|
var response = req.CreateResponse(HttpStatusCode.OK);
|
||||||
@ -73,7 +73,7 @@ public class Webhooks {
|
|||||||
var webhook = await _context.WebhookOperations.GetByWebhookId(request.OkV.WebhookId);
|
var webhook = await _context.WebhookOperations.GetByWebhookId(request.OkV.WebhookId);
|
||||||
|
|
||||||
if (webhook == null) {
|
if (webhook == null) {
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "unable to find webhook" }), "webhook update");
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.INVALID_REQUEST, "unable to find webhook"), "webhook update");
|
||||||
}
|
}
|
||||||
|
|
||||||
var updated = webhook with {
|
var updated = webhook with {
|
||||||
@ -134,7 +134,7 @@ public class Webhooks {
|
|||||||
var webhook = await _context.WebhookOperations.GetByWebhookId(request.OkV.WebhookId);
|
var webhook = await _context.WebhookOperations.GetByWebhookId(request.OkV.WebhookId);
|
||||||
|
|
||||||
if (webhook == null) {
|
if (webhook == null) {
|
||||||
return await _context.RequestHandling.NotOk(req, new Error(ErrorCode.INVALID_REQUEST, new[] { "unable to find webhook" }), "webhook delete");
|
return await _context.RequestHandling.NotOk(req, Error.Create(ErrorCode.INVALID_REQUEST, "unable to find webhook"), "webhook delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
var r = await _context.WebhookOperations.Delete(webhook);
|
var r = await _context.WebhookOperations.Delete(webhook);
|
||||||
|
@ -166,7 +166,10 @@ public record Proxy
|
|||||||
bool Outdated
|
bool Outdated
|
||||||
) : StatefulEntityBase<VmState>(State);
|
) : StatefulEntityBase<VmState>(State);
|
||||||
|
|
||||||
public record Error(ErrorCode Code, string[]? Errors = null) {
|
public record Error(ErrorCode Code, List<string>? Errors) {
|
||||||
|
public static Error Create(ErrorCode code, params string[] errors) {
|
||||||
|
return new Error(code, errors.ToList());
|
||||||
|
}
|
||||||
public sealed override string ToString() {
|
public sealed override string ToString() {
|
||||||
var errorsString = Errors != null ? string.Join("", Errors) : string.Empty;
|
var errorsString = Errors != null ? string.Join("", Errors) : string.Empty;
|
||||||
return $"Error {{ Code = {Code}, Errors = {errorsString} }}";
|
return $"Error {{ Code = {Code}, Errors = {errorsString} }}";
|
||||||
|
@ -49,7 +49,7 @@ namespace Microsoft.OneFuzz.Service {
|
|||||||
|
|
||||||
private OneFuzzResult(T_Ok ok) => (OkV, ErrorV, IsOk) = (ok, null, true);
|
private OneFuzzResult(T_Ok ok) => (OkV, ErrorV, IsOk) = (ok, null, true);
|
||||||
|
|
||||||
private OneFuzzResult(ErrorCode errorCode, string[] errors) => (OkV, ErrorV, IsOk) = (default, new Error(errorCode, errors), false);
|
private OneFuzzResult(ErrorCode errorCode, string[] errors) => (OkV, ErrorV, IsOk) = (default, new Error(errorCode, errors.ToList()), false);
|
||||||
|
|
||||||
private OneFuzzResult(Error err) => (OkV, ErrorV, IsOk) = (default, err, false);
|
private OneFuzzResult(Error err) => (OkV, ErrorV, IsOk) = (default, err, false);
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ namespace Microsoft.OneFuzz.Service {
|
|||||||
|
|
||||||
public OneFuzzResultVoid() => (ErrorV, IsOk) = (null, true);
|
public OneFuzzResultVoid() => (ErrorV, IsOk) = (null, true);
|
||||||
|
|
||||||
private OneFuzzResultVoid(ErrorCode errorCode, string[] errors) => (ErrorV, IsOk) = (new Error(errorCode, errors), false);
|
private OneFuzzResultVoid(ErrorCode errorCode, string[] errors) => (ErrorV, IsOk) = (new Error(errorCode, errors.ToList()), false);
|
||||||
|
|
||||||
private OneFuzzResultVoid(Error err) => (ErrorV, IsOk) = (err, false);
|
private OneFuzzResultVoid(Error err) => (ErrorV, IsOk) = (err, false);
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ namespace ApiService.TestHooks {
|
|||||||
|
|
||||||
if (config is null) {
|
if (config is null) {
|
||||||
_log.Error($"Instance config is null");
|
_log.Error($"Instance config is null");
|
||||||
Error err = new(ErrorCode.INVALID_REQUEST, new[] { "Instance config is null" });
|
Error err = Error.Create(ErrorCode.INVALID_REQUEST, "Instance config is null");
|
||||||
var resp = req.CreateResponse(HttpStatusCode.InternalServerError);
|
var resp = req.CreateResponse(HttpStatusCode.InternalServerError);
|
||||||
await resp.WriteAsJsonAsync(err);
|
await resp.WriteAsJsonAsync(err);
|
||||||
return resp;
|
return resp;
|
||||||
|
@ -10,7 +10,7 @@ using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
namespace ApiService.TestHooks {
|
namespace ApiService.TestHooks {
|
||||||
|
|
||||||
sealed record MarkTasks(Node node, Error? error);
|
sealed record MarkTasks(Node node, Error error);
|
||||||
|
|
||||||
public class NodeOperationsTestHooks {
|
public class NodeOperationsTestHooks {
|
||||||
private readonly ILogTracer _log;
|
private readonly ILogTracer _log;
|
||||||
|
@ -75,9 +75,9 @@ public class EndpointAuthorization : IEndpointAuthorization {
|
|||||||
|
|
||||||
return await _context.RequestHandling.NotOk(
|
return await _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
ErrorCode.UNAUTHORIZED,
|
ErrorCode.UNAUTHORIZED,
|
||||||
new string[] { reason ?? "Unrecognized agent" }
|
reason ?? "Unrecognized agent"
|
||||||
),
|
),
|
||||||
"token verification",
|
"token verification",
|
||||||
HttpStatusCode.Unauthorized
|
HttpStatusCode.Unauthorized
|
||||||
@ -92,9 +92,9 @@ public class EndpointAuthorization : IEndpointAuthorization {
|
|||||||
|
|
||||||
var config = await _context.ConfigOperations.Fetch();
|
var config = await _context.ConfigOperations.Fetch();
|
||||||
if (config is null) {
|
if (config is null) {
|
||||||
return new Error(
|
return Error.Create(
|
||||||
Code: ErrorCode.INVALID_CONFIGURATION,
|
ErrorCode.INVALID_CONFIGURATION,
|
||||||
Errors: new string[] { "no instance configuration found " });
|
"no instance configuration found ");
|
||||||
}
|
}
|
||||||
|
|
||||||
return CheckRequireAdminsImpl(config, tokenResult.OkV.UserInfo);
|
return CheckRequireAdminsImpl(config, tokenResult.OkV.UserInfo);
|
||||||
@ -117,9 +117,7 @@ public class EndpointAuthorization : IEndpointAuthorization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config.Admins is null) {
|
if (config.Admins is null) {
|
||||||
return new Error(
|
return Error.Create(ErrorCode.UNAUTHORIZED, "pool modification disabled ");
|
||||||
Code: ErrorCode.UNAUTHORIZED,
|
|
||||||
Errors: new string[] { "pool modification disabled " });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userInfo.ObjectId is Guid objectId) {
|
if (userInfo.ObjectId is Guid objectId) {
|
||||||
@ -127,13 +125,9 @@ public class EndpointAuthorization : IEndpointAuthorization {
|
|||||||
return OneFuzzResultVoid.Ok;
|
return OneFuzzResultVoid.Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Error(
|
return Error.Create(ErrorCode.UNAUTHORIZED, "not authorized to manage instance");
|
||||||
Code: ErrorCode.UNAUTHORIZED,
|
|
||||||
Errors: new string[] { "not authorized to manage instance" });
|
|
||||||
} else {
|
} else {
|
||||||
return new Error(
|
return Error.Create(ErrorCode.UNAUTHORIZED, "user had no Object ID");
|
||||||
Code: ErrorCode.UNAUTHORIZED,
|
|
||||||
Errors: new string[] { "user had no Object ID" });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,16 +151,12 @@ public class EndpointAuthorization : IEndpointAuthorization {
|
|||||||
var allowed = await membershipChecker.IsMember(rule.AllowedGroupsIds, memberId);
|
var allowed = await membershipChecker.IsMember(rule.AllowedGroupsIds, memberId);
|
||||||
if (!allowed) {
|
if (!allowed) {
|
||||||
_log.Error($"unauthorized access: {memberId:Tag:MemberId} is not authorized to access {path:Tag:Path}");
|
_log.Error($"unauthorized access: {memberId:Tag:MemberId} is not authorized to access {path:Tag:Path}");
|
||||||
return new Error(
|
return Error.Create(ErrorCode.UNAUTHORIZED, "not approved to use this endpoint");
|
||||||
Code: ErrorCode.UNAUTHORIZED,
|
|
||||||
Errors: new string[] { "not approved to use this endpoint" });
|
|
||||||
} else {
|
} else {
|
||||||
return OneFuzzResultVoid.Ok;
|
return OneFuzzResultVoid.Ok;
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
return new Error(
|
return Error.Create(ErrorCode.UNAUTHORIZED, "unable to interact with graph", ex.Message);
|
||||||
Code: ErrorCode.UNAUTHORIZED,
|
|
||||||
Errors: new string[] { "unable to interact with graph", ex.Message });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ public abstract record ImageReference {
|
|||||||
public static ImageReference MustParse(string image) {
|
public static ImageReference MustParse(string image) {
|
||||||
var result = TryParse(image);
|
var result = TryParse(image);
|
||||||
if (!result.IsOk) {
|
if (!result.IsOk) {
|
||||||
var msg = string.Join(", ", result.ErrorV.Errors ?? Array.Empty<string>());
|
var msg = result.ErrorV.Errors != null ? string.Join(", ", result.ErrorV.Errors) : string.Empty;
|
||||||
throw new ArgumentException(msg, nameof(image));
|
throw new ArgumentException(msg, nameof(image));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,18 +46,17 @@ public abstract record ImageReference {
|
|||||||
} else if (identifier.ResourceType == ImageResource.ResourceType) {
|
} else if (identifier.ResourceType == ImageResource.ResourceType) {
|
||||||
result = new Image(identifier);
|
result = new Image(identifier);
|
||||||
} else {
|
} else {
|
||||||
return new Error(
|
return Error.Create(
|
||||||
ErrorCode.INVALID_IMAGE,
|
ErrorCode.INVALID_IMAGE,
|
||||||
new[] { $"Unknown image resource type: {identifier.ResourceType}" });
|
$"Unknown image resource type: {identifier.ResourceType}");
|
||||||
}
|
}
|
||||||
} catch (FormatException) {
|
} catch (FormatException) {
|
||||||
// not an ARM identifier, try to parse a marketplace image:
|
// not an ARM identifier, try to parse a marketplace image:
|
||||||
var imageParts = image.Split(":");
|
var imageParts = image.Split(":");
|
||||||
// The python code would throw if more than 4 parts are found in the split
|
// The python code would throw if more than 4 parts are found in the split
|
||||||
if (imageParts.Length != 4) {
|
if (imageParts.Length != 4) {
|
||||||
return new Error(
|
return Error.Create(
|
||||||
Code: ErrorCode.INVALID_IMAGE,
|
ErrorCode.INVALID_IMAGE, $"Expected 4 ':' separated parts in '{image}'");
|
||||||
new[] { $"Expected 4 ':' separated parts in '{image}'" });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = new Marketplace(
|
result = new Marketplace(
|
||||||
@ -112,10 +111,10 @@ public abstract record ImageReference {
|
|||||||
if (resource.Value.Data.OSType is OperatingSystemTypes os) {
|
if (resource.Value.Data.OSType is OperatingSystemTypes os) {
|
||||||
return OneFuzzResult.Ok(Enum.Parse<Os>(os.ToString(), ignoreCase: true));
|
return OneFuzzResult.Ok(Enum.Parse<Os>(os.ToString(), ignoreCase: true));
|
||||||
} else {
|
} else {
|
||||||
return new Error(ErrorCode.INVALID_IMAGE, new[] { "Specified image had no OSType" });
|
return Error.Create(ErrorCode.INVALID_IMAGE, "Specified image had no OSType");
|
||||||
}
|
}
|
||||||
} catch (Exception ex) when (ex is RequestFailedException) {
|
} catch (Exception ex) when (ex is RequestFailedException) {
|
||||||
return new Error(ErrorCode.INVALID_IMAGE, new[] { ex.ToString() });
|
return Error.Create(ErrorCode.INVALID_IMAGE, ex.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,10 +128,10 @@ public abstract record ImageReference {
|
|||||||
if (resource.Value.Data.OSType is OperatingSystemTypes os) {
|
if (resource.Value.Data.OSType is OperatingSystemTypes os) {
|
||||||
return OneFuzzResult.Ok(Enum.Parse<Os>(os.ToString(), ignoreCase: true));
|
return OneFuzzResult.Ok(Enum.Parse<Os>(os.ToString(), ignoreCase: true));
|
||||||
} else {
|
} else {
|
||||||
return new Error(ErrorCode.INVALID_IMAGE, new[] { "Specified image had no OSType" });
|
return Error.Create(ErrorCode.INVALID_IMAGE, "Specified image had no OSType");
|
||||||
}
|
}
|
||||||
} catch (Exception ex) when (ex is RequestFailedException) {
|
} catch (Exception ex) when (ex is RequestFailedException) {
|
||||||
return new Error(ErrorCode.INVALID_IMAGE, new[] { ex.ToString() });
|
return Error.Create(ErrorCode.INVALID_IMAGE, ex.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,10 +144,10 @@ public abstract record ImageReference {
|
|||||||
if (resource.Value.Data.OSType is OperatingSystemTypes os) {
|
if (resource.Value.Data.OSType is OperatingSystemTypes os) {
|
||||||
return OneFuzzResult.Ok(Enum.Parse<Os>(os.ToString(), ignoreCase: true));
|
return OneFuzzResult.Ok(Enum.Parse<Os>(os.ToString(), ignoreCase: true));
|
||||||
} else {
|
} else {
|
||||||
return new Error(ErrorCode.INVALID_IMAGE, new[] { "Specified image had no OSType" });
|
return Error.Create(ErrorCode.INVALID_IMAGE, "Specified image had no OSType");
|
||||||
}
|
}
|
||||||
} catch (Exception ex) when (ex is RequestFailedException) {
|
} catch (Exception ex) when (ex is RequestFailedException) {
|
||||||
return new Error(ErrorCode.INVALID_IMAGE, new[] { ex.ToString() });
|
return Error.Create(ErrorCode.INVALID_IMAGE, ex.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,10 +161,10 @@ public abstract record ImageReference {
|
|||||||
if (resource.Value.Data.OSType is OperatingSystemTypes os) {
|
if (resource.Value.Data.OSType is OperatingSystemTypes os) {
|
||||||
return OneFuzzResult.Ok(Enum.Parse<Os>(os.ToString(), ignoreCase: true));
|
return OneFuzzResult.Ok(Enum.Parse<Os>(os.ToString(), ignoreCase: true));
|
||||||
} else {
|
} else {
|
||||||
return new Error(ErrorCode.INVALID_IMAGE, new[] { "Specified image had no OSType" });
|
return Error.Create(ErrorCode.INVALID_IMAGE, "Specified image had no OSType");
|
||||||
}
|
}
|
||||||
} catch (Exception ex) when (ex is RequestFailedException) {
|
} catch (Exception ex) when (ex is RequestFailedException) {
|
||||||
return new Error(ErrorCode.INVALID_IMAGE, new[] { ex.ToString() });
|
return Error.Create(ErrorCode.INVALID_IMAGE, ex.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,7 +177,7 @@ public abstract record ImageReference {
|
|||||||
var os = resource.Value.Data.StorageProfile.OSDisk.OSType.ToString();
|
var os = resource.Value.Data.StorageProfile.OSDisk.OSType.ToString();
|
||||||
return OneFuzzResult.Ok(Enum.Parse<Os>(os.ToString(), ignoreCase: true));
|
return OneFuzzResult.Ok(Enum.Parse<Os>(os.ToString(), ignoreCase: true));
|
||||||
} catch (Exception ex) when (ex is RequestFailedException) {
|
} catch (Exception ex) when (ex is RequestFailedException) {
|
||||||
return new Error(ErrorCode.INVALID_IMAGE, new[] { ex.ToString() });
|
return Error.Create(ErrorCode.INVALID_IMAGE, ex.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ public class JobOperations : StatefulOrm<Job, JobState, JobOperations>, IJobOper
|
|||||||
|
|
||||||
await foreach (var job in QueryAsync(filter)) {
|
await foreach (var job in QueryAsync(filter)) {
|
||||||
await foreach (var task in _context.TaskOperations.QueryAsync(Query.PartitionKey(job.JobId.ToString()))) {
|
await foreach (var task in _context.TaskOperations.QueryAsync(Query.PartitionKey(job.JobId.ToString()))) {
|
||||||
await _context.TaskOperations.MarkFailed(task, new Error(ErrorCode.TASK_FAILED, new[] { "job never not start" }));
|
await _context.TaskOperations.MarkFailed(task, Error.Create(ErrorCode.TASK_FAILED, "job never not start"));
|
||||||
}
|
}
|
||||||
_logTracer.Info($"stopping job that never started: {job.JobId:Tag:JobId}");
|
_logTracer.Info($"stopping job that never started: {job.JobId:Tag:JobId}");
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ public interface INodeOperations : IStatefulOrm<Node, NodeState> {
|
|||||||
|
|
||||||
IAsyncEnumerable<Node> GetDeadNodes(Guid scaleSetId, TimeSpan expirationPeriod);
|
IAsyncEnumerable<Node> GetDeadNodes(Guid scaleSetId, TimeSpan expirationPeriod);
|
||||||
|
|
||||||
Async.Task MarkTasksStoppedEarly(Node node, Error? error = null);
|
Async.Task MarkTasksStoppedEarly(Node node, Error? error);
|
||||||
static readonly TimeSpan NODE_EXPIRATION_TIME = TimeSpan.FromHours(1.0);
|
static readonly TimeSpan NODE_EXPIRATION_TIME = TimeSpan.FromHours(1.0);
|
||||||
static readonly TimeSpan NODE_REIMAGE_TIME = TimeSpan.FromDays(6.0);
|
static readonly TimeSpan NODE_REIMAGE_TIME = TimeSpan.FromDays(6.0);
|
||||||
|
|
||||||
@ -213,18 +213,18 @@ public class NodeOperations : StatefulOrm<Node, NodeState, NodeOperations>, INod
|
|||||||
|
|
||||||
var scaleset = scalesetResult.OkV;
|
var scaleset = scalesetResult.OkV;
|
||||||
if (!scaleset.State.IsAvailable()) {
|
if (!scaleset.State.IsAvailable()) {
|
||||||
return CanProcessNewWorkResponse.NotAllowed($"scaleset not available for work. Scaleset state '{scaleset.State}'"); ;
|
return CanProcessNewWorkResponse.NotAllowed($"scaleset not available for work. Scaleset state '{scaleset.State}'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var poolResult = await _context.PoolOperations.GetByName(node.PoolName);
|
var poolResult = await _context.PoolOperations.GetByName(node.PoolName);
|
||||||
if (!poolResult.IsOk) {
|
if (!poolResult.IsOk) {
|
||||||
return CanProcessNewWorkResponse.NotAllowed("invalid pool"); ;
|
return CanProcessNewWorkResponse.NotAllowed("invalid pool");
|
||||||
}
|
}
|
||||||
|
|
||||||
var pool = poolResult.OkV;
|
var pool = poolResult.OkV;
|
||||||
if (!PoolStateHelper.Available.Contains(pool.State)) {
|
if (!PoolStateHelper.Available.Contains(pool.State)) {
|
||||||
return CanProcessNewWorkResponse.NotAllowed("pool is not available for work"); ;
|
return CanProcessNewWorkResponse.NotAllowed("pool is not available for work");
|
||||||
}
|
}
|
||||||
|
|
||||||
return CanProcessNewWorkResponse.Allowed();
|
return CanProcessNewWorkResponse.Allowed();
|
||||||
@ -585,14 +585,19 @@ public class NodeOperations : StatefulOrm<Node, NodeState, NodeOperations>, INod
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Async.Task MarkTasksStoppedEarly(Node node, Error? error = null) {
|
public async Async.Task MarkTasksStoppedEarly(Node node, Error? error) {
|
||||||
if (error is null) {
|
|
||||||
error = new Error(ErrorCode.TASK_FAILED, new[] { $"node reimaged during task execution. machine_id: {node.MachineId}" });
|
|
||||||
}
|
|
||||||
|
|
||||||
await foreach (var entry in _context.NodeTasksOperations.GetByMachineId(node.MachineId)) {
|
await foreach (var entry in _context.NodeTasksOperations.GetByMachineId(node.MachineId)) {
|
||||||
var task = await _context.TaskOperations.GetByTaskId(entry.TaskId);
|
var task = await _context.TaskOperations.GetByTaskId(entry.TaskId);
|
||||||
if (task is not null) {
|
if (task is not null && !TaskStateHelper.ShuttingDown(task.State)) {
|
||||||
|
var message = $"Node {node.MachineId} stopping while the task state is '{task.State}'";
|
||||||
|
if (error is not null) {
|
||||||
|
if (error.Errors == null) {
|
||||||
|
error = error with { Errors = new List<string>() };
|
||||||
|
}
|
||||||
|
error.Errors.Add(message);
|
||||||
|
} else {
|
||||||
|
error = Error.Create(ErrorCode.TASK_FAILED, message);
|
||||||
|
}
|
||||||
await _context.TaskOperations.MarkFailed(task, error);
|
await _context.TaskOperations.MarkFailed(task, error);
|
||||||
}
|
}
|
||||||
if (!node.DebugKeepNode) {
|
if (!node.DebugKeepNode) {
|
||||||
@ -605,7 +610,7 @@ public class NodeOperations : StatefulOrm<Node, NodeState, NodeOperations>, INod
|
|||||||
}
|
}
|
||||||
|
|
||||||
public new async Async.Task Delete(Node node) {
|
public new async Async.Task Delete(Node node) {
|
||||||
await MarkTasksStoppedEarly(node);
|
await MarkTasksStoppedEarly(node, Error.Create(ErrorCode.INVALID_NODE, "node is being deleted"));
|
||||||
await _context.NodeTasksOperations.ClearByMachineId(node.MachineId);
|
await _context.NodeTasksOperations.ClearByMachineId(node.MachineId);
|
||||||
await _context.NodeMessageOperations.ClearMessages(node.MachineId);
|
await _context.NodeMessageOperations.ClearMessages(node.MachineId);
|
||||||
var r = await base.Delete(node);
|
var r = await base.Delete(node);
|
||||||
|
@ -37,15 +37,14 @@ namespace Microsoft.OneFuzz.Service {
|
|||||||
public async Async.Task<OneFuzzResult<bool>> AssociateSubnet(string name, VirtualNetworkResource vnet, SubnetResource subnet) {
|
public async Async.Task<OneFuzzResult<bool>> AssociateSubnet(string name, VirtualNetworkResource vnet, SubnetResource subnet) {
|
||||||
var nsg = await GetNsg(name);
|
var nsg = await GetNsg(name);
|
||||||
if (nsg == null) {
|
if (nsg == null) {
|
||||||
return OneFuzzResult<bool>.Error(new Error(ErrorCode.UNABLE_TO_FIND,
|
return OneFuzzResult<bool>.Error(Error.Create(ErrorCode.UNABLE_TO_FIND,
|
||||||
new[] { $"cannot associate subnet. nsg {name} not found" }));
|
$"cannot associate subnet. nsg {name} not found"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nsg.Data.Location != vnet.Data.Location) {
|
if (nsg.Data.Location != vnet.Data.Location) {
|
||||||
return OneFuzzResult<bool>.Error(new Error(ErrorCode.UNABLE_TO_UPDATE,
|
return OneFuzzResult<bool>.Error(Error.Create(ErrorCode.UNABLE_TO_UPDATE,
|
||||||
new[] {
|
|
||||||
$"subnet and nsg have to be in the same region. nsg {nsg.Data.Name} {nsg.Data.Location}, subnet: {subnet.Data.Name} {subnet.Data}"
|
$"subnet and nsg have to be in the same region. nsg {nsg.Data.Name} {nsg.Data.Location}, subnet: {subnet.Data.Name} {subnet.Data}"
|
||||||
}));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subnet.Data.NetworkSecurityGroup != null && subnet.Data.NetworkSecurityGroup.Id == nsg.Id) {
|
if (subnet.Data.NetworkSecurityGroup != null && subnet.Data.NetworkSecurityGroup.Id == nsg.Id) {
|
||||||
|
@ -212,8 +212,8 @@ public class ProxyOperations : StatefulOrm<Proxy, VmState, ProxyOperations>, IPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async System.Threading.Tasks.Task<Proxy> SetProvisionFailed(Proxy proxy, VirtualMachineInstanceView? instanceView) {
|
private async System.Threading.Tasks.Task<Proxy> SetProvisionFailed(Proxy proxy, VirtualMachineInstanceView? instanceView) {
|
||||||
var errors = GetErrors(proxy, instanceView).ToArray();
|
var errors = GetErrors(proxy, instanceView);
|
||||||
return await SetFailed(proxy, new Error(ErrorCode.PROXY_FAILED, errors));
|
return await SetFailed(proxy, new Error(ErrorCode.PROXY_FAILED, errors.ToList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Proxy> SetFailed(Proxy proxy, Error error) {
|
private async Task<Proxy> SetFailed(Proxy proxy, Error error) {
|
||||||
@ -259,7 +259,7 @@ public class ProxyOperations : StatefulOrm<Proxy, VmState, ProxyOperations>, IPr
|
|||||||
var vm = GetVm(proxy, config);
|
var vm = GetVm(proxy, config);
|
||||||
var vmData = await _context.VmOperations.GetVm(vm.Name);
|
var vmData = await _context.VmOperations.GetVm(vm.Name);
|
||||||
if (vmData is null) {
|
if (vmData is null) {
|
||||||
return await SetFailed(proxy, new Error(ErrorCode.PROXY_FAILED, new[] { "azure not able to find vm" }));
|
return await SetFailed(proxy, Error.Create(ErrorCode.PROXY_FAILED, "azure not able to find vm"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vmData.ProvisioningState == "Failed") {
|
if (vmData.ProvisioningState == "Failed") {
|
||||||
|
@ -180,9 +180,9 @@ public class ReproOperations : StatefulOrm<Repro, VmState, ReproOperations>, IRe
|
|||||||
if (vmData == null) {
|
if (vmData == null) {
|
||||||
return await _context.ReproOperations.SetError(
|
return await _context.ReproOperations.SetError(
|
||||||
repro,
|
repro,
|
||||||
new Error(
|
Error.Create(
|
||||||
ErrorCode.VM_CREATE_FAILED,
|
ErrorCode.VM_CREATE_FAILED,
|
||||||
new string[] { "failed before launching extensions" }));
|
"failed before launching extensions"));
|
||||||
}
|
}
|
||||||
if (vmData.ProvisioningState == "Failed") {
|
if (vmData.ProvisioningState == "Failed") {
|
||||||
var failedVmData = await _context.VmOperations.GetVmWithInstanceView(vm.Name);
|
var failedVmData = await _context.VmOperations.GetVmWithInstanceView(vm.Name);
|
||||||
@ -232,7 +232,7 @@ public class ReproOperations : StatefulOrm<Repro, VmState, ReproOperations>, IRe
|
|||||||
repro,
|
repro,
|
||||||
new Error(
|
new Error(
|
||||||
ErrorCode.VM_CREATE_FAILED,
|
ErrorCode.VM_CREATE_FAILED,
|
||||||
errors));
|
errors.ToList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<OneFuzzResultVoid> BuildReproScript(Repro repro) {
|
public async Task<OneFuzzResultVoid> BuildReproScript(Repro repro) {
|
||||||
|
@ -98,9 +98,9 @@ public class RequestHandling : IRequestHandling {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (errors.Any()) {
|
if (errors.Any()) {
|
||||||
return new Error(
|
return Error.Create(
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
Errors: errors.ToArray());
|
errors.ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,9 +109,9 @@ public class RequestHandling : IRequestHandling {
|
|||||||
if (Validator.TryValidateObject(t, validationContext, validationResults, validateAllProperties: true)) {
|
if (Validator.TryValidateObject(t, validationContext, validationResults, validateAllProperties: true)) {
|
||||||
return OneFuzzResult.Ok(t);
|
return OneFuzzResult.Ok(t);
|
||||||
} else {
|
} else {
|
||||||
return new Error(
|
return Error.Create(
|
||||||
Code: ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
Errors: validationResults.Select(vr => vr.ToString()).ToArray());
|
validationResults.Select(vr => vr.ToString()).ToArray());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return OneFuzzResult<T>.Error(
|
return OneFuzzResult<T>.Error(
|
||||||
@ -154,13 +154,12 @@ public class RequestHandling : IRequestHandling {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Error(
|
return Error.Create(
|
||||||
ErrorCode.INVALID_REQUEST,
|
ErrorCode.INVALID_REQUEST,
|
||||||
new string[] {
|
|
||||||
exception.Message,
|
exception.Message,
|
||||||
exception.Source ?? string.Empty,
|
exception.Source ?? string.Empty,
|
||||||
exception.StackTrace ?? string.Empty
|
exception.StackTrace ?? string.Empty
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +291,7 @@ public class ScalesetOperations : StatefulOrm<Scaleset, ScalesetState, ScalesetO
|
|||||||
|
|
||||||
if (scaleset.Auth is null) {
|
if (scaleset.Auth is null) {
|
||||||
_logTracer.Error($"Scaleset Auth is missing for scaleset {scaleset.ScalesetId:Tag:ScalesetId}");
|
_logTracer.Error($"Scaleset Auth is missing for scaleset {scaleset.ScalesetId:Tag:ScalesetId}");
|
||||||
return await SetFailed(scaleset, new Error(ErrorCode.UNABLE_TO_CREATE, new[] { "missing required auth" }));
|
return await SetFailed(scaleset, Error.Create(ErrorCode.UNABLE_TO_CREATE, "missing required auth"));
|
||||||
}
|
}
|
||||||
|
|
||||||
var vmss = await _context.VmssOperations.GetVmss(scaleset.ScalesetId);
|
var vmss = await _context.VmssOperations.GetVmss(scaleset.ScalesetId);
|
||||||
@ -455,7 +455,7 @@ public class ScalesetOperations : StatefulOrm<Scaleset, ScalesetState, ScalesetO
|
|||||||
return await SetFailed(scaleset, imageOsResult.ErrorV);
|
return await SetFailed(scaleset, imageOsResult.ErrorV);
|
||||||
} else if (imageOsResult.OkV != pool.Os) {
|
} else if (imageOsResult.OkV != pool.Os) {
|
||||||
_logTracer.Error($"got invalid OS: {imageOsResult.OkV:Tag:ActualOs} for scaleset: {scaleset.ScalesetId:Tag:ScalesetId} expected OS {pool.Os:Tag:ExpectedOs}");
|
_logTracer.Error($"got invalid OS: {imageOsResult.OkV:Tag:ActualOs} for scaleset: {scaleset.ScalesetId:Tag:ScalesetId} expected OS {pool.Os:Tag:ExpectedOs}");
|
||||||
return await SetFailed(scaleset, new Error(ErrorCode.INVALID_REQUEST, new[] { $"invalid os (got: {imageOsResult.OkV} needed: {pool.Os})" }));
|
return await SetFailed(scaleset, Error.Create(ErrorCode.INVALID_REQUEST, $"invalid os (got: {imageOsResult.OkV} needed: {pool.Os})"));
|
||||||
} else {
|
} else {
|
||||||
return await SetState(scaleset, ScalesetState.Setup);
|
return await SetState(scaleset, ScalesetState.Setup);
|
||||||
}
|
}
|
||||||
@ -605,7 +605,7 @@ public class ScalesetOperations : StatefulOrm<Scaleset, ScalesetState, ScalesetO
|
|||||||
|
|
||||||
_log.Info($"{errorMessage} {deadNode.MachineId:Tag:MachineId} {deadNode.ScalesetId:Tag:ScalesetId}");
|
_log.Info($"{errorMessage} {deadNode.MachineId:Tag:MachineId} {deadNode.ScalesetId:Tag:ScalesetId}");
|
||||||
|
|
||||||
var error = new Error(ErrorCode.TASK_FAILED, new[] { $"{errorMessage} scaleset_id {deadNode.ScalesetId} last heartbeat:{deadNode.Heartbeat}" });
|
var error = Error.Create(ErrorCode.TASK_FAILED, $"{errorMessage} scaleset_id {deadNode.ScalesetId} last heartbeat:{deadNode.Heartbeat}");
|
||||||
await _context.NodeOperations.MarkTasksStoppedEarly(deadNode, error);
|
await _context.NodeOperations.MarkTasksStoppedEarly(deadNode, error);
|
||||||
toReimage[deadNode.MachineId] = await _context.NodeOperations.ToReimage(deadNode, true);
|
toReimage[deadNode.MachineId] = await _context.NodeOperations.ToReimage(deadNode, true);
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ public class TaskOperations : StatefulOrm<Task, TaskState, TaskOperations>, ITas
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!task.State.HasStarted()) {
|
if (!task.State.HasStarted()) {
|
||||||
await MarkFailed(task, new Error(Code: ErrorCode.TASK_FAILED, Errors: new[] { "task never started" }));
|
await MarkFailed(task, Error.Create(ErrorCode.TASK_FAILED, "task never started"));
|
||||||
} else {
|
} else {
|
||||||
_ = await SetState(task, TaskState.Stopping);
|
_ = await SetState(task, TaskState.Stopping);
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ public class TaskOperations : StatefulOrm<Task, TaskState, TaskOperations>, ITas
|
|||||||
foreach (var t in taskInJob) {
|
foreach (var t in taskInJob) {
|
||||||
if (t.Config.PrereqTasks != null) {
|
if (t.Config.PrereqTasks != null) {
|
||||||
if (t.Config.PrereqTasks.Contains(task.TaskId)) {
|
if (t.Config.PrereqTasks.Contains(task.TaskId)) {
|
||||||
await MarkFailed(t, new Error(ErrorCode.TASK_FAILED, new[] { $"prerequisite task failed. task_id:{t.TaskId}" }), taskInJob);
|
await MarkFailed(t, Error.Create(ErrorCode.TASK_FAILED, $"prerequisite task failed. task_id:{t.TaskId}"), taskInJob);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,7 +264,7 @@ public class TaskOperations : StatefulOrm<Task, TaskState, TaskOperations>, ITas
|
|||||||
|
|
||||||
// if a prereq task fails, then mark this task as failed
|
// if a prereq task fails, then mark this task as failed
|
||||||
if (t == null) {
|
if (t == null) {
|
||||||
await MarkFailed(task, new Error(ErrorCode.INVALID_REQUEST, Errors: new[] { "unable to find prereq task" }));
|
await MarkFailed(task, Error.Create(ErrorCode.INVALID_REQUEST, "unable to find prereq task"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ public class VmssOperations : IVmssOperations {
|
|||||||
try {
|
try {
|
||||||
return OneFuzzResult.Ok(await GetInstanceIdForVmId(name, vmId));
|
return OneFuzzResult.Ok(await GetInstanceIdForVmId(name, vmId));
|
||||||
} catch {
|
} catch {
|
||||||
return new Error(ErrorCode.UNABLE_TO_FIND, new string[] { $"unable to find scaleset machine: {name}:{vmId}" });
|
return Error.Create(ErrorCode.UNABLE_TO_FIND, $"unable to find scaleset machine: {name}:{vmId}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ public class JinjaTemplateAdapter {
|
|||||||
new List<TaskDebugFlag> { TaskDebugFlag.KeepNodeOnCompletion },
|
new List<TaskDebugFlag> { TaskDebugFlag.KeepNodeOnCompletion },
|
||||||
true
|
true
|
||||||
),
|
),
|
||||||
new Error(ErrorCode.UNABLE_TO_FIND, new string[] { "some error message" }),
|
Error.Create(ErrorCode.UNABLE_TO_FIND, "some error message"),
|
||||||
new Authentication("password", "public key", "private key"),
|
new Authentication("password", "public key", "private key"),
|
||||||
DateTimeOffset.UtcNow,
|
DateTimeOffset.UtcNow,
|
||||||
DateTimeOffset.UtcNow,
|
DateTimeOffset.UtcNow,
|
||||||
|
@ -17,7 +17,7 @@ public abstract class NotificationsBase {
|
|||||||
|
|
||||||
public async Async.Task LogFailedNotification(Report report, Exception error, Guid notificationId) {
|
public async Async.Task LogFailedNotification(Report report, Exception error, Guid notificationId) {
|
||||||
_logTracer.Error($"notification failed: notification_id:{notificationId:Tag:NotificationId} job_id:{report.JobId:Tag:JobId} task_id:{report.TaskId:Tag:TaskId} err:{error.Message:Tag:Error}");
|
_logTracer.Error($"notification failed: notification_id:{notificationId:Tag:NotificationId} job_id:{report.JobId:Tag:JobId} task_id:{report.TaskId:Tag:TaskId} err:{error.Message:Tag:Error}");
|
||||||
Error? err = new Error(ErrorCode.NOTIFICATION_FAILURE, new string[] { $"{error}" });
|
Error? err = Error.Create(ErrorCode.NOTIFICATION_FAILURE, $"{error}");
|
||||||
await _context.Events.SendEvent(new EventNotificationFailed(
|
await _context.Events.SendEvent(new EventNotificationFailed(
|
||||||
NotificationId: notificationId,
|
NotificationId: notificationId,
|
||||||
JobId: report.JobId,
|
JobId: report.JobId,
|
||||||
|
@ -36,9 +36,9 @@ sealed class TestEndpointAuthorization : EndpointAuthorization {
|
|||||||
|
|
||||||
return _context.RequestHandling.NotOk(
|
return _context.RequestHandling.NotOk(
|
||||||
req,
|
req,
|
||||||
new Error(
|
Error.Create(
|
||||||
ErrorCode.UNAUTHORIZED,
|
ErrorCode.UNAUTHORIZED,
|
||||||
new string[] { "Unrecognized agent" }
|
"Unrecognized agent"
|
||||||
),
|
),
|
||||||
"token verification",
|
"token verification",
|
||||||
HttpStatusCode.Unauthorized
|
HttpStatusCode.Unauthorized
|
||||||
|
Reference in New Issue
Block a user