github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/client/cli/cmd/version.go (about) 1 package cmd 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 8 "github.com/spf13/cobra" 9 "google.golang.org/grpc/codes" 10 "google.golang.org/grpc/status" 11 empty "google.golang.org/protobuf/types/known/emptypb" 12 13 "github.com/telepresenceio/telepresence/rpc/v2/common" 14 daemonRpc "github.com/telepresenceio/telepresence/rpc/v2/daemon" 15 "github.com/telepresenceio/telepresence/rpc/v2/manager" 16 "github.com/telepresenceio/telepresence/v2/pkg/client" 17 "github.com/telepresenceio/telepresence/v2/pkg/client/cli/ann" 18 "github.com/telepresenceio/telepresence/v2/pkg/client/cli/connect" 19 "github.com/telepresenceio/telepresence/v2/pkg/client/cli/daemon" 20 "github.com/telepresenceio/telepresence/v2/pkg/client/socket" 21 "github.com/telepresenceio/telepresence/v2/pkg/ioutil" 22 ) 23 24 func version() *cobra.Command { 25 return &cobra.Command{ 26 Use: "version", 27 Args: cobra.NoArgs, 28 29 Short: "Show version", 30 RunE: printVersion, 31 Annotations: map[string]string{ 32 ann.UserDaemon: ann.Optional, 33 ann.UpdateCheckFormat: ann.Tel2, 34 }, 35 } 36 } 37 38 func addDaemonVersions(ctx context.Context, kvf *ioutil.KeyValueFormatter) { 39 remote := false 40 userD := daemon.GetUserClient(ctx) 41 if userD != nil { 42 remote = userD.Containerized() 43 } 44 45 if !remote { 46 version, err := daemonVersion(ctx) 47 switch { 48 case err == nil: 49 kvf.Add(version.Name, version.Version) 50 case err == connect.ErrNoRootDaemon: 51 kvf.Add("Root Daemon", "not running") 52 default: 53 kvf.Add("Root Daemon", fmt.Sprintf("error: %v", err)) 54 } 55 } 56 57 if userD != nil { 58 vi, err := userD.Version(ctx, &empty.Empty{}) 59 if err == nil { 60 kvf.Add(vi.Name, vi.Version) 61 vi, err = managerVersion(ctx) 62 switch { 63 case err == nil: 64 kvf.Add(vi.Name, vi.Version) 65 af, err := trafficAgentFQN(ctx) 66 switch status.Code(err) { 67 case codes.OK: 68 kvf.Add("Traffic Agent", af.FQN) 69 case codes.Unimplemented: 70 kvf.Add("Traffic Agent", "not reported by traffic-manager") 71 case codes.Unavailable: 72 kvf.Add("Traffic Agent", "not currently available") 73 default: 74 kvf.Add("Traffic Agent", fmt.Sprintf("error: %v", err)) 75 } 76 case status.Code(err) == codes.Unavailable: 77 kvf.Add("Traffic Manager", "not connected") 78 default: 79 kvf.Add("Traffic Manager", fmt.Sprintf("error: %v", err)) 80 } 81 } else { 82 kvf.Add("User Daemon", fmt.Sprintf("error: %v", err)) 83 } 84 } else { 85 kvf.Add("User Daemon", "not running") 86 } 87 } 88 89 func printVersion(cmd *cobra.Command, _ []string) error { 90 kvf := ioutil.DefaultKeyValueFormatter() 91 kvf.Add(client.DisplayName, client.Version()) 92 93 var mdErr daemon.MultipleDaemonsError 94 err := connect.InitCommand(cmd) 95 if err != nil { 96 if !errors.As(err, &mdErr) { 97 return err 98 } 99 } 100 ctx := cmd.Context() 101 102 if len(mdErr) > 0 { 103 for _, info := range mdErr { 104 subKvf := &ioutil.KeyValueFormatter{ 105 Indent: kvf.Indent, 106 Separator: kvf.Separator, 107 } 108 ud, err := connect.ExistingDaemon(ctx, info) 109 if err != nil { 110 subKvf.Add("User Daemon", fmt.Sprintf("error: %v", err)) 111 } 112 addDaemonVersions(daemon.WithUserClient(ctx, ud), subKvf) 113 kvf.Add("Connection "+ud.DaemonID.Name, "\n"+subKvf.String()) 114 ud.Conn.Close() 115 } 116 } else { 117 addDaemonVersions(ctx, kvf) 118 } 119 120 kvf.Println(cmd.OutOrStdout()) 121 return nil 122 } 123 124 func daemonVersion(ctx context.Context) (*common.VersionInfo, error) { 125 if conn, err := socket.Dial(ctx, socket.RootDaemonPath(ctx)); err == nil { 126 defer conn.Close() 127 return daemonRpc.NewDaemonClient(conn).Version(ctx, &empty.Empty{}) 128 } 129 return nil, connect.ErrNoRootDaemon 130 } 131 132 func managerVersion(ctx context.Context) (*common.VersionInfo, error) { 133 if userD := daemon.GetUserClient(ctx); userD != nil { 134 return userD.TrafficManagerVersion(ctx, &empty.Empty{}) 135 } 136 return nil, connect.ErrNoUserDaemon 137 } 138 139 func trafficAgentFQN(ctx context.Context) (*manager.AgentImageFQN, error) { 140 if userD := daemon.GetUserClient(ctx); userD != nil { 141 return userD.AgentImageFQN(ctx, &empty.Empty{}) 142 } 143 return nil, connect.ErrNoUserDaemon 144 }