summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.van.berkom@gmail.com>2020-08-19 11:28:17 +0000
committerTristan Van Berkom <tristan.van.berkom@gmail.com>2020-08-19 11:28:17 +0000
commitd928a54ac7925fdbd1a7d321a86b40bb25732f69 (patch)
treedd3f42dcfee3bd55712f3d09833f9658df6f827d
parentd901fcf11e43b105c47ac51f5435a24482d06e5f (diff)
parent1d88533b9c3f8e70ed009171ae4f444910bf0418 (diff)
downloadbuildstream-d928a54ac7925fdbd1a7d321a86b40bb25732f69.tar.gz
Merge branch 'abderrahim/remote-asset-bst1' into 'bst-1'
[bst-1] cascache.py: allow using Remote Asset for storing refs See merge request BuildStream/buildstream!2000
-rw-r--r--buildstream/_artifactcache/cascache.py124
-rw-r--r--buildstream/_protos/build/bazel/remote/asset/__init__.py0
-rw-r--r--buildstream/_protos/build/bazel/remote/asset/v1/__init__.py0
-rw-r--r--buildstream/_protos/build/bazel/remote/asset/v1/remote_asset.proto445
-rw-r--r--buildstream/_protos/build/bazel/remote/asset/v1/remote_asset_pb2.py666
-rw-r--r--buildstream/_protos/build/bazel/remote/asset/v1/remote_asset_pb2_grpc.py324
6 files changed, 1530 insertions, 29 deletions
diff --git a/buildstream/_artifactcache/cascache.py b/buildstream/_artifactcache/cascache.py
index 645f2dad7..27020a099 100644
--- a/buildstream/_artifactcache/cascache.py
+++ b/buildstream/_artifactcache/cascache.py
@@ -31,6 +31,7 @@ import grpc
from .._protos.google.bytestream import bytestream_pb2, bytestream_pb2_grpc
from .._protos.build.bazel.remote.execution.v2 import remote_execution_pb2, remote_execution_pb2_grpc
+from .._protos.build.bazel.remote.asset.v1 import remote_asset_pb2, remote_asset_pb2_grpc
from .._protos.buildstream.v2 import buildstream_pb2, buildstream_pb2_grpc
from .. import utils
@@ -44,6 +45,8 @@ _MAX_PAYLOAD_BYTES = 1024 * 1024
# How often is a keepalive ping sent to the server to make sure the transport is still alive
_KEEPALIVE_TIME_MS = 60000
+REMOTE_ASSET_URN_TEMPLATE = "urn:fdc:buildstream.build:2020:v1:{}"
+
class _Attempt():
@@ -215,16 +218,23 @@ class CASCache():
remote = CASRemote(remote_spec)
remote.init()
- request = buildstream_pb2.StatusRequest()
- for attempt in _retry():
- with attempt:
- response = remote.ref_storage.Status(request)
-
- if remote_spec.push and not response.allow_updates:
- q.put('CAS server does not allow push')
+ if remote.asset_fetch_supported:
+ if remote_spec.push and not remote.asset_push_supported:
+ q.put('Remote Asset server does not allow push')
+ else:
+ # No error
+ q.put(None)
else:
- # No error
- q.put(None)
+ request = buildstream_pb2.StatusRequest()
+ for attempt in _retry():
+ with attempt:
+ response = remote.ref_storage.Status(request)
+
+ if remote_spec.push and not response.allow_updates:
+ q.put('CAS server does not allow push')
+ else:
+ # No error
+ q.put(None)
except grpc.RpcError as e:
# str(e) is too verbose for errors reported to the user
@@ -251,15 +261,24 @@ class CASCache():
try:
remote.init()
- request = buildstream_pb2.GetReferenceRequest()
- request.key = ref
- for attempt in _retry():
- with attempt:
- response = remote.ref_storage.GetReference(request)
+ if remote.asset_fetch_supported:
+ request = remote_asset_pb2.FetchDirectoryRequest()
+ request.uris.append(REMOTE_ASSET_URN_TEMPLATE.format(ref))
+ for attempt in _retry():
+ with attempt:
+ response = remote.remote_asset_fetch.FetchDirectory(request)
+ digest = response.root_directory_digest
+ else:
+ request = buildstream_pb2.GetReferenceRequest()
+ request.key = ref
+ for attempt in _retry():
+ with attempt:
+ response = remote.ref_storage.GetReference(request)
+ digest = response.digest
tree = remote_execution_pb2.Digest()
- tree.hash = response.digest.hash
- tree.size_bytes = response.digest.size_bytes
+ tree.hash = digest.hash
+ tree.size_bytes = digest.size_bytes
self._fetch_directory(remote, tree)
@@ -308,13 +327,23 @@ class CASCache():
# Check whether ref is already on the server in which case
# there is no need to push the ref
try:
- request = buildstream_pb2.GetReferenceRequest()
- request.key = ref
- for attempt in _retry():
- with attempt:
- response = remote.ref_storage.GetReference(request)
+ if remote.asset_fetch_supported:
+ request = remote_asset_pb2.FetchDirectoryRequest()
+ request.uris.append(REMOTE_ASSET_URN_TEMPLATE.format(ref))
+ for attempt in _retry():
+ with attempt:
+ response = remote.remote_asset_fetch.FetchDirectory(request)
+ digest = response.root_directory_digest
- if response.digest.hash == tree.hash and response.digest.size_bytes == tree.size_bytes:
+ else:
+ request = buildstream_pb2.GetReferenceRequest()
+ request.key = ref
+ for attempt in _retry():
+ with attempt:
+ response = remote.ref_storage.GetReference(request)
+ digest = response.digest
+
+ if digest.hash == tree.hash and digest.size_bytes == tree.size_bytes:
# ref is already on the server with the same tree
continue
@@ -325,13 +354,22 @@ class CASCache():
self._send_directory(remote, tree)
- request = buildstream_pb2.UpdateReferenceRequest()
- request.keys.append(ref)
- request.digest.hash = tree.hash
- request.digest.size_bytes = tree.size_bytes
- for attempt in _retry():
- with attempt:
- remote.ref_storage.UpdateReference(request)
+ if remote.asset_push_supported:
+ request = remote_asset_pb2.PushDirectoryRequest()
+ request.uris.append(REMOTE_ASSET_URN_TEMPLATE.format(ref))
+ request.root_directory_digest.hash = tree.hash
+ request.root_directory_digest.size_bytes = tree.size_bytes
+ for attempt in _retry():
+ with attempt:
+ remote.remote_asset_push.PushDirectory(request)
+ else:
+ request = buildstream_pb2.UpdateReferenceRequest()
+ request.keys.append(ref)
+ request.digest.hash = tree.hash
+ request.digest.size_bytes = tree.size_bytes
+ for attempt in _retry():
+ with attempt:
+ remote.ref_storage.UpdateReference(request)
skipped_remote = False
except grpc.RpcError as e:
@@ -1050,6 +1088,8 @@ class CASRemote():
self.cas = remote_execution_pb2_grpc.ContentAddressableStorageStub(self.channel)
self.capabilities = remote_execution_pb2_grpc.CapabilitiesStub(self.channel)
self.ref_storage = buildstream_pb2_grpc.ReferenceStorageStub(self.channel)
+ self.remote_asset_fetch = remote_asset_pb2_grpc.FetchStub(self.channel)
+ self.remote_asset_push = remote_asset_pb2_grpc.PushStub(self.channel)
self.max_batch_total_size_bytes = _MAX_PAYLOAD_BYTES
try:
@@ -1090,6 +1130,32 @@ class CASRemote():
e.code() != grpc.StatusCode.PERMISSION_DENIED):
raise
+ self.asset_fetch_supported = False
+ try:
+ request = remote_asset_pb2.FetchDirectoryRequest()
+ for attempt in _retry():
+ with attempt:
+ response = self.remote_asset_fetch.FetchDirectory(request)
+ except grpc.RpcError as e:
+ if e.code() == grpc.StatusCode.INVALID_ARGUMENT:
+ # Expected error as the request doesn't specify any URIs.
+ self.asset_fetch_supported = True
+ elif e.code() != grpc.StatusCode.UNIMPLEMENTED:
+ raise
+
+ self.asset_push_supported = False
+ try:
+ request = remote_asset_pb2.PushDirectoryRequest()
+ for attempt in _retry():
+ with attempt:
+ response = self.remote_asset_push.PushDirectory(request)
+ except grpc.RpcError as e:
+ if e.code() == grpc.StatusCode.INVALID_ARGUMENT:
+ # Expected error as the request doesn't specify any URIs.
+ self.asset_push_supported = True
+ elif e.code() != grpc.StatusCode.UNIMPLEMENTED:
+ raise
+
self._initialized = True
diff --git a/buildstream/_protos/build/bazel/remote/asset/__init__.py b/buildstream/_protos/build/bazel/remote/asset/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/buildstream/_protos/build/bazel/remote/asset/__init__.py
diff --git a/buildstream/_protos/build/bazel/remote/asset/v1/__init__.py b/buildstream/_protos/build/bazel/remote/asset/v1/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/buildstream/_protos/build/bazel/remote/asset/v1/__init__.py
diff --git a/buildstream/_protos/build/bazel/remote/asset/v1/remote_asset.proto b/buildstream/_protos/build/bazel/remote/asset/v1/remote_asset.proto
new file mode 100644
index 000000000..60be76411
--- /dev/null
+++ b/buildstream/_protos/build/bazel/remote/asset/v1/remote_asset.proto
@@ -0,0 +1,445 @@
+// Copyright 2020 The Bazel Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package build.bazel.remote.asset.v1;
+
+import "build/bazel/remote/execution/v2/remote_execution.proto";
+import "google/api/annotations.proto";
+import "google/protobuf/duration.proto";
+import "google/protobuf/timestamp.proto";
+import "google/rpc/status.proto";
+
+option csharp_namespace = "Build.Bazel.Remote.Asset.v1";
+option go_package = "remoteasset";
+option java_multiple_files = true;
+option java_outer_classname = "RemoteAssetProto";
+option java_package = "build.bazel.remote.asset.v1";
+option objc_class_prefix = "RA";
+
+// The Remote Asset API provides a mapping from a URI and Qualifiers to
+// Digests.
+//
+// Multiple URIs may be used to refer to the same content. For example, the
+// same tarball may exist at multiple mirrors and thus be retrievable from
+// multiple URLs. When URLs are used, these should refer to actual content as
+// Fetch service implementations may choose to fetch the content directly
+// from the origin. For example, the HEAD of a git repository's active branch
+// can be referred to as:
+//
+// uri: https://github.com/bazelbuild/remote-apis.git
+//
+// URNs may be used to strongly identify content, for instance by using the
+// uuid namespace identifier: urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6.
+// This is most applicable to named content that is Push'd, where the URN
+// serves as an agreed-upon key, but carries no other inherent meaning.
+//
+// Service implementations may choose to support only URLs, only URNs for
+// Push'd content, only other URIs for which the server and client agree upon
+// semantics of, or any mixture of the above.
+
+// Qualifiers are used to disambiguate or sub-select content that shares a URI.
+// This may include specifying a particular commit or branch, in the case of
+// URIs referencing a repository; they could also be used to specify a
+// particular subdirectory of a repository or tarball. Qualifiers may also be
+// used to ensure content matches what the client expects, even when there is
+// no ambiguity to be had - for example, a qualifier specifying a checksum
+// value.
+//
+// In cases where the semantics of the request are not immediately clear from
+// the URL and/or qualifiers - e.g. dictated by URL scheme - it is recommended
+// to use an additional qualifier to remove the ambiguity. The `resource_type`
+// qualifier is recommended for this purpose.
+//
+// Qualifiers may be supplied in any order.
+message Qualifier {
+ // The "name" of the qualifier, for example "resource_type".
+ // No separation is made between 'standard' and 'nonstandard'
+ // qualifiers, in accordance with https://tools.ietf.org/html/rfc6648,
+ // however implementers *SHOULD* take care to avoid ambiguity.
+ string name = 1;
+
+ // The "value" of the qualifier. Semantics will be dictated by the name.
+ string value = 2;
+}
+
+// The Fetch service resolves or fetches assets referenced by URI and
+// Qualifiers, returning a Digest for the content in
+// [ContentAddressableStorage][build.bazel.remote.execution.v2.ContentAddressableStorage].
+//
+// As with other services in the Remote Execution API, any call may return an
+// error with a [RetryInfo][google.rpc.RetryInfo] error detail providing
+// information about when the client should retry the request; clients SHOULD
+// respect the information provided.
+service Fetch {
+ // Resolve or fetch referenced assets, making them available to the caller and
+ // other consumers in the [ContentAddressableStorage][build.bazel.remote.execution.v2.ContentAddressableStorage].
+ //
+ // Servers *MAY* fetch content that they do not already have cached, for any
+ // URLs they support.
+ //
+ // Servers *SHOULD* ensure that referenced files are present in the CAS at the
+ // time of the response, and (if supported) that they will remain available
+ // for a reasonable period of time. The TTLs of the referenced blobs *SHOULD*
+ // be increased if necessary and applicable.
+ // In the event that a client receives a reference to content that is no
+ // longer present, it *MAY* re-issue the request with
+ // `oldest_content_accepted` set to a more recent timestamp than the original
+ // attempt, to induce a re-fetch from origin.
+ //
+ // Servers *MAY* cache fetched content and reuse it for subsequent requests,
+ // subject to `oldest_content_accepted`.
+ //
+ // Servers *MAY* support the complementary [Push][build.bazel.remote.asset.v1.Push]
+ // API and allow content to be directly inserted for use in future fetch
+ // responses.
+ //
+ // Servers *MUST* ensure Fetch'd content matches all the specified
+ // qualifiers except in the case of previously Push'd resources, for which
+ // the server *MAY* trust the pushing client to have set the qualifiers
+ // correctly, without validation.
+ //
+ // Servers not implementing the complementary [Push][build.bazel.remote.asset.v1.Push]
+ // API *MUST* reject requests containing qualifiers it does not support.
+ //
+ // Servers *MAY* transform assets as part of the fetch. For example a
+ // tarball fetched by [FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory]
+ // might be unpacked, or a Git repository
+ // fetched by [FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob]
+ // might be passed through `git-archive`.
+ //
+ // Errors handling the requested assets will be returned as gRPC Status errors
+ // here; errors outside the server's control will be returned inline in the
+ // `status` field of the response (see comment there for details).
+ // The possible RPC errors include:
+ // * `INVALID_ARGUMENT`: One or more arguments were invalid, such as a
+ // qualifier that is not supported by the server.
+ // * `RESOURCE_EXHAUSTED`: There is insufficient quota of some resource to
+ // perform the requested operation. The client may retry after a delay.
+ // * `UNAVAILABLE`: Due to a transient condition the operation could not be
+ // completed. The client should retry.
+ // * `INTERNAL`: An internal error occurred while performing the operation.
+ // The client should retry.
+ // * `DEADLINE_EXCEEDED`: The fetch could not be completed within the given
+ // RPC deadline. The client should retry for at least as long as the value
+ // provided in `timeout` field of the request.
+ //
+ // In the case of unsupported qualifiers, the server *SHOULD* additionally
+ // send a [BadRequest][google.rpc.BadRequest] error detail where, for each
+ // unsupported qualifier, there is a `FieldViolation` with a `field` of
+ // `qualifiers.name` and a `description` of `"{qualifier}" not supported`
+ // indicating the name of the unsupported qualifier.
+ rpc FetchBlob(FetchBlobRequest) returns (FetchBlobResponse) {
+ option (google.api.http) = { post: "/v1/{instance_name=**}/assets:fetchBlob" body: "*" };
+ }
+ rpc FetchDirectory(FetchDirectoryRequest) returns (FetchDirectoryResponse) {
+ option (google.api.http) = { post: "/v1/{instance_name=**}/assets:fetchDirectory" body: "*" };
+ }
+}
+
+// A request message for
+// [Fetch.FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob].
+message FetchBlobRequest {
+ // The instance of the execution system to operate against. A server may
+ // support multiple instances of the execution system (with their own workers,
+ // storage, caches, etc.). The server MAY require use of this field to select
+ // between them in an implementation-defined fashion, otherwise it can be
+ // omitted.
+ string instance_name = 1;
+
+ // The timeout for the underlying fetch, if content needs to be retrieved from
+ // origin.
+ //
+ // If unset, the server *MAY* apply an implementation-defined timeout.
+ //
+ // If set, and the user-provided timeout exceeds the RPC deadline, the server
+ // *SHOULD* keep the fetch going after the RPC completes, to be made
+ // available for future Fetch calls. The server may also enforce (via clamping
+ // and/or an INVALID_ARGUMENT error) implementation-defined minimum and
+ // maximum timeout values.
+ //
+ // If this timeout is exceeded on an attempt to retrieve content from origin
+ // the client will receive DEADLINE_EXCEEDED in [FetchBlobResponse.status].
+ google.protobuf.Duration timeout = 2;
+
+ // The oldest content the client is willing to accept, as measured from the
+ // time it was Push'd or when the underlying retrieval from origin was
+ // started.
+ // Upon retries of Fetch requests that cannot be completed within a single
+ // RPC, clients *SHOULD* provide the same value for subsequent requests as the
+ // original, to simplify combining the request with the previous attempt.
+ //
+ // If unset, the client *SHOULD* accept content of any age.
+ google.protobuf.Timestamp oldest_content_accepted = 3;
+
+ // The URI(s) of the content to fetch. These may be resources that the server
+ // can directly fetch from origin, in which case multiple URIs *SHOULD*
+ // represent the same content available at different locations (such as an
+ // origin and secondary mirrors). These may also be URIs for content known to
+ // the server through other mechanisms, e.g. pushed via the [Push][build.bazel.remote.asset.v1.Push]
+ // service.
+ //
+ // Clients *MUST* supply at least one URI. Servers *MAY* match any one of the
+ // supplied URIs.
+ repeated string uris = 4;
+
+ // Qualifiers sub-specifying the content to fetch - see comments on
+ // [Qualifier][build.bazel.remote.asset.v1.Qualifier].
+ // The same qualifiers apply to all URIs.
+ //
+ // Specified qualifier names *MUST* be unique.
+ repeated Qualifier qualifiers = 5;
+}
+
+// A response message for
+// [Fetch.FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob].
+message FetchBlobResponse {
+ // If the status has a code other than `OK`, it indicates that the operation
+ // was unable to be completed for reasons outside the servers' control.
+ // The possible fetch errors include:
+ // * `DEADLINE_EXCEEDED`: The operation could not be completed within the
+ // specified timeout.
+ // * `NOT_FOUND`: The requested asset was not found at the specified location.
+ // * `PERMISSION_DENIED`: The request was rejected by a remote server, or
+ // requested an asset from a disallowed origin.
+ // * `ABORTED`: The operation could not be completed, typically due to a
+ // failed consistency check.
+ google.rpc.Status status = 1;
+
+ // The uri from the request that resulted in a successful retrieval, or from
+ // which the error indicated in `status` was obtained.
+ string uri = 2;
+
+ // Any qualifiers known to the server and of interest to clients.
+ repeated Qualifier qualifiers = 3;
+
+ // A minimum timestamp the content is expected to be available through.
+ // Servers *MAY* omit this field, if not known with confidence.
+ google.protobuf.Timestamp expires_at = 4;
+
+ // The result of the fetch, if the status had code `OK`.
+ // The digest of the file's contents, available for download through the CAS.
+ build.bazel.remote.execution.v2.Digest blob_digest = 5;
+}
+
+// A request message for
+// [Fetch.FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory].
+message FetchDirectoryRequest {
+ // The instance of the execution system to operate against. A server may
+ // support multiple instances of the execution system (with their own workers,
+ // storage, caches, etc.). The server MAY require use of this field to select
+ // between them in an implementation-defined fashion, otherwise it can be
+ // omitted.
+ string instance_name = 1;
+
+ // The timeout for the underlying fetch, if content needs to be retrieved from
+ // origin. This value is allowed to exceed the RPC deadline, in which case the
+ // server *SHOULD* keep the fetch going after the RPC completes, to be made
+ // available for future Fetch calls.
+ //
+ // If this timeout is exceeded on an attempt to retrieve content from origin
+ // the client will receive DEADLINE_EXCEEDED in [FetchDirectoryResponse.status].
+ google.protobuf.Duration timeout = 2;
+
+ // The oldest content the client is willing to accept, as measured from the
+ // time it was Push'd or when the underlying retrieval from origin was
+ // started.
+ // Upon retries of Fetch requests that cannot be completed within a single
+ // RPC, clients *SHOULD* provide the same value for subsequent requests as the
+ // original, to simplify combining the request with the previous attempt.
+ //
+ // If unset, the client *SHOULD* accept content of any age.
+ google.protobuf.Timestamp oldest_content_accepted = 3;
+
+ // The URI(s) of the content to fetch. These may be resources that the server
+ // can directly fetch from origin, in which case multiple URIs *SHOULD*
+ // represent the same content available at different locations (such as an
+ // origin and secondary mirrors). These may also be URIs for content known to
+ // the server through other mechanisms, e.g. pushed via the [Push][build.bazel.remote.asset.v1.Push]
+ // service.
+ //
+ // Clients *MUST* supply at least one URI. Servers *MAY* match any one of the
+ // supplied URIs.
+ repeated string uris = 4;
+
+ // Qualifiers sub-specifying the content to fetch - see comments on
+ // [Qualifier][build.bazel.remote.asset.v1.Qualifier].
+ // The same qualifiers apply to all URIs.
+ //
+ // Specified qualifier names *MUST* be unique.
+ repeated Qualifier qualifiers = 5;
+}
+
+// A response message for
+// [Fetch.FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory].
+message FetchDirectoryResponse {
+ // If the status has a code other than `OK`, it indicates that the operation
+ // was unable to be completed for reasons outside the servers' control.
+ // The possible fetch errors include:
+ // * `DEADLINE_EXCEEDED`: The operation could not be completed within the
+ // specified timeout.
+ // * `NOT_FOUND`: The requested asset was not found at the specified location.
+ // * `PERMISSION_DENIED`: The request was rejected by a remote server, or
+ // requested an asset from a disallowed origin.
+ // * `ABORTED`: The operation could not be completed, typically due to a
+ // failed consistency check.
+ google.rpc.Status status = 1;
+
+ // The uri from the request that resulted in a successful retrieval, or from
+ // which the error indicated in `status` was obtained.
+ string uri = 2;
+
+ // Any qualifiers known to the server and of interest to clients.
+ repeated Qualifier qualifiers = 3;
+
+ // A minimum timestamp the content is expected to be available through.
+ // Servers *MAY* omit this field, if not known with confidence.
+ google.protobuf.Timestamp expires_at = 4;
+
+ // The result of the fetch, if the status had code `OK`.
+ // the root digest of a directory tree, suitable for fetching via
+ // [ContentAddressableStorage.GetTree].
+ build.bazel.remote.execution.v2.Digest root_directory_digest = 5;
+}
+
+// The Push service is complementary to the Fetch, and allows for
+// associating contents of URLs to be returned in future Fetch API calls.
+//
+// As with other services in the Remote Execution API, any call may return an
+// error with a [RetryInfo][google.rpc.RetryInfo] error detail providing
+// information about when the client should retry the request; clients SHOULD
+// respect the information provided.
+service Push {
+ // These APIs associate the identifying information of a resource, as
+ // indicated by URI and optionally Qualifiers, with content available in the
+ // CAS. For example, associating a repository url and a commit id with a
+ // Directory Digest.
+ //
+ // Servers *SHOULD* only allow trusted clients to associate content, and *MAY*
+ // only allow certain URIs to be pushed.
+ //
+ // Clients *MUST* ensure associated content is available in CAS prior to
+ // pushing.
+ //
+ // Clients *MUST* ensure the Qualifiers listed correctly match the contents,
+ // and Servers *MAY* trust these values without validation.
+ // Fetch servers *MAY* require exact match of all qualifiers when returning
+ // content previously pushed, or allow fetching content with only a subset of
+ // the qualifiers specified on Push.
+ //
+ // Clients can specify expiration information that the server *SHOULD*
+ // respect. Subsequent requests can be used to alter the expiration time.
+ //
+ // A minimal compliant Fetch implementation may support only Push'd content
+ // and return `NOT_FOUND` for any resource that was not pushed first.
+ // Alternatively, a compliant implementation may choose to not support Push
+ // and only return resources that can be Fetch'd from origin.
+ //
+ // Errors will be returned as gRPC Status errors.
+ // The possible RPC errors include:
+ // * `INVALID_ARGUMENT`: One or more arguments to the RPC were invalid.
+ // * `RESOURCE_EXHAUSTED`: There is insufficient quota of some resource to
+ // perform the requested operation. The client may retry after a delay.
+ // * `UNAVAILABLE`: Due to a transient condition the operation could not be
+ // completed. The client should retry.
+ // * `INTERNAL`: An internal error occurred while performing the operation.
+ // The client should retry.
+ rpc PushBlob(PushBlobRequest) returns (PushBlobResponse) {
+ option (google.api.http) = { post: "/v1/{instance_name=**}/assets:pushBlob" body: "*" };
+ }
+
+ rpc PushDirectory(PushDirectoryRequest) returns (PushDirectoryResponse) {
+ option (google.api.http) = { post: "/v1/{instance_name=**}/assets:pushDirectory" body: "*" };
+ }
+}
+
+// A request message for
+// [Push.PushBlob][build.bazel.remote.asset.v1.Push.PushBlob].
+message PushBlobRequest {
+ // The instance of the execution system to operate against. A server may
+ // support multiple instances of the execution system (with their own workers,
+ // storage, caches, etc.). The server MAY require use of this field to select
+ // between them in an implementation-defined fashion, otherwise it can be
+ // omitted.
+ string instance_name = 1;
+
+ // The URI(s) of the content to associate. If multiple URIs are specified, the
+ // pushed content will be available to fetch by specifying any of them.
+ repeated string uris = 2;
+
+ // Qualifiers sub-specifying the content that is being pushed - see comments
+ // on [Qualifier][build.bazel.remote.asset.v1.Qualifier].
+ // The same qualifiers apply to all URIs.
+ repeated Qualifier qualifiers = 3;
+
+ // A time after which this content should stop being returned via [FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob].
+ // Servers *MAY* expire content early, e.g. due to storage pressure.
+ google.protobuf.Timestamp expire_at = 4;
+
+ // The blob to associate.
+ build.bazel.remote.execution.v2.Digest blob_digest = 5;
+
+ // Referenced blobs or directories that need to not expire before expiration
+ // of this association, in addition to `blob_digest` itself.
+ // These fields are hints - clients *MAY* omit them, and servers *SHOULD*
+ // respect them, at the risk of increased incidents of Fetch responses
+ // indirectly referencing unavailable blobs.
+ repeated build.bazel.remote.execution.v2.Digest references_blobs = 6;
+ repeated build.bazel.remote.execution.v2.Digest references_directories = 7;
+}
+
+// A response message for
+// [Push.PushBlob][build.bazel.remote.asset.v1.Push.PushBlob].
+message PushBlobResponse { /* empty */ }
+
+// A request message for
+// [Push.PushDirectory][build.bazel.remote.asset.v1.Push.PushDirectory].
+message PushDirectoryRequest {
+ // The instance of the execution system to operate against. A server may
+ // support multiple instances of the execution system (with their own workers,
+ // storage, caches, etc.). The server MAY require use of this field to select
+ // between them in an implementation-defined fashion, otherwise it can be
+ // omitted.
+ string instance_name = 1;
+
+ // The URI(s) of the content to associate. If multiple URIs are specified, the
+ // pushed content will be available to fetch by specifying any of them.
+ repeated string uris = 2;
+
+ // Qualifiers sub-specifying the content that is being pushed - see comments
+ // on [Qualifier][build.bazel.remote.asset.v1.Qualifier].
+ // The same qualifiers apply to all URIs.
+ repeated Qualifier qualifiers = 3;
+
+ // A time after which this content should stop being returned via
+ // [FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory].
+ // Servers *MAY* expire content early, e.g. due to storage pressure.
+ google.protobuf.Timestamp expire_at = 4;
+
+ // Directory to associate
+ build.bazel.remote.execution.v2.Digest root_directory_digest = 5;
+
+ // Referenced blobs or directories that need to not expire before expiration
+ // of this association, in addition to `root_directory_digest` itself.
+ // These fields are hints - clients *MAY* omit them, and servers *SHOULD*
+ // respect them, at the risk of increased incidents of Fetch responses
+ // indirectly referencing unavailable blobs.
+ repeated build.bazel.remote.execution.v2.Digest references_blobs = 6;
+ repeated build.bazel.remote.execution.v2.Digest references_directories = 7;
+}
+
+// A response message for
+// [Push.PushDirectory][build.bazel.remote.asset.v1.Push.PushDirectory].
+message PushDirectoryResponse { /* empty */ }
diff --git a/buildstream/_protos/build/bazel/remote/asset/v1/remote_asset_pb2.py b/buildstream/_protos/build/bazel/remote/asset/v1/remote_asset_pb2.py
new file mode 100644
index 000000000..c40df6434
--- /dev/null
+++ b/buildstream/_protos/build/bazel/remote/asset/v1/remote_asset_pb2.py
@@ -0,0 +1,666 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: build/bazel/remote/asset/v1/remote_asset.proto
+
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+from buildstream._protos.build.bazel.remote.execution.v2 import remote_execution_pb2 as build_dot_bazel_dot_remote_dot_execution_dot_v2_dot_remote__execution__pb2
+from buildstream._protos.google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2
+from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2
+from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
+from buildstream._protos.google.rpc import status_pb2 as google_dot_rpc_dot_status__pb2
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+ name='build/bazel/remote/asset/v1/remote_asset.proto',
+ package='build.bazel.remote.asset.v1',
+ syntax='proto3',
+ serialized_options=b'\n\033build.bazel.remote.asset.v1B\020RemoteAssetProtoP\001Z\013remoteasset\242\002\002RA\252\002\033Build.Bazel.Remote.Asset.v1',
+ serialized_pb=b'\n.build/bazel/remote/asset/v1/remote_asset.proto\x12\x1b\x62uild.bazel.remote.asset.v1\x1a\x36\x62uild/bazel/remote/execution/v2/remote_execution.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\"(\n\tQualifier\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\"\xdc\x01\n\x10\x46\x65tchBlobRequest\x12\x15\n\rinstance_name\x18\x01 \x01(\t\x12*\n\x07timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12;\n\x17oldest_content_accepted\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0c\n\x04uris\x18\x04 \x03(\t\x12:\n\nqualifiers\x18\x05 \x03(\x0b\x32&.build.bazel.remote.asset.v1.Qualifier\"\xee\x01\n\x11\x46\x65tchBlobResponse\x12\"\n\x06status\x18\x01 \x01(\x0b\x32\x12.google.rpc.Status\x12\x0b\n\x03uri\x18\x02 \x01(\t\x12:\n\nqualifiers\x18\x03 \x03(\x0b\x32&.build.bazel.remote.asset.v1.Qualifier\x12.\n\nexpires_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12<\n\x0b\x62lob_digest\x18\x05 \x01(\x0b\x32\'.build.bazel.remote.execution.v2.Digest\"\xe1\x01\n\x15\x46\x65tchDirectoryRequest\x12\x15\n\rinstance_name\x18\x01 \x01(\t\x12*\n\x07timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12;\n\x17oldest_content_accepted\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0c\n\x04uris\x18\x04 \x03(\t\x12:\n\nqualifiers\x18\x05 \x03(\x0b\x32&.build.bazel.remote.asset.v1.Qualifier\"\xfd\x01\n\x16\x46\x65tchDirectoryResponse\x12\"\n\x06status\x18\x01 \x01(\x0b\x32\x12.google.rpc.Status\x12\x0b\n\x03uri\x18\x02 \x01(\t\x12:\n\nqualifiers\x18\x03 \x03(\x0b\x32&.build.bazel.remote.asset.v1.Qualifier\x12.\n\nexpires_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x46\n\x15root_directory_digest\x18\x05 \x01(\x0b\x32\'.build.bazel.remote.execution.v2.Digest\"\xeb\x02\n\x0fPushBlobRequest\x12\x15\n\rinstance_name\x18\x01 \x01(\t\x12\x0c\n\x04uris\x18\x02 \x03(\t\x12:\n\nqualifiers\x18\x03 \x03(\x0b\x32&.build.bazel.remote.asset.v1.Qualifier\x12-\n\texpire_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12<\n\x0b\x62lob_digest\x18\x05 \x01(\x0b\x32\'.build.bazel.remote.execution.v2.Digest\x12\x41\n\x10references_blobs\x18\x06 \x03(\x0b\x32\'.build.bazel.remote.execution.v2.Digest\x12G\n\x16references_directories\x18\x07 \x03(\x0b\x32\'.build.bazel.remote.execution.v2.Digest\"\x12\n\x10PushBlobResponse\"\xfa\x02\n\x14PushDirectoryRequest\x12\x15\n\rinstance_name\x18\x01 \x01(\t\x12\x0c\n\x04uris\x18\x02 \x03(\t\x12:\n\nqualifiers\x18\x03 \x03(\x0b\x32&.build.bazel.remote.asset.v1.Qualifier\x12-\n\texpire_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x46\n\x15root_directory_digest\x18\x05 \x01(\x0b\x32\'.build.bazel.remote.execution.v2.Digest\x12\x41\n\x10references_blobs\x18\x06 \x03(\x0b\x32\'.build.bazel.remote.execution.v2.Digest\x12G\n\x16references_directories\x18\x07 \x03(\x0b\x32\'.build.bazel.remote.execution.v2.Digest\"\x17\n\x15PushDirectoryResponse2\xdd\x02\n\x05\x46\x65tch\x12\x9e\x01\n\tFetchBlob\x12-.build.bazel.remote.asset.v1.FetchBlobRequest\x1a..build.bazel.remote.asset.v1.FetchBlobResponse\"2\x82\xd3\xe4\x93\x02,\"\'/v1/{instance_name=**}/assets:fetchBlob:\x01*\x12\xb2\x01\n\x0e\x46\x65tchDirectory\x12\x32.build.bazel.remote.asset.v1.FetchDirectoryRequest\x1a\x33.build.bazel.remote.asset.v1.FetchDirectoryResponse\"7\x82\xd3\xe4\x93\x02\x31\",/v1/{instance_name=**}/assets:fetchDirectory:\x01*2\xd4\x02\n\x04Push\x12\x9a\x01\n\x08PushBlob\x12,.build.bazel.remote.asset.v1.PushBlobRequest\x1a-.build.bazel.remote.asset.v1.PushBlobResponse\"1\x82\xd3\xe4\x93\x02+\"&/v1/{instance_name=**}/assets:pushBlob:\x01*\x12\xae\x01\n\rPushDirectory\x12\x31.build.bazel.remote.asset.v1.PushDirectoryRequest\x1a\x32.build.bazel.remote.asset.v1.PushDirectoryResponse\"6\x82\xd3\xe4\x93\x02\x30\"+/v1/{instance_name=**}/assets:pushDirectory:\x01*Ba\n\x1b\x62uild.bazel.remote.asset.v1B\x10RemoteAssetProtoP\x01Z\x0bremoteasset\xa2\x02\x02RA\xaa\x02\x1b\x42uild.Bazel.Remote.Asset.v1b\x06proto3'
+ ,
+ dependencies=[build_dot_bazel_dot_remote_dot_execution_dot_v2_dot_remote__execution__pb2.DESCRIPTOR,google_dot_api_dot_annotations__pb2.DESCRIPTOR,google_dot_protobuf_dot_duration__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,google_dot_rpc_dot_status__pb2.DESCRIPTOR,])
+
+
+
+
+_QUALIFIER = _descriptor.Descriptor(
+ name='Qualifier',
+ full_name='build.bazel.remote.asset.v1.Qualifier',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='name', full_name='build.bazel.remote.asset.v1.Qualifier.name', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=b"".decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='value', full_name='build.bazel.remote.asset.v1.Qualifier.value', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=b"".decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=255,
+ serialized_end=295,
+)
+
+
+_FETCHBLOBREQUEST = _descriptor.Descriptor(
+ name='FetchBlobRequest',
+ full_name='build.bazel.remote.asset.v1.FetchBlobRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='instance_name', full_name='build.bazel.remote.asset.v1.FetchBlobRequest.instance_name', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=b"".decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='timeout', full_name='build.bazel.remote.asset.v1.FetchBlobRequest.timeout', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='oldest_content_accepted', full_name='build.bazel.remote.asset.v1.FetchBlobRequest.oldest_content_accepted', index=2,
+ number=3, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='uris', full_name='build.bazel.remote.asset.v1.FetchBlobRequest.uris', index=3,
+ number=4, type=9, cpp_type=9, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='qualifiers', full_name='build.bazel.remote.asset.v1.FetchBlobRequest.qualifiers', index=4,
+ number=5, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=298,
+ serialized_end=518,
+)
+
+
+_FETCHBLOBRESPONSE = _descriptor.Descriptor(
+ name='FetchBlobResponse',
+ full_name='build.bazel.remote.asset.v1.FetchBlobResponse',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='status', full_name='build.bazel.remote.asset.v1.FetchBlobResponse.status', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='uri', full_name='build.bazel.remote.asset.v1.FetchBlobResponse.uri', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=b"".decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='qualifiers', full_name='build.bazel.remote.asset.v1.FetchBlobResponse.qualifiers', index=2,
+ number=3, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='expires_at', full_name='build.bazel.remote.asset.v1.FetchBlobResponse.expires_at', index=3,
+ number=4, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='blob_digest', full_name='build.bazel.remote.asset.v1.FetchBlobResponse.blob_digest', index=4,
+ number=5, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=521,
+ serialized_end=759,
+)
+
+
+_FETCHDIRECTORYREQUEST = _descriptor.Descriptor(
+ name='FetchDirectoryRequest',
+ full_name='build.bazel.remote.asset.v1.FetchDirectoryRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='instance_name', full_name='build.bazel.remote.asset.v1.FetchDirectoryRequest.instance_name', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=b"".decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='timeout', full_name='build.bazel.remote.asset.v1.FetchDirectoryRequest.timeout', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='oldest_content_accepted', full_name='build.bazel.remote.asset.v1.FetchDirectoryRequest.oldest_content_accepted', index=2,
+ number=3, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='uris', full_name='build.bazel.remote.asset.v1.FetchDirectoryRequest.uris', index=3,
+ number=4, type=9, cpp_type=9, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='qualifiers', full_name='build.bazel.remote.asset.v1.FetchDirectoryRequest.qualifiers', index=4,
+ number=5, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=762,
+ serialized_end=987,
+)
+
+
+_FETCHDIRECTORYRESPONSE = _descriptor.Descriptor(
+ name='FetchDirectoryResponse',
+ full_name='build.bazel.remote.asset.v1.FetchDirectoryResponse',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='status', full_name='build.bazel.remote.asset.v1.FetchDirectoryResponse.status', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='uri', full_name='build.bazel.remote.asset.v1.FetchDirectoryResponse.uri', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=b"".decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='qualifiers', full_name='build.bazel.remote.asset.v1.FetchDirectoryResponse.qualifiers', index=2,
+ number=3, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='expires_at', full_name='build.bazel.remote.asset.v1.FetchDirectoryResponse.expires_at', index=3,
+ number=4, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='root_directory_digest', full_name='build.bazel.remote.asset.v1.FetchDirectoryResponse.root_directory_digest', index=4,
+ number=5, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=990,
+ serialized_end=1243,
+)
+
+
+_PUSHBLOBREQUEST = _descriptor.Descriptor(
+ name='PushBlobRequest',
+ full_name='build.bazel.remote.asset.v1.PushBlobRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='instance_name', full_name='build.bazel.remote.asset.v1.PushBlobRequest.instance_name', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=b"".decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='uris', full_name='build.bazel.remote.asset.v1.PushBlobRequest.uris', index=1,
+ number=2, type=9, cpp_type=9, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='qualifiers', full_name='build.bazel.remote.asset.v1.PushBlobRequest.qualifiers', index=2,
+ number=3, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='expire_at', full_name='build.bazel.remote.asset.v1.PushBlobRequest.expire_at', index=3,
+ number=4, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='blob_digest', full_name='build.bazel.remote.asset.v1.PushBlobRequest.blob_digest', index=4,
+ number=5, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='references_blobs', full_name='build.bazel.remote.asset.v1.PushBlobRequest.references_blobs', index=5,
+ number=6, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='references_directories', full_name='build.bazel.remote.asset.v1.PushBlobRequest.references_directories', index=6,
+ number=7, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1246,
+ serialized_end=1609,
+)
+
+
+_PUSHBLOBRESPONSE = _descriptor.Descriptor(
+ name='PushBlobResponse',
+ full_name='build.bazel.remote.asset.v1.PushBlobResponse',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1611,
+ serialized_end=1629,
+)
+
+
+_PUSHDIRECTORYREQUEST = _descriptor.Descriptor(
+ name='PushDirectoryRequest',
+ full_name='build.bazel.remote.asset.v1.PushDirectoryRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='instance_name', full_name='build.bazel.remote.asset.v1.PushDirectoryRequest.instance_name', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=b"".decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='uris', full_name='build.bazel.remote.asset.v1.PushDirectoryRequest.uris', index=1,
+ number=2, type=9, cpp_type=9, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='qualifiers', full_name='build.bazel.remote.asset.v1.PushDirectoryRequest.qualifiers', index=2,
+ number=3, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='expire_at', full_name='build.bazel.remote.asset.v1.PushDirectoryRequest.expire_at', index=3,
+ number=4, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='root_directory_digest', full_name='build.bazel.remote.asset.v1.PushDirectoryRequest.root_directory_digest', index=4,
+ number=5, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='references_blobs', full_name='build.bazel.remote.asset.v1.PushDirectoryRequest.references_blobs', index=5,
+ number=6, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='references_directories', full_name='build.bazel.remote.asset.v1.PushDirectoryRequest.references_directories', index=6,
+ number=7, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1632,
+ serialized_end=2010,
+)
+
+
+_PUSHDIRECTORYRESPONSE = _descriptor.Descriptor(
+ name='PushDirectoryResponse',
+ full_name='build.bazel.remote.asset.v1.PushDirectoryResponse',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=2012,
+ serialized_end=2035,
+)
+
+_FETCHBLOBREQUEST.fields_by_name['timeout'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION
+_FETCHBLOBREQUEST.fields_by_name['oldest_content_accepted'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP
+_FETCHBLOBREQUEST.fields_by_name['qualifiers'].message_type = _QUALIFIER
+_FETCHBLOBRESPONSE.fields_by_name['status'].message_type = google_dot_rpc_dot_status__pb2._STATUS
+_FETCHBLOBRESPONSE.fields_by_name['qualifiers'].message_type = _QUALIFIER
+_FETCHBLOBRESPONSE.fields_by_name['expires_at'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP
+_FETCHBLOBRESPONSE.fields_by_name['blob_digest'].message_type = build_dot_bazel_dot_remote_dot_execution_dot_v2_dot_remote__execution__pb2._DIGEST
+_FETCHDIRECTORYREQUEST.fields_by_name['timeout'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION
+_FETCHDIRECTORYREQUEST.fields_by_name['oldest_content_accepted'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP
+_FETCHDIRECTORYREQUEST.fields_by_name['qualifiers'].message_type = _QUALIFIER
+_FETCHDIRECTORYRESPONSE.fields_by_name['status'].message_type = google_dot_rpc_dot_status__pb2._STATUS
+_FETCHDIRECTORYRESPONSE.fields_by_name['qualifiers'].message_type = _QUALIFIER
+_FETCHDIRECTORYRESPONSE.fields_by_name['expires_at'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP
+_FETCHDIRECTORYRESPONSE.fields_by_name['root_directory_digest'].message_type = build_dot_bazel_dot_remote_dot_execution_dot_v2_dot_remote__execution__pb2._DIGEST
+_PUSHBLOBREQUEST.fields_by_name['qualifiers'].message_type = _QUALIFIER
+_PUSHBLOBREQUEST.fields_by_name['expire_at'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP
+_PUSHBLOBREQUEST.fields_by_name['blob_digest'].message_type = build_dot_bazel_dot_remote_dot_execution_dot_v2_dot_remote__execution__pb2._DIGEST
+_PUSHBLOBREQUEST.fields_by_name['references_blobs'].message_type = build_dot_bazel_dot_remote_dot_execution_dot_v2_dot_remote__execution__pb2._DIGEST
+_PUSHBLOBREQUEST.fields_by_name['references_directories'].message_type = build_dot_bazel_dot_remote_dot_execution_dot_v2_dot_remote__execution__pb2._DIGEST
+_PUSHDIRECTORYREQUEST.fields_by_name['qualifiers'].message_type = _QUALIFIER
+_PUSHDIRECTORYREQUEST.fields_by_name['expire_at'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP
+_PUSHDIRECTORYREQUEST.fields_by_name['root_directory_digest'].message_type = build_dot_bazel_dot_remote_dot_execution_dot_v2_dot_remote__execution__pb2._DIGEST
+_PUSHDIRECTORYREQUEST.fields_by_name['references_blobs'].message_type = build_dot_bazel_dot_remote_dot_execution_dot_v2_dot_remote__execution__pb2._DIGEST
+_PUSHDIRECTORYREQUEST.fields_by_name['references_directories'].message_type = build_dot_bazel_dot_remote_dot_execution_dot_v2_dot_remote__execution__pb2._DIGEST
+DESCRIPTOR.message_types_by_name['Qualifier'] = _QUALIFIER
+DESCRIPTOR.message_types_by_name['FetchBlobRequest'] = _FETCHBLOBREQUEST
+DESCRIPTOR.message_types_by_name['FetchBlobResponse'] = _FETCHBLOBRESPONSE
+DESCRIPTOR.message_types_by_name['FetchDirectoryRequest'] = _FETCHDIRECTORYREQUEST
+DESCRIPTOR.message_types_by_name['FetchDirectoryResponse'] = _FETCHDIRECTORYRESPONSE
+DESCRIPTOR.message_types_by_name['PushBlobRequest'] = _PUSHBLOBREQUEST
+DESCRIPTOR.message_types_by_name['PushBlobResponse'] = _PUSHBLOBRESPONSE
+DESCRIPTOR.message_types_by_name['PushDirectoryRequest'] = _PUSHDIRECTORYREQUEST
+DESCRIPTOR.message_types_by_name['PushDirectoryResponse'] = _PUSHDIRECTORYRESPONSE
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+Qualifier = _reflection.GeneratedProtocolMessageType('Qualifier', (_message.Message,), {
+ 'DESCRIPTOR' : _QUALIFIER,
+ '__module__' : 'build.bazel.remote.asset.v1.remote_asset_pb2'
+ # @@protoc_insertion_point(class_scope:build.bazel.remote.asset.v1.Qualifier)
+ })
+_sym_db.RegisterMessage(Qualifier)
+
+FetchBlobRequest = _reflection.GeneratedProtocolMessageType('FetchBlobRequest', (_message.Message,), {
+ 'DESCRIPTOR' : _FETCHBLOBREQUEST,
+ '__module__' : 'build.bazel.remote.asset.v1.remote_asset_pb2'
+ # @@protoc_insertion_point(class_scope:build.bazel.remote.asset.v1.FetchBlobRequest)
+ })
+_sym_db.RegisterMessage(FetchBlobRequest)
+
+FetchBlobResponse = _reflection.GeneratedProtocolMessageType('FetchBlobResponse', (_message.Message,), {
+ 'DESCRIPTOR' : _FETCHBLOBRESPONSE,
+ '__module__' : 'build.bazel.remote.asset.v1.remote_asset_pb2'
+ # @@protoc_insertion_point(class_scope:build.bazel.remote.asset.v1.FetchBlobResponse)
+ })
+_sym_db.RegisterMessage(FetchBlobResponse)
+
+FetchDirectoryRequest = _reflection.GeneratedProtocolMessageType('FetchDirectoryRequest', (_message.Message,), {
+ 'DESCRIPTOR' : _FETCHDIRECTORYREQUEST,
+ '__module__' : 'build.bazel.remote.asset.v1.remote_asset_pb2'
+ # @@protoc_insertion_point(class_scope:build.bazel.remote.asset.v1.FetchDirectoryRequest)
+ })
+_sym_db.RegisterMessage(FetchDirectoryRequest)
+
+FetchDirectoryResponse = _reflection.GeneratedProtocolMessageType('FetchDirectoryResponse', (_message.Message,), {
+ 'DESCRIPTOR' : _FETCHDIRECTORYRESPONSE,
+ '__module__' : 'build.bazel.remote.asset.v1.remote_asset_pb2'
+ # @@protoc_insertion_point(class_scope:build.bazel.remote.asset.v1.FetchDirectoryResponse)
+ })
+_sym_db.RegisterMessage(FetchDirectoryResponse)
+
+PushBlobRequest = _reflection.GeneratedProtocolMessageType('PushBlobRequest', (_message.Message,), {
+ 'DESCRIPTOR' : _PUSHBLOBREQUEST,
+ '__module__' : 'build.bazel.remote.asset.v1.remote_asset_pb2'
+ # @@protoc_insertion_point(class_scope:build.bazel.remote.asset.v1.PushBlobRequest)
+ })
+_sym_db.RegisterMessage(PushBlobRequest)
+
+PushBlobResponse = _reflection.GeneratedProtocolMessageType('PushBlobResponse', (_message.Message,), {
+ 'DESCRIPTOR' : _PUSHBLOBRESPONSE,
+ '__module__' : 'build.bazel.remote.asset.v1.remote_asset_pb2'
+ # @@protoc_insertion_point(class_scope:build.bazel.remote.asset.v1.PushBlobResponse)
+ })
+_sym_db.RegisterMessage(PushBlobResponse)
+
+PushDirectoryRequest = _reflection.GeneratedProtocolMessageType('PushDirectoryRequest', (_message.Message,), {
+ 'DESCRIPTOR' : _PUSHDIRECTORYREQUEST,
+ '__module__' : 'build.bazel.remote.asset.v1.remote_asset_pb2'
+ # @@protoc_insertion_point(class_scope:build.bazel.remote.asset.v1.PushDirectoryRequest)
+ })
+_sym_db.RegisterMessage(PushDirectoryRequest)
+
+PushDirectoryResponse = _reflection.GeneratedProtocolMessageType('PushDirectoryResponse', (_message.Message,), {
+ 'DESCRIPTOR' : _PUSHDIRECTORYRESPONSE,
+ '__module__' : 'build.bazel.remote.asset.v1.remote_asset_pb2'
+ # @@protoc_insertion_point(class_scope:build.bazel.remote.asset.v1.PushDirectoryResponse)
+ })
+_sym_db.RegisterMessage(PushDirectoryResponse)
+
+
+DESCRIPTOR._options = None
+
+_FETCH = _descriptor.ServiceDescriptor(
+ name='Fetch',
+ full_name='build.bazel.remote.asset.v1.Fetch',
+ file=DESCRIPTOR,
+ index=0,
+ serialized_options=None,
+ serialized_start=2038,
+ serialized_end=2387,
+ methods=[
+ _descriptor.MethodDescriptor(
+ name='FetchBlob',
+ full_name='build.bazel.remote.asset.v1.Fetch.FetchBlob',
+ index=0,
+ containing_service=None,
+ input_type=_FETCHBLOBREQUEST,
+ output_type=_FETCHBLOBRESPONSE,
+ serialized_options=b'\202\323\344\223\002,\"\'/v1/{instance_name=**}/assets:fetchBlob:\001*',
+ ),
+ _descriptor.MethodDescriptor(
+ name='FetchDirectory',
+ full_name='build.bazel.remote.asset.v1.Fetch.FetchDirectory',
+ index=1,
+ containing_service=None,
+ input_type=_FETCHDIRECTORYREQUEST,
+ output_type=_FETCHDIRECTORYRESPONSE,
+ serialized_options=b'\202\323\344\223\0021\",/v1/{instance_name=**}/assets:fetchDirectory:\001*',
+ ),
+])
+_sym_db.RegisterServiceDescriptor(_FETCH)
+
+DESCRIPTOR.services_by_name['Fetch'] = _FETCH
+
+
+_PUSH = _descriptor.ServiceDescriptor(
+ name='Push',
+ full_name='build.bazel.remote.asset.v1.Push',
+ file=DESCRIPTOR,
+ index=1,
+ serialized_options=None,
+ serialized_start=2390,
+ serialized_end=2730,
+ methods=[
+ _descriptor.MethodDescriptor(
+ name='PushBlob',
+ full_name='build.bazel.remote.asset.v1.Push.PushBlob',
+ index=0,
+ containing_service=None,
+ input_type=_PUSHBLOBREQUEST,
+ output_type=_PUSHBLOBRESPONSE,
+ serialized_options=b'\202\323\344\223\002+\"&/v1/{instance_name=**}/assets:pushBlob:\001*',
+ ),
+ _descriptor.MethodDescriptor(
+ name='PushDirectory',
+ full_name='build.bazel.remote.asset.v1.Push.PushDirectory',
+ index=1,
+ containing_service=None,
+ input_type=_PUSHDIRECTORYREQUEST,
+ output_type=_PUSHDIRECTORYRESPONSE,
+ serialized_options=b'\202\323\344\223\0020\"+/v1/{instance_name=**}/assets:pushDirectory:\001*',
+ ),
+])
+_sym_db.RegisterServiceDescriptor(_PUSH)
+
+DESCRIPTOR.services_by_name['Push'] = _PUSH
+
+# @@protoc_insertion_point(module_scope)
diff --git a/buildstream/_protos/build/bazel/remote/asset/v1/remote_asset_pb2_grpc.py b/buildstream/_protos/build/bazel/remote/asset/v1/remote_asset_pb2_grpc.py
new file mode 100644
index 000000000..38d31a2a1
--- /dev/null
+++ b/buildstream/_protos/build/bazel/remote/asset/v1/remote_asset_pb2_grpc.py
@@ -0,0 +1,324 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+import grpc
+
+from buildstream._protos.build.bazel.remote.asset.v1 import remote_asset_pb2 as build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2
+
+
+class FetchStub(object):
+ """The Fetch service resolves or fetches assets referenced by URI and
+ Qualifiers, returning a Digest for the content in
+ [ContentAddressableStorage][build.bazel.remote.execution.v2.ContentAddressableStorage].
+
+ As with other services in the Remote Execution API, any call may return an
+ error with a [RetryInfo][google.rpc.RetryInfo] error detail providing
+ information about when the client should retry the request; clients SHOULD
+ respect the information provided.
+ """
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.FetchBlob = channel.unary_unary(
+ '/build.bazel.remote.asset.v1.Fetch/FetchBlob',
+ request_serializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.FetchBlobRequest.SerializeToString,
+ response_deserializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.FetchBlobResponse.FromString,
+ )
+ self.FetchDirectory = channel.unary_unary(
+ '/build.bazel.remote.asset.v1.Fetch/FetchDirectory',
+ request_serializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.FetchDirectoryRequest.SerializeToString,
+ response_deserializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.FetchDirectoryResponse.FromString,
+ )
+
+
+class FetchServicer(object):
+ """The Fetch service resolves or fetches assets referenced by URI and
+ Qualifiers, returning a Digest for the content in
+ [ContentAddressableStorage][build.bazel.remote.execution.v2.ContentAddressableStorage].
+
+ As with other services in the Remote Execution API, any call may return an
+ error with a [RetryInfo][google.rpc.RetryInfo] error detail providing
+ information about when the client should retry the request; clients SHOULD
+ respect the information provided.
+ """
+
+ def FetchBlob(self, request, context):
+ """Resolve or fetch referenced assets, making them available to the caller and
+ other consumers in the [ContentAddressableStorage][build.bazel.remote.execution.v2.ContentAddressableStorage].
+
+ Servers *MAY* fetch content that they do not already have cached, for any
+ URLs they support.
+
+ Servers *SHOULD* ensure that referenced files are present in the CAS at the
+ time of the response, and (if supported) that they will remain available
+ for a reasonable period of time. The TTLs of the referenced blobs *SHOULD*
+ be increased if necessary and applicable.
+ In the event that a client receives a reference to content that is no
+ longer present, it *MAY* re-issue the request with
+ `oldest_content_accepted` set to a more recent timestamp than the original
+ attempt, to induce a re-fetch from origin.
+
+ Servers *MAY* cache fetched content and reuse it for subsequent requests,
+ subject to `oldest_content_accepted`.
+
+ Servers *MAY* support the complementary [Push][build.bazel.remote.asset.v1.Push]
+ API and allow content to be directly inserted for use in future fetch
+ responses.
+
+ Servers *MUST* ensure Fetch'd content matches all the specified
+ qualifiers except in the case of previously Push'd resources, for which
+ the server *MAY* trust the pushing client to have set the qualifiers
+ correctly, without validation.
+
+ Servers not implementing the complementary [Push][build.bazel.remote.asset.v1.Push]
+ API *MUST* reject requests containing qualifiers it does not support.
+
+ Servers *MAY* transform assets as part of the fetch. For example a
+ tarball fetched by [FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory]
+ might be unpacked, or a Git repository
+ fetched by [FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob]
+ might be passed through `git-archive`.
+
+ Errors handling the requested assets will be returned as gRPC Status errors
+ here; errors outside the server's control will be returned inline in the
+ `status` field of the response (see comment there for details).
+ The possible RPC errors include:
+ * `INVALID_ARGUMENT`: One or more arguments were invalid, such as a
+ qualifier that is not supported by the server.
+ * `RESOURCE_EXHAUSTED`: There is insufficient quota of some resource to
+ perform the requested operation. The client may retry after a delay.
+ * `UNAVAILABLE`: Due to a transient condition the operation could not be
+ completed. The client should retry.
+ * `INTERNAL`: An internal error occurred while performing the operation.
+ The client should retry.
+ * `DEADLINE_EXCEEDED`: The fetch could not be completed within the given
+ RPC deadline. The client should retry for at least as long as the value
+ provided in `timeout` field of the request.
+
+ In the case of unsupported qualifiers, the server *SHOULD* additionally
+ send a [BadRequest][google.rpc.BadRequest] error detail where, for each
+ unsupported qualifier, there is a `FieldViolation` with a `field` of
+ `qualifiers.name` and a `description` of `"{qualifier}" not supported`
+ indicating the name of the unsupported qualifier.
+ """
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def FetchDirectory(self, request, context):
+ """Missing associated documentation comment in .proto file"""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_FetchServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'FetchBlob': grpc.unary_unary_rpc_method_handler(
+ servicer.FetchBlob,
+ request_deserializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.FetchBlobRequest.FromString,
+ response_serializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.FetchBlobResponse.SerializeToString,
+ ),
+ 'FetchDirectory': grpc.unary_unary_rpc_method_handler(
+ servicer.FetchDirectory,
+ request_deserializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.FetchDirectoryRequest.FromString,
+ response_serializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.FetchDirectoryResponse.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'build.bazel.remote.asset.v1.Fetch', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
+
+
+ # This class is part of an EXPERIMENTAL API.
+class Fetch(object):
+ """The Fetch service resolves or fetches assets referenced by URI and
+ Qualifiers, returning a Digest for the content in
+ [ContentAddressableStorage][build.bazel.remote.execution.v2.ContentAddressableStorage].
+
+ As with other services in the Remote Execution API, any call may return an
+ error with a [RetryInfo][google.rpc.RetryInfo] error detail providing
+ information about when the client should retry the request; clients SHOULD
+ respect the information provided.
+ """
+
+ @staticmethod
+ def FetchBlob(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(request, target, '/build.bazel.remote.asset.v1.Fetch/FetchBlob',
+ build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.FetchBlobRequest.SerializeToString,
+ build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.FetchBlobResponse.FromString,
+ options, channel_credentials,
+ call_credentials, compression, wait_for_ready, timeout, metadata)
+
+ @staticmethod
+ def FetchDirectory(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(request, target, '/build.bazel.remote.asset.v1.Fetch/FetchDirectory',
+ build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.FetchDirectoryRequest.SerializeToString,
+ build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.FetchDirectoryResponse.FromString,
+ options, channel_credentials,
+ call_credentials, compression, wait_for_ready, timeout, metadata)
+
+
+class PushStub(object):
+ """The Push service is complementary to the Fetch, and allows for
+ associating contents of URLs to be returned in future Fetch API calls.
+
+ As with other services in the Remote Execution API, any call may return an
+ error with a [RetryInfo][google.rpc.RetryInfo] error detail providing
+ information about when the client should retry the request; clients SHOULD
+ respect the information provided.
+ """
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.PushBlob = channel.unary_unary(
+ '/build.bazel.remote.asset.v1.Push/PushBlob',
+ request_serializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.PushBlobRequest.SerializeToString,
+ response_deserializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.PushBlobResponse.FromString,
+ )
+ self.PushDirectory = channel.unary_unary(
+ '/build.bazel.remote.asset.v1.Push/PushDirectory',
+ request_serializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.PushDirectoryRequest.SerializeToString,
+ response_deserializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.PushDirectoryResponse.FromString,
+ )
+
+
+class PushServicer(object):
+ """The Push service is complementary to the Fetch, and allows for
+ associating contents of URLs to be returned in future Fetch API calls.
+
+ As with other services in the Remote Execution API, any call may return an
+ error with a [RetryInfo][google.rpc.RetryInfo] error detail providing
+ information about when the client should retry the request; clients SHOULD
+ respect the information provided.
+ """
+
+ def PushBlob(self, request, context):
+ """These APIs associate the identifying information of a resource, as
+ indicated by URI and optionally Qualifiers, with content available in the
+ CAS. For example, associating a repository url and a commit id with a
+ Directory Digest.
+
+ Servers *SHOULD* only allow trusted clients to associate content, and *MAY*
+ only allow certain URIs to be pushed.
+
+ Clients *MUST* ensure associated content is available in CAS prior to
+ pushing.
+
+ Clients *MUST* ensure the Qualifiers listed correctly match the contents,
+ and Servers *MAY* trust these values without validation.
+ Fetch servers *MAY* require exact match of all qualifiers when returning
+ content previously pushed, or allow fetching content with only a subset of
+ the qualifiers specified on Push.
+
+ Clients can specify expiration information that the server *SHOULD*
+ respect. Subsequent requests can be used to alter the expiration time.
+
+ A minimal compliant Fetch implementation may support only Push'd content
+ and return `NOT_FOUND` for any resource that was not pushed first.
+ Alternatively, a compliant implementation may choose to not support Push
+ and only return resources that can be Fetch'd from origin.
+
+ Errors will be returned as gRPC Status errors.
+ The possible RPC errors include:
+ * `INVALID_ARGUMENT`: One or more arguments to the RPC were invalid.
+ * `RESOURCE_EXHAUSTED`: There is insufficient quota of some resource to
+ perform the requested operation. The client may retry after a delay.
+ * `UNAVAILABLE`: Due to a transient condition the operation could not be
+ completed. The client should retry.
+ * `INTERNAL`: An internal error occurred while performing the operation.
+ The client should retry.
+ """
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def PushDirectory(self, request, context):
+ """Missing associated documentation comment in .proto file"""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_PushServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'PushBlob': grpc.unary_unary_rpc_method_handler(
+ servicer.PushBlob,
+ request_deserializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.PushBlobRequest.FromString,
+ response_serializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.PushBlobResponse.SerializeToString,
+ ),
+ 'PushDirectory': grpc.unary_unary_rpc_method_handler(
+ servicer.PushDirectory,
+ request_deserializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.PushDirectoryRequest.FromString,
+ response_serializer=build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.PushDirectoryResponse.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'build.bazel.remote.asset.v1.Push', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
+
+
+ # This class is part of an EXPERIMENTAL API.
+class Push(object):
+ """The Push service is complementary to the Fetch, and allows for
+ associating contents of URLs to be returned in future Fetch API calls.
+
+ As with other services in the Remote Execution API, any call may return an
+ error with a [RetryInfo][google.rpc.RetryInfo] error detail providing
+ information about when the client should retry the request; clients SHOULD
+ respect the information provided.
+ """
+
+ @staticmethod
+ def PushBlob(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(request, target, '/build.bazel.remote.asset.v1.Push/PushBlob',
+ build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.PushBlobRequest.SerializeToString,
+ build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.PushBlobResponse.FromString,
+ options, channel_credentials,
+ call_credentials, compression, wait_for_ready, timeout, metadata)
+
+ @staticmethod
+ def PushDirectory(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(request, target, '/build.bazel.remote.asset.v1.Push/PushDirectory',
+ build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.PushDirectoryRequest.SerializeToString,
+ build_dot_bazel_dot_remote_dot_asset_dot_v1_dot_remote__asset__pb2.PushDirectoryResponse.FromString,
+ options, channel_credentials,
+ call_credentials, compression, wait_for_ready, timeout, metadata)