3
0

Improve error handling & recovery

This commit is contained in:
Tomaž Jerman
2023-03-03 12:56:06 +01:00
parent a0e25b457f
commit 2f015a26f6
29 changed files with 1498 additions and 960 deletions

View File

@@ -15,6 +15,7 @@ import (
"github.com/cortezaproject/corteza/server/pkg/envoyx"
"github.com/cortezaproject/corteza/server/store"
"github.com/cortezaproject/corteza/server/system/types"
"github.com/pkg/errors"
)
type (
@@ -74,178 +75,192 @@ func (d StoreDecoder) decode(ctx context.Context, s store.Storer, dl dal.FullSer
// lives easier.
refNodes := make([]map[string]*envoyx.Node, len(p.Filter))
refRefs := make([]map[string]envoyx.Ref, len(p.Filter))
for i, a := range wrappedFilters {
if len(a.f.Refs) == 0 {
continue
err = func() (err error) {
for i, a := range wrappedFilters {
if len(a.f.Refs) == 0 {
continue
}
auxr := make(map[string]*envoyx.Node, len(a.f.Refs))
auxa := make(map[string]envoyx.Ref)
for field, ref := range a.f.Refs {
f := ref.ResourceFilter()
aux, err := d.decode(ctx, s, dl, envoyx.DecodeParams{
Type: envoyx.DecodeTypeStore,
Filter: f,
})
if err != nil {
return err
}
// @todo consider changing this.
// Currently it's required because the .decode may return some
// nested nodes as well.
// Consider a flag or a new function.
aux = envoyx.NodesForResourceType(ref.ResourceType, aux...)
if len(aux) == 0 {
return fmt.Errorf("invalid reference %v", ref)
}
if len(aux) > 1 {
return fmt.Errorf("ambiguous reference: too many resources returned %v", a.f)
}
auxr[field] = aux[0]
auxa[field] = aux[0].ToRef()
}
refNodes[i] = auxr
refRefs[i] = auxa
}
auxr := make(map[string]*envoyx.Node, len(a.f.Refs))
auxa := make(map[string]envoyx.Ref)
for field, ref := range a.f.Refs {
f := ref.ResourceFilter()
aux, err := d.decode(ctx, s, dl, envoyx.DecodeParams{
Type: envoyx.DecodeTypeStore,
Filter: f,
})
if err != nil {
return nil, err
}
// @todo consider changing this.
// Currently it's required because the .decode may return some
// nested nodes as well.
// Consider a flag or a new function.
aux = envoyx.NodesForResourceType(ref.ResourceType, aux...)
if len(aux) == 0 {
return nil, fmt.Errorf("invalid reference %v", ref)
}
if len(aux) > 1 {
return nil, fmt.Errorf("ambiguous reference: too many resources returned %v", a.f)
}
auxr[field] = aux[0]
auxa[field] = aux[0].ToRef()
}
refNodes[i] = auxr
refRefs[i] = auxa
return
}()
if err != nil {
err = errors.Wrap(err, "failed to decode node references")
return
}
var aux envoyx.NodeSet
for i, wf := range wrappedFilters {
switch wf.rt {
case types.ApplicationResourceType:
aux, err = d.decodeApplication(ctx, s, dl, d.makeApplicationFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
err = func() (err error) {
var aux envoyx.NodeSet
for i, wf := range wrappedFilters {
switch wf.rt {
case types.ApplicationResourceType:
aux, err = d.decodeApplication(ctx, s, dl, d.makeApplicationFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.ApigwRouteResourceType:
aux, err = d.decodeApigwRoute(ctx, s, dl, d.makeApigwRouteFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.ApigwRouteResourceType:
aux, err = d.decodeApigwRoute(ctx, s, dl, d.makeApigwRouteFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.ApigwFilterResourceType:
aux, err = d.decodeApigwFilter(ctx, s, dl, d.makeApigwFilterFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.ApigwFilterResourceType:
aux, err = d.decodeApigwFilter(ctx, s, dl, d.makeApigwFilterFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.AuthClientResourceType:
aux, err = d.decodeAuthClient(ctx, s, dl, d.makeAuthClientFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.AuthClientResourceType:
aux, err = d.decodeAuthClient(ctx, s, dl, d.makeAuthClientFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.QueueResourceType:
aux, err = d.decodeQueue(ctx, s, dl, d.makeQueueFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.QueueResourceType:
aux, err = d.decodeQueue(ctx, s, dl, d.makeQueueFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.ReportResourceType:
aux, err = d.decodeReport(ctx, s, dl, d.makeReportFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.ReportResourceType:
aux, err = d.decodeReport(ctx, s, dl, d.makeReportFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.RoleResourceType:
aux, err = d.decodeRole(ctx, s, dl, d.makeRoleFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.RoleResourceType:
aux, err = d.decodeRole(ctx, s, dl, d.makeRoleFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.TemplateResourceType:
aux, err = d.decodeTemplate(ctx, s, dl, d.makeTemplateFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.TemplateResourceType:
aux, err = d.decodeTemplate(ctx, s, dl, d.makeTemplateFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.UserResourceType:
aux, err = d.decodeUser(ctx, s, dl, d.makeUserFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.UserResourceType:
aux, err = d.decodeUser(ctx, s, dl, d.makeUserFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.DalConnectionResourceType:
aux, err = d.decodeDalConnection(ctx, s, dl, d.makeDalConnectionFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.DalConnectionResourceType:
aux, err = d.decodeDalConnection(ctx, s, dl, d.makeDalConnectionFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.DalSensitivityLevelResourceType:
aux, err = d.decodeDalSensitivityLevel(ctx, s, dl, d.makeDalSensitivityLevelFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
case types.DalSensitivityLevelResourceType:
aux, err = d.decodeDalSensitivityLevel(ctx, s, dl, d.makeDalSensitivityLevelFilter(scopedNodes[i], refNodes[i], wf.f))
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
default:
aux, err = d.extendDecoder(ctx, s, dl, wf.rt, refNodes[i], wf.f)
if err != nil {
return
default:
aux, err = d.extendDecoder(ctx, s, dl, wf.rt, refNodes[i], wf.f)
if err != nil {
return
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
}
for _, a := range aux {
a.Identifiers = a.Identifiers.Merge(wf.f.Identifiers)
a.References = envoyx.MergeRefs(a.References, refRefs[i])
}
out = append(out, aux...)
}
return
}()
if err != nil {
err = errors.Wrap(err, "failed to decode filters")
return
}
return

File diff suppressed because it is too large Load Diff

View File

@@ -57,13 +57,13 @@ func (e StoreEncoder) encodeResourceTranslation(ctx context.Context, p envoyx.En
for fieldLabel, ref := range n.References {
rn := tree.ParentForRef(n, ref)
if rn == nil {
err = fmt.Errorf("missing node for ref %v", ref)
err = fmt.Errorf("parent reference %v not found", ref)
return
}
auxID = rn.Resource.GetID()
if auxID == 0 {
err = fmt.Errorf("related resource doesn't provide an ID")
err = fmt.Errorf("parent reference does not provide an identifier")
return
}

View File

@@ -54,13 +54,13 @@ func (e StoreEncoder) encodeRbacRule(ctx context.Context, p envoyx.EncodeParams,
for fieldLabel, ref := range n.References {
rn := tree.ParentForRef(n, ref)
if rn == nil {
err = fmt.Errorf("missing node for ref %v", ref)
err = fmt.Errorf("parent reference %v not found", ref)
return
}
auxID = rn.Resource.GetID()
if auxID == 0 {
err = fmt.Errorf("related resource doesn't provide an ID")
err = fmt.Errorf("parent reference does not provide an identifier")
return
}

View File

@@ -8,7 +8,6 @@ package envoy
import (
"context"
"fmt"
"io"
"os"
"strings"
@@ -18,6 +17,7 @@ import (
"github.com/cortezaproject/corteza/server/pkg/y7s"
"github.com/cortezaproject/corteza/server/system/types"
systemTypes "github.com/cortezaproject/corteza/server/system/types"
"github.com/pkg/errors"
"github.com/spf13/cast"
"golang.org/x/text/language"
"gopkg.in/yaml.v3"
@@ -36,6 +36,10 @@ type (
}
)
const (
paramsKeyStream = "stream"
)
func (d YamlDecoder) CanFile(f *os.File) (ok bool) {
// @todo improve/expand
return d.canExt(f.Name())
@@ -64,6 +68,7 @@ func (d YamlDecoder) Decode(ctx context.Context, p envoyx.DecodeParams) (out env
doc := &auxYamlDoc{}
err = yaml.NewDecoder(r).Decode(doc)
if err != nil {
err = errors.Wrap(err, "system yaml decoder: failed to decode document")
return
}
@@ -86,24 +91,28 @@ func (d *auxYamlDoc) UnmarshalYAML(n *yaml.Node) (err error) {
if y7s.IsMapping(v) {
aux, err = d.unmarshalApplicationMap(dctx, v)
d.nodes = append(d.nodes, aux...)
return err
}
if y7s.IsSeq(v) {
aux, err = d.unmarshalApplicationSeq(dctx, v)
d.nodes = append(d.nodes, aux...)
}
if err != nil {
err = errors.Wrap(err, "failed to unmarshal application")
}
return err
case "apigwroute", "endpoints":
if y7s.IsMapping(v) {
aux, err = d.unmarshalApigwRouteMap(dctx, v)
d.nodes = append(d.nodes, aux...)
return err
}
if y7s.IsSeq(v) {
aux, err = d.unmarshalApigwRouteSeq(dctx, v)
d.nodes = append(d.nodes, aux...)
}
if err != nil {
err = errors.Wrap(err, "failed to unmarshal apigwRoute")
}
return err
case "apigwfilter":
@@ -111,102 +120,121 @@ func (d *auxYamlDoc) UnmarshalYAML(n *yaml.Node) (err error) {
aux, err = d.unmarshalApigwFilterSeq(dctx, v)
d.nodes = append(d.nodes, aux...)
}
if err != nil {
err = errors.Wrap(err, "failed to unmarshal apigwFilter")
}
return err
case "authclient", "authclients":
if y7s.IsMapping(v) {
aux, err = d.unmarshalAuthClientMap(dctx, v)
d.nodes = append(d.nodes, aux...)
return err
}
if y7s.IsSeq(v) {
aux, err = d.unmarshalAuthClientSeq(dctx, v)
d.nodes = append(d.nodes, aux...)
}
if err != nil {
err = errors.Wrap(err, "failed to unmarshal authClient")
}
return err
case "queue":
if y7s.IsMapping(v) {
aux, err = d.unmarshalQueueMap(dctx, v)
d.nodes = append(d.nodes, aux...)
return err
}
if y7s.IsSeq(v) {
aux, err = d.unmarshalQueueSeq(dctx, v)
d.nodes = append(d.nodes, aux...)
}
if err != nil {
err = errors.Wrap(err, "failed to unmarshal queue")
}
return err
case "report", "reports":
if y7s.IsMapping(v) {
aux, err = d.unmarshalReportMap(dctx, v)
d.nodes = append(d.nodes, aux...)
return err
}
if y7s.IsSeq(v) {
aux, err = d.unmarshalReportSeq(dctx, v)
d.nodes = append(d.nodes, aux...)
}
if err != nil {
err = errors.Wrap(err, "failed to unmarshal report")
}
return err
case "role", "roles":
if y7s.IsMapping(v) {
aux, err = d.unmarshalRoleMap(dctx, v)
d.nodes = append(d.nodes, aux...)
return err
}
if y7s.IsSeq(v) {
aux, err = d.unmarshalRoleSeq(dctx, v)
d.nodes = append(d.nodes, aux...)
}
if err != nil {
err = errors.Wrap(err, "failed to unmarshal role")
}
return err
case "template", "templates":
if y7s.IsMapping(v) {
aux, err = d.unmarshalTemplateMap(dctx, v)
d.nodes = append(d.nodes, aux...)
return err
}
if y7s.IsSeq(v) {
aux, err = d.unmarshalTemplateSeq(dctx, v)
d.nodes = append(d.nodes, aux...)
}
if err != nil {
err = errors.Wrap(err, "failed to unmarshal template")
}
return err
case "user", "users", "usr":
if y7s.IsMapping(v) {
aux, err = d.unmarshalUserMap(dctx, v)
d.nodes = append(d.nodes, aux...)
return err
}
if y7s.IsSeq(v) {
aux, err = d.unmarshalUserSeq(dctx, v)
d.nodes = append(d.nodes, aux...)
}
if err != nil {
err = errors.Wrap(err, "failed to unmarshal user")
}
return err
case "dalconnection", "connection", "connections":
if y7s.IsMapping(v) {
aux, err = d.unmarshalDalConnectionMap(dctx, v)
d.nodes = append(d.nodes, aux...)
return err
}
if y7s.IsSeq(v) {
aux, err = d.unmarshalDalConnectionSeq(dctx, v)
d.nodes = append(d.nodes, aux...)
}
if err != nil {
err = errors.Wrap(err, "failed to unmarshal dalConnection")
}
return err
case "dalsensitivitylevel", "sensitivity_level":
if y7s.IsMapping(v) {
aux, err = d.unmarshalDalSensitivityLevelMap(dctx, v)
d.nodes = append(d.nodes, aux...)
return err
}
if y7s.IsSeq(v) {
aux, err = d.unmarshalDalSensitivityLevelSeq(dctx, v)
d.nodes = append(d.nodes, aux...)
}
if err != nil {
err = errors.Wrap(err, "failed to unmarshal dalSensitivityLevel")
}
return err
// Access control nodes
@@ -214,14 +242,14 @@ func (d *auxYamlDoc) UnmarshalYAML(n *yaml.Node) (err error) {
aux, err = unmarshalAllowNode(v)
d.nodes = append(d.nodes, aux...)
if err != nil {
return err
err = errors.Wrap(err, "failed to unmarshal node: RBAC allow")
}
case "deny":
aux, err = unmarshalDenyNode(v)
d.nodes = append(d.nodes, aux...)
if err != nil {
return err
err = errors.Wrap(err, "failed to unmarshal node: RBAC deny")
}
// Resource translation nodes
@@ -229,7 +257,7 @@ func (d *auxYamlDoc) UnmarshalYAML(n *yaml.Node) (err error) {
aux, err = unmarshalLocaleNode(v)
d.nodes = append(d.nodes, aux...)
if err != nil {
return err
err = errors.Wrap(err, "failed to unmarshal node: locale")
}
// Offload to custom handlers
@@ -237,7 +265,7 @@ func (d *auxYamlDoc) UnmarshalYAML(n *yaml.Node) (err error) {
aux, err = d.unmarshalYAML(kv, v)
d.nodes = append(d.nodes, aux...)
if err != nil {
return err
err = errors.Wrap(err, "failed to unmarshal node")
}
}
return nil
@@ -3418,7 +3446,7 @@ func (d *auxYamlDoc) decodeEnvoyConfig(n *yaml.Node) (out envoyx.EnvoyConfig) {
// // // // // // // // // // // // // // // // // // // // // // // // //
func (d YamlDecoder) getReader(ctx context.Context, p envoyx.DecodeParams) (r io.Reader, err error) {
aux, ok := p.Params["stream"]
aux, ok := p.Params[paramsKeyStream]
if ok {
r, ok = aux.(io.Reader)
if ok {
@@ -3427,7 +3455,7 @@ func (d YamlDecoder) getReader(ctx context.Context, p envoyx.DecodeParams) (r io
}
// @todo consider adding support for managing files from a location
err = fmt.Errorf("YAML decoder expects a stream conforming to io.Reader interface")
err = errors.Errorf("YAML decoder expects a stream conforming to io.Reader interface")
return
}

View File

@@ -8,13 +8,13 @@ package envoy
import (
"context"
"fmt"
"io"
"time"
"github.com/cortezaproject/corteza/server/pkg/envoyx"
"github.com/cortezaproject/corteza/server/pkg/y7s"
"github.com/cortezaproject/corteza/server/system/types"
"github.com/pkg/errors"
"gopkg.in/yaml.v3"
)
@@ -24,6 +24,10 @@ type (
YamlEncoder struct{}
)
const (
paramsKeyWriter = "writer"
)
// Encode encodes the given Corteza resources into some YAML supported format
//
// Encoding should not do any additional processing apart from matching with
@@ -1068,7 +1072,6 @@ func (e YamlEncoder) encodeTimestampNil(p envoyx.EncodeParams, t *time.Time) (an
return nil, nil
}
// @todo timestamp encoding format
return e.encodeTimestamp(p, *t)
}
@@ -1089,7 +1092,7 @@ func (e YamlEncoder) encodeRef(p envoyx.EncodeParams, id uint64, field string, n
// // // // // // // // // // // // // // // // // // // // // // // // //
func (e YamlEncoder) getWriter(p envoyx.EncodeParams) (out io.Writer, err error) {
aux, ok := p.Params["writer"]
aux, ok := p.Params[paramsKeyWriter]
if ok {
out, ok = aux.(io.Writer)
if ok {
@@ -1098,6 +1101,6 @@ func (e YamlEncoder) getWriter(p envoyx.EncodeParams) (out io.Writer, err error)
}
// @todo consider adding support for managing files from a location
err = fmt.Errorf("YAML encoder expects a writer conforming to io.Writer interface")
err = errors.Errorf("YAML encoder expects a writer conforming to io.Writer interface")
return
}

View File

@@ -254,13 +254,13 @@ func (e YamlEncoder) resolveRulePathDeps(ctx context.Context, tt envoyx.Traverse
rn := tt.ParentForRef(n, ref)
if rn == nil {
err = fmt.Errorf("missing node for ref %v", ref)
err = fmt.Errorf("parent reference %v not found", ref)
return
}
auxIdent = rn.Identifiers.FriendlyIdentifier()
if auxIdent == "" || auxIdent == "0" {
err = fmt.Errorf("related resource doesn't provide an ID")
err = fmt.Errorf("parent reference does not provide an identifier")
return
}
@@ -292,9 +292,10 @@ func (e YamlEncoder) encodeAuthClientSecurityC(ctx context.Context, p envoyx.Enc
var impersonateUser string
if _, ok := n.References["Security.ImpersonateUser.UserID"]; ok {
node := tt.ParentForRef(n, n.References["Security.ImpersonateUser.UserID"])
usrRef := n.References["Security.ImpersonateUser.UserID"]
node := tt.ParentForRef(n, usrRef)
if node == nil {
err = fmt.Errorf("node not found @todo error")
err = fmt.Errorf("invalid user reference %v: user does not exist", usrRef)
return
}
impersonateUser = n.Identifiers.FriendlyIdentifier()
@@ -312,9 +313,10 @@ func (e YamlEncoder) encodeRoleSlice(n *envoyx.Node, tt envoyx.Traverser, k stri
sq, _ := y7s.MakeSeq()
for i := range rr {
node := tt.ParentForRef(n, n.References[fmt.Sprintf("%s.%d.RoleID", k, i)])
roleRef := n.References[fmt.Sprintf("%s.%d.RoleID", k, i)]
node := tt.ParentForRef(n, roleRef)
if node == nil {
err = fmt.Errorf("node not found @todo error")
err = fmt.Errorf("invalid user reference %v: user does not exist", roleRef)
return
}