Simplify socket file path selection, only use /tmp

This commit is contained in:
Brian Picciano 2024-12-16 14:59:11 +01:00
parent 4151fe8f17
commit 73af69fa04
15 changed files with 232 additions and 167 deletions

View File

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"io/fs" "io/fs"
"isle/daemon" "isle/daemon"
"isle/toolkit"
"net" "net"
"net/http" "net/http"
"os" "os"
@ -14,14 +15,25 @@ import (
"dev.mediocregopher.com/mediocre-go-lib.git/mlog" "dev.mediocregopher.com/mediocre-go-lib.git/mlog"
) )
const daemonHTTPRPCPath = "/rpc/v0.json" const (
daemonHTTPSocketDefaultPath = "/tmp/isle-daemon.sock"
daemonHTTPSocketPathEnvVar = "ISLE_DAEMON_HTTP_SOCKET_PATH"
daemonHTTPRPCPath = "/rpc/v0.json"
)
func httpSocketPath() string {
return toolkit.EnvOr(
daemonHTTPSocketPathEnvVar,
func() string { return daemonHTTPSocketDefaultPath },
)
}
func newHTTPServer( func newHTTPServer(
ctx context.Context, logger *mlog.Logger, daemonInst *daemon.Daemon, ctx context.Context, logger *mlog.Logger, daemonInst *daemon.Daemon,
) ( ) (
*http.Server, error, *http.Server, error,
) { ) {
socketPath := daemon.HTTPSocketPath() socketPath := httpSocketPath()
ctx = mctx.Annotate(ctx, "socketPath", socketPath) ctx = mctx.Annotate(ctx, "socketPath", socketPath)
if err := os.Remove(socketPath); errors.Is(err, fs.ErrNotExist) { if err := os.Remove(socketPath); errors.Is(err, fs.ErrNotExist) {

View File

@ -52,7 +52,13 @@ var subCmdGarageMC = subCmd{
return fmt.Errorf("parsing flags: %w", err) return fmt.Errorf("parsing flags: %w", err)
} }
clientParams, err := ctx.daemonRPC.GetGarageClientParams(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
clientParams, err := daemonRPC.GetGarageClientParams(ctx)
if err != nil { if err != nil {
return fmt.Errorf("calling GetGarageClientParams: %w", err) return fmt.Errorf("calling GetGarageClientParams: %w", err)
} }
@ -124,7 +130,13 @@ var subCmdGarageCLI = subCmd{
return fmt.Errorf("parsing flags: %w", err) return fmt.Errorf("parsing flags: %w", err)
} }
clientParams, err := ctx.daemonRPC.GetGarageClientParams(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
clientParams, err := daemonRPC.GetGarageClientParams(ctx)
if err != nil { if err != nil {
return fmt.Errorf("calling GetGarageClientParams: %w", err) return fmt.Errorf("calling GetGarageClientParams: %w", err)
} }

View File

@ -40,7 +40,13 @@ var subCmdHostCreate = subCmd{
return errors.New("--hostname is required") return errors.New("--hostname is required")
} }
res, err := ctx.daemonRPC.CreateHost( daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
res, err := daemonRPC.CreateHost(
ctx, hostName.V, network.CreateHostOpts{ ctx, hostName.V, network.CreateHostOpts{
IP: ip.V, IP: ip.V,
CanCreateHosts: *canCreateHosts, CanCreateHosts: *canCreateHosts,
@ -63,7 +69,13 @@ var subCmdHostList = subCmd{
return nil, fmt.Errorf("parsing flags: %w", err) return nil, fmt.Errorf("parsing flags: %w", err)
} }
currBoostrap, err := ctx.daemonRPC.GetBootstrap(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return nil, fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
currBoostrap, err := daemonRPC.GetBootstrap(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("calling GetBootstrap: %w", err) return nil, fmt.Errorf("calling GetBootstrap: %w", err)
} }
@ -131,7 +143,13 @@ var subCmdHostRemove = subCmd{
return errors.New("--hostname is required") return errors.New("--hostname is required")
} }
if err := ctx.daemonRPC.RemoveHost(ctx, hostName.V); err != nil { daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
if err := daemonRPC.RemoveHost(ctx, hostName.V); err != nil {
return fmt.Errorf("calling RemoveHost: %w", err) return fmt.Errorf("calling RemoveHost: %w", err)
} }

View File

@ -3,8 +3,6 @@ package main
import ( import (
"context" "context"
"fmt" "fmt"
"isle/daemon"
"isle/daemon/jsonrpc2"
"isle/toolkit" "isle/toolkit"
"os" "os"
"os/signal" "os/signal"
@ -66,10 +64,9 @@ var rootCmd = subCmd{
func doRootCmd( func doRootCmd(
ctx context.Context, ctx context.Context,
logger *mlog.Logger, logger *mlog.Logger,
daemonRPC daemon.RPC,
opts *subCmdCtxOpts, opts *subCmdCtxOpts,
) error { ) error {
subCmdCtx := newSubCmdCtx(ctx, logger, daemonRPC, rootCmd, opts) subCmdCtx := newSubCmdCtx(ctx, logger, rootCmd, opts)
return subCmdCtx.subCmd.do(subCmdCtx) return subCmdCtx.subCmd.do(subCmdCtx)
} }
@ -95,19 +92,7 @@ func main() {
logger.FatalString(ctx, "second signal received, force quitting, there may be zombie children left behind, good luck!") logger.FatalString(ctx, "second signal received, force quitting, there may be zombie children left behind, good luck!")
}() }()
httpClient, baseURL := toolkit.NewUnixHTTPClient( if err := doRootCmd(ctx, logger, nil); err != nil {
logger.WithNamespace("http-client"),
daemon.HTTPSocketPath(),
)
defer httpClient.Close()
baseURL.Path = daemonHTTPRPCPath
daemonRPC := daemon.RPCFromClient(
jsonrpc2.NewHTTPClient(httpClient, baseURL.String()),
)
if err := doRootCmd(ctx, logger, daemonRPC, nil); err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
} }
} }

View File

@ -58,10 +58,11 @@ func (h *runHarness) run(t *testing.T, args ...string) error {
jsonrpc2.NewHTTPClient(httpClient, h.daemonRPCServer.URL), jsonrpc2.NewHTTPClient(httpClient, h.daemonRPCServer.URL),
) )
return doRootCmd(h.ctx, h.logger, daemonRPCClient, &subCmdCtxOpts{ return doRootCmd(h.ctx, h.logger, &subCmdCtxOpts{
args: args, args: args,
stdout: h.stdout, stdout: h.stdout,
changeStager: h.changeStager, changeStager: h.changeStager,
daemonRPC: daemonRPCClient,
}) })
} }

View File

@ -58,7 +58,13 @@ var subCmdNetworkCreate = subCmd{
return errors.New("--name, --domain, --ip-net, and --hostname are required") return errors.New("--name, --domain, --ip-net, and --hostname are required")
} }
err = ctx.daemonRPC.CreateNetwork( daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
err = daemonRPC.CreateNetwork(
ctx, *name, *domain, ipNet.V, hostName.V, ctx, *name, *domain, ipNet.V, hostName.V,
) )
if err != nil { if err != nil {
@ -95,7 +101,13 @@ var subCmdNetworkJoin = subCmd{
) )
} }
return ctx.daemonRPC.JoinNetwork(ctx, newBootstrap) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
return daemonRPC.JoinNetwork(ctx, newBootstrap)
}, },
} }
@ -110,7 +122,13 @@ var subCmdNetworkList = subCmd{
return nil, fmt.Errorf("parsing flags: %w", err) return nil, fmt.Errorf("parsing flags: %w", err)
} }
networkCreationParams, err := ctx.daemonRPC.GetNetworks(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return nil, fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
networkCreationParams, err := daemonRPC.GetNetworks(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("calling GetNetworks: %w", err) return nil, fmt.Errorf("calling GetNetworks: %w", err)
} }
@ -127,10 +145,7 @@ var subCmdNetworkList = subCmd{
Lighthouses []lighthouseView `yaml:"lighthouses"` Lighthouses []lighthouseView `yaml:"lighthouses"`
} }
var ( networkViews := make([]networkView, len(networkCreationParams))
daemonRPC = ctx.daemonRPC
networkViews = make([]networkView, len(networkCreationParams))
)
for i, creationParams := range networkCreationParams { for i, creationParams := range networkCreationParams {
ctx := daemon.WithNetwork(ctx, creationParams.ID) ctx := daemon.WithNetwork(ctx, creationParams.ID)
@ -191,7 +206,13 @@ var subCmdNetworkGetConfig = subCmd{
return nil, fmt.Errorf("parsing flags: %w", err) return nil, fmt.Errorf("parsing flags: %w", err)
} }
return ctx.daemonRPC.GetConfig(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return nil, fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
return daemonRPC.GetConfig(ctx)
}), }),
} }

View File

@ -98,14 +98,20 @@ var subCmdStorageAllocationAdd = subCmd{
) )
} }
config, err := ctx.daemonRPC.GetConfig(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
config, err := daemonRPC.GetConfig(ctx)
if err != nil { if err != nil {
return fmt.Errorf("getting network config: %w", err) return fmt.Errorf("getting network config: %w", err)
} }
config.Storage.Allocations = append(config.Storage.Allocations, alloc) config.Storage.Allocations = append(config.Storage.Allocations, alloc)
if err := ctx.daemonRPC.SetConfig(ctx, config); err != nil { if err := daemonRPC.SetConfig(ctx, config); err != nil {
return fmt.Errorf("updating the network config: %w", err) return fmt.Errorf("updating the network config: %w", err)
} }
@ -122,7 +128,13 @@ var subCmdStorageAllocationList = subCmd{
return nil, fmt.Errorf("parsing flags: %w", err) return nil, fmt.Errorf("parsing flags: %w", err)
} }
config, err := ctx.daemonRPC.GetConfig(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return nil, fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
config, err := daemonRPC.GetConfig(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("getting network config: %w", err) return nil, fmt.Errorf("getting network config: %w", err)
} }
@ -152,7 +164,13 @@ var subCmdStorageAllocationRemove = subCmd{
return errors.New("At least one --index must be specified") return errors.New("At least one --index must be specified")
} }
config, err := ctx.daemonRPC.GetConfig(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
config, err := daemonRPC.GetConfig(ctx)
if err != nil { if err != nil {
return fmt.Errorf("getting network config: %w", err) return fmt.Errorf("getting network config: %w", err)
} }
@ -186,7 +204,7 @@ var subCmdStorageAllocationRemove = subCmd{
) )
config.Storage.Allocations = newAllocs config.Storage.Allocations = newAllocs
if err := ctx.daemonRPC.SetConfig(ctx, config); err != nil { if err := daemonRPC.SetConfig(ctx, config); err != nil {
return fmt.Errorf("updating the network config: %w", err) return fmt.Errorf("updating the network config: %w", err)
} }

View File

@ -6,7 +6,9 @@ import (
"fmt" "fmt"
"io" "io"
"isle/daemon" "isle/daemon"
"isle/daemon/jsonrpc2"
"isle/jsonutil" "isle/jsonutil"
"isle/toolkit"
"os" "os"
"strings" "strings"
@ -37,6 +39,7 @@ type subCmdCtxOpts struct {
subCmdNames []string // names of subCmds so far, including this one subCmdNames []string // names of subCmds so far, including this one
stdout io.Writer stdout io.Writer
changeStager *changeStager changeStager *changeStager
daemonRPC daemon.RPC
} }
func (o *subCmdCtxOpts) withDefaults() *subCmdCtxOpts { func (o *subCmdCtxOpts) withDefaults() *subCmdCtxOpts {
@ -58,10 +61,9 @@ func (o *subCmdCtxOpts) withDefaults() *subCmdCtxOpts {
// subCmdCtx contains all information available to a subCmd's do method. // subCmdCtx contains all information available to a subCmd's do method.
type subCmdCtx struct { type subCmdCtx struct {
context.Context context.Context
logger *mlog.Logger logger *mlog.Logger
daemonRPC daemon.RPC subCmd subCmd // the subCmd itself
subCmd subCmd // the subCmd itself opts *subCmdCtxOpts
opts *subCmdCtxOpts
flags *pflag.FlagSet flags *pflag.FlagSet
} }
@ -69,22 +71,55 @@ type subCmdCtx struct {
func newSubCmdCtx( func newSubCmdCtx(
ctx context.Context, ctx context.Context,
logger *mlog.Logger, logger *mlog.Logger,
daemonRPC daemon.RPC,
subCmd subCmd, subCmd subCmd,
opts *subCmdCtxOpts, opts *subCmdCtxOpts,
) subCmdCtx { ) subCmdCtx {
opts = opts.withDefaults() opts = opts.withDefaults()
return subCmdCtx{ return subCmdCtx{
Context: ctx, Context: ctx,
logger: logger, logger: logger,
daemonRPC: daemonRPC, subCmd: subCmd,
subCmd: subCmd, opts: opts,
opts: opts, flags: pflag.NewFlagSet(subCmd.name, pflag.ExitOnError),
flags: pflag.NewFlagSet(subCmd.name, pflag.ExitOnError),
} }
} }
type daemonRPCCloser struct {
daemon.RPC
Close func() error
}
func (ctx subCmdCtx) newDaemonRPC() (*daemonRPCCloser, error) {
if ctx.opts.daemonRPC != nil {
return &daemonRPCCloser{
ctx.opts.daemonRPC, func() error { return nil },
}, nil
}
socketPath := httpSocketPath()
if stat, err := os.Stat(socketPath); err != nil {
return nil, fmt.Errorf("checking http socket file: %w", err)
} else if stat.Mode().Type() != os.ModeSocket {
return nil, fmt.Errorf("%q exists but is not a socket", socketPath)
}
httpClient, baseURL := toolkit.NewUnixHTTPClient(
ctx.logger.WithNamespace("http-client"),
socketPath,
)
baseURL.Path = daemonHTTPRPCPath
daemonRPC := daemon.RPCFromClient(
jsonrpc2.NewHTTPClient(httpClient, baseURL.String()),
)
return &daemonRPCCloser{
daemonRPC, func() error { return httpClient.Close() },
}, nil
}
func (ctx subCmdCtx) getChangeStager() *changeStager { func (ctx subCmdCtx) getChangeStager() *changeStager {
if ctx.opts.changeStager != nil { if ctx.opts.changeStager != nil {
return ctx.opts.changeStager return ctx.opts.changeStager
@ -258,7 +293,7 @@ func (ctx subCmdCtx) doSubCmd(subCmds ...subCmd) error {
nextSubCmdCtxOpts.subCmdNames = append(ctx.opts.subCmdNames, subCmdName) nextSubCmdCtxOpts.subCmdNames = append(ctx.opts.subCmdNames, subCmdName)
nextSubCmdCtx := newSubCmdCtx( nextSubCmdCtx := newSubCmdCtx(
ctx.Context, ctx.logger, ctx.daemonRPC, subCmd, &nextSubCmdCtxOpts, ctx.Context, ctx.logger, subCmd, &nextSubCmdCtxOpts,
) )
if err := subCmd.do(nextSubCmdCtx); err != nil { if err := subCmd.do(nextSubCmdCtx); err != nil {

View File

@ -43,7 +43,13 @@ var subCmdVPNCreateCert = subCmd{
return fmt.Errorf("unmarshaling public key as PEM: %w", err) return fmt.Errorf("unmarshaling public key as PEM: %w", err)
} }
res, err := ctx.daemonRPC.CreateNebulaCertificate( daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
res, err := daemonRPC.CreateNebulaCertificate(
ctx, hostName.V, hostPub, ctx, hostName.V, hostPub,
) )
if err != nil { if err != nil {

View File

@ -3,6 +3,7 @@ package main
import ( import (
"errors" "errors"
"fmt" "fmt"
"isle/daemon"
"isle/daemon/daecommon" "isle/daemon/daecommon"
"slices" "slices"
"strings" "strings"
@ -14,8 +15,12 @@ const vpnFirewallConfigChangeStagerName = "vpn-firewall-config"
// vpnFirewallGetConfigWithStaged returns the network config along with any // vpnFirewallGetConfigWithStaged returns the network config along with any
// staged firewall configuration changes, if there are any. // staged firewall configuration changes, if there are any.
func vpnFirewallGetConfig(ctx subCmdCtx) (daecommon.NetworkConfig, error) { func vpnFirewallGetConfig(
config, err := ctx.daemonRPC.GetConfig(ctx) ctx subCmdCtx, daemonRPC daemon.RPC,
) (
daecommon.NetworkConfig, error,
) {
config, err := daemonRPC.GetConfig(ctx)
if err != nil { if err != nil {
return daecommon.NetworkConfig{}, err return daecommon.NetworkConfig{}, err
} }
@ -110,7 +115,13 @@ var subCmdVPNFirewallAdd = subCmd{
rule.Host = "any" rule.Host = "any"
} }
config, err := vpnFirewallGetConfig(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
config, err := vpnFirewallGetConfig(ctx, daemonRPC)
if err != nil { if err != nil {
return fmt.Errorf("getting network config: %w", err) return fmt.Errorf("getting network config: %w", err)
} }
@ -151,14 +162,20 @@ var subCmdVPNFirewallCommit = subCmd{
return errors.New("no changes staged, use 'add' or 'remove' to stage changes") return errors.New("no changes staged, use 'add' or 'remove' to stage changes")
} }
config, err := ctx.daemonRPC.GetConfig(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
config, err := daemonRPC.GetConfig(ctx)
if err != nil { if err != nil {
return fmt.Errorf("getting network config: %w", err) return fmt.Errorf("getting network config: %w", err)
} }
config.VPN.Firewall = firewallConfig config.VPN.Firewall = firewallConfig
return ctx.daemonRPC.SetConfig(ctx, config) return daemonRPC.SetConfig(ctx, config)
}, },
} }
@ -192,6 +209,12 @@ var subCmdVPNFirewallRemove = subCmd{
return fmt.Errorf("invalid --from value %q: %w", *from, err) return fmt.Errorf("invalid --from value %q: %w", *from, err)
} }
daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
indexSet := map[int]struct{}{} indexSet := map[int]struct{}{}
for _, index := range *indexes { for _, index := range *indexes {
if index < 0 { if index < 0 {
@ -200,7 +223,7 @@ var subCmdVPNFirewallRemove = subCmd{
indexSet[index] = struct{}{} indexSet[index] = struct{}{}
} }
config, err := vpnFirewallGetConfig(ctx) config, err := vpnFirewallGetConfig(ctx, daemonRPC)
if err != nil { if err != nil {
return fmt.Errorf("getting network config: %w", err) return fmt.Errorf("getting network config: %w", err)
} }
@ -309,7 +332,13 @@ var subCmdVPNFirewallShow = subCmd{
} }
if !foundStaged { if !foundStaged {
config, err := ctx.daemonRPC.GetConfig(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return nil, fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
config, err := daemonRPC.GetConfig(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("getting network config: %w", err) return nil, fmt.Errorf("getting network config: %w", err)
} }

View File

@ -15,7 +15,13 @@ var subCmdVPNPublicAddressGet = subCmd{
return nil, fmt.Errorf("parsing flags: %w", err) return nil, fmt.Errorf("parsing flags: %w", err)
} }
config, err := ctx.daemonRPC.GetConfig(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return nil, fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
config, err := daemonRPC.GetConfig(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("getting network config: %w", err) return nil, fmt.Errorf("getting network config: %w", err)
} }
@ -49,14 +55,20 @@ var subCmdVPNPublicAddressSet = subCmd{
return fmt.Errorf("invalid --public-addr: %w", err) return fmt.Errorf("invalid --public-addr: %w", err)
} }
config, err := ctx.daemonRPC.GetConfig(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
config, err := daemonRPC.GetConfig(ctx)
if err != nil { if err != nil {
return fmt.Errorf("getting network config: %w", err) return fmt.Errorf("getting network config: %w", err)
} }
config.VPN.PublicAddr = *publicAddr config.VPN.PublicAddr = *publicAddr
return ctx.daemonRPC.SetConfig(ctx, config) return daemonRPC.SetConfig(ctx, config)
}, },
} }
@ -69,14 +81,20 @@ var subCmdVPNPublicAddressUnset = subCmd{
return fmt.Errorf("parsing flags: %w", err) return fmt.Errorf("parsing flags: %w", err)
} }
config, err := ctx.daemonRPC.GetConfig(ctx) daemonRPC, err := ctx.newDaemonRPC()
if err != nil {
return fmt.Errorf("creating daemon RPC client: %w", err)
}
defer daemonRPC.Close()
config, err := daemonRPC.GetConfig(ctx)
if err != nil { if err != nil {
return fmt.Errorf("getting network config: %w", err) return fmt.Errorf("getting network config: %w", err)
} }
config.VPN.PublicAddr = "" config.VPN.PublicAddr = ""
return ctx.daemonRPC.SetConfig(ctx, config) return daemonRPC.SetConfig(ctx, config)
}, },
} }

View File

@ -2,46 +2,12 @@ package daemon
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"io/fs"
"isle/bootstrap" "isle/bootstrap"
"isle/daemon/daecommon" "isle/daemon/daecommon"
"isle/daemon/network" "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( func pickNetworkConfig(
networkConfigs map[string]daecommon.NetworkConfig, networkConfigs map[string]daecommon.NetworkConfig,
creationParams bootstrap.CreationParams, creationParams bootstrap.CreationParams,
@ -88,43 +54,3 @@ func validateConfig(
return daemonConfig.Validate() 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
}

View File

@ -2,7 +2,6 @@ package daecommon
import ( import (
"isle/toolkit" "isle/toolkit"
"os"
"path/filepath" "path/filepath"
"sync" "sync"
@ -25,12 +24,12 @@ var GetEnvVars = sync.OnceValue(func() EnvVars {
var ( var (
res EnvVars res EnvVars
stateDirPath = envOr( stateDirPath = toolkit.EnvOr(
"STATE_DIRECTORY", "STATE_DIRECTORY",
func() string { return filepath.Join(xdg.StateHome, "isle") }, func() string { return filepath.Join(xdg.StateHome, "isle") },
) )
runtimeDirPath = envOr( runtimeDirPath = toolkit.EnvOr(
"RUNTIME_DIRECTORY", "RUNTIME_DIRECTORY",
func() string { return filepath.Join(xdg.RuntimeDir, "isle") }, func() string { return filepath.Join(xdg.RuntimeDir, "isle") },
) )
@ -46,13 +45,3 @@ var GetEnvVars = sync.OnceValue(func() EnvVars {
return res return res
}) })
////////////////////////////////////////////////////////////////////////////////
// Jigs
func envOr(name string, fallback func() string) string {
if v := os.Getenv(name); v != "" {
return v
}
return fallback()
}

12
go/toolkit/env.go Normal file
View File

@ -0,0 +1,12 @@
package toolkit
import "os"
// EnvOr returns the value of the given environment variable, or the return of
// the given callback if the environment variable isn't set.
func EnvOr(name string, fallback func() string) string {
if v := os.Getenv(name); v != "" {
return v
}
return fallback()
}

View File

@ -1,17 +0,0 @@
---
type: task
---
# Audit HTTP Socket Directory Search Options
We are currently searching these directories for the first writeable one, within
which to create the socket file:
- /tmp
- /run
- /var/run
- /dev/shm
It would be ideal to not default to `/tmp`, but it seems that some of the others
aren't necessarily available always, or aren't readable/writeable by the `isle`
user.