Compare commits

...

2 Commits

10 changed files with 57 additions and 204 deletions

View File

@ -44,7 +44,6 @@ func readAdmin(path string) (admin.Admin, error) {
var subCmdAdminCreateBootstrap = subCmd{ var subCmdAdminCreateBootstrap = subCmd{
name: "create-bootstrap", name: "create-bootstrap",
descr: "Creates a new bootstrap.json file for a particular host and writes it to stdout", descr: "Creates a new bootstrap.json file for a particular host and writes it to stdout",
checkLock: false,
do: func(subCmdCtx subCmdCtx) error { do: func(subCmdCtx subCmdCtx) error {
var ( var (
flags = subCmdCtx.flagSet(false) flags = subCmdCtx.flagSet(false)
@ -115,7 +114,6 @@ var subCmdAdminCreateBootstrap = subCmd{
var subCmdAdminCreateNebulaCert = subCmd{ var subCmdAdminCreateNebulaCert = subCmd{
name: "create-nebula-cert", name: "create-nebula-cert",
descr: "Creates a signed nebula certificate file and writes it to stdout", descr: "Creates a signed nebula certificate file and writes it to stdout",
checkLock: false,
do: func(subCmdCtx subCmdCtx) error { do: func(subCmdCtx subCmdCtx) error {
var ( var (
flags = subCmdCtx.flagSet(false) flags = subCmdCtx.flagSet(false)

View File

@ -1,26 +0,0 @@
package main
import (
"errors"
"fmt"
"io/fs"
"isle/bootstrap"
)
func loadHostBootstrap() (bootstrap.Bootstrap, error) {
stateDirPath := bootstrap.StateDirPath(daemonEnvVars.StateDirPath)
hostBootstrap, err := bootstrap.FromFile(stateDirPath)
if errors.Is(err, fs.ErrNotExist) {
return bootstrap.Bootstrap{}, fmt.Errorf(
"%q not found, has the daemon ever been run?",
stateDirPath,
)
} else if err != nil {
return bootstrap.Bootstrap{}, fmt.Errorf("loading %q: %w", stateDirPath, err)
}
return hostBootstrap, nil
}

View File

@ -49,12 +49,6 @@ var subCmdDaemon = subCmd{
logger := subCmdCtx.logger.WithMaxLevel(logLevel.Int()) logger := subCmdCtx.logger.WithMaxLevel(logLevel.Int())
runtimeDirCleanup, err := setupAndLockRuntimeDir(ctx, logger)
if err != nil {
return fmt.Errorf("setting up runtime directory: %w", err)
}
defer runtimeDirCleanup()
daemonConfig, err := daemon.LoadConfig(envAppDirPath, *daemonConfigPath) daemonConfig, err := daemon.LoadConfig(envAppDirPath, *daemonConfigPath)
if err != nil { if err != nil {
return fmt.Errorf("loading daemon config: %w", err) return fmt.Errorf("loading daemon config: %w", err)

View File

@ -34,7 +34,6 @@ func initMCConfigDir() (string, error) {
var subCmdGarageMC = subCmd{ var subCmdGarageMC = subCmd{
name: "mc", name: "mc",
descr: "Runs the mc (minio-client) binary. The isle garage can be accessed under the `garage` alias", descr: "Runs the mc (minio-client) binary. The isle garage can be accessed under the `garage` alias",
checkLock: true,
do: func(subCmdCtx subCmdCtx) error { do: func(subCmdCtx subCmdCtx) error {
flags := subCmdCtx.flagSet(true) flags := subCmdCtx.flagSet(true)
@ -118,7 +117,6 @@ var subCmdGarageMC = subCmd{
var subCmdGarageCLI = subCmd{ var subCmdGarageCLI = subCmd{
name: "cli", name: "cli",
descr: "Runs the garage binary, automatically configured to point to the garage sub-process of a running isle daemon", descr: "Runs the garage binary, automatically configured to point to the garage sub-process of a running isle daemon",
checkLock: true,
do: func(subCmdCtx subCmdCtx) error { do: func(subCmdCtx subCmdCtx) error {
var clientParams bootstrap.GarageClientParams var clientParams bootstrap.GarageClientParams

View File

@ -48,7 +48,6 @@ var subCmdHostsList = subCmd{
var subCmdHostsDelete = subCmd{ var subCmdHostsDelete = subCmd{
name: "delete", name: "delete",
descr: "Deletes a host from the network", descr: "Deletes a host from the network",
checkLock: true,
do: func(subCmdCtx subCmdCtx) error { do: func(subCmdCtx subCmdCtx) error {
flags := subCmdCtx.flagSet(false) flags := subCmdCtx.flagSet(false)

View File

@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"isle/jsonutil" "isle/jsonutil"
"isle/nebula"
"os" "os"
) )
@ -16,12 +17,20 @@ var subCmdNebulaShow = subCmd{
return fmt.Errorf("parsing flags: %w", err) return fmt.Errorf("parsing flags: %w", err)
} }
hostBootstrap, err := loadHostBootstrap() hosts, err := subCmdCtx.getHosts()
if err != nil { if err != nil {
return fmt.Errorf("loading host bootstrap: %w", err) return fmt.Errorf("getting hosts: %w", err)
} }
caCert := hostBootstrap.CAPublicCredentials.Cert.Unwrap() var caPublicCreds nebula.CAPublicCredentials
err = subCmdCtx.daemonRCPClient.Call(
subCmdCtx.ctx, &caPublicCreds, "GetNebulaCAPublicCredentials", nil,
)
if err != nil {
return fmt.Errorf("calling GetNebulaCAPublicCredentials: %w", err)
}
caCert := caPublicCreds.Cert.Unwrap()
caCertPEM, err := caCert.MarshalToPEM() caCertPEM, err := caCert.MarshalToPEM()
if err != nil { if err != nil {
return fmt.Errorf("marshaling CA cert to PEM: %w", err) return fmt.Errorf("marshaling CA cert to PEM: %w", err)
@ -50,7 +59,7 @@ var subCmdNebulaShow = subCmd{
SubnetCIDR: subnet.String(), SubnetCIDR: subnet.String(),
} }
for _, h := range hostBootstrap.Hosts { for _, h := range hosts.Hosts {
if h.Nebula.PublicAddr == "" { if h.Nebula.PublicAddr == "" {
continue continue
} }

View File

@ -1,103 +0,0 @@
package main
import (
"context"
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"dev.mediocregopher.com/mediocre-go-lib.git/mctx"
"dev.mediocregopher.com/mediocre-go-lib.git/mlog"
"github.com/shirou/gopsutil/process"
)
var errDaemonNotRunning = errors.New("no isle daemon process running")
func lockFilePath() string {
return filepath.Join(daemonEnvVars.RuntimeDirPath, "lock")
}
func writeLock() error {
lockFilePath := lockFilePath()
lockFile, err := os.OpenFile(
lockFilePath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0400,
)
if errors.Is(err, os.ErrExist) {
return fmt.Errorf(
"lock file %q already exists, if the isle daemon is not already running you can safely delete this file",
lockFilePath,
)
} else if err != nil {
return fmt.Errorf("opening lockfile %q: %w", lockFilePath, err)
}
defer lockFile.Close()
if _, err := fmt.Fprintf(lockFile, "%d\n", os.Getpid()); err != nil {
return fmt.Errorf("writing pid to %q: %w", lockFilePath, err)
}
return nil
}
// returns a cleanup function which will clean up the created runtime directory.
func setupAndLockRuntimeDir(ctx context.Context, logger *mlog.Logger) (func(), error) {
ctx = mctx.Annotate(ctx, "runtimeDirPath", daemonEnvVars.RuntimeDirPath)
logger.Info(ctx, "will use runtime directory for temporary state")
if err := os.MkdirAll(daemonEnvVars.RuntimeDirPath, 0700); err != nil {
return nil, fmt.Errorf("creating directory %q: %w", daemonEnvVars.RuntimeDirPath, err)
} else if err := writeLock(); err != nil {
return nil, err
}
return func() {
logger.Info(ctx, "cleaning up runtime directory")
if err := os.RemoveAll(daemonEnvVars.RuntimeDirPath); err != nil {
logger.Error(ctx, "removing temporary directory", err)
}
}, nil
}
// checks that the lock file exists and that the process which created it also
// still exists.
func assertLock() error {
lockFilePath := lockFilePath()
lockFile, err := os.Open(lockFilePath)
if errors.Is(err, fs.ErrNotExist) {
return errDaemonNotRunning
} else if err != nil {
return fmt.Errorf("checking lock file %q: %w", lockFilePath, err)
}
defer lockFile.Close()
var pid int32
if _, err := fmt.Fscan(lockFile, &pid); err != nil {
return fmt.Errorf("scanning pid from lock file %q: %w", lockFilePath, err)
}
procExists, err := process.PidExists(pid)
if err != nil {
return fmt.Errorf("checking if process %d exists: %w", pid, err)
} else if !procExists {
return errDaemonNotRunning
}
return nil
}

View File

@ -26,7 +26,6 @@ type subCmdCtx struct {
type subCmd struct { type subCmd struct {
name string name string
descr string descr string
checkLock bool
do func(subCmdCtx) error do func(subCmdCtx) error
} }
@ -103,13 +102,6 @@ func (ctx subCmdCtx) doSubCmd(subCmds ...subCmd) error {
printUsageExit(subCmdName) printUsageExit(subCmdName)
} }
if subCmd.checkLock {
if err := assertLock(); err != nil {
return fmt.Errorf("checking lock file: %w", err)
}
}
daemonRCPClient := jsonrpc2.NewUnixHTTPClient( daemonRCPClient := jsonrpc2.NewUnixHTTPClient(
daemon.HTTPSocketPath(), daemonHTTPRPCPath, daemon.HTTPSocketPath(), daemonHTTPRPCPath,
) )

View File

@ -49,20 +49,8 @@ type Daemon interface {
// - ErrAlreadyJoined // - ErrAlreadyJoined
JoinNetwork(context.Context, bootstrap.Bootstrap) error JoinNetwork(context.Context, bootstrap.Bootstrap) error
// GetBootstrapHosts returns the hosts stored in the bootstrap. // GetBootstraps returns the currently active Bootstrap.
GetBootstrapHosts( GetBootstrap(context.Context) (bootstrap.Bootstrap, error)
ctx context.Context,
) (
map[nebula.HostName]bootstrap.Host, error,
)
// GetGarageClientParams returns a GarageClientParams based on the current
// network topology.
GetGarageClientParams(
ctx context.Context,
) (
bootstrap.GarageClientParams, error,
)
// Shutdown blocks until all resources held or created by the daemon, // Shutdown blocks until all resources held or created by the daemon,
// including child processes it has started, have been cleaned up. // including child processes it has started, have been cleaned up.
@ -573,31 +561,13 @@ func (d *daemon) JoinNetwork(
} }
} }
func (d *daemon) GetBootstrapHosts( func (d *daemon) GetBootstrap(ctx context.Context) (bootstrap.Bootstrap, error) {
ctx context.Context,
) (
map[nebula.HostName]bootstrap.Host, error,
) {
return withCurrBootstrap(d, func( return withCurrBootstrap(d, func(
currBootstrap bootstrap.Bootstrap, currBootstrap bootstrap.Bootstrap,
) ( ) (
map[nebula.HostName]bootstrap.Host, error, bootstrap.Bootstrap, error,
) { ) {
return currBootstrap.Hosts, nil return currBootstrap, nil
})
}
func (d *daemon) GetGarageClientParams(
ctx context.Context,
) (
bootstrap.GarageClientParams, error,
) {
return withCurrBootstrap(d, func(
currBootstrap bootstrap.Bootstrap,
) (
bootstrap.GarageClientParams, error,
) {
return currBootstrap.GarageClientParams(), nil
}) })
} }

View File

@ -73,12 +73,12 @@ func (r *RPC) GetHosts(
) ( ) (
GetHostsResult, error, GetHostsResult, error,
) { ) {
hostsMap, err := r.daemon.GetBootstrapHosts(ctx) b, err := r.daemon.GetBootstrap(ctx)
if err != nil { if err != nil {
return GetHostsResult{}, fmt.Errorf("retrieving hosts: %w", err) return GetHostsResult{}, fmt.Errorf("retrieving bootstrap: %w", err)
} }
hosts := maps.Values(hostsMap) hosts := maps.Values(b.Hosts)
slices.SortFunc(hosts, func(a, b bootstrap.Host) int { slices.SortFunc(hosts, func(a, b bootstrap.Host) int {
return cmp.Compare(a.Name, b.Name) return cmp.Compare(a.Name, b.Name)
}) })
@ -92,5 +92,27 @@ func (r *RPC) GetGarageClientParams(
) ( ) (
bootstrap.GarageClientParams, error, bootstrap.GarageClientParams, error,
) { ) {
return r.daemon.GetGarageClientParams(ctx) b, err := r.daemon.GetBootstrap(ctx)
if err != nil {
return bootstrap.GarageClientParams{}, fmt.Errorf(
"retrieving bootstrap: %w", err,
)
}
return b.GarageClientParams(), nil
}
func (r *RPC) GetNebulaCAPublicCredentials(
ctx context.Context, req struct{},
) (
nebula.CAPublicCredentials, error,
) {
b, err := r.daemon.GetBootstrap(ctx)
if err != nil {
return nebula.CAPublicCredentials{}, fmt.Errorf(
"retrieving bootstrap: %w", err,
)
}
return b.CAPublicCredentials, nil
} }