Summary
Implement pdsh-style hostlist expression syntax for specifying multiple hosts using range notation. This allows compact specification of host lists like node[01-10] instead of listing each host individually.
Parent Issue
Part of #91 (pdsh compatibility mode) - Phase 3: Hostlist Expression Support
Prerequisites
- Phase 2 Core Infrastructure must be complete
- The hostlist parser can be used in both pdsh compat mode and native bssh mode
Background
pdsh uses a powerful hostlist expression syntax that allows:
- Range expansion:
node[01-05] -> node01, node02, node03, node04, node05
- Multiple ranges:
node[1-3,7,9-10] -> node1, node2, node3, node7, node9, node10
- Prefix/suffix:
rack[1-2]-node[1-3] -> all combinations
- Exclusion:
node[1-10] -x node[3-5]
- File input:
^/path/to/hostfile
Proposed Implementation
Hostlist Syntax
hostlist = host_term (',' host_term)*
host_term = prefix range_expr suffix
range_expr = '[' range_list ']'
range_list = range_item (',' range_item)*
range_item = NUMBER | NUMBER '-' NUMBER
prefix = STRING (any characters before '[')
suffix = STRING (any characters after ']', may include nested ranges)
Examples
# Simple range
node[1-5] # -> node1, node2, node3, node4, node5
# Zero-padded range
node[01-05] # -> node01, node02, node03, node04, node05
# Multiple values
node[1,3,5] # -> node1, node3, node5
# Mixed ranges and values
node[1-3,7,9-10] # -> node1, node2, node3, node7, node9, node10
# Multiple range groups
rack[1-2]-node[1-3] # -> rack1-node1, rack1-node2, rack1-node3,
# rack2-node1, rack2-node2, rack2-node3
# With domain suffix
web[1-3].example.com # -> web1.example.com, web2.example.com, web3.example.com
# File input (pdsh style)
^/etc/hosts.cluster # Read hosts from file, one per line
Module Structure
// src/hostlist/mod.rs
pub mod parser;
pub mod expander;
pub fn expand_hostlist(expr: &str) -> Result<Vec<String>, HostlistError>;
pub fn parse_hostfile(path: &Path) -> Result<Vec<String>, HostlistError>;
Native bssh -H Option Integration
The hostlist expression syntax will be available in native bssh mode through the -H (hosts) option. This extends the current comma-separated host list syntax to support range expressions.
Current -H Option Syntax
# Current syntax (comma-separated hosts)
bssh -H "user@host1:22,user@host2:22,user@host3:22" "uptime"
Extended -H Option Syntax with Range Expansion
# Simple range expansion
bssh -H "node[1-5]" "uptime"
# Expands to: node1, node2, node3, node4, node5
# Zero-padded range
bssh -H "node[01-05]" "uptime"
# Expands to: node01, node02, node03, node04, node05
# With user and port specification
bssh -H "admin@web[1-3].example.com:22" "uptime"
# Expands to: admin@web1.example.com:22, admin@web2.example.com:22, admin@web3.example.com:22
# Multiple ranges in single host pattern
bssh -H "rack[1-2]-node[1-3]" "uptime"
# Expands to: rack1-node1, rack1-node2, rack1-node3, rack2-node1, rack2-node2, rack2-node3
# Multiple host patterns (comma-separated)
bssh -H "web[1-3],db[1-2]" "uptime"
# Expands to: web1, web2, web3, db1, db2
# Complex combination with user/port
bssh -H "admin@app[01-03].prod.example.com:2222,root@db[1-2].prod.example.com" "uptime"
# Expands to: admin@app01.prod.example.com:2222, admin@app02.prod.example.com:2222,
# admin@app03.prod.example.com:2222, root@db1.prod.example.com, root@db2.prod.example.com
# File input
bssh -H "^/etc/cluster/hosts" "uptime"
# Reads hosts from file
# Mixed: explicit hosts and range expressions
bssh -H "gateway,node[1-3],backup" "uptime"
# Expands to: gateway, node1, node2, node3, backup
-H Option Parsing Flow
Input: "admin@web[1-3].example.com:22"
↓
Parse user prefix: "admin@"
↓
Parse hostname with range: "web[1-3].example.com"
↓
Expand range: ["web1.example.com", "web2.example.com", "web3.example.com"]
↓
Parse port suffix: ":22"
↓
Output: ["admin@web1.example.com:22", "admin@web2.example.com:22", "admin@web3.example.com:22"]
Integration with Existing -H Features
The range expansion should work seamlessly with existing -H option features:
| Feature |
Example |
Description |
--filter |
bssh -H "node[1-10]" --filter "node[1-5]" |
Expand both, then filter |
--exclude / -x |
bssh -H "node[1-10]" -x "node[3-5]" |
Expand both, then exclude |
| Jump hosts |
bssh -H "node[1-3]" -J "bastion" |
Apply jump host to all expanded hosts |
| Output dir |
bssh -H "node[1-5]" -o ./results |
Create output files for each expanded host |
Implementation Tasks
Acceptance Criteria
Edge Cases to Handle
- Empty brackets:
node[] -> error
- Reversed range:
node[5-1] -> error or reverse iteration?
- Invalid numbers:
node[a-z] -> error
- Unclosed brackets:
node[1-5 -> error
- Nested brackets:
node[[1-2]] -> error
- Overlapping ranges:
node[1-5,3-7] -> deduplicate?
- User/port with range:
user@host[1-3]:22 -> proper parsing
- Range in username:
user[1-3]@host -> should this be supported?
- Range in port:
host:22[01-03] -> should this be an error?
- IPv6 addresses:
[2001:db8::1] vs range [1-3] -> disambiguation
Technical Considerations
- Consider using
nom or pest for parsing
- Cartesian product can produce large host lists - consider limits
- Zero-padding detection: compare digit counts in range bounds
- User/port parsing must happen before/after range expansion
- IPv6 literal brackets
[...] must not conflict with range brackets
Notes
- This feature can be enabled in native bssh mode too, not just pdsh compat
- Consider making hostlist expansion a reusable library
- The
-H option integration makes this feature immediately useful without requiring pdsh compat mode
Summary
Implement pdsh-style hostlist expression syntax for specifying multiple hosts using range notation. This allows compact specification of host lists like
node[01-10]instead of listing each host individually.Parent Issue
Part of #91 (pdsh compatibility mode) - Phase 3: Hostlist Expression Support
Prerequisites
Background
pdsh uses a powerful hostlist expression syntax that allows:
node[01-05]->node01, node02, node03, node04, node05node[1-3,7,9-10]->node1, node2, node3, node7, node9, node10rack[1-2]-node[1-3]-> all combinationsnode[1-10] -x node[3-5]^/path/to/hostfileProposed Implementation
Hostlist Syntax
Examples
Module Structure
Native bssh
-HOption IntegrationThe hostlist expression syntax will be available in native bssh mode through the
-H(hosts) option. This extends the current comma-separated host list syntax to support range expressions.Current
-HOption SyntaxExtended
-HOption Syntax with Range Expansion-HOption Parsing FlowIntegration with Existing
-HFeaturesThe range expansion should work seamlessly with existing
-Hoption features:--filterbssh -H "node[1-10]" --filter "node[1-5]"--exclude/-xbssh -H "node[1-10]" -x "node[3-5]"bssh -H "node[1-3]" -J "bastion"bssh -H "node[1-5]" -o ./resultsImplementation Tasks
src/hostlist/mod.rsmodule[1-5]syntax)[01-05]->01, 02, ...)[1,3,5])[1-3,7,9-10])^filenamesyntax-Hoption in native modeuser@) before expansion:port) after expansion--filteroption--exclude/-xoption-woption in pdsh compat modeAcceptance Criteria
node[1-5]expands to 5 hostsnode[01-05]preserves zero-paddingnode[1,3,5]expands to 3 specific hostsnode[1-3,7]combines ranges and individual valuesrack[1-2]-node[1-3]produces 6 hosts (cartesian product)^/path/to/filereads hosts from file-H "user@host[1-3]:port"correctly parses user, expands hostname, preserves port-H "host[1-3],host[5-7]"expands multiple patterns-H "node[1-10]" -x "node[3-5]"correctly excludes expanded range[1-1000])Edge Cases to Handle
node[]-> errornode[5-1]-> error or reverse iteration?node[a-z]-> errornode[1-5-> errornode[[1-2]]-> errornode[1-5,3-7]-> deduplicate?user@host[1-3]:22-> proper parsinguser[1-3]@host-> should this be supported?host:22[01-03]-> should this be an error?[2001:db8::1]vs range[1-3]-> disambiguationTechnical Considerations
nomorpestfor parsing[...]must not conflict with range bracketsNotes
-Hoption integration makes this feature immediately useful without requiring pdsh compat mode