diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..633e66b3 --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +PM_API_URL="https://xxxx.com:8006/api2/json" +PM_USER=user@pam +PM_PASS=password +PM_OTP=otpcode (only if required) +PM_HTTP_HEADERS=Key,Value,Key1,Value1 (only if required) diff --git a/.gitignore b/.gitignore index b64360b2..fdfd57f4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ proxmox-api-go .vagrant/ .vscode +.env diff --git a/README.md b/README.md index ed6b33e1..a58d69a0 100644 --- a/README.md +++ b/README.md @@ -16,13 +16,31 @@ go build -o proxmox-api-go ## Run +Create a local `.env` file in the root directory of the project and add the following environment variables: + +```sh +PM_API_URL="https://xxxx.com:8006/api2/json" +PM_USER=user@pam +PM_PASS=password +PM_OTP=otpcode (only if required) +PM_HTTP_HEADERS=Key,Value,Key1,Value1 (only if required) +``` + +**Note**: Do not commit your local `.env` file to version control to keep your credentials secure. + +Or export the environment variables: + ```sh export PM_API_URL="https://xxxx.com:8006/api2/json" export PM_USER=user@pam export PM_PASS=password export PM_OTP=otpcode (only if required) export PM_HTTP_HEADERS=Key,Value,Key1,Value1 (only if required) +``` +Run commands (examples, not a complete list): + +```sh ./proxmox-api-go installQemu proxmox-node-name < qemu1.json ./proxmox-api-go createQemu 123 proxmox-node-name < qemu1.json diff --git a/go.mod b/go.mod index 247b7230..3d20f5e0 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/joho/godotenv v1.5.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index a348c411..7c1e92f7 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= diff --git a/main.go b/main.go index f83daa67..16a83393 100644 --- a/main.go +++ b/main.go @@ -15,39 +15,88 @@ import ( "github.com/Telmate/proxmox-api-go/cli" _ "github.com/Telmate/proxmox-api-go/cli/command/commands" "github.com/Telmate/proxmox-api-go/proxmox" + + "github.com/joho/godotenv" ) +type AppConfig struct { + APIURL string + HTTPHeaders string + User string + Password string + OTP string + NewCLI bool +} + +func loadAppConfig() AppConfig { + newCLI := os.Getenv("NEW_CLI") == "true" + + if err := godotenv.Load(); err != nil { + log.Printf("Warning: Failed to load .env file: %v", err) + } + + return AppConfig{ + APIURL: os.Getenv("PM_API_URL"), + HTTPHeaders: os.Getenv("PM_HTTP_HEADERS"), + User: os.Getenv("PM_USER"), + Password: os.Getenv("PM_PASS"), + OTP: os.Getenv("PM_OTP"), + NewCLI: newCLI, + } +} + +func initializeProxmoxClient(config AppConfig, insecure bool, proxyURL string, taskTimeout int) (*proxmox.Client, error) { + tlsconf := &tls.Config{InsecureSkipVerify: insecure} + if !insecure { + tlsconf = nil + } + + client, err := proxmox.NewClient(config.APIURL, nil, config.HTTPHeaders, tlsconf, proxyURL, taskTimeout) + if err != nil { + return nil, err + } + + if userRequiresAPIToken(config.User) { + client.SetAPIToken(config.User, config.Password) + _, err := client.GetVersion() + if err != nil { + return nil, err + } + } else { + err = client.Login(config.User, config.Password, config.OTP) + if err != nil { + return nil, err + } + } + + return client, nil +} + func main() { - if os.Getenv("NEW_CLI") == "true" { + + config := loadAppConfig() + + if config.NewCLI { err := cli.Execute() if err != nil { failError(err) } os.Exit(0) } + + // Command-line flags insecure := flag.Bool("insecure", false, "TLS insecure mode") proxmox.Debug = flag.Bool("debug", false, "debug mode") fConfigFile := flag.String("file", "", "file to get the config from") - taskTimeout := flag.Int("timeout", 300, "api task timeout in seconds") - proxyURL := flag.String("proxy", "", "proxy url to connect to") - fvmid := flag.Int("vmid", -1, "custom vmid (instead of auto)") + taskTimeout := flag.Int("timeout", 300, "API task timeout in seconds") + proxyURL := flag.String("proxy", "", "proxy URL to connect to") + fvmid := flag.Int("vmid", -1, "custom VMID (instead of auto)") flag.Parse() - tlsconf := &tls.Config{InsecureSkipVerify: true} - if !*insecure { - tlsconf = nil - } - c, err := proxmox.NewClient(os.Getenv("PM_API_URL"), nil, os.Getenv("PM_HTTP_HEADERS"), tlsconf, *proxyURL, *taskTimeout) - failError(err) - if userRequiresAPIToken(os.Getenv("PM_USER")) { - c.SetAPIToken(os.Getenv("PM_USER"), os.Getenv("PM_PASS")) - // As test, get the version of the server - _, err := c.GetVersion() - if err != nil { - log.Fatalf("login error: %s", err) - } - } else { - err = c.Login(os.Getenv("PM_USER"), os.Getenv("PM_PASS"), os.Getenv("PM_OTP")) - failError(err) + + // Initialize Proxmox client + c, err := initializeProxmoxClient(config, *insecure, *proxyURL, *taskTimeout) + if err != nil { + log.Fatalf("Failed to initialize Proxmox client: %v", err) } vmid := *fvmid