diff --git a/README.md b/README.md index de01ea9..ffdd7bc 100644 --- a/README.md +++ b/README.md @@ -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**: diff --git a/debian/changelog b/debian/changelog index c20cf6f..b5d7b33 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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 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 diff --git a/docs/DETAILS.md b/docs/DETAILS.md index b77924b..98d0b75 100644 --- a/docs/DETAILS.md +++ b/docs/DETAILS.md @@ -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 diff --git a/docs/ipng-router-backup.1 b/docs/ipng-router-backup.1 index 8d3c6d8..aed430d 100644 --- a/docs/ipng-router-backup.1 +++ b/docs/ipng-router-backup.1 @@ -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: " 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 diff --git a/src/main.go b/src/main.go index 9e5317f..2cd7384 100644 --- a/src/main.go +++ b/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) } } }