Skip to content

Commit

Permalink
⭐ terraform.resources( filter ) (#2069)
Browse files Browse the repository at this point in the history
Support both string and regex filters for easily accessing all the resources that you need via their label.

Signed-off-by: Dominik Richter <[email protected]>
  • Loading branch information
arlimus authored Oct 3, 2023
1 parent c795e7c commit 020a750
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 27 deletions.
2 changes: 1 addition & 1 deletion mqlc/mqlc.go
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ func (c *compiler) unnamedArgs(callerLabel string, init *resources.Init, args []
// This needs massive improvements to dynamically cast them in LLX.
// For a full description see: https://gitlab.com/mondoolabs/mondoo/-/issues/241
// This is ONLY a temporary workaround which works in a few cases:
if vType == types.Dict && expectedType == types.String {
if (vType == types.Dict && expectedType == types.String) || expectedType == types.Any {
// we are good, LLX will handle it
} else {
return nil, errors.New("Incorrect type on argument " + strconv.Itoa(idx) +
Expand Down
18 changes: 18 additions & 0 deletions providers-sdk/v1/lr/go.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,18 @@ func (b *goBuilder) goSetData(r []*Resource) {
continue
}

if field.BasicField.Type.isAny() {
x := fmt.Sprintf(`"%s.%s": func(r plugin.Resource, v *llx.RawData) (ok bool) {
r.(*%s).%s, ok = plugin.RawDataToAnyTValue(v, v.Error)
return
},`,
resource.ID, field.BasicField.ID,
resource.structName(b), field.BasicField.methodname(),
)
fields = append(fields, x)
continue
}

x := fmt.Sprintf(`"%s.%s": func(r plugin.Resource, v *llx.RawData) (ok bool) {
r.(*%s).%s, ok = plugin.RawToTValue[%s](v.Value, v.Error)
return
Expand Down Expand Up @@ -625,6 +637,8 @@ func (t *SimpleType) typeItems(ast *LR) types.Type {
return types.Time
case "dict":
return types.Dict
case "any":
return types.Any
default:
return resourceType(t.Type, ast)
}
Expand Down Expand Up @@ -706,6 +720,10 @@ func (t *SimpleType) mondooTypeItems(b *goBuilder) string {
// panic("Cannot convert type '" + t.Type + "' to mondoo type")
}

func (t *Type) isAny() bool {
return t != nil && t.SimpleType != nil && t.SimpleType.Type == "any"
}

func (t *Type) containsResource(b *goBuilder) bool {
if t.ListType != nil {
return t.ListType.Type.containsResource(b)
Expand Down
7 changes: 7 additions & 0 deletions providers-sdk/v1/plugin/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,13 @@ func RawToTValue[T any](value interface{}, err error) (TValue[T], bool) {
return TValue[T]{Data: tv, State: StateIsSet, Error: err}, true
}

func RawDataToAnyTValue(value *llx.RawData, err error) (TValue[interface{}], bool) {
if value == nil {
return TValue[interface{}]{State: StateIsNull | StateIsSet, Error: err}, true
}
return TValue[interface{}]{Data: value, State: StateIsSet, Error: err}, true
}

type State byte

type notReady struct{}
Expand Down
67 changes: 63 additions & 4 deletions providers/terraform/resources/hcl.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/json"
"errors"
"fmt"
"regexp"
"strconv"
"strings"

Expand Down Expand Up @@ -130,10 +131,6 @@ func (t *mqlTerraform) datasources() ([]interface{}, error) {
return filterBlockByType(t.MqlRuntime, "data")
}

func (t *mqlTerraform) resources() ([]interface{}, error) {
return filterBlockByType(t.MqlRuntime, "resource")
}

func (t *mqlTerraform) variables() ([]interface{}, error) {
return filterBlockByType(t.MqlRuntime, "variable")
}
Expand Down Expand Up @@ -170,6 +167,68 @@ func extractHclCodeSnippet(file *hcl.File, fileRange hcl.Range) string {
return sb.String()
}

func (c *mqlTerraformResources) id() (string, error) {
filter := c.Filter.Data
if filter == nil {
return "", nil
}
return filter.(*llx.RawData).String(), nil
}

func (c *mqlTerraformResources) list() ([]interface{}, error) {
blocks, err := filterBlockByType(c.MqlRuntime, "resource")
if err != nil {
return nil, err
}

filter := c.Filter.Data
if filter == nil {
return blocks, err
}

var isOK func(s string) bool
raw, ok := filter.(*llx.RawData)
if !ok {
return blocks, errors.New("can't use filters, incompatible internal typ")
}

switch raw.Type {
case types.String, types.Dict:
expected, ok := raw.Value.(string)
if !ok {
return blocks, errors.New("can't use filters, it should be a simple string")
}
isOK = func(s string) bool {
return s == expected
}
case types.Regex:
expected := raw.Value.(string)
re, err := regexp.Compile(expected)
if err != nil {
return blocks, errors.New("failed to compile regex for filter: " + expected)
}
isOK = func(s string) bool {
return re.MatchString(s)
}
default:
return blocks, err
}

var res []interface{}
for i := range blocks {
block := blocks[i].(*mqlTerraformBlock)
labels := block.Labels.Data
if len(labels) == 0 {
continue
}
if isOK(labels[0].(string)) {
res = append(res, block)
}
}

return res, nil
}

func newMqlHclBlock(runtime *plugin.Runtime, block *hcl.Block, file *hcl.File) (plugin.Resource, error) {
start, end, err := newFilePosRange(runtime, block.TypeRange)
if err != nil {
Expand Down
8 changes: 6 additions & 2 deletions providers/terraform/resources/terraform.lr
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ terraform {
providers() []terraform.block
// Data sources blocks
datasources() []terraform.block
// All blocks with type resource
resources() []terraform.block
// Variable blocks
variables() []terraform.block
// Output blocks
outputs() []terraform.block
}

terraform.resources {
[]terraform.block
init(filter any)
filter any
}

// Terraform Configuration File represents a .tf or .tf.json file
terraform.file {
// tf or tf.json file
Expand Down
104 changes: 84 additions & 20 deletions providers/terraform/resources/terraform.lr.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions providers/terraform/resources/terraform.lr.manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ resources:
platform:
name:
- terraform
terraform.resources:
fields:
filter: {}
list: {}
min_mondoo_version: 9.0.0
platform:
name:
- terraform
terraform.settings:
fields:
backend:
Expand Down

0 comments on commit 020a750

Please sign in to comment.