mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-28 23:39:07 +01:00
[management] shift network map data store onto the read replica (#8302)
This commit is contained in:
@@ -6,9 +6,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go.uber.org/mock/gomock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/mock/gomock"
|
||||
|
||||
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/proxy"
|
||||
rpservice "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/service"
|
||||
@@ -38,6 +38,7 @@ func setupL4Test(t *testing.T, customPortsSupported *bool) (*Manager, store.Stor
|
||||
err = testStore.SaveAccount(ctx, &types.Account{
|
||||
Id: testAccountID,
|
||||
CreatedBy: testUserID,
|
||||
Network: types.NewNetwork(),
|
||||
Settings: &types.Settings{
|
||||
PeerExposeEnabled: true,
|
||||
PeerExposeGroups: []string{testGroupID},
|
||||
|
||||
@@ -363,6 +363,10 @@ func (m *Manager) persistNewService(ctx context.Context, accountID string, svc *
|
||||
return fmt.Errorf("create service: %w", err)
|
||||
}
|
||||
|
||||
if err := transaction.IncrementNetworkSerial(ctx, accountID); err != nil {
|
||||
return fmt.Errorf("increment network serial: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -534,6 +538,10 @@ func (m *Manager) persistNewEphemeralService(ctx context.Context, accountID, pee
|
||||
return fmt.Errorf("create service: %w", err)
|
||||
}
|
||||
|
||||
if err := transaction.IncrementNetworkSerial(ctx, accountID); err != nil {
|
||||
return fmt.Errorf("increment network serial: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -744,6 +752,10 @@ func (m *Manager) executeServiceUpdate(ctx context.Context, transaction store.St
|
||||
return fmt.Errorf("update service: %w", err)
|
||||
}
|
||||
|
||||
if err := transaction.IncrementNetworkSerial(ctx, accountID); err != nil {
|
||||
return fmt.Errorf("increment network serial: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1027,6 +1039,10 @@ func (m *Manager) DeleteService(ctx context.Context, accountID, userID, serviceI
|
||||
return fmt.Errorf("failed to delete service: %w", err)
|
||||
}
|
||||
|
||||
if err = transaction.IncrementNetworkSerial(ctx, accountID); err != nil {
|
||||
return fmt.Errorf("increment network serial: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1069,6 +1085,12 @@ func (m *Manager) DeleteAllServices(ctx context.Context, accountID, userID strin
|
||||
}
|
||||
}
|
||||
|
||||
if len(services) > 0 {
|
||||
if err = transaction.IncrementNetworkSerial(ctx, accountID); err != nil {
|
||||
return fmt.Errorf("increment network serial: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1425,6 +1447,10 @@ func (m *Manager) deletePeerService(ctx context.Context, accountID, peerID, serv
|
||||
return fmt.Errorf("delete service: %w", err)
|
||||
}
|
||||
|
||||
if err = transaction.IncrementNetworkSerial(ctx, accountID); err != nil {
|
||||
return fmt.Errorf("increment network serial: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1477,6 +1503,11 @@ func (m *Manager) deleteExpiredPeerService(ctx context.Context, accountID, peerI
|
||||
if err = transaction.DeleteService(ctx, accountID, serviceID); err != nil {
|
||||
return fmt.Errorf("delete service: %w", err)
|
||||
}
|
||||
|
||||
if err = transaction.IncrementNetworkSerial(ctx, accountID); err != nil {
|
||||
return fmt.Errorf("increment network serial: %w", err)
|
||||
}
|
||||
|
||||
deleted = true
|
||||
|
||||
return nil
|
||||
|
||||
@@ -227,6 +227,13 @@ func TestCheckDomainAvailable_EdgeCases(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func networkSerial(t *testing.T, s store.Store, accountID string) uint64 {
|
||||
t.Helper()
|
||||
account, err := s.GetAccount(context.Background(), accountID)
|
||||
require.NoError(t, err)
|
||||
return account.Network.Serial
|
||||
}
|
||||
|
||||
func TestPersistNewService(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
accountID := "test-account"
|
||||
@@ -254,6 +261,9 @@ func TestPersistNewService(t *testing.T) {
|
||||
txMock.EXPECT().
|
||||
CreateService(ctx, service).
|
||||
Return(nil)
|
||||
txMock.EXPECT().
|
||||
IncrementNetworkSerial(ctx, accountID).
|
||||
Return(nil)
|
||||
|
||||
return fn(txMock)
|
||||
})
|
||||
@@ -465,6 +475,9 @@ func TestDeletePeerService_SourcePeerValidation(t *testing.T) {
|
||||
txMock.EXPECT().
|
||||
DeleteService(ctx, accountID, serviceID).
|
||||
Return(nil)
|
||||
txMock.EXPECT().
|
||||
IncrementNetworkSerial(ctx, accountID).
|
||||
Return(nil)
|
||||
return fn(txMock)
|
||||
})
|
||||
mockStore.EXPECT().
|
||||
@@ -570,6 +583,9 @@ func TestDeletePeerService_SourcePeerValidation(t *testing.T) {
|
||||
txMock.EXPECT().
|
||||
DeleteService(ctx, accountID, serviceID).
|
||||
Return(nil)
|
||||
txMock.EXPECT().
|
||||
IncrementNetworkSerial(ctx, accountID).
|
||||
Return(nil)
|
||||
return fn(txMock)
|
||||
})
|
||||
mockStore.EXPECT().
|
||||
@@ -617,6 +633,9 @@ func TestDeletePeerService_SourcePeerValidation(t *testing.T) {
|
||||
txMock.EXPECT().
|
||||
DeleteService(ctx, accountID, serviceID).
|
||||
Return(nil)
|
||||
txMock.EXPECT().
|
||||
IncrementNetworkSerial(ctx, accountID).
|
||||
Return(nil)
|
||||
return fn(txMock)
|
||||
})
|
||||
mockStore.EXPECT().
|
||||
@@ -679,6 +698,7 @@ func setupIntegrationTest(t *testing.T) (*Manager, store.Store) {
|
||||
err = testStore.SaveAccount(ctx, &types.Account{
|
||||
Id: testAccountID,
|
||||
CreatedBy: testUserID,
|
||||
Network: types.NewNetwork(),
|
||||
Settings: &types.Settings{
|
||||
PeerExposeEnabled: true,
|
||||
PeerExposeGroups: []string{testGroupID},
|
||||
@@ -843,6 +863,7 @@ func TestCreateServiceFromPeer(t *testing.T) {
|
||||
assert.Equal(t, rpservice.SourceEphemeral, persisted.Source, "source should be ephemeral")
|
||||
assert.Equal(t, testPeerID, persisted.SourcePeer, "source peer should be set")
|
||||
assert.NotNil(t, persisted.Meta.LastRenewedAt, "last renewed should be set")
|
||||
assert.Equal(t, uint64(1), networkSerial(t, testStore, testAccountID), "network serial should be incremented")
|
||||
})
|
||||
|
||||
t.Run("creates service with custom domain", func(t *testing.T) {
|
||||
@@ -1049,8 +1070,10 @@ func TestDeleteService_DeletesEphemeralExpose(t *testing.T) {
|
||||
svc, err := testStore.GetServiceByDomain(ctx, resp.Domain)
|
||||
require.NoError(t, err)
|
||||
|
||||
serial := networkSerial(t, testStore, testAccountID)
|
||||
err = mgr.DeleteService(ctx, testAccountID, testUserID, svc.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, serial+1, networkSerial(t, testStore, testAccountID), "network serial should be incremented")
|
||||
|
||||
count, err = mgr.store.CountEphemeralServicesByPeer(ctx, store.LockingStrengthNone, testAccountID, testPeerID)
|
||||
require.NoError(t, err)
|
||||
@@ -1065,7 +1088,7 @@ func TestDeleteService_DeletesEphemeralExpose(t *testing.T) {
|
||||
|
||||
func TestDeleteAllServices_DeletesEphemeralExposes(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
mgr, _ := setupIntegrationTest(t)
|
||||
mgr, testStore := setupIntegrationTest(t)
|
||||
|
||||
for i := range 3 {
|
||||
_, err := mgr.CreateServiceFromPeer(ctx, testAccountID, testPeerID, &rpservice.ExposeServiceRequest{
|
||||
@@ -1079,8 +1102,10 @@ func TestDeleteAllServices_DeletesEphemeralExposes(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(3), count, "all ephemeral services should exist")
|
||||
|
||||
serial := networkSerial(t, testStore, testAccountID)
|
||||
err = mgr.DeleteAllServices(ctx, testAccountID, testUserID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, serial+1, networkSerial(t, testStore, testAccountID), "network serial should be incremented")
|
||||
|
||||
count, err = mgr.store.CountEphemeralServicesByPeer(ctx, store.LockingStrengthNone, testAccountID, testPeerID)
|
||||
require.NoError(t, err)
|
||||
@@ -1223,8 +1248,10 @@ func TestDeleteExpiredPeerService_DeletesTargets(t *testing.T) {
|
||||
require.Len(t, targets, 1, "ephemeral peer-exposed service should have exactly one persisted target before reaping")
|
||||
|
||||
expireEphemeralService(t, testStore, testAccountID, resp.Domain)
|
||||
serial := networkSerial(t, testStore, testAccountID)
|
||||
err = mgr.deleteExpiredPeerService(ctx, testAccountID, testPeerID, svcID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, serial+1, networkSerial(t, testStore, testAccountID), "network serial should be incremented")
|
||||
|
||||
_, err = testStore.GetServiceByDomain(ctx, resp.Domain)
|
||||
require.Error(t, err, "expired peer-exposed service should be deleted")
|
||||
@@ -1253,8 +1280,10 @@ func TestDeleteServiceFromPeer_DeletesTargets(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, targets, 1, "ephemeral peer-exposed service should have exactly one persisted target before stopping")
|
||||
|
||||
serial := networkSerial(t, testStore, testAccountID)
|
||||
err = mgr.StopServiceFromPeer(ctx, testAccountID, testPeerID, svcID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, serial+1, networkSerial(t, testStore, testAccountID), "network serial should be incremented")
|
||||
|
||||
_, err = testStore.GetServiceByDomain(ctx, resp.Domain)
|
||||
require.Error(t, err, "stopped peer-exposed service should be deleted")
|
||||
@@ -1521,3 +1550,30 @@ func TestReloadAllServicesForAccount_ContinuesAfterFailedService(t *testing.T) {
|
||||
assert.Contains(t, err.Error(), "svc-broken")
|
||||
assert.NotContains(t, err.Error(), "svc-healthy")
|
||||
}
|
||||
|
||||
func TestServiceWrites_IncrementNetworkSerial(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
mgr, testStore, _ := setupL4Test(t, nil)
|
||||
|
||||
created, err := mgr.CreateService(ctx, testAccountID, testUserID, &rpservice.Service{
|
||||
Name: "serial", Domain: "serial.test.netbird.io", Mode: rpservice.ModeHTTP, Enabled: true,
|
||||
Targets: []*rpservice.Target{{
|
||||
AccountID: testAccountID, TargetId: testPeerID,
|
||||
TargetType: rpservice.TargetTypePeer, Protocol: "http", Port: 8080, Enabled: true,
|
||||
}},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
serial := networkSerial(t, testStore, testAccountID)
|
||||
assert.Equal(t, uint64(1), serial, "create should increment the network serial")
|
||||
|
||||
updated := created.Copy()
|
||||
updated.Name = "serial renamed"
|
||||
_, err = mgr.UpdateService(ctx, testAccountID, testUserID, updated)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, serial+1, networkSerial(t, testStore, testAccountID), "update should increment the network serial")
|
||||
serial++
|
||||
|
||||
require.NoError(t, mgr.SetStatus(ctx, testAccountID, created.ID, rpservice.StatusActive))
|
||||
require.NoError(t, mgr.SetCertificateIssuedAt(ctx, testAccountID, created.ID))
|
||||
assert.Equal(t, serial, networkSerial(t, testStore, testAccountID), "meta-only writes must not increment the network serial")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user