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  }