This lets us import multiple different namespaces with modules, ... at the same time. Before, there was a chance that a thing from NS 1 would be linked to a thing in NS 2.
120 lines
2.2 KiB
Go
120 lines
2.2 KiB
Go
package envoy
|
|
|
|
import "github.com/cortezaproject/corteza-server/pkg/envoy/resource"
|
|
|
|
type (
|
|
// the node struct is used for nicer graph state management
|
|
nodeSet []*node
|
|
node struct {
|
|
res resource.Interface
|
|
|
|
pp nodeSet
|
|
cc nodeSet
|
|
}
|
|
|
|
// resource type -> identifier -> []nodes
|
|
// There can be multiple resources with same identifier; for example
|
|
// two modules under different namespaces.
|
|
nodeIndex map[string]map[string]nodeSet
|
|
)
|
|
|
|
func newNode(res resource.Interface) *node {
|
|
return &node{
|
|
res: res,
|
|
cc: make(nodeSet, 0, 10),
|
|
pp: make(nodeSet, 0, 10),
|
|
}
|
|
}
|
|
|
|
func (nn nodeSet) add(mm ...*node) nodeSet {
|
|
return append(nn, mm...)
|
|
}
|
|
|
|
func (nn nodeSet) filter(f func(n *node) bool) nodeSet {
|
|
mm := make(nodeSet, 0, len(nn))
|
|
for _, n := range nn {
|
|
if f(n) {
|
|
mm = append(mm, n)
|
|
}
|
|
}
|
|
return mm
|
|
}
|
|
|
|
func (nn nodeSet) has(m *node) bool {
|
|
for _, n := range nn {
|
|
if n == m {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (nn nodeSet) remove(mm ...*node) nodeSet {
|
|
if len(mm) <= 0 {
|
|
return nn
|
|
}
|
|
|
|
nClean := make(nodeSet, 0, len(nn))
|
|
mmSet := make(nodeSet, 0, len(mm))
|
|
mmSet = append(mmSet, mm...)
|
|
|
|
for _, n := range nn {
|
|
if !mmSet.has(n) {
|
|
nClean = append(nClean, n)
|
|
}
|
|
}
|
|
|
|
return nClean
|
|
}
|
|
|
|
func (ri nodeIndex) Add(nn ...*node) {
|
|
for _, n := range nn {
|
|
rt := n.res.ResourceType()
|
|
if _, has := ri[rt]; !has {
|
|
ri[rt] = make(map[string]nodeSet)
|
|
}
|
|
|
|
for i := range n.res.Identifiers() {
|
|
if ri[rt][i] == nil {
|
|
ri[rt][i] = make(nodeSet, 0, 5)
|
|
}
|
|
ri[rt][i] = append(ri[rt][i], n)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (ri nodeIndex) GetRef(ref *resource.Ref) *node {
|
|
refIi, has := ri[ref.ResourceType]
|
|
if !has {
|
|
return nil
|
|
}
|
|
|
|
for i := range ref.Identifiers {
|
|
rr, has := refIi[i]
|
|
if !has || len(rr) == 0 {
|
|
continue
|
|
}
|
|
|
|
// No constraints? no worries
|
|
if ref.Constraints == nil || len(ref.Constraints) == 0 {
|
|
return rr[0]
|
|
}
|
|
|
|
// Constraints? check if ok
|
|
// If this loop makes you sick, don't worry; this will be at most 3x3x1
|
|
for _, r := range rr {
|
|
for _, c := range ref.Constraints {
|
|
for _, ref := range r.res.Refs() {
|
|
if ref.ResourceType == c.ResourceType && ref.Identifiers.HasAny(c.Identifiers) {
|
|
return r
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|