Additional envoy resource manipulation utilities
This commit is contained in:
@@ -37,6 +37,16 @@ func (t *testResource) Placeholder() bool {
|
||||
return t.ph
|
||||
}
|
||||
|
||||
func (t *testResource) ReID(ii resource.Identifiers) {
|
||||
// no need for implementation
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (t *testResource) ReRef(old resource.RefSet, new resource.RefSet) {
|
||||
// no need for implementation
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func TestGraphBuilder_Rel(t *testing.T) {
|
||||
req := require.New(t)
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -31,6 +31,8 @@ func NewApplication(res *types.Application) *Application {
|
||||
})
|
||||
}
|
||||
|
||||
res.ID = 0
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,8 @@ func NewAutomationWorkflow(res *types.Workflow) *AutomationWorkflow {
|
||||
us.RunAs = MakeUserstampFromID(res.RunAs)
|
||||
r.SetUserstamps(us)
|
||||
|
||||
res.ID = 0
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
@@ -37,9 +37,29 @@ func NewComposeChart(res *types.Chart, nsRef string, mmRef []string) *ComposeCha
|
||||
// Initial timestamps
|
||||
r.SetTimestamps(MakeTimestampsCUDA(&res.CreatedAt, res.UpdatedAt, res.DeletedAt, nil))
|
||||
|
||||
res.ID = 0
|
||||
res.NamespaceID = 0
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *ComposeChart) ReRef(old RefSet, new RefSet) {
|
||||
r.base.ReRef(old, new)
|
||||
|
||||
// Additional references
|
||||
for _, n := range new {
|
||||
if n.ResourceType == types.NamespaceResourceType {
|
||||
r.RefNs = MakeRef(types.NamespaceResourceType, n.Identifiers)
|
||||
}
|
||||
}
|
||||
|
||||
for i, o := range old {
|
||||
if o.ResourceType == types.ModuleResourceType {
|
||||
r.RefMods = r.RefMods.replaceRef(o, new[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ComposeChart) SysID() uint64 {
|
||||
return r.Res.ID
|
||||
}
|
||||
|
||||
@@ -68,14 +68,38 @@ func NewComposeModule(res *types.Module, nsRef string) *ComposeModule {
|
||||
r.RefRoles = append(r.RefRoles, r.AddRef(systemTypes.RoleResourceType, refRole))
|
||||
}
|
||||
}
|
||||
|
||||
f.ID = 0
|
||||
f.NamespaceID = 0
|
||||
f.ModuleID = 0
|
||||
}
|
||||
|
||||
// Initial timestamps
|
||||
r.SetTimestamps(MakeTimestampsCUDA(&res.CreatedAt, res.UpdatedAt, res.DeletedAt, nil))
|
||||
|
||||
res.ID = 0
|
||||
res.NamespaceID = 0
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *ComposeModule) ReRef(old RefSet, new RefSet) {
|
||||
r.base.ReRef(old, new)
|
||||
|
||||
// Additional references
|
||||
for _, n := range new {
|
||||
if n.ResourceType == types.NamespaceResourceType {
|
||||
r.RefNs = MakeRef(types.NamespaceResourceType, n.Identifiers)
|
||||
}
|
||||
}
|
||||
|
||||
for i, o := range old {
|
||||
if o.ResourceType == types.ModuleResourceType {
|
||||
r.RefMods = r.RefMods.replaceRef(o, new[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ComposeModule) SysID() uint64 {
|
||||
return r.Res.ID
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ func NewComposeNamespace(ns *types.Namespace) *ComposeNamespace {
|
||||
// Initial timestamps
|
||||
r.SetTimestamps(MakeTimestampsCUDA(&ns.CreatedAt, ns.UpdatedAt, ns.DeletedAt, nil))
|
||||
|
||||
ns.ID = 0
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
@@ -48,32 +48,14 @@ func NewComposePage(pg *types.Page, nsRef, modRef, parentRef string) *ComposePag
|
||||
r.RefParent = r.AddRef(types.PageResourceType, parentRef).Constraint(r.RefNs)
|
||||
}
|
||||
|
||||
// Quick utility to extract references from options
|
||||
ss := func(m map[string]interface{}, kk ...string) string {
|
||||
for _, k := range kk {
|
||||
if vr, has := m[k]; has {
|
||||
v, _ := vr.(string)
|
||||
return v
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
add := func(rr RefSet, r *Ref) RefSet {
|
||||
if rr == nil {
|
||||
rr = make(RefSet, 0, 2)
|
||||
}
|
||||
|
||||
return append(rr, r)
|
||||
}
|
||||
|
||||
var ref *Ref
|
||||
for i, b := range pg.Blocks {
|
||||
switch b.Kind {
|
||||
case "RecordList":
|
||||
id := ss(b.Options, "module", "moduleID")
|
||||
if id != "" {
|
||||
ref := r.AddRef(types.ModuleResourceType, id).Constraint(r.RefNs)
|
||||
r.BlockRefs[i] = add(r.BlockRefs[i], ref)
|
||||
ref = r.pbRecordList(b.Options)
|
||||
if ref != nil {
|
||||
r.addRef(ref)
|
||||
r.BlockRefs[i] = append(r.BlockRefs[i], ref)
|
||||
r.ModRefs = append(r.ModRefs, ref)
|
||||
}
|
||||
|
||||
@@ -81,27 +63,27 @@ func NewComposePage(pg *types.Page, nsRef, modRef, parentRef string) *ComposePag
|
||||
bb, _ := b.Options["buttons"].([]interface{})
|
||||
for _, b := range bb {
|
||||
button, _ := b.(map[string]interface{})
|
||||
id := ss(button, "workflow", "workflowID")
|
||||
if id != "" {
|
||||
ref := r.AddRef(automationTypes.WorkflowResourceType, id)
|
||||
r.BlockRefs[i] = add(r.BlockRefs[i], ref)
|
||||
ref = r.pbAutomation(button)
|
||||
if ref != nil {
|
||||
r.addRef(ref)
|
||||
r.BlockRefs[i] = append(r.BlockRefs[i], ref)
|
||||
r.WfRefs = append(r.WfRefs, ref)
|
||||
}
|
||||
}
|
||||
|
||||
case "RecordOrganizer":
|
||||
id := ss(b.Options, "module", "moduleID")
|
||||
if id != "" {
|
||||
ref := r.AddRef(types.ModuleResourceType, id).Constraint(r.RefNs)
|
||||
r.BlockRefs[i] = add(r.BlockRefs[i], ref)
|
||||
ref = r.pbRecordList(b.Options)
|
||||
if ref != nil {
|
||||
r.addRef(ref)
|
||||
r.BlockRefs[i] = append(r.BlockRefs[i], ref)
|
||||
r.ModRefs = append(r.ModRefs, ref)
|
||||
}
|
||||
|
||||
case "Chart":
|
||||
id := ss(b.Options, "chart", "chartID")
|
||||
if id != "" {
|
||||
ref := r.AddRef(types.ChartResourceType, id).Constraint(r.RefNs)
|
||||
r.BlockRefs[i] = add(r.BlockRefs[i], ref)
|
||||
ref = r.pbChart(b.Options)
|
||||
if ref != nil {
|
||||
r.addRef(ref)
|
||||
r.BlockRefs[i] = append(r.BlockRefs[i], ref)
|
||||
r.RefCharts = append(r.RefCharts, ref)
|
||||
}
|
||||
|
||||
@@ -110,10 +92,11 @@ func NewComposePage(pg *types.Page, nsRef, modRef, parentRef string) *ComposePag
|
||||
for _, f := range ff {
|
||||
feed, _ := f.(map[string]interface{})
|
||||
fOpts, _ := (feed["options"]).(map[string]interface{})
|
||||
id := ss(fOpts, "module", "moduleID")
|
||||
if id != "" {
|
||||
ref := r.AddRef(types.ModuleResourceType, id).Constraint(r.RefNs)
|
||||
r.BlockRefs[i] = add(r.BlockRefs[i], ref)
|
||||
|
||||
ref = r.pbCalendar(fOpts)
|
||||
if ref != nil {
|
||||
r.addRef(ref)
|
||||
r.BlockRefs[i] = append(r.BlockRefs[i], ref)
|
||||
r.ModRefs = append(r.ModRefs, ref)
|
||||
}
|
||||
}
|
||||
@@ -122,10 +105,10 @@ func NewComposePage(pg *types.Page, nsRef, modRef, parentRef string) *ComposePag
|
||||
mm, _ := b.Options["metrics"].([]interface{})
|
||||
for _, m := range mm {
|
||||
mops, _ := m.(map[string]interface{})
|
||||
id := ss(mops, "module", "moduleID")
|
||||
if id != "" {
|
||||
ref := r.AddRef(types.ModuleResourceType, id).Constraint(r.RefNs)
|
||||
r.BlockRefs[i] = add(r.BlockRefs[i], ref)
|
||||
ref = r.pbMetric(mops)
|
||||
if ref != nil {
|
||||
r.addRef(ref)
|
||||
r.BlockRefs[i] = append(r.BlockRefs[i], ref)
|
||||
r.ModRefs = append(r.ModRefs, ref)
|
||||
}
|
||||
}
|
||||
@@ -143,9 +126,55 @@ func NewComposePage(pg *types.Page, nsRef, modRef, parentRef string) *ComposePag
|
||||
// Initial timestamps
|
||||
r.SetTimestamps(MakeTimestampsCUDA(&pg.CreatedAt, pg.UpdatedAt, pg.DeletedAt, nil))
|
||||
|
||||
pg.ID = 0
|
||||
pg.SelfID = 0
|
||||
pg.NamespaceID = 0
|
||||
pg.ModuleID = 0
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *ComposePage) ReRef(old RefSet, new RefSet) {
|
||||
r.base.ReRef(old, new)
|
||||
|
||||
for _, n := range new {
|
||||
switch n.ResourceType {
|
||||
case types.NamespaceResourceType:
|
||||
r.RefNs = MakeRef(types.NamespaceResourceType, n.Identifiers)
|
||||
case types.ModuleResourceType:
|
||||
r.RefMod = MakeRef(types.ModuleResourceType, n.Identifiers)
|
||||
case types.PageResourceType:
|
||||
r.RefParent = MakeRef(types.PageResourceType, n.Identifiers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ComposePage) Prune(ref *Ref) {
|
||||
var auxRef *Ref
|
||||
|
||||
outer:
|
||||
for i := len(r.Res.Blocks) - 1; i >= 0; i-- {
|
||||
b := r.Res.Blocks[i]
|
||||
|
||||
switch b.Kind {
|
||||
// Implement the rest when support is needed
|
||||
case "Automation":
|
||||
bb, _ := b.Options["buttons"].([]interface{})
|
||||
for _, b := range bb {
|
||||
button, _ := b.(map[string]interface{})
|
||||
auxRef = r.pbAutomation(button)
|
||||
|
||||
if auxRef.equals(ref) {
|
||||
r.ReplaceRef(ref, nil)
|
||||
r.WfRefs = r.WfRefs.replaceRef(ref, nil)
|
||||
r.removeBlock(i)
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ComposePage) SysID() uint64 {
|
||||
return r.Res.ID
|
||||
}
|
||||
@@ -196,3 +225,79 @@ func FindComposePage(rr InterfaceSet, ii Identifiers) (pg *types.Page) {
|
||||
func ComposePageErrUnresolved(ii Identifiers) error {
|
||||
return fmt.Errorf("compose page unresolved %v", ii.StringSlice())
|
||||
}
|
||||
|
||||
// Page block utilities
|
||||
func (r *ComposePage) removeBlock(i int) {
|
||||
// do the swap remove thing
|
||||
r.Res.Blocks[i] = r.Res.Blocks[len(r.Res.Blocks)-1]
|
||||
r.Res.Blocks = r.Res.Blocks[:len(r.Res.Blocks)-1]
|
||||
|
||||
// correct block refs.
|
||||
// +1 here because it's already cut
|
||||
r.BlockRefs[i] = r.BlockRefs[len(r.Res.Blocks)]
|
||||
delete(r.BlockRefs, len(r.Res.Blocks))
|
||||
}
|
||||
|
||||
func (r *ComposePage) optString(opt map[string]interface{}, kk ...string) string {
|
||||
for _, k := range kk {
|
||||
if vr, has := opt[k]; has {
|
||||
v, _ := vr.(string)
|
||||
return v
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *ComposePage) pbRecordList(opt map[string]interface{}) (out *Ref) {
|
||||
id := r.optString(opt, "module", "moduleID")
|
||||
if id == "" {
|
||||
return
|
||||
}
|
||||
|
||||
return MakeRef(types.ModuleResourceType, MakeIdentifiers(id)).Constraint(r.RefNs)
|
||||
}
|
||||
|
||||
func (r *ComposePage) pbAutomation(opt map[string]interface{}) (out *Ref) {
|
||||
id := r.optString(opt, "workflow", "workflowID")
|
||||
if id == "" {
|
||||
return
|
||||
}
|
||||
|
||||
return MakeRef(automationTypes.WorkflowResourceType, MakeIdentifiers(id))
|
||||
}
|
||||
|
||||
func (r *ComposePage) pbRecordOrganizer(opt map[string]interface{}) (out *Ref) {
|
||||
id := r.optString(opt, "module", "moduleID")
|
||||
if id == "" {
|
||||
return
|
||||
}
|
||||
|
||||
return MakeRef(types.ModuleResourceType, MakeIdentifiers(id)).Constraint(r.RefNs)
|
||||
}
|
||||
|
||||
func (r *ComposePage) pbChart(opt map[string]interface{}) (out *Ref) {
|
||||
id := r.optString(opt, "chart", "chartID")
|
||||
if id == "" {
|
||||
return
|
||||
}
|
||||
|
||||
return MakeRef(types.ChartResourceType, MakeIdentifiers(id)).Constraint(r.RefNs)
|
||||
}
|
||||
|
||||
func (r *ComposePage) pbCalendar(opt map[string]interface{}) (out *Ref) {
|
||||
id := r.optString(opt, "module", "moduleID")
|
||||
if id == "" {
|
||||
return
|
||||
}
|
||||
|
||||
return MakeRef(types.ModuleResourceType, MakeIdentifiers(id)).Constraint(r.RefNs)
|
||||
}
|
||||
|
||||
func (r *ComposePage) pbMetric(opt map[string]interface{}) (out *Ref) {
|
||||
id := r.optString(opt, "module", "moduleID")
|
||||
if id == "" {
|
||||
return
|
||||
}
|
||||
|
||||
return MakeRef(types.ModuleResourceType, MakeIdentifiers(id)).Constraint(r.RefNs)
|
||||
}
|
||||
|
||||
@@ -104,12 +104,13 @@ func (t *base) AddIdentifier(ss ...string) {
|
||||
t.ii.Add(ss...)
|
||||
}
|
||||
|
||||
// SetIdentifier sets the identifiers to whatever was provided
|
||||
func (t *base) SetIdentifier(ii Identifiers) {
|
||||
t.ii = ii
|
||||
}
|
||||
|
||||
// AddRef adds a new reference to the current resource
|
||||
func (t *base) AddRef(rt string, ii ...string) *Ref {
|
||||
if t.rr == nil {
|
||||
t.rr = make(RefSet, 0, 10)
|
||||
}
|
||||
|
||||
iiC := make([]string, 0, len(ii))
|
||||
for _, i := range ii {
|
||||
if i != "" {
|
||||
@@ -117,10 +118,18 @@ func (t *base) AddRef(rt string, ii ...string) *Ref {
|
||||
}
|
||||
}
|
||||
|
||||
ref := &Ref{ResourceType: rt, Identifiers: Identifiers{}.Add(iiC...)}
|
||||
t.rr = append(t.rr, ref)
|
||||
return t.addRef(&Ref{ResourceType: rt, Identifiers: Identifiers{}.Add(iiC...)})
|
||||
}
|
||||
|
||||
return ref
|
||||
func (t *base) addRef(r *Ref) *Ref {
|
||||
t.rr = append(t.rr, r)
|
||||
return r
|
||||
}
|
||||
|
||||
// ReplaceRef replaces the given ref with the new one.
|
||||
// The new ref is added regardles if the old one exists or not.
|
||||
func (t *base) ReplaceRef(old, new *Ref) {
|
||||
t.rr = t.rr.replaceRef(old, new)
|
||||
}
|
||||
|
||||
// SetResourceType sets the resource type of the current resource struct
|
||||
@@ -219,3 +228,13 @@ func MakeRef(rt string, ii Identifiers) *Ref {
|
||||
func IgnoreDepResolution(ref *Ref) bool {
|
||||
return ref.ResourceType == composeTypes.ModuleFieldResourceType
|
||||
}
|
||||
|
||||
func (t *base) ReID(ii Identifiers) {
|
||||
t.SetIdentifier(ii)
|
||||
}
|
||||
|
||||
func (t *base) ReRef(old RefSet, new RefSet) {
|
||||
for i, o := range old {
|
||||
t.ReplaceRef(o, new[i])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ func NewRole(rl *types.Role) *Role {
|
||||
// Initial timestamps
|
||||
r.SetTimestamps(MakeTimestampsCUDA(&rl.CreatedAt, rl.UpdatedAt, rl.DeletedAt, rl.ArchivedAt))
|
||||
|
||||
rl.ID = 0
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ func NewTemplate(t *types.Template) *Template {
|
||||
// Initial timestamps
|
||||
r.SetTimestamps(MakeTimestampsCUDAS(&t.CreatedAt, t.UpdatedAt, t.DeletedAt, nil, nil))
|
||||
|
||||
t.ID = 0
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
+109
-2
@@ -7,9 +7,10 @@ type (
|
||||
Identifiers() Identifiers
|
||||
ResourceType() string
|
||||
Refs() RefSet
|
||||
|
||||
MarkPlaceholder()
|
||||
Placeholder() bool
|
||||
ReID(Identifiers)
|
||||
ReRef(old RefSet, new RefSet)
|
||||
}
|
||||
|
||||
InterfaceSet []Interface
|
||||
@@ -39,6 +40,12 @@ type (
|
||||
EncodeTranslations() ([]*ResourceTranslation, error)
|
||||
}
|
||||
|
||||
PrunableInterface interface {
|
||||
Interface
|
||||
|
||||
Prune(*Ref)
|
||||
}
|
||||
|
||||
RefSet []*Ref
|
||||
Ref struct {
|
||||
// @todo check with Denis regarding strings here (the cdocs comment)
|
||||
@@ -58,6 +65,14 @@ var (
|
||||
ResourceTranslationType = "resource-translation"
|
||||
)
|
||||
|
||||
func MakeRef(rt string, ii Identifiers) *Ref {
|
||||
return &Ref{ResourceType: rt, Identifiers: ii}
|
||||
}
|
||||
|
||||
func MakeWildRef(rt string) *Ref {
|
||||
return &Ref{ResourceType: rt, Identifiers: MakeIdentifiers("*")}
|
||||
}
|
||||
|
||||
func MakeIdentifiers(ss ...string) Identifiers {
|
||||
ii := make(Identifiers)
|
||||
ii.Add(ss...)
|
||||
@@ -128,6 +143,36 @@ func (rr InterfaceSet) Walk(f func(r Interface) error) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SearchForIdentifiers returns the resources where the provided identifiers exist
|
||||
//
|
||||
// The Resource is matching if at least one identifier matches.
|
||||
func (rr InterfaceSet) SearchForIdentifiers(ii Identifiers) (out InterfaceSet) {
|
||||
out = make(InterfaceSet, 0, len(rr)/2)
|
||||
|
||||
for _, r := range rr {
|
||||
if r.Identifiers().HasAny(ii) {
|
||||
out = append(out, r)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SearchForReferences returns the resources where the provided references exist
|
||||
//
|
||||
// The Resource is matching if at least one reference matches.
|
||||
func (rr InterfaceSet) SearchForReferences(ref *Ref) (out InterfaceSet) {
|
||||
out = make(InterfaceSet, 0, len(rr)/2)
|
||||
|
||||
for _, r := range rr {
|
||||
if r.Refs().HasRef(ref) {
|
||||
out = append(out, r)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Constraint returns the current reference with added constraint
|
||||
func (r *Ref) Constraint(c *Ref) *Ref {
|
||||
if r.Constraints == nil {
|
||||
@@ -144,7 +189,69 @@ func (r *Ref) Constraint(c *Ref) *Ref {
|
||||
|
||||
// IsWildcard checks if this Ref points to all resources of a specific resource type
|
||||
func (r *Ref) IsWildcard() bool {
|
||||
return r.Identifiers["*"]
|
||||
return r.Identifiers != nil && r.Identifiers["*"]
|
||||
}
|
||||
|
||||
func (a *Ref) equals(b *Ref) bool {
|
||||
if a.ResourceType != b.ResourceType {
|
||||
return false
|
||||
}
|
||||
|
||||
if !b.IsWildcard() && !a.Identifiers.HasAny(b.Identifiers) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, c := range b.Constraints {
|
||||
if !a.Constraints.HasRef(c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (rr RefSet) findRef(ref *Ref) int {
|
||||
for i, r := range rr {
|
||||
if r.equals(ref) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
// replaceRef replaces the reference both on the ref level and on the
|
||||
// constraint level.
|
||||
func (rr RefSet) replaceRef(old, new *Ref) RefSet {
|
||||
found := false
|
||||
|
||||
for x := len(rr) - 1; x >= 0; x-- {
|
||||
r := rr[x]
|
||||
|
||||
if r.equals(old) {
|
||||
found = true
|
||||
if new == nil {
|
||||
rr[x] = rr[len(rr)-1]
|
||||
return rr[:len(rr)-1]
|
||||
} else {
|
||||
rr[x] = new
|
||||
}
|
||||
} else {
|
||||
if len(r.Constraints) > 0 {
|
||||
r.Constraints = r.Constraints.replaceRef(old, new)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return append(rr, new)
|
||||
}
|
||||
|
||||
return rr
|
||||
}
|
||||
|
||||
func (rr RefSet) HasRef(ref *Ref) bool {
|
||||
return rr.findRef(ref) > -1
|
||||
}
|
||||
|
||||
// Unique returns only unique references
|
||||
|
||||
@@ -25,6 +25,8 @@ func NewUser(u *types.User) *User {
|
||||
// Initial timestamps
|
||||
r.SetTimestamps(MakeTimestampsCUDAS(&u.CreatedAt, u.UpdatedAt, u.DeletedAt, nil, u.SuspendedAt))
|
||||
|
||||
u.ID = 0
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user