snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
This commit is contained in:
338
server/pkg/envoyx/envoy.go
Normal file
338
server/pkg/envoyx/envoy.go
Normal file
@@ -0,0 +1,338 @@
|
||||
package envoyx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/expr"
|
||||
)
|
||||
|
||||
type (
|
||||
Service struct {
|
||||
decoders map[decodeType][]Decoder
|
||||
|
||||
encoders map[encodeType][]Encoder
|
||||
preparers map[encodeType][]Preparer
|
||||
}
|
||||
|
||||
// Traverser provides a structure which can be used to traverse the node's deps
|
||||
Traverser interface {
|
||||
// ParentForRef returns the parent of the provided node which matches the ref
|
||||
//
|
||||
// If no parent is found, nil is returned.
|
||||
ParentForRef(*Node, Ref) *Node
|
||||
|
||||
// ParentForRT returns a set of parent nodes matching the resource type
|
||||
ParentForRT(*Node, string) NodeSet
|
||||
|
||||
// ChildrenForResourceType returns the children of the provided node which
|
||||
// match the provided resource type
|
||||
ChildrenForResourceType(*Node, string) NodeSet
|
||||
|
||||
// Children returns all of the children of the provided node
|
||||
Children(*Node) NodeSet
|
||||
|
||||
// NodeForRef returns the node which matches the provided ref
|
||||
NodeForRef(Ref) *Node
|
||||
}
|
||||
|
||||
Preparer interface {
|
||||
// Prepare performs generic preprocessing on the provided nodes
|
||||
//
|
||||
// The function is called for every resource type where all of the nodes of
|
||||
// that resource type are passed as the argument.
|
||||
Prepare(context.Context, EncodeParams, string, NodeSet) error
|
||||
}
|
||||
|
||||
Encoder interface {
|
||||
// Encode encodes the data
|
||||
//
|
||||
// The function receives a set of root-level nodes (with no parent dependencies)
|
||||
// and a Traverser it can use to handle all of the child nodes.
|
||||
Encode(context.Context, EncodeParams, string, NodeSet, Traverser) (err error)
|
||||
}
|
||||
|
||||
PrepareEncoder interface {
|
||||
Preparer
|
||||
Encoder
|
||||
}
|
||||
|
||||
Decoder interface {
|
||||
// Decode returns a set of Nodes extracted based on the provided definition
|
||||
Decode(ctx context.Context, p DecodeParams) (out NodeSet, err error)
|
||||
}
|
||||
|
||||
canCheckFile interface {
|
||||
CanFile(f *os.File) bool
|
||||
}
|
||||
|
||||
canCheckExt interface {
|
||||
CanExt(name string) bool
|
||||
}
|
||||
|
||||
DecodeParams struct {
|
||||
Type decodeType
|
||||
Params map[string]any
|
||||
Config map[string]any
|
||||
Filter map[string]ResourceFilter
|
||||
}
|
||||
|
||||
EncodeParams struct {
|
||||
Type encodeType
|
||||
Params map[string]any
|
||||
Envoy EnvoyConfig
|
||||
Encoder EncoderConfig
|
||||
|
||||
FieldMapping []MapEntry
|
||||
|
||||
// @note these are only used by records since v1 did just that
|
||||
// @todo make these more expanded
|
||||
DeferOk func()
|
||||
DeferNok func(error) error
|
||||
Defer func()
|
||||
}
|
||||
EncoderConfig struct {
|
||||
DefaultUserID uint64
|
||||
PreferredTimeLayout string
|
||||
PreferredTimezone string
|
||||
}
|
||||
|
||||
ResourceFilter struct {
|
||||
Identifiers Identifiers
|
||||
Refs map[string]Ref
|
||||
|
||||
Limit uint
|
||||
Query string
|
||||
Scope Scope
|
||||
}
|
||||
|
||||
decodeType string
|
||||
encodeType string
|
||||
mergeAlg int
|
||||
)
|
||||
|
||||
var (
|
||||
global *Service
|
||||
|
||||
ex = expr.NewParser()
|
||||
)
|
||||
|
||||
const (
|
||||
OnConflictDefault mergeAlg = iota
|
||||
OnConflictReplace
|
||||
OnConflictSkip
|
||||
OnConflictPanic
|
||||
// OnConflictMergeLeft mergeAlg = "mergeLeft"
|
||||
// OnConflictMergeRight mergeAlg = "mergeRight"
|
||||
|
||||
DecodeTypeURI decodeType = "uri"
|
||||
DecodeTypeIO decodeType = "io"
|
||||
DecodeTypeStore decodeType = "store"
|
||||
|
||||
EncodeTypeURI encodeType = "uri"
|
||||
EncodeTypeStore encodeType = "store"
|
||||
EncodeTypeIo encodeType = "io"
|
||||
)
|
||||
|
||||
// New initializes a new Envoy service
|
||||
func New() *Service {
|
||||
return &Service{}
|
||||
}
|
||||
|
||||
// SetGlobal sets the global envoy service
|
||||
func SetGlobal(n *Service) {
|
||||
global = n
|
||||
}
|
||||
|
||||
// Global gets the global envoy service
|
||||
func Global() *Service {
|
||||
if global == nil {
|
||||
panic("global service not defined")
|
||||
}
|
||||
|
||||
return global
|
||||
}
|
||||
|
||||
func Initialized() bool {
|
||||
return global != nil
|
||||
}
|
||||
|
||||
// Decode returns a set of envoy Nodes based on the given decode params
|
||||
func (svc *Service) Decode(ctx context.Context, p DecodeParams) (nodes NodeSet, providers []Provider, err error) {
|
||||
err = p.validate()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch p.Type {
|
||||
case DecodeTypeURI:
|
||||
return svc.decodeUri(ctx, p)
|
||||
case DecodeTypeIO:
|
||||
return svc.decodeIo(ctx, p)
|
||||
case DecodeTypeStore:
|
||||
nodes, err = svc.decodeStore(ctx, p)
|
||||
return
|
||||
default:
|
||||
err = fmt.Errorf("unsupported decoder type %s", p.Type)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (svc *Service) Bake(ctx context.Context, p EncodeParams, providers []Provider, nodes ...*Node) (gg *DepGraph, err error) {
|
||||
err = svc.bakeEnvoyConfig(p.Envoy, nodes...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = svc.bakeExpressions(nodes...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
svc.bakeProviders(providers, nodes...)
|
||||
|
||||
gg = BuildDepGraph(nodes...)
|
||||
return
|
||||
}
|
||||
|
||||
// Encode encodes Corteza resources bases on the provided encode params
|
||||
//
|
||||
// use the BuildDepGraph function to build the default dependency graph.
|
||||
func (svc *Service) Encode(ctx context.Context, p EncodeParams, dg *DepGraph) (err error) {
|
||||
err = p.validate()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch p.Type {
|
||||
case EncodeTypeStore:
|
||||
return svc.encodeStore(ctx, dg, p)
|
||||
case EncodeTypeIo:
|
||||
return svc.encodeIo(ctx, dg, p)
|
||||
default:
|
||||
err = fmt.Errorf("unsupported encoder type %s", p.Type)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (svc *Service) AddDecoder(t decodeType, dd ...Decoder) {
|
||||
if svc.decoders == nil {
|
||||
svc.decoders = make(map[decodeType][]Decoder)
|
||||
}
|
||||
svc.decoders[t] = append(svc.decoders[t], dd...)
|
||||
}
|
||||
|
||||
func (svc *Service) AddEncoder(t encodeType, ee ...Encoder) {
|
||||
if svc.encoders == nil {
|
||||
svc.encoders = make(map[encodeType][]Encoder)
|
||||
}
|
||||
if svc.preparers == nil {
|
||||
svc.preparers = make(map[encodeType][]Preparer)
|
||||
}
|
||||
svc.encoders[t] = append(svc.encoders[t], ee...)
|
||||
|
||||
for _, e := range ee {
|
||||
p, ok := e.(Preparer)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
svc.preparers[t] = append(svc.preparers[t], p)
|
||||
}
|
||||
}
|
||||
|
||||
func (svc *Service) AddPreparer(t encodeType, pp ...Preparer) {
|
||||
if svc.preparers == nil {
|
||||
svc.preparers = make(map[encodeType][]Preparer)
|
||||
}
|
||||
svc.preparers[t] = append(svc.preparers[t], pp...)
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
|
||||
func (p DecodeParams) validate() (err error) {
|
||||
switch p.Type {
|
||||
case DecodeTypeURI:
|
||||
_, ok := p.Params["uri"]
|
||||
if !ok {
|
||||
return fmt.Errorf("URI decoder expects a uri location parameter")
|
||||
}
|
||||
|
||||
case DecodeTypeStore:
|
||||
|
||||
}
|
||||
|
||||
// @todo...
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (p EncodeParams) validate() (err error) {
|
||||
switch p.Type {
|
||||
// @todo...
|
||||
}
|
||||
|
||||
// @todo...
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func CastMergeAlg(v string) (mergeAlg mergeAlg) {
|
||||
switch strings.ToLower(v) {
|
||||
case "replace", "mergeleft":
|
||||
mergeAlg = OnConflictReplace
|
||||
case "skip", "mergeright":
|
||||
mergeAlg = OnConflictSkip
|
||||
case "panic", "error":
|
||||
mergeAlg = OnConflictPanic
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (svc *Service) bakeEnvoyConfig(dft EnvoyConfig, nodes ...*Node) (err error) {
|
||||
for _, n := range nodes {
|
||||
n.Config = svc.mergeEnvoyConfigs(n.Config, dft)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (svc *Service) bakeExpressions(nodes ...*Node) (err error) {
|
||||
for _, n := range nodes {
|
||||
if n.Config.SkipIf == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
n.Config.SkipIfEval, err = ex.Parse(n.Config.SkipIf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (svc *Service) bakeProviders(providers []Provider, nodes ...*Node) {
|
||||
SetDecoderSources(nodes, providers...)
|
||||
}
|
||||
|
||||
func (svc *Service) mergeEnvoyConfigs(a, b EnvoyConfig) (c EnvoyConfig) {
|
||||
c = a
|
||||
if c.MergeAlg == OnConflictDefault {
|
||||
c.MergeAlg = b.MergeAlg
|
||||
}
|
||||
if c.MergeAlg == OnConflictDefault {
|
||||
c.MergeAlg = OnConflictReplace
|
||||
}
|
||||
|
||||
// @todo pre eval this?
|
||||
if c.SkipIf == "" {
|
||||
c.SkipIf = b.SkipIf
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user