github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/client/cli/connect/daemon.go (about) 1 package connect 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "strconv" 9 "time" 10 11 "google.golang.org/protobuf/types/known/emptypb" 12 13 "github.com/datawire/dlib/dlog" 14 rootDaemon "github.com/telepresenceio/telepresence/rpc/v2/daemon" 15 "github.com/telepresenceio/telepresence/v2/pkg/client" 16 "github.com/telepresenceio/telepresence/v2/pkg/client/cli/daemon" 17 "github.com/telepresenceio/telepresence/v2/pkg/client/cli/output" 18 "github.com/telepresenceio/telepresence/v2/pkg/client/socket" 19 "github.com/telepresenceio/telepresence/v2/pkg/errcat" 20 "github.com/telepresenceio/telepresence/v2/pkg/filelocation" 21 "github.com/telepresenceio/telepresence/v2/pkg/ioutil" 22 "github.com/telepresenceio/telepresence/v2/pkg/proc" 23 ) 24 25 func launchDaemon(ctx context.Context, cr *daemon.Request) error { 26 ioutil.Println(output.Info(ctx), "Launching Telepresence Root Daemon") 27 28 // Ensure that the logfile is present before the daemon starts so that it isn't created with 29 // root permissions. 30 logDir := filelocation.AppUserLogDir(ctx) 31 logFile := filepath.Join(logDir, "daemon.log") 32 if _, err := os.Stat(logFile); err != nil { 33 if !os.IsNotExist(err) { 34 return err 35 } 36 if err = os.MkdirAll(logDir, 0o700); err != nil { 37 return err 38 } 39 fh, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY, 0o600) 40 if err != nil { 41 return err 42 } 43 _ = fh.Close() 44 } 45 46 args := []string{client.GetExe(ctx), "daemon-foreground"} 47 if cr != nil && cr.RootDaemonProfilingPort > 0 { 48 args = append(args, "--pprof", strconv.Itoa(int(cr.RootDaemonProfilingPort))) 49 } 50 if os.Getenv("SCOUT_DISABLE") == "1" { 51 args = append(args, "--disable-metriton") 52 } 53 args = append(args, logDir, filelocation.AppUserConfigDir(ctx)) 54 return proc.StartInBackgroundAsRoot(ctx, args...) 55 } 56 57 // ensureRootDaemonRunning ensures that the daemon is running. 58 func ensureRootDaemonRunning(ctx context.Context) error { 59 cr := daemon.GetRequest(ctx) 60 if cr != nil && cr.Docker { 61 // Never start root daemon when connecting using a docker container. 62 return nil 63 } 64 if addr := client.GetEnv(ctx).UserDaemonAddress; addr != "" { 65 // Always assume that root daemon is running when a user daemon address is provided 66 return nil 67 } 68 running, err := socket.IsRunning(ctx, socket.RootDaemonPath(ctx)) 69 if err != nil || running { 70 return err 71 } 72 if err = launchDaemon(ctx, cr); err != nil { 73 return fmt.Errorf("failed to launch the daemon service: %w", err) 74 } 75 if err = socket.WaitUntilRunning(ctx, "daemon", socket.RootDaemonPath(ctx), 10*time.Second); err != nil { 76 return fmt.Errorf("daemon service did not start: %w", err) 77 } 78 return nil 79 } 80 81 func quitRootDaemon(ctx context.Context) { 82 if conn, err := socket.Dial(ctx, socket.RootDaemonPath(ctx)); err == nil { 83 if _, err = rootDaemon.NewDaemonClient(conn).Quit(ctx, &emptypb.Empty{}); err != nil { 84 dlog.Errorf(ctx, "error when quitting root daemon: %v", err) 85 } 86 } 87 } 88 89 func mkdir(dirType, path string) error { 90 if err := os.MkdirAll(path, 0o700); err != nil { 91 return errcat.NoDaemonLogs.Newf("unable to ensure that %s directory %q exists: %w", dirType, path, err) 92 } 93 return nil 94 } 95 96 func ensureAppUserCacheDirs(ctx context.Context) error { 97 cacheDir := filelocation.AppUserCacheDir(ctx) 98 if err := mkdir("cache", filepath.Join(cacheDir, "daemons")); err != nil { 99 return err 100 } 101 if err := mkdir("cache", filepath.Join(cacheDir, "kube")); err != nil { 102 return err 103 } 104 if err := mkdir("cache", filepath.Join(cacheDir, "sessions")); err != nil { 105 return err 106 } 107 return nil 108 } 109 110 func ensureAppUserConfigDir(ctx context.Context) error { 111 configDir := filelocation.AppUserConfigDir(ctx) 112 if err := mkdir("config", filepath.Join(configDir, "sessions")); err != nil { 113 return err 114 } 115 return nil 116 }