Skip to content

Structured configuration layer #881

Open

Description

@foxcpp

We need a decoder that will map config.Node's into Go types using reflection.

  • structures are unmarshalled using config.Map according to provided tags.
  • time.Duration is unmarshalled like config.Map.Duration
  • other types supported by config.Map are unmarshalled using the same way.
  • slices handle duplicates directives, each directive parsed as a separate entry.
  • config.StringSet
  • config.Node is copied as-is.
// Module config structure example
type Config struct{
  Hostname `maddy:"hostname,required,inherit"`
  Timeout time.Duration `maddy:"timeout,required,inherit"`
  DataSize config.DataSize `maddy:"data_size"` // default without explicit value keeps existing value

  Defaults config.DataSize `maddy:"default:1m"`

  DeliverTo []ModuleReference // multiple directives
  AuthMethods config.Enum[string] `maddy:"enum:login plain oauth"`// one directive, duplicates fail, unknown values fail
  IPs config.List[string] // one directive, duplicates allowed

  // unknown can be used multiple times 
  Endpoint []GlobalEndpoint `maddy:"unknown"`
  SharedModules []GlobalModule `maddy:"unknown"`

  // Escape hatch for handling unknown directives via legacy code.
  // allows two-step processing.
  Unknown []config.Node `maddy:"unknown"`
}
type ConfigContext struct{
  *container.C
  Globals map[string]any
}

// Sentinel error that can be returned by UnmarshalConfig when handling `unknown` struct field that tells
// it to skip the directive and try parsing it 
var ErrSkipUnknown error

type ConfigUnmarshaller interface{
  UnmarshalConfig(*config.Node, ConfigContext) error
}

For referencing module instances that is lazily resolved.

type ModuleReference struct{
}
func (ModuleReference) GetModule() module.Module { ...}

Modules may implement alternative interface to read configuration without using raw *config.Map:

type ConfigModule interface{
  // GetConfig must return same object each time for module instance.
  GetConfig() any
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions