Skip to content

Commit

Permalink
feat: delete tailnet
Browse files Browse the repository at this point in the history
  • Loading branch information
jsiebens committed May 16, 2022
1 parent c74a082 commit 9769f40
Show file tree
Hide file tree
Showing 15 changed files with 485 additions and 221 deletions.
5 changes: 5 additions & 0 deletions internal/broker/broker.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type Broker interface {
AddClient(*Client)
RemoveClient(uint64)

SignalTailnedDeleted()
SignalPeerUpdated(id uint64)
SignalPeersRemoved([]uint64)
SignalDNSUpdated()
Expand Down Expand Up @@ -82,6 +83,10 @@ func (h *broker) RemoveClient(id uint64) {
h.closingClients <- id
}

func (h *broker) SignalTailnedDeleted() {
h.signalChannel <- &Signal{}
}

func (h *broker) SignalPeerUpdated(id uint64) {
h.signalChannel <- &Signal{PeerUpdated: &id}
}
Expand Down
47 changes: 46 additions & 1 deletion internal/cmd/tailnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"context"
"fmt"
"github.com/jsiebens/ionscale/pkg/gen/api"
"github.com/muesli/coral"
"github.com/rodaine/table"
Expand All @@ -16,6 +17,7 @@ func tailnetCommand() *coral.Command {

command.AddCommand(listTailnetsCommand())
command.AddCommand(createTailnetsCommand())
command.AddCommand(deleteTailnetCommand())
command.AddCommand(getDNSConfig())
command.AddCommand(setDNSConfig())
command.AddCommand(getACLConfig())
Expand Down Expand Up @@ -65,7 +67,6 @@ func createTailnetsCommand() *coral.Command {
command := &coral.Command{
Use: "create",
Short: "Create a new tailnet",
Long: `List tailnets in this ionscale instance.`,
SilenceUsage: true,
}

Expand Down Expand Up @@ -99,3 +100,47 @@ func createTailnetsCommand() *coral.Command {

return command
}

func deleteTailnetCommand() *coral.Command {
command := &coral.Command{
Use: "delete",
Short: "Delete a tailnet",
SilenceUsage: true,
}

var tailnetID uint64
var tailnetName string
var force bool
var target = Target{}
target.prepareCommand(command)

command.Flags().StringVar(&tailnetName, "tailnet", "", "")
command.Flags().Uint64Var(&tailnetID, "tailnet-id", 0, "")
command.Flags().BoolVar(&force, "force", false, "")

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
}

_, err = client.DeleteTailnet(context.Background(), &api.DeleteTailnetRequest{TailnetId: tailnet.Id, Force: force})

if err != nil {
return err
}

fmt.Println("Tailnet deleted.")

return nil
}

return command
}
8 changes: 8 additions & 0 deletions internal/domain/auth_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ func (r *repository) DeleteAuthKey(ctx context.Context, id uint64) (bool, error)
return tx.RowsAffected == 1, tx.Error
}

func (r *repository) DeleteAuthKeysByTailnet(ctx context.Context, tailnetID uint64) error {
tx := r.withContext(ctx).
Where("tailnet_id = ?", tailnetID).
Delete(&AuthKey{TailnetID: tailnetID})

return tx.Error
}

func (r *repository) ListAuthKeys(ctx context.Context, tailnetID uint64) ([]AuthKey, error) {
var authKeys = []AuthKey{}
tx := (r.withContext(ctx).
Expand Down
17 changes: 17 additions & 0 deletions internal/domain/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,23 @@ func (r *repository) CountMachinesWithIPv4(ctx context.Context, ip string) (int6
return count, nil
}

func (r *repository) CountMachineByTailnet(ctx context.Context, tailnetID uint64) (int64, error) {
var count int64

tx := r.withContext(ctx).Model(&Machine{}).Where("tailnet_id = ?", tailnetID).Count(&count)

if tx.Error != nil {
return 0, tx.Error
}

return count, nil
}

func (r *repository) DeleteMachineByTailnet(ctx context.Context, tailnetID uint64) error {
tx := r.withContext(ctx).Model(&Machine{}).Where("tailnet_id = ?", tailnetID).Delete(&Machine{})
return tx.Error
}

func (r *repository) ListMachineByTailnet(ctx context.Context, tailnetID uint64) (Machines, error) {
var machines = []Machine{}

Expand Down
15 changes: 15 additions & 0 deletions internal/domain/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,24 @@ type Repository interface {
GetOrCreateTailnet(ctx context.Context, name string) (*Tailnet, bool, error)
GetTailnet(ctx context.Context, id uint64) (*Tailnet, error)
ListTailnets(ctx context.Context) ([]Tailnet, error)
DeleteTailnet(ctx context.Context, id uint64) error

GetDNSConfig(ctx context.Context, tailnetID uint64) (*DNSConfig, error)
SetDNSConfig(ctx context.Context, tailnetID uint64, config *DNSConfig) error
DeleteDNSConfig(ctx context.Context, tailnetID uint64) error
GetACLPolicy(ctx context.Context, tailnetID uint64) (*ACLPolicy, error)
SetACLPolicy(ctx context.Context, tailnetID uint64, policy *ACLPolicy) error
DeleteACLPolicy(ctx context.Context, tailnetID uint64) error

SaveAuthKey(ctx context.Context, key *AuthKey) error
DeleteAuthKey(ctx context.Context, id uint64) (bool, error)
DeleteAuthKeysByTailnet(ctx context.Context, tailnetID uint64) error
ListAuthKeys(ctx context.Context, tailnetID uint64) ([]AuthKey, error)
LoadAuthKey(ctx context.Context, key string) (*AuthKey, error)

GetOrCreateServiceUser(ctx context.Context, tailnet *Tailnet) (*User, bool, error)
ListUsers(ctx context.Context, tailnetID uint64) (Users, error)
DeleteUsersByTailnet(ctx context.Context, tailnetID uint64) error

SaveMachine(ctx context.Context, m *Machine) error
DeleteMachine(ctx context.Context, id uint64) (bool, error)
Expand All @@ -36,9 +41,13 @@ type Repository interface {
CountMachinesWithIPv4(ctx context.Context, ip string) (int64, error)
GetNextMachineNameIndex(ctx context.Context, tailnetID uint64, name string) (uint64, error)
ListMachineByTailnet(ctx context.Context, tailnetID uint64) (Machines, error)
CountMachineByTailnet(ctx context.Context, tailnetID uint64) (int64, error)
DeleteMachineByTailnet(ctx context.Context, tailnetID uint64) error
ListMachinePeers(ctx context.Context, tailnetID uint64, key string) (Machines, error)
ListInactiveEphemeralMachines(ctx context.Context, checkpoint time.Time) (Machines, error)
SetMachineLastSeen(ctx context.Context, machineID uint64) error

Transaction(func(rp Repository) error) error
}

func NewRepository(db *gorm.DB) Repository {
Expand All @@ -54,3 +63,9 @@ type repository struct {
func (r *repository) withContext(ctx context.Context) *gorm.DB {
return r.db.WithContext(ctx)
}

func (r *repository) Transaction(action func(Repository) error) error {
return r.db.Transaction(func(tx *gorm.DB) error {
return action(NewRepository(tx))
})
}
5 changes: 5 additions & 0 deletions internal/domain/tailnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,8 @@ func (r *repository) ListTailnets(ctx context.Context) ([]Tailnet, error) {
}
return tailnets, nil
}

func (r *repository) DeleteTailnet(ctx context.Context, id uint64) error {
tx := r.withContext(ctx).Delete(&Tailnet{ID: id})
return tx.Error
}
18 changes: 18 additions & 0 deletions internal/domain/tailnet_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ func (r *repository) SetDNSConfig(ctx context.Context, tailnetID uint64, config
return r.setConfig(ctx, "dns_config", tailnetID, config)
}

func (r *repository) DeleteDNSConfig(ctx context.Context, tailnetID uint64) error {
return r.deleteConfig(ctx, "dns_config", tailnetID)
}

func (r *repository) SetACLPolicy(ctx context.Context, tailnetID uint64, policy *ACLPolicy) error {
if err := r.setConfig(ctx, "acl_policy", tailnetID, policy); err != nil {
return err
Expand All @@ -49,6 +53,10 @@ func (r *repository) GetACLPolicy(ctx context.Context, tailnetID uint64) (*ACLPo
return &p, nil
}

func (r *repository) DeleteACLPolicy(ctx context.Context, tailnetID uint64) error {
return r.deleteConfig(ctx, "acl_policy", tailnetID)
}

func (r *repository) getConfig(ctx context.Context, s string, tailnetID uint64, v interface{}) error {
var m TailnetConfig
tx := r.withContext(ctx).Take(&m, "key = ? AND tailnet_id = ?", s, tailnetID)
Expand Down Expand Up @@ -83,3 +91,13 @@ func (r *repository) setConfig(ctx context.Context, s string, tailnetID uint64,

return tx.Error
}

func (r *repository) deleteConfig(ctx context.Context, s string, tailnetID uint64) error {
c := &TailnetConfig{
Key: s,
TailnetID: tailnetID,
}
tx := r.withContext(ctx).Delete(c)

return tx.Error
}
5 changes: 5 additions & 0 deletions internal/domain/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,8 @@ func (r *repository) ListUsers(ctx context.Context, tailnetID uint64) (Users, er

return users, nil
}

func (r *repository) DeleteUsersByTailnet(ctx context.Context, tailnetID uint64) error {
tx := r.withContext(ctx).Where("tailnet_id = ?", tailnetID).Delete(&User{})
return tx.Error
}
51 changes: 51 additions & 0 deletions internal/service/tailnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package service
import (
"context"
"fmt"
"github.com/jsiebens/ionscale/internal/domain"
"github.com/jsiebens/ionscale/pkg/gen/api"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func (s *Service) CreateTailnet(ctx context.Context, req *api.CreateTailnetRequest) (*api.CreateTailnetResponse, error) {
Expand Down Expand Up @@ -37,3 +40,51 @@ func (s *Service) ListTailnets(ctx context.Context, _ *api.ListTailnetRequest) (
}
return resp, nil
}

func (s *Service) DeleteTailnet(ctx context.Context, req *api.DeleteTailnetRequest) (*api.DeleteTailnetResponse, error) {

count, err := s.repository.CountMachineByTailnet(ctx, req.TailnetId)
if err != nil {
return nil, err
}

if !req.Force && count > 0 {
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("tailnet is not empty, number of machines: %d", count))
}

err = s.repository.Transaction(func(tx domain.Repository) error {
if err := tx.DeleteMachineByTailnet(ctx, req.TailnetId); err != nil {
return err
}

if err := tx.DeleteAuthKeysByTailnet(ctx, req.TailnetId); err != nil {
return err
}

if err := tx.DeleteUsersByTailnet(ctx, req.TailnetId); err != nil {
return err
}

if err := tx.DeleteACLPolicy(ctx, req.TailnetId); err != nil {
return err
}

if err := tx.DeleteDNSConfig(ctx, req.TailnetId); err != nil {
return err
}

if err := tx.DeleteTailnet(ctx, req.TailnetId); err != nil {
return err
}

return nil
})

if err != nil {
return nil, err
}

s.brokers(req.TailnetId).SignalTailnedDeleted()

return &api.DeleteTailnetResponse{}, nil
}
Loading

0 comments on commit 9769f40

Please sign in to comment.