Skip to content

Commit

Permalink
🐛 update for field in props (#2973)
Browse files Browse the repository at this point in the history
We were never fully implementing referential properties until now. This
PR fixes the fact that the `for` field is referencing other properties
in the same bundle using their `uid`. It now correctly generates their
`mrn` and sets the `uid` to empty string like in the property itself.

Signed-off-by: Dominik Richter <[email protected]>
  • Loading branch information
arlimus authored Jan 10, 2024
1 parent 76a73c4 commit 0e7903c
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 4 deletions.
40 changes: 37 additions & 3 deletions explorer/property.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
package explorer

import (
"context"
"errors"

"github.com/rs/zerolog/log"
Expand All @@ -26,9 +25,20 @@ func (p *Property) RefreshMRN(ownerMRN string) error {
log.Error().Err(err).Str("owner", ownerMRN).Str("uid", p.Uid).Msg("failed to refresh mrn")
return multierr.Wrap(err, "failed to refresh mrn for query "+p.Title)
}

p.Mrn = nu
p.Uid = ""

for i := range p.For {
pfor := p.For[i]
pforNu, err := RefreshMRN(ownerMRN, pfor.Mrn, MRN_RESOURCE_QUERY, pfor.Uid)
if err != nil {
log.Error().Err(err).Str("owner", ownerMRN).Str("uid", p.Uid).Msg("failed to refresh mrn")
return multierr.Wrap(err, "failed to refresh mrn for query "+p.Title)
}
pfor.Mrn = pforNu
pfor.Uid = ""
}

return nil
}

Expand Down Expand Up @@ -125,26 +135,50 @@ func NewPropsCache() PropsCache {
func (c PropsCache) Add(props ...*Property) {
for i := range props {
base := props[i]

if base.Uid != "" && base.Mrn == "" {
// keep track of properties that were specified by uid only.
// we will merge them in later if we find a matching mrn
c.uidOnlyProps[base.Uid] = base
continue
}

// All properties at this point should have a mrn
merged := base

if base.Mrn != "" {
name, _ := mrn.GetResource(base.Mrn, MRN_RESOURCE_QUERY)
if uidProp, ok := c.uidOnlyProps[name]; ok {
p := proto.Clone(uidProp).(*Property)
p.Merge(base)
base = p
merged = p
}

if existingProp, ok := c.cache[base.Mrn]; ok {
existingProp.Merge(base)
merged = existingProp
} else {
c.cache[base.Mrn] = base
}
}

for i := range base.For {
pfor := base.For[i]
if pfor.Mrn != "" {
if existingProp, ok := c.cache[pfor.Mrn]; ok {
existingProp.Merge(merged)
} else {
c.cache[pfor.Mrn] = merged
}
}
}
}
}

// try to Get the mrn, will also return uid-based
// properties if they exist first
func (c PropsCache) Get(ctx context.Context, propMrn string) (*Property, string, error) {
func (c PropsCache) Get(propMrn string) (*Property, string, error) {
if res, ok := c.cache[propMrn]; ok {
name, err := mrn.GetResource(propMrn, MRN_RESOURCE_QUERY)
if err != nil {
Expand Down
28 changes: 28 additions & 0 deletions explorer/property_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1

package explorer

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestProperty_RefreshMrn(t *testing.T) {
in := &Property{
Uid: "uid1",
For: []*ObjectRef{{
Uid: "uid2",
}},
}

err := in.RefreshMRN("//my.owner")
require.NoError(t, err)

assert.Equal(t, "", in.Uid)
assert.Equal(t, "//my.owner/queries/uid1", in.Mrn)
assert.Equal(t, "", in.For[0].Uid)
assert.Equal(t, "//my.owner/queries/uid2", in.For[0].Mrn)
}
2 changes: 1 addition & 1 deletion explorer/query_conductor.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ func (s *LocalServices) addQueryToJob(ctx context.Context, query *Mquery, job *E
for i := range query.Props {
prop := query.Props[i]

override, name, _ := propsCache.Get(ctx, prop.Mrn)
override, name, _ := propsCache.Get(prop.Mrn)
if override != nil {
prop = override
}
Expand Down

0 comments on commit 0e7903c

Please sign in to comment.