Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Support for Loading Environment Variables from .env Files #311

Merged
merged 4 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -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)
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
proxmox-api-go
.vagrant/
.vscode
.env
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
JamborJan marked this conversation as resolved.
Show resolved Hide resolved

```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
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
89 changes: 69 additions & 20 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,88 @@
"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 {

Check failure on line 22 in main.go

View workflow job for this annotation

GitHub Actions / audit

exported type AppConfig should have comment or be unexported
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
Expand Down Expand Up @@ -467,7 +516,7 @@
//Users
case "getUser":
var config interface{}
userId, err := proxmox.NewUserID(flag.Args()[1])

Check failure on line 519 in main.go

View workflow job for this annotation

GitHub Actions / audit

var userId should be userID
failError(err)
config, err = proxmox.NewConfigUserFromApi(userId, c)
failError(err)
Expand All @@ -490,7 +539,7 @@
log.Printf("Error: Userid and Password required")
os.Exit(1)
}
userId, err := proxmox.NewUserID(flag.Args()[1])

Check failure on line 542 in main.go

View workflow job for this annotation

GitHub Actions / audit

var userId should be userID
failError(err)
err = proxmox.ConfigUser{
Password: proxmox.UserPassword(flag.Args()[2]),
Expand All @@ -503,7 +552,7 @@
var password proxmox.UserPassword
config, err := proxmox.NewConfigUserFromJson(GetConfig(*fConfigFile))
failError(err)
userId, err := proxmox.NewUserID(flag.Args()[1])

Check failure on line 555 in main.go

View workflow job for this annotation

GitHub Actions / audit

var userId should be userID
failError(err)
if len(flag.Args()) > 2 {
password = proxmox.UserPassword(flag.Args()[2])
Expand All @@ -516,7 +565,7 @@
log.Printf("Error: userId required")
os.Exit(1)
}
userId, err := proxmox.NewUserID(flag.Args()[1])

Check failure on line 568 in main.go

View workflow job for this annotation

GitHub Actions / audit

var userId should be userID
failError(err)
err = proxmox.ConfigUser{User: userId}.DeleteUser(c)
failError(err)
Expand Down Expand Up @@ -926,9 +975,9 @@
failError(fmt.Errorf("error: invoke with <vmID> <node> <diskID [<forceRemoval: false|true>]"))
}

vmIdUnparsed := flag.Args()[1]

Check failure on line 978 in main.go

View workflow job for this annotation

GitHub Actions / audit

var vmIdUnparsed should be vmIDUnparsed
node := flag.Args()[2]
vmId, err := strconv.Atoi(vmIdUnparsed)

Check failure on line 980 in main.go

View workflow job for this annotation

GitHub Actions / audit

var vmId should be vmID
if err != nil {
failError(fmt.Errorf("failed to convert vmId: %s to a string, error: %+v", vmIdUnparsed, err))
}
Expand Down
Loading