package daemon import ( "context" "errors" "fmt" "io/fs" "isle/bootstrap" "isle/daemon/daecommon" "isle/daemon/network" "os" "path/filepath" "slices" "strings" "sync" ) func getDefaultHTTPSocketDirPath() string { path, err := firstExistingDir( "/tmp", "/run", "/var/run", "/dev/shm", ) if err != nil { panic(fmt.Sprintf("Failed to find directory for HTTP socket: %v", err)) } return path } // HTTPSocketPath returns the path to the daemon's HTTP socket which is used for // RPC and other functionality. var HTTPSocketPath = sync.OnceValue(func() string { return envOr( "ISLE_DAEMON_HTTP_SOCKET_PATH", func() string { return filepath.Join( getDefaultHTTPSocketDirPath(), "isle-daemon.sock", ) }, ) }) func pickNetworkConfig( networkConfigs map[string]daecommon.NetworkConfig, creationParams bootstrap.CreationParams, ) *daecommon.NetworkConfig { if len(networkConfigs) == 1 { // DEPRECATED if c, ok := networkConfigs[daecommon.DeprecatedNetworkID]; ok { return &c } } for searchStr, networkConfig := range networkConfigs { if creationParams.Matches(searchStr) { return &networkConfig } } return nil } func validateConfig( ctx context.Context, networkLoader network.Loader, daemonConfig daecommon.Config, loadableNetworks []bootstrap.CreationParams, ) error { givenConfigs := daemonConfig.Networks daemonConfig.Networks = map[string]daecommon.NetworkConfig{} for _, creationParams := range loadableNetworks { id := creationParams.ID if c := pickNetworkConfig(givenConfigs, creationParams); c != nil { daemonConfig.Networks[id] = *c continue } c, err := networkLoader.StoredConfig(ctx, id) if err != nil { return fmt.Errorf("getting stored config for %q: %w", id, err) } daemonConfig.Networks[id] = c } return daemonConfig.Validate() } //////////////////////////////////////////////////////////////////////////////// // Jigs func envOr(name string, fallback func() string) string { if v := os.Getenv(name); v != "" { return v } return fallback() } func firstExistingDir(paths ...string) (string, error) { var errs []error for _, path := range paths { stat, err := os.Stat(path) switch { case errors.Is(err, fs.ErrExist): continue case err != nil: errs = append( errs, fmt.Errorf("checking if path %q exists: %w", path, err), ) case !stat.IsDir(): errs = append( errs, fmt.Errorf("path %q exists but is not a directory", path), ) default: return path, nil } } err := fmt.Errorf( "no directory found at any of the following paths: %s", strings.Join(paths, ", "), ) if len(errs) > 0 { err = errors.Join(slices.Insert(errs, 0, err)...) } return "", err }