Skip to content

Commit

Permalink
Add table and plugin level defaults for ShouldIgnoreError and RetryCo…
Browse files Browse the repository at this point in the history
…nfig. Closes #257
  • Loading branch information
kaidaguerre committed Mar 28, 2022
1 parent 8d0ee5c commit cf18abf
Show file tree
Hide file tree
Showing 18 changed files with 492 additions and 96 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/acceptance-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,28 @@ env:
STEAMPIPE_UPDATE_CHECK: false

jobs:
sdkUnitTests:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.16

- name: Run SDK Unit Tests
run: |
go clean -testcache
go test -timeout 30s ./...
buildChaosPlugin:
name: Build Chaos Plugin
runs-on: ubuntu-latest
steps:

- name: Set up Go
uses: actions/setup-go@v2
with:
Expand Down
2 changes: 1 addition & 1 deletion cache/index_item.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (i IndexItem) SatisfiesQuals(checkQualMap map[string]*proto.Quals, keyColum
// isSubset means all data returned by check quals is returned by index quals
isSubset = checkQuals.IsASubsetOf(indexQuals)
} else {
log.Printf("[TRACE] SatisfiesQuals index item has qual for %s which check quals do not - NOT SATISFIED")
log.Printf("[TRACE] SatisfiesQuals index item has qual for %s which check quals do not - NOT SATISFIED", col)
}
log.Printf("[TRACE] get check qual %v, isSubset %v", ok, isSubset)
if !ok || !isSubset {
Expand Down
2 changes: 1 addition & 1 deletion cache/query_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ func (c *QueryCache) logMetrics() {
log.Printf("[TRACE] ------------------------------------ ")
log.Printf("[TRACE] Cache Metrics ")
log.Printf("[TRACE] ------------------------------------ ")
log.Printf("[TRACE] MaxCost: %d", c.cache.MaxCost)
log.Printf("[TRACE] MaxCost: %d", c.cache.MaxCost())
log.Printf("[TRACE] KeysAdded: %d", c.cache.Metrics.KeysAdded())
log.Printf("[TRACE] CostAdded: %d", c.cache.Metrics.CostAdded())
log.Printf("[TRACE] KeysEvicted: %d", c.cache.Metrics.KeysEvicted())
Expand Down
9 changes: 7 additions & 2 deletions grpc/proto/qual.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package proto
import "log"

func (x *Qual) Equals(other *Qual) bool {
log.Printf("[TRACE] me %s, other %s", x.String(), other.String())
//log.Printf("[TRACE] me %s, other %s", x.String(), other.String())
return x.String() == other.String()
}

func (x *Qual) IsASubsetOf(other *Qual) bool {
log.Printf("[TRACE] IsASubsetOf me %+v, other %+v", x, other)
//log.Printf("[TRACE] IsASubsetOf me %+v, other %+v", x, other)
operator, ok := x.Operator.(*Qual_StringValue)
if !ok {
log.Printf("[TRACE] IsASubsetOf my operator is not a string - returning false")
Expand All @@ -23,6 +23,11 @@ func (x *Qual) IsASubsetOf(other *Qual) bool {
log.Printf("[TRACE] IsASubsetOf Value nil - returning false")
return false
}
// check the fields are the same
if x.FieldName != other.FieldName {
log.Printf("[TRACE] IsASubsetOf field names different - returning false")
return false
}

switch value := x.Value.Value.(type) {
case *QualValue_StringValue:
Expand Down
8 changes: 8 additions & 0 deletions plugin/concurrency.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import (
"sync"
)

// DefaultConcurrencyConfig contains plugin level config to define default hydrate concurrency
// - this is used if no HydrateConfig is specified for a specific call
type DefaultConcurrencyConfig struct {
// max number of ALL hydrate calls in progress
TotalMaxConcurrency int
DefaultMaxConcurrency int
}

// ConcurrencyManager struct ensures that hydrate functions stay within concurrency limits
type ConcurrencyManager struct {
mut sync.Mutex
Expand Down
18 changes: 12 additions & 6 deletions plugin/connection_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ var testCasesParseConfig = map[string]parseConfigTest{
Type: schema.TypeString,
Required: true,
},
"count": {
Type: schema.TypeInt,
},
},
},
expectedFunc: func(res interface{}) bool {
Expand Down Expand Up @@ -438,12 +441,15 @@ func TestParseConnectionConfig(t *testing.T) {
}
continue
}
if test.expectedFunc != nil && !test.expectedFunc(config) {
t.Errorf(`Test: '%s' FAILED : expect verification func failed`, name)
}
if !reflect.DeepEqual(config, test.expected) {
fmt.Printf("")
t.Errorf(`Test: '%s' FAILED : expected %v, got %v`, name, test.expected, config)
if test.expectedFunc != nil {
if !test.expectedFunc(config) {
t.Errorf(`Test: '%s' FAILED : expect verification func failed`, name)
}
} else {
if !reflect.DeepEqual(config, test.expected) {
fmt.Printf("")
t.Errorf(`Test: '%s' FAILED : expected %v, got %v`, name, test.expected, config)
}
}

}
Expand Down
39 changes: 0 additions & 39 deletions plugin/hydrate_call.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,6 @@ import (
"github.com/turbot/go-kit/helpers"
)

// HydrateData contains the input data passed to every hydrate function
type HydrateData struct {
// if there was a parent-child list call, store the parent list item
ParentItem interface{}
Item interface{}
HydrateResults map[string]interface{}
}

// HydrateFunc is a function which retrieves some or all row data for a single row item.
type HydrateFunc func(context.Context, *QueryData, *HydrateData) (interface{}, error)

// HydrateDependencies defines the hydrate function dependencies - other hydrate functions which must be run first
// Deprecated: used HydrateConfig
type HydrateDependencies struct {
Func HydrateFunc
Depends []HydrateFunc
}

// HydrateConfig defines the hydrate function configurations, Name, Maximum number of concurrent calls to be allowed, dependencies
type HydrateConfig struct {
Func HydrateFunc
MaxConcurrency int
RetryConfig *RetryConfig
ShouldIgnoreError ErrorPredicate
Depends []HydrateFunc
}

type RetryConfig struct {
ShouldRetryError ErrorPredicate
}

// DefaultConcurrencyConfig contains plugin level config to define default hydrate concurrency
// - this is used if no HydrateConfig is specified for a specific call
type DefaultConcurrencyConfig struct {
// max number of ALL hydrate calls in progress
TotalMaxConcurrency int
DefaultMaxConcurrency int
}

// HydrateCall struct encapsulates a hydrate call, its config and dependencies
type HydrateCall struct {
Func HydrateFunc
Expand Down
51 changes: 51 additions & 0 deletions plugin/hydrate_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package plugin

import (
"fmt"
"strings"

"github.com/turbot/go-kit/helpers"
)

// HydrateConfig defines the hydrate function configurations, Name, Maximum number of concurrent calls to be allowed, dependencies
type HydrateConfig struct {
Func HydrateFunc
MaxConcurrency int
RetryConfig *RetryConfig

ShouldIgnoreError ErrorPredicate
Depends []HydrateFunc
}

func (c *HydrateConfig) DefaultTo(defaultConfig *HydrateConfig) {
if defaultConfig == nil {
return
}
if c.RetryConfig == nil {
c.RetryConfig = defaultConfig.RetryConfig
}
if c.Depends == nil {
c.Depends = defaultConfig.Depends
}
}

func (c *HydrateConfig) String() interface{} {
shouldIgnoreErrorString := ""
if c.ShouldIgnoreError != nil {
shouldIgnoreErrorString = helpers.GetFunctionName(c.Func)
}
var dependsStrings = make([]string, len(c.Depends))
for i, dep := range c.Depends {
dependsStrings[i] = helpers.GetFunctionName(dep)
}
return fmt.Sprintf(`Func: %s
MaxConcurrency: %d
RetryConfig: %s
ShouldIgnoreError: %s
Depends: %s`,
helpers.GetFunctionName(c.Func),
c.MaxConcurrency,
c.RetryConfig.String(),
shouldIgnoreErrorString,
strings.Join(dependsStrings, ","))
}
9 changes: 9 additions & 0 deletions plugin/hydrate_data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package plugin

// HydrateData contains the input data passed to every hydrate function
type HydrateData struct {
// if there was a parent-child list call, store the parent list item
ParentItem interface{}
Item interface{}
HydrateResults map[string]interface{}
}
8 changes: 8 additions & 0 deletions plugin/hydrate_dependencies.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package plugin

// HydrateDependencies defines the hydrate function dependencies - other hydrate functions which must be run first
// Deprecated: used HydrateConfig
type HydrateDependencies struct {
Func HydrateFunc
Depends []HydrateFunc
}
8 changes: 8 additions & 0 deletions plugin/hydrate_func.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package plugin

import (
"context"
)

// HydrateFunc is a function which retrieves some or all row data for a single row item.
type HydrateFunc func(context.Context, *QueryData, *HydrateData) (interface{}, error)
14 changes: 8 additions & 6 deletions plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,20 @@ var validSchemaModes = []string{SchemaModeStatic, SchemaModeDynamic}

// Plugin is an object used to build all necessary data for a given query
type Plugin struct {
Name string
Logger hclog.Logger
Name string
Logger hclog.Logger
// TableMap is a map of all the tables in the plugin, keyed by the table name
TableMap map[string]*Table
// TableMapFunc is a callback function which can be used to populate the table map
// this con optionally be provided by the plugin, and allows the connection config to be used in the table creation
// (connection config is not available at plugin creation time)
TableMapFunc func(ctx context.Context, p *Plugin) (map[string]*Table, error)

DefaultTransform *transform.ColumnTransforms
DefaultGetConfig *GetConfig
DefaultConcurrency *DefaultConcurrencyConfig
DefaultRetryConfig *RetryConfig
DefaultTransform *transform.ColumnTransforms
DefaultGetConfig *GetConfig
DefaultConcurrency *DefaultConcurrencyConfig
DefaultRetryConfig *RetryConfig
DefaultShouldIgnoreError ErrorPredicate
// every table must implement these columns
RequiredColumns []*Column
ConnectionConfigSchema *ConnectionConfigSchema
Expand Down
7 changes: 4 additions & 3 deletions plugin/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ var testCasesValidate = map[string]validateTest{
},
RequiredColumns: []*Column{{Name: "name", Type: proto.ColumnType_STRING}},
},
expected: "table 'table' GetConfig does not specify a key",
expected: "table 'table' GetConfig does not specify a KeyColumn",
},
"no get hydrate": {
plugin: Plugin{
Expand Down Expand Up @@ -323,16 +323,17 @@ var testCasesValidate = map[string]validateTest{
},
RequiredColumns: []*Column{{Name: "name", Type: proto.ColumnType_STRING}},
},
expected: "table 'table' GetConfig does not specify a key",
expected: "table 'table' GetConfig does not specify a KeyColumn",
},
}

func TestValidate(t *testing.T) {
for name, test := range testCasesValidate {
test.plugin.Initialise()
validationErrors := test.plugin.Validate()

if test.expected != validationErrors {
t.Errorf("Test: '%s'' FAILED. \nExpected: '%s' \nGot: '%s'", name, test.expected, validationErrors)
t.Errorf("Test: '%s'' FAILED. \nExpected: '%s' \nGot: '%s' ", name, test.expected, validationErrors)
}
}
}
3 changes: 2 additions & 1 deletion plugin/required_hydrate_calls.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ func (c requiredHydrateCallBuilder) Add(hydrateFunc HydrateFunc) {

// if the resolved hydrate call is NOT the same as the fetch call, add to the map of hydrate functions to call
if hydrateName != c.fetchCallName {
if _, ok := c.requiredHydrateCalls[hydrateName]; !ok {
if _, ok := c.requiredHydrateCalls[hydrateName]; ok {
return
}

// get the config for this hydrate function
Expand Down
15 changes: 15 additions & 0 deletions plugin/retry_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package plugin

import (
"fmt"

"github.com/turbot/go-kit/helpers"
)

type RetryConfig struct {
ShouldRetryError ErrorPredicate
}

func (c RetryConfig) String() interface{} {
return fmt.Sprintf("ShouldRetryError: %s", helpers.GetFunctionName(c.ShouldRetryError))
}
38 changes: 31 additions & 7 deletions plugin/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ type Table struct {
// table description
Description string
// column definitions
Columns []*Column
List *ListConfig
Get *GetConfig
GetMatrixItem MatrixItemFunc
DefaultTransform *transform.ColumnTransforms
Columns []*Column
List *ListConfig
Get *GetConfig
GetMatrixItem MatrixItemFunc
DefaultTransform *transform.ColumnTransforms
DefaultShouldIgnoreError ErrorPredicate
DefaultRetryConfig *RetryConfig

// the parent plugin object
Plugin *Plugin
// definitions of dependencies between hydrate functions
// Deprecated: used HydrateConfig
HydrateDependencies []HydrateDependencies
HydrateConfig []HydrateConfig
// map of hydrate function name to columns it provides
Expand Down Expand Up @@ -97,10 +101,16 @@ func (t *Table) getFetchFunc(fetchType fetchType) HydrateFunc {
return t.List.Hydrate
}
return t.Get.Hydrate

}

// search through HydrateConfig and HydrateDependencies finding a function with the given name
// if found return its dependencies
func (t *Table) getHydrateDependencies(hydrateFuncName string) []HydrateFunc {
for _, d := range t.HydrateConfig {
if helpers.GetFunctionName(d.Func) == hydrateFuncName {
return d.Depends
}
}
for _, d := range t.HydrateDependencies {
if helpers.GetFunctionName(d.Func) == hydrateFuncName {
return d.Depends
Expand All @@ -115,11 +125,25 @@ func (t *Table) getHydrateConfig(hydrateFuncName string) *HydrateConfig {
for _, d := range t.HydrateConfig {
if helpers.GetFunctionName(d.Func) == hydrateFuncName {
config = &d
break
}
}
// now use default values if needed
if config.RetryConfig == nil {
config.RetryConfig = t.Plugin.DefaultRetryConfig
if t.DefaultRetryConfig != nil {
config.RetryConfig = t.DefaultRetryConfig
} else {
config.RetryConfig = t.Plugin.DefaultRetryConfig
}
}
if config.ShouldIgnoreError == nil {
if t.DefaultShouldIgnoreError != nil {
config.ShouldIgnoreError = t.DefaultShouldIgnoreError
} else {
config.ShouldIgnoreError = t.Plugin.DefaultShouldIgnoreError
}
}

// if no hydrate dependencies are specified in the hydrate config, check the deprecated "HydrateDependencies" property
if config.Depends == nil {
config.Depends = t.getHydrateDependencies(hydrateFuncName)
Expand Down
Loading

0 comments on commit cf18abf

Please sign in to comment.