From 68db2e593614038ff08824092954613b45c5a3a2 Mon Sep 17 00:00:00 2001 From: Giuseppe Pagano Date: Wed, 24 Jul 2024 12:17:46 +0200 Subject: [PATCH] feat: add support for json configuration --- .gitignore | 1 + config.go | 87 +++++++++++++++++++++++++++++++++++++++++++++ config.json.example | 11 ++++++ main.go | 44 ++++++++--------------- 4 files changed, 114 insertions(+), 29 deletions(-) create mode 100644 config.go create mode 100644 config.json.example diff --git a/.gitignore b/.gitignore index 8efed37..d8cb3da 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ dist/ proxmoxbackupgo_cli.exe proxmoxbackupgo.exe +config.json \ No newline at end of file diff --git a/config.go b/config.go new file mode 100644 index 0000000..9f946ad --- /dev/null +++ b/config.go @@ -0,0 +1,87 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "os" +) + +type Config struct { + BaseURL string `json:"baseurl"` + CertFingerprint string `json:"certfingerprint"` + AuthID string `json:"authid"` + Secret string `json:"secret"` + Datastore string `json:"datastore"` + Namespace string `json:"namespace"` + BackupID string `json:"backup-id"` + BackupSourceDir string `json:"backupdir"` + PxarOut string `json:"pxarout"` +} + +func (c *Config) valid() bool { + return c.BaseURL != "" && c.CertFingerprint != "" && c.AuthID != "" && c.Secret != "" && c.Datastore != "" && c.BackupSourceDir != "" +} + +func loadConfig() *Config { + // Define flags + baseURLFlag := flag.String("baseurl", "", "Base URL for the proxmox backup server, example: https://192.168.1.10:8007") + certFingerprintFlag := flag.String("certfingerprint", "", "Certificate fingerprint for SSL connection, example: ea:7d:06:f9...") + authIDFlag := flag.String("authid", "", "Authentication ID (PBS Api token)") + secretFlag := flag.String("secret", "", "Secret for authentication") + datastoreFlag := flag.String("datastore", "", "Datastore name") + namespaceFlag := flag.String("namespace", "", "Namespace (optional)") + backupIDFlag := flag.String("backup-id", "", "Backup ID (optional - if not specified, the hostname is used as the default)") + backupSourceDirFlag := flag.String("backupdir", "", "Backup source directory, must not be symlink") + pxarOutFlag := flag.String("pxarout", "", "Output PXAR archive for debug purposes (optional)") + configFile := flag.String("config", "", "Path to JSON config file") + + // Parse command line flags + flag.Parse() + + // Create a config struct and try to load values from the JSON file if specified + config := &Config{} + if *configFile != "" { + file, err := os.ReadFile(*configFile) + if err != nil { + fmt.Printf("Error reading config file: %v\n", err) + os.Exit(1) + } + err = json.Unmarshal(file, config) + if err != nil { + fmt.Printf("Error parsing config file: %v\n", err) + os.Exit(1) + } + } + + // Override JSON config with command line flags if provided + if *baseURLFlag != "" { + config.BaseURL = *baseURLFlag + } + if *certFingerprintFlag != "" { + config.CertFingerprint = *certFingerprintFlag + } + if *authIDFlag != "" { + config.AuthID = *authIDFlag + } + if *secretFlag != "" { + config.Secret = *secretFlag + } + if *datastoreFlag != "" { + config.Datastore = *datastoreFlag + } + if *namespaceFlag != "" { + config.Namespace = *namespaceFlag + } + if *backupIDFlag != "" { + config.BackupID = *backupIDFlag + } + if *backupSourceDirFlag != "" { + config.BackupSourceDir = *backupSourceDirFlag + } + if *pxarOutFlag != "" { + config.PxarOut = *pxarOutFlag + } + + return config +} diff --git a/config.json.example b/config.json.example new file mode 100644 index 0000000..fb1b3d6 --- /dev/null +++ b/config.json.example @@ -0,0 +1,11 @@ +{ + "baseurl": "https://your.pbs.installation.net:8007", + "certfingerprint": "XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX", + "authid": "MY-SECRET-AUTH-ID", + "secret": "secret-uuid", + "datastore": "myDatastore", + "backupdir": "C:", + "namespace": "", + "backup-id": "", + "pxarout": "" +} diff --git a/main.go b/main.go index dbd9573..d8f6057 100644 --- a/main.go +++ b/main.go @@ -47,27 +47,13 @@ func (c *ChunkState) Init() { c.C.New(1024 * 1024 * 4) } -func main2() { +func main() { var newchunk *atomic.Uint64 var reusechunk *atomic.Uint64 - // Define command-line flags - baseURLFlag := flag.String("baseurl", "", "Base URL for the proxmox backup server, example: https://192.168.1.10:8007") - certFingerprintFlag := flag.String("certfingerprint", "", "Certificate fingerprint for SSL connection, example: ea:7d:06:f9...") - authIDFlag := flag.String("authid", "", "Authentication ID (PBS Api token)") - secretFlag := flag.String("secret", "", "Secret for authentication") - datastoreFlag := flag.String("datastore", "", "Datastore name") - namespaceFlag := flag.String("namespace", "", "Namespace (optional)") - backupIDFlag := flag.String("backup-id", "", "Backup ID (optional - if not specified, the hostname is used as the default)") - backupSourceDirFlag := flag.String("backupdir", "", "Backup source directory, must not be symlink") - pxarOut := flag.String("pxarout", "", "Output PXAR archive for debug purposes (optional)") - - // Parse command-line flags - flag.Parse() - - // Validate required flags - if *baseURLFlag == "" || *certFingerprintFlag == "" || *authIDFlag == "" || *secretFlag == "" || *datastoreFlag == "" || *backupSourceDirFlag == "" { + cfg := loadConfig() + if ok := cfg.valid(); !ok { if runtime.GOOS == "windows" { usage := "All options are mandatory:\n" flag.VisitAll(func(f *flag.Flag) { @@ -95,18 +81,18 @@ func main2() { } client := &PBSClient{ - baseurl: *baseURLFlag, - certfingerprint: *certFingerprintFlag, //"ea:7d:06:f9:87:73:a4:72:d0:e8:05:a4:b3:3d:95:d7:0a:26:dd:6d:5c:ca:e6:99:83:e4:11:3b:5f:10:f4:4b", - authid: *authIDFlag, - secret: *secretFlag, - datastore: *datastoreFlag, - namespace: *namespaceFlag, + baseurl: cfg.BaseURL, + certfingerprint: cfg.CertFingerprint, //"ea:7d:06:f9:87:73:a4:72:d0:e8:05:a4:b3:3d:95:d7:0a:26:dd:6d:5c:ca:e6:99:83:e4:11:3b:5f:10:f4:4b", + authid: cfg.AuthID, + secret: cfg.Secret, + datastore: cfg.Datastore, + namespace: cfg.Namespace, manifest: BackupManifest{ - BackupID: *backupIDFlag, + BackupID: cfg.BackupID, }, } - backup(client, newchunk, reusechunk, pxarOut, *backupSourceDirFlag) + backup(client, newchunk, reusechunk, cfg.PxarOut, cfg.BackupSourceDir) fmt.Printf("New %d , Reused %d\n", newchunk.Load(), reusechunk.Load()) if runtime.GOOS == "windows" { @@ -116,7 +102,7 @@ func main2() { } -func backup(client *PBSClient, newchunk, reusechunk *atomic.Uint64, pxarOut *string, backupdir string) { +func backup(client *PBSClient, newchunk, reusechunk *atomic.Uint64, pxarOut string, backupdir string) { knownChunks := hashmap.New[string, bool]() fmt.Printf("Starting backup of %s\n", backupdir) @@ -163,8 +149,8 @@ func backup(client *PBSClient, newchunk, reusechunk *atomic.Uint64, pxarOut *str fmt.Printf("Known chunks: %d!\n", knownChunks.Len()) f := &os.File{} - if *pxarOut != "" { - f, _ = os.Create(*pxarOut) + if pxarOut != "" { + f, _ = os.Create(pxarOut) defer f.Close() } /**/ @@ -215,7 +201,7 @@ func backup(client *PBSClient, newchunk, reusechunk *atomic.Uint64, pxarOut *str chunkpos = pxarChunk.C.Scan(b[chunkpos:]) } - if *pxarOut != "" { + if pxarOut != "" { f.Write(b) } //