// Copyright 2024 Matthew Rich . All rights reserved. package config import ( "context" "io" "fmt" "net/url" "decl/internal/codec" "decl/internal/command" "decl/internal/data" "decl/internal/folio" "encoding/json" "gopkg.in/yaml.v3" ) func init() { folio.DocumentRegistry.ConfigurationTypes.Register([]string{"exec"}, func(u *url.URL) data.Configuration { x := NewExec() return x }) } type Exec struct { Path string `yaml:"path" json:"path"` Args []command.CommandArg `yaml:"args" json:"args"` ValuesFormat codec.Format `yaml:"format" json:"format"` Values map[string]any `yaml:"values" json:"values"` ReadCommand *command.Command `yaml:"-" json:"-"` } func NewExec() *Exec { x := &Exec{} return x } func (x *Exec) SetURI(uri string) error { return nil } func (x *Exec) SetParsedURI(uri data.URIParser) error { return nil } func (x *Exec) URI() string { return fmt.Sprintf("%s://%s", x.Type(), x.Path) } func (x *Exec) Read(ctx context.Context) ([]byte, error) { out, err := x.ReadCommand.Execute(x) if err != nil { return nil, err } exErr := x.ReadCommand.Extractor(out, x) if exErr != nil { return nil, exErr } return nil, exErr } func (x *Exec) Load(r io.Reader) (err error) { err = codec.NewYAMLDecoder(r).Decode(x) if err == nil { _, err = x.Read(context.Background()) } return err } func (x *Exec) LoadYAML(yamlData string) (err error) { err = codec.NewYAMLStringDecoder(yamlData).Decode(x) if err == nil { _, err = x.Read(context.Background()) } return err } func (x *Exec) UnmarshalJSON(data []byte) error { if unmarshalErr := json.Unmarshal(data, x); unmarshalErr != nil { return unmarshalErr } x.NewReadConfigCommand() return nil } func (x *Exec) UnmarshalYAML(value *yaml.Node) error { type decodeExec Exec if unmarshalErr := value.Decode((*decodeExec)(x)); unmarshalErr != nil { return unmarshalErr } x.NewReadConfigCommand() return nil } func (x *Exec) Clone() data.Configuration { clone := NewExec() clone.Path = x.Path clone.Args = x.Args clone.ValuesFormat = x.ValuesFormat clone.Values = x.Values clone.ReadCommand = x.ReadCommand return clone } func (x *Exec) Type() string { return "exec" } func (x *Exec) GetValue(name string) (result any, err error) { var ok bool if result, ok = x.Values[name]; !ok { err = data.ErrUnknownConfigurationKey } return } func (x *Exec) Has(key string) (ok bool) { _, ok = x.Values[key] return } func (ex *Exec) NewReadConfigCommand() { ex.ReadCommand = command.NewCommand() ex.ReadCommand.Path = ex.Path ex.ReadCommand.Args = ex.Args ex.ReadCommand.Extractor = func(out []byte, target any) error { x := target.(*Exec) switch x.ValuesFormat { case codec.FormatYaml: return codec.NewYAMLStringDecoder(string(out)).Decode(&x.Values) case codec.FormatJson: return codec.NewJSONStringDecoder(string(out)).Decode(&x.Values) case codec.FormatProtoBuf: } return nil } }