154 lines
3.4 KiB
Go
154 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"isle/daemon/network"
|
|
"os"
|
|
)
|
|
|
|
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 (
|
|
hostName hostNameFlag
|
|
ip ipFlag
|
|
)
|
|
|
|
hostNameF := ctx.flags.VarPF(
|
|
&hostName,
|
|
"hostname", "n",
|
|
"Name of the host to generate bootstrap.json for",
|
|
)
|
|
|
|
ctx.flags.VarP(&ip, "ip", "i", "IP of the new host. An available IP will be chosen if none is given.")
|
|
|
|
canCreateHosts := ctx.flags.Bool(
|
|
"can-create-hosts",
|
|
false,
|
|
"The new host should have the ability to create hosts too",
|
|
)
|
|
|
|
ctx, err := ctx.withParsedFlags()
|
|
if err != nil {
|
|
return fmt.Errorf("parsing flags: %w", err)
|
|
}
|
|
|
|
if !hostNameF.Changed {
|
|
return errors.New("--hostname is required")
|
|
}
|
|
|
|
res, err := ctx.getDaemonRPC().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: doWithOutput(func(ctx subCmdCtx) (any, error) {
|
|
ctx, err := ctx.withParsedFlags()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("parsing flags: %w", err)
|
|
}
|
|
|
|
currBoostrap, err := ctx.getDaemonRPC().GetBootstrap(ctx)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("calling GetBootstrap: %w", err)
|
|
}
|
|
|
|
hosts := currBoostrap.HostsOrdered()
|
|
|
|
type storageInstanceView struct {
|
|
ID string `yaml:"id"`
|
|
RPCPort int `yaml:"rpc_port"`
|
|
S3APIPort int `yaml:"s3_api_port"`
|
|
}
|
|
|
|
type hostView struct {
|
|
Name string `yaml:"name"`
|
|
VPN struct {
|
|
IP string `yaml:"ip"`
|
|
PublicAddr string `yaml:"public_addr,omitempty"`
|
|
}
|
|
Storage struct {
|
|
Instances []storageInstanceView `yaml:"instances"`
|
|
} `yaml:",omitempty"`
|
|
}
|
|
|
|
hostViews := make([]hostView, len(hosts))
|
|
for i, host := range hosts {
|
|
storageInstanceViews := make([]storageInstanceView, len(host.Garage.Instances))
|
|
for i := range host.Garage.Instances {
|
|
storageInstanceViews[i] = storageInstanceView(host.Garage.Instances[i])
|
|
}
|
|
|
|
hostView := hostView{
|
|
Name: string(host.Name),
|
|
}
|
|
|
|
hostView.VPN.IP = host.IP().String()
|
|
hostView.VPN.PublicAddr = host.Nebula.PublicAddr
|
|
hostView.Storage.Instances = storageInstanceViews
|
|
hostViews[i] = hostView
|
|
}
|
|
|
|
return hostViews, nil
|
|
}),
|
|
}
|
|
|
|
var subCmdHostRemove = subCmd{
|
|
name: "remove",
|
|
descr: "Removes a host from the network",
|
|
do: func(ctx subCmdCtx) error {
|
|
var (
|
|
hostName hostNameFlag
|
|
)
|
|
|
|
hostNameF := ctx.flags.VarPF(
|
|
&hostName,
|
|
"hostname", "n",
|
|
"Name of the host to remove",
|
|
)
|
|
|
|
ctx, err := ctx.withParsedFlags()
|
|
if err != nil {
|
|
return fmt.Errorf("parsing flags: %w", err)
|
|
}
|
|
|
|
if !hostNameF.Changed {
|
|
return errors.New("--hostname is required")
|
|
}
|
|
|
|
if err := ctx.getDaemonRPC().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,
|
|
)
|
|
},
|
|
}
|