Add generated python protobuffer files Remote Asset API
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 0000000..e69de29
--- /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 0000000..e69de29
--- /dev/null
+++ b/buildstream/_protos/build/bazel/remote/asset/v1/__init__.py
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 0000000..c40df64
--- /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 0000000..38d31a2
--- /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)