Allow glob of --host and --yaml; cut release 1.2.1
This commit is contained in:
@ -56,11 +56,11 @@ make build
|
||||
|
||||
```bash
|
||||
# Backup all devices (multiple YAML files are automatically merged)
|
||||
ipng-router-backup --yaml 00-device-types.yaml --yaml config.yaml --output-dir /backup
|
||||
ipng-router-backup --yaml "00-*.yaml" --yaml config.yaml --output-dir /backup
|
||||
|
||||
# Backup specific devices
|
||||
ipng-router-backup --yaml 00-device-types.yaml --yaml config.yaml --output-dir /backup \
|
||||
--host asw100
|
||||
--host "asw*"
|
||||
```
|
||||
|
||||
3. **Check output**:
|
||||
|
8
debian/changelog
vendored
8
debian/changelog
vendored
@ -1,3 +1,11 @@
|
||||
ipng-router-backup (1.2.1) stable; urgency=low
|
||||
|
||||
* Add glob pattern support for --yaml flag (e.g., --yaml "*.yaml")
|
||||
* Add glob pattern support for --host flag (e.g., --host "asw*")
|
||||
* Update documentation with glob pattern examples
|
||||
|
||||
-- Pim van Pelt <pim@ipng.ch> Sun, 07 Jul 2025 21:00:00 +0100
|
||||
|
||||
ipng-router-backup (1.2.0) stable; urgency=low
|
||||
|
||||
* Add atomic file operations with .new suffix for backup reliability
|
||||
|
@ -79,16 +79,20 @@ Files are merged automatically using mergo. Later files override earlier ones:
|
||||
```bash
|
||||
# Load multiple files - later files override earlier ones
|
||||
ipng-router-backup --yaml 00-device-types.yaml --yaml config.yaml --yaml overrides.yaml
|
||||
|
||||
# Load files using glob patterns
|
||||
ipng-router-backup --yaml "*.yaml"
|
||||
ipng-router-backup --yaml "config/*.yaml"
|
||||
```
|
||||
|
||||
## Command Line Usage
|
||||
|
||||
### Required Flags
|
||||
- **`--yaml`**: Path to YAML configuration file(s) (can be repeated)
|
||||
- **`--yaml`**: Path to YAML configuration file(s) or glob patterns (can be repeated)
|
||||
|
||||
### Optional Flags
|
||||
- **`--output-dir`**: Output directory (default: `/tmp`)
|
||||
- **`--host`**: Specific hostname(s) to process (can be repeated)
|
||||
- **`--host`**: Specific hostname(s) or glob patterns to process (can be repeated)
|
||||
- **`--password`**: SSH password
|
||||
- **`--key-file`**: SSH private key file path
|
||||
- **`--port`**: SSH port (default: `22`)
|
||||
@ -96,14 +100,14 @@ ipng-router-backup --yaml 00-device-types.yaml --yaml config.yaml --yaml overrid
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# Basic usage
|
||||
ipng-router-backup --yaml config.yaml
|
||||
# Basic usage with glob patterns
|
||||
ipng-router-backup --yaml "*.yaml"
|
||||
|
||||
# Multiple files
|
||||
ipng-router-backup --yaml 00-device-types.yaml --yaml config.yaml
|
||||
|
||||
# Specific devices only
|
||||
ipng-router-backup --yaml config.yaml --host asw100 --host core-01
|
||||
# Devices matching patterns
|
||||
ipng-router-backup --yaml config.yaml --host "asw*" --host "*switch*"
|
||||
|
||||
# Custom output directory
|
||||
ipng-router-backup --yaml config.yaml --output-dir /backup/network
|
||||
|
@ -18,7 +18,7 @@ The tool supports multiple device types with predefined command sets, SSH agent
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BR --yaml " \fICONFIG_FILE\fR"
|
||||
YAML configuration file(s) (required)
|
||||
YAML configuration file(s) or glob patterns (required)
|
||||
.TP
|
||||
.BR --output-dir " \fIDIRECTORY\fR"
|
||||
Output directory for command output files (default: /tmp)
|
||||
@ -33,7 +33,7 @@ SSH private key file path
|
||||
SSH port number (default: 22)
|
||||
.TP
|
||||
.BR --host " \fIHOSTNAME\fR"
|
||||
Specific host(s) to process (can be repeated, processes all if not specified)
|
||||
Specific host(s) or glob patterns to process (can be repeated, processes all if not specified)
|
||||
.TP
|
||||
.BR --help
|
||||
Show help message
|
||||
@ -72,9 +72,9 @@ Password authentication (--password option)
|
||||
For each device, a text file named after the hostname is created in the specified directory. Each command output is prefixed with "## COMMAND: <command_name>" for easy identification.
|
||||
.SH EXAMPLES
|
||||
.TP
|
||||
Basic usage:
|
||||
Basic usage with glob patterns:
|
||||
.EX
|
||||
ipng-router-backup --yaml /etc/ipng-router-backup/*.yaml
|
||||
ipng-router-backup --yaml "*.yaml"
|
||||
.EE
|
||||
.TP
|
||||
Custom output directory:
|
||||
@ -87,9 +87,9 @@ Using password authentication:
|
||||
ipng-router-backup --yaml config.yaml --password mysecretpass
|
||||
.EE
|
||||
.TP
|
||||
Process specific hosts only:
|
||||
Process hosts matching patterns:
|
||||
.EX
|
||||
ipng-router-backup --yaml config.yaml --host asw100 --host asw120
|
||||
ipng-router-backup --yaml config.yaml --host "asw*" --host "*switch*"
|
||||
.EE
|
||||
.SH FILES
|
||||
.TP
|
||||
|
33
src/main.go
33
src/main.go
@ -6,11 +6,12 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const Version = "1.2.0"
|
||||
const Version = "1.2.1"
|
||||
|
||||
// Config and SSH types are now in separate packages
|
||||
|
||||
@ -36,8 +37,21 @@ func main() {
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Printf("IPng Networks Router Backup v%s\n", Version)
|
||||
|
||||
// Expand glob patterns in YAML files
|
||||
var expandedYamlFiles []string
|
||||
for _, pattern := range yamlFiles {
|
||||
matches, err := filepath.Glob(pattern)
|
||||
if err != nil {
|
||||
log.Fatalf("Invalid glob pattern '%s': %v", pattern, err)
|
||||
}
|
||||
if len(matches) == 0 {
|
||||
log.Fatalf("No files matched pattern '%s'", pattern)
|
||||
}
|
||||
expandedYamlFiles = append(expandedYamlFiles, matches...)
|
||||
}
|
||||
|
||||
// Load configuration
|
||||
cfg, err := ConfigRead(yamlFiles)
|
||||
cfg, err := ConfigRead(expandedYamlFiles)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load config: %v", err)
|
||||
}
|
||||
@ -63,11 +77,16 @@ func main() {
|
||||
devicesToProcess := cfg.Devices
|
||||
if len(hostFilter) > 0 {
|
||||
devicesToProcess = make(map[string]Device)
|
||||
for _, hostname := range hostFilter {
|
||||
if deviceConfig, exists := cfg.Devices[hostname]; exists {
|
||||
devicesToProcess[hostname] = deviceConfig
|
||||
} else {
|
||||
fmt.Printf("Warning: Host '%s' not found in config file\n", hostname)
|
||||
for _, pattern := range hostFilter {
|
||||
patternMatched := false
|
||||
for hostname, deviceConfig := range cfg.Devices {
|
||||
if matched, _ := filepath.Match(pattern, hostname); matched {
|
||||
devicesToProcess[hostname] = deviceConfig
|
||||
patternMatched = true
|
||||
}
|
||||
}
|
||||
if !patternMatched {
|
||||
fmt.Printf("Warning: Host pattern '%s' did not match any devices\n", pattern)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user