| // Copyright 2017 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.config; |
| |
| import "proto/config/config.proto"; |
| import "proto/config/realms.proto"; |
| |
| option go_package = "go.chromium.org/luci/swarming/proto/config;configpb"; |
| |
| // Schema for pools.cfg service config file in luci-config. |
| // |
| // It defined a set of Pool objects, each one corresponding to a single Swarming |
| // pool dimension. Each Swarming task resided in some pool, and each Swarming |
| // bot belongs to at least one pool. |
| // |
| // Pools are used to isolate groups of tasks/bots from each other for security |
| // and capacity reasons. Two different pools should not interfere with each |
| // other at all (unless explicitly configured to share bots or accounts). |
| message PoolsCfg { |
| reserved 2; |
| |
| // List of all defined pools. |
| repeated Pool pool = 1; |
| |
| // Configures the default isolate and CIPD services to use for all pools on |
| // this server. |
| ExternalServices default_external_services = 6; |
| |
| // This is the "shared namespace" of task templates. |
| // |
| // Task templates allow pools to specify some property defaults (particularly |
| // around caches, CIPD packages and Environment variables) for tasks created |
| // within the pool. These templates can have 'include' statements, and those |
| // include statements draw from this namespace. |
| // |
| // Swarming will do a 2-pass parse of these so order doesn't matter (i.e. If |
| // A includes B, but is defined B-then-A, it's not an error). |
| repeated TaskTemplate task_template = 3; |
| |
| // This is the "shared namespace" of deployments. |
| // |
| // When pools specify a task_template_deployment, it draws from this |
| // namespace. |
| repeated TaskTemplateDeployment task_template_deployment = 4; |
| |
| // Defines about how to monitor bots in a pool. Each pool above may refer to |
| // one of the BotMonitoring message by name, which permits reusing |
| // BotMonitoring definitions. |
| repeated BotMonitoring bot_monitoring = 5; |
| } |
| |
| |
| // Properties of a single pool or a bunch of identically configured pools. |
| // |
| // In particular contains authorization configuration. |
| message Pool { |
| // Names of the pools this config applies to. |
| // |
| // Tasks target the pool by specifying its name as 'pool' dimension, thus |
| // names here should be valid dimension value. |
| repeated string name = 1; |
| |
| // Contact information for people that own this pool. |
| // |
| // Not used in any ACLs, just informational field. |
| repeated string owners = 2; |
| |
| // Defines who can schedule tasks in this pool. |
| // |
| // The checks here act as a second authorization layer, consulted after the |
| // first server-global one (defined based on groups set in settings.cfg, see |
| // AuthSettings in config.proto). |
| Schedulers schedulers = 3; |
| |
| reserved 4, 5; |
| reserved "allowed_service_account", "allowed_service_account_group"; |
| |
| oneof task_deployment_scheme { |
| // Most Pools will include a task_template_deployment by name. |
| string task_template_deployment = 6; |
| |
| // However, pools which substantially differ from other ones can define an |
| // entire deployment inline without putting it in the shared namespace. |
| // |
| // The name fields in this deployment and any embedded task_templates must |
| // not be specified. |
| TaskTemplateDeployment task_template_deployment_inline = 7; |
| } |
| |
| // Refer to one bot_monitoring at the file level by name. |
| string bot_monitoring = 8; |
| |
| // If specified, this is the description of the external schedulers to be used |
| // for tasks and bots for this pool that match the dimension set of a scheduler. |
| // For a given task or bot, the first entry in this list that matches based on |
| // dimension eligibility will be used. |
| repeated ExternalSchedulerConfig external_schedulers = 9; |
| |
| // Realm name that the pool is associated with. |
| // |
| // e.g. |
| // 'infra:pool/flex/try' for 'luci.flex.try' pool |
| // |
| // See also |
| // https://chromium.googlesource.com/infra/luci/luci-go/+/HEAD/server/auth/service/protocol/components/auth/proto/realms.proto |
| string realm = 10; |
| |
| // Enforcements of permissions can be controlled by pool during migration |
| // from legacy ACLs configs to Realms configs. |
| // |
| // When scheduling tasks: |
| // * If a task doesn't have a realm (i.e. it is a legacy task), it will be |
| // assigned `default_task_realm` and only permissions listed here will be |
| // enforced. If some permission is not enforced, Swarming will use a |
| // legacy ACL check for it instead. |
| // * If a task has a realm (i.e. it is a modern task aware of realms), all |
| // permissions will always be enforced for it. Legacy ACLs will not be |
| // used at all. |
| // |
| // This field is not used for permissions not related to task scheduling. |
| // |
| // This field will be deprecated after migration. All scheduling permissions |
| // will be enforced at all times. |
| repeated RealmPermission enforced_realm_permissions = 11; |
| |
| // Realm name to use for tasks if they don't have a realm associated. |
| string default_task_realm = 12; |
| |
| // Settings controlling migration to the RBE Scheduler. |
| message RBEMigration { |
| // An RBE instance to send tasks to. |
| string rbe_instance = 1; |
| // Approximate percent of tasks targeting this pool to send to RBE. |
| // |
| // The decision is done randomly when the task is scheduled. |
| // |
| // Additionally tasks that have `rbe:require` tag will always use RBE and |
| // tasks that have `rbe:prevent` tag will never use RBE. If both tags are |
| // set, `rbe:prevent` takes precedence. |
| int32 rbe_mode_percent = 2; |
| // Distribution of bots in this pool across migration modes. Percents must |
| // sum up to 100. |
| // |
| // Bots are assigned the corresponding mode based on hash of their ID modulo |
| // 100. The full space of such IDs always looks like this: |
| // |
| // [---SWARMING---|---HYBRID---|---RBE---] |
| // |
| // Where width of sections are defined by `percent` below. In other words, |
| // there are two boundaries that can be moved: |
| // 1. SWARMING <-> HYBRID. |
| // 2. HYBRID <-> RBE. |
| // |
| // Migration starts with all bots being SWARMING, then SWARMING <-> HYBRID |
| // boundary is moved until all bots are HYBRID. Then HYBRID <-> RBE boundary |
| // is moved until all bots are RBE. |
| // |
| // If a bot belongs to multiple pools (should be rare), the mode is derived |
| // to be compatible across all bot's pools: |
| // 1. All pools indicate the bot should be in SWARMING => use SWARMING. |
| // 2. All pools indicate the bot should be in RBE => use RBE. |
| // 3. Otherwise use HYBRID. |
| message BotModeAllocation { |
| enum BotMode { |
| UNKNOWN = 0; |
| SWARMING = 1; |
| HYBRID = 2; |
| RBE = 3; |
| } |
| BotMode mode = 1; |
| int32 percent = 2; |
| } |
| repeated BotModeAllocation bot_mode_allocation = 3; |
| } |
| RBEMigration rbe_migration = 13; |
| |
| // Controls the scheduling algorithm used by Swarming to schedule tasks. |
| // _gen_queue_number() in server/task_to_run.py uses this to control the |
| // queue_number of a task, which the ordering of tasks to run is based on. |
| enum SchedulingAlgorithm { |
| // Unknown or unspecified scheduling algorithm. |
| SCHEDULING_ALGORITHM_UNKNOWN = 0; |
| // First in first out (FIFO) scheduling algorithm. |
| // |
| // First task that comes in is scheduled first. |
| SCHEDULING_ALGORITHM_FIFO = 1; |
| // Last in first out (LIFO) scheduling algorithm. |
| // |
| // Last task that comes in is scheduled first. |
| SCHEDULING_ALGORITHM_LIFO = 2; |
| } |
| SchedulingAlgorithm scheduling_algorithm = 14; |
| } |
| |
| |
| // Defines who can schedule tasks in a pool. |
| message Schedulers { |
| // Emails of individual end-users. |
| // |
| // Useful to avoid creating one-person groups. |
| repeated string user = 1; |
| |
| // List of groups with end-users. |
| repeated string group = 2; |
| |
| // See TrustedDelegation comment. |
| repeated TrustedDelegation trusted_delegation = 3; |
| } |
| |
| |
| // Defines a delegatee trusted to make authorization decisions for who can use |
| // a pool. |
| // |
| // This is based on LUCI delegation protocol. Imagine an end user U calling |
| // Swarming through an intermediary service X. In this case U is a delegator and |
| // X is a delegatee. When X calls Swarming, it makes an RPC to the token server |
| // to make a delegation token that says "<X can call Swarming on behalf of U>". |
| // |
| // This token is then sent to the Swarming with the RPC. Swarming sees that |
| // the direct peer it's talking to is X, but the call should be performed under |
| // the authority of U. |
| // |
| // We extend this to also allow X make authorization decisions about whether U |
| // can use particular Swarming resource or not. The result of this decision is |
| // encoded in the delegation token as a set of "key:value" tags. Swarming then |
| // can treat presence of such tags as a signal that the particular call is |
| // allowed. |
| // |
| // In this scenario we totally trust X to make the correct decision. |
| message TrustedDelegation { |
| message TagList { |
| repeated string tag = 1; |
| } |
| |
| // Email of a trusted delegatee (the one who's minting the delegation token). |
| string peer_id = 1; |
| |
| // A list of tags to expected in the delegation token to allow the usage of |
| // a pool. |
| // |
| // Presence of any of the specified tags are enough. The format of these tags |
| // generally depends on what service is doing the delegation. |
| TagList require_any_of = 2; |
| } |
| |
| |
| // A TaskTemplate describes a set of properties (caches, CIPD packages and |
| // envvars) which apply to tasks created within a swarming pool. |
| // |
| // TaskTemplates may either be defined inline inside of |
| // a TaskTemplateDeployment, or in "shared namespace" of the |
| // PoolsCfg.task_template field. |
| // |
| // TaskTemplates may also include other TaskTemplates by name from the "shared |
| // namespace" in PoolsCfg. Swarming calculates the final value for a given |
| // TaskTemplate by applying all of its `include` fields depth-first, and then by |
| // applying the properties in the body of the TaskTemplate. Includes may never |
| // be repeated, including transitively. This means that "diamond shaped |
| // dependencies" are forbidden (i.e. A<-B<-D and A<-C<-D would be forbidden |
| // because `A` is included in `D` twice (via both C and B)). |
| message TaskTemplate { |
| // This gives the template a name for the 'include' field below. This only |
| // applies to templates defined within the PoolsCfg message (i.e. the |
| // top-level message), not to templates inlined into a TaskTemplateDeployment. |
| string name = 1; |
| |
| // Includes properties from the named other TaskTemplate. This can only |
| // include templates defined in the top-level PoolsCfg message. |
| repeated string include = 2; |
| |
| message CacheEntry { |
| // The name of the cache (required). |
| string name = 1; |
| // The path relative to the task root to mount the cache (required). |
| string path = 2; |
| } |
| // CacheEntries are keyed by `name`, and `path` is overridden wholesale. |
| // |
| // It is illegal to have any TaskTemplate with multiple cache entries mapping |
| // to the same path. It is illegal to have any cache paths overlap with cipd |
| // package paths. |
| repeated CacheEntry cache = 3; |
| |
| message CipdPackage { |
| // The relative to the task root to unpack the CIPD package. A blank value |
| // is permitted and means 'the root directory of the task'. |
| string path = 1; |
| // The CIPD package name template to use (required). |
| string pkg = 2; |
| // The version of the CIPD package to use (required). |
| string version = 3; |
| } |
| // CipdPackages are keyed by (path, name), and `version` is overridden |
| // wholesale. |
| // |
| // It is illegal to have any cipd paths overlap with cache entry paths. |
| repeated CipdPackage cipd_package = 4; |
| |
| message Env { |
| // The envvar you want to set (required). |
| string var = 1; |
| |
| // The envvar value you want to set. Any prefixes are prepended to this |
| // value. If the value is unset, prefixes will be prepended to the bot's |
| // current value of this envvar (see examples) |
| string value = 2; |
| |
| // Paths relative to the task root to prepend to this envvar on the bot. |
| // These will be resolved to absolute paths on the bot. |
| repeated string prefix = 3; |
| |
| // If true, tasks setting this EnvVar can overwrite the value and/or the |
| // prefix. Otherwise, tasks will not be permitted to to set any env var or |
| // env_prefix for this var. |
| // |
| // This should be True for envvars you expect tasks to extend, like $PATH. |
| // Note that this only affects envvar manipulation at the Swarming API |
| // level; once the task is running it can (of course) manipulate the env |
| // however it wants. |
| bool soft = 4; |
| } |
| // Env vars are keyed by the `var` field, |
| // |
| // `value` fields overwrite included values. |
| // `soft` fields overwrite included values. |
| // `prefix` fields append to included values. For example, Doing: |
| // |
| // {name: "1" env { var: "PATH" prefix: "a" }} |
| // {name: "2" env { var: "PATH" prefix: "b" }} |
| // {name: "3" include: "1" include: "2" } |
| // |
| // Is equivalent to: |
| // |
| // {name: "3" env { var: "PATH" prefix: "a" prefix: "b" }} |
| // |
| // |
| // Full Example: |
| // |
| // env { |
| // var: "PATH" |
| // value: "/disable_system_path" |
| // prefix: "a" |
| // prefix: "b" |
| // prefix: "c" |
| // soft: true |
| // } |
| // env { |
| // var: "OTHER" |
| // value: "1" |
| // } |
| // env { |
| // var: "PYTHONPATH" |
| // prefix: "a" |
| // } |
| // |
| // Results in, essentially: |
| // |
| // $PATH=/path/to/a:/path/to/b:/path/to/c:/disable_system_path |
| // $OTHER=1 |
| // $PYTHONPATH=/path/to/a:$PYTHONPATH |
| repeated Env env = 5; |
| } |
| |
| |
| // This is a tuple of (prod template, canary template, canary_chance), so that it |
| // can be referenced from multiple pools simultaneously as a single unit. |
| message TaskTemplateDeployment { |
| // This gives the deployment a name for the 'task_template_deployment' field |
| // in PoolCfg. |
| // |
| // When this TaskTemplateDeployment is inlined into another message (e.g. |
| // `TaskTemplate.task_template_deployment_inline`), the name field must not be |
| // specified. |
| string name = 1; |
| |
| // Most Deployments will have a TaskTemplate with just a single include |
| // directive. |
| // |
| // However, pools which substantially differ from other ones could define an |
| // entire template inline without being forced to put it in the shared |
| // namespace. |
| // |
| // The name field in this template (and the canary template) must not be |
| // specified. |
| TaskTemplate prod = 2; |
| |
| // The canary template can be defined like the `prod` field above. If this is |
| // defined and `canary_chance` is greater than 0, then this template will be |
| // selected instead of `prod`. |
| TaskTemplate canary = 3; |
| |
| // range [0, 9999] where each tick corresponds to %0.01 chance of selecting |
| // the template. Exactly 0 means 'canary is disabled', meaning that tasks |
| // in this pool will always get the prod template. |
| // |
| // Examples: |
| // * 1 ".01% chance of picking canary" |
| // * 10 ".1% chance of picking canary" |
| // * 100 "1% chance of picking canary" |
| // * 1000 "10% chance of picking canary" |
| // * 5000 "50% chance of picking canary" |
| // * 7500 "75% chance of picking canary" |
| // * 9999 "99.99% chance of picking canary" |
| int32 canary_chance = 4; |
| } |
| |
| |
| // Defines about how to monitor bots. |
| message BotMonitoring { |
| // Name is used by Pool to describe how to monitor bots in this pool. |
| string name = 1; |
| // Dimension keys to be used to bucket the bots. |
| // |
| // The algorithm for a key with multiple values is: |
| // def simplify(values): |
| // values = sorted(values) |
| // return '|'.join( |
| // v for i, v in enumerate(values) |
| // if not any(v.startswith(value) for v in values[i+1:])) |
| // |
| // For example, if 'os' is specified and a bot has the values |
| // ['Linux', 'Ubuntu', 'Ubuntu-16.04'], the bucket value used for this bot |
| // will be 'Linux|Ubuntu-16.04'. |
| // |
| // Then whole algorithm then works for each key: |
| // def bucket(keys, bot_dimensions): |
| // return ';'.join( |
| // '%s:%s' % (key, simplify(bot_dimensions.get(values, [])) |
| // for key in keys) |
| // |
| // so the end result may look like: 'os:Linux|Ubuntu-16.04;pool:Testers'. |
| // |
| // More precisely, when this is used, the other bot dimensions are ignored. |
| // 'pool' is always implicit. |
| repeated string dimension_key = 2; |
| } |
| |
| // Describes an external scheduler used by a particular swarming pool and |
| // dimension set, via the external scheduler API. |
| message ExternalSchedulerConfig { |
| // Service address of external scheduler. |
| string address = 1; |
| |
| // Scheduler id within the external scheduler service to use. This value |
| // is opaque to swarming. |
| string id = 2; |
| |
| // Dimensions is a list of dimension strings in "key:value" format (e.g. |
| // ["os:foo", "featureX:bar"]) that determines eligibility for a bot or task |
| // to use this external scheduler. In particular: |
| // - a bot will be eligible if it contains all of these dimensions. |
| // - a task will be eligible if all its slices contain all these dimensions. |
| // |
| // Note of care: if this list is empty, that means all requests in the pool |
| // are eligible to be forwarded to it. |
| // |
| // Note: To be deprecated, in favor of: any_dimensions and all_dimensions. |
| repeated string dimensions = 3; |
| |
| // If not enabled, this external scheduler config will be ignored. This |
| // makes it safer to add new configs (the naive approach of adding a config |
| // with empty dimentions list would cause all requests to be routed to |
| // that config). |
| bool enabled = 4; |
| |
| bool fallback_when_empty = 5 [deprecated=true]; |
| |
| // A task or bot must have all of these dimensions in order to match this |
| // dimension set. |
| // |
| // Note: Support not yet implemented. |
| repeated string all_dimensions = 6; |
| |
| // If any_dimensions is defined, a task or bot must have any of these |
| // dimensions in order to match this dimension set. |
| // |
| // Note: Support not yet implemented. |
| repeated string any_dimensions = 7; |
| |
| // If true, allows the swarming native scheduler to reap tasks that would |
| // otherwise be owned by this external scheduler, if the external scheduler |
| // returns no results. |
| // |
| // This field should be enabled temporarily when first turning on a new |
| // external scheduler config, to allow tasks that existing prior to that time |
| // to still have a chance to run. After prior tasks have aged out of the |
| // system, this flag should be disabled, to get stricter consistency between |
| // swarming's state and external scheduler's state. |
| bool allow_es_fallback = 8; |
| } |
| |
| message ExternalServices { |
| // (deprecated) isolate field is not used. |
| reserved 1; |
| |
| message CIPD { |
| reserved 2; // Used to be "client_version", no longer used. |
| reserved "client_version"; |
| |
| // (required) URL of the default CIPD server to use, if it is not specified |
| // in the task. |
| // |
| // Must start with "https://" or "http://". |
| // |
| // e.g. "https://chrome-infra-packages.appspot.com" |
| string server = 1; |
| |
| // (required) The version of the cipd client to use. This is likely the |
| // 'infra/tools/cipd/${platform}' package, but because it's part of the |
| // bootstrap needs special logic to handle its installation. |
| CipdPackage client_package = 3; |
| } |
| CIPD cipd = 2; |
| } |