add yaml include feature
This commit is contained in:
79
src/main.go
79
src/main.go
@ -9,6 +9,8 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@ -180,15 +182,15 @@ func (rb *RouterBackup) Disconnect() {
|
||||
}
|
||||
}
|
||||
|
||||
// loadConfig loads the YAML configuration file
|
||||
// loadConfig loads the YAML configuration file with !include support
|
||||
func loadConfig(configPath string) (*Config, error) {
|
||||
data, err := ioutil.ReadFile(configPath)
|
||||
processedYAML, err := processIncludes(configPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read config file %s: %v", configPath, err)
|
||||
return nil, fmt.Errorf("failed to process includes: %v", err)
|
||||
}
|
||||
|
||||
var config Config
|
||||
err = yaml.Unmarshal(data, &config)
|
||||
err = yaml.Unmarshal([]byte(processedYAML), &config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse YAML: %v", err)
|
||||
}
|
||||
@ -196,6 +198,75 @@ func loadConfig(configPath string) (*Config, error) {
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// processIncludes processes YAML files with !include directives (one level deep)
|
||||
func processIncludes(filePath string) (string, error) {
|
||||
// Read the file
|
||||
data, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read file %s: %v", filePath, err)
|
||||
}
|
||||
|
||||
content := string(data)
|
||||
|
||||
// Process !include directives
|
||||
// Match patterns like: !include path/to/file.yaml (excluding commented lines)
|
||||
includeRegex := regexp.MustCompile(`(?m)^(\s*)!include\s+(.+)$`)
|
||||
|
||||
baseDir := filepath.Dir(filePath)
|
||||
|
||||
// Process includes line by line to avoid conflicts
|
||||
lines := strings.Split(content, "\n")
|
||||
var resultLines []string
|
||||
|
||||
for _, line := range lines {
|
||||
// Check if this line matches our include pattern
|
||||
if match := includeRegex.FindStringSubmatch(line); match != nil {
|
||||
leadingWhitespace := match[1]
|
||||
includePath := strings.TrimSpace(match[2])
|
||||
|
||||
// Skip commented lines
|
||||
if strings.Contains(strings.TrimSpace(line), "#") && strings.Index(strings.TrimSpace(line), "#") < strings.Index(strings.TrimSpace(line), "!include") {
|
||||
resultLines = append(resultLines, line)
|
||||
continue
|
||||
}
|
||||
|
||||
// Remove quotes if present
|
||||
includePath = strings.Trim(includePath, "\"'")
|
||||
|
||||
// Make path relative to current config file
|
||||
if !filepath.IsAbs(includePath) {
|
||||
includePath = filepath.Join(baseDir, includePath)
|
||||
}
|
||||
|
||||
// Read the included file
|
||||
includedData, err := ioutil.ReadFile(includePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read include file %s: %v", includePath, err)
|
||||
}
|
||||
|
||||
// Use the captured leading whitespace as indentation prefix
|
||||
indentPrefix := leadingWhitespace
|
||||
|
||||
// Indent each line of included content to match the !include line's indentation
|
||||
includedLines := strings.Split(string(includedData), "\n")
|
||||
for _, includeLine := range includedLines {
|
||||
if strings.TrimSpace(includeLine) == "" {
|
||||
resultLines = append(resultLines, "")
|
||||
} else {
|
||||
resultLines = append(resultLines, indentPrefix+includeLine)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Regular line, just copy it
|
||||
resultLines = append(resultLines, line)
|
||||
}
|
||||
}
|
||||
|
||||
content = strings.Join(resultLines, "\n")
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
||||
// findDefaultSSHKey looks for default SSH keys
|
||||
func findDefaultSSHKey() string {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
|
Reference in New Issue
Block a user