Skip to content

Commit 455aabb

Browse files
committed
feat: Add transformer to update table description with its table options
1 parent fa285f0 commit 455aabb

File tree

7 files changed

+172
-4
lines changed

7 files changed

+172
-4
lines changed

docs/table_options.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package docs
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"reflect"
7+
"regexp"
8+
"strings"
9+
10+
schemaDocs "github.com/cloudquery/codegen/jsonschema/docs"
11+
"github.com/cloudquery/plugin-sdk/v4/schema"
12+
invoschema "github.com/invopop/jsonschema"
13+
)
14+
15+
func TableOptionsDescriptionTransformer(tableOptions any, jsonSchema string) (schema.Transform, error) {
16+
var sc invoschema.Schema
17+
if err := json.Unmarshal([]byte(jsonSchema), &sc); err != nil {
18+
return nil, err
19+
}
20+
tableNamesToOptionsDocs := make(map[string]string)
21+
tableOptionsType := reflect.ValueOf(tableOptions).Elem().Type()
22+
for i := range tableOptionsType.NumField() {
23+
field := tableOptionsType.Field(i)
24+
fieldType := field.Type.String()
25+
if strings.Contains(fieldType, ".") {
26+
fieldType = strings.Split(fieldType, ".")[1]
27+
}
28+
defValue, ok := sc.Definitions[fieldType]
29+
if !ok {
30+
return nil, errors.New("definition not found for " + field.Name)
31+
}
32+
tableName := strings.Split(field.Tag.Get("json"), ",")[0]
33+
if tableName == "" {
34+
return nil, errors.New("json tag not found for table " + field.Name)
35+
}
36+
newRoot := sc
37+
newRoot.ID = "Table Options"
38+
newRoot.Ref = "#/$defs/" + "Table Options"
39+
newRoot.Definitions["Table Options"] = defValue
40+
sch, _ := json.Marshal(newRoot)
41+
doc, _ := schemaDocs.Generate(sch, 1)
42+
tocRegex := regexp.MustCompile(`# Table of contents[\s\S]+?##`)
43+
tableNamesToOptionsDocs[tableName] = tocRegex.ReplaceAllString(doc, "##")
44+
}
45+
46+
return func(table *schema.Table) error {
47+
if tableNamesToOptionsDocs[table.Name] != "" {
48+
table.Description = table.Description + "\n\n" + tableNamesToOptionsDocs[table.Name]
49+
}
50+
return nil
51+
}, nil
52+
}

docs/table_options_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package docs
2+
3+
import (
4+
_ "embed"
5+
"github.com/cloudquery/plugin-sdk/v4/docs/testdata"
6+
"github.com/cloudquery/plugin-sdk/v4/schema"
7+
"github.com/stretchr/testify/require"
8+
"testing"
9+
)
10+
11+
//go:embed testdata/schema.json
12+
var testSchema string
13+
14+
type testTableOptions struct {
15+
Dummy testdata.DummyTableOptions `json:"dummy,omitempty"`
16+
}
17+
18+
var testTable = &schema.Table{
19+
Name: "dummy",
20+
Description: "This is a dummy table",
21+
}
22+
23+
func TestTableOptionsDescriptionTransformer(t *testing.T) {
24+
type args struct {
25+
tableOptions any
26+
jsonSchema string
27+
table *schema.Table
28+
}
29+
tests := []struct {
30+
name string
31+
args args
32+
wantDesc string
33+
wantErr bool
34+
}{
35+
{
36+
name: "adds table options to description",
37+
args: args{tableOptions: &testTableOptions{}, jsonSchema: testSchema, table: testTable},
38+
wantDesc: "This is a dummy table\n\n## <a name=\"Table Options\"></a>Table Options\n\n DummyTableOptions contains configuration for the dummy table\n\n* `filter` (`string`)\n",
39+
},
40+
{
41+
name: "leaves description unchanged when table doesn't have options",
42+
args: args{tableOptions: &testTableOptions{}, jsonSchema: testSchema, table: &schema.Table{Description: "Foobar"}},
43+
wantDesc: "Foobar",
44+
},
45+
{
46+
name: "errors out when table options don't match schema",
47+
wantErr: true,
48+
args: args{tableOptions: &testTableOptions{}, jsonSchema: "", table: testTable},
49+
},
50+
}
51+
for _, tt := range tests {
52+
t.Run(tt.name, func(t *testing.T) {
53+
transformer, err := TableOptionsDescriptionTransformer(tt.args.tableOptions, tt.args.jsonSchema)
54+
if tt.wantErr {
55+
require.Error(t, err)
56+
return
57+
}
58+
require.NoError(t, transformer(tt.args.table))
59+
require.Equal(t, tt.wantDesc, tt.args.table.Description)
60+
})
61+
}
62+
}

docs/testdata/schema.json

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "test/spec",
4+
"$ref": "#/$defs/Spec",
5+
"$defs": {
6+
"Spec": {
7+
"properties": {
8+
"table_options": {
9+
"$ref": "#/$defs/TableOptions",
10+
"description": "TableOptions is a set of options to override the defaults for certain tables."
11+
}
12+
},
13+
"additionalProperties": false,
14+
"type": "object"
15+
},
16+
"TableOptions": {
17+
"properties": {
18+
"dummy": {
19+
"oneOf": [
20+
{
21+
"$ref": "#/$defs/DummyTableOptions",
22+
"description": "Options for the dummy table."
23+
},
24+
{
25+
"type": "null"
26+
}
27+
]
28+
}
29+
},
30+
"additionalProperties": false,
31+
"type": "object"
32+
},
33+
"DummyTableOptions": {
34+
"properties": {
35+
"filter": {
36+
"type": "string"
37+
}
38+
},
39+
"additionalProperties": false,
40+
"type": "object",
41+
"description": "DummyTableOptions contains configuration for the dummy table"
42+
}
43+
}
44+
}

docs/testdata/tableoptions.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package testdata
2+
3+
type DummyTableOptions struct {
4+
Filter string `json:"filter,omitempty"`
5+
}

examples/simple_plugin/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/cloudquery/plugin-sdk/examples/simple_plugin
22

3-
go 1.23.0
3+
go 1.23.4
44

55
toolchain go1.24.1
66

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/cloudquery/plugin-sdk/v4
22

3-
go 1.23.0
3+
go 1.23.4
44

55
toolchain go1.24.1
66

@@ -65,6 +65,7 @@ require (
6565
github.com/bahlo/generic-list-go v0.2.0 // indirect
6666
github.com/buger/jsonparser v1.1.1 // indirect
6767
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
68+
github.com/cloudquery/codegen v0.3.26 // indirect
6869
github.com/davecgh/go-spew v1.1.1 // indirect
6970
github.com/ghodss/yaml v1.0.0 // indirect
7071
github.com/go-logr/logr v1.4.2 // indirect
@@ -97,3 +98,5 @@ require (
9798
gopkg.in/yaml.v2 v2.4.0 // indirect
9899
gopkg.in/yaml.v3 v3.0.1 // indirect
99100
)
101+
102+
replace github.com/invopop/jsonschema => github.com/cloudquery/jsonschema v0.0.0-20240220124159-92878faa2a66

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK3
5252
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
5353
github.com/cloudquery/cloudquery-api-go v1.13.8 h1:8n5D0G2wynbUdexr1GS8ND8i0uOwm0gXKNipJsijPe0=
5454
github.com/cloudquery/cloudquery-api-go v1.13.8/go.mod h1:ZhEjPkDGDL2KZKlQLUnsgQ0mPz3qC7qftr37q3q+IcA=
55+
github.com/cloudquery/codegen v0.3.26 h1:cWORVpObYW5/0LnjC0KO/Ocg1+vbZivJfFd+sMpb5ZY=
56+
github.com/cloudquery/codegen v0.3.26/go.mod h1:bg/M1JxFvNVABMLMFb/uAQmTGAyI2L/E4zL4kho9RFs=
57+
github.com/cloudquery/jsonschema v0.0.0-20240220124159-92878faa2a66 h1:OZLPSIBYEfvkAUeOeM8CwTgVQy5zhayI99ishCrsFV0=
58+
github.com/cloudquery/jsonschema v0.0.0-20240220124159-92878faa2a66/go.mod h1:0SoZ/U7yJlNOR+fWsBSeTvTbGXB6DK01tzJ7m2Xfg34=
5559
github.com/cloudquery/plugin-pb-go v1.26.9 h1:lkgxqIzabD6yvDm7D7oJvgO/T/bYIh7SSOojEgbMpnA=
5660
github.com/cloudquery/plugin-pb-go v1.26.9/go.mod h1:euhtVJKRtmWzukBxOjJyCKHPU9O9Gs5vasiBCaZVFRA=
5761
github.com/cloudquery/plugin-sdk/v2 v2.7.0 h1:hRXsdEiaOxJtsn/wZMFQC9/jPfU1MeMK3KF+gPGqm7U=
@@ -99,8 +103,6 @@ github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISH
99103
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
100104
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
101105
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
102-
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
103-
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
104106
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
105107
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
106108
github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4=

0 commit comments

Comments
 (0)