github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/client/cli/main.go (about)

     1  package cli
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  
     8  	"github.com/spf13/cobra"
     9  
    10  	"github.com/telepresenceio/telepresence/v2/pkg/client"
    11  	"github.com/telepresenceio/telepresence/v2/pkg/client/cli/cmd"
    12  	"github.com/telepresenceio/telepresence/v2/pkg/client/cli/connect"
    13  	"github.com/telepresenceio/telepresence/v2/pkg/client/cli/output"
    14  	"github.com/telepresenceio/telepresence/v2/pkg/client/logging"
    15  	"github.com/telepresenceio/telepresence/v2/pkg/client/rootd"
    16  	"github.com/telepresenceio/telepresence/v2/pkg/client/userd"
    17  	userDaemon "github.com/telepresenceio/telepresence/v2/pkg/client/userd/daemon"
    18  	"github.com/telepresenceio/telepresence/v2/pkg/client/userd/trafficmgr"
    19  	"github.com/telepresenceio/telepresence/v2/pkg/errcat"
    20  	"github.com/telepresenceio/telepresence/v2/pkg/filelocation"
    21  	"github.com/telepresenceio/telepresence/v2/pkg/proc"
    22  )
    23  
    24  func InitContext(ctx context.Context) context.Context {
    25  	env, err := client.LoadEnv()
    26  	if err != nil {
    27  		fmt.Fprintf(os.Stderr, "Failed to load environment: %v", err)
    28  		os.Exit(1)
    29  	}
    30  	ctx = client.WithEnv(ctx, env)
    31  	switch client.ProcessName() {
    32  	case userd.ProcessName:
    33  		if proc.RunningInContainer() {
    34  			client.DisplayName = "OSS Daemon in container"
    35  		} else {
    36  			client.DisplayName = "OSS User Daemon"
    37  		}
    38  		ctx = userd.WithNewServiceFunc(ctx, userDaemon.NewService)
    39  		ctx = userd.WithNewSessionFunc(ctx, trafficmgr.NewSession)
    40  	case rootd.ProcessName:
    41  		client.DisplayName = "OSS Root Daemon"
    42  		ctx = rootd.WithNewServiceFunc(ctx, rootd.NewService)
    43  		ctx = rootd.WithNewSessionFunc(ctx, rootd.NewSession)
    44  	default:
    45  		client.DisplayName = "OSS Client"
    46  		ctx = connect.WithCommandInitializer(ctx, connect.CommandInitializer)
    47  		ctx = cmd.WithSubCommands(ctx)
    48  	}
    49  	if client.IsDaemon() {
    50  		ctx = cmd.WithDaemonSubCommands(ctx)
    51  	} else {
    52  		ctx = cmd.WithSubCommands(ctx)
    53  	}
    54  	return ctx
    55  }
    56  
    57  func Main(ctx context.Context) {
    58  	if dir := os.Getenv("DEV_TELEPRESENCE_CONFIG_DIR"); dir != "" {
    59  		ctx = filelocation.WithAppUserConfigDir(ctx, dir)
    60  	}
    61  	if dir := os.Getenv("DEV_TELEPRESENCE_LOG_DIR"); dir != "" {
    62  		ctx = filelocation.WithAppUserLogDir(ctx, dir)
    63  	}
    64  
    65  	if client.IsDaemon() {
    66  		// Avoid the initialization of all subcommands except for [connector|daemon]-foreground and
    67  		// avoids checks for legacy commands.
    68  		if cmd, _, err := output.Execute(cmd.TelepresenceDaemon(ctx)); err != nil {
    69  			fmt.Fprintf(cmd.ErrOrStderr(), "%s: error: %v\n", cmd.CommandPath(), err)
    70  			os.Exit(1)
    71  		}
    72  	} else {
    73  		if cmd, fmtOutput, err := output.Execute(cmd.Telepresence(ctx)); err != nil {
    74  			if fmtOutput {
    75  				os.Exit(1)
    76  			}
    77  			fmt.Fprintf(cmd.ErrOrStderr(), "%s: error: %v\n", cmd.CommandPath(), err)
    78  			if errcat.GetCategory(err) > errcat.NoDaemonLogs {
    79  				if summarizeLogs(ctx, cmd) {
    80  					// If the user gets here, it might be an actual bug that they found, so
    81  					// point them to the `gather-logs` command in case they want to open an
    82  					// issue.
    83  					fmt.Fprintln(cmd.ErrOrStderr(), "If you think you have encountered a bug"+
    84  						", please run `telepresence gather-logs` and attach the "+
    85  						"telepresence_logs.zip to your github issue or create a new one: "+
    86  						"https://github.com/telepresenceio/telepresence/issues/new?template=Bug_report.md .")
    87  				}
    88  			}
    89  			os.Exit(1)
    90  		}
    91  	}
    92  }
    93  
    94  // summarizeLogs outputs the logs from the root and user daemons. It returns true
    95  // if output were produced, false otherwise (might happen if no logs exist yet).
    96  func summarizeLogs(ctx context.Context, cmd *cobra.Command) bool {
    97  	w := cmd.ErrOrStderr()
    98  	first := true
    99  	for _, proc := range []string{rootd.ProcessName, userd.ProcessName} {
   100  		if summary, err := logging.SummarizeLog(ctx, proc); err != nil {
   101  			fmt.Fprintf(w, "failed to scan %s logs: %v\n", proc, err)
   102  		} else if summary != "" {
   103  			if first {
   104  				fmt.Fprintln(w)
   105  				first = false
   106  			}
   107  			fmt.Fprintln(w, summary)
   108  		}
   109  	}
   110  	return !first
   111  }