Skip to content

Commit

Permalink
Merge pull request #70 from redpanda-data/walk-config-fields
Browse files Browse the repository at this point in the history
Add ConfigWalker to schema APIs
  • Loading branch information
Jeffail authored Aug 6, 2024
2 parents 97fca4a + 3e9a03b commit 3742ba4
Show file tree
Hide file tree
Showing 9 changed files with 1,018 additions and 272 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ Changelog

All notable changes to this project will be documented in this file.

## 4.34.0 - TBD
## 4.34.0 - 2024-08-06

### Added

- The `list` subcommand now supports the format `jsonschema`. (@Jeffail)
- Go API: New `WithX` methods added to the environment type. (@Jeffail)
- Go API: New `ConfigWalker` API added to the schema type. (@Jeffail)

## 4.33.0 - 2024-07-19

Expand Down
85 changes: 0 additions & 85 deletions internal/docs/field_interop.go

This file was deleted.

149 changes: 0 additions & 149 deletions internal/docs/format_yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -961,155 +961,6 @@ func (f FieldSpecs) YAMLToMap(node *yaml.Node, conf ToValueConfig) (map[string]a
return resultMap, nil
}

//------------------------------------------------------------------------------

func walkComponentsYAML(cType Type, node *yaml.Node, prov Provider, fn ComponentWalkYAMLFunc) error {
node = unwrapDocumentNode(node)

name, spec, err := GetInferenceCandidateFromYAML(prov, cType, node)
if err != nil {
return err
}

var label string
for i := 0; i < len(node.Content)-1; i += 2 {
if node.Content[i].Value == "label" {
label = node.Content[i+1].Value
break
}
}

if err := fn(WalkedYAMLComponent{
ComponentType: cType,
Name: name,
Label: label,
Conf: node,
}); err != nil {
return err
}

reservedFields := ReservedFieldsByType(cType)
for i := 0; i < len(node.Content)-1; i += 2 {
if node.Content[i].Value == name {
if err := spec.Config.WalkYAML(node.Content[i+1], prov, fn); err != nil {
return err
}
continue
}
if node.Content[i].Value == "type" || node.Content[i].Value == "label" {
continue
}
if spec, exists := reservedFields[node.Content[i].Value]; exists {
if err := spec.WalkYAML(node.Content[i+1], prov, fn); err != nil {
return err
}
}
}
return nil
}

// WalkYAML walks each node of a YAML tree and for any component types within
// the config a provided func is called.
func (f FieldSpec) WalkYAML(node *yaml.Node, prov Provider, fn ComponentWalkYAMLFunc) error {
node = unwrapDocumentNode(node)

if coreType, isCore := f.Type.IsCoreComponent(); isCore {
switch f.Kind {
case Kind2DArray:
for i := 0; i < len(node.Content); i++ {
for j := 0; j < len(node.Content[i].Content); j++ {
if err := walkComponentsYAML(coreType, node.Content[i].Content[j], prov, fn); err != nil {
return err
}
}
}
case KindArray:
for i := 0; i < len(node.Content); i++ {
if err := walkComponentsYAML(coreType, node.Content[i], prov, fn); err != nil {
return err
}
}
case KindMap:
for i := 0; i < len(node.Content)-1; i += 2 {
if err := walkComponentsYAML(coreType, node.Content[i+1], prov, fn); err != nil {
return err
}
}
default:
if err := walkComponentsYAML(coreType, node, prov, fn); err != nil {
return err
}
}
} else if len(f.Children) > 0 {
switch f.Kind {
case Kind2DArray:
for i := 0; i < len(node.Content); i++ {
for j := 0; j < len(node.Content[i].Content); j++ {
if err := f.Children.WalkYAML(node.Content[i].Content[j], prov, fn); err != nil {
return err
}
}
}
case KindArray:
for i := 0; i < len(node.Content); i++ {
if err := f.Children.WalkYAML(node.Content[i], prov, fn); err != nil {
return err
}
}
case KindMap:
for i := 0; i < len(node.Content)-1; i += 2 {
if err := f.Children.WalkYAML(node.Content[i+1], prov, fn); err != nil {
return err
}
}
default:
if err := f.Children.WalkYAML(node, prov, fn); err != nil {
return err
}
}
}
return nil
}

// ComponentWalkYAMLFunc is called for each component type within a YAML config,
// where the node representing that component is provided along with the type
// and implementation name.
type ComponentWalkYAMLFunc func(c WalkedYAMLComponent) error

// WalkedYAMLComponent is a struct containing information about a component
// yielded via the WalkYAML method.
type WalkedYAMLComponent struct {
ComponentType Type
Name string
Label string
Conf *yaml.Node
}

// WalkYAML walks each node of a YAML tree and for any component types within
// the config a provided func is called.
func (f FieldSpecs) WalkYAML(node *yaml.Node, prov Provider, fn ComponentWalkYAMLFunc) error {
node = unwrapDocumentNode(node)

nodeKeys := map[string]*yaml.Node{}
for i := 0; i < len(node.Content)-1; i += 2 {
nodeKeys[node.Content[i].Value] = node.Content[i+1]
}

// Following the order of our field specs, walk each field.
for _, field := range f {
value, exists := nodeKeys[field.Name]
if !exists {
continue
}
if err := field.WalkYAML(value, prov, fn); err != nil {
return err
}
}
return nil
}

//------------------------------------------------------------------------------

func unwrapDocumentNode(node *yaml.Node) *yaml.Node {
if node != nil && node.Kind == yaml.DocumentNode && len(node.Content) > 0 {
node = node.Content[0]
Expand Down
Loading

0 comments on commit 3742ba4

Please sign in to comment.