isle/go/cmd/entrypoint/hosts.go

113 lines
2.3 KiB
Go

package main
import (
"encoding/json"
"errors"
"fmt"
"isle/bootstrap"
"isle/daemon"
"isle/jsonutil"
"os"
"regexp"
"sort"
)
var hostNameRegexp = regexp.MustCompile(`^[a-z][a-z0-9\-]*$`)
func validateHostName(name string) error {
if !hostNameRegexp.MatchString(name) {
return errors.New("a host's name must start with a letter and only contain letters, numbers, and dashes")
}
return nil
}
var subCmdHostsList = subCmd{
name: "list",
descr: "Lists all hosts in the network, and their IPs",
do: func(subCmdCtx subCmdCtx) error {
ctx := subCmdCtx.ctx
var resRaw json.RawMessage
err := subCmdCtx.daemonRCPClient.Call(ctx, &resRaw, "GetHosts", nil)
if err != nil {
return fmt.Errorf("calling GetHosts: %w", err)
}
var res daemon.GetHostsResult
if err := json.Unmarshal(resRaw, &res); err != nil {
return fmt.Errorf("unmarshaling %s into %T: %w", string(resRaw), res, err)
}
type host struct {
Name string
VPN struct {
IP string
}
Storage bootstrap.GarageHost `json:",omitempty"`
}
hosts := make([]host, 0, len(res.Hosts))
for _, h := range res.Hosts {
host := host{
Name: 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 subCmdHostsDelete = subCmd{
name: "delete",
descr: "Deletes a host from the network",
checkLock: true,
do: func(subCmdCtx subCmdCtx) error {
flags := subCmdCtx.flagSet(false)
hostName := flags.StringP(
"hostname", "h", "",
"Name of the host to delete",
)
if err := flags.Parse(subCmdCtx.args); err != nil {
return fmt.Errorf("parsing flags: %w", err)
}
if *hostName == "" {
return errors.New("--hostname is required")
}
hostBootstrap, err := loadHostBootstrap()
if err != nil {
return fmt.Errorf("loading host bootstrap: %w", err)
}
client := hostBootstrap.GlobalBucketS3APIClient()
return bootstrap.RemoveGarageBootstrapHost(subCmdCtx.ctx, client, *hostName)
},
}
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(
subCmdHostsDelete,
subCmdHostsList,
)
},
}