From b573edfd13b3e9ed608b31ffa1423a5f8c01293e Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Wed, 6 May 2026 12:28:48 +0200 Subject: [PATCH 1/4] feat: uc image rm Allow for image removal via the uc cmd line. This just does 'rm' not 'prune', but adds a missing option to uncloud to at least have the possibility to remove images remotely. SSH is of course still an option. All the plumbing and docker rpcs is done. It needs an e2e test still. See #167 Signed-off-by: Miek Gieben --- cmd/uncloud/image/root.go | 1 + internal/machine/api/pb/docker.pb.go | 593 ++++++++++++---------- internal/machine/api/pb/docker.proto | 6 + internal/machine/api/pb/docker_grpc.pb.go | 38 ++ internal/machine/docker/client.go | 15 + internal/machine/docker/server.go | 16 + mise.lock | 171 ++++++- pkg/client/image.go | 24 + website/docs/9-cli-reference/uc_image.md | 1 + 9 files changed, 606 insertions(+), 259 deletions(-) diff --git a/cmd/uncloud/image/root.go b/cmd/uncloud/image/root.go index 53ddfee6..05b61a5e 100644 --- a/cmd/uncloud/image/root.go +++ b/cmd/uncloud/image/root.go @@ -13,6 +13,7 @@ func NewRootCommand() *cobra.Command { cmd.AddCommand( NewListCommand(), NewPushCommand(), + NewRemoveCommand(), ) return cmd diff --git a/internal/machine/api/pb/docker.pb.go b/internal/machine/api/pb/docker.pb.go index 8cf74da9..daafbea3 100644 --- a/internal/machine/api/pb/docker.pb.go +++ b/internal/machine/api/pb/docker.pb.go @@ -67,7 +67,7 @@ func (x CreateServiceContainerRequest_ContainerType) Number() protoreflect.EnumN // Deprecated: Use CreateServiceContainerRequest_ContainerType.Descriptor instead. func (CreateServiceContainerRequest_ContainerType) EnumDescriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{31, 0} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{32, 0} } type CreateContainerRequest struct { @@ -1515,6 +1515,61 @@ func (x *MachineImages) GetContainerdStore() bool { return false } +type RemoveImageRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Force bool `protobuf:"varint,2,opt,name=force,proto3" json:"force,omitempty"` +} + +func (x *RemoveImageRequest) Reset() { + *x = RemoveImageRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveImageRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveImageRequest) ProtoMessage() {} + +func (x *RemoveImageRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveImageRequest.ProtoReflect.Descriptor instead. +func (*RemoveImageRequest) Descriptor() ([]byte, []int) { + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{25} +} + +func (x *RemoveImageRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *RemoveImageRequest) GetForce() bool { + if x != nil { + return x.Force + } + return false +} + type CreateVolumeRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1527,7 +1582,7 @@ type CreateVolumeRequest struct { func (x *CreateVolumeRequest) Reset() { *x = CreateVolumeRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[25] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1540,7 +1595,7 @@ func (x *CreateVolumeRequest) String() string { func (*CreateVolumeRequest) ProtoMessage() {} func (x *CreateVolumeRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[25] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1553,7 +1608,7 @@ func (x *CreateVolumeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateVolumeRequest.ProtoReflect.Descriptor instead. func (*CreateVolumeRequest) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{25} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{26} } func (x *CreateVolumeRequest) GetOptions() []byte { @@ -1575,7 +1630,7 @@ type CreateVolumeResponse struct { func (x *CreateVolumeResponse) Reset() { *x = CreateVolumeResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[26] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1588,7 +1643,7 @@ func (x *CreateVolumeResponse) String() string { func (*CreateVolumeResponse) ProtoMessage() {} func (x *CreateVolumeResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[26] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1601,7 +1656,7 @@ func (x *CreateVolumeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateVolumeResponse.ProtoReflect.Descriptor instead. func (*CreateVolumeResponse) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{26} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{27} } func (x *CreateVolumeResponse) GetVolume() []byte { @@ -1623,7 +1678,7 @@ type ListVolumesRequest struct { func (x *ListVolumesRequest) Reset() { *x = ListVolumesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[27] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1636,7 +1691,7 @@ func (x *ListVolumesRequest) String() string { func (*ListVolumesRequest) ProtoMessage() {} func (x *ListVolumesRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[27] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1649,7 +1704,7 @@ func (x *ListVolumesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListVolumesRequest.ProtoReflect.Descriptor instead. func (*ListVolumesRequest) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{27} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{28} } func (x *ListVolumesRequest) GetOptions() []byte { @@ -1671,7 +1726,7 @@ type ListVolumesResponse struct { func (x *ListVolumesResponse) Reset() { *x = ListVolumesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[28] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1684,7 +1739,7 @@ func (x *ListVolumesResponse) String() string { func (*ListVolumesResponse) ProtoMessage() {} func (x *ListVolumesResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[28] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1697,7 +1752,7 @@ func (x *ListVolumesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListVolumesResponse.ProtoReflect.Descriptor instead. func (*ListVolumesResponse) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{28} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{29} } func (x *ListVolumesResponse) GetMessages() []*MachineVolumes { @@ -1720,7 +1775,7 @@ type MachineVolumes struct { func (x *MachineVolumes) Reset() { *x = MachineVolumes{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[29] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1733,7 +1788,7 @@ func (x *MachineVolumes) String() string { func (*MachineVolumes) ProtoMessage() {} func (x *MachineVolumes) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[29] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1746,7 +1801,7 @@ func (x *MachineVolumes) ProtoReflect() protoreflect.Message { // Deprecated: Use MachineVolumes.ProtoReflect.Descriptor instead. func (*MachineVolumes) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{29} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{30} } func (x *MachineVolumes) GetMetadata() *Metadata { @@ -1775,7 +1830,7 @@ type RemoveVolumeRequest struct { func (x *RemoveVolumeRequest) Reset() { *x = RemoveVolumeRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[30] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1788,7 +1843,7 @@ func (x *RemoveVolumeRequest) String() string { func (*RemoveVolumeRequest) ProtoMessage() {} func (x *RemoveVolumeRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[30] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1801,7 +1856,7 @@ func (x *RemoveVolumeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveVolumeRequest.ProtoReflect.Descriptor instead. func (*RemoveVolumeRequest) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{30} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{31} } func (x *RemoveVolumeRequest) GetId() string { @@ -1833,7 +1888,7 @@ type CreateServiceContainerRequest struct { func (x *CreateServiceContainerRequest) Reset() { *x = CreateServiceContainerRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[31] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1846,7 +1901,7 @@ func (x *CreateServiceContainerRequest) String() string { func (*CreateServiceContainerRequest) ProtoMessage() {} func (x *CreateServiceContainerRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[31] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1859,7 +1914,7 @@ func (x *CreateServiceContainerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateServiceContainerRequest.ProtoReflect.Descriptor instead. func (*CreateServiceContainerRequest) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{31} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{32} } func (x *CreateServiceContainerRequest) GetServiceId() string { @@ -1904,7 +1959,7 @@ type ServiceContainer struct { func (x *ServiceContainer) Reset() { *x = ServiceContainer{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[32] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1917,7 +1972,7 @@ func (x *ServiceContainer) String() string { func (*ServiceContainer) ProtoMessage() {} func (x *ServiceContainer) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[32] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1930,7 +1985,7 @@ func (x *ServiceContainer) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceContainer.ProtoReflect.Descriptor instead. func (*ServiceContainer) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{32} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{33} } func (x *ServiceContainer) GetContainer() []byte { @@ -1960,7 +2015,7 @@ type ListServiceContainersRequest struct { func (x *ListServiceContainersRequest) Reset() { *x = ListServiceContainersRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[33] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1973,7 +2028,7 @@ func (x *ListServiceContainersRequest) String() string { func (*ListServiceContainersRequest) ProtoMessage() {} func (x *ListServiceContainersRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[33] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1986,7 +2041,7 @@ func (x *ListServiceContainersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListServiceContainersRequest.ProtoReflect.Descriptor instead. func (*ListServiceContainersRequest) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{33} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{34} } func (x *ListServiceContainersRequest) GetServiceId() string { @@ -2016,7 +2071,7 @@ type ListServiceContainersResponse struct { func (x *ListServiceContainersResponse) Reset() { *x = ListServiceContainersResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[34] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2029,7 +2084,7 @@ func (x *ListServiceContainersResponse) String() string { func (*ListServiceContainersResponse) ProtoMessage() {} func (x *ListServiceContainersResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[34] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2042,7 +2097,7 @@ func (x *ListServiceContainersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListServiceContainersResponse.ProtoReflect.Descriptor instead. func (*ListServiceContainersResponse) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{34} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{35} } func (x *ListServiceContainersResponse) GetMessages() []*MachineServiceContainers { @@ -2066,7 +2121,7 @@ type MachineServiceContainers struct { func (x *MachineServiceContainers) Reset() { *x = MachineServiceContainers{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[35] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2079,7 +2134,7 @@ func (x *MachineServiceContainers) String() string { func (*MachineServiceContainers) ProtoMessage() {} func (x *MachineServiceContainers) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[35] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2092,7 +2147,7 @@ func (x *MachineServiceContainers) ProtoReflect() protoreflect.Message { // Deprecated: Use MachineServiceContainers.ProtoReflect.Descriptor instead. func (*MachineServiceContainers) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{35} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{36} } func (x *MachineServiceContainers) GetMetadata() *Metadata { @@ -2247,168 +2302,175 @@ var file_internal_machine_api_pb_docker_proto_rawDesc = []byte{ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x64, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x2f, 0x0a, 0x13, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x2e, 0x0a, 0x14, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x22, 0x2e, 0x0a, 0x12, 0x4c, - 0x69, 0x73, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x46, 0x0a, 0x13, 0x4c, - 0x69, 0x73, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, - 0x6e, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x73, 0x22, 0x57, 0x0a, 0x0e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x56, 0x6f, - 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x0a, 0x13, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x8f, 0x02, 0x0a, 0x1d, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x25, 0x0a, - 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x57, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x22, 0x2c, 0x0a, - 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, - 0x0a, 0x07, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x50, - 0x52, 0x45, 0x5f, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x10, 0x01, 0x22, 0x53, 0x0a, 0x10, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, - 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x0a, - 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, - 0x22, 0x57, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, - 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x5a, 0x0a, 0x1d, 0x4c, 0x69, 0x73, - 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x08, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0xbc, 0x01, 0x0a, 0x18, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, - 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x73, 0x12, 0x29, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x35, 0x0a, - 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x73, 0x12, 0x3e, 0x0a, 0x0f, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x69, 0x6e, 0x65, 0x72, 0x64, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x3a, 0x0a, 0x12, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x2f, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, + 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x2e, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x22, 0x2e, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x56, + 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, + 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x46, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x56, + 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, + 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x56, 0x6f, + 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, + 0x57, 0x0a, 0x0e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, + 0x73, 0x12, 0x29, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x0a, 0x13, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, + 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x8f, 0x02, 0x0a, 0x1d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x57, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x22, 0x2c, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, + 0x52, 0x56, 0x49, 0x43, 0x45, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x45, 0x5f, 0x44, + 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x10, 0x01, 0x22, 0x53, 0x0a, 0x10, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x22, 0x57, 0x0a, 0x1c, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x5a, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x73, 0x22, 0xbc, 0x01, 0x0a, 0x18, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x29, + 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, + 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x35, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x52, 0x0e, 0x68, 0x6f, 0x6f, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x73, 0x32, 0xfb, 0x0a, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x12, - 0x4c, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, - 0x10, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, - 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x69, 0x6e, 0x65, 0x72, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, + 0x12, 0x3e, 0x0a, 0x0f, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x52, 0x0e, 0x68, 0x6f, 0x6f, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, + 0x32, 0xbb, 0x0b, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x4c, 0x0a, 0x0f, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1b, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x10, 0x49, 0x6e, 0x73, + 0x70, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0e, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x12, 0x42, 0x0a, 0x0d, 0x53, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0d, 0x53, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x70, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4a, 0x0a, 0x0d, 0x45, - 0x78, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x78, - 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x32, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, - 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0d, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x30, 0x01, 0x12, 0x36, 0x0a, 0x09, 0x50, - 0x75, 0x6c, 0x6c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, - 0x75, 0x6c, 0x6c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x30, 0x01, 0x12, 0x43, 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x49, 0x6d, - 0x61, 0x67, 0x65, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, - 0x74, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x49, 0x6d, 0x61, 0x67, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x12, 0x49, 0x6e, 0x73, 0x70, - 0x65, 0x63, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1e, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3d, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x12, 0x16, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x49, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, - 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x18, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6d, - 0x65, 0x73, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x6f, 0x6c, - 0x75, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0c, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x56, - 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x46, 0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x5a, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x17, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1c, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x12, 0x5e, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x21, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1b, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x70, 0x73, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x6b, 0x69, 0x2f, 0x75, 0x6e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6d, 0x61, 0x63, - 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4a, 0x0a, 0x0d, 0x45, 0x78, 0x65, 0x63, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, + 0x78, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, + 0x01, 0x30, 0x01, 0x12, 0x32, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x6f, 0x67, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x30, 0x01, 0x12, 0x36, 0x0a, 0x09, 0x50, 0x75, 0x6c, 0x6c, 0x49, + 0x6d, 0x61, 0x67, 0x65, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x49, + 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x12, + 0x43, 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, + 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x49, 0x6d, 0x61, + 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x12, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, + 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x6d, + 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x6d, + 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x4c, + 0x69, 0x73, 0x74, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6d, 0x61, 0x67, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x0c, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x40, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x12, 0x17, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x40, 0x0a, 0x0c, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, + 0x65, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x56, 0x6f, + 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x5a, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x22, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4e, 0x0a, 0x17, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, + 0x5e, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4d, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x37, + 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x73, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x73, 0x6b, 0x69, 0x2f, 0x75, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2424,7 +2486,7 @@ func file_internal_machine_api_pb_docker_proto_rawDescGZIP() []byte { } var file_internal_machine_api_pb_docker_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_internal_machine_api_pb_docker_proto_msgTypes = make([]protoimpl.MessageInfo, 36) +var file_internal_machine_api_pb_docker_proto_msgTypes = make([]protoimpl.MessageInfo, 37) var file_internal_machine_api_pb_docker_proto_goTypes = []any{ (CreateServiceContainerRequest_ContainerType)(0), // 0: api.CreateServiceContainerRequest.ContainerType (*CreateContainerRequest)(nil), // 1: api.CreateContainerRequest @@ -2452,40 +2514,41 @@ var file_internal_machine_api_pb_docker_proto_goTypes = []any{ (*ListImagesRequest)(nil), // 23: api.ListImagesRequest (*ListImagesResponse)(nil), // 24: api.ListImagesResponse (*MachineImages)(nil), // 25: api.MachineImages - (*CreateVolumeRequest)(nil), // 26: api.CreateVolumeRequest - (*CreateVolumeResponse)(nil), // 27: api.CreateVolumeResponse - (*ListVolumesRequest)(nil), // 28: api.ListVolumesRequest - (*ListVolumesResponse)(nil), // 29: api.ListVolumesResponse - (*MachineVolumes)(nil), // 30: api.MachineVolumes - (*RemoveVolumeRequest)(nil), // 31: api.RemoveVolumeRequest - (*CreateServiceContainerRequest)(nil), // 32: api.CreateServiceContainerRequest - (*ServiceContainer)(nil), // 33: api.ServiceContainer - (*ListServiceContainersRequest)(nil), // 34: api.ListServiceContainersRequest - (*ListServiceContainersResponse)(nil), // 35: api.ListServiceContainersResponse - (*MachineServiceContainers)(nil), // 36: api.MachineServiceContainers - (*Metadata)(nil), // 37: api.Metadata - (*LogsRequest)(nil), // 38: api.LogsRequest - (*emptypb.Empty)(nil), // 39: google.protobuf.Empty - (*LogEntry)(nil), // 40: api.LogEntry + (*RemoveImageRequest)(nil), // 26: api.RemoveImageRequest + (*CreateVolumeRequest)(nil), // 27: api.CreateVolumeRequest + (*CreateVolumeResponse)(nil), // 28: api.CreateVolumeResponse + (*ListVolumesRequest)(nil), // 29: api.ListVolumesRequest + (*ListVolumesResponse)(nil), // 30: api.ListVolumesResponse + (*MachineVolumes)(nil), // 31: api.MachineVolumes + (*RemoveVolumeRequest)(nil), // 32: api.RemoveVolumeRequest + (*CreateServiceContainerRequest)(nil), // 33: api.CreateServiceContainerRequest + (*ServiceContainer)(nil), // 34: api.ServiceContainer + (*ListServiceContainersRequest)(nil), // 35: api.ListServiceContainersRequest + (*ListServiceContainersResponse)(nil), // 36: api.ListServiceContainersResponse + (*MachineServiceContainers)(nil), // 37: api.MachineServiceContainers + (*Metadata)(nil), // 38: api.Metadata + (*LogsRequest)(nil), // 39: api.LogsRequest + (*emptypb.Empty)(nil), // 40: google.protobuf.Empty + (*LogEntry)(nil), // 41: api.LogEntry } var file_internal_machine_api_pb_docker_proto_depIdxs = []int32{ 9, // 0: api.ListContainersResponse.messages:type_name -> api.MachineContainers - 37, // 1: api.MachineContainers.metadata:type_name -> api.Metadata + 38, // 1: api.MachineContainers.metadata:type_name -> api.Metadata 12, // 2: api.ExecContainerRequest.config:type_name -> api.ExecConfig 13, // 3: api.ExecContainerRequest.resize:type_name -> api.ResizeEvent 19, // 4: api.InspectImageResponse.messages:type_name -> api.Image - 37, // 5: api.Image.metadata:type_name -> api.Metadata + 38, // 5: api.Image.metadata:type_name -> api.Metadata 22, // 6: api.InspectRemoteImageResponse.messages:type_name -> api.RemoteImage - 37, // 7: api.RemoteImage.metadata:type_name -> api.Metadata + 38, // 7: api.RemoteImage.metadata:type_name -> api.Metadata 25, // 8: api.ListImagesResponse.messages:type_name -> api.MachineImages - 37, // 9: api.MachineImages.metadata:type_name -> api.Metadata - 30, // 10: api.ListVolumesResponse.messages:type_name -> api.MachineVolumes - 37, // 11: api.MachineVolumes.metadata:type_name -> api.Metadata + 38, // 9: api.MachineImages.metadata:type_name -> api.Metadata + 31, // 10: api.ListVolumesResponse.messages:type_name -> api.MachineVolumes + 38, // 11: api.MachineVolumes.metadata:type_name -> api.Metadata 0, // 12: api.CreateServiceContainerRequest.container_type:type_name -> api.CreateServiceContainerRequest.ContainerType - 36, // 13: api.ListServiceContainersResponse.messages:type_name -> api.MachineServiceContainers - 37, // 14: api.MachineServiceContainers.metadata:type_name -> api.Metadata - 33, // 15: api.MachineServiceContainers.containers:type_name -> api.ServiceContainer - 33, // 16: api.MachineServiceContainers.hook_containers:type_name -> api.ServiceContainer + 37, // 13: api.ListServiceContainersResponse.messages:type_name -> api.MachineServiceContainers + 38, // 14: api.MachineServiceContainers.metadata:type_name -> api.Metadata + 34, // 15: api.MachineServiceContainers.containers:type_name -> api.ServiceContainer + 34, // 16: api.MachineServiceContainers.hook_containers:type_name -> api.ServiceContainer 1, // 17: api.Docker.CreateContainer:input_type -> api.CreateContainerRequest 3, // 18: api.Docker.InspectContainer:input_type -> api.InspectContainerRequest 5, // 19: api.Docker.StartContainer:input_type -> api.StartContainerRequest @@ -2493,39 +2556,41 @@ var file_internal_machine_api_pb_docker_proto_depIdxs = []int32{ 7, // 21: api.Docker.ListContainers:input_type -> api.ListContainersRequest 10, // 22: api.Docker.RemoveContainer:input_type -> api.RemoveContainerRequest 11, // 23: api.Docker.ExecContainer:input_type -> api.ExecContainerRequest - 38, // 24: api.Docker.ContainerLogs:input_type -> api.LogsRequest + 39, // 24: api.Docker.ContainerLogs:input_type -> api.LogsRequest 15, // 25: api.Docker.PullImage:input_type -> api.PullImageRequest 17, // 26: api.Docker.InspectImage:input_type -> api.InspectImageRequest 20, // 27: api.Docker.InspectRemoteImage:input_type -> api.InspectRemoteImageRequest 23, // 28: api.Docker.ListImages:input_type -> api.ListImagesRequest - 26, // 29: api.Docker.CreateVolume:input_type -> api.CreateVolumeRequest - 28, // 30: api.Docker.ListVolumes:input_type -> api.ListVolumesRequest - 31, // 31: api.Docker.RemoveVolume:input_type -> api.RemoveVolumeRequest - 32, // 32: api.Docker.CreateServiceContainer:input_type -> api.CreateServiceContainerRequest - 3, // 33: api.Docker.InspectServiceContainer:input_type -> api.InspectContainerRequest - 34, // 34: api.Docker.ListServiceContainers:input_type -> api.ListServiceContainersRequest - 10, // 35: api.Docker.RemoveServiceContainer:input_type -> api.RemoveContainerRequest - 2, // 36: api.Docker.CreateContainer:output_type -> api.CreateContainerResponse - 4, // 37: api.Docker.InspectContainer:output_type -> api.InspectContainerResponse - 39, // 38: api.Docker.StartContainer:output_type -> google.protobuf.Empty - 39, // 39: api.Docker.StopContainer:output_type -> google.protobuf.Empty - 8, // 40: api.Docker.ListContainers:output_type -> api.ListContainersResponse - 39, // 41: api.Docker.RemoveContainer:output_type -> google.protobuf.Empty - 14, // 42: api.Docker.ExecContainer:output_type -> api.ExecContainerResponse - 40, // 43: api.Docker.ContainerLogs:output_type -> api.LogEntry - 16, // 44: api.Docker.PullImage:output_type -> api.JSONMessage - 18, // 45: api.Docker.InspectImage:output_type -> api.InspectImageResponse - 21, // 46: api.Docker.InspectRemoteImage:output_type -> api.InspectRemoteImageResponse - 24, // 47: api.Docker.ListImages:output_type -> api.ListImagesResponse - 27, // 48: api.Docker.CreateVolume:output_type -> api.CreateVolumeResponse - 29, // 49: api.Docker.ListVolumes:output_type -> api.ListVolumesResponse - 39, // 50: api.Docker.RemoveVolume:output_type -> google.protobuf.Empty - 2, // 51: api.Docker.CreateServiceContainer:output_type -> api.CreateContainerResponse - 33, // 52: api.Docker.InspectServiceContainer:output_type -> api.ServiceContainer - 35, // 53: api.Docker.ListServiceContainers:output_type -> api.ListServiceContainersResponse - 39, // 54: api.Docker.RemoveServiceContainer:output_type -> google.protobuf.Empty - 36, // [36:55] is the sub-list for method output_type - 17, // [17:36] is the sub-list for method input_type + 26, // 29: api.Docker.RemoveImage:input_type -> api.RemoveImageRequest + 27, // 30: api.Docker.CreateVolume:input_type -> api.CreateVolumeRequest + 29, // 31: api.Docker.ListVolumes:input_type -> api.ListVolumesRequest + 32, // 32: api.Docker.RemoveVolume:input_type -> api.RemoveVolumeRequest + 33, // 33: api.Docker.CreateServiceContainer:input_type -> api.CreateServiceContainerRequest + 3, // 34: api.Docker.InspectServiceContainer:input_type -> api.InspectContainerRequest + 35, // 35: api.Docker.ListServiceContainers:input_type -> api.ListServiceContainersRequest + 10, // 36: api.Docker.RemoveServiceContainer:input_type -> api.RemoveContainerRequest + 2, // 37: api.Docker.CreateContainer:output_type -> api.CreateContainerResponse + 4, // 38: api.Docker.InspectContainer:output_type -> api.InspectContainerResponse + 40, // 39: api.Docker.StartContainer:output_type -> google.protobuf.Empty + 40, // 40: api.Docker.StopContainer:output_type -> google.protobuf.Empty + 8, // 41: api.Docker.ListContainers:output_type -> api.ListContainersResponse + 40, // 42: api.Docker.RemoveContainer:output_type -> google.protobuf.Empty + 14, // 43: api.Docker.ExecContainer:output_type -> api.ExecContainerResponse + 41, // 44: api.Docker.ContainerLogs:output_type -> api.LogEntry + 16, // 45: api.Docker.PullImage:output_type -> api.JSONMessage + 18, // 46: api.Docker.InspectImage:output_type -> api.InspectImageResponse + 21, // 47: api.Docker.InspectRemoteImage:output_type -> api.InspectRemoteImageResponse + 24, // 48: api.Docker.ListImages:output_type -> api.ListImagesResponse + 40, // 49: api.Docker.RemoveImage:output_type -> google.protobuf.Empty + 28, // 50: api.Docker.CreateVolume:output_type -> api.CreateVolumeResponse + 30, // 51: api.Docker.ListVolumes:output_type -> api.ListVolumesResponse + 40, // 52: api.Docker.RemoveVolume:output_type -> google.protobuf.Empty + 2, // 53: api.Docker.CreateServiceContainer:output_type -> api.CreateContainerResponse + 34, // 54: api.Docker.InspectServiceContainer:output_type -> api.ServiceContainer + 36, // 55: api.Docker.ListServiceContainers:output_type -> api.ListServiceContainersResponse + 40, // 56: api.Docker.RemoveServiceContainer:output_type -> google.protobuf.Empty + 37, // [37:57] is the sub-list for method output_type + 17, // [17:37] is the sub-list for method input_type 17, // [17:17] is the sub-list for extension type_name 17, // [17:17] is the sub-list for extension extendee 0, // [0:17] is the sub-list for field type_name @@ -2839,7 +2904,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[25].Exporter = func(v any, i int) any { - switch v := v.(*CreateVolumeRequest); i { + switch v := v.(*RemoveImageRequest); i { case 0: return &v.state case 1: @@ -2851,7 +2916,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[26].Exporter = func(v any, i int) any { - switch v := v.(*CreateVolumeResponse); i { + switch v := v.(*CreateVolumeRequest); i { case 0: return &v.state case 1: @@ -2863,7 +2928,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[27].Exporter = func(v any, i int) any { - switch v := v.(*ListVolumesRequest); i { + switch v := v.(*CreateVolumeResponse); i { case 0: return &v.state case 1: @@ -2875,7 +2940,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[28].Exporter = func(v any, i int) any { - switch v := v.(*ListVolumesResponse); i { + switch v := v.(*ListVolumesRequest); i { case 0: return &v.state case 1: @@ -2887,7 +2952,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[29].Exporter = func(v any, i int) any { - switch v := v.(*MachineVolumes); i { + switch v := v.(*ListVolumesResponse); i { case 0: return &v.state case 1: @@ -2899,7 +2964,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[30].Exporter = func(v any, i int) any { - switch v := v.(*RemoveVolumeRequest); i { + switch v := v.(*MachineVolumes); i { case 0: return &v.state case 1: @@ -2911,7 +2976,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[31].Exporter = func(v any, i int) any { - switch v := v.(*CreateServiceContainerRequest); i { + switch v := v.(*RemoveVolumeRequest); i { case 0: return &v.state case 1: @@ -2923,7 +2988,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[32].Exporter = func(v any, i int) any { - switch v := v.(*ServiceContainer); i { + switch v := v.(*CreateServiceContainerRequest); i { case 0: return &v.state case 1: @@ -2935,7 +3000,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[33].Exporter = func(v any, i int) any { - switch v := v.(*ListServiceContainersRequest); i { + switch v := v.(*ServiceContainer); i { case 0: return &v.state case 1: @@ -2947,7 +3012,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[34].Exporter = func(v any, i int) any { - switch v := v.(*ListServiceContainersResponse); i { + switch v := v.(*ListServiceContainersRequest); i { case 0: return &v.state case 1: @@ -2959,6 +3024,18 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[35].Exporter = func(v any, i int) any { + switch v := v.(*ListServiceContainersResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_machine_api_pb_docker_proto_msgTypes[36].Exporter = func(v any, i int) any { switch v := v.(*MachineServiceContainers); i { case 0: return &v.state @@ -2988,7 +3065,7 @@ func file_internal_machine_api_pb_docker_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_internal_machine_api_pb_docker_proto_rawDesc, NumEnums: 1, - NumMessages: 36, + NumMessages: 37, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/machine/api/pb/docker.proto b/internal/machine/api/pb/docker.proto index 09d93100..5d234471 100644 --- a/internal/machine/api/pb/docker.proto +++ b/internal/machine/api/pb/docker.proto @@ -24,6 +24,7 @@ service Docker { // Docker auth credentials if necessary. rpc InspectRemoteImage(InspectRemoteImageRequest) returns (InspectRemoteImageResponse); rpc ListImages(ListImagesRequest) returns (ListImagesResponse); + rpc RemoveImage(RemoveImageRequest) returns (google.protobuf.Empty); rpc CreateVolume(CreateVolumeRequest) returns (CreateVolumeResponse); rpc ListVolumes(ListVolumesRequest) returns (ListVolumesResponse); @@ -192,6 +193,11 @@ message MachineImages { bool containerd_store = 3; } +message RemoveImageRequest { + string id = 1; + bool force = 2; +} + message CreateVolumeRequest { // JSON serialised volume.CreateOptions. bytes options = 1; diff --git a/internal/machine/api/pb/docker_grpc.pb.go b/internal/machine/api/pb/docker_grpc.pb.go index e5a743ce..12320b0b 100644 --- a/internal/machine/api/pb/docker_grpc.pb.go +++ b/internal/machine/api/pb/docker_grpc.pb.go @@ -32,6 +32,7 @@ const ( Docker_InspectImage_FullMethodName = "/api.Docker/InspectImage" Docker_InspectRemoteImage_FullMethodName = "/api.Docker/InspectRemoteImage" Docker_ListImages_FullMethodName = "/api.Docker/ListImages" + Docker_RemoveImage_FullMethodName = "/api.Docker/RemoveImage" Docker_CreateVolume_FullMethodName = "/api.Docker/CreateVolume" Docker_ListVolumes_FullMethodName = "/api.Docker/ListVolumes" Docker_RemoveVolume_FullMethodName = "/api.Docker/RemoveVolume" @@ -59,6 +60,7 @@ type DockerClient interface { // Docker auth credentials if necessary. InspectRemoteImage(ctx context.Context, in *InspectRemoteImageRequest, opts ...grpc.CallOption) (*InspectRemoteImageResponse, error) ListImages(ctx context.Context, in *ListImagesRequest, opts ...grpc.CallOption) (*ListImagesResponse, error) + RemoveImage(ctx context.Context, in *RemoveImageRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) CreateVolume(ctx context.Context, in *CreateVolumeRequest, opts ...grpc.CallOption) (*CreateVolumeResponse, error) ListVolumes(ctx context.Context, in *ListVolumesRequest, opts ...grpc.CallOption) (*ListVolumesResponse, error) RemoveVolume(ctx context.Context, in *RemoveVolumeRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) @@ -217,6 +219,16 @@ func (c *dockerClient) ListImages(ctx context.Context, in *ListImagesRequest, op return out, nil } +func (c *dockerClient) RemoveImage(ctx context.Context, in *RemoveImageRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, Docker_RemoveImage_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *dockerClient) CreateVolume(ctx context.Context, in *CreateVolumeRequest, opts ...grpc.CallOption) (*CreateVolumeResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CreateVolumeResponse) @@ -305,6 +317,7 @@ type DockerServer interface { // Docker auth credentials if necessary. InspectRemoteImage(context.Context, *InspectRemoteImageRequest) (*InspectRemoteImageResponse, error) ListImages(context.Context, *ListImagesRequest) (*ListImagesResponse, error) + RemoveImage(context.Context, *RemoveImageRequest) (*emptypb.Empty, error) CreateVolume(context.Context, *CreateVolumeRequest) (*CreateVolumeResponse, error) ListVolumes(context.Context, *ListVolumesRequest) (*ListVolumesResponse, error) RemoveVolume(context.Context, *RemoveVolumeRequest) (*emptypb.Empty, error) @@ -358,6 +371,9 @@ func (UnimplementedDockerServer) InspectRemoteImage(context.Context, *InspectRem func (UnimplementedDockerServer) ListImages(context.Context, *ListImagesRequest) (*ListImagesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListImages not implemented") } +func (UnimplementedDockerServer) RemoveImage(context.Context, *RemoveImageRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemoveImage not implemented") +} func (UnimplementedDockerServer) CreateVolume(context.Context, *CreateVolumeRequest) (*CreateVolumeResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateVolume not implemented") } @@ -591,6 +607,24 @@ func _Docker_ListImages_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Docker_RemoveImage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemoveImageRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DockerServer).RemoveImage(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Docker_RemoveImage_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DockerServer).RemoveImage(ctx, req.(*RemoveImageRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Docker_CreateVolume_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateVolumeRequest) if err := dec(in); err != nil { @@ -760,6 +794,10 @@ var Docker_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListImages", Handler: _Docker_ListImages_Handler, }, + { + MethodName: "RemoveImage", + Handler: _Docker_RemoveImage_Handler, + }, { MethodName: "CreateVolume", Handler: _Docker_CreateVolume_Handler, diff --git a/internal/machine/docker/client.go b/internal/machine/docker/client.go index fd7e89fa..4cbd6540 100644 --- a/internal/machine/docker/client.go +++ b/internal/machine/docker/client.go @@ -420,6 +420,21 @@ func (c *Client) RemoveVolume(ctx context.Context, id string, force bool) error return err } +// RemoveImage removes an image with the given ID. +func (c *Client) RemoveImage(ctx context.Context, id string, force bool) error { + _, err := c.GRPCClient.RemoveImage(ctx, &pb.RemoveImageRequest{ + Id: id, + Force: force, + }) + if err != nil { + if status.Convert(err).Code() == codes.NotFound { + return errdefs.NotFound(err) + } + } + + return err +} + // InspectServiceContainer returns the container information and service specification that was used to create the // container with the given ID. func (c *Client) InspectServiceContainer(ctx context.Context, id string) (api.ServiceContainer, error) { diff --git a/internal/machine/docker/server.go b/internal/machine/docker/server.go index 813f15c1..94c46d55 100644 --- a/internal/machine/docker/server.go +++ b/internal/machine/docker/server.go @@ -431,6 +431,22 @@ func (s *Server) ListImages(ctx context.Context, req *pb.ListImagesRequest) (*pb }, nil } +func (s *Server) RemoveImage(ctx context.Context, req *pb.RemoveImageRequest) (*emptypb.Empty, error) { + opts := image.RemoveOptions{ + Force: req.Force, + PruneChildren: true, // TODO(miek): make option? + } + + if _, err := s.client.ImageRemove(ctx, req.Id, opts); err != nil { + if errdefs.IsNotFound(err) { + return nil, status.Error(codes.NotFound, err.Error()) + } + return nil, status.Error(codes.Internal, err.Error()) + } + + return &emptypb.Empty{}, nil +} + // CreateVolume creates a new volume with the given options. func (s *Server) CreateVolume(ctx context.Context, req *pb.CreateVolumeRequest) (*pb.CreateVolumeResponse, error) { var opts volume.CreateOptions diff --git a/mise.lock b/mise.lock index b262818c..367f9a81 100644 --- a/mise.lock +++ b/mise.lock @@ -1,83 +1,252 @@ -# @generated - this file is auto-generated by `mise lock` https://mise.jdx.dev/dev-tools/mise-lock.html +# @generated - this file is auto-generated by `mise lock` https://mise.en.dev/dev-tools/mise-lock.html [[tools."aqua:vektra/mockery"]] version = "3.5.3" backend = "aqua:vektra/mockery" +[tools."aqua:vektra/mockery"."platforms.linux-arm64"] +checksum = "sha256:ec02ca72b7ad1ff5a1de5503a27d3b1b3f230d722eb35c5b92e43e295a8e1290" +url = "https://github.com/vektra/mockery/releases/download/v3.5.3/mockery_3.5.3_Linux_arm64.tar.gz" + +[tools."aqua:vektra/mockery"."platforms.linux-arm64-musl"] +checksum = "sha256:ec02ca72b7ad1ff5a1de5503a27d3b1b3f230d722eb35c5b92e43e295a8e1290" +url = "https://github.com/vektra/mockery/releases/download/v3.5.3/mockery_3.5.3_Linux_arm64.tar.gz" + [tools."aqua:vektra/mockery"."platforms.linux-x64"] checksum = "sha256:ebce416b0175338525246c376885a1579ca6cd4d4015140ba0c70e6b5339a39c" url = "https://github.com/vektra/mockery/releases/download/v3.5.3/mockery_3.5.3_Linux_x86_64.tar.gz" +[tools."aqua:vektra/mockery"."platforms.linux-x64-musl"] +checksum = "sha256:ebce416b0175338525246c376885a1579ca6cd4d4015140ba0c70e6b5339a39c" +url = "https://github.com/vektra/mockery/releases/download/v3.5.3/mockery_3.5.3_Linux_x86_64.tar.gz" + [tools."aqua:vektra/mockery"."platforms.macos-arm64"] checksum = "sha256:a3a94b14c7414e148f2252199ffc4a0108d311358f3d336cbe05bb73cb203704" url = "https://github.com/vektra/mockery/releases/download/v3.5.3/mockery_3.5.3_Darwin_arm64.tar.gz" +[tools."aqua:vektra/mockery"."platforms.macos-x64"] +checksum = "sha256:8bd2b3e4722e476400395920fb5bbd68be4ea22ec12cddf1e424c40610fda863" +url = "https://github.com/vektra/mockery/releases/download/v3.5.3/mockery_3.5.3_Darwin_x86_64.tar.gz" + +[tools."aqua:vektra/mockery"."platforms.windows-x64"] +checksum = "sha256:3b4264066db615a56a8b59abda992f6db82b8cd7666937ed9dd8f4a4bfc424a0" +url = "https://github.com/vektra/mockery/releases/download/v3.5.3/mockery_3.5.3_Windows_x86_64.tar.gz" + [[tools.go]] version = "1.26.1" backend = "core:go" +[tools.go."platforms.linux-arm64"] +checksum = "sha256:a290581cfe4fe28ddd737dde3095f3dbeb7f2e4065cab4eae44dfc53b760c2f7" +url = "https://dl.google.com/go/go1.26.1.linux-arm64.tar.gz" + +[tools.go."platforms.linux-arm64-musl"] +checksum = "sha256:a290581cfe4fe28ddd737dde3095f3dbeb7f2e4065cab4eae44dfc53b760c2f7" +url = "https://dl.google.com/go/go1.26.1.linux-arm64.tar.gz" + [tools.go."platforms.linux-x64"] checksum = "sha256:031f088e5d955bab8657ede27ad4e3bc5b7c1ba281f05f245bcc304f327c987a" url = "https://dl.google.com/go/go1.26.1.linux-amd64.tar.gz" +[tools.go."platforms.linux-x64-musl"] +checksum = "sha256:031f088e5d955bab8657ede27ad4e3bc5b7c1ba281f05f245bcc304f327c987a" +url = "https://dl.google.com/go/go1.26.1.linux-amd64.tar.gz" + [tools.go."platforms.macos-arm64"] checksum = "sha256:353df43a7811ce284c8938b5f3c7df40b7bfb6f56cb165b150bc40b5e2dd541f" url = "https://dl.google.com/go/go1.26.1.darwin-arm64.tar.gz" +[tools.go."platforms.macos-x64"] +checksum = "sha256:65773dab2f8cc4cd23d93ba6d0a805de150ca0b78378879292be0b903b8cdd08" +url = "https://dl.google.com/go/go1.26.1.darwin-amd64.tar.gz" + +[tools.go."platforms.windows-x64"] +checksum = "sha256:9b68112c913f45b7aebbf13c036721264bbba7e03a642f8f7490c561eebd1ecc" +url = "https://dl.google.com/go/go1.26.1.windows-amd64.zip" + [[tools.golangci-lint]] version = "2.11.2" backend = "aqua:golangci/golangci-lint" +[tools.golangci-lint."platforms.linux-arm64"] +checksum = "sha256:c3c83c7ed003e881991af21361c487151abd37969927ed9062cd0b48f3cd1d8d" +url = "https://github.com/golangci/golangci-lint/releases/download/v2.11.2/golangci-lint-2.11.2-linux-arm64.tar.gz" +provenance = "github-attestations" + +[tools.golangci-lint."platforms.linux-arm64-musl"] +checksum = "sha256:c3c83c7ed003e881991af21361c487151abd37969927ed9062cd0b48f3cd1d8d" +url = "https://github.com/golangci/golangci-lint/releases/download/v2.11.2/golangci-lint-2.11.2-linux-arm64.tar.gz" +provenance = "github-attestations" + [tools.golangci-lint."platforms.linux-x64"] checksum = "sha256:852741ea769f4543ab4b6cf86b313cb7173f2e8d2d39f00eb0cd5ef5d4d5eda9" url = "https://github.com/golangci/golangci-lint/releases/download/v2.11.2/golangci-lint-2.11.2-linux-amd64.tar.gz" provenance = "github-attestations" +[tools.golangci-lint."platforms.linux-x64-musl"] +checksum = "sha256:852741ea769f4543ab4b6cf86b313cb7173f2e8d2d39f00eb0cd5ef5d4d5eda9" +url = "https://github.com/golangci/golangci-lint/releases/download/v2.11.2/golangci-lint-2.11.2-linux-amd64.tar.gz" +provenance = "github-attestations" + [tools.golangci-lint."platforms.macos-arm64"] checksum = "sha256:11e9549b955bae4bfb71aa3b5c2762e446e2d3f975fe963d6d767b8f745d9344" url = "https://github.com/golangci/golangci-lint/releases/download/v2.11.2/golangci-lint-2.11.2-darwin-arm64.tar.gz" provenance = "github-attestations" +[tools.golangci-lint."platforms.macos-x64"] +checksum = "sha256:1dbbbe745eadba9cf012d49bd0b8c9290cbcb50dbf2cf9611f75a715b46ae3af" +url = "https://github.com/golangci/golangci-lint/releases/download/v2.11.2/golangci-lint-2.11.2-darwin-amd64.tar.gz" +provenance = "github-attestations" + +[tools.golangci-lint."platforms.windows-x64"] +checksum = "sha256:60e50178253d276d1c808ef00845eddcabca63b7d69d86a6dbaa41e88bc843f3" +url = "https://github.com/golangci/golangci-lint/releases/download/v2.11.2/golangci-lint-2.11.2-windows-amd64.zip" +provenance = "github-attestations" + [[tools.goreleaser]] version = "2.15.2" backend = "aqua:goreleaser/goreleaser" +[tools.goreleaser."platforms.linux-arm64"] +checksum = "sha256:5db66761a98f6693161e49e1a95d28d2673a892ba60cb4a5e16736cafd41c4c9" +url = "https://github.com/goreleaser/goreleaser/releases/download/v2.15.2/goreleaser_Linux_arm64.tar.gz" +provenance = "github-attestations" + +[tools.goreleaser."platforms.linux-arm64-musl"] +checksum = "sha256:5db66761a98f6693161e49e1a95d28d2673a892ba60cb4a5e16736cafd41c4c9" +url = "https://github.com/goreleaser/goreleaser/releases/download/v2.15.2/goreleaser_Linux_arm64.tar.gz" +provenance = "github-attestations" + [tools.goreleaser."platforms.linux-x64"] checksum = "sha256:0ebdbf0353aba566b969dde746cc4e4806f96c27aa2f3971b229a9df7611fedc" url = "https://github.com/goreleaser/goreleaser/releases/download/v2.15.2/goreleaser_Linux_x86_64.tar.gz" provenance = "github-attestations" +[tools.goreleaser."platforms.linux-x64-musl"] +checksum = "sha256:0ebdbf0353aba566b969dde746cc4e4806f96c27aa2f3971b229a9df7611fedc" +url = "https://github.com/goreleaser/goreleaser/releases/download/v2.15.2/goreleaser_Linux_x86_64.tar.gz" +provenance = "github-attestations" + [tools.goreleaser."platforms.macos-arm64"] checksum = "sha256:0e6bd67688ac949780bf1166813a91f89856898ef4c40d7d46c2c74ebaa4b9ee" url = "https://github.com/goreleaser/goreleaser/releases/download/v2.15.2/goreleaser_Darwin_all.tar.gz" provenance = "github-attestations" +[tools.goreleaser."platforms.macos-x64"] +checksum = "sha256:0e6bd67688ac949780bf1166813a91f89856898ef4c40d7d46c2c74ebaa4b9ee" +url = "https://github.com/goreleaser/goreleaser/releases/download/v2.15.2/goreleaser_Darwin_all.tar.gz" +provenance = "github-attestations" + +[tools.goreleaser."platforms.windows-x64"] +checksum = "sha256:7459832946dbe122c144f8d7f87484d8572ca005b779310aa6bb03346e8de17a" +url = "https://github.com/goreleaser/goreleaser/releases/download/v2.15.2/goreleaser_Windows_x86_64.zip" +provenance = "github-attestations" + [[tools.node]] version = "22.20.0" backend = "core:node" +[tools.node."platforms.linux-arm64"] +checksum = "sha256:4181609e03dcb9880e7e5bf956061ecc0503c77a480c6631d868cb1f65a2c7dd" +url = "https://nodejs.org/dist/v22.20.0/node-v22.20.0-linux-arm64.tar.gz" + +[tools.node."platforms.linux-arm64-musl"] +url = "https://unofficial-builds.nodejs.org/download/release/v22.20.0/node-v22.20.0-linux-arm64-musl.tar.gz" + [tools.node."platforms.linux-x64"] checksum = "sha256:eeaccb0378b79406f2208e8b37a62479c70595e20be6b659125eb77dd1ab2a29" url = "https://nodejs.org/dist/v22.20.0/node-v22.20.0-linux-x64.tar.gz" +[tools.node."platforms.linux-x64-musl"] +checksum = "sha256:461aafed5eb607357479c6de5df978515d74daf7e0169e972e61c8390c035f1a" +url = "https://unofficial-builds.nodejs.org/download/release/v22.20.0/node-v22.20.0-linux-x64-musl.tar.gz" + [tools.node."platforms.macos-arm64"] checksum = "sha256:cc04a76a09f79290194c0646f48fec40354d88969bec467789a5d55dd097f949" url = "https://nodejs.org/dist/v22.20.0/node-v22.20.0-darwin-arm64.tar.gz" +[tools.node."platforms.macos-x64"] +checksum = "sha256:00df9c5df3e4ec6848c26b70fb47bf96492f342f4bed6b17f12d99b3a45eeecc" +url = "https://nodejs.org/dist/v22.20.0/node-v22.20.0-darwin-x64.tar.gz" + +[tools.node."platforms.windows-x64"] +checksum = "sha256:bb819d6eb8f5bfda294bbc83a7e4ec6539da67c4233d54b0d655b9248b15e29d" +url = "https://nodejs.org/dist/v22.20.0/node-v22.20.0-win-x64.zip" + [[tools.protoc]] version = "27.3" backend = "aqua:protocolbuffers/protobuf/protoc" +[tools.protoc."platforms.linux-arm64"] +checksum = "blake3:4f8a7d5d44611dddcd4deddf3fe781f8b7f978e34db06519c5fa79e78ebe7819" +url = "https://github.com/protocolbuffers/protobuf/releases/download/v27.3/protoc-27.3-linux-aarch_64.zip" + +[tools.protoc."platforms.linux-arm64-musl"] +url = "https://github.com/protocolbuffers/protobuf/releases/download/v27.3/protoc-27.3-linux-aarch_64.zip" + +[tools.protoc."platforms.linux-x64"] +url = "https://github.com/protocolbuffers/protobuf/releases/download/v27.3/protoc-27.3-linux-x86_64.zip" + +[tools.protoc."platforms.linux-x64-musl"] +url = "https://github.com/protocolbuffers/protobuf/releases/download/v27.3/protoc-27.3-linux-x86_64.zip" + +[tools.protoc."platforms.macos-arm64"] +url = "https://github.com/protocolbuffers/protobuf/releases/download/v27.3/protoc-27.3-osx-aarch_64.zip" + +[tools.protoc."platforms.macos-x64"] +url = "https://github.com/protocolbuffers/protobuf/releases/download/v27.3/protoc-27.3-osx-x86_64.zip" + +[tools.protoc."platforms.windows-x64"] +url = "https://github.com/protocolbuffers/protobuf/releases/download/v27.3/protoc-27.3-win64.zip" + [[tools.protoc-gen-go]] version = "1.34.2" backend = "aqua:protocolbuffers/protobuf-go/protoc-gen-go" +[tools.protoc-gen-go."platforms.linux-arm64"] +checksum = "blake3:bc36e84cf68d0eb52c599cbdabdda6b3c2c4d769332d04b0ae0b3be8c3c0fb91" +url = "https://github.com/protocolbuffers/protobuf-go/releases/download/v1.34.2/protoc-gen-go.v1.34.2.linux.arm64.tar.gz" + +[tools.protoc-gen-go."platforms.linux-arm64-musl"] +url = "https://github.com/protocolbuffers/protobuf-go/releases/download/v1.34.2/protoc-gen-go.v1.34.2.linux.arm64.tar.gz" + [tools.protoc-gen-go."platforms.linux-x64"] url = "https://github.com/protocolbuffers/protobuf-go/releases/download/v1.34.2/protoc-gen-go.v1.34.2.linux.amd64.tar.gz" +[tools.protoc-gen-go."platforms.linux-x64-musl"] +url = "https://github.com/protocolbuffers/protobuf-go/releases/download/v1.34.2/protoc-gen-go.v1.34.2.linux.amd64.tar.gz" + [tools.protoc-gen-go."platforms.macos-arm64"] url = "https://github.com/protocolbuffers/protobuf-go/releases/download/v1.34.2/protoc-gen-go.v1.34.2.darwin.arm64.tar.gz" +[tools.protoc-gen-go."platforms.macos-x64"] +url = "https://github.com/protocolbuffers/protobuf-go/releases/download/v1.34.2/protoc-gen-go.v1.34.2.darwin.amd64.tar.gz" + +[tools.protoc-gen-go."platforms.windows-x64"] +url = "https://github.com/protocolbuffers/protobuf-go/releases/download/v1.34.2/protoc-gen-go.v1.34.2.windows.amd64.zip" + [[tools.protoc-gen-go-grpc]] version = "1.5.1" backend = "aqua:grpc/grpc-go/protoc-gen-go-grpc" + +[tools.protoc-gen-go-grpc."platforms.linux-arm64"] +checksum = "blake3:a2348c3ca8bc2ebc9d7ec8f4b17db76f2924076b5beb51d1647a2bdbb5dbd987" +url = "https://github.com/grpc/grpc-go/releases/download/cmd/protoc-gen-go-grpc/v1.5.1/protoc-gen-go-grpc.v1.5.1.linux.arm64.tar.gz" + +[tools.protoc-gen-go-grpc."platforms.linux-arm64-musl"] +url = "https://github.com/grpc/grpc-go/releases/download/cmd/protoc-gen-go-grpc/v1.5.1/protoc-gen-go-grpc.v1.5.1.linux.arm64.tar.gz" + +[tools.protoc-gen-go-grpc."platforms.linux-x64"] +url = "https://github.com/grpc/grpc-go/releases/download/cmd/protoc-gen-go-grpc/v1.5.1/protoc-gen-go-grpc.v1.5.1.linux.amd64.tar.gz" + +[tools.protoc-gen-go-grpc."platforms.linux-x64-musl"] +url = "https://github.com/grpc/grpc-go/releases/download/cmd/protoc-gen-go-grpc/v1.5.1/protoc-gen-go-grpc.v1.5.1.linux.amd64.tar.gz" + +[tools.protoc-gen-go-grpc."platforms.macos-arm64"] +url = "https://github.com/grpc/grpc-go/releases/download/cmd/protoc-gen-go-grpc/v1.5.1/protoc-gen-go-grpc.v1.5.1.darwin.arm64.tar.gz" + +[tools.protoc-gen-go-grpc."platforms.macos-x64"] +url = "https://github.com/grpc/grpc-go/releases/download/cmd/protoc-gen-go-grpc/v1.5.1/protoc-gen-go-grpc.v1.5.1.darwin.amd64.tar.gz" + +[tools.protoc-gen-go-grpc."platforms.windows-x64"] +url = "https://github.com/grpc/grpc-go/releases/download/cmd/protoc-gen-go-grpc/v1.5.1/protoc-gen-go-grpc.v1.5.1.windows.amd64.tar.gz" diff --git a/pkg/client/image.go b/pkg/client/image.go index e9f8e6ab..98a8f962 100644 --- a/pkg/client/image.go +++ b/pkg/client/image.go @@ -25,6 +25,7 @@ import ( "github.com/docker/docker/pkg/jsonmessage" "github.com/docker/go-connections/nat" ocispec "github.com/opencontainers/image-spec/specs-go/v1" + cliprogress "github.com/psviderski/uncloud/internal/cli/progress" "github.com/psviderski/uncloud/internal/docker" "github.com/psviderski/uncloud/internal/machine/api/pb" "github.com/psviderski/uncloud/internal/machine/constants" @@ -404,6 +405,29 @@ func (cli *Client) pushImageToMachine( return nil } +func (cli *Client) RemoveImage(ctx context.Context, machineNameOrID, imageID string, force bool) error { + machine, err := cli.InspectMachine(ctx, machineNameOrID) + if err != nil { + return fmt.Errorf("inspect machine '%s': %w", machineNameOrID, err) + } + // Proxy Docker gRPC requests to the selected machine. + ctx = proxyToMachine(ctx, machine.Machine) + + pw := progress.ContextWriter(ctx) + eventID := cliprogress.ImageEventID(imageID, machine.Machine.Name) + pw.Event(progress.RemovingEvent(eventID)) + + if err = cli.Docker.RemoveImage(ctx, imageID, force); err != nil { + if errdefs.IsNotFound(err) { + return api.ErrNotFound + } + return err + } + pw.Event(progress.RemovedEvent(eventID)) + + return nil +} + // checkRemoteConnectivity verifies that remoteAddr is reachable via dialer within a timeout. func checkRemoteConnectivity(ctx context.Context, dialer netproxy.ContextDialer, remoteAddr string) error { ctx, cancel := context.WithTimeout(ctx, 10*time.Second) diff --git a/website/docs/9-cli-reference/uc_image.md b/website/docs/9-cli-reference/uc_image.md index 0c121ff0..8ca57a58 100644 --- a/website/docs/9-cli-reference/uc_image.md +++ b/website/docs/9-cli-reference/uc_image.md @@ -22,4 +22,5 @@ Manage images on machines in the cluster. * [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes. * [uc image ls](uc_image_ls.md) - List images on machines in the cluster. * [uc image push](uc_image_push.md) - Upload a local Docker image to the cluster. +* [uc image rm](uc_image_rm.md) - Remove one or more images. From c4851958c8368949c7928eadcce2afa0d8972f39 Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Wed, 6 May 2026 12:33:09 +0200 Subject: [PATCH 2/4] add rm.go Signed-off-by: Miek Gieben --- cmd/uncloud/image/rm.go | 148 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 cmd/uncloud/image/rm.go diff --git a/cmd/uncloud/image/rm.go b/cmd/uncloud/image/rm.go new file mode 100644 index 00000000..dc8747bf --- /dev/null +++ b/cmd/uncloud/image/rm.go @@ -0,0 +1,148 @@ +package image + +import ( + "context" + "errors" + "fmt" + "strings" + + "github.com/psviderski/uncloud/internal/cli" + "github.com/psviderski/uncloud/internal/cli/completion" + "github.com/psviderski/uncloud/internal/cli/tui" + "github.com/psviderski/uncloud/pkg/api" + "github.com/spf13/cobra" +) + +type removeOptions struct { + force bool + machines []string + yes bool +} + +func NewRemoveCommand() *cobra.Command { + opts := removeOptions{} + + cmd := &cobra.Command{ + Use: "rm IMAGE [IMAGE...]", + Aliases: []string{"remove", "delete"}, + Short: "Remove one or more images.", + Long: "Remove one or more images. You cannot remove an image that is in use by a container.", + Args: cobra.MinimumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + uncli := cmd.Context().Value("cli").(*cli.CLI) + return remove(cmd.Context(), uncli, args, opts) + }, + } + + cmd.Flags().BoolVarP(&opts.force, "force", "f", false, + "Force the removal of one or more images.") + cmd.Flags().StringSliceVarP(&opts.machines, "machine", "m", nil, + "Name or ID of the machine to remove one or more images from. "+ + "Can be specified multiple times or as a comma-separated list.\n"+ + "If not specified, the found images(s) will be removed from all machines.") + cmd.Flags().BoolVarP(&opts.yes, "yes", "y", false, + "Do not prompt for confirmation before removing the image(s).") + + completion.MachinesFlag(cmd) + + return cmd +} + +func remove(ctx context.Context, uncli *cli.CLI, names []string, opts removeOptions) error { + client, err := uncli.ConnectCluster(ctx) + if err != nil { + return fmt.Errorf("connect to cluster: %w", err) + } + defer client.Close() + + filter := api.ImageFilter{} + + if len(opts.machines) > 0 { + machines := cli.ExpandCommaSeparatedValues(opts.machines) + filter.Machines = machines + } + + images := []api.MachineImages{} + for _, name := range names { + filter.Name = name + clusterImages, err := client.ListImages(ctx, filter) + if err != nil { + return fmt.Errorf("list images: %w", err) + } + for i := range clusterImages { + if len(clusterImages[i].Images) > 0 { + images = append(images, clusterImages[i]) + } + } + } + + if len(images) == 0 { + return fmt.Errorf("no images found matching the specified names") + } + + allMachines, err := client.ListMachines(ctx, nil) + if err != nil { + return fmt.Errorf("list machines: %w", err) + } + + // Confirm removal if not using --yes flag. + if !opts.yes { + fmt.Println("The following images will be removed:") + for _, machineImage := range images { + // Get machine name for better readability. + machineName := machineImage.Metadata.Machine + if m := allMachines.FindByNameOrID(machineName); m != nil { + machineName = m.Machine.Name + } + + for _, img := range machineImage.Images { + id := strings.TrimPrefix(img.ID, "sha256:")[:12] + name := "" + if len(img.RepoTags) > 0 && img.RepoTags[0] != ":" { + name = img.RepoTags[0] + } + + fmt.Printf(" • '%s' ('%s') on machine '%s'\n", name, id, machineName) + } + } + + fmt.Println() + confirmed, err := tui.Confirm("") + if err != nil { + return fmt.Errorf("confirm removal: %w", err) + } + if !confirmed { + // tODO: cancelled + fmt.Println("Cancelled. No images were removed.") + return nil + } + } + + var removeErr error + for _, machineImage := range images { + machineName := machineImage.Metadata.Machine + if m := allMachines.FindByNameOrID(machineName); m != nil { + machineName = m.Machine.Name + } + + for _, img := range machineImage.Images { + id := strings.TrimPrefix(img.ID, "sha256:")[:12] + name := "" + if len(img.RepoTags) > 0 && img.RepoTags[0] != ":" { + name = img.RepoTags[0] + } + + if err := client.RemoveImage(ctx, machineImage.Metadata.Machine, img.ID, opts.force); err != nil { + if !errors.Is(err, api.ErrNotFound) { + removeErr = errors.Join(removeErr, fmt.Errorf("failed to remove image '%s' ('%s') on machine '%s': %w", + name, id, machineName, err)) + } + continue + } + + fmt.Printf("Image '%s' ('%s') removed from machine '%s'.\n", name, id, machineName) + } + } + + return removeErr +} From 1bbe8c05ed4de05f4c4261d2cbdc6dd0993c499b Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Wed, 6 May 2026 12:34:14 +0200 Subject: [PATCH 3/4] Use cli.Cancelled Signed-off-by: Miek Gieben --- cmd/uncloud/image/rm.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/uncloud/image/rm.go b/cmd/uncloud/image/rm.go index dc8747bf..5e227032 100644 --- a/cmd/uncloud/image/rm.go +++ b/cmd/uncloud/image/rm.go @@ -112,9 +112,7 @@ func remove(ctx context.Context, uncli *cli.CLI, names []string, opts removeOpti return fmt.Errorf("confirm removal: %w", err) } if !confirmed { - // tODO: cancelled - fmt.Println("Cancelled. No images were removed.") - return nil + return cli.Cancelled("Cancelled. No images were removed.") } } From d3d1bdb14a5ef6bb7425c15fd2119240c679fcfb Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Wed, 6 May 2026 12:44:08 +0200 Subject: [PATCH 4/4] ... and factor out Signed-off-by: Miek Gieben --- cmd/uncloud/image/ls.go | 19 +++++++++++++------ cmd/uncloud/image/rm.go | 15 ++++----------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/cmd/uncloud/image/ls.go b/cmd/uncloud/image/ls.go index 324a7e08..b4135eb7 100644 --- a/cmd/uncloud/image/ls.go +++ b/cmd/uncloud/image/ls.go @@ -129,12 +129,8 @@ func list(ctx context.Context, uncli *cli.CLI, opts listOptions) error { // Process each image for this machine. for _, img := range machineImages.Images { // Show the first 12 chars without 'sha256:' as the image ID like Docker does. - id := strings.TrimPrefix(img.ID, "sha256:")[:12] - - name := "" - if len(img.RepoTags) > 0 && img.RepoTags[0] != ":" { - name = img.RepoTags[0] - } + id := normalizeID(img.ID) + name := normalizeName(img) imgPlatforms, _ := imagePlatforms(img) formattedPlatforms := formatPlatforms(imgPlatforms) @@ -303,3 +299,14 @@ func formatImageTable(rows []imageRow) string { return t.String() } + +func normalizeID(id string) string { + return strings.TrimPrefix(id, "sha256:")[:12] +} + +func normalizeName(img image.Summary) string { + if len(img.RepoTags) > 0 && img.RepoTags[0] != ":" { + return img.RepoTags[0] + } + return "" +} diff --git a/cmd/uncloud/image/rm.go b/cmd/uncloud/image/rm.go index 5e227032..fe2670ba 100644 --- a/cmd/uncloud/image/rm.go +++ b/cmd/uncloud/image/rm.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "strings" "github.com/psviderski/uncloud/internal/cli" "github.com/psviderski/uncloud/internal/cli/completion" @@ -96,11 +95,8 @@ func remove(ctx context.Context, uncli *cli.CLI, names []string, opts removeOpti } for _, img := range machineImage.Images { - id := strings.TrimPrefix(img.ID, "sha256:")[:12] - name := "" - if len(img.RepoTags) > 0 && img.RepoTags[0] != ":" { - name = img.RepoTags[0] - } + id := normalizeID(img.ID) + name := normalizeName(img) fmt.Printf(" • '%s' ('%s') on machine '%s'\n", name, id, machineName) } @@ -124,11 +120,8 @@ func remove(ctx context.Context, uncli *cli.CLI, names []string, opts removeOpti } for _, img := range machineImage.Images { - id := strings.TrimPrefix(img.ID, "sha256:")[:12] - name := "" - if len(img.RepoTags) > 0 && img.RepoTags[0] != ":" { - name = img.RepoTags[0] - } + id := normalizeID(img.ID) + name := normalizeName(img) if err := client.RemoveImage(ctx, machineImage.Metadata.Machine, img.ID, opts.force); err != nil { if !errors.Is(err, api.ErrNotFound) {