edit bugs
This commit is contained in:
24
README.md
24
README.md
@@ -107,6 +107,30 @@ proxmox_host: "192.168.1.100"
|
||||
proxmox_user: "root@pam"
|
||||
```
|
||||
|
||||
### Batch mode (multiple templates):
|
||||
|
||||
Buat file batch (contoh: `batch.txt`) dengan list config files:
|
||||
```
|
||||
# Ubuntu templates
|
||||
configs/ubuntu-22.04.yaml
|
||||
configs/ubuntu-20.04.yaml
|
||||
|
||||
# Debian templates
|
||||
configs/debian-12.yaml
|
||||
configs/debian-11.yaml
|
||||
```
|
||||
|
||||
Jalankan batch:
|
||||
```bash
|
||||
proxmox-cloud-image -batch batch.txt
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Process multiple config files sekaligus
|
||||
- Max 3 concurrent jobs (parallel)
|
||||
- Auto-skip lines yang kosong atau comment (#)
|
||||
- Summary report di akhir
|
||||
|
||||
## Cloud Image URLs
|
||||
|
||||
### Ubuntu
|
||||
|
||||
13
batch.example.txt
Normal file
13
batch.example.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
# Batch file example - one config file per line
|
||||
# Lines starting with # are comments
|
||||
|
||||
# Ubuntu templates
|
||||
configs/ubuntu-22.04.yaml
|
||||
configs/ubuntu-20.04.yaml
|
||||
|
||||
# Debian templates
|
||||
configs/debian-12.yaml
|
||||
configs/debian-11.yaml
|
||||
|
||||
# CentOS templates
|
||||
configs/centos-stream-9.yaml
|
||||
85
batch.go
Normal file
85
batch.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func runBatch(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("Found %d config files to process\n\n", len(configFiles))
|
||||
|
||||
var wg sync.WaitGroup
|
||||
errors := make(chan error, len(configFiles))
|
||||
semaphore := make(chan struct{}, 3) // Max 3 concurrent jobs
|
||||
|
||||
for i, configFile := range configFiles {
|
||||
wg.Add(1)
|
||||
go func(index int, cfgFile string) {
|
||||
defer wg.Done()
|
||||
semaphore <- struct{}{}
|
||||
defer func() { <-semaphore }()
|
||||
|
||||
fmt.Printf("[%d/%d] Processing: %s\n", index+1, len(configFiles), cfgFile)
|
||||
|
||||
config := &Config{}
|
||||
if err := loadConfigFile(cfgFile, config); err != nil {
|
||||
errors <- fmt.Errorf("[%s] failed to load config: %w", cfgFile, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := run(config); err != nil {
|
||||
errors <- fmt.Errorf("[%s] failed to create template: %w", cfgFile, err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("[%d/%d] ✓ Completed: %s\n\n", index+1, len(configFiles), cfgFile)
|
||||
}(i, configFile)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
close(errors)
|
||||
|
||||
var batchErrors []error
|
||||
for err := range errors {
|
||||
batchErrors = append(batchErrors, err)
|
||||
}
|
||||
|
||||
if len(batchErrors) > 0 {
|
||||
fmt.Fprintf(os.Stderr, "\n%d template(s) failed:\n", len(batchErrors))
|
||||
for _, err := range batchErrors {
|
||||
fmt.Fprintf(os.Stderr, " - %v\n", err)
|
||||
}
|
||||
return fmt.Errorf("%d template(s) failed", len(batchErrors))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ... existing code ...
|
||||
12
configs/debian-12.yaml
Normal file
12
configs/debian-12.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
image_url: "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2"
|
||||
vm_name: "debian-12-template"
|
||||
vm_id: 0
|
||||
storage: "local-lvm"
|
||||
memory: 2048
|
||||
cores: 2
|
||||
disk_size: "20G"
|
||||
bridge: "vmbr0"
|
||||
vlan_tag: 0
|
||||
ssh_key: "/root/.ssh/id_rsa.pub"
|
||||
proxmox_host: "192.168.1.100"
|
||||
proxmox_user: "root@pam"
|
||||
12
configs/ubuntu-20.04.yaml
Normal file
12
configs/ubuntu-20.04.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
image_url: "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img"
|
||||
vm_name: "ubuntu-20.04-template"
|
||||
vm_id: 0
|
||||
storage: "local-lvm"
|
||||
memory: 2048
|
||||
cores: 2
|
||||
disk_size: "20G"
|
||||
bridge: "vmbr0"
|
||||
vlan_tag: 0
|
||||
ssh_key: "/root/.ssh/id_rsa.pub"
|
||||
proxmox_host: "192.168.1.100"
|
||||
proxmox_user: "root@pam"
|
||||
12
configs/ubuntu-22.04.yaml
Normal file
12
configs/ubuntu-22.04.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
image_url: "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
|
||||
vm_name: "ubuntu-22.04-template"
|
||||
vm_id: 0
|
||||
storage: "local-lvm"
|
||||
memory: 2048
|
||||
cores: 2
|
||||
disk_size: "20G"
|
||||
bridge: "vmbr0"
|
||||
vlan_tag: 0
|
||||
ssh_key: "/root/.ssh/id_rsa.pub"
|
||||
proxmox_host: "192.168.1.100"
|
||||
proxmox_user: "root@pam"
|
||||
13
main.go
13
main.go
@@ -25,8 +25,10 @@ type Config struct {
|
||||
func main() {
|
||||
config := &Config{}
|
||||
var configFile string
|
||||
var batchFile string
|
||||
|
||||
flag.StringVar(&configFile, "config", "", "Config file path (YAML)")
|
||||
flag.StringVar(&batchFile, "batch", "", "Batch file with multiple config paths (one per line)")
|
||||
flag.StringVar(&config.ImageURL, "image-url", "", "Cloud image URL to download")
|
||||
flag.StringVar(&config.VMName, "vm-name", "cloud-vm", "VM name")
|
||||
flag.IntVar(&config.VMID, "vm-id", 0, "VM ID (0 = auto-find from 10000+)")
|
||||
@@ -43,6 +45,17 @@ func main() {
|
||||
|
||||
flag.Parse()
|
||||
|
||||
// Batch mode
|
||||
if batchFile != "" {
|
||||
if err := runBatch(batchFile); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Batch error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("\nAll templates created successfully!")
|
||||
return
|
||||
}
|
||||
|
||||
// Single config mode
|
||||
if configFile != "" {
|
||||
if err := loadConfigFile(configFile, config); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error loading config file: %v\n", err)
|
||||
|
||||
Reference in New Issue
Block a user