diff --git a/pkg/proto/objectstoresnapshotpb/v1/gen.go b/pkg/proto/objectstoresnapshotpb/v1/gen.go new file mode 100644 index 0000000000..8baf4835c3 --- /dev/null +++ b/pkg/proto/objectstoresnapshotpb/v1/gen.go @@ -0,0 +1,17 @@ +// Copyright 2026 Google LLC +// +// 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. + +package objectstoresnapshotv1 + +//go:generate bash -c "../../../../hack/protoc.sh --plugin=protoc-gen-go=$(bash ../../../../hack/run-tool.sh --print-bin-path protoc-gen-go) --plugin=protoc-gen-go-grpc=$(bash ../../../../hack/run-tool.sh --print-bin-path protoc-gen-go-grpc) --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. objectstoresnapshot.proto" diff --git a/pkg/proto/objectstoresnapshotpb/v1/objectstoresnapshot.pb.go b/pkg/proto/objectstoresnapshotpb/v1/objectstoresnapshot.pb.go new file mode 100644 index 0000000000..e7ebe1b7b6 --- /dev/null +++ b/pkg/proto/objectstoresnapshotpb/v1/objectstoresnapshot.pb.go @@ -0,0 +1,530 @@ +// Copyright 2026 Google LLC +// +// 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11-devel +// protoc v4.25.3 +// source: objectstoresnapshot.proto + +package objectstoresnapshotv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// FetchSnapshotRequest asks the plugin to download snapshot files. +type FetchSnapshotRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The snapshot to read, e.g. gs:///. + SnapshotUri string `protobuf:"bytes,1,opt,name=snapshot_uri,json=snapshotUri,proto3" json:"snapshot_uri,omitempty"` + // The JWT of the actor that owns the snapshot, for plugins that authorize + // storage access per actor. Substrate does not set it yet, so it is + // currently always empty. + ActorJwt string `protobuf:"bytes,2,opt,name=actor_jwt,json=actorJwt,proto3" json:"actor_jwt,omitempty"` + // Full local path of the directory the files are written into. It must + // exist. + WritePath string `protobuf:"bytes,3,opt,name=write_path,json=writePath,proto3" json:"write_path,omitempty"` + // Base names of the files to download. Required. + Files []string `protobuf:"bytes,4,rep,name=files,proto3" json:"files,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FetchSnapshotRequest) Reset() { + *x = FetchSnapshotRequest{} + mi := &file_objectstoresnapshot_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FetchSnapshotRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FetchSnapshotRequest) ProtoMessage() {} + +func (x *FetchSnapshotRequest) ProtoReflect() protoreflect.Message { + mi := &file_objectstoresnapshot_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FetchSnapshotRequest.ProtoReflect.Descriptor instead. +func (*FetchSnapshotRequest) Descriptor() ([]byte, []int) { + return file_objectstoresnapshot_proto_rawDescGZIP(), []int{0} +} + +func (x *FetchSnapshotRequest) GetSnapshotUri() string { + if x != nil { + return x.SnapshotUri + } + return "" +} + +func (x *FetchSnapshotRequest) GetActorJwt() string { + if x != nil { + return x.ActorJwt + } + return "" +} + +func (x *FetchSnapshotRequest) GetWritePath() string { + if x != nil { + return x.WritePath + } + return "" +} + +func (x *FetchSnapshotRequest) GetFiles() []string { + if x != nil { + return x.Files + } + return nil +} + +type FetchSnapshotResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FetchSnapshotResponse) Reset() { + *x = FetchSnapshotResponse{} + mi := &file_objectstoresnapshot_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FetchSnapshotResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FetchSnapshotResponse) ProtoMessage() {} + +func (x *FetchSnapshotResponse) ProtoReflect() protoreflect.Message { + mi := &file_objectstoresnapshot_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FetchSnapshotResponse.ProtoReflect.Descriptor instead. +func (*FetchSnapshotResponse) Descriptor() ([]byte, []int) { + return file_objectstoresnapshot_proto_rawDescGZIP(), []int{1} +} + +// UploadSnapshotRequest asks the plugin to upload snapshot files. +type UploadSnapshotRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The snapshot to write, e.g. gs:///. + SnapshotUri string `protobuf:"bytes,1,opt,name=snapshot_uri,json=snapshotUri,proto3" json:"snapshot_uri,omitempty"` + // The JWT of the actor that owns the snapshot, for plugins that authorize + // storage access per actor. Substrate does not set it yet, so it is + // currently always empty. + ActorJwt string `protobuf:"bytes,2,opt,name=actor_jwt,json=actorJwt,proto3" json:"actor_jwt,omitempty"` + // Full local path of the directory the files are read from. + LocalPath string `protobuf:"bytes,3,opt,name=local_path,json=localPath,proto3" json:"local_path,omitempty"` + // Base names of the files to upload. Required. + Files []string `protobuf:"bytes,4,rep,name=files,proto3" json:"files,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UploadSnapshotRequest) Reset() { + *x = UploadSnapshotRequest{} + mi := &file_objectstoresnapshot_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UploadSnapshotRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UploadSnapshotRequest) ProtoMessage() {} + +func (x *UploadSnapshotRequest) ProtoReflect() protoreflect.Message { + mi := &file_objectstoresnapshot_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UploadSnapshotRequest.ProtoReflect.Descriptor instead. +func (*UploadSnapshotRequest) Descriptor() ([]byte, []int) { + return file_objectstoresnapshot_proto_rawDescGZIP(), []int{2} +} + +func (x *UploadSnapshotRequest) GetSnapshotUri() string { + if x != nil { + return x.SnapshotUri + } + return "" +} + +func (x *UploadSnapshotRequest) GetActorJwt() string { + if x != nil { + return x.ActorJwt + } + return "" +} + +func (x *UploadSnapshotRequest) GetLocalPath() string { + if x != nil { + return x.LocalPath + } + return "" +} + +func (x *UploadSnapshotRequest) GetFiles() []string { + if x != nil { + return x.Files + } + return nil +} + +type UploadSnapshotResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UploadSnapshotResponse) Reset() { + *x = UploadSnapshotResponse{} + mi := &file_objectstoresnapshot_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UploadSnapshotResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UploadSnapshotResponse) ProtoMessage() {} + +func (x *UploadSnapshotResponse) ProtoReflect() protoreflect.Message { + mi := &file_objectstoresnapshot_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UploadSnapshotResponse.ProtoReflect.Descriptor instead. +func (*UploadSnapshotResponse) Descriptor() ([]byte, []int) { + return file_objectstoresnapshot_proto_rawDescGZIP(), []int{3} +} + +// CleanupSnapshotRequest names the snapshots to delete. +type CleanupSnapshotRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // A snapshot URI, or the prefix of a resource that owns several snapshots + // (e.g. gs:////atespaces//actors/). Every file + // below it is deleted. A bare bucket is rejected with INVALID_ARGUMENT. + SnapshotUri string `protobuf:"bytes,1,opt,name=snapshot_uri,json=snapshotUri,proto3" json:"snapshot_uri,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CleanupSnapshotRequest) Reset() { + *x = CleanupSnapshotRequest{} + mi := &file_objectstoresnapshot_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CleanupSnapshotRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CleanupSnapshotRequest) ProtoMessage() {} + +func (x *CleanupSnapshotRequest) ProtoReflect() protoreflect.Message { + mi := &file_objectstoresnapshot_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CleanupSnapshotRequest.ProtoReflect.Descriptor instead. +func (*CleanupSnapshotRequest) Descriptor() ([]byte, []int) { + return file_objectstoresnapshot_proto_rawDescGZIP(), []int{4} +} + +func (x *CleanupSnapshotRequest) GetSnapshotUri() string { + if x != nil { + return x.SnapshotUri + } + return "" +} + +type CleanupSnapshotResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CleanupSnapshotResponse) Reset() { + *x = CleanupSnapshotResponse{} + mi := &file_objectstoresnapshot_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CleanupSnapshotResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CleanupSnapshotResponse) ProtoMessage() {} + +func (x *CleanupSnapshotResponse) ProtoReflect() protoreflect.Message { + mi := &file_objectstoresnapshot_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CleanupSnapshotResponse.ProtoReflect.Descriptor instead. +func (*CleanupSnapshotResponse) Descriptor() ([]byte, []int) { + return file_objectstoresnapshot_proto_rawDescGZIP(), []int{5} +} + +// CopySnapshotRequest names the source and destination snapshots. +type CopySnapshotRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The URI to copy from, e.g. an actor's snapshot. + SrcUri string `protobuf:"bytes,1,opt,name=src_uri,json=srcUri,proto3" json:"src_uri,omitempty"` + // The URI to copy to, e.g. a tag's prefix. + DstUri string `protobuf:"bytes,2,opt,name=dst_uri,json=dstUri,proto3" json:"dst_uri,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CopySnapshotRequest) Reset() { + *x = CopySnapshotRequest{} + mi := &file_objectstoresnapshot_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CopySnapshotRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CopySnapshotRequest) ProtoMessage() {} + +func (x *CopySnapshotRequest) ProtoReflect() protoreflect.Message { + mi := &file_objectstoresnapshot_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CopySnapshotRequest.ProtoReflect.Descriptor instead. +func (*CopySnapshotRequest) Descriptor() ([]byte, []int) { + return file_objectstoresnapshot_proto_rawDescGZIP(), []int{6} +} + +func (x *CopySnapshotRequest) GetSrcUri() string { + if x != nil { + return x.SrcUri + } + return "" +} + +func (x *CopySnapshotRequest) GetDstUri() string { + if x != nil { + return x.DstUri + } + return "" +} + +type CopySnapshotResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CopySnapshotResponse) Reset() { + *x = CopySnapshotResponse{} + mi := &file_objectstoresnapshot_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CopySnapshotResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CopySnapshotResponse) ProtoMessage() {} + +func (x *CopySnapshotResponse) ProtoReflect() protoreflect.Message { + mi := &file_objectstoresnapshot_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CopySnapshotResponse.ProtoReflect.Descriptor instead. +func (*CopySnapshotResponse) Descriptor() ([]byte, []int) { + return file_objectstoresnapshot_proto_rawDescGZIP(), []int{7} +} + +var File_objectstoresnapshot_proto protoreflect.FileDescriptor + +const file_objectstoresnapshot_proto_rawDesc = "" + + "\n" + + "\x19objectstoresnapshot.proto\x12\x16objectstoresnapshot.v1\"\x8b\x01\n" + + "\x14FetchSnapshotRequest\x12!\n" + + "\fsnapshot_uri\x18\x01 \x01(\tR\vsnapshotUri\x12\x1b\n" + + "\tactor_jwt\x18\x02 \x01(\tR\bactorJwt\x12\x1d\n" + + "\n" + + "write_path\x18\x03 \x01(\tR\twritePath\x12\x14\n" + + "\x05files\x18\x04 \x03(\tR\x05files\"\x17\n" + + "\x15FetchSnapshotResponse\"\x8c\x01\n" + + "\x15UploadSnapshotRequest\x12!\n" + + "\fsnapshot_uri\x18\x01 \x01(\tR\vsnapshotUri\x12\x1b\n" + + "\tactor_jwt\x18\x02 \x01(\tR\bactorJwt\x12\x1d\n" + + "\n" + + "local_path\x18\x03 \x01(\tR\tlocalPath\x12\x14\n" + + "\x05files\x18\x04 \x03(\tR\x05files\"\x18\n" + + "\x16UploadSnapshotResponse\";\n" + + "\x16CleanupSnapshotRequest\x12!\n" + + "\fsnapshot_uri\x18\x01 \x01(\tR\vsnapshotUri\"\x19\n" + + "\x17CleanupSnapshotResponse\"G\n" + + "\x13CopySnapshotRequest\x12\x17\n" + + "\asrc_uri\x18\x01 \x01(\tR\x06srcUri\x12\x17\n" + + "\adst_uri\x18\x02 \x01(\tR\x06dstUri\"\x16\n" + + "\x14CopySnapshotResponse2\xf1\x01\n" + + "\fNodeProvider\x12n\n" + + "\rFetchSnapshot\x12,.objectstoresnapshot.v1.FetchSnapshotRequest\x1a-.objectstoresnapshot.v1.FetchSnapshotResponse\"\x00\x12q\n" + + "\x0eUploadSnapshot\x12-.objectstoresnapshot.v1.UploadSnapshotRequest\x1a..objectstoresnapshot.v1.UploadSnapshotResponse\"\x002\xf4\x01\n" + + "\x0fControlProvider\x12t\n" + + "\x0fCleanupSnapshot\x12..objectstoresnapshot.v1.CleanupSnapshotRequest\x1a/.objectstoresnapshot.v1.CleanupSnapshotResponse\"\x00\x12k\n" + + "\fCopySnapshot\x12+.objectstoresnapshot.v1.CopySnapshotRequest\x1a,.objectstoresnapshot.v1.CopySnapshotResponse\"\x00B_Z]github.com/agent-substrate/substrate/pkg/proto/objectstoresnapshotpb/v1;objectstoresnapshotv1b\x06proto3" + +var ( + file_objectstoresnapshot_proto_rawDescOnce sync.Once + file_objectstoresnapshot_proto_rawDescData []byte +) + +func file_objectstoresnapshot_proto_rawDescGZIP() []byte { + file_objectstoresnapshot_proto_rawDescOnce.Do(func() { + file_objectstoresnapshot_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_objectstoresnapshot_proto_rawDesc), len(file_objectstoresnapshot_proto_rawDesc))) + }) + return file_objectstoresnapshot_proto_rawDescData +} + +var file_objectstoresnapshot_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_objectstoresnapshot_proto_goTypes = []any{ + (*FetchSnapshotRequest)(nil), // 0: objectstoresnapshot.v1.FetchSnapshotRequest + (*FetchSnapshotResponse)(nil), // 1: objectstoresnapshot.v1.FetchSnapshotResponse + (*UploadSnapshotRequest)(nil), // 2: objectstoresnapshot.v1.UploadSnapshotRequest + (*UploadSnapshotResponse)(nil), // 3: objectstoresnapshot.v1.UploadSnapshotResponse + (*CleanupSnapshotRequest)(nil), // 4: objectstoresnapshot.v1.CleanupSnapshotRequest + (*CleanupSnapshotResponse)(nil), // 5: objectstoresnapshot.v1.CleanupSnapshotResponse + (*CopySnapshotRequest)(nil), // 6: objectstoresnapshot.v1.CopySnapshotRequest + (*CopySnapshotResponse)(nil), // 7: objectstoresnapshot.v1.CopySnapshotResponse +} +var file_objectstoresnapshot_proto_depIdxs = []int32{ + 0, // 0: objectstoresnapshot.v1.NodeProvider.FetchSnapshot:input_type -> objectstoresnapshot.v1.FetchSnapshotRequest + 2, // 1: objectstoresnapshot.v1.NodeProvider.UploadSnapshot:input_type -> objectstoresnapshot.v1.UploadSnapshotRequest + 4, // 2: objectstoresnapshot.v1.ControlProvider.CleanupSnapshot:input_type -> objectstoresnapshot.v1.CleanupSnapshotRequest + 6, // 3: objectstoresnapshot.v1.ControlProvider.CopySnapshot:input_type -> objectstoresnapshot.v1.CopySnapshotRequest + 1, // 4: objectstoresnapshot.v1.NodeProvider.FetchSnapshot:output_type -> objectstoresnapshot.v1.FetchSnapshotResponse + 3, // 5: objectstoresnapshot.v1.NodeProvider.UploadSnapshot:output_type -> objectstoresnapshot.v1.UploadSnapshotResponse + 5, // 6: objectstoresnapshot.v1.ControlProvider.CleanupSnapshot:output_type -> objectstoresnapshot.v1.CleanupSnapshotResponse + 7, // 7: objectstoresnapshot.v1.ControlProvider.CopySnapshot:output_type -> objectstoresnapshot.v1.CopySnapshotResponse + 4, // [4:8] is the sub-list for method output_type + 0, // [0:4] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_objectstoresnapshot_proto_init() } +func file_objectstoresnapshot_proto_init() { + if File_objectstoresnapshot_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_objectstoresnapshot_proto_rawDesc), len(file_objectstoresnapshot_proto_rawDesc)), + NumEnums: 0, + NumMessages: 8, + NumExtensions: 0, + NumServices: 2, + }, + GoTypes: file_objectstoresnapshot_proto_goTypes, + DependencyIndexes: file_objectstoresnapshot_proto_depIdxs, + MessageInfos: file_objectstoresnapshot_proto_msgTypes, + }.Build() + File_objectstoresnapshot_proto = out.File + file_objectstoresnapshot_proto_goTypes = nil + file_objectstoresnapshot_proto_depIdxs = nil +} diff --git a/pkg/proto/objectstoresnapshotpb/v1/objectstoresnapshot.proto b/pkg/proto/objectstoresnapshotpb/v1/objectstoresnapshot.proto new file mode 100644 index 0000000000..c1d4694344 --- /dev/null +++ b/pkg/proto/objectstoresnapshotpb/v1/objectstoresnapshot.proto @@ -0,0 +1,123 @@ +// Copyright 2026 Google LLC +// +// 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 objectstoresnapshot.v1; + +option go_package = "github.com/agent-substrate/substrate/pkg/proto/objectstoresnapshotpb/v1;objectstoresnapshotv1"; + +// NodeProvider is the plugin API an object storage platform implements +// on every node. atelet calls it to move actor snapshots between the node and +// the platform's object storage. How the platform stores them (object names, +// compression) is private to the plugin. The only requirement is that +// FetchSnapshot returns the bytes UploadSnapshot was given. Substrate stores +// no checksums; verifying integrity is up to the plugin. +// +// Callers name every file they want moved. A snapshot's file list lives in +// its manifest, which the caller fetches first by name. The caller also owns +// commit ordering: it uploads the data files, and only after that call +// succeeds does it upload the manifest in a separate call, so a reader that +// finds the manifest can rely on every file it lists. +// +// Every RPC is idempotent: a retry overwrites whatever an earlier attempt +// stored or wrote. +service NodeProvider { + // FetchSnapshot downloads the named files of a snapshot into write_path. + // It returns NOT_FOUND if any requested file is absent from the snapshot. + // A plugin that authorizes per actor returns PERMISSION_DENIED if actor_jwt + // does not grant read access to snapshot_uri. + rpc FetchSnapshot(FetchSnapshotRequest) returns (FetchSnapshotResponse) {} + + // UploadSnapshot uploads the named files from local_path into a snapshot. + // It returns success only once every file is durably stored. On failure, + // files already stored may remain, and the caller can remove them with + // ControlProvider.CleanupSnapshot. A plugin that authorizes per actor returns + // PERMISSION_DENIED if actor_jwt does not grant write access to snapshot_uri. + rpc UploadSnapshot(UploadSnapshotRequest) returns (UploadSnapshotResponse) {} +} + +// FetchSnapshotRequest asks the plugin to download snapshot files. +message FetchSnapshotRequest { + // The snapshot to read, e.g. gs:///. + string snapshot_uri = 1; + + // The JWT of the actor that owns the snapshot, for plugins that authorize + // storage access per actor. Substrate does not set it yet, so it is + // currently always empty. + string actor_jwt = 2; + + // Full local path of the directory the files are written into. It must + // exist. + string write_path = 3; + + // Base names of the files to download. Required. + repeated string files = 4; +} + +message FetchSnapshotResponse {} + +// UploadSnapshotRequest asks the plugin to upload snapshot files. +message UploadSnapshotRequest { + // The snapshot to write, e.g. gs:///. + string snapshot_uri = 1; + + // The JWT of the actor that owns the snapshot, for plugins that authorize + // storage access per actor. Substrate does not set it yet, so it is + // currently always empty. + string actor_jwt = 2; + + // Full local path of the directory the files are read from. + string local_path = 3; + + // Base names of the files to upload. Required. + repeated string files = 4; +} + +message UploadSnapshotResponse {} + +// ControlProvider is the plugin API an object storage platform +// implements for the control plane. ate-api-server calls it to manage whole +// snapshots. +service ControlProvider { + // CleanupSnapshot deletes every file of a snapshot, or of every snapshot + // under an owner's prefix. Deleting an absent snapshot succeeds. + rpc CleanupSnapshot(CleanupSnapshotRequest) returns (CleanupSnapshotResponse) {} + + // CopySnapshot copies every file of src_uri to dst_uri, overwriting files + // already at dst_uri. src_uri and dst_uri may be in different buckets. It + // returns FAILED_PRECONDITION if src_uri holds no files. + rpc CopySnapshot(CopySnapshotRequest) returns (CopySnapshotResponse) {} +} + +// CleanupSnapshotRequest names the snapshots to delete. +message CleanupSnapshotRequest { + // A snapshot URI, or the prefix of a resource that owns several snapshots + // (e.g. gs:////atespaces//actors/). Every file + // below it is deleted. A bare bucket is rejected with INVALID_ARGUMENT. + string snapshot_uri = 1; +} + +message CleanupSnapshotResponse {} + +// CopySnapshotRequest names the source and destination snapshots. +message CopySnapshotRequest { + // The URI to copy from, e.g. an actor's snapshot. + string src_uri = 1; + + // The URI to copy to, e.g. a tag's prefix. + string dst_uri = 2; +} + +message CopySnapshotResponse {} diff --git a/pkg/proto/objectstoresnapshotpb/v1/objectstoresnapshot_grpc.pb.go b/pkg/proto/objectstoresnapshotpb/v1/objectstoresnapshot_grpc.pb.go new file mode 100644 index 0000000000..e9066c3a3b --- /dev/null +++ b/pkg/proto/objectstoresnapshotpb/v1/objectstoresnapshot_grpc.pb.go @@ -0,0 +1,381 @@ +// Copyright 2026 Google LLC +// +// 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. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.2 +// - protoc v4.25.3 +// source: objectstoresnapshot.proto + +package objectstoresnapshotv1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + NodeProvider_FetchSnapshot_FullMethodName = "/objectstoresnapshot.v1.NodeProvider/FetchSnapshot" + NodeProvider_UploadSnapshot_FullMethodName = "/objectstoresnapshot.v1.NodeProvider/UploadSnapshot" +) + +// NodeProviderClient is the client API for NodeProvider service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// NodeProvider is the plugin API an object storage platform implements +// on every node. atelet calls it to move actor snapshots between the node and +// the platform's object storage. How the platform stores them (object names, +// compression) is private to the plugin. The only requirement is that +// FetchSnapshot returns the bytes UploadSnapshot was given. Substrate stores +// no checksums; verifying integrity is up to the plugin. +// +// Callers name every file they want moved. A snapshot's file list lives in +// its manifest, which the caller fetches first by name. The caller also owns +// commit ordering: it uploads the data files, and only after that call +// succeeds does it upload the manifest in a separate call, so a reader that +// finds the manifest can rely on every file it lists. +// +// Every RPC is idempotent: a retry overwrites whatever an earlier attempt +// stored or wrote. +type NodeProviderClient interface { + // FetchSnapshot downloads the named files of a snapshot into write_path. + // It returns NOT_FOUND if any requested file is absent from the snapshot. + // A plugin that authorizes per actor returns PERMISSION_DENIED if actor_jwt + // does not grant read access to snapshot_uri. + FetchSnapshot(ctx context.Context, in *FetchSnapshotRequest, opts ...grpc.CallOption) (*FetchSnapshotResponse, error) + // UploadSnapshot uploads the named files from local_path into a snapshot. + // It returns success only once every file is durably stored. On failure, + // files already stored may remain, and the caller can remove them with + // ControlProvider.CleanupSnapshot. A plugin that authorizes per actor returns + // PERMISSION_DENIED if actor_jwt does not grant write access to snapshot_uri. + UploadSnapshot(ctx context.Context, in *UploadSnapshotRequest, opts ...grpc.CallOption) (*UploadSnapshotResponse, error) +} + +type nodeProviderClient struct { + cc grpc.ClientConnInterface +} + +func NewNodeProviderClient(cc grpc.ClientConnInterface) NodeProviderClient { + return &nodeProviderClient{cc} +} + +func (c *nodeProviderClient) FetchSnapshot(ctx context.Context, in *FetchSnapshotRequest, opts ...grpc.CallOption) (*FetchSnapshotResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(FetchSnapshotResponse) + err := c.cc.Invoke(ctx, NodeProvider_FetchSnapshot_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeProviderClient) UploadSnapshot(ctx context.Context, in *UploadSnapshotRequest, opts ...grpc.CallOption) (*UploadSnapshotResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UploadSnapshotResponse) + err := c.cc.Invoke(ctx, NodeProvider_UploadSnapshot_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// NodeProviderServer is the server API for NodeProvider service. +// All implementations must embed UnimplementedNodeProviderServer +// for forward compatibility. +// +// NodeProvider is the plugin API an object storage platform implements +// on every node. atelet calls it to move actor snapshots between the node and +// the platform's object storage. How the platform stores them (object names, +// compression) is private to the plugin. The only requirement is that +// FetchSnapshot returns the bytes UploadSnapshot was given. Substrate stores +// no checksums; verifying integrity is up to the plugin. +// +// Callers name every file they want moved. A snapshot's file list lives in +// its manifest, which the caller fetches first by name. The caller also owns +// commit ordering: it uploads the data files, and only after that call +// succeeds does it upload the manifest in a separate call, so a reader that +// finds the manifest can rely on every file it lists. +// +// Every RPC is idempotent: a retry overwrites whatever an earlier attempt +// stored or wrote. +type NodeProviderServer interface { + // FetchSnapshot downloads the named files of a snapshot into write_path. + // It returns NOT_FOUND if any requested file is absent from the snapshot. + // A plugin that authorizes per actor returns PERMISSION_DENIED if actor_jwt + // does not grant read access to snapshot_uri. + FetchSnapshot(context.Context, *FetchSnapshotRequest) (*FetchSnapshotResponse, error) + // UploadSnapshot uploads the named files from local_path into a snapshot. + // It returns success only once every file is durably stored. On failure, + // files already stored may remain, and the caller can remove them with + // ControlProvider.CleanupSnapshot. A plugin that authorizes per actor returns + // PERMISSION_DENIED if actor_jwt does not grant write access to snapshot_uri. + UploadSnapshot(context.Context, *UploadSnapshotRequest) (*UploadSnapshotResponse, error) + mustEmbedUnimplementedNodeProviderServer() +} + +// UnimplementedNodeProviderServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedNodeProviderServer struct{} + +func (UnimplementedNodeProviderServer) FetchSnapshot(context.Context, *FetchSnapshotRequest) (*FetchSnapshotResponse, error) { + return nil, status.Error(codes.Unimplemented, "method FetchSnapshot not implemented") +} +func (UnimplementedNodeProviderServer) UploadSnapshot(context.Context, *UploadSnapshotRequest) (*UploadSnapshotResponse, error) { + return nil, status.Error(codes.Unimplemented, "method UploadSnapshot not implemented") +} +func (UnimplementedNodeProviderServer) mustEmbedUnimplementedNodeProviderServer() {} +func (UnimplementedNodeProviderServer) testEmbeddedByValue() {} + +// UnsafeNodeProviderServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to NodeProviderServer will +// result in compilation errors. +type UnsafeNodeProviderServer interface { + mustEmbedUnimplementedNodeProviderServer() +} + +func RegisterNodeProviderServer(s grpc.ServiceRegistrar, srv NodeProviderServer) { + // If the following call panics, it indicates UnimplementedNodeProviderServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&NodeProvider_ServiceDesc, srv) +} + +func _NodeProvider_FetchSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FetchSnapshotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeProviderServer).FetchSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NodeProvider_FetchSnapshot_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeProviderServer).FetchSnapshot(ctx, req.(*FetchSnapshotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeProvider_UploadSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UploadSnapshotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeProviderServer).UploadSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NodeProvider_UploadSnapshot_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeProviderServer).UploadSnapshot(ctx, req.(*UploadSnapshotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// NodeProvider_ServiceDesc is the grpc.ServiceDesc for NodeProvider service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var NodeProvider_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "objectstoresnapshot.v1.NodeProvider", + HandlerType: (*NodeProviderServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "FetchSnapshot", + Handler: _NodeProvider_FetchSnapshot_Handler, + }, + { + MethodName: "UploadSnapshot", + Handler: _NodeProvider_UploadSnapshot_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "objectstoresnapshot.proto", +} + +const ( + ControlProvider_CleanupSnapshot_FullMethodName = "/objectstoresnapshot.v1.ControlProvider/CleanupSnapshot" + ControlProvider_CopySnapshot_FullMethodName = "/objectstoresnapshot.v1.ControlProvider/CopySnapshot" +) + +// ControlProviderClient is the client API for ControlProvider service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// ControlProvider is the plugin API an object storage platform +// implements for the control plane. ate-api-server calls it to manage whole +// snapshots. +type ControlProviderClient interface { + // CleanupSnapshot deletes every file of a snapshot, or of every snapshot + // under an owner's prefix. Deleting an absent snapshot succeeds. + CleanupSnapshot(ctx context.Context, in *CleanupSnapshotRequest, opts ...grpc.CallOption) (*CleanupSnapshotResponse, error) + // CopySnapshot copies every file of src_uri to dst_uri, overwriting files + // already at dst_uri. src_uri and dst_uri may be in different buckets. It + // returns FAILED_PRECONDITION if src_uri holds no files. + CopySnapshot(ctx context.Context, in *CopySnapshotRequest, opts ...grpc.CallOption) (*CopySnapshotResponse, error) +} + +type controlProviderClient struct { + cc grpc.ClientConnInterface +} + +func NewControlProviderClient(cc grpc.ClientConnInterface) ControlProviderClient { + return &controlProviderClient{cc} +} + +func (c *controlProviderClient) CleanupSnapshot(ctx context.Context, in *CleanupSnapshotRequest, opts ...grpc.CallOption) (*CleanupSnapshotResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CleanupSnapshotResponse) + err := c.cc.Invoke(ctx, ControlProvider_CleanupSnapshot_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlProviderClient) CopySnapshot(ctx context.Context, in *CopySnapshotRequest, opts ...grpc.CallOption) (*CopySnapshotResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CopySnapshotResponse) + err := c.cc.Invoke(ctx, ControlProvider_CopySnapshot_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ControlProviderServer is the server API for ControlProvider service. +// All implementations must embed UnimplementedControlProviderServer +// for forward compatibility. +// +// ControlProvider is the plugin API an object storage platform +// implements for the control plane. ate-api-server calls it to manage whole +// snapshots. +type ControlProviderServer interface { + // CleanupSnapshot deletes every file of a snapshot, or of every snapshot + // under an owner's prefix. Deleting an absent snapshot succeeds. + CleanupSnapshot(context.Context, *CleanupSnapshotRequest) (*CleanupSnapshotResponse, error) + // CopySnapshot copies every file of src_uri to dst_uri, overwriting files + // already at dst_uri. src_uri and dst_uri may be in different buckets. It + // returns FAILED_PRECONDITION if src_uri holds no files. + CopySnapshot(context.Context, *CopySnapshotRequest) (*CopySnapshotResponse, error) + mustEmbedUnimplementedControlProviderServer() +} + +// UnimplementedControlProviderServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedControlProviderServer struct{} + +func (UnimplementedControlProviderServer) CleanupSnapshot(context.Context, *CleanupSnapshotRequest) (*CleanupSnapshotResponse, error) { + return nil, status.Error(codes.Unimplemented, "method CleanupSnapshot not implemented") +} +func (UnimplementedControlProviderServer) CopySnapshot(context.Context, *CopySnapshotRequest) (*CopySnapshotResponse, error) { + return nil, status.Error(codes.Unimplemented, "method CopySnapshot not implemented") +} +func (UnimplementedControlProviderServer) mustEmbedUnimplementedControlProviderServer() {} +func (UnimplementedControlProviderServer) testEmbeddedByValue() {} + +// UnsafeControlProviderServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ControlProviderServer will +// result in compilation errors. +type UnsafeControlProviderServer interface { + mustEmbedUnimplementedControlProviderServer() +} + +func RegisterControlProviderServer(s grpc.ServiceRegistrar, srv ControlProviderServer) { + // If the following call panics, it indicates UnimplementedControlProviderServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&ControlProvider_ServiceDesc, srv) +} + +func _ControlProvider_CleanupSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CleanupSnapshotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlProviderServer).CleanupSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlProvider_CleanupSnapshot_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlProviderServer).CleanupSnapshot(ctx, req.(*CleanupSnapshotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ControlProvider_CopySnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CopySnapshotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlProviderServer).CopySnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlProvider_CopySnapshot_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlProviderServer).CopySnapshot(ctx, req.(*CopySnapshotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// ControlProvider_ServiceDesc is the grpc.ServiceDesc for ControlProvider service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ControlProvider_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "objectstoresnapshot.v1.ControlProvider", + HandlerType: (*ControlProviderServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CleanupSnapshot", + Handler: _ControlProvider_CleanupSnapshot_Handler, + }, + { + MethodName: "CopySnapshot", + Handler: _ControlProvider_CopySnapshot_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "objectstoresnapshot.proto", +}