2024-07-07 10:44:49 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
2024-07-09 09:43:17 +00:00
|
|
|
"isle/admin"
|
2024-07-07 10:44:49 +00:00
|
|
|
"isle/bootstrap"
|
2024-07-09 09:43:17 +00:00
|
|
|
"isle/daemon"
|
|
|
|
"os"
|
2024-07-07 10:44:49 +00:00
|
|
|
)
|
|
|
|
|
2024-07-09 09:43:17 +00:00
|
|
|
var subCmdNetworkCreate = subCmd{
|
|
|
|
name: "create",
|
|
|
|
descr: "Create's a new network, with this host being the first host in that network. The resulting admin.json is output to stdout.",
|
|
|
|
do: func(subCmdCtx subCmdCtx) error {
|
|
|
|
var (
|
|
|
|
ctx = subCmdCtx.ctx
|
|
|
|
flags = subCmdCtx.flagSet(false)
|
|
|
|
req daemon.CreateNetworkRequest
|
|
|
|
)
|
|
|
|
|
|
|
|
flags.StringVarP(
|
|
|
|
&req.Name, "name", "n", "",
|
|
|
|
"Human-readable name to identify the network as.",
|
|
|
|
)
|
|
|
|
|
|
|
|
flags.StringVarP(
|
|
|
|
&req.Domain, "domain", "d", "",
|
|
|
|
"Domain name that should be used as the root domain in the network.",
|
|
|
|
)
|
|
|
|
|
2024-07-12 13:30:21 +00:00
|
|
|
ipNetF := flags.VarPF(
|
|
|
|
textUnmarshalerFlag{&req.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.`,
|
2024-07-09 09:43:17 +00:00
|
|
|
)
|
|
|
|
|
2024-07-12 13:30:21 +00:00
|
|
|
hostNameF := flags.VarPF(
|
|
|
|
textUnmarshalerFlag{&req.HostName},
|
|
|
|
"hostname", "h",
|
2024-07-09 09:43:17 +00:00
|
|
|
"Name of this host, which will be the first host in the network",
|
|
|
|
)
|
|
|
|
|
|
|
|
if err := flags.Parse(subCmdCtx.args); err != nil {
|
|
|
|
return fmt.Errorf("parsing flags: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if req.Name == "" ||
|
|
|
|
req.Domain == "" ||
|
2024-07-12 13:30:21 +00:00
|
|
|
!ipNetF.Changed ||
|
|
|
|
!hostNameF.Changed {
|
2024-07-09 09:43:17 +00:00
|
|
|
return errors.New("--name, --domain, --ip-net, and --hostname are required")
|
|
|
|
}
|
|
|
|
|
|
|
|
var adm admin.Admin
|
|
|
|
err := subCmdCtx.daemonRCPClient.Call(ctx, &adm, "CreateNetwork", req)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("creating network: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := adm.WriteTo(os.Stdout); err != nil {
|
|
|
|
return fmt.Errorf("writing admin.json to stdout")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-07-07 10:44:49 +00:00
|
|
|
var subCmdNetworkJoin = subCmd{
|
|
|
|
name: "join",
|
|
|
|
descr: "Joins this host to an existing network",
|
|
|
|
do: func(subCmdCtx subCmdCtx) error {
|
|
|
|
var (
|
|
|
|
ctx = subCmdCtx.ctx
|
|
|
|
flags = subCmdCtx.flagSet(false)
|
|
|
|
)
|
|
|
|
|
|
|
|
bootstrapPath := flags.StringP(
|
|
|
|
"bootstrap-path", "b", "", "Path to a bootstrap.json file.",
|
|
|
|
)
|
|
|
|
|
|
|
|
if err := flags.Parse(subCmdCtx.args); err != nil {
|
|
|
|
return fmt.Errorf("parsing flags: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if *bootstrapPath == "" {
|
|
|
|
return errors.New("--bootstrap-path is required")
|
|
|
|
}
|
|
|
|
|
|
|
|
newBootstrap, err := bootstrap.FromFile(*bootstrapPath)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf(
|
|
|
|
"loading bootstrap from %q: %w", *bootstrapPath, err,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return subCmdCtx.daemonRCPClient.Call(
|
|
|
|
ctx, nil, "JoinNetwork", newBootstrap,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var subCmdNetwork = subCmd{
|
|
|
|
name: "network",
|
|
|
|
descr: "Sub-commands related to network membership",
|
|
|
|
do: func(subCmdCtx subCmdCtx) error {
|
|
|
|
return subCmdCtx.doSubCmd(
|
2024-07-09 09:43:17 +00:00
|
|
|
subCmdNetworkCreate,
|
2024-07-07 10:44:49 +00:00
|
|
|
subCmdNetworkJoin,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
}
|