Skip to content

Commit

Permalink
🐛 handle correct structs for protobof init calls (#541)
Browse files Browse the repository at this point in the history
Adding validation of the keys in provider-specific config to only be
strings

Adding test cases to validate both JSON and yaml provider settings files
will work.

fixes #501

Signed-off-by: Shawn Hurley <[email protected]>
  • Loading branch information
shawn-hurley authored Mar 20, 2024
1 parent 650120f commit 2e45db3
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 0 deletions.
82 changes: 82 additions & 0 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ func GetConfig(filepath string) ([]Config, error) {
if ic.Proxy == nil {
ic.Proxy = c.Proxy
}
newConfig, err := validateAndUpdateProviderSpecificConfig(ic.ProviderSpecificConfig)
if err != nil {
return configs, err
}
ic.ProviderSpecificConfig = newConfig

}
}
if !foundBuiltin {
Expand All @@ -185,6 +191,82 @@ func GetConfig(filepath string) ([]Config, error) {

}

func validateAndUpdateProviderSpecificConfig(oldPSC map[string]interface{}) (map[string]interface{}, error) {
newPSC := map[string]interface{}{}
for k, v := range oldPSC {
if old, ok := v.(map[interface{}]interface{}); ok {
new, err := validateUpdateInternalProviderConfig(old)
if err != nil {
return nil, err
}
newPSC[k] = new
continue
}
if oldList, ok := v.([]interface{}); ok {
newList, err := validateUpdateListProviderConfig(oldList)
if err != nil {
return nil, err
}
newPSC[k] = newList
continue
}
newPSC[k] = v
}
return newPSC, nil
}

func validateUpdateListProviderConfig(old []interface{}) ([]interface{}, error) {
new := []interface{}{}
for _, v := range old {
if oldV, ok := v.(map[interface{}]interface{}); ok {
newMap, err := validateUpdateInternalProviderConfig(oldV)
if err != nil {
return nil, err
}
new = append(new, newMap)
continue
}
if oldList, ok := v.([]interface{}); ok {
newList, err := validateUpdateListProviderConfig(oldList)
if err != nil {
return nil, err
}
new = append(new, newList)
continue
}
new = append(new, v)
}
return new, nil
}

func validateUpdateInternalProviderConfig(old map[interface{}]interface{}) (map[string]interface{}, error) {
new := map[string]interface{}{}
for k, v := range old {
s, ok := k.(string)
if !ok {
return nil, fmt.Errorf("provider specific config must only have keys that strings")
}
if o, ok := v.(map[interface{}]interface{}); ok {
new, err := validateUpdateInternalProviderConfig(o)
if err != nil {
return nil, err
}
new[s] = new
continue
}
if oldList, ok := v.([]interface{}); ok {
newList, err := validateUpdateListProviderConfig(oldList)
if err != nil {
return nil, err
}
new[s] = newList
continue
}
new[s] = v
}
return new, nil
}

func validateProviderName(configs []Config) error {
providerNames := make(map[string]bool)
for _, config := range configs {
Expand Down
75 changes: 75 additions & 0 deletions provider/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package provider

import (
"context"
"fmt"
"reflect"
"testing"

Expand Down Expand Up @@ -337,3 +338,77 @@ func Test_deduplication(t *testing.T) {
}

}

func Test_GetConfigs(t *testing.T) {
tests := []struct {
title string
testdataFile string
expectedProviderSpecificConfig map[string]interface{}
shouldErr bool
}{
{
title: "testnested",
testdataFile: "testdata/provider_settings_nested_types.json",
expectedProviderSpecificConfig: map[string]interface{}{
"lspServerName": "generic",
"lspServerPath": "/root/go/bin/gopls",
"lspServerArgs": []interface{}{"string"},
"lspServerInitializationOptions": "",
"workspaceFolders": []interface{}{"file:///analyzer-lsp/examples/golang"},
"dependencyFolders": []interface{}{},
"groupVersionKinds": []interface{}{
map[string]interface{}{"group": "apps", "version": "v1", "kind": "Deployment"},
},
"object": map[string]interface{}{"nestedObject": "object"},
"dependencyProviderPath": "/usr/bin/golang-dependency-provider",
},
},
{
title: "test nested yaml",
testdataFile: "testdata/provider_settings_simple.yaml",
expectedProviderSpecificConfig: map[string]interface{}{
"lspServerName": "generic",
"lspServerPath": "/root/go/bin/gopls",
"lspServerArgs": []interface{}{"string"},
"lspServerInitializationOptions": "",
"workspaceFolders": []interface{}{"file:///analyzer-lsp/examples/golang"},
"dependencyFolders": []interface{}{},
"groupVersionKinds": []interface{}{
map[string]interface{}{"group": "apps", "version": "v1", "kind": "Deployment"},
},
"object": map[string]interface{}{"nestedObject": "object"},
"dependencyProviderPath": "/usr/bin/golang-dependency-provider",
},
},
{
title: "test yaml int keys",
testdataFile: "testdata/provider_settings_invalid.yaml",
shouldErr: true,
},
}
for _, tc := range tests {
t.Run(tc.title, func(t *testing.T) {
config, err := GetConfig(tc.testdataFile)
if err != nil && !tc.shouldErr {
t.Fatalf("got error: %v", err)
}
if err != nil && tc.shouldErr {
return
}
// This is true because of the builtin config that will be added if not there
if len(config) != 2 {
t.Fatalf("got config longer than one: %v", len(config))
}
c := config[0]
if len(c.InitConfig) != 1 {
t.Fatalf("got init config longer than one: %v", len(c.InitConfig))
}
pc := c.InitConfig[0]
if !reflect.DeepEqual(pc.ProviderSpecificConfig, tc.expectedProviderSpecificConfig) {
fmt.Printf("\n%#v", pc.ProviderSpecificConfig)
fmt.Printf("\n%#v\n", tc.expectedProviderSpecificConfig)
t.Fatalf("Got config is different than expected config")
}
})
}
}
21 changes: 21 additions & 0 deletions provider/testdata/provider_settings_invalid.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
- name: "go"
binaryPath: "/usr/bin/generic-external-provider"
initConfig:
- analysisMode: "full"
providerSpecificConfig:
lspServerName: "generic"
lspServerPath: "/root/go/bin/gopls"
lspServerArgs:
- "string"
lspServerInitializationOptions: ""
workspaceFolders:
- "file:///analyzer-lsp/examples/golang"
dependencyFolders: []
groupVersionKinds:
- group: "apps"
version: "v1"
kind: "Deployment"
1: "newThing"
object:
nestedObject: "object"
dependencyProviderPath: "/usr/bin/golang-dependency-provider"
23 changes: 23 additions & 0 deletions provider/testdata/provider_settings_nested_types.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

[
{
"name": "go",
"binaryPath": "/usr/bin/generic-external-provider",
"initConfig": [{
"analysisMode": "full",
"providerSpecificConfig": {
"lspServerName": "generic",
"lspServerPath": "/root/go/bin/gopls",
"lspServerArgs": ["string"],
"lspServerInitializationOptions": "",

"workspaceFolders": ["file:///analyzer-lsp/examples/golang"],
"dependencyFolders": [],
"groupVersionKinds": [{"group": "apps", "version": "v1", "kind": "Deployment"}],
"object": {"nestedObject": "object"},

"dependencyProviderPath": "/usr/bin/golang-dependency-provider"
}
}]
}
]
20 changes: 20 additions & 0 deletions provider/testdata/provider_settings_simple.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
- name: "go"
binaryPath: "/usr/bin/generic-external-provider"
initConfig:
- analysisMode: "full"
providerSpecificConfig:
lspServerName: "generic"
lspServerPath: "/root/go/bin/gopls"
lspServerArgs:
- "string"
lspServerInitializationOptions: ""
workspaceFolders:
- "file:///analyzer-lsp/examples/golang"
dependencyFolders: []
groupVersionKinds:
- group: "apps"
version: "v1"
kind: "Deployment"
object:
nestedObject: "object"
dependencyProviderPath: "/usr/bin/golang-dependency-provider"

0 comments on commit 2e45db3

Please sign in to comment.