Skip to content

Commit

Permalink
feat: allow substitutions in plugin env variables (argoproj#6097)
Browse files Browse the repository at this point in the history
* feat: allow substitutions in plugin env variables

Signed-off-by: Leah <[email protected]>

* allow all variables

Signed-off-by: Leah <[email protected]>

* add docs

Signed-off-by: Leah <[email protected]>

* better phrasing

Signed-off-by: Leah <[email protected]>

* add generic error to env var parsing

Signed-off-by: Leah <[email protected]>
  • Loading branch information
ForsakenHarmony authored Jun 4, 2021
1 parent c3b1220 commit abb0c4b
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 6 deletions.
4 changes: 3 additions & 1 deletion docs/user-guide/config-management-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Commands have access to

1. The system environment variables
2. [Standard build environment](build-environment.md)
3. Variables in the application spec:
3. Variables in the application spec (References to system and build variables will get interpolated in the variables' values):

> v1.2

Expand All @@ -44,4 +44,6 @@ spec:
env:
- name: FOO
value: bar
- name: REV
value: test-$ARGOCD_APP_REVISION
```
19 changes: 17 additions & 2 deletions reposerver/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,7 @@ func runConfigManagementPlugin(appPath string, envVars *v1alpha1.Env, q *apiclie

plugin := findPlugin(q.Plugins, q.ApplicationSource.Plugin.Name)
if plugin == nil {
return nil, fmt.Errorf("Config management plugin with name '%s' is not supported.", q.ApplicationSource.Plugin.Name)
return nil, fmt.Errorf("config management plugin with name '%s' is not supported", q.ApplicationSource.Plugin.Name)
}
env := append(os.Environ(), envVars.Environ()...)
if creds != nil {
Expand All @@ -1108,9 +1108,24 @@ func runConfigManagementPlugin(appPath string, envVars *v1alpha1.Env, q *apiclie
defer func() { _ = closer.Close() }()
env = append(env, environ...)
}
env = append(env, q.ApplicationSource.Plugin.Env.Environ()...)
env = append(env, "KUBE_VERSION="+q.KubeVersion)
env = append(env, "KUBE_API_VERSIONS="+strings.Join(q.ApiVersions, ","))

parsedEnv := make(v1alpha1.Env, len(env))
for i, v := range env {
parsedVar, err := v1alpha1.NewEnvEntry(v)
if err != nil {
return nil, fmt.Errorf("failed to parse env vars")
}
parsedEnv[i] = parsedVar
}

pluginEnv := q.ApplicationSource.Plugin.Env
for i, j := range pluginEnv {
pluginEnv[i].Value = parsedEnv.Envsubst(j.Value)
}
env = append(env, pluginEnv.Environ()...)

if plugin.Init != nil {
_, err := runCommand(*plugin.Init, appPath, env)
if err != nil {
Expand Down
14 changes: 11 additions & 3 deletions reposerver/repository/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -850,31 +850,39 @@ func TestRunCustomTool(t *testing.T) {
ApplicationSource: &argoappv1.ApplicationSource{
Plugin: &argoappv1.ApplicationSourcePlugin{
Name: "test",
Env: argoappv1.Env{
{
Name: "TEST_REVISION",
Value: "prefix-$ARGOCD_APP_REVISION",
},
},
},
},
Plugins: []*argoappv1.ConfigManagementPlugin{{
Name: "test",
Generate: argoappv1.Command{
Command: []string{"sh", "-c"},
Args: []string{`echo "{\"kind\": \"FakeObject\", \"metadata\": { \"name\": \"$ARGOCD_APP_NAME\", \"namespace\": \"$ARGOCD_APP_NAMESPACE\", \"annotations\": {\"GIT_ASKPASS\": \"$GIT_ASKPASS\", \"GIT_USERNAME\": \"$GIT_USERNAME\", \"GIT_PASSWORD\": \"$GIT_PASSWORD\"}}}"`},
Args: []string{`echo "{\"kind\": \"FakeObject\", \"metadata\": { \"name\": \"$ARGOCD_APP_NAME\", \"namespace\": \"$ARGOCD_APP_NAMESPACE\", \"annotations\": {\"GIT_ASKPASS\": \"$GIT_ASKPASS\", \"GIT_USERNAME\": \"$GIT_USERNAME\", \"GIT_PASSWORD\": \"$GIT_PASSWORD\"}, \"labels\": {\"revision\": \"$TEST_REVISION\"}}}"`},
},
}},
Repo: &argoappv1.Repository{
Username: "foo", Password: "bar",
},
})

assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, 1, len(res.Manifests))

obj := &unstructured.Unstructured{}
assert.Nil(t, json.Unmarshal([]byte(res.Manifests[0]), obj))
assert.NoError(t, json.Unmarshal([]byte(res.Manifests[0]), obj))

assert.Equal(t, obj.GetName(), "test-app")
assert.Equal(t, obj.GetNamespace(), "test-namespace")
assert.Equal(t, "git-ask-pass.sh", obj.GetAnnotations()["GIT_ASKPASS"])
assert.Equal(t, "foo", obj.GetAnnotations()["GIT_USERNAME"])
assert.Equal(t, "bar", obj.GetAnnotations()["GIT_PASSWORD"])
// Git client is mocked, so the revision is always mock.Anything
assert.Equal(t, map[string]string{"revision": "prefix-mock.Anything"}, obj.GetLabels())
}

func TestGenerateFromUTF16(t *testing.T) {
Expand Down

0 comments on commit abb0c4b

Please sign in to comment.