diff --git a/cmd/kubevpn/cmds/reset.go b/cmd/kubevpn/cmds/reset.go index 5822d4c7..386d6830 100644 --- a/cmd/kubevpn/cmds/reset.go +++ b/cmd/kubevpn/cmds/reset.go @@ -1,14 +1,12 @@ package cmds import ( - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" cmdutil "k8s.io/kubectl/pkg/cmd/util" "k8s.io/kubectl/pkg/util/i18n" "k8s.io/kubectl/pkg/util/templates" - "k8s.io/utils/ptr" "github.com/wencaiwulue/kubevpn/v2/pkg/daemon" "github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc" @@ -20,59 +18,48 @@ func CmdReset(f cmdutil.Factory) *cobra.Command { var sshConf = &pkgssh.SshConfig{} cmd := &cobra.Command{ Use: "reset", - Short: "Reset all resource create by kubevpn in k8s cluster", + Short: "Reset workloads to origin status", Long: templates.LongDesc(i18n.T(` - Reset all resource create by kubevpn in k8s cluster + Reset workloads to origin status - Reset will delete all resources create by kubevpn in k8s cluster, like deployment, service, serviceAccount... - and it will also delete local develop docker containers, docker networks. delete hosts entry added by kubevpn, - cleanup DNS settings. + Reset will remove injected container envoy-proxy and vpn, and restore service mesh rules. `)), Example: templates.Examples(i18n.T(` - # Reset default namespace - kubevpn reset + # Reset default namespace workloads depooyment/productpage + kubevpn reset deployment/productpage - # Reset another namespace test - kubevpn reset -n test + # Reset another namespace test workloads depooyment/productpage + kubevpn reset deployment/productpage -n test - # Reset cluster api-server behind of bastion host or ssh jump host - kubevpn reset --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem + # Reset workloads depooyment/productpage which api-server behind of bastion host or ssh jump host + kubevpn reset deployment/productpage --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem # It also supports ProxyJump, like ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐ │ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │ └──────┘ └──────┘ └──────┘ └──────┘ └────────────┘ - kubevpn reset --ssh-alias + kubevpn reset deployment/productpage --ssh-alias # Support ssh auth GSSAPI - kubevpn reset --ssh-addr --ssh-username --gssapi-keytab /path/to/keytab - kubevpn reset --ssh-addr --ssh-username --gssapi-cache /path/to/cache - kubevpn reset --ssh-addr --ssh-username --gssapi-password + kubevpn reset deployment/productpage --ssh-addr --ssh-username --gssapi-keytab /path/to/keytab + kubevpn reset deployment/productpage --ssh-addr --ssh-username --gssapi-cache /path/to/cache + kubevpn reset deployment/productpage --ssh-addr --ssh-username --gssapi-password `)), PreRunE: func(cmd *cobra.Command, args []string) error { util.InitLoggerForClient(false) return daemon.StartupDaemon(cmd.Context()) }, + Args: cobra.MatchAll(cobra.ExactArgs(1)), RunE: func(cmd *cobra.Command, args []string) error { bytes, ns, err := util.ConvertToKubeConfigBytes(f) if err != nil { return err } cli := daemon.GetClient(false) - disconnect, err := cli.Disconnect(cmd.Context(), &rpc.DisconnectRequest{ - KubeconfigBytes: ptr.To(string(bytes)), - Namespace: ptr.To(ns), - SshJump: sshConf.ToRPC(), - }) - if err != nil { - log.Warnf("Failed to disconnect from cluter: %v", err) - } else { - _ = util.PrintGRPCStream[rpc.DisconnectResponse](disconnect) - } - req := &rpc.ResetRequest{ KubeconfigBytes: string(bytes), Namespace: ns, + Workloads: args, SshJump: sshConf.ToRPC(), } resp, err := cli.Reset(cmd.Context(), req) diff --git a/cmd/kubevpn/cmds/root.go b/cmd/kubevpn/cmds/root.go index fbb39856..f5c879e3 100644 --- a/cmd/kubevpn/cmds/root.go +++ b/cmd/kubevpn/cmds/root.go @@ -80,6 +80,7 @@ func NewKubeVPNCommand() *cobra.Command { CmdLogs(factory), CmdCp(factory), CmdReset(factory), + CmdUninstall(factory), CmdQuit(factory), }, }, diff --git a/cmd/kubevpn/cmds/uninstall.go b/cmd/kubevpn/cmds/uninstall.go new file mode 100644 index 00000000..3b7c64d6 --- /dev/null +++ b/cmd/kubevpn/cmds/uninstall.go @@ -0,0 +1,95 @@ +package cmds + +import ( + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + cmdutil "k8s.io/kubectl/pkg/cmd/util" + "k8s.io/kubectl/pkg/util/i18n" + "k8s.io/kubectl/pkg/util/templates" + "k8s.io/utils/ptr" + + "github.com/wencaiwulue/kubevpn/v2/pkg/daemon" + "github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc" + pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh" + "github.com/wencaiwulue/kubevpn/v2/pkg/util" +) + +func CmdUninstall(f cmdutil.Factory) *cobra.Command { + var sshConf = &pkgssh.SshConfig{} + cmd := &cobra.Command{ + Use: "uninstall", + Short: "Uninstall all resource create by kubevpn in k8s cluster", + Long: templates.LongDesc(i18n.T(` + Uninstall all resource create by kubevpn in k8s cluster + + Uninstall will delete all resources create by kubevpn in k8s cluster, like deployment, service, serviceAccount... + and it will also delete local develop docker containers, docker networks. delete hosts entry added by kubevpn, + cleanup DNS settings. + `)), + Example: templates.Examples(i18n.T(` + # Uninstall default namespace + kubevpn uninstall + + # Uninstall another namespace test + kubevpn uninstall -n test + + # Uninstall cluster api-server behind of bastion host or ssh jump host + kubevpn uninstall --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem + + # It also supports ProxyJump, like + ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐ + │ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │ + └──────┘ └──────┘ └──────┘ └──────┘ └────────────┘ + kubevpn uninstall --ssh-alias + + # Support ssh auth GSSAPI + kubevpn uninstall --ssh-addr --ssh-username --gssapi-keytab /path/to/keytab + kubevpn uninstall --ssh-addr --ssh-username --gssapi-cache /path/to/cache + kubevpn uninstall --ssh-addr --ssh-username --gssapi-password + `)), + PreRunE: func(cmd *cobra.Command, args []string) error { + util.InitLoggerForClient(false) + return daemon.StartupDaemon(cmd.Context()) + }, + RunE: func(cmd *cobra.Command, args []string) error { + bytes, ns, err := util.ConvertToKubeConfigBytes(f) + if err != nil { + return err + } + cli := daemon.GetClient(false) + disconnect, err := cli.Disconnect(cmd.Context(), &rpc.DisconnectRequest{ + KubeconfigBytes: ptr.To(string(bytes)), + Namespace: ptr.To(ns), + SshJump: sshConf.ToRPC(), + }) + if err != nil { + log.Warnf("Failed to disconnect from cluter: %v", err) + } else { + _ = util.PrintGRPCStream[rpc.DisconnectResponse](disconnect) + } + + req := &rpc.UninstallRequest{ + KubeconfigBytes: string(bytes), + Namespace: ns, + SshJump: sshConf.ToRPC(), + } + resp, err := cli.Uninstall(cmd.Context(), req) + if err != nil { + return err + } + err = util.PrintGRPCStream[rpc.UninstallResponse](resp) + if err != nil { + if status.Code(err) == codes.Canceled { + return nil + } + return err + } + return nil + }, + } + + pkgssh.AddSshFlags(cmd.Flags(), sshConf) + return cmd +} diff --git a/pkg/daemon/action/reset.go b/pkg/daemon/action/reset.go index 45720032..7e5d1db6 100644 --- a/pkg/daemon/action/reset.go +++ b/pkg/daemon/action/reset.go @@ -25,7 +25,7 @@ func (svr *Server) Reset(req *rpc.ResetRequest, resp rpc.Daemon_ResetServer) err connect := &handler.ConnectOptions{ Namespace: req.Namespace, - Lock: &svr.Lock, + Workloads: req.Workloads, } file, err := util.ConvertToTempKubeconfigFile([]byte(req.KubeconfigBytes)) diff --git a/pkg/daemon/action/uninstall.go b/pkg/daemon/action/uninstall.go new file mode 100644 index 00000000..c1cb7278 --- /dev/null +++ b/pkg/daemon/action/uninstall.go @@ -0,0 +1,71 @@ +package action + +import ( + "io" + + log "github.com/sirupsen/logrus" + "github.com/spf13/pflag" + + "github.com/wencaiwulue/kubevpn/v2/pkg/config" + "github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc" + "github.com/wencaiwulue/kubevpn/v2/pkg/handler" + "github.com/wencaiwulue/kubevpn/v2/pkg/ssh" + "github.com/wencaiwulue/kubevpn/v2/pkg/util" +) + +func (svr *Server) Uninstall(req *rpc.UninstallRequest, resp rpc.Daemon_UninstallServer) error { + defer func() { + util.InitLoggerForServer(true) + log.SetOutput(svr.LogFile) + config.Debug = false + }() + out := io.MultiWriter(newUninstallWarp(resp), svr.LogFile) + util.InitLoggerForClient(config.Debug) + log.SetOutput(out) + + connect := &handler.ConnectOptions{ + Namespace: req.Namespace, + Lock: &svr.Lock, + } + + file, err := util.ConvertToTempKubeconfigFile([]byte(req.KubeconfigBytes)) + if err != nil { + return err + } + flags := pflag.NewFlagSet("", pflag.ContinueOnError) + flags.AddFlag(&pflag.Flag{ + Name: "kubeconfig", + DefValue: file, + }) + var sshConf = ssh.ParseSshFromRPC(req.SshJump) + var ctx = resp.Context() + var path string + path, err = ssh.SshJump(ctx, sshConf, flags, false) + if err != nil { + return err + } + err = connect.InitClient(util.InitFactoryByPath(path, req.Namespace)) + if err != nil { + return err + } + err = connect.Uninstall(ctx) + if err != nil { + return err + } + return nil +} + +type uninstallWarp struct { + server rpc.Daemon_UninstallServer +} + +func (r *uninstallWarp) Write(p []byte) (n int, err error) { + _ = r.server.Send(&rpc.UninstallResponse{ + Message: string(p), + }) + return len(p), nil +} + +func newUninstallWarp(server rpc.Daemon_UninstallServer) io.Writer { + return &uninstallWarp{server: server} +} diff --git a/pkg/daemon/rpc/daemon.pb.go b/pkg/daemon/rpc/daemon.pb.go index f49a997c..aaf00c28 100644 --- a/pkg/daemon/rpc/daemon.pb.go +++ b/pkg/daemon/rpc/daemon.pb.go @@ -2392,23 +2392,133 @@ func (x *UpgradeResponse) GetNeedUpgrade() bool { return false } -type ResetRequest struct { +type UninstallRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields KubeconfigBytes string `protobuf:"bytes,1,opt,name=KubeconfigBytes,proto3" json:"KubeconfigBytes,omitempty"` Namespace string `protobuf:"bytes,2,opt,name=Namespace,proto3" json:"Namespace,omitempty"` - // repeated string Workloads = 3; - // // ssh jump SshJump *SshJump `protobuf:"bytes,3,opt,name=SshJump,proto3" json:"SshJump,omitempty"` } +func (x *UninstallRequest) Reset() { + *x = UninstallRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_daemon_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UninstallRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UninstallRequest) ProtoMessage() {} + +func (x *UninstallRequest) ProtoReflect() protoreflect.Message { + mi := &file_daemon_proto_msgTypes[39] + 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 UninstallRequest.ProtoReflect.Descriptor instead. +func (*UninstallRequest) Descriptor() ([]byte, []int) { + return file_daemon_proto_rawDescGZIP(), []int{39} +} + +func (x *UninstallRequest) GetKubeconfigBytes() string { + if x != nil { + return x.KubeconfigBytes + } + return "" +} + +func (x *UninstallRequest) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *UninstallRequest) GetSshJump() *SshJump { + if x != nil { + return x.SshJump + } + return nil +} + +type UninstallResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *UninstallResponse) Reset() { + *x = UninstallResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_daemon_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UninstallResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UninstallResponse) ProtoMessage() {} + +func (x *UninstallResponse) ProtoReflect() protoreflect.Message { + mi := &file_daemon_proto_msgTypes[40] + 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 UninstallResponse.ProtoReflect.Descriptor instead. +func (*UninstallResponse) Descriptor() ([]byte, []int) { + return file_daemon_proto_rawDescGZIP(), []int{40} +} + +func (x *UninstallResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type ResetRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + KubeconfigBytes string `protobuf:"bytes,1,opt,name=KubeconfigBytes,proto3" json:"KubeconfigBytes,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=Namespace,proto3" json:"Namespace,omitempty"` + Workloads []string `protobuf:"bytes,3,rep,name=Workloads,proto3" json:"Workloads,omitempty"` + // ssh jump + SshJump *SshJump `protobuf:"bytes,4,opt,name=SshJump,proto3" json:"SshJump,omitempty"` +} + func (x *ResetRequest) Reset() { *x = ResetRequest{} if protoimpl.UnsafeEnabled { - mi := &file_daemon_proto_msgTypes[39] + mi := &file_daemon_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2421,7 +2531,7 @@ func (x *ResetRequest) String() string { func (*ResetRequest) ProtoMessage() {} func (x *ResetRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[39] + mi := &file_daemon_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2434,7 +2544,7 @@ func (x *ResetRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResetRequest.ProtoReflect.Descriptor instead. func (*ResetRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{39} + return file_daemon_proto_rawDescGZIP(), []int{41} } func (x *ResetRequest) GetKubeconfigBytes() string { @@ -2451,6 +2561,13 @@ func (x *ResetRequest) GetNamespace() string { return "" } +func (x *ResetRequest) GetWorkloads() []string { + if x != nil { + return x.Workloads + } + return nil +} + func (x *ResetRequest) GetSshJump() *SshJump { if x != nil { return x.SshJump @@ -2469,7 +2586,7 @@ type ResetResponse struct { func (x *ResetResponse) Reset() { *x = ResetResponse{} if protoimpl.UnsafeEnabled { - mi := &file_daemon_proto_msgTypes[40] + mi := &file_daemon_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2482,7 +2599,7 @@ func (x *ResetResponse) String() string { func (*ResetResponse) ProtoMessage() {} func (x *ResetResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[40] + mi := &file_daemon_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2495,7 +2612,7 @@ func (x *ResetResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResetResponse.ProtoReflect.Descriptor instead. func (*ResetResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{40} + return file_daemon_proto_rawDescGZIP(), []int{42} } func (x *ResetResponse) GetMessage() string { @@ -2525,7 +2642,7 @@ type SshJump struct { func (x *SshJump) Reset() { *x = SshJump{} if protoimpl.UnsafeEnabled { - mi := &file_daemon_proto_msgTypes[41] + mi := &file_daemon_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2538,7 +2655,7 @@ func (x *SshJump) String() string { func (*SshJump) ProtoMessage() {} func (x *SshJump) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[41] + mi := &file_daemon_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2551,7 +2668,7 @@ func (x *SshJump) ProtoReflect() protoreflect.Message { // Deprecated: Use SshJump.ProtoReflect.Descriptor instead. func (*SshJump) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{41} + return file_daemon_proto_rawDescGZIP(), []int{43} } func (x *SshJump) GetAddr() string { @@ -2637,7 +2754,7 @@ type ExtraRoute struct { func (x *ExtraRoute) Reset() { *x = ExtraRoute{} if protoimpl.UnsafeEnabled { - mi := &file_daemon_proto_msgTypes[42] + mi := &file_daemon_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2650,7 +2767,7 @@ func (x *ExtraRoute) String() string { func (*ExtraRoute) ProtoMessage() {} func (x *ExtraRoute) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[42] + mi := &file_daemon_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2663,7 +2780,7 @@ func (x *ExtraRoute) ProtoReflect() protoreflect.Message { // Deprecated: Use ExtraRoute.ProtoReflect.Descriptor instead. func (*ExtraRoute) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{42} + return file_daemon_proto_rawDescGZIP(), []int{44} } func (x *ExtraRoute) GetExtraCIDR() []string { @@ -2696,7 +2813,7 @@ type IdentifyRequest struct { func (x *IdentifyRequest) Reset() { *x = IdentifyRequest{} if protoimpl.UnsafeEnabled { - mi := &file_daemon_proto_msgTypes[43] + mi := &file_daemon_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2709,7 +2826,7 @@ func (x *IdentifyRequest) String() string { func (*IdentifyRequest) ProtoMessage() {} func (x *IdentifyRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[43] + mi := &file_daemon_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2722,7 +2839,7 @@ func (x *IdentifyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use IdentifyRequest.ProtoReflect.Descriptor instead. func (*IdentifyRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{43} + return file_daemon_proto_rawDescGZIP(), []int{45} } type IdentifyResponse struct { @@ -2736,7 +2853,7 @@ type IdentifyResponse struct { func (x *IdentifyResponse) Reset() { *x = IdentifyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_daemon_proto_msgTypes[44] + mi := &file_daemon_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2749,7 +2866,7 @@ func (x *IdentifyResponse) String() string { func (*IdentifyResponse) ProtoMessage() {} func (x *IdentifyResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[44] + mi := &file_daemon_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2762,7 +2879,7 @@ func (x *IdentifyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use IdentifyResponse.ProtoReflect.Descriptor instead. func (*IdentifyResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{44} + return file_daemon_proto_rawDescGZIP(), []int{46} } func (x *IdentifyResponse) GetID() string { @@ -3059,124 +3176,142 @@ var file_daemon_proto_rawDesc = []byte{ 0x69, 0x6f, 0x6e, 0x22, 0x33, 0x0a, 0x0f, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x4e, 0x65, 0x65, 0x64, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x4e, 0x65, 0x65, - 0x64, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x22, 0x7e, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x65, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x4b, 0x75, 0x62, 0x65, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0f, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x12, 0x26, 0x0a, 0x07, 0x53, 0x73, 0x68, 0x4a, 0x75, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0c, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x73, 0x68, 0x4a, 0x75, 0x6d, 0x70, 0x52, - 0x07, 0x53, 0x73, 0x68, 0x4a, 0x75, 0x6d, 0x70, 0x22, 0x29, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x22, 0xc7, 0x02, 0x0a, 0x07, 0x53, 0x73, 0x68, 0x4a, 0x75, 0x6d, 0x70, 0x12, - 0x12, 0x0a, 0x04, 0x41, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x41, - 0x64, 0x64, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4b, 0x65, 0x79, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x4a, 0x75, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4a, 0x75, 0x6d, - 0x70, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x6c, 0x69, 0x61, 0x73, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x6c, - 0x69, 0x61, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x75, 0x62, - 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x52, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x2a, 0x0a, 0x10, 0x47, 0x53, 0x53, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x74, 0x61, 0x62, 0x43, - 0x6f, 0x6e, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x47, 0x53, 0x53, 0x41, 0x50, - 0x49, 0x4b, 0x65, 0x79, 0x74, 0x61, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x12, 0x26, 0x0a, 0x0e, 0x47, - 0x53, 0x53, 0x41, 0x50, 0x49, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x47, 0x53, 0x53, 0x41, 0x50, 0x49, 0x50, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x47, 0x53, 0x53, 0x41, 0x50, 0x49, 0x43, 0x61, 0x63, - 0x68, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x47, 0x53, - 0x53, 0x41, 0x50, 0x49, 0x43, 0x61, 0x63, 0x68, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x22, 0x6e, 0x0a, - 0x0a, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x45, - 0x78, 0x74, 0x72, 0x61, 0x43, 0x49, 0x44, 0x52, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, - 0x45, 0x78, 0x74, 0x72, 0x61, 0x43, 0x49, 0x44, 0x52, 0x12, 0x20, 0x0a, 0x0b, 0x45, 0x78, 0x74, - 0x72, 0x61, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, - 0x45, 0x78, 0x74, 0x72, 0x61, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x45, - 0x78, 0x74, 0x72, 0x61, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x50, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0b, 0x45, 0x78, 0x74, 0x72, 0x61, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x50, 0x22, 0x11, 0x0a, - 0x0f, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x22, 0x22, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x49, 0x44, 0x32, 0xa6, 0x09, 0x0a, 0x06, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12, - 0x38, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x13, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, - 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0a, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, - 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x36, 0x0a, 0x05, 0x50, 0x72, - 0x6f, 0x78, 0x79, 0x12, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x30, 0x01, 0x12, 0x32, 0x0a, 0x05, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x12, 0x11, 0x2e, 0x72, 0x70, - 0x63, 0x2e, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, - 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x32, 0x0a, 0x05, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x12, - 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x35, 0x0a, 0x06, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x12, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, - 0x01, 0x12, 0x3c, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x64, 0x64, 0x12, 0x15, - 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x64, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x45, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, - 0x18, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x70, 0x63, 0x2e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x08, 0x53, 0x73, 0x68, 0x53, 0x74, 0x61, - 0x72, 0x74, 0x12, 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x73, 0x68, 0x53, 0x74, 0x61, 0x72, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, - 0x73, 0x68, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x36, 0x0a, 0x07, 0x53, 0x73, 0x68, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x13, 0x2e, 0x72, - 0x70, 0x63, 0x2e, 0x53, 0x73, 0x68, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x73, 0x68, 0x53, 0x74, 0x6f, 0x70, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0a, 0x53, 0x73, 0x68, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x73, - 0x68, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x17, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x2d, - 0x0a, 0x04, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x0f, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, - 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x2d, 0x0a, - 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2a, 0x0a, 0x03, - 0x47, 0x65, 0x74, 0x12, 0x0f, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x07, 0x55, 0x70, 0x67, 0x72, - 0x61, 0x64, 0x65, 0x12, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x55, - 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x33, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, - 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x32, 0x0a, - 0x05, 0x52, 0x65, 0x73, 0x65, 0x74, 0x12, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, - 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x72, 0x70, 0x63, 0x2e, - 0x52, 0x65, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, - 0x01, 0x12, 0x2f, 0x0a, 0x04, 0x51, 0x75, 0x69, 0x74, 0x12, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, - 0x51, 0x75, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x72, 0x70, - 0x63, 0x2e, 0x51, 0x75, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x30, 0x01, 0x12, 0x39, 0x0a, 0x08, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x12, 0x14, - 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x07, 0x5a, - 0x05, 0x2e, 0x3b, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x22, 0x82, 0x01, 0x0a, 0x10, 0x55, 0x6e, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, + 0x0f, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x07, 0x53, 0x73, 0x68, 0x4a, 0x75, 0x6d, 0x70, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x73, 0x68, + 0x4a, 0x75, 0x6d, 0x70, 0x52, 0x07, 0x53, 0x73, 0x68, 0x4a, 0x75, 0x6d, 0x70, 0x22, 0x2d, 0x0a, + 0x11, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x9c, 0x01, 0x0a, + 0x0c, 0x52, 0x65, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, + 0x0f, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, + 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, + 0x61, 0x64, 0x73, 0x12, 0x26, 0x0a, 0x07, 0x53, 0x73, 0x68, 0x4a, 0x75, 0x6d, 0x70, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x73, 0x68, 0x4a, 0x75, + 0x6d, 0x70, 0x52, 0x07, 0x53, 0x73, 0x68, 0x4a, 0x75, 0x6d, 0x70, 0x22, 0x29, 0x0a, 0x0d, 0x52, + 0x65, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc7, 0x02, 0x0a, 0x07, 0x53, 0x73, 0x68, 0x4a, 0x75, + 0x6d, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x41, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x41, 0x64, 0x64, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x66, 0x69, 0x6c, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4b, 0x65, 0x79, 0x66, 0x69, 0x6c, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x4a, 0x75, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x4a, 0x75, 0x6d, 0x70, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x6c, + 0x69, 0x61, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x10, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x2a, 0x0a, 0x10, 0x47, 0x53, 0x53, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x74, + 0x61, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x47, 0x53, + 0x53, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x74, 0x61, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x12, 0x26, + 0x0a, 0x0e, 0x47, 0x53, 0x53, 0x41, 0x50, 0x49, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x47, 0x53, 0x53, 0x41, 0x50, 0x49, 0x50, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x47, 0x53, 0x53, 0x41, 0x50, 0x49, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x47, 0x53, 0x53, 0x41, 0x50, 0x49, 0x43, 0x61, 0x63, 0x68, 0x65, 0x46, 0x69, 0x6c, 0x65, + 0x22, 0x6e, 0x0a, 0x0a, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x45, 0x78, 0x74, 0x72, 0x61, 0x43, 0x49, 0x44, 0x52, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x09, 0x45, 0x78, 0x74, 0x72, 0x61, 0x43, 0x49, 0x44, 0x52, 0x12, 0x20, 0x0a, 0x0b, + 0x45, 0x78, 0x74, 0x72, 0x61, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0b, 0x45, 0x78, 0x74, 0x72, 0x61, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x20, + 0x0a, 0x0b, 0x45, 0x78, 0x74, 0x72, 0x61, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x50, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0b, 0x45, 0x78, 0x74, 0x72, 0x61, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x50, + 0x22, 0x11, 0x0a, 0x0f, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x22, 0x22, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x32, 0xe6, 0x09, 0x0a, 0x06, 0x44, 0x61, 0x65, 0x6d, + 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x13, 0x2e, + 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x0b, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x13, 0x2e, 0x72, 0x70, + 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0a, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x17, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x36, 0x0a, + 0x05, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x70, + 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x32, 0x0a, 0x05, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x12, 0x11, + 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x12, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x32, 0x0a, 0x05, 0x43, 0x6c, 0x6f, + 0x6e, 0x65, 0x12, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x35, 0x0a, + 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x12, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x72, 0x70, + 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x64, + 0x64, 0x12, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x64, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x12, 0x18, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, + 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x08, 0x53, 0x73, 0x68, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x73, 0x68, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x72, 0x70, + 0x63, 0x2e, 0x53, 0x73, 0x68, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x07, 0x53, 0x73, 0x68, 0x53, 0x74, 0x6f, 0x70, 0x12, + 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x73, 0x68, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x73, 0x68, 0x53, 0x74, + 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0a, + 0x53, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x16, 0x2e, 0x72, 0x70, 0x63, + 0x2e, 0x53, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, + 0x01, 0x12, 0x2d, 0x0a, 0x04, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x0f, 0x2e, 0x72, 0x70, 0x63, 0x2e, + 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x72, 0x70, 0x63, + 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, + 0x12, 0x2d, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x72, 0x70, 0x63, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x2a, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x0f, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x07, 0x55, + 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x67, + 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x70, + 0x63, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x2e, + 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x32, 0x0a, 0x05, 0x52, 0x65, 0x73, 0x65, 0x74, 0x12, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, + 0x52, 0x65, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x72, + 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x30, 0x01, 0x12, 0x3e, 0x0a, 0x09, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, + 0x6c, 0x12, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, + 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x55, + 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x30, 0x01, 0x12, 0x2f, 0x0a, 0x04, 0x51, 0x75, 0x69, 0x74, 0x12, 0x10, 0x2e, 0x72, + 0x70, 0x63, 0x2e, 0x51, 0x75, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, + 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x39, 0x0a, 0x08, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x79, 0x12, 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x3b, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -3191,7 +3326,7 @@ func file_daemon_proto_rawDescGZIP() []byte { return file_daemon_proto_rawDescData } -var file_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 50) +var file_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 52) var file_daemon_proto_goTypes = []interface{}{ (*ConnectRequest)(nil), // 0: rpc.ConnectRequest (*ConnectResponse)(nil), // 1: rpc.ConnectResponse @@ -3232,84 +3367,89 @@ var file_daemon_proto_goTypes = []interface{}{ (*GetResponse)(nil), // 36: rpc.GetResponse (*UpgradeRequest)(nil), // 37: rpc.UpgradeRequest (*UpgradeResponse)(nil), // 38: rpc.UpgradeResponse - (*ResetRequest)(nil), // 39: rpc.ResetRequest - (*ResetResponse)(nil), // 40: rpc.ResetResponse - (*SshJump)(nil), // 41: rpc.SshJump - (*ExtraRoute)(nil), // 42: rpc.ExtraRoute - (*IdentifyRequest)(nil), // 43: rpc.IdentifyRequest - (*IdentifyResponse)(nil), // 44: rpc.IdentifyResponse - nil, // 45: rpc.ConnectRequest.HeadersEntry - nil, // 46: rpc.CloneRequest.HeadersEntry - nil, // 47: rpc.ProxyRule.HeadersEntry - nil, // 48: rpc.ProxyRule.PortMapEntry - nil, // 49: rpc.CloneRule.HeadersEntry + (*UninstallRequest)(nil), // 39: rpc.UninstallRequest + (*UninstallResponse)(nil), // 40: rpc.UninstallResponse + (*ResetRequest)(nil), // 41: rpc.ResetRequest + (*ResetResponse)(nil), // 42: rpc.ResetResponse + (*SshJump)(nil), // 43: rpc.SshJump + (*ExtraRoute)(nil), // 44: rpc.ExtraRoute + (*IdentifyRequest)(nil), // 45: rpc.IdentifyRequest + (*IdentifyResponse)(nil), // 46: rpc.IdentifyResponse + nil, // 47: rpc.ConnectRequest.HeadersEntry + nil, // 48: rpc.CloneRequest.HeadersEntry + nil, // 49: rpc.ProxyRule.HeadersEntry + nil, // 50: rpc.ProxyRule.PortMapEntry + nil, // 51: rpc.CloneRule.HeadersEntry } var file_daemon_proto_depIdxs = []int32{ - 45, // 0: rpc.ConnectRequest.Headers:type_name -> rpc.ConnectRequest.HeadersEntry - 42, // 1: rpc.ConnectRequest.ExtraRoute:type_name -> rpc.ExtraRoute - 41, // 2: rpc.ConnectRequest.SshJump:type_name -> rpc.SshJump - 41, // 3: rpc.DisconnectRequest.SshJump:type_name -> rpc.SshJump - 46, // 4: rpc.CloneRequest.Headers:type_name -> rpc.CloneRequest.HeadersEntry - 42, // 5: rpc.CloneRequest.ExtraRoute:type_name -> rpc.ExtraRoute - 41, // 6: rpc.CloneRequest.SshJump:type_name -> rpc.SshJump + 47, // 0: rpc.ConnectRequest.Headers:type_name -> rpc.ConnectRequest.HeadersEntry + 44, // 1: rpc.ConnectRequest.ExtraRoute:type_name -> rpc.ExtraRoute + 43, // 2: rpc.ConnectRequest.SshJump:type_name -> rpc.SshJump + 43, // 3: rpc.DisconnectRequest.SshJump:type_name -> rpc.SshJump + 48, // 4: rpc.CloneRequest.Headers:type_name -> rpc.CloneRequest.HeadersEntry + 44, // 5: rpc.CloneRequest.ExtraRoute:type_name -> rpc.ExtraRoute + 43, // 6: rpc.CloneRequest.SshJump:type_name -> rpc.SshJump 14, // 7: rpc.StatusResponse.List:type_name -> rpc.Status 15, // 8: rpc.Status.ProxyList:type_name -> rpc.Proxy 17, // 9: rpc.Status.CloneList:type_name -> rpc.Clone 16, // 10: rpc.Proxy.RuleList:type_name -> rpc.ProxyRule - 47, // 11: rpc.ProxyRule.Headers:type_name -> rpc.ProxyRule.HeadersEntry - 48, // 12: rpc.ProxyRule.PortMap:type_name -> rpc.ProxyRule.PortMapEntry + 49, // 11: rpc.ProxyRule.Headers:type_name -> rpc.ProxyRule.HeadersEntry + 50, // 12: rpc.ProxyRule.PortMap:type_name -> rpc.ProxyRule.PortMapEntry 18, // 13: rpc.Clone.RuleList:type_name -> rpc.CloneRule - 49, // 14: rpc.CloneRule.Headers:type_name -> rpc.CloneRule.HeadersEntry - 41, // 15: rpc.ConfigAddRequest.SshJump:type_name -> rpc.SshJump - 41, // 16: rpc.SshConnectRequest.SshJump:type_name -> rpc.SshJump - 41, // 17: rpc.ResetRequest.SshJump:type_name -> rpc.SshJump - 0, // 18: rpc.Daemon.Connect:input_type -> rpc.ConnectRequest - 0, // 19: rpc.Daemon.ConnectFork:input_type -> rpc.ConnectRequest - 2, // 20: rpc.Daemon.Disconnect:input_type -> rpc.DisconnectRequest - 0, // 21: rpc.Daemon.Proxy:input_type -> rpc.ConnectRequest - 4, // 22: rpc.Daemon.Leave:input_type -> rpc.LeaveRequest - 6, // 23: rpc.Daemon.Clone:input_type -> rpc.CloneRequest - 8, // 24: rpc.Daemon.Remove:input_type -> rpc.RemoveRequest - 21, // 25: rpc.Daemon.ConfigAdd:input_type -> rpc.ConfigAddRequest - 29, // 26: rpc.Daemon.ConfigRemove:input_type -> rpc.ConfigRemoveRequest - 22, // 27: rpc.Daemon.SshStart:input_type -> rpc.SshStartRequest - 24, // 28: rpc.Daemon.SshStop:input_type -> rpc.SshStopRequest - 26, // 29: rpc.Daemon.SshConnect:input_type -> rpc.SshConnectRequest - 31, // 30: rpc.Daemon.Logs:input_type -> rpc.LogRequest - 33, // 31: rpc.Daemon.List:input_type -> rpc.ListRequest - 35, // 32: rpc.Daemon.Get:input_type -> rpc.GetRequest - 37, // 33: rpc.Daemon.Upgrade:input_type -> rpc.UpgradeRequest - 12, // 34: rpc.Daemon.Status:input_type -> rpc.StatusRequest - 19, // 35: rpc.Daemon.Version:input_type -> rpc.VersionRequest - 39, // 36: rpc.Daemon.Reset:input_type -> rpc.ResetRequest - 10, // 37: rpc.Daemon.Quit:input_type -> rpc.QuitRequest - 43, // 38: rpc.Daemon.Identify:input_type -> rpc.IdentifyRequest - 1, // 39: rpc.Daemon.Connect:output_type -> rpc.ConnectResponse - 1, // 40: rpc.Daemon.ConnectFork:output_type -> rpc.ConnectResponse - 3, // 41: rpc.Daemon.Disconnect:output_type -> rpc.DisconnectResponse - 1, // 42: rpc.Daemon.Proxy:output_type -> rpc.ConnectResponse - 5, // 43: rpc.Daemon.Leave:output_type -> rpc.LeaveResponse - 7, // 44: rpc.Daemon.Clone:output_type -> rpc.CloneResponse - 9, // 45: rpc.Daemon.Remove:output_type -> rpc.RemoveResponse - 28, // 46: rpc.Daemon.ConfigAdd:output_type -> rpc.ConfigAddResponse - 30, // 47: rpc.Daemon.ConfigRemove:output_type -> rpc.ConfigRemoveResponse - 23, // 48: rpc.Daemon.SshStart:output_type -> rpc.SshStartResponse - 25, // 49: rpc.Daemon.SshStop:output_type -> rpc.SshStopResponse - 27, // 50: rpc.Daemon.SshConnect:output_type -> rpc.SshConnectResponse - 32, // 51: rpc.Daemon.Logs:output_type -> rpc.LogResponse - 34, // 52: rpc.Daemon.List:output_type -> rpc.ListResponse - 36, // 53: rpc.Daemon.Get:output_type -> rpc.GetResponse - 38, // 54: rpc.Daemon.Upgrade:output_type -> rpc.UpgradeResponse - 13, // 55: rpc.Daemon.Status:output_type -> rpc.StatusResponse - 20, // 56: rpc.Daemon.Version:output_type -> rpc.VersionResponse - 40, // 57: rpc.Daemon.Reset:output_type -> rpc.ResetResponse - 11, // 58: rpc.Daemon.Quit:output_type -> rpc.QuitResponse - 44, // 59: rpc.Daemon.Identify:output_type -> rpc.IdentifyResponse - 39, // [39:60] is the sub-list for method output_type - 18, // [18:39] is the sub-list for method input_type - 18, // [18:18] is the sub-list for extension type_name - 18, // [18:18] is the sub-list for extension extendee - 0, // [0:18] is the sub-list for field type_name + 51, // 14: rpc.CloneRule.Headers:type_name -> rpc.CloneRule.HeadersEntry + 43, // 15: rpc.ConfigAddRequest.SshJump:type_name -> rpc.SshJump + 43, // 16: rpc.SshConnectRequest.SshJump:type_name -> rpc.SshJump + 43, // 17: rpc.UninstallRequest.SshJump:type_name -> rpc.SshJump + 43, // 18: rpc.ResetRequest.SshJump:type_name -> rpc.SshJump + 0, // 19: rpc.Daemon.Connect:input_type -> rpc.ConnectRequest + 0, // 20: rpc.Daemon.ConnectFork:input_type -> rpc.ConnectRequest + 2, // 21: rpc.Daemon.Disconnect:input_type -> rpc.DisconnectRequest + 0, // 22: rpc.Daemon.Proxy:input_type -> rpc.ConnectRequest + 4, // 23: rpc.Daemon.Leave:input_type -> rpc.LeaveRequest + 6, // 24: rpc.Daemon.Clone:input_type -> rpc.CloneRequest + 8, // 25: rpc.Daemon.Remove:input_type -> rpc.RemoveRequest + 21, // 26: rpc.Daemon.ConfigAdd:input_type -> rpc.ConfigAddRequest + 29, // 27: rpc.Daemon.ConfigRemove:input_type -> rpc.ConfigRemoveRequest + 22, // 28: rpc.Daemon.SshStart:input_type -> rpc.SshStartRequest + 24, // 29: rpc.Daemon.SshStop:input_type -> rpc.SshStopRequest + 26, // 30: rpc.Daemon.SshConnect:input_type -> rpc.SshConnectRequest + 31, // 31: rpc.Daemon.Logs:input_type -> rpc.LogRequest + 33, // 32: rpc.Daemon.List:input_type -> rpc.ListRequest + 35, // 33: rpc.Daemon.Get:input_type -> rpc.GetRequest + 37, // 34: rpc.Daemon.Upgrade:input_type -> rpc.UpgradeRequest + 12, // 35: rpc.Daemon.Status:input_type -> rpc.StatusRequest + 19, // 36: rpc.Daemon.Version:input_type -> rpc.VersionRequest + 41, // 37: rpc.Daemon.Uninstall:input_type -> rpc.ResetRequest + 39, // 38: rpc.Daemon.Uninstall:input_type -> rpc.UninstallRequest + 10, // 39: rpc.Daemon.Quit:input_type -> rpc.QuitRequest + 45, // 40: rpc.Daemon.Identify:input_type -> rpc.IdentifyRequest + 1, // 41: rpc.Daemon.Connect:output_type -> rpc.ConnectResponse + 1, // 42: rpc.Daemon.ConnectFork:output_type -> rpc.ConnectResponse + 3, // 43: rpc.Daemon.Disconnect:output_type -> rpc.DisconnectResponse + 1, // 44: rpc.Daemon.Proxy:output_type -> rpc.ConnectResponse + 5, // 45: rpc.Daemon.Leave:output_type -> rpc.LeaveResponse + 7, // 46: rpc.Daemon.Clone:output_type -> rpc.CloneResponse + 9, // 47: rpc.Daemon.Remove:output_type -> rpc.RemoveResponse + 28, // 48: rpc.Daemon.ConfigAdd:output_type -> rpc.ConfigAddResponse + 30, // 49: rpc.Daemon.ConfigRemove:output_type -> rpc.ConfigRemoveResponse + 23, // 50: rpc.Daemon.SshStart:output_type -> rpc.SshStartResponse + 25, // 51: rpc.Daemon.SshStop:output_type -> rpc.SshStopResponse + 27, // 52: rpc.Daemon.SshConnect:output_type -> rpc.SshConnectResponse + 32, // 53: rpc.Daemon.Logs:output_type -> rpc.LogResponse + 34, // 54: rpc.Daemon.List:output_type -> rpc.ListResponse + 36, // 55: rpc.Daemon.Get:output_type -> rpc.GetResponse + 38, // 56: rpc.Daemon.Upgrade:output_type -> rpc.UpgradeResponse + 13, // 57: rpc.Daemon.Status:output_type -> rpc.StatusResponse + 20, // 58: rpc.Daemon.Version:output_type -> rpc.VersionResponse + 42, // 59: rpc.Daemon.Uninstall:output_type -> rpc.ResetResponse + 40, // 60: rpc.Daemon.Uninstall:output_type -> rpc.UninstallResponse + 11, // 61: rpc.Daemon.Quit:output_type -> rpc.QuitResponse + 46, // 62: rpc.Daemon.Identify:output_type -> rpc.IdentifyResponse + 41, // [41:63] is the sub-list for method output_type + 19, // [19:41] is the sub-list for method input_type + 19, // [19:19] is the sub-list for extension type_name + 19, // [19:19] is the sub-list for extension extendee + 0, // [0:19] is the sub-list for field type_name } func init() { file_daemon_proto_init() } @@ -3787,7 +3927,7 @@ func file_daemon_proto_init() { } } file_daemon_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetRequest); i { + switch v := v.(*UninstallRequest); i { case 0: return &v.state case 1: @@ -3799,7 +3939,7 @@ func file_daemon_proto_init() { } } file_daemon_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetResponse); i { + switch v := v.(*UninstallResponse); i { case 0: return &v.state case 1: @@ -3811,7 +3951,7 @@ func file_daemon_proto_init() { } } file_daemon_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SshJump); i { + switch v := v.(*ResetRequest); i { case 0: return &v.state case 1: @@ -3823,7 +3963,7 @@ func file_daemon_proto_init() { } } file_daemon_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExtraRoute); i { + switch v := v.(*ResetResponse); i { case 0: return &v.state case 1: @@ -3835,7 +3975,7 @@ func file_daemon_proto_init() { } } file_daemon_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IdentifyRequest); i { + switch v := v.(*SshJump); i { case 0: return &v.state case 1: @@ -3847,6 +3987,30 @@ func file_daemon_proto_init() { } } file_daemon_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtraRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_daemon_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IdentifyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_daemon_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*IdentifyResponse); i { case 0: return &v.state @@ -3866,7 +4030,7 @@ func file_daemon_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_daemon_proto_rawDesc, NumEnums: 0, - NumMessages: 50, + NumMessages: 52, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/daemon/rpc/daemon.proto b/pkg/daemon/rpc/daemon.proto index d3e40c23..26060aed 100644 --- a/pkg/daemon/rpc/daemon.proto +++ b/pkg/daemon/rpc/daemon.proto @@ -26,6 +26,7 @@ service Daemon { rpc Status (StatusRequest) returns (StatusResponse) {} rpc Version (VersionRequest) returns (VersionResponse) {} rpc Reset (ResetRequest) returns (stream ResetResponse) {} + rpc Uninstall (UninstallRequest) returns (stream UninstallResponse) {} rpc Quit (QuitRequest) returns (stream QuitResponse) {} rpc Identify (IdentifyRequest) returns (IdentifyResponse) {} @@ -281,12 +282,23 @@ message UpgradeResponse { bool NeedUpgrade = 1; } +message UninstallRequest { + string KubeconfigBytes = 1; + string Namespace = 2; + // ssh jump + SshJump SshJump = 3; +} + +message UninstallResponse { + string message = 1; +} + message ResetRequest { string KubeconfigBytes = 1; string Namespace = 2; -// repeated string Workloads = 3; + repeated string Workloads = 3; // ssh jump - SshJump SshJump = 3; + SshJump SshJump = 4; } message ResetResponse { diff --git a/pkg/daemon/rpc/daemon_grpc.pb.go b/pkg/daemon/rpc/daemon_grpc.pb.go index a672d7bf..33841139 100644 --- a/pkg/daemon/rpc/daemon_grpc.pb.go +++ b/pkg/daemon/rpc/daemon_grpc.pb.go @@ -38,6 +38,7 @@ const ( Daemon_Status_FullMethodName = "/rpc.Daemon/Status" Daemon_Version_FullMethodName = "/rpc.Daemon/Version" Daemon_Reset_FullMethodName = "/rpc.Daemon/Reset" + Daemon_Uninstall_FullMethodName = "/rpc.Daemon/Uninstall" Daemon_Quit_FullMethodName = "/rpc.Daemon/Quit" Daemon_Identify_FullMethodName = "/rpc.Daemon/Identify" ) @@ -65,6 +66,7 @@ type DaemonClient interface { Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) Version(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*VersionResponse, error) Reset(ctx context.Context, in *ResetRequest, opts ...grpc.CallOption) (Daemon_ResetClient, error) + Uninstall(ctx context.Context, in *UninstallRequest, opts ...grpc.CallOption) (Daemon_UninstallClient, error) Quit(ctx context.Context, in *QuitRequest, opts ...grpc.CallOption) (Daemon_QuitClient, error) Identify(ctx context.Context, in *IdentifyRequest, opts ...grpc.CallOption) (*IdentifyResponse, error) } @@ -477,8 +479,40 @@ func (x *daemonResetClient) Recv() (*ResetResponse, error) { return m, nil } +func (c *daemonClient) Uninstall(ctx context.Context, in *UninstallRequest, opts ...grpc.CallOption) (Daemon_UninstallClient, error) { + stream, err := c.cc.NewStream(ctx, &Daemon_ServiceDesc.Streams[10], Daemon_Uninstall_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &daemonUninstallClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Daemon_UninstallClient interface { + Recv() (*UninstallResponse, error) + grpc.ClientStream +} + +type daemonUninstallClient struct { + grpc.ClientStream +} + +func (x *daemonUninstallClient) Recv() (*UninstallResponse, error) { + m := new(UninstallResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func (c *daemonClient) Quit(ctx context.Context, in *QuitRequest, opts ...grpc.CallOption) (Daemon_QuitClient, error) { - stream, err := c.cc.NewStream(ctx, &Daemon_ServiceDesc.Streams[10], Daemon_Quit_FullMethodName, opts...) + stream, err := c.cc.NewStream(ctx, &Daemon_ServiceDesc.Streams[11], Daemon_Quit_FullMethodName, opts...) if err != nil { return nil, err } @@ -541,6 +575,7 @@ type DaemonServer interface { Status(context.Context, *StatusRequest) (*StatusResponse, error) Version(context.Context, *VersionRequest) (*VersionResponse, error) Reset(*ResetRequest, Daemon_ResetServer) error + Uninstall(*UninstallRequest, Daemon_UninstallServer) error Quit(*QuitRequest, Daemon_QuitServer) error Identify(context.Context, *IdentifyRequest) (*IdentifyResponse, error) mustEmbedUnimplementedDaemonServer() @@ -607,6 +642,9 @@ func (UnimplementedDaemonServer) Version(context.Context, *VersionRequest) (*Ver func (UnimplementedDaemonServer) Reset(*ResetRequest, Daemon_ResetServer) error { return status.Errorf(codes.Unimplemented, "method Reset not implemented") } +func (UnimplementedDaemonServer) Uninstall(*UninstallRequest, Daemon_UninstallServer) error { + return status.Errorf(codes.Unimplemented, "method Uninstall not implemented") +} func (UnimplementedDaemonServer) Quit(*QuitRequest, Daemon_QuitServer) error { return status.Errorf(codes.Unimplemented, "method Quit not implemented") } @@ -1003,6 +1041,27 @@ func (x *daemonResetServer) Send(m *ResetResponse) error { return x.ServerStream.SendMsg(m) } +func _Daemon_Uninstall_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(UninstallRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(DaemonServer).Uninstall(m, &daemonUninstallServer{stream}) +} + +type Daemon_UninstallServer interface { + Send(*UninstallResponse) error + grpc.ServerStream +} + +type daemonUninstallServer struct { + grpc.ServerStream +} + +func (x *daemonUninstallServer) Send(m *UninstallResponse) error { + return x.ServerStream.SendMsg(m) +} + func _Daemon_Quit_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(QuitRequest) if err := stream.RecvMsg(m); err != nil { @@ -1142,6 +1201,11 @@ var Daemon_ServiceDesc = grpc.ServiceDesc{ Handler: _Daemon_Reset_Handler, ServerStreams: true, }, + { + StreamName: "Uninstall", + Handler: _Daemon_Uninstall_Handler, + ServerStreams: true, + }, { StreamName: "Quit", Handler: _Daemon_Quit_Handler, diff --git a/pkg/handler/reset.go b/pkg/handler/reset.go index 62c88e63..2db4997d 100644 --- a/pkg/handler/reset.go +++ b/pkg/handler/reset.go @@ -2,81 +2,64 @@ package handler import ( "context" + "encoding/json" "strings" - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" log "github.com/sirupsen/logrus" - corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/pointer" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/sets" + pkgresource "k8s.io/cli-runtime/pkg/resource" + "k8s.io/client-go/kubernetes" + v1 "k8s.io/client-go/kubernetes/typed/core/v1" + cmdutil "k8s.io/kubectl/pkg/cmd/util" "sigs.k8s.io/yaml" "github.com/wencaiwulue/kubevpn/v2/pkg/config" "github.com/wencaiwulue/kubevpn/v2/pkg/controlplane" "github.com/wencaiwulue/kubevpn/v2/pkg/inject" + "github.com/wencaiwulue/kubevpn/v2/pkg/util" ) // Reset -// 1) quit daemon -// 2) get all proxy-resources from configmap -// 3) cleanup all containers -// 4) cleanup hosts +// 1) reset configmap +// 2) remove inject containers envoy and vpn +// 3) restore service targetPort to containerPort func (c *ConnectOptions) Reset(ctx context.Context) error { - err := c.LeaveProxyResources(ctx) + if c == nil || c.clientset == nil { + return nil + } + err := c.PreCheckResource() if err != nil { - log.Errorf("Leave proxy resources error: %v", err) - } else { - log.Debugf("Leave proxy resources successfully") + return err } - log.Infof("Cleaning up resources") - ns := c.Namespace - name := config.ConfigMapPodTrafficManager - options := metav1.DeleteOptions{GracePeriodSeconds: pointer.Int64(0)} - _ = c.clientset.CoreV1().ConfigMaps(ns).Delete(ctx, name, options) - _ = c.clientset.CoreV1().Pods(ns).Delete(ctx, config.CniNetName, options) - _ = c.clientset.CoreV1().Secrets(ns).Delete(ctx, name, options) - _ = c.clientset.AdmissionregistrationV1().MutatingWebhookConfigurations().Delete(ctx, name+"."+ns, options) - _ = c.clientset.RbacV1().RoleBindings(ns).Delete(ctx, name, options) - _ = c.clientset.CoreV1().ServiceAccounts(ns).Delete(ctx, name, options) - _ = c.clientset.RbacV1().Roles(ns).Delete(ctx, name, options) - _ = c.clientset.CoreV1().Services(ns).Delete(ctx, name, options) - _ = c.clientset.AppsV1().Deployments(ns).Delete(ctx, name, options) + err = resetConfigMap(ctx, c.clientset.CoreV1().ConfigMaps(c.Namespace), c.Workloads) + if err != nil { + log.Error(err) + } + + for _, workload := range c.Workloads { + err = removeInjectContainer(ctx, c.factory, c.clientset, c.Namespace, workload) + if err != nil { + log.Error(err) + } + } - _ = c.CleanupLocalContainer(ctx) - log.Info("Done") return nil } -func (c *ConnectOptions) CleanupLocalContainer(ctx context.Context) error { - cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) +func resetConfigMap(ctx context.Context, mapInterface v1.ConfigMapInterface, workloads []string) error { + cm, err := mapInterface.Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{}) if err != nil { + if apierrors.IsNotFound(err) { + return nil + } return err } - var networkResource types.NetworkResource - networkResource, err = cli.NetworkInspect(ctx, config.ConfigMapPodTrafficManager, types.NetworkInspectOptions{}) - if err != nil { - return err - } - if len(networkResource.Containers) == 0 { - err = cli.NetworkRemove(ctx, config.ConfigMapPodTrafficManager) - } - return err -} - -func (c *ConnectOptions) LeaveProxyResources(ctx context.Context) (err error) { - if c == nil || c.clientset == nil { - return - } - - mapInterface := c.clientset.CoreV1().ConfigMaps(c.Namespace) - var cm *corev1.ConfigMap - cm, err = mapInterface.Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{}) - if err != nil && !apierrors.IsNotFound(err) { - return - } if cm == nil || cm.Data == nil || len(cm.Data[config.KeyEnvoy]) == 0 { log.Infof("No proxy resources found") return nil @@ -85,29 +68,90 @@ func (c *ConnectOptions) LeaveProxyResources(ctx context.Context) (err error) { str := cm.Data[config.KeyEnvoy] if err = yaml.Unmarshal([]byte(str), &v); err != nil { log.Errorf("Unmarshal envoy config error: %v", err) - return + return nil + } + ws := sets.New[string]() + for _, workload := range workloads { + ws.Insert(ConvertWorkloadToUid(workload)) } - v4, _ := c.GetLocalTunIP() - for _, virtual := range v { - var found bool - for _, rule := range virtual.Rules { - if rule.LocalTunIPv4 == v4 { - found = true - break - } - } - if !found { - continue - } - // deployments.apps.ry-server --> deployments.apps/ry-server - lastIndex := strings.LastIndex(virtual.Uid, ".") - uid := virtual.Uid[:lastIndex] + "/" + virtual.Uid[lastIndex+1:] - err = inject.UnPatchContainer(c.factory, c.clientset.CoreV1().ConfigMaps(c.Namespace), c.Namespace, uid, v4) - if err != nil { - log.Errorf("Failed to leave workload %s: %v", uid, err) - continue + for i := 0; i < len(v); i++ { + if ws.Has(v[i].Uid) { + v = append(v[:i], v[i+1:]...) + i-- } } + + marshal, err := yaml.Marshal(v) + if err != nil { + return err + } + cm.Data[config.KeyEnvoy] = string(marshal) + _, err = mapInterface.Update(ctx, cm, metav1.UpdateOptions{}) + return err +} + +// ConvertUidToWorkload +// deployments.apps.ry-server --> deployments.apps/ry-server +func ConvertUidToWorkload(uid string) string { + lastIndex := strings.LastIndex(uid, ".") + workload := uid[:lastIndex] + "/" + uid[lastIndex+1:] + return workload +} + +// ConvertWorkloadToUid +// deployments.apps/ry-server --> deployments.apps.ry-server +func ConvertWorkloadToUid(workload string) string { + lastIndex := strings.LastIndex(workload, "/") + uid := workload[:lastIndex] + "." + workload[lastIndex+1:] + return uid +} + +func removeInjectContainer(ctx context.Context, factory cmdutil.Factory, clientset *kubernetes.Clientset, namespace, workload string) error { + object, err := util.GetUnstructuredObject(factory, namespace, workload) + if err != nil { + log.Errorf("Failed to get unstructured object: %v", err) + return err + } + + u := object.Object.(*unstructured.Unstructured) + templateSpec, depth, err := util.GetPodTemplateSpecPath(u) + if err != nil { + log.Errorf("Failed to get template spec path: %v", err) + return err + } + + log.Infof("Leaving workload %s", workload) + + inject.RemoveContainers(templateSpec) + + helper := pkgresource.NewHelper(object.Client, object.Mapping) + log.Debugf("The %s is under controller management", workload) + // resource with controller, like deployment,statefulset + var bytes []byte + bytes, err = json.Marshal([]inject.P{ + { + Op: "replace", + Path: "/" + strings.Join(append(depth, "spec"), "/"), + Value: templateSpec.Spec, + }, + }) + if err != nil { + log.Errorf("Failed to generate json patch: %v", err) + return err + } + _, err = helper.Patch(object.Namespace, object.Name, types.JSONPatchType, bytes, &metav1.PatchOptions{}) + if err != nil { + log.Errorf("Failed to patch resource: %s %s: %v", object.Mapping.GroupVersionKind.GroupKind().String(), object.Name, err) + return err + } + + var portmap = make(map[int32]int32) + for _, container := range templateSpec.Spec.Containers { + for _, port := range container.Ports { + portmap[port.ContainerPort] = port.ContainerPort + } + } + err = inject.ModifyServiceTargetPort(ctx, clientset, namespace, labels.SelectorFromSet(templateSpec.Labels).String(), portmap) return err } diff --git a/pkg/handler/uninstall.go b/pkg/handler/uninstall.go new file mode 100644 index 00000000..92311284 --- /dev/null +++ b/pkg/handler/uninstall.go @@ -0,0 +1,113 @@ +package handler + +import ( + "context" + "strings" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" + log "github.com/sirupsen/logrus" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/pointer" + "sigs.k8s.io/yaml" + + "github.com/wencaiwulue/kubevpn/v2/pkg/config" + "github.com/wencaiwulue/kubevpn/v2/pkg/controlplane" + "github.com/wencaiwulue/kubevpn/v2/pkg/inject" +) + +// Uninstall +// 1) quit daemon +// 2) get all proxy-resources from configmap +// 3) cleanup all containers +// 4) cleanup hosts +func (c *ConnectOptions) Uninstall(ctx context.Context) error { + err := c.LeaveProxyResources(ctx) + if err != nil { + log.Errorf("Leave proxy resources error: %v", err) + } else { + log.Debugf("Leave proxy resources successfully") + } + + log.Infof("Cleaning up resources") + ns := c.Namespace + name := config.ConfigMapPodTrafficManager + options := metav1.DeleteOptions{GracePeriodSeconds: pointer.Int64(0)} + _ = c.clientset.CoreV1().ConfigMaps(ns).Delete(ctx, name, options) + _ = c.clientset.CoreV1().Pods(ns).Delete(ctx, config.CniNetName, options) + _ = c.clientset.CoreV1().Secrets(ns).Delete(ctx, name, options) + _ = c.clientset.AdmissionregistrationV1().MutatingWebhookConfigurations().Delete(ctx, name+"."+ns, options) + _ = c.clientset.RbacV1().RoleBindings(ns).Delete(ctx, name, options) + _ = c.clientset.CoreV1().ServiceAccounts(ns).Delete(ctx, name, options) + _ = c.clientset.RbacV1().Roles(ns).Delete(ctx, name, options) + _ = c.clientset.CoreV1().Services(ns).Delete(ctx, name, options) + _ = c.clientset.AppsV1().Deployments(ns).Delete(ctx, name, options) + + _ = c.CleanupLocalContainer(ctx) + log.Info("Done") + return nil +} + +func (c *ConnectOptions) CleanupLocalContainer(ctx context.Context) error { + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + if err != nil { + return err + } + var networkResource types.NetworkResource + networkResource, err = cli.NetworkInspect(ctx, config.ConfigMapPodTrafficManager, types.NetworkInspectOptions{}) + if err != nil { + return err + } + if len(networkResource.Containers) == 0 { + err = cli.NetworkRemove(ctx, config.ConfigMapPodTrafficManager) + } + return err +} + +func (c *ConnectOptions) LeaveProxyResources(ctx context.Context) (err error) { + if c == nil || c.clientset == nil { + return + } + + mapInterface := c.clientset.CoreV1().ConfigMaps(c.Namespace) + var cm *corev1.ConfigMap + cm, err = mapInterface.Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{}) + if err != nil && !apierrors.IsNotFound(err) { + return + } + if cm == nil || cm.Data == nil || len(cm.Data[config.KeyEnvoy]) == 0 { + log.Infof("No proxy resources found") + return nil + } + var v = make([]*controlplane.Virtual, 0) + str := cm.Data[config.KeyEnvoy] + if err = yaml.Unmarshal([]byte(str), &v); err != nil { + log.Errorf("Unmarshal envoy config error: %v", err) + return + } + v4, _ := c.GetLocalTunIP() + for _, virtual := range v { + var found bool + for _, rule := range virtual.Rules { + if rule.LocalTunIPv4 == v4 { + found = true + break + } + } + if !found { + continue + } + + // deployments.apps.ry-server --> deployments.apps/ry-server + lastIndex := strings.LastIndex(virtual.Uid, ".") + uid := virtual.Uid[:lastIndex] + "/" + virtual.Uid[lastIndex+1:] + err = inject.UnPatchContainer(c.factory, c.clientset.CoreV1().ConfigMaps(c.Namespace), c.Namespace, uid, v4) + if err != nil { + log.Errorf("Failed to leave workload %s: %v", uid, err) + continue + } + } + return err +} diff --git a/pkg/inject/fargate.go b/pkg/inject/fargate.go index b5449946..057fbd1f 100644 --- a/pkg/inject/fargate.go +++ b/pkg/inject/fargate.go @@ -3,8 +3,10 @@ package inject import ( "context" "fmt" + "net" "net/netip" "strings" + "sync" "time" log "github.com/sirupsen/logrus" @@ -19,6 +21,7 @@ import ( pkgresource "k8s.io/cli-runtime/pkg/resource" runtimeresource "k8s.io/cli-runtime/pkg/resource" "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" cmdutil "k8s.io/kubectl/pkg/cmd/util" "github.com/wencaiwulue/kubevpn/v2/pkg/config" @@ -99,7 +102,7 @@ func InjectEnvoySidecar(ctx context.Context, f cmdutil.Factory, clientset *kuber } // 2) modify service containerPort to envoy listener port - err = modifyServiceTargetPort(ctx, clientset, namespace, labels.SelectorFromSet(templateSpec.Labels).String(), containerPort2EnvoyListenerPort) + err = ModifyServiceTargetPort(ctx, clientset, namespace, labels.SelectorFromSet(templateSpec.Labels).String(), containerPort2EnvoyListenerPort) if err != nil { return err } @@ -108,7 +111,7 @@ func InjectEnvoySidecar(ctx context.Context, f cmdutil.Factory, clientset *kuber return err } -func modifyServiceTargetPort(ctx context.Context, clientset *kubernetes.Clientset, namespace string, labels string, m map[int32]int32) error { +func ModifyServiceTargetPort(ctx context.Context, clientset *kubernetes.Clientset, namespace string, labels string, m map[int32]int32) error { list, err := clientset.CoreV1().Services(namespace).List(ctx, metav1.ListOptions{LabelSelector: labels}) if err != nil { return err @@ -201,3 +204,24 @@ func exposeLocalPortToRemote(ctx context.Context, clientset *kubernetes.Clientse } return nil } + +type Injector struct { + Namespace string + Headers map[string]string + PortMap []string + Workloads []string + Engine config.Engine + Lock *sync.Mutex + + ctx context.Context + cancel context.CancelFunc + + clientset *kubernetes.Clientset + restclient *rest.RESTClient + config *rest.Config + factory cmdutil.Factory + // needs to give it back to dhcp + localTunIPv4 *net.IPNet + localTunIPv6 *net.IPNet + tunName string +}