1// Copyright 2020 The Bazel Authors. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15syntax = "proto3"; 16 17package build.bazel.remote.asset.v1; 18 19import "build/bazel/remote/execution/v2/remote_execution.proto"; 20import "google/api/annotations.proto"; 21import "google/protobuf/duration.proto"; 22import "google/protobuf/timestamp.proto"; 23import "google/rpc/status.proto"; 24 25option csharp_namespace = "Build.Bazel.Remote.Asset.v1"; 26option go_package = "github.com/bazelbuild/remote-apis/build/bazel/remote/asset/v1;remoteasset"; 27option java_multiple_files = true; 28option java_outer_classname = "RemoteAssetProto"; 29option java_package = "build.bazel.remote.asset.v1"; 30option objc_class_prefix = "RA"; 31 32// The Remote Asset API provides a mapping from a URI and Qualifiers to 33// Digests. 34// 35// Multiple URIs may be used to refer to the same content. For example, the 36// same tarball may exist at multiple mirrors and thus be retrievable from 37// multiple URLs. When URLs are used, these should refer to actual content as 38// Fetch service implementations may choose to fetch the content directly 39// from the origin. For example, the HEAD of a git repository's active branch 40// can be referred to as: 41// 42// uri: https://github.com/bazelbuild/remote-apis.git 43// 44// URNs may be used to strongly identify content, for instance by using the 45// uuid namespace identifier: urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6. 46// This is most applicable to named content that is Push'd, where the URN 47// serves as an agreed-upon key, but carries no other inherent meaning. 48// 49// Service implementations may choose to support only URLs, only URNs for 50// Push'd content, only other URIs for which the server and client agree upon 51// semantics of, or any mixture of the above. 52 53// Qualifiers are used to disambiguate or sub-select content that shares a URI. 54// This may include specifying a particular commit or branch, in the case of 55// URIs referencing a repository; they could also be used to specify a 56// particular subdirectory of a repository or tarball. Qualifiers may also be 57// used to ensure content matches what the client expects, even when there is 58// no ambiguity to be had - for example, a qualifier specifying a checksum 59// value. 60// 61// In cases where the semantics of the request are not immediately clear from 62// the URL and/or qualifiers - e.g. dictated by URL scheme - it is recommended 63// to use an additional qualifier to remove the ambiguity. The `resource_type` 64// qualifier is recommended for this purpose. 65// 66// Qualifiers may be supplied in any order. 67message Qualifier { 68 // The "name" of the qualifier, for example "resource_type". 69 // No separation is made between 'standard' and 'nonstandard' 70 // qualifiers, in accordance with https://tools.ietf.org/html/rfc6648, 71 // however implementers *SHOULD* take care to avoid ambiguity. 72 string name = 1; 73 74 // The "value" of the qualifier. Semantics will be dictated by the name. 75 string value = 2; 76} 77 78// The Fetch service resolves or fetches assets referenced by URI and 79// Qualifiers, returning a Digest for the content in 80// [ContentAddressableStorage][build.bazel.remote.execution.v2.ContentAddressableStorage]. 81// 82// As with other services in the Remote Execution API, any call may return an 83// error with a [RetryInfo][google.rpc.RetryInfo] error detail providing 84// information about when the client should retry the request; clients SHOULD 85// respect the information provided. 86service Fetch { 87 // Resolve or fetch referenced assets, making them available to the caller and 88 // other consumers in the [ContentAddressableStorage][build.bazel.remote.execution.v2.ContentAddressableStorage]. 89 // 90 // Servers *MAY* fetch content that they do not already have cached, for any 91 // URLs they support. 92 // 93 // Servers *SHOULD* ensure that referenced files are present in the CAS at the 94 // time of the response, and (if supported) that they will remain available 95 // for a reasonable period of time. The lifetimes of the referenced blobs *SHOULD* 96 // be increased if necessary and applicable. 97 // In the event that a client receives a reference to content that is no 98 // longer present, it *MAY* re-issue the request with 99 // `oldest_content_accepted` set to a more recent timestamp than the original 100 // attempt, to induce a re-fetch from origin. 101 // 102 // Servers *MAY* cache fetched content and reuse it for subsequent requests, 103 // subject to `oldest_content_accepted`. 104 // 105 // Servers *MAY* support the complementary [Push][build.bazel.remote.asset.v1.Push] 106 // API and allow content to be directly inserted for use in future fetch 107 // responses. 108 // 109 // Servers *MUST* ensure Fetch'd content matches all the specified 110 // qualifiers except in the case of previously Push'd resources, for which 111 // the server *MAY* trust the pushing client to have set the qualifiers 112 // correctly, without validation. 113 // 114 // Servers not implementing the complementary [Push][build.bazel.remote.asset.v1.Push] 115 // API *MUST* reject requests containing qualifiers it does not support. 116 // 117 // Servers *MAY* transform assets as part of the fetch. For example a 118 // tarball fetched by [FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory] 119 // might be unpacked, or a Git repository 120 // fetched by [FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob] 121 // might be passed through `git-archive`. 122 // 123 // Errors handling the requested assets will be returned as gRPC Status errors 124 // here; errors outside the server's control will be returned inline in the 125 // `status` field of the response (see comment there for details). 126 // The possible RPC errors include: 127 // * `INVALID_ARGUMENT`: One or more arguments were invalid, such as a 128 // qualifier that is not supported by the server. 129 // * `RESOURCE_EXHAUSTED`: There is insufficient quota of some resource to 130 // perform the requested operation. The client may retry after a delay. 131 // * `UNAVAILABLE`: Due to a transient condition the operation could not be 132 // completed. The client should retry. 133 // * `INTERNAL`: An internal error occurred while performing the operation. 134 // The client should retry. 135 // * `DEADLINE_EXCEEDED`: The fetch could not be completed within the given 136 // RPC deadline. The client should retry for at least as long as the value 137 // provided in `timeout` field of the request. 138 // 139 // In the case of unsupported qualifiers, the server *SHOULD* additionally 140 // send a [BadRequest][google.rpc.BadRequest] error detail where, for each 141 // unsupported qualifier, there is a `FieldViolation` with a `field` of 142 // `qualifiers.name` and a `description` of `"{qualifier}" not supported` 143 // indicating the name of the unsupported qualifier. 144 rpc FetchBlob(FetchBlobRequest) returns (FetchBlobResponse) { 145 option (google.api.http) = { post: "/v1/{instance_name=**}/assets:fetchBlob" body: "*" }; 146 } 147 rpc FetchDirectory(FetchDirectoryRequest) returns (FetchDirectoryResponse) { 148 option (google.api.http) = { post: "/v1/{instance_name=**}/assets:fetchDirectory" body: "*" }; 149 } 150} 151 152// A request message for 153// [Fetch.FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob]. 154message FetchBlobRequest { 155 // The instance of the execution system to operate against. A server may 156 // support multiple instances of the execution system (with their own workers, 157 // storage, caches, etc.). The server MAY require use of this field to select 158 // between them in an implementation-defined fashion, otherwise it can be 159 // omitted. 160 string instance_name = 1; 161 162 // The timeout for the underlying fetch, if content needs to be retrieved from 163 // origin. 164 // 165 // If unset, the server *MAY* apply an implementation-defined timeout. 166 // 167 // If set, and the user-provided timeout exceeds the RPC deadline, the server 168 // *SHOULD* keep the fetch going after the RPC completes, to be made 169 // available for future Fetch calls. The server may also enforce (via clamping 170 // and/or an INVALID_ARGUMENT error) implementation-defined minimum and 171 // maximum timeout values. 172 // 173 // If this timeout is exceeded on an attempt to retrieve content from origin 174 // the client will receive DEADLINE_EXCEEDED in [FetchBlobResponse.status]. 175 google.protobuf.Duration timeout = 2; 176 177 // The oldest content the client is willing to accept, as measured from the 178 // time it was Push'd or when the underlying retrieval from origin was 179 // started. 180 // Upon retries of Fetch requests that cannot be completed within a single 181 // RPC, clients *SHOULD* provide the same value for subsequent requests as the 182 // original, to simplify combining the request with the previous attempt. 183 // 184 // If unset, the client *SHOULD* accept content of any age. 185 google.protobuf.Timestamp oldest_content_accepted = 3; 186 187 // The URI(s) of the content to fetch. These may be resources that the server 188 // can directly fetch from origin, in which case multiple URIs *SHOULD* 189 // represent the same content available at different locations (such as an 190 // origin and secondary mirrors). These may also be URIs for content known to 191 // the server through other mechanisms, e.g. pushed via the [Push][build.bazel.remote.asset.v1.Push] 192 // service. 193 // 194 // Clients *MUST* supply at least one URI. Servers *MAY* match any one of the 195 // supplied URIs. 196 repeated string uris = 4; 197 198 // Qualifiers sub-specifying the content to fetch - see comments on 199 // [Qualifier][build.bazel.remote.asset.v1.Qualifier]. 200 // The same qualifiers apply to all URIs. 201 // 202 // Specified qualifier names *MUST* be unique. 203 repeated Qualifier qualifiers = 5; 204 205 // The digest function the server must use to compute the digest. 206 // 207 // If unset, the server SHOULD default to SHA256. 208 build.bazel.remote.execution.v2.DigestFunction.Value digest_function = 6; 209} 210 211// A response message for 212// [Fetch.FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob]. 213message FetchBlobResponse { 214 // If the status has a code other than `OK`, it indicates that the operation 215 // was unable to be completed for reasons outside the servers' control. 216 // The possible fetch errors include: 217 // * `DEADLINE_EXCEEDED`: The operation could not be completed within the 218 // specified timeout. 219 // * `NOT_FOUND`: The requested asset was not found at the specified location. 220 // * `PERMISSION_DENIED`: The request was rejected by a remote server, or 221 // requested an asset from a disallowed origin. 222 // * `ABORTED`: The operation could not be completed, typically due to a 223 // failed consistency check. 224 // * `RESOURCE_EXHAUSTED`: There is insufficient quota of some resource to 225 // perform the requested operation. The client may retry after a delay. 226 google.rpc.Status status = 1; 227 228 // The uri from the request that resulted in a successful retrieval, or from 229 // which the error indicated in `status` was obtained. 230 string uri = 2; 231 232 // Any qualifiers known to the server and of interest to clients. 233 repeated Qualifier qualifiers = 3; 234 235 // A minimum timestamp the content is expected to be available through. 236 // Servers *MAY* omit this field, if not known with confidence. 237 google.protobuf.Timestamp expires_at = 4; 238 239 // The result of the fetch, if the status had code `OK`. 240 // The digest of the file's contents, available for download through the CAS. 241 build.bazel.remote.execution.v2.Digest blob_digest = 5; 242 243 // This field SHOULD be set to the digest function that was used by the server 244 // to compute [FetchBlobResponse.blob_digest]. 245 // Clients could use this to determine whether the server honors 246 // [FetchBlobRequest.digest_function] that was set in the request. 247 // 248 // If unset, clients SHOULD default to use SHA256 regardless of the requested 249 // [FetchBlobRequest.digest_function]. 250 build.bazel.remote.execution.v2.DigestFunction.Value digest_function = 6; 251} 252 253// A request message for 254// [Fetch.FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory]. 255message FetchDirectoryRequest { 256 // The instance of the execution system to operate against. A server may 257 // support multiple instances of the execution system (with their own workers, 258 // storage, caches, etc.). The server MAY require use of this field to select 259 // between them in an implementation-defined fashion, otherwise it can be 260 // omitted. 261 string instance_name = 1; 262 263 // The timeout for the underlying fetch, if content needs to be retrieved from 264 // origin. This value is allowed to exceed the RPC deadline, in which case the 265 // server *SHOULD* keep the fetch going after the RPC completes, to be made 266 // available for future Fetch calls. 267 // 268 // If this timeout is exceeded on an attempt to retrieve content from origin 269 // the client will receive DEADLINE_EXCEEDED in [FetchDirectoryResponse.status]. 270 google.protobuf.Duration timeout = 2; 271 272 // The oldest content the client is willing to accept, as measured from the 273 // time it was Push'd or when the underlying retrieval from origin was 274 // started. 275 // Upon retries of Fetch requests that cannot be completed within a single 276 // RPC, clients *SHOULD* provide the same value for subsequent requests as the 277 // original, to simplify combining the request with the previous attempt. 278 // 279 // If unset, the client *SHOULD* accept content of any age. 280 google.protobuf.Timestamp oldest_content_accepted = 3; 281 282 // The URI(s) of the content to fetch. These may be resources that the server 283 // can directly fetch from origin, in which case multiple URIs *SHOULD* 284 // represent the same content available at different locations (such as an 285 // origin and secondary mirrors). These may also be URIs for content known to 286 // the server through other mechanisms, e.g. pushed via the [Push][build.bazel.remote.asset.v1.Push] 287 // service. 288 // 289 // Clients *MUST* supply at least one URI. Servers *MAY* match any one of the 290 // supplied URIs. 291 repeated string uris = 4; 292 293 // Qualifiers sub-specifying the content to fetch - see comments on 294 // [Qualifier][build.bazel.remote.asset.v1.Qualifier]. 295 // The same qualifiers apply to all URIs. 296 // 297 // Specified qualifier names *MUST* be unique. 298 repeated Qualifier qualifiers = 5; 299 300 // The digest function the server must use to compute the digest. 301 // 302 // If unset, the server SHOULD default to SHA256. 303 build.bazel.remote.execution.v2.DigestFunction.Value digest_function = 6; 304} 305 306// A response message for 307// [Fetch.FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory]. 308message FetchDirectoryResponse { 309 // If the status has a code other than `OK`, it indicates that the operation 310 // was unable to be completed for reasons outside the servers' control. 311 // The possible fetch errors include: 312 // * `DEADLINE_EXCEEDED`: The operation could not be completed within the 313 // specified timeout. 314 // * `NOT_FOUND`: The requested asset was not found at the specified location. 315 // * `PERMISSION_DENIED`: The request was rejected by a remote server, or 316 // requested an asset from a disallowed origin. 317 // * `ABORTED`: The operation could not be completed, typically due to a 318 // failed consistency check. 319 // * `RESOURCE_EXHAUSTED`: There is insufficient quota of some resource to 320 // perform the requested operation. The client may retry after a delay. 321 google.rpc.Status status = 1; 322 323 // The uri from the request that resulted in a successful retrieval, or from 324 // which the error indicated in `status` was obtained. 325 string uri = 2; 326 327 // Any qualifiers known to the server and of interest to clients. 328 repeated Qualifier qualifiers = 3; 329 330 // A minimum timestamp the content is expected to be available through. 331 // Servers *MAY* omit this field, if not known with confidence. 332 google.protobuf.Timestamp expires_at = 4; 333 334 // The result of the fetch, if the status had code `OK`. 335 // the root digest of a directory tree, suitable for fetching via 336 // [ContentAddressableStorage.GetTree]. 337 build.bazel.remote.execution.v2.Digest root_directory_digest = 5; 338 339 // This field SHOULD be set to the digest function that was used by the server 340 // to compute [FetchBlobResponse.root_directory_digest]. 341 // Clients could use this to determine whether the server honors 342 // [FetchDirectoryRequest.digest_function] that was set in the request. 343 // 344 // If unset, clients SHOULD default to use SHA256 regardless of the requested 345 // [FetchDirectoryRequest.digest_function]. 346 build.bazel.remote.execution.v2.DigestFunction.Value digest_function = 6; 347} 348 349// The Push service is complementary to the Fetch, and allows for 350// associating contents of URLs to be returned in future Fetch API calls. 351// 352// As with other services in the Remote Execution API, any call may return an 353// error with a [RetryInfo][google.rpc.RetryInfo] error detail providing 354// information about when the client should retry the request; clients SHOULD 355// respect the information provided. 356service Push { 357 // These APIs associate the identifying information of a resource, as 358 // indicated by URI and optionally Qualifiers, with content available in the 359 // CAS. For example, associating a repository url and a commit id with a 360 // Directory Digest. 361 // 362 // Servers *SHOULD* only allow trusted clients to associate content, and *MAY* 363 // only allow certain URIs to be pushed. 364 // 365 // Clients *MUST* ensure associated content is available in CAS prior to 366 // pushing. 367 // 368 // Clients *MUST* ensure the Qualifiers listed correctly match the contents, 369 // and Servers *MAY* trust these values without validation. 370 // Fetch servers *MAY* require exact match of all qualifiers when returning 371 // content previously pushed, or allow fetching content with only a subset of 372 // the qualifiers specified on Push. 373 // 374 // Clients can specify expiration information that the server *SHOULD* 375 // respect. Subsequent requests can be used to alter the expiration time. 376 // 377 // A minimal compliant Fetch implementation may support only Push'd content 378 // and return `NOT_FOUND` for any resource that was not pushed first. 379 // Alternatively, a compliant implementation may choose to not support Push 380 // and only return resources that can be Fetch'd from origin. 381 // 382 // Errors will be returned as gRPC Status errors. 383 // The possible RPC errors include: 384 // * `INVALID_ARGUMENT`: One or more arguments to the RPC were invalid. 385 // * `RESOURCE_EXHAUSTED`: There is insufficient quota of some resource to 386 // perform the requested operation. The client may retry after a delay. 387 // * `UNAVAILABLE`: Due to a transient condition the operation could not be 388 // completed. The client should retry. 389 // * `INTERNAL`: An internal error occurred while performing the operation. 390 // The client should retry. 391 rpc PushBlob(PushBlobRequest) returns (PushBlobResponse) { 392 option (google.api.http) = { post: "/v1/{instance_name=**}/assets:pushBlob" body: "*" }; 393 } 394 395 rpc PushDirectory(PushDirectoryRequest) returns (PushDirectoryResponse) { 396 option (google.api.http) = { post: "/v1/{instance_name=**}/assets:pushDirectory" body: "*" }; 397 } 398} 399 400// A request message for 401// [Push.PushBlob][build.bazel.remote.asset.v1.Push.PushBlob]. 402message PushBlobRequest { 403 // The instance of the execution system to operate against. A server may 404 // support multiple instances of the execution system (with their own workers, 405 // storage, caches, etc.). The server MAY require use of this field to select 406 // between them in an implementation-defined fashion, otherwise it can be 407 // omitted. 408 string instance_name = 1; 409 410 // The URI(s) of the content to associate. If multiple URIs are specified, the 411 // pushed content will be available to fetch by specifying any of them. 412 repeated string uris = 2; 413 414 // Qualifiers sub-specifying the content that is being pushed - see comments 415 // on [Qualifier][build.bazel.remote.asset.v1.Qualifier]. 416 // The same qualifiers apply to all URIs. 417 repeated Qualifier qualifiers = 3; 418 419 // A time after which this content should stop being returned via [FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob]. 420 // Servers *MAY* expire content early, e.g. due to storage pressure. 421 google.protobuf.Timestamp expire_at = 4; 422 423 // The blob to associate. 424 build.bazel.remote.execution.v2.Digest blob_digest = 5; 425 426 // Referenced blobs or directories that need to not expire before expiration 427 // of this association, in addition to `blob_digest` itself. 428 // These fields are hints - clients *MAY* omit them, and servers *SHOULD* 429 // respect them, at the risk of increased incidents of Fetch responses 430 // indirectly referencing unavailable blobs. 431 repeated build.bazel.remote.execution.v2.Digest references_blobs = 6; 432 repeated build.bazel.remote.execution.v2.Digest references_directories = 7; 433 434 // The digest function that was used to compute the blob digest. 435 // 436 // If the digest function used is one of MD5, MURMUR3, SHA1, SHA256, 437 // SHA384, SHA512, or VSO, the client MAY leave this field unset. In 438 // that case the server SHOULD infer the digest function using the 439 // length of the action digest hash and the digest functions announced 440 // in the server's capabilities. 441 build.bazel.remote.execution.v2.DigestFunction.Value digest_function = 8; 442} 443 444// A response message for 445// [Push.PushBlob][build.bazel.remote.asset.v1.Push.PushBlob]. 446message PushBlobResponse { /* empty */ } 447 448// A request message for 449// [Push.PushDirectory][build.bazel.remote.asset.v1.Push.PushDirectory]. 450message PushDirectoryRequest { 451 // The instance of the execution system to operate against. A server may 452 // support multiple instances of the execution system (with their own workers, 453 // storage, caches, etc.). The server MAY require use of this field to select 454 // between them in an implementation-defined fashion, otherwise it can be 455 // omitted. 456 string instance_name = 1; 457 458 // The URI(s) of the content to associate. If multiple URIs are specified, the 459 // pushed content will be available to fetch by specifying any of them. 460 repeated string uris = 2; 461 462 // Qualifiers sub-specifying the content that is being pushed - see comments 463 // on [Qualifier][build.bazel.remote.asset.v1.Qualifier]. 464 // The same qualifiers apply to all URIs. 465 repeated Qualifier qualifiers = 3; 466 467 // A time after which this content should stop being returned via 468 // [FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory]. 469 // Servers *MAY* expire content early, e.g. due to storage pressure. 470 google.protobuf.Timestamp expire_at = 4; 471 472 // Directory to associate 473 build.bazel.remote.execution.v2.Digest root_directory_digest = 5; 474 475 // Referenced blobs or directories that need to not expire before expiration 476 // of this association, in addition to `root_directory_digest` itself. 477 // These fields are hints - clients *MAY* omit them, and servers *SHOULD* 478 // respect them, at the risk of increased incidents of Fetch responses 479 // indirectly referencing unavailable blobs. 480 repeated build.bazel.remote.execution.v2.Digest references_blobs = 6; 481 repeated build.bazel.remote.execution.v2.Digest references_directories = 7; 482 483 // The digest function that was used to compute blob digests. 484 // 485 // If the digest function used is one of MD5, MURMUR3, SHA1, SHA256, 486 // SHA384, SHA512, or VSO, the client MAY leave this field unset. In 487 // that case the server SHOULD infer the digest function using the 488 // length of the action digest hash and the digest functions announced 489 // in the server's capabilities. 490 build.bazel.remote.execution.v2.DigestFunction.Value digest_function = 8; 491} 492 493// A response message for 494// [Push.PushDirectory][build.bazel.remote.asset.v1.Push.PushDirectory]. 495message PushDirectoryResponse { /* empty */ } 496