This is an automated email from the ASF dual-hosted git repository.

borisstoyanov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack-cloudmonkey.git


The following commit(s) were added to refs/heads/main by this push:
     new 9f4cecf  Add support to pass env vars to in addition to args to 
configure cmk (#220)
9f4cecf is described below

commit 9f4cecf73204a04d67f8624a426f8c7f81f6564a
Author: Vishesh <[email protected]>
AuthorDate: Tue Sep 8 13:48:16 2026 +0530

    Add support to pass env vars to in addition to args to configure cmk (#220)
---
 README.md        | 21 +++++++++++++++++++++
 cmd/command.go   | 16 +++++++++-------
 cmk.go           | 30 ++++++++++++++++++++++++++++--
 config/config.go | 21 ++++++++++++++++++++-
 4 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md
index 66f4dc6..7f101b6 100644
--- a/README.md
+++ b/README.md
@@ -79,6 +79,27 @@ If cloudmonkey is being upgraded from a version lower than 
v6.0.0, it must be no
 that the cloudmonkey configuration path is changed from 
`~/.cloudmonkey/config` to 
 `~/.cmk/config` and a default `localcloud` profile is created. One must first 
set up basic configurations such as apikey/secretkey/username/password/url for 
the required profile(s) as required
 
+### Environment Variables
+
+`cmk` supports environment variables that mirror its CLI flags. CLI flags take
+precedence over environment variables, which take precedence over values in the
+config file.
+
+| Environment variable | Flag | Description |
+|----------------------|------|-------------|
+| `CMK_CONFIG` | `-c` | Config file path |
+| `CMK_PROFILE` | `-p` | Server profile |
+| `CMK_URL` | `-u` | CloudStack's API endpoint URL |
+| `CMK_API_KEY` | `-k` | CloudStack user's API key |
+| `CMK_SECRET_KEY` | `-s` | CloudStack user's secret key |
+| `CMK_OUTPUT` | `-o` | API response output format |
+| `CMK_DEBUG` | `-d` | Enable debug mode when set to a boolean true value 
(e.g. `true` or `1`) |
+
+`CMK_CONFIG` must point to an existing config file, and `CMK_PROFILE` must name
+an existing profile in the config; otherwise `cmk` exits with an error. A 
profile
+selected via `CMK_PROFILE` applies only to that invocation and is not persisted
+to the config file.
+
 ### License
 
 Licensed to the Apache Software Foundation (ASF) under one
diff --git a/cmd/command.go b/cmd/command.go
index 1928755..d9842c1 100644
--- a/cmd/command.go
+++ b/cmd/command.go
@@ -65,13 +65,15 @@ CloudMonkey (cmk) 🐵 is a command line interface for Apache 
CloudStack.
 Allowed flags:
   -h        Show this help message or API doc when specified after an API
   -v        Print version
-  -o        API response output format: json, text, table, column, csv
-  -p        Server profile
-  -d        Enable debug mode
-  -c        Different config file path
-  -u       CloudStack's API endpoint URL
-  -s       CloudStack user's secret Key
-  -k       CloudStack user's API Key
+  -o        API response output format: json, text, table, column, csv (env: 
CMK_OUTPUT)
+  -p        Server profile (env: CMK_PROFILE)
+  -d        Enable debug mode (env: CMK_DEBUG)
+  -c        Different config file path (env: CMK_CONFIG)
+  -u        CloudStack's API endpoint URL (env: CMK_URL)
+  -s        CloudStack user's secret key (env: CMK_SECRET_KEY)
+  -k        CloudStack user's API key (env: CMK_API_KEY)
+
+CLI flags take precedence over their environment variables.
 
 Default commands:
 %s
diff --git a/cmk.go b/cmk.go
index 9ba8073..2869d89 100644
--- a/cmk.go
+++ b/cmk.go
@@ -21,6 +21,7 @@ import (
        "flag"
        "fmt"
        "os"
+       "strconv"
        "strings"
 
        "github.com/apache/cloudstack-cloudmonkey/cli"
@@ -48,11 +49,36 @@ func main() {
        profile := flag.String("p", "", "server profile")
        configFilePath := flag.String("c", "", "config file path")
        acsURL := flag.String("u", config.DefaultACSAPIEndpoint, "cloudStack's 
API endpoint URL")
-       apiKey := flag.String("k", "", "cloudStack user's API Key")
-       secretKey := flag.String("s", "", "cloudStack user's secret Key")
+       apiKey := flag.String("k", "", "cloudStack user's API key")
+       secretKey := flag.String("s", "", "cloudStack user's secret key")
        flag.Parse()
        args := flag.Args()
 
+       // Fall back to environment variables for flags not passed on the
+       // command line; CLI flags take precedence over environment variables.
+       passedFlags := make(map[string]bool)
+       flag.Visit(func(f *flag.Flag) {
+               passedFlags[f.Name] = true
+       })
+       fallbackToEnvVar := func(flagName string, flagValue *string, envVar 
string) {
+               if !passedFlags[flagName] {
+                       if value := os.Getenv(envVar); value != "" {
+                               *flagValue = value
+                       }
+               }
+       }
+       fallbackToEnvVar("c", configFilePath, config.ConfigFileEnvVar)
+       fallbackToEnvVar("p", profile, config.ProfileEnvVar)
+       fallbackToEnvVar("u", acsURL, config.URLEnvVar)
+       fallbackToEnvVar("k", apiKey, config.APIKeyEnvVar)
+       fallbackToEnvVar("s", secretKey, config.SecretKeyEnvVar)
+       fallbackToEnvVar("o", outputFormat, config.OutputEnvVar)
+       if !passedFlags["d"] {
+               if value, err := 
strconv.ParseBool(strings.TrimSpace(os.Getenv(config.DebugEnvVar))); err == nil 
{
+                       *debug = value
+               }
+       }
+
        cfg := config.NewConfig(configFilePath)
 
        if *showVersion {
diff --git a/config/config.go b/config/config.go
index 1fb06d8..02b50f0 100644
--- a/config/config.go
+++ b/config/config.go
@@ -56,6 +56,25 @@ var nonEmptyConfigKeys = map[string]bool{
 // DefaultACSAPIEndpoint is the default API endpoint for CloudStack.
 const DefaultACSAPIEndpoint = "http://localhost:8080/client/api";
 
+// Environment variables that mirror CLI flags; flags take precedence.
+const (
+       // ConfigFileEnvVar sets the config file path when -c is not passed
+       ConfigFileEnvVar = "CMK_CONFIG"
+       // ProfileEnvVar sets the server profile when -p is not passed
+       ProfileEnvVar = "CMK_PROFILE"
+       // URLEnvVar sets CloudStack's API endpoint URL when -u is not passed
+       URLEnvVar = "CMK_URL"
+       // APIKeyEnvVar sets CloudStack user's API key when -k is not passed
+       APIKeyEnvVar = "CMK_API_KEY"
+       // SecretKeyEnvVar sets CloudStack user's secret key when -s is not 
passed
+       SecretKeyEnvVar = "CMK_SECRET_KEY"
+       // OutputEnvVar sets the API response output format when -o is not 
passed
+       OutputEnvVar = "CMK_OUTPUT"
+       // DebugEnvVar enables debug mode when set to a boolean true value
+       // (e.g. true or 1) and -d is not passed
+       DebugEnvVar = "CMK_DEBUG"
+)
+
 // ServerProfile describes a management server
 type ServerProfile struct {
        URL       string       `ini:"url"`
@@ -435,7 +454,7 @@ func NewConfig(configFilePath *string) *Config {
        if *configFilePath != "" {
                defaultConf.ConfigFile, _ = filepath.Abs(*configFilePath)
                if _, err := os.Stat(defaultConf.ConfigFile); 
os.IsNotExist(err) {
-                       fmt.Println("Config file doesn't exist.")
+                       fmt.Printf("Config file '%s' doesn't exist.\n", 
defaultConf.ConfigFile)
                        os.Exit(1)
                }
        }

Reply via email to