mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-20 20:39:08 +02:00
[management] network map for affected peers (#6105)
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/service"
|
||||
"github.com/netbirdio/netbird/management/server/account"
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
"github.com/netbirdio/netbird/management/server/affectedpeers"
|
||||
"github.com/netbirdio/netbird/management/server/groups"
|
||||
"github.com/netbirdio/netbird/management/server/networks/resources/types"
|
||||
"github.com/netbirdio/netbird/management/server/permissions"
|
||||
@@ -29,7 +30,7 @@ type Manager interface {
|
||||
GetResource(ctx context.Context, accountID, userID, networkID, resourceID string) (*types.NetworkResource, error)
|
||||
UpdateResource(ctx context.Context, userID string, resource *types.NetworkResource) (*types.NetworkResource, error)
|
||||
DeleteResource(ctx context.Context, accountID, userID, networkID, resourceID string) error
|
||||
DeleteResourceInTransaction(ctx context.Context, transaction store.Store, accountID, userID, networkID, resourceID string) ([]func(), error)
|
||||
DeleteResourceInTransaction(ctx context.Context, transaction store.Store, accountID, userID, networkID, resourceID string) (*types.NetworkResource, []func(), error)
|
||||
}
|
||||
|
||||
type managerImpl struct {
|
||||
@@ -114,45 +115,12 @@ func (m *managerImpl) CreateResource(ctx context.Context, userID string, resourc
|
||||
}
|
||||
|
||||
var eventsToStore []func()
|
||||
var snap *affectedpeers.Snapshot
|
||||
change := affectedpeers.Change{Resources: []*types.NetworkResource{resource}}
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
_, err = transaction.GetNetworkResourceByName(ctx, store.LockingStrengthNone, resource.AccountID, resource.Name)
|
||||
if err == nil {
|
||||
return status.Errorf(status.InvalidArgument, "resource with name %s already exists", resource.Name)
|
||||
}
|
||||
|
||||
network, err := transaction.GetNetworkByID(ctx, store.LockingStrengthUpdate, resource.AccountID, resource.NetworkID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
err = transaction.SaveNetworkResource(ctx, resource)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to save network resource: %w", err)
|
||||
}
|
||||
|
||||
event := func() {
|
||||
m.accountManager.StoreEvent(ctx, userID, resource.ID, resource.AccountID, activity.NetworkResourceCreated, resource.EventMeta(network))
|
||||
}
|
||||
eventsToStore = append(eventsToStore, event)
|
||||
|
||||
res := nbtypes.Resource{
|
||||
ID: resource.ID,
|
||||
Type: nbtypes.ResourceType(resource.Type.String()),
|
||||
}
|
||||
for _, groupID := range resource.GroupIDs {
|
||||
event, err := m.groupsManager.AddResourceToGroupInTransaction(ctx, transaction, resource.AccountID, userID, groupID, &res)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add resource to group: %w", err)
|
||||
}
|
||||
eventsToStore = append(eventsToStore, event)
|
||||
}
|
||||
|
||||
err = transaction.IncrementNetworkSerial(ctx, resource.AccountID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to increment network serial: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
var txErr error
|
||||
eventsToStore, snap, txErr = m.createResourceInTransaction(ctx, transaction, userID, resource, change)
|
||||
return txErr
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create network resource: %w", err)
|
||||
@@ -162,11 +130,55 @@ func (m *managerImpl) CreateResource(ctx context.Context, userID string, resourc
|
||||
event()
|
||||
}
|
||||
|
||||
go m.accountManager.UpdateAccountPeers(ctx, resource.AccountID, nbtypes.UpdateReason{Resource: nbtypes.UpdateResourceNetworkResource, Operation: nbtypes.UpdateOperationCreate})
|
||||
m.accountManager.ExpandAndUpdateAffected(ctx, resource.AccountID, snap, change)
|
||||
|
||||
return resource, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) createResourceInTransaction(ctx context.Context, transaction store.Store, userID string, resource *types.NetworkResource, change affectedpeers.Change) ([]func(), *affectedpeers.Snapshot, error) {
|
||||
_, err := transaction.GetNetworkResourceByName(ctx, store.LockingStrengthNone, resource.AccountID, resource.Name)
|
||||
if err == nil {
|
||||
return nil, nil, status.Errorf(status.InvalidArgument, "resource with name %s already exists", resource.Name)
|
||||
}
|
||||
|
||||
network, err := transaction.GetNetworkByID(ctx, store.LockingStrengthUpdate, resource.AccountID, resource.NetworkID)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
if err = transaction.SaveNetworkResource(ctx, resource); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to save network resource: %w", err)
|
||||
}
|
||||
|
||||
var eventsToStore []func()
|
||||
eventsToStore = append(eventsToStore, func() {
|
||||
m.accountManager.StoreEvent(ctx, userID, resource.ID, resource.AccountID, activity.NetworkResourceCreated, resource.EventMeta(network))
|
||||
})
|
||||
|
||||
res := nbtypes.Resource{
|
||||
ID: resource.ID,
|
||||
Type: nbtypes.ResourceType(resource.Type.String()),
|
||||
}
|
||||
for _, groupID := range resource.GroupIDs {
|
||||
event, err := m.groupsManager.AddResourceToGroupInTransaction(ctx, transaction, resource.AccountID, userID, groupID, &res)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to add resource to group: %w", err)
|
||||
}
|
||||
eventsToStore = append(eventsToStore, event)
|
||||
}
|
||||
|
||||
if err = transaction.IncrementNetworkSerial(ctx, resource.AccountID); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to increment network serial: %w", err)
|
||||
}
|
||||
|
||||
snap, err := affectedpeers.Load(ctx, transaction, resource.AccountID, change)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return eventsToStore, snap, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) GetResource(ctx context.Context, accountID, userID, networkID, resourceID string) (*types.NetworkResource, error) {
|
||||
ok, ctx, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Read)
|
||||
if err != nil {
|
||||
@@ -207,6 +219,8 @@ func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resourc
|
||||
resource.Prefix = prefix
|
||||
|
||||
var eventsToStore []func()
|
||||
var snap *affectedpeers.Snapshot
|
||||
var change affectedpeers.Change
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
network, err := transaction.GetNetworkByID(ctx, store.LockingStrengthUpdate, resource.AccountID, resource.NetworkID)
|
||||
if err != nil {
|
||||
@@ -232,6 +246,14 @@ func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resourc
|
||||
return fmt.Errorf("failed to get network resource: %w", err)
|
||||
}
|
||||
|
||||
oldGroups, err := m.groupsManager.GetResourceGroupsInTransaction(ctx, transaction, store.LockingStrengthNone, resource.AccountID, resource.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get old resource groups: %w", err)
|
||||
}
|
||||
for _, g := range oldGroups {
|
||||
oldResource.GroupIDs = append(oldResource.GroupIDs, g.ID)
|
||||
}
|
||||
|
||||
err = transaction.SaveNetworkResource(ctx, resource)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to save network resource: %w", err)
|
||||
@@ -247,6 +269,11 @@ func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resourc
|
||||
m.accountManager.StoreEvent(ctx, userID, resource.ID, resource.AccountID, activity.NetworkResourceUpdated, resource.EventMeta(network))
|
||||
})
|
||||
|
||||
change = affectedpeers.Change{Resources: []*types.NetworkResource{oldResource, resource}}
|
||||
if snap, err = affectedpeers.Load(ctx, transaction, resource.AccountID, change); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = transaction.IncrementNetworkSerial(ctx, resource.AccountID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to increment network serial: %w", err)
|
||||
@@ -270,7 +297,7 @@ func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resourc
|
||||
}
|
||||
}()
|
||||
|
||||
go m.accountManager.UpdateAccountPeers(ctx, resource.AccountID, nbtypes.UpdateReason{Resource: nbtypes.UpdateResourceNetworkResource, Operation: nbtypes.UpdateOperationUpdate})
|
||||
m.accountManager.ExpandAndUpdateAffected(ctx, resource.AccountID, snap, change)
|
||||
|
||||
return resource, nil
|
||||
}
|
||||
@@ -331,8 +358,26 @@ func (m *managerImpl) DeleteResource(ctx context.Context, accountID, userID, net
|
||||
}
|
||||
|
||||
var events []func()
|
||||
var snap *affectedpeers.Snapshot
|
||||
var change affectedpeers.Change
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
events, err = m.DeleteResourceInTransaction(ctx, transaction, accountID, userID, networkID, resourceID)
|
||||
existing, err := transaction.GetNetworkResourceByID(ctx, store.LockingStrengthUpdate, accountID, resourceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network resource: %w", err)
|
||||
}
|
||||
oldGroups, err := m.groupsManager.GetResourceGroupsInTransaction(ctx, transaction, store.LockingStrengthNone, accountID, resourceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get resource groups: %w", err)
|
||||
}
|
||||
for _, g := range oldGroups {
|
||||
existing.GroupIDs = append(existing.GroupIDs, g.ID)
|
||||
}
|
||||
change = affectedpeers.Change{Resources: []*types.NetworkResource{existing}}
|
||||
if snap, err = affectedpeers.Load(ctx, transaction, accountID, change); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, events, err = m.DeleteResourceInTransaction(ctx, transaction, accountID, userID, networkID, resourceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete resource: %w", err)
|
||||
}
|
||||
@@ -352,51 +397,53 @@ func (m *managerImpl) DeleteResource(ctx context.Context, accountID, userID, net
|
||||
event()
|
||||
}
|
||||
|
||||
go m.accountManager.UpdateAccountPeers(ctx, accountID, nbtypes.UpdateReason{Resource: nbtypes.UpdateResourceNetworkResource, Operation: nbtypes.UpdateOperationDelete})
|
||||
m.accountManager.ExpandAndUpdateAffected(ctx, accountID, snap, change)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) DeleteResourceInTransaction(ctx context.Context, transaction store.Store, accountID, userID, networkID, resourceID string) ([]func(), error) {
|
||||
func (m *managerImpl) DeleteResourceInTransaction(ctx context.Context, transaction store.Store, accountID, userID, networkID, resourceID string) (*types.NetworkResource, []func(), error) {
|
||||
resource, err := transaction.GetNetworkResourceByID(ctx, store.LockingStrengthUpdate, accountID, resourceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get network resource: %w", err)
|
||||
return nil, nil, fmt.Errorf("failed to get network resource: %w", err)
|
||||
}
|
||||
|
||||
network, err := transaction.GetNetworkByID(ctx, store.LockingStrengthUpdate, accountID, networkID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get network: %w", err)
|
||||
return nil, nil, fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
if resource.NetworkID != networkID {
|
||||
return nil, errors.New("resource not part of network")
|
||||
return nil, nil, errors.New("resource not part of network")
|
||||
}
|
||||
|
||||
groups, err := m.groupsManager.GetResourceGroupsInTransaction(ctx, transaction, store.LockingStrengthUpdate, accountID, resourceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get resource groups: %w", err)
|
||||
return nil, nil, fmt.Errorf("failed to get resource groups: %w", err)
|
||||
}
|
||||
|
||||
var eventsToStore []func()
|
||||
|
||||
for _, group := range groups {
|
||||
resource.GroupIDs = append(resource.GroupIDs, group.ID)
|
||||
|
||||
event, err := m.groupsManager.RemoveResourceFromGroupInTransaction(ctx, transaction, accountID, userID, group.ID, resourceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to remove resource from group: %w", err)
|
||||
return nil, nil, fmt.Errorf("failed to remove resource from group: %w", err)
|
||||
}
|
||||
eventsToStore = append(eventsToStore, event)
|
||||
}
|
||||
|
||||
err = transaction.DeleteNetworkResource(ctx, accountID, resourceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to delete network resource: %w", err)
|
||||
return nil, nil, fmt.Errorf("failed to delete network resource: %w", err)
|
||||
}
|
||||
|
||||
eventsToStore = append(eventsToStore, func() {
|
||||
m.accountManager.StoreEvent(ctx, userID, resourceID, accountID, activity.NetworkResourceDeleted, resource.EventMeta(network))
|
||||
})
|
||||
|
||||
return eventsToStore, nil
|
||||
return resource, eventsToStore, nil
|
||||
}
|
||||
|
||||
func NewManagerMock() Manager {
|
||||
@@ -431,6 +478,6 @@ func (m *mockManager) DeleteResource(ctx context.Context, accountID, userID, net
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockManager) DeleteResourceInTransaction(ctx context.Context, transaction store.Store, accountID, userID, networkID, resourceID string) ([]func(), error) {
|
||||
return []func(){}, nil
|
||||
func (m *mockManager) DeleteResourceInTransaction(ctx context.Context, transaction store.Store, accountID, userID, networkID, resourceID string) (*types.NetworkResource, []func(), error) {
|
||||
return nil, []func(){}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user