v0.35.2 lwconf, doc and deploy update
Package / arch (push) Canceled after 0s
Package / user (push) Canceled after 0s
Package / deb (push) Canceled after 0s
Package / freebsd (push) Canceled after 0s
Package / image (push) Canceled after 0s
Test / test (push) Canceled after 0s
Test / e2e (push) Canceled after 0s
Package / arch (push) Canceled after 0s
Package / user (push) Canceled after 0s
Package / deb (push) Canceled after 0s
Package / freebsd (push) Canceled after 0s
Package / image (push) Canceled after 0s
Test / test (push) Canceled after 0s
Test / e2e (push) Canceled after 0s
This commit is contained in:
1 parent
0b8701ec13
commit
de87b9a008
21 files changed
+255
-185
No files matched your search
+25
-10
@@ -61,13 +61,21 @@ func FromPreset(name string, values map[string]string, isDir config.IsDir) (*Com
|
||||
|
||||
// FromCommandLine starts from a pasted lw command line, quoted as a POSIX
|
||||
// shell reads it; it takes pipeline flags only, at least one, as a composition
|
||||
// holds no settings
|
||||
// holds no settings. Of a line piped into lw it reads lw's part, whose
|
||||
// pipelines read standard input.
|
||||
func FromCommandLine(line string, isDir config.IsDir) (*Composition, error) {
|
||||
words, err := split(strings.NewReplacer("\r\n", "\n", "\r", "\n").Replace(line)) // pasted line ends
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(words) > 0 && (words[0] == "lw" || strings.HasSuffix(words[0], "/lw")) {
|
||||
lw := func(word string) bool { return word == "lw" || strings.HasSuffix(word, "/lw") }
|
||||
for i := len(words) - 2; i >= 0; i-- {
|
||||
if words[i] == "|" && lw(words[i+1]) {
|
||||
words = words[i+1:]
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(words) > 0 && lw(words[0]) {
|
||||
words = words[1:]
|
||||
}
|
||||
var specs []config.Spec
|
||||
@@ -77,8 +85,12 @@ func FromCommandLine(line string, isDir config.IsDir) (*Composition, error) {
|
||||
name = "--preset"
|
||||
}
|
||||
flag, long := strings.CutPrefix(name, "--")
|
||||
if !long || !slices.ContainsFunc(config.SpecFlags(), func(f config.SpecFlag) bool { return f.Flag == flag }) {
|
||||
return nil, fmt.Errorf("%s: not a pipeline flag", words[i])
|
||||
if flags := config.SpecFlags(); !long || !slices.ContainsFunc(flags, func(f config.SpecFlag) bool { return f.Flag == flag }) {
|
||||
var names []string
|
||||
for _, f := range flags {
|
||||
names = append(names, "--"+f.Flag)
|
||||
}
|
||||
return nil, fmt.Errorf("%s: not a pipeline flag; paste lw's %s only", words[i], strings.Join(names, ", "))
|
||||
}
|
||||
if !inline {
|
||||
if i++; i == len(words) || strings.HasPrefix(words[i], "-") {
|
||||
@@ -205,8 +217,11 @@ func (c *Composition) RenamePipeline(i int, name string) error {
|
||||
|
||||
// free refuses a name that is empty or held by a pipeline other than i
|
||||
func (c *Composition) free(name string, i int) error {
|
||||
if j := slices.IndexFunc(c.Pipelines, func(p config.PipelineConfig) bool { return p.Name == name }); name == "" || j >= 0 && j != i {
|
||||
return fmt.Errorf("pipeline %q: a name no other pipeline has", name)
|
||||
switch j := slices.IndexFunc(c.Pipelines, func(p config.PipelineConfig) bool { return p.Name == name }); {
|
||||
case name == "":
|
||||
return errors.New("a pipeline needs a name; give it one")
|
||||
case j >= 0 && j != i:
|
||||
return fmt.Errorf("another pipeline is named %q; choose another name", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -574,7 +589,7 @@ func (c *Composition) CommandLine() (string, error) {
|
||||
// line as an environment file holds them; the environment holds one pipeline
|
||||
func (c *Composition) Environment() (string, error) {
|
||||
if len(c.Pipelines) != 1 {
|
||||
return "", fmt.Errorf("the environment holds one pipeline, not %d", len(c.Pipelines))
|
||||
return "", fmt.Errorf("the environment holds one pipeline, not %d; choose the command or file form, or remove pipelines down to one", len(c.Pipelines))
|
||||
}
|
||||
specs, err := c.shellSpecs()
|
||||
if err != nil {
|
||||
@@ -632,9 +647,9 @@ type Form struct {
|
||||
}
|
||||
|
||||
var forms = []Form{
|
||||
{"command", "lw's flags", (*Composition).CommandLine, FromCommandLine},
|
||||
{"environment", "LOGWISP_ variables: one pipeline", (*Composition).Environment, FromEnvironment},
|
||||
{"file", "a configuration file's pipelines", func(c *Composition) (string, error) {
|
||||
{"command", "an lw command line", (*Composition).CommandLine, FromCommandLine},
|
||||
{"environment", "LOGWISP_ variables for one pipeline", (*Composition).Environment, FromEnvironment},
|
||||
{"file", "the pipelines of a configuration file", func(c *Composition) (string, error) {
|
||||
data, err := c.File()
|
||||
return string(data), err
|
||||
}, func(text string, _ config.IsDir) (*Composition, error) { return FromFile([]byte(text)) }},
|
||||
|
||||
@@ -115,6 +115,18 @@ func TestPastedEnvironmentReadsAsAShellRunsIt(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Of a line piped into lw, lw's part is read, its pipeline reading standard
|
||||
// input; a word that is no pipeline flag is refused, naming those to paste
|
||||
func TestPastedCommandLineIsLwsPart(t *testing.T) {
|
||||
c, err := FromCommandLine("tail -F app.log | lw --filter include:patterns=ERROR", nil)
|
||||
if err != nil || c.Pipelines[0].PluginSources[0].Type != "console" || len(c.Pipelines[0].Flow.Filters) != 1 {
|
||||
t.Fatalf("%v %v", c, err)
|
||||
}
|
||||
if _, err := FromCommandLine("lw -c lw.toml --sink null", nil); err == nil || !strings.HasPrefix(err.Error(), "-c: not a pipeline flag; paste lw's --pipeline, --preset, ") {
|
||||
t.Fatalf("-c: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Locate places a problem by its path: a plugin's key, a key of its table, a
|
||||
// rule between its table's keys, a list entry, the plugin itself under an id
|
||||
// holding ']', a filter's list entry, a stage and the pipeline; and nothing
|
||||
@@ -192,8 +204,9 @@ func TestShellFormsRefuseControlCharacters(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Set refuses a value of the wrong kind and leaves the key as it was; Unset
|
||||
// returns a key to its default, dropping a table it leaves empty
|
||||
// Set refuses a value of the wrong kind, a plugin's and a stage's alike, and
|
||||
// leaves the key as it was; Unset returns a key to its default, dropping a
|
||||
// table it leaves empty
|
||||
func TestSetKeepsAKeyItCannotTake(t *testing.T) {
|
||||
c := &Composition{}
|
||||
if err := c.AddPipeline("p"); err != nil {
|
||||
@@ -207,8 +220,11 @@ func TestSetKeepsAKeyItCannotTake(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if err := c.Set(0, n, "port", "http"); err == nil || !strings.HasPrefix(err.Error(), "port: ") {
|
||||
t.Fatalf("port http: %v", err)
|
||||
for want, err := range map[string]error{"port: not an integer": c.Set(0, n, "port", "http"),
|
||||
"interval_ms: not an integer": c.Set(0, beat, "interval_ms", "soon")} {
|
||||
if err == nil || err.Error() != want {
|
||||
t.Errorf("%v, want %s", err, want)
|
||||
}
|
||||
}
|
||||
if m, beat := c.Pipelines[0].PluginSinks[0].Config, c.Pipelines[0].Flow.Heartbeat; !reflect.DeepEqual(m, map[string]any{"port": int64(8080)}) ||
|
||||
beat.IntervalMS != 1000 {
|
||||
|
||||
Reference in new issue
Block a user