Skip to content

Commit 137a7b6

Browse files
committed
feat: get watch CLI flags from environment
1 parent d2ff0d8 commit 137a7b6

File tree

6 files changed

+141
-95
lines changed

6 files changed

+141
-95
lines changed

README.md

Lines changed: 97 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,64 @@ Argo Values is a Config Management Plugin (CMP) for Argo CD that enhances Helm-b
77
## Features
88

99
- **Dynamic Value Injection**: Merge values from ConfigMaps and Secrets into Helm template application files
10-
- **Environment Variable Substitution**: Replace `${VAR_NAME}` placeholders in application files with actual values
10+
- **Environment Variable Substitution**: Replace variable placeholders in application files with actual values
1111
- **Automatic Refresh**: Watch for ConfigMap/Secret changes and trigger application refreshes
1212
- **Helm Integration**: Full compatibility with Helm charts and templating
1313
- **Selective Processing**: Respect `.helmignore` patterns
1414

15-
## Example
15+
## Installation with ArgoCD Helm chart
1616

17-
Install ArgoCD with CMP and an example application:
18-
```bash
19-
helm upgrade --install argocd argo/argo-cd -n argocd -f values.yaml
20-
```
17+
### Configure argo-values CMP
2118

22-
values.yaml:
19+
Add the following snippet to your `values.yaml` to configure argo-values as CMP:
2320
```yaml
21+
extraObjects:
22+
- apiVersion: v1
23+
kind: ConfigMap
24+
metadata:
25+
name: argocd-cmp-plugin-config
26+
namespace: argocd
27+
data:
28+
plugin.yaml: |
29+
apiVersion: argoproj.io/v1alpha1
30+
kind: ConfigManagementPlugin
31+
metadata:
32+
name: argo-values
33+
spec:
34+
version: v1.0
35+
init:
36+
command: [argo-values]
37+
args: [init]
38+
generate:
39+
command: [argo-values]
40+
args: [generate]
41+
discover:
42+
find:
43+
command: [argo-values]
44+
args: [discover]
45+
```
46+
47+
### Add argo-values to ArgoCD application controller (optional)
2448
25-
# add argo-values as sidecar to Argo controller for automatic application refresh
49+
To trigger application refresh automatically every time a ConfigMap or Secret changed, add the following snippet to your `values.yaml`:
50+
```yaml
2651
controller:
2752
extraContainers:
2853
- name: argo-values
29-
image: argo-values:latest
54+
image: ghcr.io/hbtgmbh/argo-values:latest
3055
command: [argo-values]
3156
args: [watch]
57+
env:
58+
- name: ARGOCD_VALUES_REFRESH_SECONDS
59+
value: "3"
60+
- name: ARGOCD_VALUES_NAMESPACES
61+
value: "argocd,default"
62+
```
3263

33-
# add argo-values as CMP to Argo's repo-server
64+
### Add argo-values to ArgoCD repo server
65+
66+
To run argo-values as sidecar with the repo server, add the following snippet to your `values.yaml`:
67+
```yaml
3468
repoServer:
3569
initContainers:
3670
- name: copy-cmp-server
@@ -41,7 +75,7 @@ repoServer:
4175
mountPath: /custom-tools
4276
extraContainers:
4377
- name: argo-values
44-
image: argo-values:latest
78+
image: ghcr.io/hbtgmbh/argo-values:latest
4579
command: [/custom-tools/argocd-cmp-server]
4680
imagePullPolicy: Always
4781
securityContext:
@@ -67,72 +101,59 @@ repoServer:
67101
emptyDir: {}
68102
- name: custom-tools
69103
emptyDir: {}
104+
```
70105

71-
# the CMP configuration
72-
extraObjects:
73-
- apiVersion: v1
74-
kind: ConfigMap
75-
metadata:
76-
name: argocd-cmp-plugin-config
77-
namespace: argocd
78-
data:
79-
plugin.yaml: |
80-
apiVersion: argoproj.io/v1alpha1
81-
kind: ConfigManagementPlugin
82-
metadata:
83-
name: argo-values
84-
spec:
85-
version: v1.0
86-
init:
87-
command: [argo-values]
88-
args: [init]
89-
generate:
90-
command: [argo-values]
91-
args: [generate]
92-
discover:
93-
find:
94-
command: [argo-values]
95-
args: [discover]
96-
97-
# an example application with two additional ConfigMaps
98-
- apiVersion: argoproj.io/v1alpha1
99-
kind: Application
100-
metadata:
101-
name: nginx-example
102-
namespace: argocd
103-
spec:
104-
project: default
105-
source:
106-
repoURL: https://github.com/argoproj/argocd-example-apps.git
107-
targetRevision: HEAD
108-
path: helm-guestbook
109-
plugin:
110-
env:
111-
- name: env-configs
112-
value: test-env
113-
- name: value-configs
114-
value: test-values
115-
destination:
116-
server: https://kubernetes.default.svc # Targets the same cluster as Argo CD
117-
namespace: default
118-
- apiVersion: v1
119-
kind: ConfigMap
120-
metadata:
121-
name: test-env
122-
namespace: default
123-
data:
124-
values.yaml: |
125-
cpu: "100m"
126-
- apiVersion: v1
127-
kind: ConfigMap
128-
metadata:
129-
name: test-values
130-
namespace: default
131-
data:
132-
values.yaml: |
133-
resources:
134-
requests:
135-
cpu: "${CPU}"
106+
## Examples
107+
108+
### Add additional values.yaml from ConfigMap to Helm chart
109+
110+
```yaml
111+
apiVersion: argoproj.io/v1alpha1
112+
kind: Application
113+
metadata:
114+
name: nginx-example
115+
namespace: argocd
116+
spec:
117+
project: default
118+
source:
119+
repoURL: https://github.com/argoproj/argocd-example-apps.git
120+
targetRevision: HEAD
121+
path: helm-guestbook
122+
plugin:
123+
env:
124+
- name: value-configs
125+
value: default/application-values # <- list of ConfigMaps or namespace/ConfigMap separated by ","
126+
- name: env-configs
127+
value: default/application-variables # <- list of ConfigMaps or namespace/ConfigMap separated by ","
128+
```
129+
130+
Every ConfigMap from `value-configs` or Secret from `value-secrets` will be added directly to the Helm templates of the application:
131+
132+
```yaml
133+
apiVersion: v1
134+
kind: ConfigMap
135+
metadata:
136+
name: application-values
137+
namespace: default
138+
data:
139+
# additional values.yaml
140+
values.yaml: |
141+
resources:
142+
requests:
143+
cpu: "${CPU}"
144+
memory: "100Mi"
145+
```
146+
147+
All values from `env-configs` or `value-secrets` are available as environment variables and substituted in the Helm templates of the application:
148+
149+
```yaml
150+
apiVersion: v1
151+
kind: ConfigMap
152+
metadata:
153+
name: application-variables
154+
namespace: default
155+
data:
156+
cpu: "123m"
136157
```
137158

138159
## License

cmd/argo-values/main.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,23 @@ var RootCmd = &cobra.Command{
2525

2626
func init() {
2727
// Add global flags
28-
RootCmd.PersistentFlags().StringVarP(&config.LogLevel, "log-level", "l", env.GetString("LOG_LEVEL", "debug"), "Log level (debug, info, warn, error, fatal, panic)")
29-
RootCmd.PersistentFlags().StringVar(&config.LogFormat, "log-format", env.GetString("LOG_FORMAT", "json"), "Log format (text, json)")
30-
RootCmd.PersistentFlags().StringVar(&config.LogOutput, "log-output", env.GetString("LOG_OUTPUT", "stdout"), "Log output (stderr, stdout)")
31-
32-
RootCmd.PersistentFlags().StringVarP(&config.KubeConfigPath, "kubeconfig", "k", "", "Path to kubeconfig file")
33-
34-
RootCmd.PersistentFlags().StringVarP(&config.ValuesFileName, "file-values", "v", "app-values.yaml", "Path to values file")
35-
RootCmd.PersistentFlags().StringVarP(&config.TargetDirectory, "file-target", "t", ".", "Path to application files")
36-
37-
RootCmd.PersistentFlags().BoolVarP(&config.DryRun, "dry-run", "d", false, "dry-run enabled (true, false)")
28+
RootCmd.PersistentFlags().StringVarP(&config.LogLevel, "log-level", "l",
29+
env.GetString("LOG_LEVEL", "debug"), "Log level (debug, info, warn, error, fatal, panic)")
30+
RootCmd.PersistentFlags().StringVar(&config.LogFormat, "log-format",
31+
env.GetString("LOG_FORMAT", "json"), "Log format (text, json)")
32+
RootCmd.PersistentFlags().StringVar(&config.LogOutput, "log-output",
33+
env.GetString("LOG_OUTPUT", "stdout"), "Log output (stderr, stdout)")
34+
35+
RootCmd.PersistentFlags().StringVarP(&config.KubeConfigPath, "kubeconfig", "k",
36+
"", "Path to kubeconfig file")
37+
38+
RootCmd.PersistentFlags().StringVarP(&config.ValuesFileName, "file-values", "v",
39+
"app-values.yaml", "Path to values file")
40+
RootCmd.PersistentFlags().StringVarP(&config.TargetDirectory, "file-target", "t",
41+
".", "Path to application files")
42+
43+
RootCmd.PersistentFlags().BoolVarP(&config.DryRun, "dry-run", "d",
44+
false, "dry-run enabled (true, false)")
3845

3946
// Add subcommands
4047
RootCmd.AddCommand(commands.DiscoverCommand)

internal/commands/generate.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ var (
1616
)
1717

1818
func init() {
19-
GenerateCmd.Flags().StringVar(&appName, "app-name", env.GetString("ARGOCD_APP_NAME", ""), "Name of the Argo CD application")
20-
GenerateCmd.Flags().StringVar(&appNamespace, "app-namespace", env.GetString("ARGOCD_APP_NAMESPACE", ""), "Namespace of the Argo CD application")
19+
GenerateCmd.Flags().StringVar(&appName, "app-name",
20+
env.GetString("ARGOCD_APP_NAME", ""), "Name of the Argo CD application")
21+
GenerateCmd.Flags().StringVar(&appNamespace, "app-namespace",
22+
env.GetString("ARGOCD_APP_NAMESPACE", "argocd"), "Namespace of the Argo CD application")
2123
}
2224

2325
var GenerateCmd = &cobra.Command{

internal/commands/init.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@ var (
2323
)
2424

2525
func init() {
26-
InitCmd.Flags().StringArrayVar(&valueConfigs, "value-maps", []string{}, "ConfigMaps containing values to merge into the application files")
27-
InitCmd.Flags().StringArrayVar(&envConfigs, "env-maps", []string{}, "ConfigMaps containing environment variables to inject into application files")
28-
InitCmd.Flags().StringArrayVar(&valueSecrets, "value-secrets", []string{}, "Secrets containing values to merge into the application files")
29-
InitCmd.Flags().StringArrayVar(&envSecrets, "env-secrets", []string{}, "Secrets containing environment variables to inject into application files")
26+
InitCmd.Flags().StringArrayVar(&valueConfigs, "value-maps",
27+
[]string{}, "ConfigMaps containing values to merge into the application files")
28+
InitCmd.Flags().StringArrayVar(&envConfigs, "env-maps",
29+
[]string{}, "ConfigMaps containing environment variables to inject into application files")
30+
InitCmd.Flags().StringArrayVar(&valueSecrets, "value-secrets",
31+
[]string{}, "Secrets containing values to merge into the application files")
32+
InitCmd.Flags().StringArrayVar(&envSecrets, "env-secrets",
33+
[]string{}, "Secrets containing environment variables to inject into application files")
3034
}
3135

3236
var InitCmd = &cobra.Command{

internal/commands/watch.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ var (
2424
)
2525

2626
func init() {
27-
WatchCmd.Flags().DurationVarP(&debounceDuration, "event-interval", "i", 2*time.Second, "Debounce interval for resource change events")
28-
WatchCmd.Flags().StringArrayVar(&namespaces, "namespaces", config.GetArrayFromEnv("ARGOCD_VALUES_NAMESPACES", []string{"argocd", "default"}), "Namespaces to watch for resource changes")
27+
WatchCmd.Flags().DurationVarP(&debounceDuration, "refresh-interval", "i",
28+
config.GetSecondsFromEnv("ARGOCD_VALUES_REFRESH_SECONDS", 2*time.Second), "Debounce interval for resource change events")
29+
WatchCmd.Flags().StringArrayVar(&namespaces, "namespaces",
30+
config.GetArrayFromEnv("ARGOCD_VALUES_NAMESPACES", []string{"argocd", "default"}), "Namespaces to watch for resource changes")
2931
}
3032

3133
var WatchCmd = &cobra.Command{
@@ -36,7 +38,7 @@ Argo CD applications when their dependent resources (ConfigMaps, Secrets) change
3638
3739
This command establishes watches on ConfigMaps and Secrets in the specified namespaces
3840
and triggers application refreshes when any watched resource changes. The refresh
39-
debounce multiple rapid changes according to the event-interval flag.
41+
debounce multiple rapid changes according to the refresh-interval flag.
4042
4143
The command maintains a mapping of which applications depend on which resources and
4244
only refreshes applications that are affected by the specific resource changes.

internal/config/plugin.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import (
55
"encoding/json"
66
"fmt"
77
"os"
8+
"strconv"
89
"strings"
10+
"time"
911

1012
"k8s.io/utils/env"
1113
)
@@ -76,6 +78,14 @@ func GetStringFromEnv(name string, def string) string {
7678
return def
7779
}
7880

81+
func GetSecondsFromEnv(name string, def time.Duration) time.Duration {
82+
secondsFromEnv := GetStringFromEnv(name, "")
83+
if seconds, err := strconv.Atoi(secondsFromEnv); err == nil {
84+
return time.Duration(seconds) * time.Second
85+
}
86+
return def
87+
}
88+
7989
func GetArrayFromEnv(name string, def []string) []string {
8090
arrayFromEnv := strings.Split(GetStringFromEnv(name, ""), ",")
8191
arrayFiltered := utils.NonEmpty(arrayFromEnv)

0 commit comments

Comments
 (0)