Files
ionscale/internal/cmd/machine.go
T
2022-06-03 14:25:31 +02:00

234 lines
5.3 KiB
Go

package cmd
import (
"context"
"fmt"
"github.com/bufbuild/connect-go"
api "github.com/jsiebens/ionscale/pkg/gen/ionscale/v1"
"github.com/muesli/coral"
"github.com/nleeper/goment"
"github.com/rodaine/table"
"inet.af/netaddr"
"strings"
)
func machineCommands() *coral.Command {
command := &coral.Command{
Use: "machines",
Short: "Manage ionscale machines",
SilenceUsage: true,
}
command.AddCommand(deleteMachineCommand())
command.AddCommand(expireMachineCommand())
command.AddCommand(listMachinesCommand())
command.AddCommand(getMachineRoutesCommand())
command.AddCommand(setMachineRoutesCommand())
return command
}
func deleteMachineCommand() *coral.Command {
command := &coral.Command{
Use: "delete",
Short: "Deletes a machine",
SilenceUsage: true,
}
var machineID uint64
var target = Target{}
target.prepareCommand(command)
command.Flags().Uint64Var(&machineID, "machine-id", 0, "")
command.RunE = func(command *coral.Command, args []string) error {
client, c, err := target.createGRPCClient()
if err != nil {
return err
}
defer safeClose(c)
req := api.DeleteMachineRequest{MachineId: machineID}
if _, err := client.DeleteMachine(context.Background(), connect.NewRequest(&req)); err != nil {
return err
}
fmt.Println("Machine deleted.")
return nil
}
return command
}
func expireMachineCommand() *coral.Command {
command := &coral.Command{
Use: "expire",
Short: "Expires a machine",
SilenceUsage: true,
}
var machineID uint64
var target = Target{}
target.prepareCommand(command)
command.Flags().Uint64Var(&machineID, "machine-id", 0, "")
command.RunE = func(command *coral.Command, args []string) error {
client, c, err := target.createGRPCClient()
if err != nil {
return err
}
defer safeClose(c)
req := api.ExpireMachineRequest{MachineId: machineID}
if _, err := client.ExpireMachine(context.Background(), connect.NewRequest(&req)); err != nil {
return err
}
fmt.Println("Machine key expired.")
return nil
}
return command
}
func listMachinesCommand() *coral.Command {
command := &coral.Command{
Use: "list",
Short: "List machines",
SilenceUsage: true,
}
var tailnetID uint64
var tailnetName string
var target = Target{}
target.prepareCommand(command)
command.Flags().StringVar(&tailnetName, "tailnet", "", "")
command.Flags().Uint64Var(&tailnetID, "tailnet-id", 0, "")
command.RunE = func(command *coral.Command, args []string) error {
client, c, err := target.createGRPCClient()
if err != nil {
return err
}
defer safeClose(c)
tailnet, err := findTailnet(client, tailnetName, tailnetID)
if err != nil {
return err
}
req := api.ListMachinesRequest{TailnetId: tailnet.Id}
resp, err := client.ListMachines(context.Background(), connect.NewRequest(&req))
if err != nil {
return err
}
tbl := table.New("ID", "TAILNET", "NAME", "IPv4", "IPv6", "EPHEMERAL", "LAST_SEEN", "TAGS")
for _, m := range resp.Msg.Machines {
var lastSeen = "N/A"
if m.Connected {
lastSeen = "Connected"
} else if m.LastSeen != nil {
mom, err := goment.New(m.LastSeen.AsTime())
if err == nil {
lastSeen = mom.FromNow()
}
}
tbl.AddRow(m.Id, m.Tailnet.Name, m.Name, m.Ipv4, m.Ipv6, m.Ephemeral, lastSeen, strings.Join(m.Tags, ","))
}
tbl.Print()
return nil
}
return command
}
func getMachineRoutesCommand() *coral.Command {
command := &coral.Command{
Use: "get-routes",
Short: "Show the routes of a machine",
SilenceUsage: true,
}
var machineID uint64
var target = Target{}
target.prepareCommand(command)
command.Flags().Uint64Var(&machineID, "machine-id", 0, "")
command.RunE = func(command *coral.Command, args []string) error {
grpcClient, c, err := target.createGRPCClient()
if err != nil {
return err
}
defer safeClose(c)
req := api.GetMachineRoutesRequest{MachineId: machineID}
resp, err := grpcClient.GetMachineRoutes(context.Background(), connect.NewRequest(&req))
if err != nil {
return err
}
tbl := table.New("ROUTE", "ALLOWED")
for _, r := range resp.Msg.Routes {
tbl.AddRow(r.Advertised, r.Allowed)
}
tbl.Print()
return nil
}
return command
}
func setMachineRoutesCommand() *coral.Command {
command := &coral.Command{
Use: "set-routes",
Short: "Enable routes of a machine",
SilenceUsage: true,
}
var machineID uint64
var allowedIps []string
var target = Target{}
target.prepareCommand(command)
command.Flags().Uint64Var(&machineID, "machine-id", 0, "")
command.Flags().StringSliceVar(&allowedIps, "allowed-ips", []string{}, "")
command.RunE = func(command *coral.Command, args []string) error {
client, c, err := target.createGRPCClient()
if err != nil {
return err
}
defer safeClose(c)
var prefixes []netaddr.IPPrefix
for _, r := range allowedIps {
p, err := netaddr.ParseIPPrefix(r)
if err != nil {
return err
}
prefixes = append(prefixes, p)
}
req := api.SetMachineRoutesRequest{MachineId: machineID, AllowedIps: allowedIps}
resp, err := client.SetMachineRoutes(context.Background(), connect.NewRequest(&req))
if err != nil {
return err
}
tbl := table.New("ROUTE", "ALLOWED")
for _, r := range resp.Msg.Routes {
tbl.AddRow(r.Advertised, r.Allowed)
}
tbl.Print()
return nil
}
return command
}