package main import ( "bufio" "fmt" "os" "strings" "sync" "gopkg.in/yaml.v3" ) func loadConfig(filename string, config *WindowsConfig) error { data, err := os.ReadFile(filename) if err != nil { return fmt.Errorf("failed to read config file: %w", err) } if err := yaml.Unmarshal(data, config); err != nil { return fmt.Errorf("failed to parse config file: %w", err) } return nil } func processBatchFile(batchFile string) error { file, err := os.Open(batchFile) if err != nil { return fmt.Errorf("failed to open batch file: %w", err) } defer file.Close() var configFiles []string scanner := bufio.NewScanner(file) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if line == "" || strings.HasPrefix(line, "#") { continue } configFiles = append(configFiles, line) } if err := scanner.Err(); err != nil { return fmt.Errorf("failed to read batch file: %w", err) } if len(configFiles) == 0 { return fmt.Errorf("no config files found in batch file") } fmt.Printf("Processing %d config files...\n\n", len(configFiles)) maxConcurrent := 3 semaphore := make(chan struct{}, maxConcurrent) var wg sync.WaitGroup var mu sync.Mutex results := make(map[string]error) for _, configFile := range configFiles { wg.Add(1) go func(cf string) { defer wg.Done() semaphore <- struct{}{} defer func() { <-semaphore }() fmt.Printf("Processing: %s\n", cf) config := &WindowsConfig{} if err := loadConfig(cf, config); err != nil { mu.Lock() results[cf] = err mu.Unlock() fmt.Printf("Error loading %s: %v\n", cf, err) return } if config.VMID == 0 { vmid, err := findAvailableVMID(config) if err != nil { mu.Lock() results[cf] = err mu.Unlock() fmt.Printf("Error finding VM ID for %s: %v\n", cf, err) return } config.VMID = vmid } if err := createProxmoxWindowsVM(config); err != nil { mu.Lock() results[cf] = err mu.Unlock() fmt.Printf("Error creating template from %s: %v\n", cf, err) return } mu.Lock() results[cf] = nil mu.Unlock() fmt.Printf("Successfully created template from %s\n", cf) }(configFile) } wg.Wait() fmt.Println("\n========================================") fmt.Println("Batch Processing Summary") fmt.Println("========================================") successCount := 0 failCount := 0 for configFile, err := range results { if err == nil { fmt.Printf("✓ %s - SUCCESS\n", configFile) successCount++ } else { fmt.Printf("✗ %s - FAILED: %v\n", configFile, err) failCount++ } } fmt.Printf("\nTotal: %d | Success: %d | Failed: %d\n", len(configFiles), successCount, failCount) if failCount > 0 { return fmt.Errorf("%d config(s) failed to process", failCount) } return nil }