blob: aadb63672688e0b058a5128e9c5848a4485f0916 [file] [log] [blame]
// Copyright 2022 The LUCI Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
syntax = "proto3";
package swarming.v2;
option go_package = "go.chromium.org/luci/swarming/proto/api_v2;apipb";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "google/rpc/status.proto";
service Bots {
// GetBot returns information on a single bot
rpc GetBot(BotRequest) returns (BotInfo);
// DeleteBot makes Swarming forget about a single bot.
//
// This includes the event history, task history and current state (dimensions,
// cache state, etc). Once deleted, Swarming will not send tasks to this bot.
// A still running bot will fininsh executing its task and then not have any
// further tasks queued on it.
//
// For non-GCE-Provider bots, this does not remove any data on the bot
// machine itself, and if the bot is still running on that machine, it will
// likely show up again in swarming shortly after calling this API.
//
// If this bot is managed with GCE Provider, the underlying VM will be recycled
// and all data on that VM will be lost.
//
// If you wish to shut the bot down, call TerminateBot.
rpc DeleteBot(BotRequest) returns (DeleteResponse);
// ListBotEvents returns a section of the Events (limited in quantity, time range)
// related to a single Bot.
//
// The bot in question must still be 'known' to Swarming.
rpc ListBotEvents(BotEventsRequest) returns (BotEventsResponse);
// TerminateBot asks a bot to terminate itself gracefully.
// The bot will stay in the DB, use 'delete' to remove it from the DB
// afterward. This request returns a pseudo-taskid that can be waited for to
// wait for the bot to turn down.
// This command is particularly useful when a privileged user needs to safely
// debug a machine specific issue. The user can trigger a terminate for one of
// the bot exhibiting the issue, wait for the pseudo-task to run then access
// the machine with the guarantee that the bot is not running anymore.
rpc TerminateBot(TerminateRequest) returns (TerminateResponse);
// ListBotTasks returns a section of the Task history (limited in quantity, time
// range) in the context of a single bot.
//
// The bot in question must still be 'known' to Swarming.
rpc ListBotTasks(BotTasksRequest) returns (TaskListResponse);
// ListBots returns the state of a filtered (dimensions, state) list of known bots.
rpc ListBots(BotsRequest) returns (BotInfoListResponse);
// CountBots returns the number of bots which match given set of filters.
rpc CountBots(BotsCountRequest) returns (BotsCount);
// GetBotDimensions returns a list of known dimensions/values for bots currently
// connected to a given pool.
rpc GetBotDimensions(BotsDimensionsRequest) returns (BotsDimensions);
}
service Tasks {
// GetResult reports the result of the task corresponding to a task ID.
// It can be a 'run' ID specifying a specific retry or a 'summary' ID hidding
// the fact that a task may have been retried transparently, when a bot reports
// BOT_DIED.
// A summary ID ends with '0', a run ID ends with '1' or '2'.
//
// TODO(vadimsh): Require the summary ID ending with '0'.
rpc GetResult(TaskIdWithPerfRequest) returns (TaskResultResponse);
// BatchGetResult returns results of many tasks at once.
rpc BatchGetResult(BatchGetResultRequest) returns (BatchGetResultResponse);
// GetRequest returns the task request corresponding to a task ID.
rpc GetRequest(TaskIdRequest) returns (TaskRequestResponse);
// CancelTask cancels a task. If a bot was running the task, the bot will forcibly cancel the task.
rpc CancelTask(TaskCancelRequest) returns (CancelResponse);
// GetStdout returns the output of the task corresponding to a task ID.
rpc GetStdout(TaskIdWithOffsetRequest) returns (TaskOutputResponse);
// NewTask creates a new task.
// The task will be enqueued in the tasks list and will be executed at the
// earliest opportunity by a bot that has at least the dimensions as described
// in the task request.
rpc NewTask(NewTaskRequest) returns (TaskRequestMetadataResponse);
// ListTasks returns full task results based on the filters.
// This endpoint is significantly slower than 'count'. Use 'count' when
// possible. If you just want the state of tasks, use 'get_states'.
rpc ListTasks(TasksWithPerfRequest) returns (TaskListResponse);
// ListTaskStates returns task state for a specific set of tasks."""
rpc ListTaskStates(TaskStatesRequest) returns (TaskStates);
// GetTaskRequests returns the task request corresponding to a task ID.
rpc ListTaskRequests(TasksRequest) returns (TaskRequestsResponse);
// CancelTasks cancels a subset of pending tasks based on the tags.
// Cancellation happens asynchronously, so when this call returns,
// cancellations will not have completed yet.
rpc CancelTasks(TasksCancelRequest) returns (TasksCancelResponse);
// CountTasks returns the number of tasks in a given state."""
rpc CountTasks(TasksCountRequest) returns (TasksCount);
}
service Swarming {
// GetDetails returns public information about the Swarming instance.
rpc GetDetails(google.protobuf.Empty) returns (ServerDetails);
// GetToken returns a token to bootstrap a new bot.
rpc GetToken(google.protobuf.Empty) returns (BootstrapToken);
// GetPermissions returns the caller's permissions.
rpc GetPermissions(PermissionsRequest) returns (ClientPermissions);
}
// Enums
// Use one of the values in this enum to query for tasks in one of the
// specified state.
//
// Use 'ALL' to not use any filtering based on task state.
//
// As an example, this enum enables querying for all tasks with state COMPLETED
// but non-zero exit code via COMPLETED_FAILURE.
//
// Do not confuse StateQuery and TaskState. StateQuery is to query tasks
// via the API. TaskState is the current task state.
enum StateQuery {
// Query for all tasks currently TaskState.PENDING.
QUERY_PENDING = 0;
// Query for all tasks currently TaskState.RUNNING. This includes tasks
// currently in the overhead phase; mapping input files or archiving outputs
// back to the server.
QUERY_RUNNING = 1;
// Query for all tasks currently TaskState.PENDING or TaskState.RUNNING. This
// is the query for the 'active' tasks.
QUERY_PENDING_RUNNING = 2;
// Query for all tasks that completed normally as TaskState.COMPLETED,
// independent of the process exit code.
QUERY_COMPLETED = 3;
// Query for all tasks that completed normally as TaskState.COMPLETED and that
// had exit code 0.
QUERY_COMPLETED_SUCCESS = 4;
// Query for all tasks that completed normally as TaskState.COMPLETED and that
// had exit code not 0.
QUERY_COMPLETED_FAILURE = 5;
// Query for all tasks that are TaskState.EXPIRED.
QUERY_EXPIRED = 6;
// Query for all tasks that are TaskState.TIMED_OUT.
QUERY_TIMED_OUT = 7;
// Query for all tasks that are TaskState.BOT_DIED.
QUERY_BOT_DIED = 8;
// Query for all tasks that are TaskState.CANCELED.
QUERY_CANCELED = 9;
// Query for all tasks, independent of the task state.
//
// In hindsight, this constant should have been the value 0. Sorry, the
// original author was young and foolish.
QUERY_ALL = 10;
// Query for all tasks that are TaskState.COMPLETED but that actually didn't
// run due to TaskProperties.idempotent being True *and* that a previous task
// with the exact same TaskProperties had successfully run before, aka
// COMPLETED_SUCCESS.
QUERY_DEDUPED = 11;
// Query for all tasks that are TaskState.KILLED.
QUERY_KILLED = 12;
// Query for all tasks that are TaskState.NO_RESOURCE.
QUERY_NO_RESOURCE = 13;
// Query for all tasks that are TaskState.CLIENT_ERROR.
QUERY_CLIENT_ERROR = 14;
}
// Flag to sort returned tasks. The natural sort is CREATED_TS.
enum SortQuery {
QUERY_CREATED_TS = 0;
// Used to be QUERY_MODIFIED_TS which cannot be used to sort task results.
reserved 1;
QUERY_COMPLETED_TS = 2;
QUERY_ABANDONED_TS = 3;
QUERY_STARTED_TS = 4;
}
enum NullableBool {
NULL = 0;
FALSE = 1;
TRUE = 2;
}
// Messages
// Represents a mapping of string to a string.
//
// If the StringPair is itself repeated inside another message, the list
// must be sorted by key and the keys must be unique.
message StringPair {
string key = 1;
string value = 2;
}
// Represents a mapping of string to a list of strings.
//
// If the StringListPair is itself repeated inside another message, the list
// must be sorted by key and the keys must be unique.
message StringListPair {
string key = 1;
// All the values for this key. values must be sorted. Human readable.
//
// This string should make sense to a user in the context of 'key'.
repeated string value = 2;
}
// Public details about the server.
message ServerDetails {
string server_version = 1;
string bot_version = 2;
string machine_provider_template = 3 [deprecated=true];
string display_server_url_template = 4;
string luci_config = 5 [deprecated=true];
string cas_viewer_server = 6;
}
// An opaque token that can be used to bootstrap a new bot.
message BootstrapToken {
string bootstrap_token = 1;
}
// Actions the caller is permitted to perform over a resource.
//
// The subject of an action is either a bot, a task or a bunch of pools, as
// specified in the PermissionsRequest message. Pools as specified indirectly
// via "pool:<name>" tags.
//
// This methods exists primarily to be used by the Web UI e.g. to hide
// inaccessible elements.
message ClientPermissions {
// True if allowed to delete the specified bot.
bool delete_bot = 1;
// True if allowed to delete bots in all specified pools.
bool delete_bots = 2;
// True if allowed to terminate the specified bot.
bool terminate_bot = 3;
// Not used, always false.
bool get_configs = 4 [deprecated=true];
// Not used, always false.
bool put_configs = 5 [deprecated=true];
// True if allowed to cancel the specified task.
bool cancel_task = 6;
// True if allowed to request a bot bootstrap token.
bool get_bootstrap_token = 7;
// True if allowed to cancel tasks in all specified pools.
bool cancel_tasks = 8;
// All known pools in which the caller is permitted to list all bots.
repeated string list_bots = 9;
// All known pools in which the caller is permitted to list all tasks.
repeated string list_tasks = 10;
}
// This is a [Digest][build.bazel.remote.execution.v2.Digest] of a blob on
// RBE-CAS. See the explanations at the original definition.
// pylint: disable=line-too-long
// https://github.com/bazelbuild/remote-apis/blob/77cfb44a88577a7ade5dd2400425f6d50469ec6d/build/bazel/remote/execution/v2/remote_execution.proto#L753-L791
message Digest {
string hash = 1;
int64 size_bytes = 2;
}
message CASReference {
// Full name of RBE-CAS instance. `projects/{project_id}/instances/{instance}`.
// e.g. projects/chromium-swarm/instances/default_instance
string cas_instance = 1;
// CAS Digest consists of hash and size bytes.
Digest digest = 2;
}
message CipdPackage {
// A CIPD package to install in the run dir before task execution."""
// A template of a full CIPD package name, e.g.
// "infra/tools/authutil/${platform}"
// See also cipd.ALL_PARAMS.
string package_name = 1;
// Valid package version for all packages matched by package name.
string version = 2;
// Path to dir, relative to the root dir, where to install the package.
// If empty, the package will be installed a the root of the mapped directory.
// If file names in the package and in the isolate clash, it will cause a
// failure.
string path = 3;
}
// Defines CIPD packages to install in task run directory.
message CipdInput {
// URL of the CIPD server. Must start with "https://" or "http://".
// This field or its subfields are optional if default cipd client is defined
// in the server config.
string server = 1;
// CIPD package of CIPD client to use.
// client_package.version is required.
// This field is optional is default value is defined in the server config.
// client_package.path must be empty.
CipdPackage client_package = 2;
// List of CIPD packages to install.
repeated CipdPackage packages = 3;
}
// Defines pinned CIPD packages that were installed during the task.
message CipdPins {
// The pinned package + version of the CIPD client that was actually used.
CipdPackage client_package = 1;
// List of CIPD packages that were installed in the task with fully resolved
// package names and versions.
repeated CipdPackage packages = 2;
}
// Describes a named cache that should be present on the bot.
//
// A CacheEntry in a task specified that the task prefers the cache to be present
// on the bot. A symlink to the cache directory is created at <run_dir>/|path|.
// If cache is not present on the machine, the directory is empty.
// If the tasks makes any changes to the contents of the cache directory, they
// are persisted on the machine. If another task runs on the same machine and
// requests the same named cache, even if mapped to a different path, it will see
// the changes.
message CacheEntry {
// Unique name of the cache. Required. Length is limited to 4096.
string name = 1;
// Relative path to the directory that will be linked to the named cache.
// Required.
// A path cannot be shared among multiple caches or CIPD installations.
// A task will fail if a file/dir with the same name already exists.
string path = 2;
}
// Defines the type of "sandbox" to run the task process in.
//
// Unimplemented.
message Containment {
enum ContainmentType {
// Historical value, not specified. Containment may or may not be used.
NOT_SPECIFIED = 0;
// No containment, the default for now.
NONE = 1;
// Use the containment appropriate on the platform.
AUTO = 2;
// Use Job Object on Windows. Will fail if used on other platforms.
JOB_OBJECT = 3;
}
// Lowers the priority of the task process when started. Doesn't require
// containment. This gives the bot a chance to survive when the task starts an
// overwhelming number of children processes.
bool lower_priority = 1;
// Defines the type of containment used.
ContainmentType containment_type = 2;
// The values below require a form of containment to be enforced.
// Limits the number of concurrent active processes.
int64 limit_processes = 3;
// Limits the total amount of memory allocated by processes.
int64 limit_total_committed_memory = 4;
}
// Important metadata about a particular task.
message TaskProperties {
// Specifies named caches to map into the working directory. These caches
// outlives the task, which can then be reused by tasks later used on this bot
// that request the same named cache.
repeated CacheEntry caches = 1;
// CIPD packages to install. These packages are meant to be software that is
// needed (a dependency) to the task being run. Unlike isolated files, the CIPD
// packages do not expire from the server.
CipdInput cipd_input = 2;
// Command to run. This has priority over a command specified in the isolated
// files.
repeated string command = 3;
// Relative working directory to start the 'command' in, defaults to the root
// mapped directory or what is provided in the isolated file, if any.
string relative_cwd = 4;
// Dimensions are what is used to determine which bot can run the task. The
// bot must have all the matching dimensions, even for repeated keys with
// multiple different values. It is a logical AND, all values must match.
//
// It should have been a StringListPair but this would be a breaking change.
repeated StringPair dimensions = 5;
// Environment variables to set when running the task.
repeated StringPair env = 6;
// Swarming-root relative paths to prepend to a given environment variable.
//
// These allow you to put certain subdirectories of the task into PATH,
// PYTHONPATH, or other PATH-like environment variables. The order of
// operations is:
// * Turn slashes into native-platform slashes.
// * Make the path absolute
// * Prepend it to the current value of the envvar using the os-native list
// separator (i.e. `;` on windows, `:` on POSIX).
//
// Each envvar can have multiple paths to prepend. They will be prepended in
// the order seen here.
//
// For example, if env_prefixes was:
// [("PATH", ["foo", "bar"]),
// ("CUSTOMPATH", ["custom"])]
//
// The task would see:
// PATH=/path/to/swarming/rundir/foo:/path/to/swarming/rundir/bar:$PATH
// CUSTOMPATH=/path/to/swarming/rundir/custom
//
// The path should always be specified here with forward-slashes, and it must
// not attempt to escape the swarming root (i.e. must not contain `..`).
//
// These are applied AFTER evaluating `env` entries.
repeated StringListPair env_prefixes = 7;
// Maximum number of seconds the task can run before its process is forcibly
// terminated and the task results in TIMED_OUT.
int32 execution_timeout_secs = 8;
// Number of second to give the child process after a SIGTERM before sending a
// SIGKILL. See doc/Bot.md#timeout-handling
int32 grace_period_secs = 9;
// True if the task does not access any service through the network and is
// believed to be 100% reproducible with the same outcome. In the case of a
// successful task, previous results will be reused if possible.
bool idempotent = 10;
// Digest of the input root uploaded to RBE-CAS.
// This MUST be digest of [build.bazel.remote.execution.v2.Directory].
CASReference cas_input_root = 11;
// Maximum number of seconds the task may be silent (no output to stdout nor
// stderr) before it is considered hung and it forcibly terminated early and
// the task results in TIMED_OUT.
int32 io_timeout_secs = 12;
// Paths in the working directory to archive back.
repeated string outputs = 13;
// Secret bytes to provide to the task. Cannot be retrieved back.
bytes secret_bytes = 14;
// Containment of the task processes.
Containment containment = 15;
}
// Defines a possible task execution for a task request to be run on the
// Swarming infrastructure.
//
// This is one of the possible fallback on a task request.
message TaskSlice {
// The property of the task to try to run.
//
// If there is no bot that can serve this properties.dimensions when this task
// slice is enqueued, it is immediately denied. This can trigger if:
// - There is no bot with these dimensions currently known.
// - Bots that could run this task are either all dead or quarantined.
// Swarming considers a bot dead if it hasn't pinged in the last N minutes
// (currently 10 minutes).
TaskProperties properties = 1;
// Maximum of seconds the task slice may stay PENDING.
//
// If this task request slice is not scheduled after waiting this long, the
// next one will be processed. If this slice is the last one, the task state
// will be set to EXPIRED.
int32 expiration_secs = 2;
// When a task is scheduled and there are currently no bots available to run
// the task, the TaskSlice can either be PENDING, or be denied immediately.
// When denied, the next TaskSlice is enqueued, and if there's no following
// TaskSlice, the task state is set to NO_RESOURCE. This should normally be
// set to False to avoid unnecessary waiting.
bool wait_for_capacity = 3;
}
message SwarmingTaskBackendConfig {
// Task priority, the lower the more important.
//
// Valid values are between 1 and 255.
int32 priority = 1;
// Maximum delay (in seconds) between bot pings before the bot is considered
// dead while running a task.
//
// When a task is running, the bot sends update to the server every
// few seconds. In some cases, like when the system is overloaded,
// the bot may be preempted and delayed in sending its updates.
// After the delay specified here, the server will claim the bot to
// be dead and will forcibly abort the task as BOT_DIED. This is to
// catch system wide issues like a BSOD.
int64 bot_ping_tolerance = 2;
// Parent Swarming task run ID of the process requesting this task.
//
// This field is set on the children tasks when a Swarming task creates
// children Swarming tasks.
//
// This points to the TaskResult.run_id (ending with '1', '2' or more).
string parent_run_id = 3;
// Defines what OAuth2 credentials the task uses when calling other services.
//
// Possible values are:
// - 'none': do not use a task service account at all, this is the default.
// - 'bot': use bot's own account, works only if bots authenticate with
// OAuth2.
// - <some email>: use this specific service account if it is allowed in the
// pool (via 'allowed_service_account' pools.cfg setting) and configured
// in the token server's service_accounts.cfg.
//
// Note that the service account name is specified outside of task properties,
// and thus it is possible to have two tasks with different service accounts,
// but identical properties hash (so one can be deduped). If this is
// unsuitable use 'idempotent=False' or include a service account name in
// properties separately.
string service_account = 4;
// When a task is scheduled and there are currently no bots available to run
// the task, the TaskSlice can either be PENDING, or be denied immediately.
// When denied, the next TaskSlice is enqueued, and if there's no following
// TaskSlice, the task state is set to NO_RESOURCE. This should normally be
// set to False to avoid unnecessary waiting.
bool wait_for_capacity = 5;
// CIPD package of the agent binary that should be called to run the task
// command. Note that it will end with "${platform}"
string agent_binary_cipd_pkg = 6;
// CIPD package tag or ref of the agent binary.
string agent_binary_cipd_vers = 7;
// Name of the file within the CIPD package and should be used to construct
// the task command line.
string agent_binary_cipd_filename = 8;
// Name of the CIPD server.
string agent_binary_cipd_server = 9;
// Tags are 'key:value' strings that describes what the task is about.
// This can later be leveraged to search for kinds of tasks per tag.
repeated string tags = 10;
// Customized name of the task.
string task_name = 11;
}
// Swarming:ResultDB integration configuration for a task.
// See NewTaskRequest.resultdb for more details.
message ResultDBCfg {
// If True and this task is not deduplicated, create
// "task-{swarming_hostname}-{run_id}" invocation for this task,
// provide its update token to the task subprocess via LUCI_CONTEXT
// and finalize the invocation when the task is done.
// If the task is deduplicated, then TaskResult.invocation_name will be the
// invocation name of the original task.
// Swarming:ResultDB integration is off by default, but it may change in the
// future.
bool enable = 1;
}
// Description of a new task request as described by the client.
// This message is used to create a new task.
message NewTaskRequest {
// DEPRECATED. Use task_slices[0].expiration_secs.
int32 expiration_secs = 1;
// Task name for display purpose.
string name = 2;
// Parent Swarming run ID of the process requesting this task. This is to tell
// the server about reentrancy: when a task creates children Swarming tasks, so
// that the tree of tasks can be presented in the UI; the parent task will list
// all the children tasks that were triggered.
string parent_task_id = 3;
// Task priority, the lower the more important.
int32 priority = 4;
// DEPRECATED. Use task_slices[0].properties.
TaskProperties properties = 5;
// Slice of TaskSlice, along their scheduling parameters. Cannot be used at the
// same time as properties and expiration_secs.
//
// This defines all the various possible task execution for a task request to
// be run on the Swarming infrastructure. They are processed in order, and it
// is guaranteed that at most one of these will be processed.
repeated TaskSlice task_slices = 6;
// Tags are 'key:value' strings that describes what the task is about. This can
// later be leveraged to search for kinds of tasks per tag.
repeated string tags = 7;
// User on which behalf this task is run, if relevant. Not validated.
string user = 8;
// Defines what OAuth2 credentials the task uses when calling other services.
//
// Possible values are:
// - 'none': do not use a task service account at all, this is the default.
// - 'bot': use bot's own account, works only if bots authenticate with
// OAuth2.
// - <some email>: use this specific service account if it is allowed in the
// pool (via 'allowed_service_account' pools.cfg setting) and configured
// in the token server's service_accounts.cfg.
//
// Note that the service account name is specified outside of task properties,
// and thus it is possible to have two tasks with different service accounts,
// but identical properties hash (so one can be deduped). If this is unsuitable
// use 'idempotent=False' or include a service account name in properties
// separately.
string service_account = 9;
// Full topic name to post task state updates to, e.g.
// "projects/<id>/topics/<id>".
string pubsub_topic = 10;
// Secret string to put into "auth_token" attribute of PubSub message.
string pubsub_auth_token = 11;
// Will be but into "userdata" fields of PubSub message.
string pubsub_userdata = 12;
// Only evaluate the task, as if we were going to schedule it, but don't
// actually schedule it. This will return the TaskRequest, but without
// a task_id.
bool evaluate_only = 13;
// Controls the application of the pool's TaskTemplate to the creation of this
// task. By default this will automatically select the pool's preference for
// template, but you can also instruct swarming to prefer/prevent the
// application of canary templates, as well as skipping the template
// altogether.
enum PoolTaskTemplateField {
AUTO = 0;
CANARY_PREFER = 1;
CANARY_NEVER = 2;
SKIP = 3;
}
PoolTaskTemplateField pool_task_template = 14;
// Maximum delay between bot pings before the bot is considered dead
// while running a task.
int32 bot_ping_tolerance_secs = 15;
// This is used to make new task request idempotent in best effort.
// If new request has request_uuid field, it checks memcache before scheduling
// actual task to check there is already the task triggered by same request
// previously.
string request_uuid = 16;
// Configuration of Swarming:ResultDB integration.
ResultDBCfg resultdb = 17;
// Task realm.
// See api/swarming.proto for more details.
string realm = 18;
}
// Description of a task request as registered by the server.
// This message is used when retrieving information about an existing task.
// See NewTaskRequest for more details.
message TaskRequestResponse {
string task_id = 1;
int32 expiration_secs = 2;
string name = 3;
string parent_task_id = 4;
int32 priority = 5;
// For some amount of time, the properties will be copied into the
// task_slices and vice-versa, to give time to the clients to update.
// Eventually, only task_slices will be supported.
TaskProperties properties = 6;
repeated string tags = 7;
google.protobuf.Timestamp created_ts = 8;
string user = 9;
// User name of whoever posted this task, extracted from the credentials.
string authenticated = 10;
repeated TaskSlice task_slices = 11;
// Indicates what OAuth2 credentials the task uses when calling other services.
string service_account = 12;
string realm = 13;
// Configuration of Swarming:ResultDB integration.
ResultDBCfg resultdb = 14;
string pubsub_topic = 15;
string pubsub_userdata = 16;
int32 bot_ping_tolerance_secs = 17;
string rbe_instance = 18;
}
// Request to cancel one task.
message TaskCancelRequest {
string task_id = 1;
bool kill_running = 2;
}
// Request to cancel some subset of pending/running tasks.
message TasksCancelRequest {
// Number of items to cancel per request. limit must be in [1..1000].
int32 limit = 1;
// Previous call would have returned a cursor if there were more tasks to kill.
string cursor = 2;
// Any task which contains one or more of tags will be cancelled.
repeated string tags = 3;
// Kill running tasks if set. Otherwise running tasks will be ignored.
bool kill_running = 4;
// Only tasks later or equal to start will be cancelled. No effect if unset.
google.protobuf.Timestamp start = 5;
// Only tasks earlier or equal to end will be cancelled. No effect if unset.
google.protobuf.Timestamp end = 6;
}
message OperationStats {
// Duration in seconds.
float duration = 1;
}
message CASOperationStats {
// Duration in seconds.
float duration = 1;
int32 initial_number_items = 2;
int64 initial_size = 3;
// These buffers are compressed as deflate'd delta-encoded varints. They are
// all the items for an isolated operation, which can scale in the 100k range.
// So can be large! See //client/utils/large.py for the code to handle these.
bytes items_cold = 4;
bytes items_hot = 5;
// Corresponding summaries; for each list above, sum of the number of files
// and the sum bytes of the files.
int64 num_items_cold = 6;
int64 total_bytes_items_cold = 7;
int64 num_items_hot = 8;
int64 total_bytes_items_hot = 9;
}
// Performance stats of task execution.
// See task_result.PerformanceStats for details.
message PerformanceStats {
float bot_overhead = 1;
CASOperationStats isolated_download = 2;
CASOperationStats isolated_upload = 3;
OperationStats package_installation = 4;
OperationStats cache_trim = 5;
OperationStats named_caches_install = 6;
OperationStats named_caches_uninstall = 7;
OperationStats cleanup = 8;
}
// Result of a request to cancel a task.
message CancelResponse {
// True if the cancellation succeeded. Either the task atomically changed
// from PENDING to CANCELED or it was RUNNING and killing bit has been set.
bool canceled = 1;
// True if the task was running while it was canceled.
bool was_running = 2;
}
// Result of canceling some subset of pending tasks.
message TasksCancelResponse {
string cursor = 1;
google.protobuf.Timestamp now = 2;
int32 matched = 3;
}
// A task's output as a bytestring
message TaskOutputResponse {
bytes output = 1;
// Current state of the task (e.g. PENDING, RUNNING, COMPLETED, EXPIRED, etc).
TaskState state = 2;
}
// ResultDB properties of a completed task.
message ResultDBInfo {
// ResultDB hostname, e.g. "results.api.cr.dev"
string hostname = 1;
// Name of the task's ResultDB invocation.
//
// For example "invocations/task-chromium-swarm.appspot.com-deadbeef1".
// Unset if Swarming:ResultDB integration was not enabled for this task.
//
// If the task was deduplicated, this equals invocation name of the original
// task.
string invocation = 2;
}
// Representation of the TaskResultSummary or TaskRunResult ndb model.
message TaskResultResponse {
reserved 7;
reserved "children_task_ids";
// Summary task ID (ending with '0') when creating a new task.
string task_id = 1;
// Time when the task was abandoned instead of normal completion (e.g.
// EXPIRED, BOT_DIED, KILLED).
//
// The same key cannot be repeated.
repeated StringListPair bot_dimensions = 2;
// Unique ID of the bot.
string bot_id = 3;
// Time the bot became ready for a next task.
google.protobuf.Timestamp bot_idle_since_ts = 4;
// Hash of the bot code which ran the task.
string bot_version = 5;
// The cloud project id where the bot saves its logs.
string bot_logs_cloud_project = 6;
// Time the task completed normally. Only one of abandoned_ts or completed_ts
// can be set except for state == KILLED.
//
// In case of KILLED, completed_ts is the time the task completed.
google.protobuf.Timestamp completed_ts = 8;
// $ saved for task with state DEDUPED.
float cost_saved_usd = 9;
// Time the task was requested.
google.protobuf.Timestamp created_ts = 10;
// Task ID which results was reused for state DEDUPED.
string deduped_from = 11;
// Duration of the task in seconds. This excludes overheads.
float duration = 12;
// Process exit code if relevant. May be forcibly set to -1 in exceptional
// cases.
int64 exit_code = 13;
// True if exit_code != 0.
bool failure = 14;
// True if state is BOT_DIED.
bool internal_failure = 15;
// Time the results was last updated in the DB.
google.protobuf.Timestamp modified_ts = 16;
// CAS Digest of the output root uploaded to RBE-CAS.
// This MUST be digest of [build.bazel.remote.execution.v2.Directory].
CASReference cas_output_root = 17;
// Server versions that touched this task.
repeated string server_versions = 18;
// Time the task started being run by a bot.
google.protobuf.Timestamp started_ts = 19;
// Current state of the task (e.g. PENDING, RUNNING, COMPLETED, EXPIRED, etc).
TaskState state = 20;
// In the case of KILLED, this records the time the user requested the task to
// stop.
google.protobuf.Timestamp abandoned_ts = 21;
// Can be multiple values only in TaskResultSummary.
repeated float costs_usd = 22;
// Name of the task. Only set when requesting task ID summary, ending with '0'.
string name = 23;
// Tags associated with the task when it was requested. Only set when
// requesting task ID summary, ending with '0'.
repeated string tags = 24;
// User on behalf this task was requested. Only set when requesting task ID
// summary, ending with '0'.
string user = 25;
// Statistics about overhead for an isolated task. Only sent when requested.
PerformanceStats performance_stats = 26;
// Listing of the ACTUAL pinned CipdPackages that the task used. These can vary
// from the input packages if the inputs included non-identity versions (e.g. a
// ref like "latest").
CipdPins cipd_pins = 27;
// Actual executed task id that this task represents. For deduped tasks, it is
// the same value as deduped_from. This value can be empty if there is no
// execution, for example the task was cancelled.
string run_id = 28;
// Index in the TaskRequest.task_slices (TaskSlice instance) that this result
// represents. This is updated when a TaskSlice is enqueued to run.
//
// The TaskSlice contains a TaskProperties, which defines what is run.
int32 current_task_slice = 29;
// ResultDB related information.
// None if the integration was not enabled for this task.
ResultDBInfo resultdb_info = 30;
// Reported missing CAS packages on CLIENT_ERROR state
repeated CASReference missing_cas = 31;
// Reported missing CIPD packages on CLIENT_ERROR state
repeated CipdPackage missing_cipd = 32;
}
// Represents the current task state.
//
// Some states are still mutable: PENDING and RUNNING. The others are final and
// will not change afterward.
//
// A task is guaranteed to be in exactly one state at any point of time.
//
// Do not confuse StateQuery and TaskState. StateQuery is to query tasks
// via the API. TaskState is the current task state.
//
// As you read the following constants, astute readers may wonder why these
// constants look like a bitmask. This is because of historical reasons and this
// is effectively an enum, not a bitmask.
enum TaskState {
// Invalid state, do not use.
INVALID = 0x00;
// The task is currently running. This is in fact 3 phases: the initial
// overhead to fetch input files, the actual task running, and the tear down
// overhead to archive output files to the server.
RUNNING = 0x10;
// The task is currently pending. This means that no bot reaped the task. It
// will stay in this state until either a task reaps it or the expiration
// elapsed. The task pending expiration is specified as
// TaskSlice.expiration_secs, one per task slice.
PENDING = 0x20;
// The task is not pending anymore, and never ran due to lack of capacity. This
// means that other higher priority tasks ran instead and that not enough bots
// were available to run this task for TaskSlice.expiration_secs seconds.
EXPIRED = 0x30;
// The task ran for longer than the allowed time in
// TaskProperties.execution_timeout_secs or TaskProperties.io_timeout_secs.
// This means the bot forcefully killed the task process as described in the
// graceful termination dance in the documentation.
TIMED_OUT = 0x40;
// The task ran but the bot had an internal failure, unrelated to the task
// itself. It can be due to the server being unavailable to get task update,
// the host on which the bot is running crashing or rebooting, etc.
BOT_DIED = 0x50;
// The task never ran, and was manually cancelled via the 'cancel' API before
// it was reaped.
CANCELED = 0x60;
// The task ran and completed normally. The task process exit code may be 0 or
// another value.
COMPLETED = 0x70;
// The task ran but was manually killed via the 'cancel' API. This means the
// bot forcefully killed the task process as described in the graceful
// termination dance in the documentation.
KILLED = 0x80;
// The task was never set to PENDING and was immediately refused, as the server
// determined that there is no bot capacity to run this task. This happens
// because no bot exposes a superset of the requested task dimensions.
//
// Set TaskSlice.wait_for_capacity to True to force the server to keep the task
// slice pending even in this case. Generally speaking, the task will
// eventually switch to EXPIRED, as there's no bot to run it. That said, there
// are situations where it is known that in some not-too-distant future a wild
// bot will appear that will be able to run this task.
NO_RESOURCE = 0x100;
// The task run into an issue that was caused by the client. It can be due to
// a bad CIPD or CAS package. Retrying the task with the same parameters will
// not change the result.
CLIENT_ERROR = 0x200;
}
// Only holds states. Used in the 'get_states' RPC.
message TaskStates {
repeated TaskState states = 1;
}
// Wraps a list of TaskResult.
message TaskListResponse {
string cursor = 1;
repeated TaskResultResponse items = 2;
google.protobuf.Timestamp now = 3;
}
// Wraps a list of TaskRequest.
message TaskRequestsResponse {
string cursor = 1;
repeated TaskRequestResponse items = 2;
google.protobuf.Timestamp now = 3;
}
// Returns the count, as requested.
message TasksCount {
int32 count = 1;
google.protobuf.Timestamp now = 2;
}
// Provides the ID of the requested TaskRequest.
message TaskRequestMetadataResponse {
string task_id = 1;
TaskRequestResponse request = 2;
// Set to finished task result in case task was deduplicated.
TaskResultResponse task_result = 3;
}
// Representation of the BotInfo ndb model.
message BotInfo {
string bot_id = 1;
string task_id = 2;
string external_ip = 3;
string authenticated_as = 4;
google.protobuf.Timestamp first_seen_ts = 5;
bool is_dead = 6;
google.protobuf.Timestamp last_seen_ts = 7;
bool quarantined = 8;
string maintenance_msg = 9;
repeated StringListPair dimensions = 10;
string task_name = 11;
string version = 12;
// Encoded as json since it's an arbitrary dict.
string state = 13;
bool deleted = 14;
}
// Wraps a list of BotInfo.
message BotInfoListResponse {
string cursor = 1;
repeated BotInfo items = 2;
google.protobuf.Timestamp now = 3;
int32 death_timeout = 4;
}
// Returns the count, as requested.
message BotsCount {
google.protobuf.Timestamp now = 1;
int32 count = 2;
int32 quarantined = 3;
int32 maintenance = 4;
int32 dead = 5;
int32 busy = 6;
}
// Returns all the dimensions and dimension possibilities in the fleet.
message BotsDimensions {
repeated StringListPair bots_dimensions = 1;
// Time at which this summary was calculated.
google.protobuf.Timestamp ts = 2;
}
message BotEventResponse {
// google.protobuf.Timestamp of this event.
google.protobuf.Timestamp ts = 1;
// Type of event.
string event_type = 2;
// Message included in the event.
string message = 3;
// Bot dimensions at that moment.
repeated StringListPair dimensions = 4;
// Bot state at that moment, encoded as json.
string state = 5;
// IP address as seen by the HTTP handler.
string external_ip = 6;
// Bot identity as seen by the HTTP handler.
string authenticated_as = 7;
// Version of swarming_bot.zip the bot is currently running.
string version = 8;
// If True, the bot is not accepting task due to being quarantined.
bool quarantined = 9;
// If set, the bot is rejecting tasks due to maintenance.
string maintenance_msg = 10;
// Affected by event_type == 'request_task', 'task_completed', 'task_error'.
string task_id = 11;
}
message BotEventsResponse {
string cursor = 1;
repeated BotEventResponse items = 2;
google.protobuf.Timestamp now = 3;
}
// Indicates whether a bot was deleted.
message DeleteResponse {
bool deleted = 1;
}
// Returns the pseudo taskid to wait for the bot to shut down.
message TerminateResponse {
string task_id = 1;
}
message BotRequest {
string bot_id = 1;
}
message TerminateRequest {
// Id of bot to terminate.
string bot_id = 1;
// Reason why the termination was created.
string reason = 2;
}
message BotEventsRequest {
string bot_id = 1;
int32 limit = 2;
string cursor = 3;
google.protobuf.Timestamp start = 4;
google.protobuf.Timestamp end = 5;
}
message BotTasksRequest {
string bot_id = 1;
int32 limit = 2;
string cursor = 3;
google.protobuf.Timestamp start = 4;
google.protobuf.Timestamp end = 5;
StateQuery state = 6;
SortQuery sort = 7;
bool include_performance_stats = 8;
}
message BotsRequest {
int32 limit = 1;
string cursor = 2;
repeated StringPair dimensions = 3;
NullableBool quarantined = 4;
NullableBool in_maintenance = 5;
NullableBool is_dead = 6;
NullableBool is_busy = 7;
}
message BotsCountRequest {
repeated StringPair dimensions = 1;
}
message BotsDimensionsRequest {
string pool = 1;
}
message PermissionsRequest {
string bot_id = 1;
string task_id = 2;
repeated string tags = 3;
}
message TaskStatesRequest {
repeated string task_id = 1;
}
message TasksWithPerfRequest {
int32 limit = 1;
string cursor = 2;
// These were floats in the legacy protorpc api
google.protobuf.Timestamp start = 3;
google.protobuf.Timestamp end = 4;
StateQuery state = 5;
SortQuery sort = 6;
repeated string tags = 7;
bool include_performance_stats = 8;
}
message TasksRequest {
int32 limit = 1;
string cursor = 2;
// These were floats in the legacy protorpc api
google.protobuf.Timestamp start = 3;
google.protobuf.Timestamp end = 4;
StateQuery state = 5;
SortQuery sort = 6;
repeated string tags = 7;
}
message TasksCountRequest {
google.protobuf.Timestamp start = 1;
google.protobuf.Timestamp end = 2;
StateQuery state = 3;
repeated string tags = 4;
}
message TaskIdRequest {
string task_id = 1;
}
message TaskIdWithOffsetRequest {
string task_id = 1;
int64 offset = 2;
int64 length = 3;
}
message TaskIdWithPerfRequest {
string task_id = 1;
bool include_performance_stats = 2;
}
message BatchGetResultRequest {
// One or more task IDs (ending with '0'), must have no duplicates.
repeated string task_ids = 1;
// If true, populate `performance_stats` in the output.
bool include_performance_stats = 2;
}
message BatchGetResultResponse {
// Outcome of fetching one task's result.
message ResultOrError {
string task_id = 1;
oneof outcome {
TaskResultResponse result = 2;
google.rpc.Status error = 3;
}
}
// Task results or errors, in the same order as `task_ids` in the request.
repeated ResultOrError results = 1;
}