stubbing pdsh

This commit is contained in:
brent saner
2025-08-17 02:58:24 -04:00
parent e797a14911
commit 5a62622892
20 changed files with 432 additions and 130 deletions

View File

@@ -1,86 +1,60 @@
package pdsh
// TODO: This... doesn't really have much usefulness, does it?
/*
type (
HostLister interface {
// Hosts returns ALL hsots (where applicable) that are considered/generated for a Lister.
Hosts() (hosts []string, err error)
}
)
*/
type (
/*
DshGroupLister behaves like the host list generator
for pdsh(1)'s "dshgroup module options" (the `misc/dshgroup`
module for pdsh).
Generator is one of the PDSH host generators/iterators offered by this module.
Note that these generators/iterators are *stateful*, which means they shouldn't
(probably; I'm not your dad) be used concurrently (unless you want some hard-to-debug results)
and all methods advance the generator - so you probably don't want to call both Generate() and
Next()/Host() on the same instance, for example.
*/
DshGroupLister struct {
Generator interface {
/*
NoEnv, if true, will *not* use DSHGROUP_PATH (force-defaulting to /etc/dsh/group/,
but see NoDefault).
*/
NoEnv bool
/*
NoDefault, if true, will *not* add the default path `/etc/dsh/group/`
to the search paths.
Generate provides a Go-native iterator (also called a "RangeFunc" or "range over function type")
as found in Go 1.23 onwards.
If NoDefault is false, this path is only added if DSHGROUP_PATH is not defined
(or, if it IS defined, if NoEnv is true).
See the assocaied blog entry for details: https://go.dev/blog/range-functions
Essentially it allows for e.g.:
for host := range (Generator).Generate() {
// ...
}
which is the "new standard" approach for iteration.
*/
NoDefault bool
// NoHome, if true, will *not* add the `~/.dsh/group/` path to the search paths.
NoHome bool
Generate() (yieldFunc func(yield func(host string) (done bool)))
/*
ForceLegacy, if true, will disable the PDSH `#include <PATH|GROUP>` modification --
treating the source as a traditional DSH group file instead (e.g. `#include ...`
is treated as just a comment).
Reset is used to reset a Generator, allowing one to "restart" the generation at the beginning.
Generators in this module are generally single-use, but can be reset/reused with this method.
*/
ForceLegacy bool
}
)
type (
dshGrpGenerator struct {
/*
tokens are interleaved with tokenized and indexed *after*;
in other words, str = <substr0><token0><substr1><token1>...
*/
tokens []dshGrpToken
// tokenized holds the split original text with tokens removed and split where the tokens occur.
tokenized []string
// text holds the original pattern.
text string
}
dshGrpToken struct {
/*
token contains the original range specifier.
Tokens may be e.g.:
* 3: str3
* 3-5: str3, str4, str5
* 3,5: str3, str5
*/
token string
// subtokens hold a split of the individual range specifiers.
subtokens []dshGrpSubtoken
}
dshGrpSubtoken struct {
// start indicates either the single value or the start of the range.
start uint
// end, if 0 or less than start, indicates a single-value range.
end uint
// pad, if non-empty, is a string to add to the beginning of each of the generated substrings for this subtoken.
pad string
}
)
type (
PtrnParseErr struct {
pos uint
ptrn string
r rune
err error
Reset()
/*
Hosts returns a complete generated hostlist at once if you'd rather not iterate.
Hosts() *does* perform an iteration in runtime, so the recommendation against concurrency
stands, but it calls Reset() when done generating to allow other methods of a Generator to be used.
*/
Hosts() (hostList []string)
/*
Next and Host behave like more "traditional" iterators, e.g. like (database/sql).Row.Next().
Next advances the internal state to the next host, and Host() returns it.
*/
Next() (done bool)
/*
Host returns the current host string (or "" if done).
Be sure to e.g.:
for (Generator).Next() {
host := (Generator).Host()
}
otherwise the Host return value will not change.
*/
Host() (host string)
}
)