v0.30.0 lw --tui, compose pipeline on screen
This commit is contained in:
1 parent
2d72772943
commit
883af0fcaa
20 files changed
+2442
-69
No files matched your search
@@ -94,14 +94,18 @@ func FromCommandLine(line string, isDir config.IsDir) (*Composition, error) {
|
||||
return c, c.settle()
|
||||
}
|
||||
|
||||
// settle gives every flow stage its defaults and every plugin's options their
|
||||
// kinds; the rules are Validate's
|
||||
// settle gives every flow stage its defaults, every plugin's options their
|
||||
// kinds and every source and sink an id; the rules are Validate's
|
||||
func (c *Composition) settle() error {
|
||||
for i := range c.Pipelines {
|
||||
p := &c.Pipelines[i]
|
||||
if p.Flow == nil {
|
||||
p.Flow = &config.FlowConfig{}
|
||||
}
|
||||
name(len(p.PluginSources), func(j int) *string { return &p.PluginSources[j].ID },
|
||||
func(j int) string { return p.PluginSources[j].Type })
|
||||
name(len(p.PluginSinks), func(j int) *string { return &p.PluginSinks[j].ID },
|
||||
func(j int) string { return p.PluginSinks[j].Type })
|
||||
for _, stage := range stages(p.Flow) {
|
||||
if !stage.IsNil() {
|
||||
config.Fill(stage.Interface())
|
||||
@@ -126,6 +130,23 @@ func (c *Composition) settle() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// name gives the parts a file left unnamed the ids their specs would get: the
|
||||
// shell forms write no empty id
|
||||
func name(n int, id func(int) *string, typ func(int) string) {
|
||||
var taken []string
|
||||
for j := range n {
|
||||
if *id(j) != "" {
|
||||
taken = append(taken, *id(j))
|
||||
}
|
||||
}
|
||||
for j := range n {
|
||||
if *id(j) == "" {
|
||||
*id(j) = config.FreeID(typ(j), taken)
|
||||
taken = append(taken, *id(j))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stages are the flow table's fields that hold one stage each, by key: a
|
||||
// pointer, nil while the stage is off. The filters are a list.
|
||||
func stages(f *config.FlowConfig) map[string]reflect.Value {
|
||||
@@ -358,6 +379,31 @@ func editStage(stage reflect.Value, change func(map[string]any) error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Options returns a copy of a node's options that are set, and whether it is
|
||||
// on: a flow stage that is off has none
|
||||
func (c *Composition) Options(pi int, n Node) (map[string]any, bool, error) {
|
||||
p, err := c.pipeline(pi)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
switch i := index(p, n); {
|
||||
case i < 0:
|
||||
case n.Role == "source":
|
||||
return config.Clone(p.PluginSources[i].Config), true, nil
|
||||
case n.Role == "sink":
|
||||
return config.Clone(p.PluginSinks[i].Config), true, nil
|
||||
case n.Role == "filters":
|
||||
return config.Values(&p.Flow.Filters[i]), true, nil
|
||||
}
|
||||
if stage, ok := stages(p.Flow)[n.Role]; ok {
|
||||
if stage.IsNil() {
|
||||
return nil, false, nil
|
||||
}
|
||||
return config.Values(stage.Interface()), true, nil
|
||||
}
|
||||
return nil, false, n.missing()
|
||||
}
|
||||
|
||||
// Validate applies every rule lw applies at load, naming the refused key's path
|
||||
func (c *Composition) Validate() error { return config.ValidatePipelines(c.Pipelines) }
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/lixenwraith/logwisp/internal/config"
|
||||
)
|
||||
|
||||
// The engine builds as WebAssembly for the website: it links no TLS, HTTP,
|
||||
@@ -117,3 +119,43 @@ func TestSetKeepsAKeyItCannotTake(t *testing.T) {
|
||||
t.Fatalf("options %v, heartbeat %+v", m, beat)
|
||||
}
|
||||
}
|
||||
|
||||
// Options are a copy: changing them changes no pipeline; a stage that is off
|
||||
// has none
|
||||
func TestOptionsAreACopy(t *testing.T) {
|
||||
c := &Composition{}
|
||||
if err := c.AddPipeline("p"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
n, _ := c.Add(0, "sink", "tcp")
|
||||
if err := c.Set(0, n, "port", "9000"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
opts, on, err := c.Options(0, n)
|
||||
opts["port"] = int64(1)
|
||||
if _, rate, _ := c.Options(0, Node{Role: "rate_limit"}); err != nil || !on || rate || c.Pipelines[0].PluginSinks[0].Config["port"] != int64(9000) {
|
||||
t.Fatalf("%v %v %v %v", opts, on, rate, err)
|
||||
}
|
||||
}
|
||||
|
||||
// A file may leave a source's or sink's id out: the engine names it as a
|
||||
// spec would, around the ids the file gave, so the shell forms load back
|
||||
func TestUnnamedPartsTakeFreeIDs(t *testing.T) {
|
||||
c, err := FromConfig(&config.Config{Pipelines: []config.PipelineConfig{{Name: "p",
|
||||
PluginSources: []config.PluginSourceConfig{{Type: "null"}, {ID: "null", Type: "null"}},
|
||||
PluginSinks: []config.PluginSinkConfig{{Type: "null"}}}}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
p := c.Pipelines[0]
|
||||
if ids := []string{p.PluginSources[0].ID, p.PluginSources[1].ID, p.PluginSinks[0].ID}; !slices.Equal(ids, []string{"null_2", "null", "null"}) {
|
||||
t.Fatalf("ids %q", ids)
|
||||
}
|
||||
line, err := c.CommandLine()
|
||||
if err == nil {
|
||||
_, err = FromCommandLine(line, nil)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("%v\n%s", err, line)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user