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.
143 lines
2.8 KiB
Go
143 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"isle/bootstrap"
|
|
"isle/daemon/network"
|
|
"isle/jsonutil"
|
|
"os"
|
|
"sort"
|
|
)
|
|
|
|
var subCmdHostCreate = subCmd{
|
|
name: "create",
|
|
descr: "Creates a new host in the network, writing its new bootstrap.json to stdout",
|
|
do: func(ctx subCmdCtx) error {
|
|
var (
|
|
flags = ctx.flagSet(false)
|
|
hostName hostNameFlag
|
|
ip ipFlag
|
|
)
|
|
|
|
hostNameF := flags.VarPF(
|
|
&hostName,
|
|
"hostname", "n",
|
|
"Name of the host to generate bootstrap.json for",
|
|
)
|
|
|
|
flags.VarP(&ip, "ip", "i", "IP of the new host. An available IP will be chosen if none is given.")
|
|
|
|
canCreateHosts := flags.Bool(
|
|
"can-create-hosts",
|
|
false,
|
|
"The new host should have the ability to create hosts too",
|
|
)
|
|
|
|
if err := flags.Parse(ctx.args); err != nil {
|
|
return fmt.Errorf("parsing flags: %w", err)
|
|
}
|
|
|
|
if !hostNameF.Changed {
|
|
return errors.New("--hostname is required")
|
|
}
|
|
|
|
var (
|
|
res network.JoiningBootstrap
|
|
err error
|
|
)
|
|
res, err = ctx.daemonRPC.CreateHost(
|
|
ctx, hostName.V, network.CreateHostOpts{
|
|
IP: ip.V,
|
|
CanCreateHosts: *canCreateHosts,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return fmt.Errorf("calling CreateHost: %w", err)
|
|
}
|
|
|
|
return json.NewEncoder(os.Stdout).Encode(res)
|
|
},
|
|
}
|
|
|
|
var subCmdHostList = subCmd{
|
|
name: "list",
|
|
descr: "Lists all hosts in the network, and their IPs",
|
|
do: func(ctx subCmdCtx) error {
|
|
hostsRes, err := ctx.getHosts()
|
|
if err != nil {
|
|
return fmt.Errorf("calling GetHosts: %w", err)
|
|
}
|
|
|
|
type host struct {
|
|
Name string
|
|
VPN struct {
|
|
IP string
|
|
}
|
|
Storage bootstrap.GarageHost `json:",omitempty"`
|
|
}
|
|
|
|
hosts := make([]host, 0, len(hostsRes))
|
|
for _, h := range hostsRes {
|
|
|
|
host := host{
|
|
Name: string(h.Name),
|
|
Storage: h.Garage,
|
|
}
|
|
|
|
host.VPN.IP = h.IP().String()
|
|
|
|
hosts = append(hosts, host)
|
|
}
|
|
|
|
sort.Slice(hosts, func(i, j int) bool { return hosts[i].Name < hosts[j].Name })
|
|
|
|
return jsonutil.WriteIndented(os.Stdout, hosts)
|
|
},
|
|
}
|
|
|
|
var subCmdHostRemove = subCmd{
|
|
name: "remove",
|
|
descr: "Removes a host from the network",
|
|
do: func(ctx subCmdCtx) error {
|
|
var (
|
|
flags = ctx.flagSet(false)
|
|
hostName hostNameFlag
|
|
)
|
|
|
|
hostNameF := flags.VarPF(
|
|
&hostName,
|
|
"hostname", "n",
|
|
"Name of the host to remove",
|
|
)
|
|
|
|
if err := flags.Parse(ctx.args); err != nil {
|
|
return fmt.Errorf("parsing flags: %w", err)
|
|
}
|
|
|
|
if !hostNameF.Changed {
|
|
return errors.New("--hostname is required")
|
|
}
|
|
|
|
if err := ctx.daemonRPC.RemoveHost(ctx, hostName.V); err != nil {
|
|
return fmt.Errorf("calling RemoveHost: %w", err)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var subCmdHost = subCmd{
|
|
name: "host",
|
|
plural: "s",
|
|
descr: "Sub-commands having to do with configuration of hosts in the network",
|
|
do: func(ctx subCmdCtx) error {
|
|
return ctx.doSubCmd(
|
|
subCmdHostCreate,
|
|
subCmdHostRemove,
|
|
subCmdHostList,
|
|
)
|
|
},
|
|
}
|