jx/internal/config/file.go
Matthew Rich 1460d2285b
Some checks failed
Declarative Tests / build-ubuntu-focal (push) Waiting to run
Lint / golangci-lint (push) Failing after 15s
Declarative Tests / test (push) Failing after 5s
Declarative Tests / build-fedora (push) Has been cancelled
add support for configuration documents
2024-07-01 14:54:18 -07:00

138 lines
3.3 KiB
Go

// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
package config
import (
_ "context"
_ "encoding/json"
_ "fmt"
_ "gopkg.in/yaml.v3"
"net/url"
"path/filepath"
"decl/internal/transport"
"decl/internal/codec"
_ "os"
"io"
"errors"
"log/slog"
)
type ConfigFile struct {
Path string `yaml:"path" json:"path"`
Format codec.Format `yaml:"format" json:"format"`
reader *transport.Reader `yaml:"-" json:"-"`
writer *transport.Writer `yaml:"-" json:"-"`
encoder codec.Encoder `yaml:"-" json:"-"`
decoder codec.Decoder `yaml:"-" json:"-"`
}
func NewConfigFile() *ConfigFile {
return &ConfigFile{ Format: codec.FormatYaml }
}
func NewConfigFileFromURI(u *url.URL) *ConfigFile {
t := NewConfigFile()
if u.Scheme == "file" {
t.Path,_ = filepath.Abs(filepath.Join(u.Hostname(), u.RequestURI()))
} else {
t.Path = filepath.Join(u.Hostname(), u.Path)
}
return t
}
func NewConfigFileSource(u *url.URL) *ConfigFile {
t := NewConfigFileFromURI(u)
t.reader,_ = transport.NewReader(u)
if formatErr := t.Format.Set(t.reader.ContentType()); formatErr != nil {
panic(formatErr)
}
t.decoder = codec.NewDecoder(t.reader, t.Format)
return t
}
func NewConfigFileTarget(u *url.URL) *ConfigFile {
t := NewConfigFileFromURI(u)
t.writer,_ = transport.NewWriter(u)
if formatErr := t.Format.Set(t.writer.ContentType()); formatErr != nil {
panic(formatErr)
}
t.encoder = codec.NewEncoder(t.writer, t.Format)
return t
}
func init() {
ConfigSourceTypes.Register([]string{"file"}, func(u *url.URL) ConfigSource {
return NewConfigFileSource(u)
})
ConfigSourceTypes.Register([]string{"pb","pb.gz","json","json.gz","yaml","yml","yaml.gz","yml.gz"}, func(u *url.URL) ConfigSource {
return NewConfigFileSource(u)
})
ConfigTargetTypes.Register([]string{"file"}, func(u *url.URL) ConfigTarget {
return NewConfigFileTarget(u)
})
ConfigTargetTypes.Register([]string{"pb","pb.gz","json","json.gz","yaml","yml","yaml.gz","yml.gz"}, func(u *url.URL) ConfigTarget {
return NewConfigFileTarget(u)
})
}
func (c *ConfigFile) Type() string { return "file" }
func (c *ConfigFile) Extract(filter ConfigurationSelector) ([]*Document, error) {
documents := make([]*Document, 0, 100)
defer func() {
c.reader.Close()
}()
slog.Info("Extract()", "documents", documents)
index := 0
for {
doc := NewDocument()
e := c.decoder.Decode(doc)
if errors.Is(e, io.EOF) {
break
}
if e != nil {
return documents, e
}
slog.Info("Extract()", "res", doc.ConfigBlocks[0].Values)
if validationErr := doc.Validate(); validationErr != nil {
return documents, validationErr
}
documents = append(documents, doc)
index++
}
return documents, nil
}
func (c *ConfigFile) EmitResources(documents []*Document, filter ConfigurationSelector) (error) {
defer func() {
c.encoder.Close()
c.writer.Close()
}()
for _, doc := range documents {
emitDoc := NewDocument()
if validationErr := doc.Validate(); validationErr != nil {
return validationErr
}
for _, block := range doc.Filter(filter) {
emitDoc.ConfigBlocks = append(emitDoc.ConfigBlocks, *block)
}
slog.Info("EmitResources", "doctarget", c, "encoder", c.encoder, "emit", emitDoc)
if documentErr := c.encoder.Encode(emitDoc); documentErr != nil {
slog.Info("EmitResources", "err", documentErr)
return documentErr
}
}
return nil
}
func (c *ConfigFile) Close() (error) {
return nil
}