Skip to content

Commit

Permalink
Remove need for connection config schema - support hcl tags on connec…
Browse files Browse the repository at this point in the history
…tion config struct. Closes #482
  • Loading branch information
kaidaguerre authored Jan 25, 2023
1 parent b7b9614 commit 95612a4
Show file tree
Hide file tree
Showing 6 changed files with 473 additions and 73 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ require (
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/golang/glog v1.0.0 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/googleapis/gax-go/v2 v2.0.5 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
Expand Down Expand Up @@ -374,6 +375,7 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec=
github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
Expand Down
55 changes: 42 additions & 13 deletions plugin/connection_config.go → plugin/connection_config_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ package plugin

import (
"fmt"
"log"

"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/hcl/v2/hclparse"
"github.com/turbot/go-kit/helpers"
"github.com/turbot/steampipe-plugin-sdk/v5/plugin/schema"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
"github.com/zclconf/go-cty/cty/gocty"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"log"
)

/*
Expand All @@ -36,7 +39,7 @@ Usage:
},
}
func ConfigInstance() interface{} {
func ConfigInstance() any {
return &hackernewsConfig{}
}
Expand All @@ -56,7 +59,7 @@ ConnectionConfigInstanceFunc is a function type which returns 'any'.
It is used to implement [plugin.ConnectionConfigSchema.NewInstance].
*/
type ConnectionConfigInstanceFunc func() interface{}
type ConnectionConfigInstanceFunc func() any

/*
Connection is a struct which is used to store connection config.
Expand All @@ -74,27 +77,28 @@ type Connection struct {
Name string
// the connection config
// NOTE: we always pass and store connection config BY VALUE
Config interface{}
Config any
}

// parse function parses the hcl config string into a connection config struct.
//
// The schema and the struct to parse into are provided by the plugin
func (c *ConnectionConfigSchema) parse(configString string) (config interface{}, err error) {
func (c *ConnectionConfigSchema) parse(configString string) (config any, err error) {
defer func() {
if r := recover(); r != nil {
log.Printf("[WARN] ConnectionConfigSchema parse caught a panic: %v\n", r)
err = status.Error(codes.Internal, fmt.Sprintf("ConnectionConfigSchema parse failed with panic %v", r))
}
}()

// ensure a schema is set
if len(c.Schema) == 0 {
return nil, fmt.Errorf("cannot parse connection config as no config schema is set in the connection config")
}
if c.NewInstance == nil {
return nil, fmt.Errorf("cannot parse connection config as no NewInstance function is specified in the connection config")
if c.Schema == nil {
return c.parseConfigWithHclTags(configString)
}
return c.parseConfigWithCtyTags(configString)
}

// parse for legacy format config struct using cty tags
func (c *ConnectionConfigSchema) parseConfigWithCtyTags(configString string) (any, error) {
configStruct := c.NewInstance()
spec := schema.SchemaToObjectSpec(c.Schema)
parser := hclparse.NewParser()
Expand All @@ -110,9 +114,34 @@ func (c *ConnectionConfigSchema) parse(configString string) (config interface{},

// decode into the provided struct
if err := gocty.FromCtyValue(value, configStruct); err != nil {
return nil, fmt.Errorf("Failed to marshal parsed config into config struct: %v", err)
return nil, fmt.Errorf("failed to marshal parsed config into config struct: %v", err)
}
// return the struct by value
return helpers.DereferencePointer(configStruct), nil
}

func (c *ConnectionConfigSchema) parseConfigWithHclTags(configString string) (_ any, err error) {
configStruct := c.NewInstance()
parser := hclparse.NewParser()
file, diags := parser.ParseHCL([]byte(configString), "")
if diags.HasErrors() {
return nil, DiagsToError("failed to parse connection config", diags)
}
_, body, diags := file.Body.PartialContent(&hcl.BodySchema{})
if diags.HasErrors() {
return nil, DiagsToError("failed to parse connection config", diags)
}

evalCtx := &hcl.EvalContext{
Variables: make(map[string]cty.Value),
Functions: make(map[string]function.Function),
}

moreDiags := gohcl.DecodeBody(body, evalCtx, configStruct)
diags = append(diags, moreDiags...)
if diags.HasErrors() {
return nil, DiagsToError("failed to parse connection config", diags)
}
// return the struct by value
return helpers.DereferencePointer(configStruct), nil
}
Loading

0 comments on commit 95612a4

Please sign in to comment.