{{ message }}
Repository navigation
Tags: GSI-HPC/go-nodeset
Tags
go-nodeset v1.1.0 A minor release that adds one optional interface: a resolver whose every lookup is a round trip can now be handed the groups of an expression at once. No exported identifier was removed or changed, every expression names the same hosts as in v1.0.1, and `String`, `Hostlist` and `Expand` write any given set as before ([decision 10](https://github.com/GSI-HPC/go-nodeset/blob/v1.1.0/doc/decisions.md#10-the-first-release-is-v100)). ## New - `BatchResolver`, with `GroupRef` and `GroupAnswer` (#15, #16). The parser asked a `Resolver` for one group at a time, as it reached each reference, so `@rack:r01,@rack:r02,…,@rack:r08` over a source that runs a command, queries a directory or calls a service waited for eight round trips one after the other. A `Resolver` that also implements `ResolveBatch(refs []GroupRef) []GroupAnswer` is now asked, before an expression is evaluated, for the groups it refers to in one call, when there are at least two: the expression given to `ParseWith`, and each expression a group answers with. The resolver decides how to answer, in one request, in parallel or from a cache; the package starts no goroutines. - A bare reference inside a group of a named source is passed with that source, as `Resolve` is given it. - Within one call of `ParseWith`, a group that has been answered, by `ResolveBatch` or by `Resolve`, failure included, is not asked for again. Keeping answers from one call to the next is the resolver's to do. - A shorter slice, or nil, leaves the groups without an answer to `Resolve`. `@*` and `@source:*` are answered by `All`, as before. - An expression names the same hosts, and fails with the same error, as through `Resolve` alone: an answer's error is reported where the evaluation reaches that group. An expression that fails may have had groups looked up that its evaluation did not reach. - Which groups are asked for together is not part of the API, any more than speed is ([decision 13](https://github.com/GSI-HPC/go-nodeset/blob/v1.1.0/doc/decisions.md#13-a-resolver-may-look-up-the-groups-of-an-expression-at-once)). `ExampleBatchResolver` shows a resolver. ## Changes - Parsing no longer copies each term of an expression before reading it, so an expression of many terms allocates far less: one of 2,000 names without brackets allocates about a tenth as often as in v1.0.1. ## Upgrading from v1.0.1 Nothing changes for a program whose resolver has no `ResolveBatch` method: it is asked exactly as before. A program that looks up the groups of an expression together in front of the package, by reading its references itself, can implement `BatchResolver` instead and drop that copy of the parser's rules. ## Requirements Go 1.26 or newer.
go-nodeset v1.0.1 A patch release with three fixes. Each corrects behaviour that contradicted the documentation of v1.0.0, and each makes some expressions that v1.0.0 accepted an error or name other hosts. A fix is a patch release ([decision 10](https://github.com/GSI-HPC/go-nodeset/blob/v1.0.1/doc/decisions.md#10-the-first-release-is-v100)), so the section on upgrading names every such change, for a program to tell whether it is affected. No exported identifier was added, removed or changed, and `String`, `Hostlist` and `Expand` write any given set as v1.0.0 did. ## Fixes - A range needs both its bounds (#10, #11). v1.0.0 read a range with a dash and no last bound as its first bound alone: `exe[1-]` was `exe1`, and `exe[1-,5]` was `exe[1,5]`. That is what `exe[1-$N]` leaves behind when `N` is empty or unset, so a command meant for many hosts ran on `exe1` alone. ClusterShell 1.10.1 rejects such a range, and the language reference of v1.0.0 did not list it among the differences. It is now an error: `in "exe[1-]": the range "1-" has no last bound`. - `@*` and `@source:*` over a `MapResolver` evaluate each group on its own (#12, #13). `MapResolver.All` joined the expressions of a source's groups with commas into one expression, which is evaluated left to right, so the `!`, `&` or `^` of one group applied to every group before it. With `a: exe1` and `b: exe[2-4]!exe1`, `@*` named `exe[2-4]` where `@a,@b` named `exe[1-4]`, against the doc comments of `Resolver.All` and `MapResolver.All`, which promise every host the source knows and the union of its groups. `All` now refers to such a group as `@source:group`, which the parser evaluates on its own, and `@*` names `exe[1-4]`. ClusterShell 1.10.1 also joins the groups of a source without an `all` group into one expression, and the notes of v1.0.0 said that `MapResolver` resolves `@*` as ClusterShell does. Here the package now departs from it ([decision 11](https://github.com/GSI-HPC/go-nodeset/blob/v1.0.1/doc/decisions.md#11-mapresolver-evaluates-every-group-of-a-source-on-its-own)). - A group whose brackets do not balance is evaluated on its own too. v1.0.0 wrote it into the join as it was, so it took the comma and the next group into its range: with `a: exe[1` and `b: 3]`, `@*` named `exe[1,3]`, although each group alone is an error. `All` now refers to such a group as well, and `@*` is an error, as each group is. ClusterShell's fallback names `exe[1,3]` too ([decision 12](https://github.com/GSI-HPC/go-nodeset/blob/v1.0.1/doc/decisions.md#12-a-group-with-unbalanced-brackets-is-evaluated-on-its-own-too)). ## Upgrading from v1.0.0 Any expression not covered here names the same hosts as in v1.0.0. - A range without its last bound is an error wherever it is written. `exe[1-]` and `exe[1-/1]` were `exe1`, `exe[01-]` was `exe01`, `exe[1-,5]` and `exe[5,1-]` were `exe[1,5]`, and `a[1-]b[2-3]` was `a1b[2-3]`. `Parse`, `ParseWith` and `Add` return the error, and `MustParse` panics. `Contains("exe[1-]")` and `Canonical("exe[1-]")`, which found `exe1`, now report that the set does not hold it. A group whose expression holds such a range makes every reference to it an error, `@*` over its source included. `exe[1-/2]` was an error already, and only its message changed. `String` and `Hostlist` always write both bounds, so whatever v1.0.0 printed parses as it did. The other two fixes concern a program only if it uses `@*`, `@source:*` or `MapResolver.All` over a `MapResolver` source in which a group holds `!`, `&` or `^`, or a bracket that does not balance. To tell what changes for such a source, parse `@source:g` for each such group `g`. If one is an error, `@source:*` is now an error too. Otherwise `@source:*` now names those groups and the expressions of the others together, unless one of the errors below applies or the groups together exceed the limits. - Where the `MapResolver` itself resolves what `All` returns, `@*` can only gain hosts, unless it is now an error. With `batch: exe[1-100]`, `drained: exe[5,7]` and `up: @Batch!@drained`, `@*` was `exe[1-4,6,8-100]` and is now `exe[1-100]`, so a program that acts on `@*` now reaches the drained hosts too. Combined with another set `X`, `X!@*` can remove more hosts and `X&@*` keep more. - Where one host is spelled with different padding in different groups, `@*` can print and list it in another spelling. With `a: exe1`, `b: exe[2-4]!exe1` and `c: exe01`, `@*` was `exe[01,2-4]` and is now `exe[1-4]`, and `Expand` and `Canonical` give `exe1` where they gave `exe01`. - `MapResolver.All` returns another expression for such a source. With `a: exe1` and `b: exe[2-4]!exe1` in the source `local`, `All("local")` was `exe1,exe[2-4]!exe1` and is now `exe1,@Local:b`. With `a: exe[1` and `b: 3]` it was `exe[1,3]` and is now `@local:a,@Local:b`. A program that stores or compares that string, or hands it to another tool, sees the difference. A source whose groups hold no operator but the union and balance their brackets gets the same expression as before. - `All`, and with it `@*` and `@source:*`, is an error when it has to refer to a group whose name is empty or `*`, or holds whitespace of any kind, a comma, `!`, `&`, `^` or a bracket, or to a group of a source whose name holds one of those or a colon, since such a reference might not read back as that group. The error quotes the reference. This includes sources v1.0.0 answered right: with the one group `my group: exe[1-4]!exe2`, `@*` was `exe[1,3-4]` and is now an error. - A group that `All` refers to is evaluated one level of nesting deeper. A chain of group references that `@*` or `@source:*` resolved in v1.0.0 at the sixteenth level now fails with `group references nested more than 16 levels deep`. - A custom `Resolver` whose `All` calls `MapResolver.All` now receives, in its `Resolve`, the references `All` returns and the bare references inside the groups they name, both with the `MapResolver`'s own source name. It has to answer for that source as the `MapResolver` does, or `@*` leaves those groups out or fails. A resolver whose own `All` joins the expressions of several groups has the bug that this release fixes in `MapResolver`, and the doc comment of `Resolver.All` now says so. - ClusterShell names the same hosts for such a source when it is given what `All` returns as the `all` group of a source of the same name, apart from the differences and limits the [language reference](https://github.com/GSI-HPC/go-nodeset/blob/v1.0.1/doc/language.md#groups) lists and group names it reads otherwise, such as one beginning with `@`. v1.0.0 is not retracted. Upgrading is recommended, above all for a program that builds expressions from variables or user input. ## Requirements Go 1.26 or newer.
go-nodeset v1.0.0 The first release of go-nodeset: ClusterShell node sets for Go, in one package that needs nothing but the standard library. It parses, folds and expands ranges, steps and names with several numbers, applies the set operators `,` `!` `&` `^`, and resolves `@group` references through a resolver of your own. It names the same hosts as ClusterShell 1.10.1, folds them alike and lists them in the same order, apart from the differences below. The engine was written as the `nodeset` package of [clusterctl](https://github.com/GSI-HPC/clusterctl) and shipped there first. ## Stability From this release on, a minor or patch release does not break the exported API, the hosts an expression names, or the output of `String`, `Hostlist` and `Expand` ([decision 10](https://github.com/GSI-HPC/go-nodeset/blob/v1.0.0/doc/decisions.md#10-the-first-release-is-v100)). The text of errors, speed and memory are not covered. ## What it does - `Parse`, `ParseWith` and `MustParse` read an expression; `New` and `Add` build a set. - `String` folds a set as ClusterShell does, including names with several numbers; `Hostlist` writes one that Slurm accepts; `Expand` lists the hosts in ClusterShell's order. - `Union`, `Intersection`, `Difference`, `SymmetricDifference`, `Split`, `Contains`, `Canonical`, `Len`, `Clone`. - `Resolver`, the optional `Lister` and `MapResolver` resolve groups as ClusterShell does, `@source:group` and `@*` included. - `WithAutostep` folds arithmetic progressions as ClusterShell's autostep does. - Sets keep their ranges: `r[1-1000]n[1-1000]` is held as two ranges rather than a million hosts, and is listed host by host only when an operator has to combine it with hosts it does not hold. ## Differences from ClusterShell A few expressions are read differently, on purpose: padding is not part of a host's identity (`exe1,exe01` is one host), adjacent numeric parts, names beginning with `-` and `exe[1-2-3]` are errors, whitespace unions, and an empty operand names nothing. Where one pattern holds numbers of different widths, the folded output may order them differently: ClusterShell prints `exe[3,01-02]`, go-nodeset `exe[01-02,3]`. [doc/language.md](https://github.com/GSI-HPC/go-nodeset/blob/v1.0.0/doc/language.md#where-this-differs-from-clustershell) lists every difference. An expression may name at most 1,048,576 hosts, and a bracket may hold at most as many elements, so that a typo such as `exe[1-100000000]` is refused rather than exhausting memory ([limits](https://github.com/GSI-HPC/go-nodeset/blob/v1.0.0/doc/language.md#limits)). ClusterShell has no such limit. ## Requirements Go 1.26 or newer.
