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

169 lines
4.3 KiB
Go

package service
import (
"context"
"errors"
"fmt"
"github.com/bufbuild/connect-go"
api "github.com/jsiebens/ionscale/pkg/gen/ionscale/v1"
"google.golang.org/protobuf/types/known/timestamppb"
"inet.af/netaddr"
"time"
)
func (s *Service) ListMachines(ctx context.Context, req *connect.Request[api.ListMachinesRequest]) (*connect.Response[api.ListMachinesResponse], error) {
tailnet, err := s.repository.GetTailnet(ctx, req.Msg.TailnetId)
if err != nil {
return nil, err
}
if tailnet == nil {
return nil, connect.NewError(connect.CodeNotFound, errors.New("tailnet not found"))
}
machines, err := s.repository.ListMachineByTailnet(ctx, tailnet.ID)
if err != nil {
return nil, err
}
response := &api.ListMachinesResponse{}
for _, m := range machines {
var name = m.Name
if m.NameIdx != 0 {
name = fmt.Sprintf("%s-%d", m.Name, m.NameIdx)
}
online := s.brokers(m.TailnetID).IsConnected(m.ID)
var lastSeen *timestamppb.Timestamp
if m.LastSeen != nil {
lastSeen = timestamppb.New(*m.LastSeen)
}
response.Machines = append(response.Machines, &api.Machine{
Id: m.ID,
Name: name,
Ipv4: m.IPv4.String(),
Ipv6: m.IPv6.String(),
Ephemeral: m.Ephemeral,
Tags: m.Tags,
LastSeen: lastSeen,
Connected: online,
Tailnet: &api.Ref{
Id: m.Tailnet.ID,
Name: m.Tailnet.Name,
},
User: &api.Ref{
Id: m.User.ID,
Name: m.User.Name,
},
})
}
return connect.NewResponse(response), nil
}
func (s *Service) DeleteMachine(ctx context.Context, req *connect.Request[api.DeleteMachineRequest]) (*connect.Response[api.DeleteMachineResponse], error) {
m, err := s.repository.GetMachine(ctx, req.Msg.MachineId)
if err != nil {
return nil, err
}
if m == nil {
return nil, connect.NewError(connect.CodeNotFound, errors.New("machine not found"))
}
if _, err := s.repository.DeleteMachine(ctx, req.Msg.MachineId); err != nil {
return nil, err
}
s.brokers(m.TailnetID).SignalPeersRemoved([]uint64{m.ID})
return connect.NewResponse(&api.DeleteMachineResponse{}), nil
}
func (s *Service) ExpireMachine(ctx context.Context, req *connect.Request[api.ExpireMachineRequest]) (*connect.Response[api.ExpireMachineResponse], error) {
m, err := s.repository.GetMachine(ctx, req.Msg.MachineId)
if err != nil {
return nil, err
}
if m == nil {
return nil, connect.NewError(connect.CodeNotFound, errors.New("machine not found"))
}
timestamp := time.Unix(123, 0)
m.ExpiresAt = &timestamp
if err := s.repository.SaveMachine(ctx, m); err != nil {
return nil, err
}
s.brokers(m.TailnetID).SignalPeerUpdated(m.ID)
return connect.NewResponse(&api.ExpireMachineResponse{}), nil
}
func (s *Service) GetMachineRoutes(ctx context.Context, req *connect.Request[api.GetMachineRoutesRequest]) (*connect.Response[api.GetMachineRoutesResponse], error) {
m, err := s.repository.GetMachine(ctx, req.Msg.MachineId)
if err != nil {
return nil, err
}
if m == nil {
return nil, connect.NewError(connect.CodeNotFound, errors.New("machine not found"))
}
var routes []*api.RoutableIP
for _, r := range m.HostInfo.RoutableIPs {
routes = append(routes, &api.RoutableIP{
Advertised: r.String(),
Allowed: m.IsAllowedIPPrefix(r),
})
}
response := api.GetMachineRoutesResponse{
Routes: routes,
}
return connect.NewResponse(&response), nil
}
func (s *Service) SetMachineRoutes(ctx context.Context, req *connect.Request[api.SetMachineRoutesRequest]) (*connect.Response[api.GetMachineRoutesResponse], error) {
m, err := s.repository.GetMachine(ctx, req.Msg.MachineId)
if err != nil {
return nil, err
}
if m == nil {
return nil, connect.NewError(connect.CodeNotFound, errors.New("machine not found"))
}
var allowedIps []netaddr.IPPrefix
for _, r := range req.Msg.AllowedIps {
prefix, err := netaddr.ParseIPPrefix(r)
if err != nil {
return nil, err
}
allowedIps = append(allowedIps, prefix)
}
m.AllowIPs = allowedIps
if err := s.repository.SaveMachine(ctx, m); err != nil {
return nil, err
}
s.brokers(m.TailnetID).SignalPeerUpdated(m.ID)
var routes []*api.RoutableIP
for _, r := range m.HostInfo.RoutableIPs {
routes = append(routes, &api.RoutableIP{
Advertised: r.String(),
Allowed: m.IsAllowedIPPrefix(r),
})
}
response := api.GetMachineRoutesResponse{
Routes: routes,
}
return connect.NewResponse(&response), nil
}