Add network resources store implementation

Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com>
This commit is contained in:
bcmmbaga 2024-12-10 16:42:11 +01:00
parent 6dd6992415
commit 382dba4a85
No known key found for this signature in database
GPG Key ID: 511EED5C928AD547
6 changed files with 187 additions and 12 deletions

View File

@ -278,8 +278,9 @@ type Account struct {
// Settings is a dictionary of Account settings
Settings *Settings `gorm:"embedded;embeddedPrefix:settings_"`
Networks []*networks.Network `gorm:"foreignKey:AccountID;references:id"`
NetworkRouters []*networks.NetworkRouter `gorm:"foreignKey:AccountID;references:id"`
Networks []*networks.Network `gorm:"foreignKey:AccountID;references:id"`
NetworkRouters []*networks.NetworkRouter `gorm:"foreignKey:AccountID;references:id"`
NetworkResources []*networks.NetworkResource `gorm:"foreignKey:AccountID;references:id"`
}
// Subclass used in gorm to only load settings and not whole account

View File

@ -1704,22 +1704,54 @@ func (s *SqlStore) DeleteNetworkRouter(ctx context.Context, lockStrength Locking
return nil
}
func (s *SqlStore) GetAccountNetworkResourceByNetID(ctx context.Context, lockStrength LockingStrength, accountID, networkID string) (*networks.NetworkResource, error) {
//TODO implement me
panic("implement me")
func (s *SqlStore) GetNetworkResourcesByNetID(ctx context.Context, lockStrength LockingStrength, accountID, networkID string) ([]*networks.NetworkResource, error) {
var netResources []*networks.NetworkResource
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).
Find(&netResources, "account_id = ? AND network_id = ?", accountID, networkID)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to get network resources from store: %v", result.Error)
return nil, status.Errorf(status.Internal, "failed to get network resources from store")
}
return netResources, nil
}
func (s *SqlStore) GetNetworkResourceByID(ctx context.Context, lockStrength LockingStrength, accountID, resourceID string) (*networks.NetworkResource, error) {
//TODO implement me
panic("implement me")
var netResources *networks.NetworkResource
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).
First(&netResources, accountAndIDQueryCondition, accountID, resourceID)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, status.NewNetworkResourceNotFoundError(resourceID)
}
log.WithContext(ctx).Errorf("failed to get network resource from store: %v", result.Error)
return nil, status.Errorf(status.Internal, "failed to get network resource from store")
}
return netResources, nil
}
func (s *SqlStore) SaveNetworkResource(ctx context.Context, lockStrength LockingStrength, resource *networks.NetworkResource) error {
//TODO implement me
panic("implement me")
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).Save(resource)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to save network resource to store: %v", result.Error)
return status.Errorf(status.Internal, "failed to save network resource to store")
}
return nil
}
func (s *SqlStore) DeleteNetworkResource(ctx context.Context, lockStrength LockingStrength, accountID, resourceID string) error {
//TODO implement me
panic("implement me")
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).
Delete(&networks.NetworkResource{}, accountAndIDQueryCondition, accountID, resourceID)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to delete network resource from store: %v", result.Error)
return status.Errorf(status.Internal, "failed to delete network resource from store")
}
if result.RowsAffected == 0 {
return status.NewNetworkResourceNotFoundError(resourceID)
}
return nil
}

View File

@ -325,6 +325,17 @@ func TestSqlite_DeleteAccount(t *testing.T) {
Metric: 1,
},
}
account.NetworkResources = []*networks.NetworkResource{
{
ID: "resource_id",
NetworkID: account.Networks[0].ID,
AccountID: account.Id,
Name: "Name",
Description: "Description",
Type: "Domain",
Address: "example.com",
},
}
err = store.SaveAccount(context.Background(), account)
require.NoError(t, err)
@ -375,6 +386,10 @@ func TestSqlite_DeleteAccount(t *testing.T) {
routers, err := store.GetNetworkRoutersByNetID(context.Background(), LockingStrengthShare, account.Id, network.ID)
require.NoError(t, err, "expecting no error after removing DeleteAccount when searching for network routers")
require.Len(t, routers, 0, "expecting no network routers to be found after DeleteAccount")
resources, err := store.GetNetworkResourcesByNetID(context.Background(), LockingStrengthShare, account.Id, network.ID)
require.NoError(t, err, "expecting no error after removing DeleteAccount when searching for network resources")
require.Len(t, resources, 0, "expecting no network resources to be found after DeleteAccount")
}
}
@ -2309,3 +2324,120 @@ func TestSqlStore_DeleteNetworkRouter(t *testing.T) {
require.Equal(t, status.NotFound, sErr.Type())
require.Nil(t, netRouter)
}
func TestSqlStore_GetNetworkResourcesByNetID(t *testing.T) {
store, cleanup, err := NewTestStoreFromSQL(context.Background(), "testdata/store.sql", t.TempDir())
t.Cleanup(cleanup)
require.NoError(t, err)
accountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
tests := []struct {
name string
networkID string
expectedCount int
}{
{
name: "retrieve resources by existing network ID",
networkID: "ct286bi7qv930dsrrug0",
expectedCount: 1,
},
{
name: "retrieve resources by non-existing network ID",
networkID: "non-existent",
expectedCount: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resources, err := store.GetNetworkResourcesByNetID(context.Background(), LockingStrengthShare, accountID, tt.networkID)
require.NoError(t, err)
require.Len(t, resources, tt.expectedCount)
})
}
}
func TestSqlStore_GetNetworkResourceByID(t *testing.T) {
store, cleanup, err := NewTestStoreFromSQL(context.Background(), "testdata/store.sql", t.TempDir())
t.Cleanup(cleanup)
require.NoError(t, err)
accountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
tests := []struct {
name string
networkResourceID string
expectError bool
}{
{
name: "retrieve existing network resource ID",
networkResourceID: "ctc4nci7qv9061u6ilfg",
expectError: false,
},
{
name: "retrieve non-existing network resource ID",
networkResourceID: "non-existing",
expectError: true,
},
{
name: "retrieve network with empty resource ID",
networkResourceID: "",
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
networkResource, err := store.GetNetworkResourceByID(context.Background(), LockingStrengthShare, accountID, tt.networkResourceID)
if tt.expectError {
require.Error(t, err)
sErr, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, sErr.Type(), status.NotFound)
require.Nil(t, networkResource)
} else {
require.NoError(t, err)
require.NotNil(t, networkResource)
require.Equal(t, tt.networkResourceID, networkResource.ID)
}
})
}
}
func TestSqlStore_SaveNetworkResource(t *testing.T) {
store, cleanup, err := NewTestStoreFromSQL(context.Background(), "testdata/store.sql", t.TempDir())
t.Cleanup(cleanup)
require.NoError(t, err)
accountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
networkID := "ct286bi7qv930dsrrug0"
netResource, err := networks.NewNetworkResource(accountID, networkID, "resource-name", "resource-description", "example.com")
require.NoError(t, err)
err = store.SaveNetworkResource(context.Background(), LockingStrengthUpdate, netResource)
require.NoError(t, err)
savedNetResource, err := store.GetNetworkResourceByID(context.Background(), LockingStrengthShare, accountID, netResource.ID)
require.NoError(t, err)
require.Equal(t, netResource, savedNetResource)
}
func TestSqlStore_DeleteNetworkResource(t *testing.T) {
store, cleanup, err := NewTestStoreFromSQL(context.Background(), "testdata/store.sql", t.TempDir())
t.Cleanup(cleanup)
require.NoError(t, err)
accountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
netResourceID := "ctc4nci7qv9061u6ilfg"
err = store.DeleteNetworkResource(context.Background(), LockingStrengthUpdate, accountID, netResourceID)
require.NoError(t, err)
netRouter, err := store.GetNetworkByID(context.Background(), LockingStrengthShare, accountID, netResourceID)
require.Error(t, err)
sErr, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, status.NotFound, sErr.Type())
require.Nil(t, netRouter)
}

View File

@ -164,3 +164,8 @@ func NewNetworkNotFoundError(networkID string) error {
func NewNetworkRouterNotFoundError(routerID string) error {
return Errorf(NotFound, "network router: %s not found", routerID)
}
// NewNetworkResourceNotFoundError creates a new Error with NotFound type for a missing network resource.
func NewNetworkResourceNotFoundError(resourceID string) error {
return Errorf(NotFound, "network resource: %s not found", resourceID)
}

View File

@ -152,7 +152,7 @@ type Store interface {
SaveNetworkRouter(ctx context.Context, lockStrength LockingStrength, router *networks.NetworkRouter) error
DeleteNetworkRouter(ctx context.Context, lockStrength LockingStrength, accountID, routerID string) error
GetAccountNetworkResourceByNetID(ctx context.Context, lockStrength LockingStrength, accountID, netID string) (*networks.NetworkResource, error)
GetNetworkResourcesByNetID(ctx context.Context, lockStrength LockingStrength, accountID, netID string) ([]*networks.NetworkResource, error)
GetNetworkResourceByID(ctx context.Context, lockStrength LockingStrength, accountID, resourceID string) (*networks.NetworkResource, error)
SaveNetworkResource(ctx context.Context, lockStrength LockingStrength, resource *networks.NetworkResource) error
DeleteNetworkResource(ctx context.Context, lockStrength LockingStrength, accountID, resourceID string) error

View File

@ -13,6 +13,7 @@ CREATE TABLE `extra_settings` (`peer_approval_enabled` numeric,`integrated_valid
CREATE TABLE `posture_checks` (`id` text,`name` text,`description` text,`account_id` text,`checks` text,PRIMARY KEY (`id`),CONSTRAINT `fk_accounts_posture_checks` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`));
CREATE TABLE `network_addresses` (`net_ip` text,`mac` text);
CREATE TABLE `network_routers` (`id` text,`network_id` text,`account_id` text,`peer` text,`peer_groups` text,`masquerade` numeric,`metric` integer,PRIMARY KEY (`id`));
CREATE TABLE `network_resources` (`id` text,`network_id` text,`account_id` text,`type` text,`address` text,PRIMARY KEY (`id`));
CREATE TABLE `networks` (`id` text,`account_id` text,`name` text,`description` text,PRIMARY KEY (`id`),CONSTRAINT `fk_accounts_networks` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`));
CREATE INDEX `idx_accounts_domain` ON `accounts`(`domain`);
CREATE INDEX `idx_setup_keys_account_id` ON `setup_keys`(`account_id`);
@ -29,6 +30,9 @@ CREATE INDEX `idx_posture_checks_account_id` ON `posture_checks`(`account_id`);
CREATE INDEX `idx_network_routers_id` ON `network_routers`(`id`);
CREATE INDEX `idx_network_routers_account_id` ON `network_routers`(`account_id`);
CREATE INDEX `idx_network_routers_network_id` ON `network_routers`(`network_id`);
CREATE INDEX `idx_network_resources_account_id` ON `network_resources`(`account_id`);
CREATE INDEX `idx_network_resources_network_id` ON `network_resources`(`network_id`);
CREATE INDEX `idx_network_resources_id` ON `network_resources`(`id`);
CREATE INDEX `idx_networks_id` ON `networks`(`id`);
CREATE INDEX `idx_networks_account_id` ON `networks`(`account_id`);
@ -42,4 +46,5 @@ INSERT INTO installations VALUES(1,'');
INSERT INTO policies VALUES('cs1tnh0hhcjnqoiuebf0','bf1c8084-ba50-4ce7-9439-34653001fc3b','Default','This is a default rule that allows connections between all the resources',1,'[]');
INSERT INTO policy_rules VALUES('cs387mkv2d4bgq41b6n0','cs1tnh0hhcjnqoiuebf0','Default','This is a default rule that allows connections between all the resources',1,'accept','["cs1tnh0hhcjnqoiuebeg"]','["cs1tnh0hhcjnqoiuebeg"]',1,'all',NULL,NULL);
INSERT INTO network_routers VALUES('ctc20ji7qv9ck2sebc80','ct286bi7qv930dsrrug0','bf1c8084-ba50-4ce7-9439-34653001fc3b','cs1tnh0hhcjnqoiuebeg',NULL,0,0);
INSERT INTO network_resources VALUES ('ctc4nci7qv9061u6ilfg','ct286bi7qv930dsrrug0','bf1c8084-ba50-4ce7-9439-34653001fc3b','Host','192.168.1.1');
INSERT INTO networks VALUES('ct286bi7qv930dsrrug0','bf1c8084-ba50-4ce7-9439-34653001fc3b','Test Network','Test Network');