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

vishesh92 pushed a commit to branch add-env-vars-support
in repository https://gitbox.apache.org/repos/asf/cloudstack-cloudmonkey.git

commit 306f2a40b1e23c6ec35cb5219eb9ca30c1a343c4
Author: vishesh92 <[email protected]>
AuthorDate: Tue Sep 1 13:29:20 2026 +0530

    Add support to pass env vars to in addition to args to configure cmk
---
 README.md        | 21 +++++++++++++++++++++
 cmd/command.go   | 16 +++++++++-------
 cmk.go           | 28 ++++++++++++++++++++++++++++
 config/config.go | 20 +++++++++++++++++++-
 4 files changed, 77 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index 66f4dc6..4c3edc9 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 `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..b0ffaef 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..03b97b0 100644
--- a/cmk.go
+++ b/cmk.go
@@ -53,6 +53,34 @@ func main() {
        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.
+       if *configFilePath == "" {
+               *configFilePath = os.Getenv(config.ConfigFileEnvVar)
+       }
+       if *profile == "" {
+               *profile = os.Getenv(config.ProfileEnvVar)
+       }
+       if *acsURL == config.DefaultACSAPIEndpoint {
+               if value := os.Getenv(config.URLEnvVar); value != "" {
+                       *acsURL = value
+               }
+       }
+       if *apiKey == "" {
+               *apiKey = os.Getenv(config.APIKeyEnvVar)
+       }
+       if *secretKey == "" {
+               *secretKey = os.Getenv(config.SecretKeyEnvVar)
+       }
+       if *outputFormat == "" {
+               *outputFormat = os.Getenv(config.OutputEnvVar)
+       }
+       if !*debug {
+               if value := os.Getenv(config.DebugEnvVar); value == "true" || 
value == "1" {
+                       *debug = true
+               }
+       }
+
        cfg := config.NewConfig(configFilePath)
 
        if *showVersion {
diff --git a/config/config.go b/config/config.go
index 1fb06d8..8fd216f 100644
--- a/config/config.go
+++ b/config/config.go
@@ -56,6 +56,24 @@ 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 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 +453,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