Skip to content

Commit bc492e9

Browse files
atoulmepjanotti
andauthored
[checkapi] use a YAML schema (#1148)
* [checkapi] use a YAML schema * code review --------- Co-authored-by: Paulo Janotti <[email protected]>
1 parent 590e7da commit bc492e9

File tree

8 files changed

+88
-95
lines changed

8 files changed

+88
-95
lines changed

.chloggen/yaml_output.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: enhancement
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. crosslink)
5+
component: checkapi
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: Work with a JSON schema stored as yaml under metadata.yaml config key.
9+
10+
# One or more tracking issues related to the change
11+
issues: [1148]
12+
13+
# (Optional) One or more lines of additional information to render under the primary note.
14+
# These lines will be padded with 2 spaces and then inserted directly into the document.
15+
# Use pipe (|) for multiline entries.
16+
subtext:

checkapi/internal/config/receiver/badconfigreceiver/config.schema.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

checkapi/internal/config/receiver/configcallreceiver/config.schema.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

checkapi/internal/config/receiver/configreceiver/config.schema.json

Lines changed: 0 additions & 47 deletions
This file was deleted.
Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,34 @@
11
type: config
22

33
status:
4-
class: receiver
4+
class: receiver
5+
6+
config:
7+
properties:
8+
bar:
9+
type: string
10+
bool:
11+
type: boolean
12+
data_defined_elsewhere:
13+
$ref: http://example.com/schemas/external_schema.json#/properties/data
14+
foo:
15+
type: string
16+
my_special_embedded_field:
17+
type: string
18+
ptrStruct:
19+
type: object
20+
subconfig:
21+
allOf:
22+
- $ref: http://example.com/schemas/external_schema.json#/properties/data
23+
properties:
24+
bar:
25+
type: boolean
26+
foo:
27+
type: string
28+
sub_config2:
29+
properties:
30+
foobar:
31+
type: string
32+
type: object
33+
type: object
34+
type: object

checkapi/internal/jsonschema.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,12 @@ package internal
66
import (
77
"errors"
88
"fmt"
9-
"os"
10-
"path"
119
"slices"
1210
"strings"
1311

1412
"github.com/kaptinlin/jsonschema"
1513
)
1614

17-
// ReadJSONSchema returns a JSON schema from the config.schema.json file under the folder
18-
func ReadJSONSchema(folder string) (*jsonschema.Schema, error) {
19-
schemaFile := path.Join(folder, "config.schema.json")
20-
b, err := os.ReadFile(schemaFile) //nolint: gosec
21-
if err != nil {
22-
return nil, err
23-
}
24-
compiler := jsonschema.NewCompiler()
25-
return compiler.Compile(b)
26-
}
27-
2815
// DeriveSchema interprets the config struct to return a valid JSON schema
2916
func DeriveSchema(cfgStruct APIstruct, structs []APIstruct, typeMappings map[string]string) (*jsonschema.Schema, error) {
3017
return createObject(parseObject(cfgStruct, structs, typeMappings)), nil

checkapi/internal/metadata.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,29 @@ import (
1111
"gopkg.in/yaml.v3"
1212
)
1313

14-
type status struct {
14+
// Status of the component
15+
type Status struct {
1516
Class string `yaml:"class"`
1617
}
1718

18-
type metadata struct {
19-
Status status `yaml:"status"`
19+
// Metadata of the component
20+
type Metadata struct {
21+
Status Status `yaml:"status"`
22+
Config any `yaml:"config"`
2023
}
2124

22-
// ReadComponentType reads the component type from the metadata.yaml file in the given folder.
23-
func ReadComponentType(folder string) (string, error) {
24-
var componentType string
25+
// ReadMetadata reads from the metadata.yaml file in the given folder.
26+
func ReadMetadata(folder string) (Metadata, error) {
2527
if _, err := os.Stat(filepath.Join(folder, "metadata.yaml")); errors.Is(err, os.ErrNotExist) {
26-
componentType = "pkg"
27-
} else {
28-
m, err := os.ReadFile(filepath.Join(folder, "metadata.yaml")) // #nosec G304
29-
if err != nil {
30-
return "", err
31-
}
32-
var componentInfo metadata
33-
if err = yaml.Unmarshal(m, &componentInfo); err != nil {
34-
return "", err
35-
}
36-
componentType = componentInfo.Status.Class
28+
return Metadata{Status: Status{Class: "pkg"}}, nil
3729
}
38-
return componentType, nil
30+
m, err := os.ReadFile(filepath.Join(folder, "metadata.yaml")) // #nosec G304
31+
if err != nil {
32+
return Metadata{}, err
33+
}
34+
var componentInfo Metadata
35+
if err = yaml.Unmarshal(m, &componentInfo); err != nil {
36+
return Metadata{}, err
37+
}
38+
return componentInfo, nil
3939
}

checkapi/main.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"strings"
1919
"unicode"
2020

21+
"github.com/goccy/go-json"
2122
"github.com/kaptinlin/jsonschema"
2223

2324
"go.opentelemetry.io/build-tools/checkapi/internal"
@@ -63,11 +64,11 @@ func run(folder string, configPath string) error {
6364
return nil
6465
}
6566
}
66-
componentType, err3 := internal.ReadComponentType(base)
67+
metadata, err3 := internal.ReadMetadata(base)
6768
if err3 != nil {
6869
return err3
6970
}
70-
if err = walkFolder(cfg, base, componentType); err != nil {
71+
if err = walkFolder(cfg, base, metadata); err != nil {
7172
errs = append(errs, err)
7273
}
7374
}
@@ -82,7 +83,7 @@ func run(folder string, configPath string) error {
8283
return nil
8384
}
8485

85-
func walkFolder(cfg internal.Config, folder string, componentType string) error {
86+
func walkFolder(cfg internal.Config, folder string, metadata internal.Metadata) error {
8687
result, err := internal.Read(folder, cfg.IgnoredFunctions, cfg.ExcludedFiles)
8788
if err != nil {
8889
return err
@@ -111,7 +112,7 @@ func walkFolder(cfg internal.Config, folder string, componentType string) error
111112
functionsPresent := map[string]struct{}{}
112113
OUTER:
113114
for _, fnDesc := range cfg.AllowedFunctions {
114-
if !slices.Contains(fnDesc.Classes, componentType) {
115+
if !slices.Contains(fnDesc.Classes, metadata.Status.Class) {
115116
continue
116117
}
117118
for _, fn := range result.Functions {
@@ -131,12 +132,13 @@ func walkFolder(cfg internal.Config, folder string, componentType string) error
131132

132133
if cfg.UnkeyedLiteral.Enabled {
133134
for _, s := range result.Structs {
134-
if err := checkStructDisallowUnkeyedLiteral(cfg, s, folder); err != nil {
135+
if err = checkStructDisallowUnkeyedLiteral(cfg, s, folder); err != nil {
135136
errs = append(errs, err)
136137
}
137138
}
138139
}
139140

141+
componentType := metadata.Status.Class
140142
if (!cfg.JSONSchema.CheckPresent && !cfg.JSONSchema.CheckValid && !cfg.ComponentAPI && !cfg.ComponentAPIStrict) || (componentType != "connector" && componentType != "exporter" && componentType != "extension" && componentType != "processor" && componentType != "receiver") {
141143
return errors.Join(errs...)
142144
}
@@ -165,24 +167,31 @@ func walkFolder(cfg internal.Config, folder string, componentType string) error
165167
return errors.Join(errs...)
166168
}
167169

168-
if _, err := os.Stat(filepath.Join(folder, "config.schema.json")); errors.Is(err, os.ErrNotExist) {
170+
if metadata.Config == nil {
169171
if cfg.JSONSchema.CheckPresent {
170172
errs = append(errs, err)
171173
}
172174
} else {
173-
jsonSchema, err := internal.ReadJSONSchema(folder)
175+
configSchemaBytes, err := json.Marshal(metadata.Config)
174176
if err != nil {
175177
errs = append(errs, err)
176178
} else {
177-
var after *jsonschema.Schema
178-
if after, err = internal.DeriveSchema(*cfgStruct, result.Structs, cfg.JSONSchema.TypeMappings); err != nil {
179+
configSchema, err := jsonschema.NewCompiler().Compile(configSchemaBytes)
180+
if err != nil {
179181
errs = append(errs, err)
180-
} else if err := internal.CompareJSONSchema(folder, jsonSchema, after); err != nil {
181-
errs = append(errs, err)
182-
b, _ := after.MarshalJSON()
183-
errs = append(errs, fmt.Errorf("[%s] new JSON schema: %s", folder, string(b)))
182+
} else {
183+
var structDerivedSchema *jsonschema.Schema
184+
if structDerivedSchema, err = internal.DeriveSchema(*cfgStruct, result.Structs, cfg.JSONSchema.TypeMappings); err != nil {
185+
errs = append(errs, err)
186+
} else if err := internal.CompareJSONSchema(folder, configSchema, structDerivedSchema); err != nil {
187+
errs = append(errs, err)
188+
configSchemaBytes, _ := structDerivedSchema.MarshalJSON()
189+
rawJSON := map[string]any{}
190+
_ = json.Unmarshal(configSchemaBytes, &rawJSON)
191+
configSchemaYAML, _ := yaml.Marshal(rawJSON)
192+
errs = append(errs, fmt.Errorf("[%s] new JSON schema: %s", folder, string(configSchemaYAML)))
193+
}
184194
}
185-
186195
}
187196
}
188197

0 commit comments

Comments
 (0)