Compare commits

..

2 Commits

5 changed files with 67 additions and 22 deletions

View File

@ -41,6 +41,12 @@ func (o *Opts) withDefaults() *Opts {
var _ RPC = (*Daemon)(nil) var _ RPC = (*Daemon)(nil)
type joinedNetwork struct {
network.Network
userConfig bool
}
// Daemon implements all methods of the Daemon interface, plus others used // Daemon implements all methods of the Daemon interface, plus others used
// to manage this particular implementation. // to manage this particular implementation.
// //
@ -67,7 +73,7 @@ type Daemon struct {
networksRuntimeDir toolkit.Dir networksRuntimeDir toolkit.Dir
l sync.RWMutex l sync.RWMutex
networks map[string]network.Network networks map[string]joinedNetwork
} }
// New initializes and returns a Daemon. // New initializes and returns a Daemon.
@ -97,7 +103,7 @@ func New(
daemonConfig: daemonConfig, daemonConfig: daemonConfig,
envBinDirPath: envBinDirPath, envBinDirPath: envBinDirPath,
opts: opts, opts: opts,
networks: map[string]network.Network{}, networks: map[string]joinedNetwork{},
} }
{ {
@ -135,7 +141,7 @@ func New(
networkConfig, _ := pickNetworkConfig(daemonConfig, creationParams) networkConfig, _ := pickNetworkConfig(daemonConfig, creationParams)
d.networks[id], err = network.Load( network, err := network.Load(
ctx, ctx,
logger.WithNamespace("network"), logger.WithNamespace("network"),
networkConfig, networkConfig,
@ -149,6 +155,11 @@ func New(
if err != nil { if err != nil {
return nil, fmt.Errorf("loading network %q: %w", id, err) return nil, fmt.Errorf("loading network %q: %w", id, err)
} }
d.networks[id] = joinedNetwork{
Network: network,
userConfig: true,
}
} }
return d, nil return d, nil
@ -169,7 +180,9 @@ func New(
// - network.ErrInvalidConfig // - network.ErrInvalidConfig
func (d *Daemon) CreateNetwork( func (d *Daemon) CreateNetwork(
ctx context.Context, ctx context.Context,
name, domain string, ipNet nebula.IPNet, hostName nebula.HostName, name, domain string,
ipNet nebula.IPNet,
hostName nebula.HostName,
) error { ) error {
creationParams := bootstrap.NewCreationParams(name, domain) creationParams := bootstrap.NewCreationParams(name, domain)
ctx = mctx.WithAnnotator(ctx, creationParams) ctx = mctx.WithAnnotator(ctx, creationParams)
@ -221,7 +234,11 @@ func (d *Daemon) CreateNetwork(
} }
d.logger.Info(ctx, "Network created successfully") d.logger.Info(ctx, "Network created successfully")
d.networks[creationParams.ID] = n d.networks[creationParams.ID] = joinedNetwork{
Network: n,
userConfig: true,
}
return nil return nil
} }
@ -279,7 +296,10 @@ func (d *Daemon) JoinNetwork(
} }
d.logger.Info(ctx, "Network joined successfully") d.logger.Info(ctx, "Network joined successfully")
d.networks[networkID] = n d.networks[networkID] = joinedNetwork{
Network: n,
userConfig: true,
}
return nil return nil
} }
@ -296,7 +316,7 @@ func withNetwork[Res any](
network, err := pickNetwork(ctx, d.networks, d.networksStateDir) network, err := pickNetwork(ctx, d.networks, d.networksStateDir)
if err != nil { if err != nil {
var zero Res var zero Res
return zero, nil return zero, err
} }
return fn(ctx, network) return fn(ctx, network)
@ -331,6 +351,24 @@ func (d *Daemon) GetNetworks(
return res, nil return res, nil
} }
func (d *Daemon) SetConfig(
ctx context.Context, config daecommon.NetworkConfig,
) error {
d.l.RLock()
defer d.l.RUnlock()
network, err := pickNetwork(ctx, d.networks, d.networksStateDir)
if err != nil {
return err
}
if network.userConfig {
return ErrUserManagedNetworkConfig
}
return network.SetConfig(ctx, config)
}
// GetHost implements the method for the network.RPC interface. // GetHost implements the method for the network.RPC interface.
func (d *Daemon) GetHosts(ctx context.Context) ([]bootstrap.Host, error) { func (d *Daemon) GetHosts(ctx context.Context) ([]bootstrap.Host, error) {
return withNetwork( return withNetwork(

View File

@ -10,6 +10,7 @@ const (
errCodeAlreadyJoined errCodeAlreadyJoined
errCodeNoMatchingNetworks errCodeNoMatchingNetworks
errCodeMultipleMatchingNetworks errCodeMultipleMatchingNetworks
errCodeUserManagedNetworkConfig
) )
var ( var (
@ -33,4 +34,11 @@ var (
errCodeMultipleMatchingNetworks, errCodeMultipleMatchingNetworks,
"Multiple networks matched the search string", "Multiple networks matched the search string",
) )
// ErrUserManagedNetworkConfig is returned when attempting to modify a
// network config which is managed by the user.
ErrUserManagedNetworkConfig = jsonrpc2.NewError(
errCodeUserManagedNetworkConfig,
"Network configuration is managed by the user",
)
) )

View File

@ -75,18 +75,18 @@ func loadableNetworks(
func pickNetwork( func pickNetwork(
ctx context.Context, ctx context.Context,
networks map[string]network.Network, networks map[string]joinedNetwork,
networksStateDir toolkit.Dir, networksStateDir toolkit.Dir,
) ( ) (
network.Network, error, joinedNetwork, error,
) { ) {
if len(networks) == 0 { if len(networks) == 0 {
return nil, ErrNoNetwork return joinedNetwork{}, ErrNoNetwork
} }
creationParams, err := loadableNetworks(networksStateDir) creationParams, err := loadableNetworks(networksStateDir)
if err != nil { if err != nil {
return nil, fmt.Errorf("getting loadable networks: %w", err) return joinedNetwork{}, fmt.Errorf("getting loadable networks: %w", err)
} }
var ( var (
@ -101,9 +101,9 @@ func pickNetwork(
} }
if len(matchingNetworkIDs) == 0 { if len(matchingNetworkIDs) == 0 {
return nil, ErrNoMatchingNetworks return joinedNetwork{}, ErrNoMatchingNetworks
} else if len(matchingNetworkIDs) > 1 { } else if len(matchingNetworkIDs) > 1 {
return nil, ErrMultipleMatchingNetworks return joinedNetwork{}, ErrMultipleMatchingNetworks
} }
return networks[matchingNetworkIDs[0]], nil return networks[matchingNetworkIDs[0]], nil
@ -111,7 +111,7 @@ func pickNetwork(
func alreadyJoined( func alreadyJoined(
ctx context.Context, ctx context.Context,
networks map[string]network.Network, networks map[string]joinedNetwork,
creationParams bootstrap.CreationParams, creationParams bootstrap.CreationParams,
) ( ) (
bool, error, bool, error,

View File

@ -225,14 +225,10 @@ func TestNetwork_SetConfig(t *testing.T) {
}) })
networkConfig = secondus.getConfig(t) networkConfig = secondus.getConfig(t)
prevHost = secondus.getHostsByName(t)[secondus.hostName] prevHost = secondus.getHostsByName(t)[secondus.hostName]
removedAlloc = networkConfig.Storage.Allocations[0] removedRole = allocsToRoles(
removedRole = allocsToRoles(
secondus.hostName, prevHost.Garage.Instances, secondus.hostName, prevHost.Garage.Instances,
)[0] )[0]
removedGarageInst = daecommon.BootstrapGarageHostForAlloc(
prevHost, removedAlloc,
)
primusGarageAdminClient = primus.garageAdminClient(t) primusGarageAdminClient = primus.garageAdminClient(t)
) )
@ -246,8 +242,7 @@ func TestNetwork_SetConfig(t *testing.T) {
assert.True(t, ok) assert.True(t, ok)
allocs := newHost.HostConfigured.Garage.Instances allocs := newHost.HostConfigured.Garage.Instances
assert.Len(t, allocs, 3) assert.Empty(t, allocs)
assert.NotContains(t, allocs, removedGarageInst)
t.Log("Checking that garage layout still contains the old allocation") t.Log("Checking that garage layout still contains the old allocation")
layout, err := primusGarageAdminClient.GetLayout(h.ctx) layout, err := primusGarageAdminClient.GetLayout(h.ctx)

View File

@ -3,6 +3,7 @@ package daemon
import ( import (
"context" "context"
"isle/bootstrap" "isle/bootstrap"
"isle/daemon/daecommon"
"isle/daemon/jsonrpc2" "isle/daemon/jsonrpc2"
"isle/daemon/network" "isle/daemon/network"
"isle/nebula" "isle/nebula"
@ -25,6 +26,8 @@ type RPC interface {
GetNetworks(context.Context) ([]bootstrap.CreationParams, error) GetNetworks(context.Context) ([]bootstrap.CreationParams, error)
SetConfig(context.Context, daecommon.NetworkConfig) error
// All network.RPC methods are automatically implemented by Daemon using the // All network.RPC methods are automatically implemented by Daemon using the
// currently joined network. If no network is joined then any call to these // currently joined network. If no network is joined then any call to these
// methods will return ErrNoNetwork. // methods will return ErrNoNetwork.
@ -34,6 +37,7 @@ type RPC interface {
// these errors, in addition to those documented on the individual methods: // these errors, in addition to those documented on the individual methods:
// //
// Errors: // Errors:
// - ErrNoNetwork
// - ErrNoMatchingNetworks // - ErrNoMatchingNetworks
// - ErrMultipleMatchingNetworks // - ErrMultipleMatchingNetworks
network.RPC network.RPC