Skip to content

Commit

Permalink
🐛 update for field in props
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 <dominik.richter@gmail.com>
  • Loading branch information
arlimus committed Jan 8, 2024
1 parent 076fe69 commit 167e16c
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 167e16c

Please sign in to comment.