diff --git a/go/daemon/network/loader.go b/go/daemon/network/loader.go index 4b1789c..d41403c 100644 --- a/go/daemon/network/loader.go +++ b/go/daemon/network/loader.go @@ -4,12 +4,14 @@ package network import ( "context" + "errors" "fmt" "isle/bootstrap" "isle/daemon/children" "isle/daemon/daecommon" "isle/nebula" "isle/toolkit" + "os" "dev.mediocregopher.com/mediocre-go-lib.git/mlog" ) @@ -30,6 +32,26 @@ func networkRuntimeDir( return networksRuntimeDir.MkChildDir(networkID, mayExist) } +func cleanupDirs( + networkStateDir, networkRuntimeDir toolkit.Dir, +) error { + var errs []error + + if err := os.RemoveAll(networkStateDir.Path); err != nil { + errs = append(errs, fmt.Errorf( + "removing %q: %w", networkStateDir.Path, err, + )) + } + + if err := os.RemoveAll(networkRuntimeDir.Path); err != nil { + errs = append(errs, fmt.Errorf( + "removing %q: %w", networkRuntimeDir.Path, err, + )) + } + + return errors.Join(errs...) +} + func networkDirs( networksStateDir, networksRuntimeDir toolkit.Dir, networkID string, @@ -268,6 +290,22 @@ func (l *loader) Join( networkID = creationParams.ID ) + // Start by checking that the new network isn't already joined. This + // shouldn't _technically_ be necessary, as the caller of Join should + // already be handling this, but it's worth doing to make sure we don't + // accidentally delete the state directory of an already joined network. + + allJoinedCreationParams, err := l.Loadable(ctx) + if err != nil { + return nil, fmt.Errorf("getting already joined networks: %w", err) + } + + for _, joinedCreationParams := range allJoinedCreationParams { + if joinedCreationParams.ID == networkID { + return nil, fmt.Errorf("network %q already joined", networkID) + } + } + networkStateDir, networkRuntimeDir, err := networkDirs( l.networksStateDir, l.networksRuntimeDir, networkID, false, ) @@ -277,7 +315,7 @@ func (l *loader) Join( ) } - return join( + n, err := join( ctx, logger, l.envBinDirPath, @@ -287,6 +325,14 @@ func (l *loader) Join( networkRuntimeDir, opts, ) + + if err != nil { + return nil, errors.Join( + err, cleanupDirs(networkStateDir, networkRuntimeDir), + ) + } + + return n, nil } func (l *loader) Create( @@ -310,7 +356,7 @@ func (l *loader) Create( ) } - return create( + n, err := create( ctx, logger, l.envBinDirPath, @@ -322,4 +368,12 @@ func (l *loader) Create( hostName, opts, ) + + if err != nil { + return nil, errors.Join( + err, cleanupDirs(networkStateDir, networkRuntimeDir), + ) + } + + return n, nil } diff --git a/tasks/v0.0.3/network-leave.md b/tasks/v0.0.3/network-leave.md new file mode 100644 index 0000000..0a306b2 --- /dev/null +++ b/tasks/v0.0.3/network-leave.md @@ -0,0 +1,8 @@ +--- +type: task +--- + +# Implement `network leave` sub-command + +When leaving a network the daemon should remove the now-defunct state-directory, +or at least mark it as inactive in some way.