2022-10-20 19:59:46 +00:00
|
|
|
package main
|
2021-04-20 21:31:37 +00:00
|
|
|
|
|
|
|
import (
|
2024-07-14 09:58:39 +00:00
|
|
|
"encoding/json"
|
2021-04-20 21:31:37 +00:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
2024-06-10 16:56:36 +00:00
|
|
|
"isle/bootstrap"
|
2024-07-12 15:05:39 +00:00
|
|
|
"isle/daemon"
|
2024-06-10 16:56:36 +00:00
|
|
|
"isle/jsonutil"
|
2024-07-12 15:05:39 +00:00
|
|
|
"isle/nebula"
|
2024-07-13 14:31:52 +00:00
|
|
|
"net/netip"
|
2021-04-20 21:31:37 +00:00
|
|
|
"os"
|
2022-10-15 16:41:07 +00:00
|
|
|
"sort"
|
2021-04-20 21:31:37 +00:00
|
|
|
)
|
|
|
|
|
2024-07-13 14:31:52 +00:00
|
|
|
var subCmdHostsCreate = subCmd{
|
|
|
|
name: "create",
|
|
|
|
descr: "Creates a new host in the network, writing its new bootstrap.json to stdout",
|
|
|
|
do: func(subCmdCtx subCmdCtx) error {
|
|
|
|
var (
|
|
|
|
flags = subCmdCtx.flagSet(false)
|
|
|
|
hostName nebula.HostName
|
|
|
|
ip netip.Addr
|
|
|
|
)
|
|
|
|
|
|
|
|
hostNameF := flags.VarPF(
|
|
|
|
textUnmarshalerFlag{&hostName},
|
|
|
|
"hostname", "h",
|
|
|
|
"Name of the host to generate bootstrap.json for",
|
|
|
|
)
|
|
|
|
|
|
|
|
ipF := flags.VarPF(
|
|
|
|
textUnmarshalerFlag{&ip}, "ip", "i", "IP of the new host",
|
|
|
|
)
|
|
|
|
|
2024-07-14 11:33:29 +00:00
|
|
|
canCreateHosts := flags.Bool(
|
|
|
|
"can-create-hosts",
|
|
|
|
false,
|
|
|
|
"The new host should have the ability to create hosts too",
|
|
|
|
)
|
|
|
|
|
2024-07-13 14:31:52 +00:00
|
|
|
if err := flags.Parse(subCmdCtx.args); err != nil {
|
|
|
|
return fmt.Errorf("parsing flags: %w", err)
|
|
|
|
}
|
|
|
|
|
2024-07-14 11:11:18 +00:00
|
|
|
if !hostNameF.Changed || !ipF.Changed {
|
|
|
|
return errors.New("--hostname and --ip are required")
|
2024-07-13 14:31:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var res daemon.CreateHostResult
|
2024-07-14 11:11:18 +00:00
|
|
|
err := subCmdCtx.daemonRCPClient.Call(
|
2024-07-13 14:31:52 +00:00
|
|
|
subCmdCtx.ctx,
|
|
|
|
&res,
|
|
|
|
"CreateHost",
|
|
|
|
daemon.CreateHostRequest{
|
2024-07-14 11:11:18 +00:00
|
|
|
HostName: hostName,
|
|
|
|
IP: ip,
|
2024-07-14 11:33:29 +00:00
|
|
|
Opts: daemon.CreateHostOpts{
|
|
|
|
CanCreateHosts: *canCreateHosts,
|
|
|
|
},
|
2024-07-13 14:31:52 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("calling CreateHost: %w", err)
|
|
|
|
}
|
|
|
|
|
2024-07-14 09:58:39 +00:00
|
|
|
return json.NewEncoder(os.Stdout).Encode(res.JoiningBootstrap)
|
2024-07-13 14:31:52 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2021-04-20 21:31:37 +00:00
|
|
|
var subCmdHostsList = subCmd{
|
2024-06-23 12:37:10 +00:00
|
|
|
name: "list",
|
|
|
|
descr: "Lists all hosts in the network, and their IPs",
|
2021-04-20 21:31:37 +00:00
|
|
|
do: func(subCmdCtx subCmdCtx) error {
|
2024-07-09 13:14:29 +00:00
|
|
|
hostsRes, err := subCmdCtx.getHosts()
|
2022-10-26 22:23:39 +00:00
|
|
|
if err != nil {
|
2024-06-23 12:37:10 +00:00
|
|
|
return fmt.Errorf("calling GetHosts: %w", err)
|
2022-10-26 22:23:39 +00:00
|
|
|
}
|
|
|
|
|
2022-11-05 15:55:17 +00:00
|
|
|
type host struct {
|
2024-06-10 16:56:36 +00:00
|
|
|
Name string
|
|
|
|
VPN struct {
|
|
|
|
IP string
|
|
|
|
}
|
|
|
|
Storage bootstrap.GarageHost `json:",omitempty"`
|
2022-11-05 15:55:17 +00:00
|
|
|
}
|
|
|
|
|
2024-07-09 13:14:29 +00:00
|
|
|
hosts := make([]host, 0, len(hostsRes.Hosts))
|
|
|
|
for _, h := range hostsRes.Hosts {
|
2022-11-05 15:55:17 +00:00
|
|
|
|
|
|
|
host := host{
|
2024-07-12 13:30:21 +00:00
|
|
|
Name: string(h.Name),
|
2024-06-10 16:56:36 +00:00
|
|
|
Storage: h.Garage,
|
2022-11-05 15:55:17 +00:00
|
|
|
}
|
|
|
|
|
2024-06-10 16:56:36 +00:00
|
|
|
host.VPN.IP = h.IP().String()
|
2022-11-05 15:55:17 +00:00
|
|
|
|
2022-10-15 16:41:07 +00:00
|
|
|
hosts = append(hosts, host)
|
2021-04-20 21:31:37 +00:00
|
|
|
}
|
|
|
|
|
2022-10-15 16:41:07 +00:00
|
|
|
sort.Slice(hosts, func(i, j int) bool { return hosts[i].Name < hosts[j].Name })
|
|
|
|
|
2024-06-10 16:56:36 +00:00
|
|
|
return jsonutil.WriteIndented(os.Stdout, hosts)
|
2021-04-20 21:31:37 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-07-12 15:05:39 +00:00
|
|
|
var subCmdHostsRemove = subCmd{
|
|
|
|
name: "remove",
|
|
|
|
descr: "Removes a host from the network",
|
2021-04-20 21:31:37 +00:00
|
|
|
do: func(subCmdCtx subCmdCtx) error {
|
2024-07-12 15:05:39 +00:00
|
|
|
var (
|
|
|
|
flags = subCmdCtx.flagSet(false)
|
|
|
|
hostName nebula.HostName
|
|
|
|
)
|
2021-04-20 21:31:37 +00:00
|
|
|
|
2024-07-12 15:05:39 +00:00
|
|
|
hostNameF := flags.VarPF(
|
|
|
|
textUnmarshalerFlag{&hostName},
|
|
|
|
"hostname", "h",
|
|
|
|
"Name of the host to remove",
|
2021-04-20 21:31:37 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
if err := flags.Parse(subCmdCtx.args); err != nil {
|
|
|
|
return fmt.Errorf("parsing flags: %w", err)
|
|
|
|
}
|
|
|
|
|
2024-07-12 15:05:39 +00:00
|
|
|
if !hostNameF.Changed {
|
2022-11-05 11:34:49 +00:00
|
|
|
return errors.New("--hostname is required")
|
2021-04-20 21:31:37 +00:00
|
|
|
}
|
|
|
|
|
2024-07-12 14:03:37 +00:00
|
|
|
err := subCmdCtx.daemonRCPClient.Call(
|
2024-07-12 15:05:39 +00:00
|
|
|
subCmdCtx.ctx, nil, "RemoveHost", daemon.RemoveHostRequest{
|
|
|
|
HostName: hostName,
|
|
|
|
},
|
2024-07-12 14:03:37 +00:00
|
|
|
)
|
2022-10-26 22:23:39 +00:00
|
|
|
if err != nil {
|
2024-07-12 15:05:39 +00:00
|
|
|
return fmt.Errorf("calling RemoveHost: %w", err)
|
2022-10-26 22:23:39 +00:00
|
|
|
}
|
|
|
|
|
2024-07-12 15:05:39 +00:00
|
|
|
return nil
|
2021-04-20 21:31:37 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var subCmdHosts = subCmd{
|
|
|
|
name: "hosts",
|
|
|
|
descr: "Sub-commands having to do with configuration of hosts in the network",
|
|
|
|
do: func(subCmdCtx subCmdCtx) error {
|
|
|
|
return subCmdCtx.doSubCmd(
|
2024-07-13 14:31:52 +00:00
|
|
|
subCmdHostsCreate,
|
2024-07-12 15:05:39 +00:00
|
|
|
subCmdHostsRemove,
|
2022-10-16 15:18:50 +00:00
|
|
|
subCmdHostsList,
|
2021-04-20 21:31:37 +00:00
|
|
|
)
|
|
|
|
},
|
|
|
|
}
|