Fed. node store implementation & gen. code
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package store
|
||||
|
||||
// This file is auto-generated.
|
||||
//
|
||||
// Template: pkg/codegen/assets/store_base.gen.go.tpl
|
||||
// Definitions: store/federation_nodes.yaml
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza-server/federation/types"
|
||||
)
|
||||
|
||||
type (
|
||||
FederationNodes interface {
|
||||
SearchFederationNodes(ctx context.Context, f types.NodeFilter) (types.NodeSet, types.NodeFilter, error)
|
||||
LookupFederationNodeByID(ctx context.Context, id uint64) (*types.Node, error)
|
||||
|
||||
CreateFederationNode(ctx context.Context, rr ...*types.Node) error
|
||||
|
||||
UpdateFederationNode(ctx context.Context, rr ...*types.Node) error
|
||||
|
||||
UpsertFederationNode(ctx context.Context, rr ...*types.Node) error
|
||||
|
||||
DeleteFederationNode(ctx context.Context, rr ...*types.Node) error
|
||||
DeleteFederationNodeByID(ctx context.Context, ID uint64) error
|
||||
|
||||
TruncateFederationNodes(ctx context.Context) error
|
||||
}
|
||||
)
|
||||
|
||||
var _ *types.Node
|
||||
var _ context.Context
|
||||
|
||||
// SearchFederationNodes returns all matching FederationNodes from store
|
||||
func SearchFederationNodes(ctx context.Context, s FederationNodes, f types.NodeFilter) (types.NodeSet, types.NodeFilter, error) {
|
||||
return s.SearchFederationNodes(ctx, f)
|
||||
}
|
||||
|
||||
// LookupFederationNodeByID searches for shared federation node by ID
|
||||
//
|
||||
// It returns shared federation node
|
||||
func LookupFederationNodeByID(ctx context.Context, s FederationNodes, id uint64) (*types.Node, error) {
|
||||
return s.LookupFederationNodeByID(ctx, id)
|
||||
}
|
||||
|
||||
// CreateFederationNode creates one or more FederationNodes in store
|
||||
func CreateFederationNode(ctx context.Context, s FederationNodes, rr ...*types.Node) error {
|
||||
return s.CreateFederationNode(ctx, rr...)
|
||||
}
|
||||
|
||||
// UpdateFederationNode updates one or more (existing) FederationNodes in store
|
||||
func UpdateFederationNode(ctx context.Context, s FederationNodes, rr ...*types.Node) error {
|
||||
return s.UpdateFederationNode(ctx, rr...)
|
||||
}
|
||||
|
||||
// UpsertFederationNode creates new or updates existing one or more FederationNodes in store
|
||||
func UpsertFederationNode(ctx context.Context, s FederationNodes, rr ...*types.Node) error {
|
||||
return s.UpsertFederationNode(ctx, rr...)
|
||||
}
|
||||
|
||||
// DeleteFederationNode Deletes one or more FederationNodes from store
|
||||
func DeleteFederationNode(ctx context.Context, s FederationNodes, rr ...*types.Node) error {
|
||||
return s.DeleteFederationNode(ctx, rr...)
|
||||
}
|
||||
|
||||
// DeleteFederationNodeByID Deletes FederationNode from store
|
||||
func DeleteFederationNodeByID(ctx context.Context, s FederationNodes, ID uint64) error {
|
||||
return s.DeleteFederationNodeByID(ctx, ID)
|
||||
}
|
||||
|
||||
// TruncateFederationNodes Deletes all FederationNodes from store
|
||||
func TruncateFederationNodes(ctx context.Context, s FederationNodes) error {
|
||||
return s.TruncateFederationNodes(ctx)
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import:
|
||||
- github.com/cortezaproject/corteza-server/federation/types
|
||||
|
||||
types:
|
||||
type: types.Node
|
||||
|
||||
fields:
|
||||
- { field: ID }
|
||||
- { field: Name }
|
||||
- { field: SharedNodeID }
|
||||
- { field: BaseURL }
|
||||
- { field: Status }
|
||||
- { field: PairToken }
|
||||
- { field: AuthToken }
|
||||
- { field: CreatedBy }
|
||||
- { field: UpdatedBy }
|
||||
- { field: DeletedBy }
|
||||
- { field: CreatedAt }
|
||||
- { field: UpdatedAt }
|
||||
- { field: DeletedAt }
|
||||
|
||||
|
||||
lookups:
|
||||
- fields: [ID]
|
||||
description: |-
|
||||
searches for shared federation node by ID
|
||||
|
||||
It returns shared federation node
|
||||
|
||||
search:
|
||||
enablePaging: false
|
||||
enableSorting: false
|
||||
|
||||
rdbms:
|
||||
alias: fdn
|
||||
table: federation_nodes
|
||||
customFilterConverter: true
|
||||
mapFields:
|
||||
BaseURL: { column: base_url }
|
||||
SharedNodeID: { column: shared_node_id }
|
||||
@@ -18,6 +18,7 @@ package store
|
||||
// - store/credentials.yaml
|
||||
// - store/federation_exposed_modules.yaml
|
||||
// - store/federation_module_mappings.yaml
|
||||
// - store/federation_nodes.yaml
|
||||
// - store/federation_shared_modules.yaml
|
||||
// - store/labels.yaml
|
||||
// - store/messaging_attachments.yaml
|
||||
@@ -56,6 +57,7 @@ type (
|
||||
Credentials
|
||||
FederationExposedModules
|
||||
FederationModuleMappings
|
||||
FederationNodes
|
||||
FederationSharedModules
|
||||
Labels
|
||||
MessagingAttachments
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
package rdbms
|
||||
|
||||
// This file is an auto-generated file
|
||||
//
|
||||
// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl
|
||||
// Definitions: store/federation_nodes.yaml
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior
|
||||
// and will be lost if the code is regenerated.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/cortezaproject/corteza-server/federation/types"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
)
|
||||
|
||||
var _ = errors.Is
|
||||
|
||||
// SearchFederationNodes returns all matching rows
|
||||
//
|
||||
// This function calls convertFederationNodeFilter with the given
|
||||
// types.NodeFilter and expects to receive a working squirrel.SelectBuilder
|
||||
func (s Store) SearchFederationNodes(ctx context.Context, f types.NodeFilter) (types.NodeSet, types.NodeFilter, error) {
|
||||
var (
|
||||
err error
|
||||
set []*types.Node
|
||||
q squirrel.SelectBuilder
|
||||
)
|
||||
q, err = s.convertFederationNodeFilter(f)
|
||||
if err != nil {
|
||||
return nil, f, err
|
||||
}
|
||||
|
||||
return set, f, s.config.ErrorHandler(func() error {
|
||||
set, _, _, err = s.QueryFederationNodes(ctx, q, f.Check)
|
||||
return err
|
||||
|
||||
}())
|
||||
}
|
||||
|
||||
// QueryFederationNodes queries the database, converts and checks each row and
|
||||
// returns collected set
|
||||
//
|
||||
// Fn also returns total number of fetched items and last fetched item so that the caller can construct cursor
|
||||
// for next page of results
|
||||
func (s Store) QueryFederationNodes(
|
||||
ctx context.Context,
|
||||
q squirrel.Sqlizer,
|
||||
check func(*types.Node) (bool, error),
|
||||
) ([]*types.Node, uint, *types.Node, error) {
|
||||
var (
|
||||
set = make([]*types.Node, 0, DefaultSliceCapacity)
|
||||
res *types.Node
|
||||
|
||||
// Query rows with
|
||||
rows, err = s.Query(ctx, q)
|
||||
|
||||
fetched uint
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, nil, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
fetched++
|
||||
if err = rows.Err(); err == nil {
|
||||
res, err = s.internalFederationNodeRowScanner(rows)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, nil, err
|
||||
}
|
||||
|
||||
// If check function is set, call it and act accordingly
|
||||
if check != nil {
|
||||
if chk, err := check(res); err != nil {
|
||||
return nil, 0, nil, err
|
||||
} else if !chk {
|
||||
// did not pass the check
|
||||
// go with the next row
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
set = append(set, res)
|
||||
}
|
||||
|
||||
return set, fetched, res, rows.Err()
|
||||
}
|
||||
|
||||
// LookupFederationNodeByID searches for shared federation node by ID
|
||||
//
|
||||
// It returns shared federation node
|
||||
func (s Store) LookupFederationNodeByID(ctx context.Context, id uint64) (*types.Node, error) {
|
||||
return s.execLookupFederationNode(ctx, squirrel.Eq{
|
||||
s.preprocessColumn("fdn.id", ""): s.preprocessValue(id, ""),
|
||||
})
|
||||
}
|
||||
|
||||
// CreateFederationNode creates one or more rows in federation_nodes table
|
||||
func (s Store) CreateFederationNode(ctx context.Context, rr ...*types.Node) (err error) {
|
||||
for _, res := range rr {
|
||||
err = s.checkFederationNodeConstraints(ctx, res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.execCreateFederationNodes(ctx, s.internalFederationNodeEncoder(res))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateFederationNode updates one or more existing rows in federation_nodes
|
||||
func (s Store) UpdateFederationNode(ctx context.Context, rr ...*types.Node) error {
|
||||
return s.config.ErrorHandler(s.partialFederationNodeUpdate(ctx, nil, rr...))
|
||||
}
|
||||
|
||||
// partialFederationNodeUpdate updates one or more existing rows in federation_nodes
|
||||
func (s Store) partialFederationNodeUpdate(ctx context.Context, onlyColumns []string, rr ...*types.Node) (err error) {
|
||||
for _, res := range rr {
|
||||
err = s.checkFederationNodeConstraints(ctx, res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.execUpdateFederationNodes(
|
||||
ctx,
|
||||
squirrel.Eq{
|
||||
s.preprocessColumn("fdn.id", ""): s.preprocessValue(res.ID, ""),
|
||||
},
|
||||
s.internalFederationNodeEncoder(res).Skip("id").Only(onlyColumns...))
|
||||
if err != nil {
|
||||
return s.config.ErrorHandler(err)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UpsertFederationNode updates one or more existing rows in federation_nodes
|
||||
func (s Store) UpsertFederationNode(ctx context.Context, rr ...*types.Node) (err error) {
|
||||
for _, res := range rr {
|
||||
err = s.checkFederationNodeConstraints(ctx, res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.config.ErrorHandler(s.execUpsertFederationNodes(ctx, s.internalFederationNodeEncoder(res)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteFederationNode Deletes one or more rows from federation_nodes table
|
||||
func (s Store) DeleteFederationNode(ctx context.Context, rr ...*types.Node) (err error) {
|
||||
for _, res := range rr {
|
||||
|
||||
err = s.execDeleteFederationNodes(ctx, squirrel.Eq{
|
||||
s.preprocessColumn("fdn.id", ""): s.preprocessValue(res.ID, ""),
|
||||
})
|
||||
if err != nil {
|
||||
return s.config.ErrorHandler(err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteFederationNodeByID Deletes row from the federation_nodes table
|
||||
func (s Store) DeleteFederationNodeByID(ctx context.Context, ID uint64) error {
|
||||
return s.execDeleteFederationNodes(ctx, squirrel.Eq{
|
||||
s.preprocessColumn("fdn.id", ""): s.preprocessValue(ID, ""),
|
||||
})
|
||||
}
|
||||
|
||||
// TruncateFederationNodes Deletes all rows from the federation_nodes table
|
||||
func (s Store) TruncateFederationNodes(ctx context.Context) error {
|
||||
return s.config.ErrorHandler(s.Truncate(ctx, s.federationNodeTable()))
|
||||
}
|
||||
|
||||
// execLookupFederationNode prepares FederationNode query and executes it,
|
||||
// returning types.Node (or error)
|
||||
func (s Store) execLookupFederationNode(ctx context.Context, cnd squirrel.Sqlizer) (res *types.Node, err error) {
|
||||
var (
|
||||
row rowScanner
|
||||
)
|
||||
|
||||
row, err = s.QueryRow(ctx, s.federationNodesSelectBuilder().Where(cnd))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
res, err = s.internalFederationNodeRowScanner(row)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// execCreateFederationNodes updates all matched (by cnd) rows in federation_nodes with given data
|
||||
func (s Store) execCreateFederationNodes(ctx context.Context, payload store.Payload) error {
|
||||
return s.config.ErrorHandler(s.Exec(ctx, s.InsertBuilder(s.federationNodeTable()).SetMap(payload)))
|
||||
}
|
||||
|
||||
// execUpdateFederationNodes updates all matched (by cnd) rows in federation_nodes with given data
|
||||
func (s Store) execUpdateFederationNodes(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
|
||||
return s.config.ErrorHandler(s.Exec(ctx, s.UpdateBuilder(s.federationNodeTable("fdn")).Where(cnd).SetMap(set)))
|
||||
}
|
||||
|
||||
// execUpsertFederationNodes inserts new or updates matching (by-primary-key) rows in federation_nodes with given data
|
||||
func (s Store) execUpsertFederationNodes(ctx context.Context, set store.Payload) error {
|
||||
upsert, err := s.config.UpsertBuilder(
|
||||
s.config,
|
||||
s.federationNodeTable(),
|
||||
set,
|
||||
"id",
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.config.ErrorHandler(s.Exec(ctx, upsert))
|
||||
}
|
||||
|
||||
// execDeleteFederationNodes Deletes all matched (by cnd) rows in federation_nodes with given data
|
||||
func (s Store) execDeleteFederationNodes(ctx context.Context, cnd squirrel.Sqlizer) error {
|
||||
return s.config.ErrorHandler(s.Exec(ctx, s.DeleteBuilder(s.federationNodeTable("fdn")).Where(cnd)))
|
||||
}
|
||||
|
||||
func (s Store) internalFederationNodeRowScanner(row rowScanner) (res *types.Node, err error) {
|
||||
res = &types.Node{}
|
||||
|
||||
if _, has := s.config.RowScanners["federationNode"]; has {
|
||||
scanner := s.config.RowScanners["federationNode"].(func(_ rowScanner, _ *types.Node) error)
|
||||
err = scanner(row, res)
|
||||
} else {
|
||||
err = row.Scan(
|
||||
&res.ID,
|
||||
&res.Name,
|
||||
&res.SharedNodeID,
|
||||
&res.BaseURL,
|
||||
&res.Status,
|
||||
&res.PairToken,
|
||||
&res.AuthToken,
|
||||
&res.CreatedBy,
|
||||
&res.UpdatedBy,
|
||||
&res.DeletedBy,
|
||||
&res.CreatedAt,
|
||||
&res.UpdatedAt,
|
||||
&res.DeletedAt,
|
||||
)
|
||||
}
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, store.ErrNotFound
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not scan db row for FederationNode: %w", err)
|
||||
} else {
|
||||
return res, nil
|
||||
}
|
||||
}
|
||||
|
||||
// QueryFederationNodes returns squirrel.SelectBuilder with set table and all columns
|
||||
func (s Store) federationNodesSelectBuilder() squirrel.SelectBuilder {
|
||||
return s.SelectBuilder(s.federationNodeTable("fdn"), s.federationNodeColumns("fdn")...)
|
||||
}
|
||||
|
||||
// federationNodeTable name of the db table
|
||||
func (Store) federationNodeTable(aa ...string) string {
|
||||
var alias string
|
||||
if len(aa) > 0 {
|
||||
alias = " AS " + aa[0]
|
||||
}
|
||||
|
||||
return "federation_nodes" + alias
|
||||
}
|
||||
|
||||
// FederationNodeColumns returns all defined table columns
|
||||
//
|
||||
// With optional string arg, all columns are returned aliased
|
||||
func (Store) federationNodeColumns(aa ...string) []string {
|
||||
var alias string
|
||||
if len(aa) > 0 {
|
||||
alias = aa[0] + "."
|
||||
}
|
||||
|
||||
return []string{
|
||||
alias + "id",
|
||||
alias + "name",
|
||||
alias + "shared_node_id",
|
||||
alias + "base_url",
|
||||
alias + "status",
|
||||
alias + "pair_token",
|
||||
alias + "auth_token",
|
||||
alias + "created_by",
|
||||
alias + "updated_by",
|
||||
alias + "deleted_by",
|
||||
alias + "created_at",
|
||||
alias + "updated_at",
|
||||
alias + "deleted_at",
|
||||
}
|
||||
}
|
||||
|
||||
// {true true false false true}
|
||||
|
||||
// internalFederationNodeEncoder encodes fields from types.Node to store.Payload (map)
|
||||
//
|
||||
// Encoding is done by using generic approach or by calling encodeFederationNode
|
||||
// func when rdbms.customEncoder=true
|
||||
func (s Store) internalFederationNodeEncoder(res *types.Node) store.Payload {
|
||||
return store.Payload{
|
||||
"id": res.ID,
|
||||
"name": res.Name,
|
||||
"shared_node_id": res.SharedNodeID,
|
||||
"base_url": res.BaseURL,
|
||||
"status": res.Status,
|
||||
"pair_token": res.PairToken,
|
||||
"auth_token": res.AuthToken,
|
||||
"created_by": res.CreatedBy,
|
||||
"updated_by": res.UpdatedBy,
|
||||
"deleted_by": res.DeletedBy,
|
||||
"created_at": res.CreatedAt,
|
||||
"updated_at": res.UpdatedAt,
|
||||
"deleted_at": res.DeletedAt,
|
||||
}
|
||||
}
|
||||
|
||||
// checkFederationNodeConstraints performs lookups (on valid) resource to check if any of the values on unique fields
|
||||
// already exists in the store
|
||||
//
|
||||
// Using built-in constraint checking would be more performant but unfortunately we can not rely
|
||||
// on the full support (MySQL does not support conditional indexes)
|
||||
func (s *Store) checkFederationNodeConstraints(ctx context.Context, res *types.Node) error {
|
||||
// Consider resource valid when all fields in unique constraint check lookups
|
||||
// have valid (non-empty) value
|
||||
//
|
||||
// Only string and uint64 are supported for now
|
||||
// feel free to add additional types if needed
|
||||
var valid = true
|
||||
|
||||
if !valid {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package rdbms
|
||||
|
||||
import (
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/cortezaproject/corteza-server/federation/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (s Store) convertFederationNodeFilter(f types.NodeFilter) (query squirrel.SelectBuilder, err error) {
|
||||
query = s.federationNodesSelectBuilder()
|
||||
|
||||
query = filter.StateCondition(query, "fdn.deleted_at", f.Deleted)
|
||||
|
||||
if f.Query != "" {
|
||||
q := "%" + strings.ToLower(f.Query) + "%"
|
||||
query = query.Where(squirrel.Or{
|
||||
squirrel.Like{"LOWER(fdn.name)": q},
|
||||
squirrel.Like{"LOWER(fdn.base_url)": q},
|
||||
})
|
||||
}
|
||||
|
||||
if f.Status != "" {
|
||||
query = query.Where(squirrel.Eq{"fdn.status": strings.ToLower(f.Status)})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testFederationExposedModules(t *testing.T, s store.FederationExposedModules) {
|
||||
// @todo
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testFederationModuleMappings(t *testing.T, s store.FederationModuleMappings) {
|
||||
// @todo
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza-server/federation/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza-server/pkg/id"
|
||||
"github.com/cortezaproject/corteza-server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func testFederationNodes(t *testing.T, s store.FederationNodes) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(name string) *types.Node {
|
||||
// minimum data set for new FederationNode
|
||||
return &types.Node{
|
||||
ID: id.Next(),
|
||||
CreatedAt: time.Now(),
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Node) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateFederationNodes(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateFederationNode(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
FederationNode := makeNew("FederationNodeCRUD")
|
||||
req.NoError(s.CreateFederationNode(ctx, FederationNode))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, FederationNode := truncAndCreate(t)
|
||||
fetched, err := s.LookupFederationNodeByID(ctx, FederationNode.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(FederationNode.Name, fetched.Name)
|
||||
req.Equal(FederationNode.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, FederationNode := truncAndCreate(t)
|
||||
FederationNode.Name = "FederationNodeCRUD+2"
|
||||
|
||||
req.NoError(s.UpdateFederationNode(ctx, FederationNode))
|
||||
|
||||
updated, err := s.LookupFederationNodeByID(ctx, FederationNode.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(FederationNode.Name, updated.Name)
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, FederationNode := truncAndCreate(t)
|
||||
FederationNode.Name = "FederationNodeCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertFederationNode(ctx, FederationNode))
|
||||
|
||||
updated, err := s.LookupFederationNodeByID(ctx, FederationNode.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(FederationNode.Name, updated.Name)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
FederationNode := makeNew("upsert me")
|
||||
FederationNode.Name = "ComposeChartCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertFederationNode(ctx, FederationNode))
|
||||
|
||||
upserted, err := s.LookupFederationNodeByID(ctx, FederationNode.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(FederationNode.Name, upserted.Name)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by FederationNode", func(t *testing.T) {
|
||||
req, FederationNode := truncAndCreate(t)
|
||||
req.NoError(s.DeleteFederationNode(ctx, FederationNode))
|
||||
_, err := s.LookupFederationNodeByID(ctx, FederationNode.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, FederationNode := truncAndCreate(t)
|
||||
req.NoError(s.DeleteFederationNodeByID(ctx, FederationNode.ID))
|
||||
_, err := s.LookupFederationNodeByID(ctx, FederationNode.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.Node{
|
||||
makeNew("/one-one"),
|
||||
makeNew("/one-two"),
|
||||
makeNew("/two-one"),
|
||||
makeNew("/two-two"),
|
||||
makeNew("/two-deleted"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateFederationNodes(ctx))
|
||||
req.NoError(s.CreateFederationNode(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, f, err := s.SearchFederationNodes(ctx, types.NodeFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, f, err = s.SearchFederationNodes(ctx, types.NodeFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, f, err = s.SearchFederationNodes(ctx, types.NodeFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
// find all prefixed
|
||||
set, f, err = s.SearchFederationNodes(ctx, types.NodeFilter{Query: "/two"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
|
||||
_ = f // dummy
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testFederationSharedModules(t *testing.T, s store.FederationSharedModules) {
|
||||
// @todo
|
||||
}
|
||||
@@ -16,6 +16,7 @@ package tests
|
||||
// - store/credentials.yaml
|
||||
// - store/federation_exposed_modules.yaml
|
||||
// - store/federation_module_mappings.yaml
|
||||
// - store/federation_nodes.yaml
|
||||
// - store/federation_shared_modules.yaml
|
||||
// - store/labels.yaml
|
||||
// - store/messaging_attachments.yaml
|
||||
@@ -114,6 +115,11 @@ func testAllGenerated(t *testing.T, s store.Storer) {
|
||||
testFederationModuleMappings(t, s)
|
||||
})
|
||||
|
||||
// Run generated tests for FederationNodes
|
||||
t.Run("FederationNodes", func(t *testing.T) {
|
||||
testFederationNodes(t, s)
|
||||
})
|
||||
|
||||
// Run generated tests for FederationSharedModules
|
||||
t.Run("FederationSharedModules", func(t *testing.T) {
|
||||
testFederationSharedModules(t, s)
|
||||
|
||||
Reference in New Issue
Block a user