Brian Picciano
8c3e6a2845
In a world where the daemon can manage more than one network, the Daemon is really responsible only for knowing which networks are currently joined, creating/joining/leaving networks, and routing incoming RPC requests to the correct network handler as needed. The new network package, with its Network interface, inherits most of the logic that Daemon used to have, leaving Daemon only the parts needed for the functionality just described. There's a lot of cleanup done here in order to really nail down the separation of concerns between the two, especially around directory creation.
105 lines
2.3 KiB
Go
105 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"isle/daemon/network"
|
|
"isle/jsonutil"
|
|
)
|
|
|
|
var subCmdNetworkCreate = subCmd{
|
|
name: "create",
|
|
descr: "Create's a new network, with this host being the first host in that network.",
|
|
do: func(ctx subCmdCtx) error {
|
|
var (
|
|
flags = ctx.flagSet(false)
|
|
ipNet ipNetFlag
|
|
hostName hostNameFlag
|
|
)
|
|
|
|
name := flags.StringP(
|
|
"name", "N", "",
|
|
"Human-readable name to identify the network as.",
|
|
)
|
|
|
|
domain := flags.StringP(
|
|
"domain", "d", "",
|
|
"Domain name that should be used as the root domain in the network.",
|
|
)
|
|
|
|
ipNetF := flags.VarPF(
|
|
&ipNet, "ip-net", "i",
|
|
`An IP subnet, in CIDR form, which will be the overall range of`+
|
|
` possible IPs in the network. The first IP in this network`+
|
|
` range will become this first host's IP.`,
|
|
)
|
|
|
|
hostNameF := flags.VarPF(
|
|
&hostName,
|
|
"hostname", "n",
|
|
"Name of this host, which will be the first host in the network",
|
|
)
|
|
|
|
if err := flags.Parse(ctx.args); err != nil {
|
|
return fmt.Errorf("parsing flags: %w", err)
|
|
}
|
|
|
|
if *name == "" ||
|
|
*domain == "" ||
|
|
!ipNetF.Changed ||
|
|
!hostNameF.Changed {
|
|
return errors.New("--name, --domain, --ip-net, and --hostname are required")
|
|
}
|
|
|
|
err := ctx.daemonRPC.CreateNetwork(
|
|
ctx, *name, *domain, ipNet.V, hostName.V,
|
|
)
|
|
if err != nil {
|
|
return fmt.Errorf("creating network: %w", err)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var subCmdNetworkJoin = subCmd{
|
|
name: "join",
|
|
descr: "Joins this host to an existing network",
|
|
do: func(ctx subCmdCtx) error {
|
|
var (
|
|
flags = ctx.flagSet(false)
|
|
bootstrapPath = flags.StringP(
|
|
"bootstrap-path", "b", "", "Path to a bootstrap.json file.",
|
|
)
|
|
)
|
|
|
|
if err := flags.Parse(ctx.args); err != nil {
|
|
return fmt.Errorf("parsing flags: %w", err)
|
|
}
|
|
|
|
if *bootstrapPath == "" {
|
|
return errors.New("--bootstrap-path is required")
|
|
}
|
|
|
|
var newBootstrap network.JoiningBootstrap
|
|
if err := jsonutil.LoadFile(&newBootstrap, *bootstrapPath); err != nil {
|
|
return fmt.Errorf(
|
|
"loading bootstrap from %q: %w", *bootstrapPath, err,
|
|
)
|
|
}
|
|
|
|
return ctx.daemonRPC.JoinNetwork(ctx, newBootstrap)
|
|
},
|
|
}
|
|
|
|
var subCmdNetwork = subCmd{
|
|
name: "network",
|
|
descr: "Sub-commands related to network membership",
|
|
do: func(ctx subCmdCtx) error {
|
|
return ctx.doSubCmd(
|
|
subCmdNetworkCreate,
|
|
subCmdNetworkJoin,
|
|
)
|
|
},
|
|
}
|