Skip to content

Commit

Permalink
When passing a slice as a query arg, ensure it is strongly typed so P…
Browse files Browse the repository at this point in the history
…ostgres can convert it. Fix multiple with blocks. #2789. #2772
  • Loading branch information
kaidaguerre authored Nov 24, 2022
1 parent daf952c commit b1c1c4e
Show file tree
Hide file tree
Showing 106 changed files with 283 additions and 70 deletions.
7 changes: 5 additions & 2 deletions pkg/dashboard/dashboardexecute/leaf_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,10 @@ func (r *LeafRun) addRuntimeDependencies() {
return
}
runtimeDependencies := queryProvider.GetRuntimeDependencies()
for name, dep := range runtimeDependencies {
for n, d := range runtimeDependencies {
// read name and dep into local loop vars to ensure correct value used when getValueFunc is invoked
name := n
dep := d
// determine the function to use to retrieve the runtime dependency value
var getValueFunc func(string) (any, error)
switch dep.PropertyPath.ItemType {
Expand Down Expand Up @@ -563,6 +566,7 @@ func (r *LeafRun) combineChildData() {
func (r *LeafRun) getWithValue(name string, path *modconfig.ParsedPropertyPath) (any, error) {
r.withValueMutex.Lock()
defer r.withValueMutex.Unlock()

val, ok := r.withValues[name]
if !ok {
return nil, nil
Expand Down Expand Up @@ -637,7 +641,6 @@ func (r *LeafRun) getWithValue(name string, path *modconfig.ParsedPropertyPath)
}

func columnValuesFromRows(column string, rows []map[string]interface{}) (any, error) {

var res = make([]any, len(rows))
for i, row := range rows {
var ok bool
Expand Down
18 changes: 12 additions & 6 deletions pkg/steampipeconfig/modconfig/query_args.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package modconfig

import (
"encoding/json"
"fmt"
"strings"

Expand Down Expand Up @@ -48,14 +49,19 @@ func (q *QueryArgs) ArgsStringList() []string {
return argsStringList
}

// TODO RENAME
// SafeArgsList convert ArgLists into list of strings but return as an interface slice
func (q *QueryArgs) SafeArgsList() []any {
var argsStringList = make([]any, len(q.ArgList))
// ConvertArgsList convert ArgList into list of interface{} by unmarshalling
func (q *QueryArgs) ConvertArgsList() ([]any, error) {
var argList = make([]any, len(q.ArgList))

for i, a := range q.ArgList {
argsStringList[i] = typehelpers.SafeString(a)
if a != nil {
err := json.Unmarshal([]byte(*a), &argList[i])
if err != nil {
return nil, err
}
}
}
return argsStringList
return argList, nil
}

func NewQueryArgs() *QueryArgs {
Expand Down
12 changes: 10 additions & 2 deletions pkg/steampipeconfig/modconfig/query_args_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"log"
"strings"

"github.com/turbot/steampipe/pkg/type_conversion"
"github.com/turbot/steampipe/pkg/utils"
)

Expand Down Expand Up @@ -69,6 +70,11 @@ func ResolveArgs(source QueryProvider, runtimeArgs *QueryArgs) ([]any, error) {
return nil, nil
}

// convert any array args into a strongly typed array
for i, v := range paramVals {
paramVals[i] = type_conversion.AnySliceToTypedSlice(v)
}

// success!
return paramVals, nil
}
Expand Down Expand Up @@ -135,7 +141,10 @@ func resolvePositionalParameters(queryProvider QueryProvider, args *QueryArgs) (
if len(params) == 0 {
// no params defined, so we return as many args as are provided
// (convert from *string to string)
argValues = args.SafeArgsList()
argValues, err = args.ConvertArgsList()
if err != nil {
return nil, nil, err
}
return argValues, nil, nil
}

Expand Down Expand Up @@ -173,7 +182,6 @@ func resolvePositionalParameters(queryProvider QueryProvider, args *QueryArgs) (
if err != nil {
return nil, nil, err
}

argValues[i] = argVal
} else if defaultValue != nil {
// so we have run out of provided params - is there a default?
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

188 changes: 188 additions & 0 deletions pkg/steampipeconfig/testdata/manual_testing/args/with1/dashboard.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@

dashboard "bug_column_does_not_exist" {
title = "column does not exist"


input "policy_arn" {
title = "Select a policy:"
query = query.test1_aws_iam_policy_input
width = 4
}


container {

graph {
title = "Relationships"
type = "graph"
direction = "left_right" //"TD"

with "attached_users" {
sql = <<-EOQ
select
u.arn as user_arn
--,policy_arn
from
aws_iam_user as u,
jsonb_array_elements_text(attached_policy_arns) as policy_arn
where
policy_arn = $1;
--policy_arn = 'arn:aws:iam::aws:policy/AdministratorAccess'
EOQ

param policy_arn {
// commented out becuase input not working here yet..
// default = self.input.policy_arn.value
default = "arn:aws:iam::aws:policy/AdministratorAccess"
}

}

with "attached_roles" {
sql = <<-EOQ
select
arn as role_arn
from
aws_iam_role,
jsonb_array_elements_text(attached_policy_arns) as policy_arn
where
policy_arn = $1;
EOQ

#args = [self.input.policy_arn.value]
#args = ["arn:aws:iam::aws:policy/AdministratorAccess"]

param policy_arn {
//default = self.input.policy_arn.value
default = "arn:aws:iam::aws:policy/AdministratorAccess"
}
}


nodes = [
node.test1_aws_iam_policy_node,
node.test1_aws_iam_user_nodes,
]

edges = [
edge.test1_aws_iam_policy_from_iam_user_edges,
]

args = {
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess" //self.input.policy_arn.value

//// works if you hardcode the list
policy_arns = ["arn:aws:iam::aws:policy/AdministratorAccess"]

// this causes cannot serialize unknown values
//policy_arns = [self.input.policy_arn.value]

user_arns = with.attached_users.rows[*].user_arn
role_arns = with.attached_roles.rows[*].role_arn

}
}

}
}

query "test1_aws_iam_policy_input" {
sql = <<-EOQ
with policies as (
select
title as label,
arn as value,
json_build_object(
'account_id', account_id
) as tags
from
aws_iam_policy
where
not is_aws_managed
union all select
distinct on (arn)
title as label,
arn as value,
json_build_object(
'account_id', 'AWS Managed'
) as tags
from
aws_iam_policy
where
is_aws_managed
)
select
*
from
policies
order by
label;
EOQ
}



node "test1_aws_iam_policy_node" {
sql = <<-EOQ
select
distinct on (arn)
arn as id,
name as title,
jsonb_build_object(
'ARN', arn,
'AWS Managed', is_aws_managed::text,
'Attached', is_attached::text,
'Create Date', create_date,
'Account ID', account_id
) as properties
from
aws_iam_policy
where
arn = $1;
EOQ

param "policy_arn" {}
}


node "test1_aws_iam_user_nodes" {

sql = <<-EOQ
select
arn as id,
name as title,
jsonb_build_object(
'ARN', arn,
'Path', path,
'Create Date', create_date,
'MFA Enabled', mfa_enabled::text,
'Account ID', account_id
) as properties
from
aws_iam_user
where
arn = any($1::text[]);
EOQ

param "user_arns" {}
}



edge "test1_aws_iam_policy_from_iam_user_edges" {
title = "attaches"

sql = <<-EOQ
select
policy_arns as to_id,
user_arns as from_id
from
unnest($1::text[]) as policy_arns,
unnest($2::text[]) as user_arns
EOQ

param "policy_arns" {}
param "user_arns" {}

}
19 changes: 19 additions & 0 deletions pkg/steampipeconfig/testdata/manual_testing/args/with1/query.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
query "q1" {
description = "test array argument"
sql = <<-EOQ
select
name
from
aws_iam_user
where
arn = any($1::text[]);
EOQ

param arns{
default = [
"arn:aws:iam::876515858155:user/lalit",
"arn:aws:iam::876515858155:user/mike"
]
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod reports_poc {
title = "Reports POC"
}
Loading

0 comments on commit b1c1c4e

Please sign in to comment.