diff --git a/cmd/uncloud/machine/list.go b/cmd/uncloud/machine/list.go new file mode 100644 index 00000000..2b2c5bf1 --- /dev/null +++ b/cmd/uncloud/machine/list.go @@ -0,0 +1,24 @@ +package machine + +import ( + "github.com/spf13/cobra" + "uncloud/internal/cli" +) + +func NewListCommand() *cobra.Command { + opts := addOptions{} + cmd := &cobra.Command{ + Use: "list", + Aliases: []string{"ls"}, + Short: "List machines in a cluster", + RunE: func(cmd *cobra.Command, args []string) error { + uncli := cmd.Context().Value("cli").(*cli.CLI) + return uncli.ListMachines(cmd.Context(), opts.cluster) + }, + } + cmd.Flags().StringVarP( + &opts.cluster, "cluster", "c", "", + "Name of the cluster (default is the current cluster)", + ) + return cmd +} diff --git a/cmd/uncloud/machine/root.go b/cmd/uncloud/machine/root.go index 0bf7e4a0..aaff2c07 100644 --- a/cmd/uncloud/machine/root.go +++ b/cmd/uncloud/machine/root.go @@ -12,6 +12,7 @@ func NewRootCommand() *cobra.Command { cmd.AddCommand( NewAddCommand(), NewInitCommand(), + NewListCommand(), NewTokenCommand(), ) return cmd diff --git a/internal/cli/cli.go b/internal/cli/cli.go index 519aa4eb..d177e5ee 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -6,6 +6,9 @@ import ( "fmt" "google.golang.org/protobuf/types/known/emptypb" "net/netip" + "os" + "strings" + "text/tabwriter" "uncloud/internal/cli/client" "uncloud/internal/cli/client/connector" "uncloud/internal/cli/config" @@ -250,15 +253,18 @@ func (cli *CLI) AddMachine(ctx context.Context, remoteMachine RemoteMachine, clu if err != nil { return fmt.Errorf("add machine to cluster: %w", err) } - fmt.Println("Machine added to cluster", addResp.Machine) + //joinReq := &pb.JoinClusterRequest{ + // Machine: addResp.Machine, + //} + // TODO: // --1. Establish a client connection to the remote machine. // --2. Check if the machine is already provisioned and ask the user to reset it first. // --3. Download and install the latest uncloudd binary by running the install shell script from GitHub. // --4. Request token from the remote machine. - // 5. Add the machine to the cluster using its token and receive the added machine info. + // --5. Add the machine to the cluster using its token and receive the added machine info. // 6. Request the machine to join the cluster using the configuration token. // 7. Save the machine's SSH connection details in the cluster config. @@ -275,3 +281,42 @@ func (cli *CLI) AddMachine(ctx context.Context, remoteMachine RemoteMachine, clu return nil } + +func (cli *CLI) ListMachines(ctx context.Context, clusterName string) error { + c, err := cli.ConnectCluster(ctx, clusterName) + if err != nil { + return fmt.Errorf("connect to cluster: %w", err) + } + defer func() { + _ = c.Close() + }() + + listResp, err := c.ListMachines(ctx, &emptypb.Empty{}) + if err != nil { + return fmt.Errorf("list machines: %w", err) + } + + // Print the list of machines in a table format. + tw := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0) + // Print header. + if _, err = fmt.Fprintln(tw, "NAME\tSUBNET\tPUBLIC KEY\tENDPOINTS"); err != nil { + return fmt.Errorf("write header: %w", err) + } + // Print rows. + fmt.Println("listResp", len(listResp.Machines)) + for _, m := range listResp.Machines { + subnet, _ := m.Network.Subnet.ToPrefix() + endpoints := make([]string, len(m.Network.Endpoints)) + for i, ep := range m.Network.Endpoints { + addrPort, _ := ep.ToAddrPort() + endpoints[i] = addrPort.String() + } + publicKey := secret.Secret(m.Network.PublicKey) + if _, err = fmt.Fprintf( + tw, "%s\t%s\t%s\t%s\n", m.Name, subnet, publicKey, strings.Join(endpoints, ", "), + ); err != nil { + return fmt.Errorf("write row: %w", err) + } + } + return tw.Flush() +} diff --git a/internal/machine/api/pb/cluster.pb.go b/internal/machine/api/pb/cluster.pb.go index bc05b34a..6371b988 100644 --- a/internal/machine/api/pb/cluster.pb.go +++ b/internal/machine/api/pb/cluster.pb.go @@ -9,6 +9,7 @@ package pb import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" reflect "reflect" sync "sync" ) @@ -122,6 +123,53 @@ func (x *AddMachineResponse) GetMachine() *MachineInfo { return nil } +type ListMachinesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Machines []*MachineInfo `protobuf:"bytes,1,rep,name=machines,proto3" json:"machines,omitempty"` +} + +func (x *ListMachinesResponse) Reset() { + *x = ListMachinesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListMachinesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListMachinesResponse) ProtoMessage() {} + +func (x *ListMachinesResponse) ProtoReflect() protoreflect.Message { + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[2] + 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 ListMachinesResponse.ProtoReflect.Descriptor instead. +func (*ListMachinesResponse) Descriptor() ([]byte, []int) { + return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{2} +} + +func (x *ListMachinesResponse) GetMachines() []*MachineInfo { + if x != nil { + return x.Machines + } + return nil +} + type ListMachineEndpointsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -133,7 +181,7 @@ type ListMachineEndpointsRequest struct { func (x *ListMachineEndpointsRequest) Reset() { *x = ListMachineEndpointsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[2] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -146,7 +194,7 @@ func (x *ListMachineEndpointsRequest) String() string { func (*ListMachineEndpointsRequest) ProtoMessage() {} func (x *ListMachineEndpointsRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[2] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -159,7 +207,7 @@ func (x *ListMachineEndpointsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMachineEndpointsRequest.ProtoReflect.Descriptor instead. func (*ListMachineEndpointsRequest) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{2} + return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{3} } func (x *ListMachineEndpointsRequest) GetId() string { @@ -180,7 +228,7 @@ type ListMachineEndpointsResponse struct { func (x *ListMachineEndpointsResponse) Reset() { *x = ListMachineEndpointsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[3] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -193,7 +241,7 @@ func (x *ListMachineEndpointsResponse) String() string { func (*ListMachineEndpointsResponse) ProtoMessage() {} func (x *ListMachineEndpointsResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[3] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -206,7 +254,7 @@ func (x *ListMachineEndpointsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMachineEndpointsResponse.ProtoReflect.Descriptor instead. func (*ListMachineEndpointsResponse) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{3} + return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{4} } func (x *ListMachineEndpointsResponse) GetEndpoints() *MachineEndpoints { @@ -229,7 +277,7 @@ type MachineInfo struct { func (x *MachineInfo) Reset() { *x = MachineInfo{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[4] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -242,7 +290,7 @@ func (x *MachineInfo) String() string { func (*MachineInfo) ProtoMessage() {} func (x *MachineInfo) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[4] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -255,7 +303,7 @@ func (x *MachineInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use MachineInfo.ProtoReflect.Descriptor instead. func (*MachineInfo) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{4} + return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{5} } func (x *MachineInfo) GetId() string { @@ -293,7 +341,7 @@ type NetworkConfig struct { func (x *NetworkConfig) Reset() { *x = NetworkConfig{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[5] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -306,7 +354,7 @@ func (x *NetworkConfig) String() string { func (*NetworkConfig) ProtoMessage() {} func (x *NetworkConfig) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[5] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -319,7 +367,7 @@ func (x *NetworkConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use NetworkConfig.ProtoReflect.Descriptor instead. func (*NetworkConfig) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{5} + return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{6} } func (x *NetworkConfig) GetSubnet() *IPPrefix { @@ -362,7 +410,7 @@ type MachineEndpoints struct { func (x *MachineEndpoints) Reset() { *x = MachineEndpoints{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[6] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -375,7 +423,7 @@ func (x *MachineEndpoints) String() string { func (*MachineEndpoints) ProtoMessage() {} func (x *MachineEndpoints) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[6] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -388,7 +436,7 @@ func (x *MachineEndpoints) ProtoReflect() protoreflect.Message { // Deprecated: Use MachineEndpoints.ProtoReflect.Descriptor instead. func (*MachineEndpoints) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{6} + return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{7} } func (x *MachineEndpoints) GetId() string { @@ -416,7 +464,7 @@ type User struct { func (x *User) Reset() { *x = User{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[7] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -429,7 +477,7 @@ func (x *User) String() string { func (*User) ProtoMessage() {} func (x *User) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[7] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -442,7 +490,7 @@ func (x *User) ProtoReflect() protoreflect.Message { // Deprecated: Use User.ProtoReflect.Descriptor instead. func (*User) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{7} + return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{8} } func (x *User) GetNetwork() *NetworkConfig { @@ -468,7 +516,7 @@ type State struct { func (x *State) Reset() { *x = State{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[8] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -481,7 +529,7 @@ func (x *State) String() string { func (*State) ProtoMessage() {} func (x *State) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[8] + mi := &file_internal_machine_api_pb_cluster_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -494,7 +542,7 @@ func (x *State) ProtoReflect() protoreflect.Message { // Deprecated: Use State.ProtoReflect.Descriptor instead. func (*State) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{8} + return file_internal_machine_api_pb_cluster_proto_rawDescGZIP(), []int{9} } func (x *State) GetNetwork() *IPPrefix { @@ -530,90 +578,100 @@ var File_internal_machine_api_pb_cluster_proto protoreflect.FileDescriptor var file_internal_machine_api_pb_cluster_proto_rawDesc = []byte{ 0x0a, 0x25, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x62, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x61, 0x70, 0x69, 0x1a, 0x24, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x61, - 0x70, 0x69, 0x2f, 0x70, 0x62, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0x55, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x6e, - 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x40, 0x0a, 0x12, 0x41, 0x64, 0x64, - 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2a, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x2d, 0x0a, 0x1b, 0x4c, - 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x53, 0x0a, 0x1c, 0x4c, 0x69, - 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x65, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x73, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, - 0x5f, 0x0a, 0x0b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x22, 0xad, 0x01, 0x0a, 0x0d, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x25, 0x0a, 0x06, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x50, 0x50, 0x72, 0x65, 0x66, 0x69, - 0x78, 0x52, 0x06, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x12, 0x2c, 0x0a, 0x0d, 0x6d, 0x61, 0x6e, - 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x07, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x50, 0x52, 0x0c, 0x6d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x29, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x70, 0x69, + 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x61, 0x70, 0x69, 0x1a, 0x1b, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, + 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x70, 0x62, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0x55, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x6e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x40, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x4d, 0x61, 0x63, + 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x07, + 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x44, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, + 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x2c, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x2d, + 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x53, 0x0a, + 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, + 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x73, 0x22, 0x5f, 0x0a, 0x0b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x22, 0xad, 0x01, 0x0a, 0x0d, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x06, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x50, 0x50, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x52, 0x06, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x12, 0x2c, 0x0a, 0x0d, + 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x50, 0x52, 0x0c, 0x6d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x29, 0x0a, 0x09, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x49, 0x50, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, + 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x4b, 0x65, 0x79, 0x22, 0x4d, 0x0a, 0x10, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x29, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x50, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, - 0x22, 0x4d, 0x0a, 0x10, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x29, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x50, - 0x50, 0x6f, 0x72, 0x74, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, - 0x34, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4e, - 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x6e, 0x65, - 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0xe4, 0x02, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, - 0x27, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x50, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, - 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x68, - 0x69, 0x6e, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x37, - 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x65, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x1a, 0x4d, 0x0a, 0x0d, 0x4d, 0x61, 0x63, 0x68, - 0x69, 0x6e, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x53, 0x0a, 0x0e, 0x45, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0xa5, 0x01, 0x0a, - 0x07, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x4d, - 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x64, 0x64, - 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x64, 0x64, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4d, - 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, - 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, - 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, - 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 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, + 0x74, 0x73, 0x22, 0x34, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x07, 0x6e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0xe4, 0x02, 0x0a, 0x05, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x27, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x50, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x52, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x34, 0x0a, 0x08, 0x6d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, + 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, + 0x73, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x05, 0x75, 0x73, + 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x1a, 0x4d, 0x0a, 0x0d, 0x4d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x53, 0x0a, 0x0e, 0x45, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2b, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, + 0xe8, 0x01, 0x0a, 0x07, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x0a, 0x41, + 0x64, 0x64, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x41, 0x64, 0x64, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x64, 0x64, 0x4d, 0x61, 0x63, 0x68, 0x69, + 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x4c, 0x69, + 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, + 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, + 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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 ( @@ -628,48 +686,53 @@ func file_internal_machine_api_pb_cluster_proto_rawDescGZIP() []byte { return file_internal_machine_api_pb_cluster_proto_rawDescData } -var file_internal_machine_api_pb_cluster_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_internal_machine_api_pb_cluster_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_internal_machine_api_pb_cluster_proto_goTypes = []any{ (*AddMachineRequest)(nil), // 0: api.AddMachineRequest (*AddMachineResponse)(nil), // 1: api.AddMachineResponse - (*ListMachineEndpointsRequest)(nil), // 2: api.ListMachineEndpointsRequest - (*ListMachineEndpointsResponse)(nil), // 3: api.ListMachineEndpointsResponse - (*MachineInfo)(nil), // 4: api.MachineInfo - (*NetworkConfig)(nil), // 5: api.NetworkConfig - (*MachineEndpoints)(nil), // 6: api.MachineEndpoints - (*User)(nil), // 7: api.User - (*State)(nil), // 8: api.State - nil, // 9: api.State.MachinesEntry - nil, // 10: api.State.EndpointsEntry - (*IPPrefix)(nil), // 11: api.IPPrefix - (*IP)(nil), // 12: api.IP - (*IPPort)(nil), // 13: api.IPPort + (*ListMachinesResponse)(nil), // 2: api.ListMachinesResponse + (*ListMachineEndpointsRequest)(nil), // 3: api.ListMachineEndpointsRequest + (*ListMachineEndpointsResponse)(nil), // 4: api.ListMachineEndpointsResponse + (*MachineInfo)(nil), // 5: api.MachineInfo + (*NetworkConfig)(nil), // 6: api.NetworkConfig + (*MachineEndpoints)(nil), // 7: api.MachineEndpoints + (*User)(nil), // 8: api.User + (*State)(nil), // 9: api.State + nil, // 10: api.State.MachinesEntry + nil, // 11: api.State.EndpointsEntry + (*IPPrefix)(nil), // 12: api.IPPrefix + (*IP)(nil), // 13: api.IP + (*IPPort)(nil), // 14: api.IPPort + (*emptypb.Empty)(nil), // 15: google.protobuf.Empty } var file_internal_machine_api_pb_cluster_proto_depIdxs = []int32{ - 5, // 0: api.AddMachineRequest.network:type_name -> api.NetworkConfig - 4, // 1: api.AddMachineResponse.machine:type_name -> api.MachineInfo - 6, // 2: api.ListMachineEndpointsResponse.endpoints:type_name -> api.MachineEndpoints - 5, // 3: api.MachineInfo.network:type_name -> api.NetworkConfig - 11, // 4: api.NetworkConfig.subnet:type_name -> api.IPPrefix - 12, // 5: api.NetworkConfig.management_ip:type_name -> api.IP - 13, // 6: api.NetworkConfig.endpoints:type_name -> api.IPPort - 13, // 7: api.MachineEndpoints.endpoints:type_name -> api.IPPort - 5, // 8: api.User.network:type_name -> api.NetworkConfig - 11, // 9: api.State.Network:type_name -> api.IPPrefix - 9, // 10: api.State.machines:type_name -> api.State.MachinesEntry - 10, // 11: api.State.endpoints:type_name -> api.State.EndpointsEntry - 7, // 12: api.State.users:type_name -> api.User - 4, // 13: api.State.MachinesEntry.value:type_name -> api.MachineInfo - 6, // 14: api.State.EndpointsEntry.value:type_name -> api.MachineEndpoints - 0, // 15: api.Cluster.AddMachine:input_type -> api.AddMachineRequest - 2, // 16: api.Cluster.ListMachineEndpoints:input_type -> api.ListMachineEndpointsRequest - 1, // 17: api.Cluster.AddMachine:output_type -> api.AddMachineResponse - 3, // 18: api.Cluster.ListMachineEndpoints:output_type -> api.ListMachineEndpointsResponse - 17, // [17:19] is the sub-list for method output_type - 15, // [15:17] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name + 6, // 0: api.AddMachineRequest.network:type_name -> api.NetworkConfig + 5, // 1: api.AddMachineResponse.machine:type_name -> api.MachineInfo + 5, // 2: api.ListMachinesResponse.machines:type_name -> api.MachineInfo + 7, // 3: api.ListMachineEndpointsResponse.endpoints:type_name -> api.MachineEndpoints + 6, // 4: api.MachineInfo.network:type_name -> api.NetworkConfig + 12, // 5: api.NetworkConfig.subnet:type_name -> api.IPPrefix + 13, // 6: api.NetworkConfig.management_ip:type_name -> api.IP + 14, // 7: api.NetworkConfig.endpoints:type_name -> api.IPPort + 14, // 8: api.MachineEndpoints.endpoints:type_name -> api.IPPort + 6, // 9: api.User.network:type_name -> api.NetworkConfig + 12, // 10: api.State.Network:type_name -> api.IPPrefix + 10, // 11: api.State.machines:type_name -> api.State.MachinesEntry + 11, // 12: api.State.endpoints:type_name -> api.State.EndpointsEntry + 8, // 13: api.State.users:type_name -> api.User + 5, // 14: api.State.MachinesEntry.value:type_name -> api.MachineInfo + 7, // 15: api.State.EndpointsEntry.value:type_name -> api.MachineEndpoints + 0, // 16: api.Cluster.AddMachine:input_type -> api.AddMachineRequest + 15, // 17: api.Cluster.ListMachines:input_type -> google.protobuf.Empty + 3, // 18: api.Cluster.ListMachineEndpoints:input_type -> api.ListMachineEndpointsRequest + 1, // 19: api.Cluster.AddMachine:output_type -> api.AddMachineResponse + 2, // 20: api.Cluster.ListMachines:output_type -> api.ListMachinesResponse + 4, // 21: api.Cluster.ListMachineEndpoints:output_type -> api.ListMachineEndpointsResponse + 19, // [19:22] is the sub-list for method output_type + 16, // [16:19] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name } func init() { file_internal_machine_api_pb_cluster_proto_init() } @@ -704,7 +767,7 @@ func file_internal_machine_api_pb_cluster_proto_init() { } } file_internal_machine_api_pb_cluster_proto_msgTypes[2].Exporter = func(v any, i int) any { - switch v := v.(*ListMachineEndpointsRequest); i { + switch v := v.(*ListMachinesResponse); i { case 0: return &v.state case 1: @@ -716,7 +779,7 @@ func file_internal_machine_api_pb_cluster_proto_init() { } } file_internal_machine_api_pb_cluster_proto_msgTypes[3].Exporter = func(v any, i int) any { - switch v := v.(*ListMachineEndpointsResponse); i { + switch v := v.(*ListMachineEndpointsRequest); i { case 0: return &v.state case 1: @@ -728,7 +791,7 @@ func file_internal_machine_api_pb_cluster_proto_init() { } } file_internal_machine_api_pb_cluster_proto_msgTypes[4].Exporter = func(v any, i int) any { - switch v := v.(*MachineInfo); i { + switch v := v.(*ListMachineEndpointsResponse); i { case 0: return &v.state case 1: @@ -740,7 +803,7 @@ func file_internal_machine_api_pb_cluster_proto_init() { } } file_internal_machine_api_pb_cluster_proto_msgTypes[5].Exporter = func(v any, i int) any { - switch v := v.(*NetworkConfig); i { + switch v := v.(*MachineInfo); i { case 0: return &v.state case 1: @@ -752,7 +815,7 @@ func file_internal_machine_api_pb_cluster_proto_init() { } } file_internal_machine_api_pb_cluster_proto_msgTypes[6].Exporter = func(v any, i int) any { - switch v := v.(*MachineEndpoints); i { + switch v := v.(*NetworkConfig); i { case 0: return &v.state case 1: @@ -764,7 +827,7 @@ func file_internal_machine_api_pb_cluster_proto_init() { } } file_internal_machine_api_pb_cluster_proto_msgTypes[7].Exporter = func(v any, i int) any { - switch v := v.(*User); i { + switch v := v.(*MachineEndpoints); i { case 0: return &v.state case 1: @@ -776,6 +839,18 @@ func file_internal_machine_api_pb_cluster_proto_init() { } } file_internal_machine_api_pb_cluster_proto_msgTypes[8].Exporter = func(v any, i int) any { + switch v := v.(*User); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_machine_api_pb_cluster_proto_msgTypes[9].Exporter = func(v any, i int) any { switch v := v.(*State); i { case 0: return &v.state @@ -794,7 +869,7 @@ func file_internal_machine_api_pb_cluster_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_internal_machine_api_pb_cluster_proto_rawDesc, NumEnums: 0, - NumMessages: 11, + NumMessages: 12, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/machine/api/pb/cluster.proto b/internal/machine/api/pb/cluster.proto index 3abb7e99..7b92efcc 100644 --- a/internal/machine/api/pb/cluster.proto +++ b/internal/machine/api/pb/cluster.proto @@ -4,10 +4,12 @@ package api; option go_package = "github.com/psviderski/uncloud/internal/machine/api/pb"; +import "google/protobuf/empty.proto"; import "internal/machine/api/pb/common.proto"; service Cluster { rpc AddMachine(AddMachineRequest) returns (AddMachineResponse); + rpc ListMachines(google.protobuf.Empty) returns (ListMachinesResponse); rpc ListMachineEndpoints(ListMachineEndpointsRequest) returns (ListMachineEndpointsResponse); } @@ -20,6 +22,10 @@ message AddMachineResponse { MachineInfo machine = 1; } +message ListMachinesResponse { + repeated MachineInfo machines = 1; +} + message ListMachineEndpointsRequest { string id = 1; } diff --git a/internal/machine/api/pb/cluster_grpc.pb.go b/internal/machine/api/pb/cluster_grpc.pb.go index 862576b5..54891c2a 100644 --- a/internal/machine/api/pb/cluster_grpc.pb.go +++ b/internal/machine/api/pb/cluster_grpc.pb.go @@ -11,6 +11,7 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + emptypb "google.golang.org/protobuf/types/known/emptypb" ) // This is a compile-time assertion to ensure that this generated file @@ -20,6 +21,7 @@ const _ = grpc.SupportPackageIsVersion9 const ( Cluster_AddMachine_FullMethodName = "/api.Cluster/AddMachine" + Cluster_ListMachines_FullMethodName = "/api.Cluster/ListMachines" Cluster_ListMachineEndpoints_FullMethodName = "/api.Cluster/ListMachineEndpoints" ) @@ -28,6 +30,7 @@ const ( // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type ClusterClient interface { AddMachine(ctx context.Context, in *AddMachineRequest, opts ...grpc.CallOption) (*AddMachineResponse, error) + ListMachines(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ListMachinesResponse, error) ListMachineEndpoints(ctx context.Context, in *ListMachineEndpointsRequest, opts ...grpc.CallOption) (*ListMachineEndpointsResponse, error) } @@ -49,6 +52,16 @@ func (c *clusterClient) AddMachine(ctx context.Context, in *AddMachineRequest, o return out, nil } +func (c *clusterClient) ListMachines(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ListMachinesResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListMachinesResponse) + err := c.cc.Invoke(ctx, Cluster_ListMachines_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *clusterClient) ListMachineEndpoints(ctx context.Context, in *ListMachineEndpointsRequest, opts ...grpc.CallOption) (*ListMachineEndpointsResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListMachineEndpointsResponse) @@ -64,6 +77,7 @@ func (c *clusterClient) ListMachineEndpoints(ctx context.Context, in *ListMachin // for forward compatibility. type ClusterServer interface { AddMachine(context.Context, *AddMachineRequest) (*AddMachineResponse, error) + ListMachines(context.Context, *emptypb.Empty) (*ListMachinesResponse, error) ListMachineEndpoints(context.Context, *ListMachineEndpointsRequest) (*ListMachineEndpointsResponse, error) mustEmbedUnimplementedClusterServer() } @@ -78,6 +92,9 @@ type UnimplementedClusterServer struct{} func (UnimplementedClusterServer) AddMachine(context.Context, *AddMachineRequest) (*AddMachineResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AddMachine not implemented") } +func (UnimplementedClusterServer) ListMachines(context.Context, *emptypb.Empty) (*ListMachinesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListMachines not implemented") +} func (UnimplementedClusterServer) ListMachineEndpoints(context.Context, *ListMachineEndpointsRequest) (*ListMachineEndpointsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListMachineEndpoints not implemented") } @@ -120,6 +137,24 @@ func _Cluster_AddMachine_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _Cluster_ListMachines_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ClusterServer).ListMachines(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Cluster_ListMachines_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ClusterServer).ListMachines(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + func _Cluster_ListMachineEndpoints_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListMachineEndpointsRequest) if err := dec(in); err != nil { @@ -149,6 +184,10 @@ var Cluster_ServiceDesc = grpc.ServiceDesc{ MethodName: "AddMachine", Handler: _Cluster_AddMachine_Handler, }, + { + MethodName: "ListMachines", + Handler: _Cluster_ListMachines_Handler, + }, { MethodName: "ListMachineEndpoints", Handler: _Cluster_ListMachineEndpoints_Handler, diff --git a/internal/machine/api/pb/machine.pb.go b/internal/machine/api/pb/machine.pb.go index 0549bb6f..3bea2ec2 100644 --- a/internal/machine/api/pb/machine.pb.go +++ b/internal/machine/api/pb/machine.pb.go @@ -131,6 +131,61 @@ func (x *InitClusterResponse) GetMachine() *MachineInfo { return nil } +type JoinClusterRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Machine *MachineInfo `protobuf:"bytes,1,opt,name=machine,proto3" json:"machine,omitempty"` + OtherMachines []*MachineInfo `protobuf:"bytes,3,rep,name=other_machines,json=otherMachines,proto3" json:"other_machines,omitempty"` +} + +func (x *JoinClusterRequest) Reset() { + *x = JoinClusterRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_machine_api_pb_machine_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *JoinClusterRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JoinClusterRequest) ProtoMessage() {} + +func (x *JoinClusterRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_machine_api_pb_machine_proto_msgTypes[2] + 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 JoinClusterRequest.ProtoReflect.Descriptor instead. +func (*JoinClusterRequest) Descriptor() ([]byte, []int) { + return file_internal_machine_api_pb_machine_proto_rawDescGZIP(), []int{2} +} + +func (x *JoinClusterRequest) GetMachine() *MachineInfo { + if x != nil { + return x.Machine + } + return nil +} + +func (x *JoinClusterRequest) GetOtherMachines() []*MachineInfo { + if x != nil { + return x.OtherMachines + } + return nil +} + type TokenResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -142,7 +197,7 @@ type TokenResponse struct { func (x *TokenResponse) Reset() { *x = TokenResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_machine_proto_msgTypes[2] + mi := &file_internal_machine_api_pb_machine_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -155,7 +210,7 @@ func (x *TokenResponse) String() string { func (*TokenResponse) ProtoMessage() {} func (x *TokenResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_machine_proto_msgTypes[2] + mi := &file_internal_machine_api_pb_machine_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -168,7 +223,7 @@ func (x *TokenResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use TokenResponse.ProtoReflect.Descriptor instead. func (*TokenResponse) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_machine_proto_rawDescGZIP(), []int{2} + return file_internal_machine_api_pb_machine_proto_rawDescGZIP(), []int{3} } func (x *TokenResponse) GetToken() string { @@ -202,22 +257,33 @@ var file_internal_machine_api_pb_machine_proto_rawDesc = []byte{ 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x25, 0x0a, 0x0d, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, - 0x32, 0x80, 0x01, 0x0a, 0x07, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x40, 0x0a, 0x0b, - 0x49, 0x6e, 0x69, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x17, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, - 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 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, + 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x79, 0x0a, 0x12, 0x4a, 0x6f, 0x69, + 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x2a, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x37, 0x0a, 0x0e, 0x6f, + 0x74, 0x68, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x68, + 0x69, 0x6e, 0x65, 0x73, 0x22, 0x25, 0x0a, 0x0d, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0xc0, 0x01, 0x0a, 0x07, + 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x49, 0x6e, 0x69, 0x74, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x69, + 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x4a, 0x6f, 0x69, + 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4a, + 0x6f, 0x69, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 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, 0x33, 0x0a, 0x05, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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 ( @@ -232,29 +298,34 @@ func file_internal_machine_api_pb_machine_proto_rawDescGZIP() []byte { return file_internal_machine_api_pb_machine_proto_rawDescData } -var file_internal_machine_api_pb_machine_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_internal_machine_api_pb_machine_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_internal_machine_api_pb_machine_proto_goTypes = []any{ (*InitClusterRequest)(nil), // 0: api.InitClusterRequest (*InitClusterResponse)(nil), // 1: api.InitClusterResponse - (*TokenResponse)(nil), // 2: api.TokenResponse - (*IPPrefix)(nil), // 3: api.IPPrefix - (*User)(nil), // 4: api.User - (*MachineInfo)(nil), // 5: api.MachineInfo - (*emptypb.Empty)(nil), // 6: google.protobuf.Empty + (*JoinClusterRequest)(nil), // 2: api.JoinClusterRequest + (*TokenResponse)(nil), // 3: api.TokenResponse + (*IPPrefix)(nil), // 4: api.IPPrefix + (*User)(nil), // 5: api.User + (*MachineInfo)(nil), // 6: api.MachineInfo + (*emptypb.Empty)(nil), // 7: google.protobuf.Empty } var file_internal_machine_api_pb_machine_proto_depIdxs = []int32{ - 3, // 0: api.InitClusterRequest.network:type_name -> api.IPPrefix - 4, // 1: api.InitClusterRequest.user:type_name -> api.User - 5, // 2: api.InitClusterResponse.machine:type_name -> api.MachineInfo - 0, // 3: api.Machine.InitCluster:input_type -> api.InitClusterRequest - 6, // 4: api.Machine.Token:input_type -> google.protobuf.Empty - 1, // 5: api.Machine.InitCluster:output_type -> api.InitClusterResponse - 2, // 6: api.Machine.Token:output_type -> api.TokenResponse - 5, // [5:7] is the sub-list for method output_type - 3, // [3:5] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 4, // 0: api.InitClusterRequest.network:type_name -> api.IPPrefix + 5, // 1: api.InitClusterRequest.user:type_name -> api.User + 6, // 2: api.InitClusterResponse.machine:type_name -> api.MachineInfo + 6, // 3: api.JoinClusterRequest.machine:type_name -> api.MachineInfo + 6, // 4: api.JoinClusterRequest.other_machines:type_name -> api.MachineInfo + 0, // 5: api.Machine.InitCluster:input_type -> api.InitClusterRequest + 2, // 6: api.Machine.JoinCluster:input_type -> api.JoinClusterRequest + 7, // 7: api.Machine.Token:input_type -> google.protobuf.Empty + 1, // 8: api.Machine.InitCluster:output_type -> api.InitClusterResponse + 7, // 9: api.Machine.JoinCluster:output_type -> google.protobuf.Empty + 3, // 10: api.Machine.Token:output_type -> api.TokenResponse + 8, // [8:11] is the sub-list for method output_type + 5, // [5:8] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_internal_machine_api_pb_machine_proto_init() } @@ -290,6 +361,18 @@ func file_internal_machine_api_pb_machine_proto_init() { } } file_internal_machine_api_pb_machine_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*JoinClusterRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_machine_api_pb_machine_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*TokenResponse); i { case 0: return &v.state @@ -308,7 +391,7 @@ func file_internal_machine_api_pb_machine_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_internal_machine_api_pb_machine_proto_rawDesc, NumEnums: 0, - NumMessages: 3, + NumMessages: 4, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/machine/api/pb/machine.proto b/internal/machine/api/pb/machine.proto index 71151e08..0d035761 100644 --- a/internal/machine/api/pb/machine.proto +++ b/internal/machine/api/pb/machine.proto @@ -10,6 +10,7 @@ import "internal/machine/api/pb/cluster.proto"; service Machine { rpc InitCluster(InitClusterRequest) returns (InitClusterResponse); + rpc JoinCluster(JoinClusterRequest) returns (google.protobuf.Empty); rpc Token(google.protobuf.Empty) returns (TokenResponse); } @@ -23,6 +24,11 @@ message InitClusterResponse { MachineInfo machine = 1; } +message JoinClusterRequest { + MachineInfo machine = 1; + repeated MachineInfo other_machines = 3; +} + message TokenResponse { string token = 1; } diff --git a/internal/machine/api/pb/machine_grpc.pb.go b/internal/machine/api/pb/machine_grpc.pb.go index fce571ee..f36112a7 100644 --- a/internal/machine/api/pb/machine_grpc.pb.go +++ b/internal/machine/api/pb/machine_grpc.pb.go @@ -21,6 +21,7 @@ const _ = grpc.SupportPackageIsVersion9 const ( Machine_InitCluster_FullMethodName = "/api.Machine/InitCluster" + Machine_JoinCluster_FullMethodName = "/api.Machine/JoinCluster" Machine_Token_FullMethodName = "/api.Machine/Token" ) @@ -29,6 +30,7 @@ const ( // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type MachineClient interface { InitCluster(ctx context.Context, in *InitClusterRequest, opts ...grpc.CallOption) (*InitClusterResponse, error) + JoinCluster(ctx context.Context, in *JoinClusterRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) Token(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*TokenResponse, error) } @@ -50,6 +52,16 @@ func (c *machineClient) InitCluster(ctx context.Context, in *InitClusterRequest, return out, nil } +func (c *machineClient) JoinCluster(ctx context.Context, in *JoinClusterRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, Machine_JoinCluster_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *machineClient) Token(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*TokenResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(TokenResponse) @@ -65,6 +77,7 @@ func (c *machineClient) Token(ctx context.Context, in *emptypb.Empty, opts ...gr // for forward compatibility. type MachineServer interface { InitCluster(context.Context, *InitClusterRequest) (*InitClusterResponse, error) + JoinCluster(context.Context, *JoinClusterRequest) (*emptypb.Empty, error) Token(context.Context, *emptypb.Empty) (*TokenResponse, error) mustEmbedUnimplementedMachineServer() } @@ -79,6 +92,9 @@ type UnimplementedMachineServer struct{} func (UnimplementedMachineServer) InitCluster(context.Context, *InitClusterRequest) (*InitClusterResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method InitCluster not implemented") } +func (UnimplementedMachineServer) JoinCluster(context.Context, *JoinClusterRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method JoinCluster not implemented") +} func (UnimplementedMachineServer) Token(context.Context, *emptypb.Empty) (*TokenResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Token not implemented") } @@ -121,6 +137,24 @@ func _Machine_InitCluster_Handler(srv interface{}, ctx context.Context, dec func return interceptor(ctx, in, info, handler) } +func _Machine_JoinCluster_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(JoinClusterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MachineServer).JoinCluster(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Machine_JoinCluster_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MachineServer).JoinCluster(ctx, req.(*JoinClusterRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Machine_Token_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(emptypb.Empty) if err := dec(in); err != nil { @@ -150,6 +184,10 @@ var Machine_ServiceDesc = grpc.ServiceDesc{ MethodName: "InitCluster", Handler: _Machine_InitCluster_Handler, }, + { + MethodName: "JoinCluster", + Handler: _Machine_JoinCluster_Handler, + }, { MethodName: "Token", Handler: _Machine_Token_Handler, diff --git a/internal/machine/cluster/cluster.go b/internal/machine/cluster/cluster.go index 258a8e22..2c28b318 100644 --- a/internal/machine/cluster/cluster.go +++ b/internal/machine/cluster/cluster.go @@ -7,6 +7,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/emptypb" "log/slog" "net/netip" "uncloud/internal/machine/api/pb" @@ -163,6 +164,21 @@ func (c *Cluster) AddMachine(ctx context.Context, req *pb.AddMachineRequest) (*p return resp, nil } +func (c *Cluster) ListMachines(ctx context.Context, _ *emptypb.Empty) (*pb.ListMachinesResponse, error) { + if c.state == nil { + return nil, status.Error(codes.FailedPrecondition, "cluster is not initialized") + } + // TODO: consider creating MachineInfo type that pb.MachineInfo is mapped to always carry valid data to reduce + // error handling caused by conversions and nil pointers. + machines := make([]*pb.MachineInfo, 0, len(c.state.State.Machines)) + for _, sm := range c.state.State.Machines { + m := proto.Clone(sm).(*pb.MachineInfo) + m.Network.Endpoints = c.state.State.Endpoints[m.Id].Endpoints + machines = append(machines, m) + } + return &pb.ListMachinesResponse{Machines: machines}, nil +} + func (c *Cluster) ListMachineEndpoints( ctx context.Context, req *pb.ListMachineEndpointsRequest, ) (*pb.ListMachineEndpointsResponse, error) {