Skip to content

Commit

Permalink
🧹 default to MQL asset context (#3805)
Browse files Browse the repository at this point in the history
* 🧹 default to MQL asset context

We had this feature-flag since v7, aimed to make it the default in v8. Until now, it has not been mainlined.

This is changing today. Compiling with context is generally very helpful
and provides nice auto-complete on embedded resources (similar to how
you can access embedded fields in golang structs).

There is more work to be done, namely that we want to tie the context of
the connection to the MQL execution itself. This will allow us to call
fields without constantly refering to the global context in the future.
(i.e. instead of `docker.file.sth`, once you connect to a Dockerfile you
can just call `sth`). For this reason, we retain the feature-flag and
will complete its functionality in this major release.

* 🟢 remove cross-provider aliases (for now)

These were added in v7, but unfortunately we had to break the compatibility in v9. We will regain this ability, once cross-provider calls (in the new model) are added back.

Signed-off-by: Dominik Richter <[email protected]>

---------

Signed-off-by: Dominik Richter <[email protected]>
  • Loading branch information
arlimus authored Apr 22, 2024
1 parent 225f397 commit 1c99b96
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 83 deletions.
3 changes: 2 additions & 1 deletion featureflags.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ const (
// MQLAssetContext feature flag
//
// start: v7.0
// end: v8.0
// updated: v11.0 We default to embed flags and re-use this feature for actual asset context
// end: v12.0
MQLAssetContext

// ErrorsAsFailures feature flag
Expand Down
20 changes: 11 additions & 9 deletions llx/llx.go
Original file line number Diff line number Diff line change
Expand Up @@ -693,15 +693,17 @@ func pargs2argmap(b *blockExecutor, ref uint64, args []*Primitive) (map[string]*

func (b *blockExecutor) createResource(name string, binding uint64, f *Function, ref uint64) (*RawData, uint64, error) {
runtime := b.ctx.runtime
if binding != 0 {
panic("NOT SURE HOW TO RESOLVE THIS")
// res, dref, err := b.resolveRef(binding, ref)
// if dref != 0 || err != nil {
// return res, dref, err
// }
// mqlResource := res.Value.(resourceInterface).MqlResource()
// runtime = mqlResource.MqlRuntime
}
// if binding != 0 {
// // This happens with aliases, like:
// // > os.unix.sshd.config.file.path
// // TODO: Re-connect cross-provider resource calls in this part
// res, dref, err := b.resolveRef(binding, ref)
// if dref != 0 || err != nil {
// return res, dref, err
// }
// mqlResource := res.Value.(resourceInterface).MqlResource()
// // runtime = mqlResource.MqlRuntime
// }

args, rref, err := pargs2argmap(b, ref, f.Args)
if err != nil || rref != 0 {
Expand Down
2 changes: 1 addition & 1 deletion mql/mql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func TestResourceAliases(t *testing.T) {
"_": llx.ResourceData(&llx.MockResource{Name: "sshd"}, "os.unix.sshd"),
"__s": llx.NilData,
"__t": llx.BoolData(true),
"k6rlXoYpV48Qd19gKeNl+/IiPnkI5VNQBiqZBca3gDKsIRiLcpXQUlDv52x9sscIWiqOMpC7+x/aBpY0IUq0ww==": llx.StringData("/etc/ssh/sshd_config"),
"SM/iGp+gb6JBt0bBm5RWqTtPLKzx6ebI+nUm4Q6LCQDuEu1QSRsWqEI3Tl/oK+u0b0eit+nTLhNdjlsOdIIDJQ==": llx.StringData("/etc/ssh/sshd_config"),
},
},
})
Expand Down
73 changes: 1 addition & 72 deletions mqlc/mqlc.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package mqlc

import (
"errors"
"fmt"
"regexp"
"sort"
"strconv"
Expand Down Expand Up @@ -919,11 +918,7 @@ func (c *compiler) findField(resource *resources.ResourceInfo, fieldName string)
// example: user { name } , where name is compiled bound to the user
// it will return false if it cannot bind the identifier
func (c *compiler) compileBoundIdentifier(id string, binding *variable, call *parser.Call) (bool, types.Type, error) {
if c.UseAssetContext {
return c.compileBoundIdentifierWithMqlCtx(id, binding, call)
} else {
return c.compileBoundIdentifierWithoutMqlCtx(id, binding, call)
}
return c.compileBoundIdentifierWithMqlCtx(id, binding, call)
}

func (c *compiler) compileBoundIdentifierWithMqlCtx(id string, binding *variable, call *parser.Call) (bool, types.Type, error) {
Expand Down Expand Up @@ -1018,72 +1013,6 @@ func (c *compiler) compileBoundIdentifierWithMqlCtx(id string, binding *variable
return false, types.Nil, nil
}

// compileBoundIdentifierWithoutMqlCtx will compile a bound identifier without being able
// create implicit resources with context attached. The reason this is needed is because
// that feature requires use of a new global function 'createResource'. We cannot start
// automatically adding that to compiled queries without breaking existing clients
func (c *compiler) compileBoundIdentifierWithoutMqlCtx(id string, binding *variable, call *parser.Call) (bool, types.Type, error) {
typ := binding.typ

if typ.IsResource() {
resource, fieldinfo := c.Schema.LookupField(typ.ResourceName(), id)
if resource == nil {
return true, types.Nil, errors.New("cannot find resource that is called by '" + id + "' of type " + typ.Label())
}

if fieldinfo != nil {
c.CompilerConfig.Stats.CallField(resource.Name, fieldinfo)

if call != nil && len(call.Function) > 0 {
return true, types.Nil, errors.New("cannot call resource field with arguments yet")
}

if fieldinfo.IsEmbedded {
return true, types.Nil, fmt.Errorf("field '%s' on '%s' requires the MQLAssetContext feature", id, typ.Label())
}

c.Result.MinMondooVersion = getMinMondooVersion(c.Schema, c.Result.MinMondooVersion, resource.Name, id)

// this only happens when we call a field of a bridging resource,
// in which case we don't call the field (since there is nothing to do)
// and instead we call the resource directly:
typ := types.Type(fieldinfo.Type)
if fieldinfo.IsImplicitResource {
name := typ.ResourceName()
c.addChunk(&llx.Chunk{
Call: llx.Chunk_FUNCTION,
Id: name,
})

// the new ID is now the full resource call, which is not what the
// field is originally labeled when we get it, so we have to fix it
checksum := c.Result.CodeV2.Checksums[c.tailRef()]
c.Result.Labels.Labels[checksum] = id
return true, typ, nil
}

c.addChunk(&llx.Chunk{
Call: llx.Chunk_FUNCTION,
Id: id,
Function: &llx.Function{
Type: fieldinfo.Type,
Binding: binding.ref,
},
})
return true, typ, nil
}
}

h, _ := builtinFunction(typ, id)
if h != nil {
call = filterTrailingNullArgs(call)
typ, err := c.compileBuiltinFunction(h, id, binding, call)
return true, typ, err
}

return false, types.Nil, nil
}

// compile a resource from an identifier, trying to find the longest matching resource
// and execute all call functions if there are any
func (c *compiler) compileResource(id string, calls []*parser.Call) (bool, []*parser.Call, types.Type, error) {
Expand Down

0 comments on commit 1c99b96

Please sign in to comment.