Skip to content
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
19 changes: 10 additions & 9 deletions cmpserver/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/argoproj/pkg/rand"

"github.com/argoproj/argo-cd/v2/cmpserver/apiclient"
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/util/buffered_context"
"github.com/argoproj/argo-cd/v2/util/cmp"
Expand All @@ -22,8 +23,6 @@ import (
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/mattn/go-zglob"
log "github.com/sirupsen/logrus"

"github.com/argoproj/argo-cd/v2/cmpserver/apiclient"
)

// cmpTimeoutBuffer is the amount of time before the request deadline to timeout server-side work. It makes sure there's
Expand Down Expand Up @@ -311,12 +310,16 @@ func (s *Service) GetParametersAnnouncement(stream apiclient.ConfigManagementPlu
}
}()

_, err = cmp.ReceiveRepoStream(bufferedCtx, stream, workDir)
metadata, err := cmp.ReceiveRepoStream(bufferedCtx, stream, workDir)
if err != nil {
return fmt.Errorf("parameters announcement error receiving stream: %s", err)
}
appPath := filepath.Clean(filepath.Join(workDir, metadata.AppRelPath))
if !strings.HasPrefix(appPath, workDir) {
return fmt.Errorf("illegal appPath: out of workDir bound")
}

repoResponse, err := s.getParametersAnnouncement(bufferedCtx, workDir)
repoResponse, err := getParametersAnnouncement(bufferedCtx, appPath, s.initConstants.PluginConfig.Spec.Parameters.Static, s.initConstants.PluginConfig.Spec.Parameters.Dynamic)
if err != nil {
return fmt.Errorf("get parameters announcement error: %s", err)
}
Expand All @@ -328,11 +331,9 @@ func (s *Service) GetParametersAnnouncement(stream apiclient.ConfigManagementPlu
return nil
}

func (s *Service) getParametersAnnouncement(ctx context.Context, workDir string) (*apiclient.ParametersAnnouncementResponse, error) {
config := s.initConstants.PluginConfig

func getParametersAnnouncement(ctx context.Context, appDir string, staticAnnouncements []Static, command Command) (*apiclient.ParametersAnnouncementResponse, error) {
var staticParamAnnouncements []*apiclient.ParameterAnnouncement
for _, static := range config.Spec.Parameters.Static {
for _, static := range staticAnnouncements {
staticParamAnnouncements = append(staticParamAnnouncements, &apiclient.ParameterAnnouncement{
Name: static.Name,
Title: static.Title,
Expand All @@ -346,7 +347,7 @@ func (s *Service) getParametersAnnouncement(ctx context.Context, workDir string)
})
}

stdout, err := runCommand(ctx, config.Spec.Parameters.Dynamic, workDir, os.Environ())
stdout, err := runCommand(ctx, command, appDir, os.Environ())
if err != nil {
return nil, fmt.Errorf("error executing dynamic parameter output command: %s", err)
}
Expand Down
52 changes: 52 additions & 0 deletions cmpserver/plugin/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/argoproj/argo-cd/v2/cmpserver/apiclient"
"github.com/argoproj/argo-cd/v2/test"
)

Expand Down Expand Up @@ -226,3 +228,53 @@ func TestRunCommandContextTimeout(t *testing.T) {
assert.Error(t, err) // The command should time out, causing an error.
assert.Less(t, after.Sub(before), 1*time.Second)
}

func Test_getParametersAnnouncement_empty_command(t *testing.T) {
staticYAML := `
- name: static-a
- name: static-b
`
static := &[]Static{}
err := yaml.Unmarshal([]byte(staticYAML), static)
require.NoError(t, err)
command := Command{
Command: []string{"echo"},
Args: []string{`[]`},
}
res, err := getParametersAnnouncement(context.Background(), "", *static, command)
require.NoError(t, err)
assert.Equal(t, []*apiclient.ParameterAnnouncement{{Name: "static-a"}, {Name: "static-b"}}, res.ParameterAnnouncements)
}

func Test_getParametersAnnouncement_static_and_dynamic(t *testing.T) {
staticYAML := `
- name: static-a
- name: static-b
`
static := &[]Static{}
err := yaml.Unmarshal([]byte(staticYAML), static)
require.NoError(t, err)
command := Command{
Command: []string{"echo"},
Args: []string{`[{"name": "dynamic-a"}, {"name": "dynamic-b"}]`},
}
res, err := getParametersAnnouncement(context.Background(), "", *static, command)
require.NoError(t, err)
expected := []*apiclient.ParameterAnnouncement{
{Name: "static-a"},
{Name: "static-b"},
{Name: "dynamic-a"},
{Name: "dynamic-b"},
}
assert.Equal(t, expected, res.ParameterAnnouncements)
}

func Test_getParametersAnnouncement_invalid_json(t *testing.T) {
command := Command{
Command: []string{"echo"},
Args: []string{`[`},
}
_, err := getParametersAnnouncement(context.Background(), "", []Static{}, command)
assert.Error(t, err)
assert.Contains(t, err.Error(), "unexpected end of JSON input")
}
82 changes: 82 additions & 0 deletions pkg/apis/application/v1alpha1/types_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package v1alpha1

import (
"encoding/json"
fmt "fmt"
"io/ioutil"
"os"
Expand All @@ -10,6 +11,7 @@ import (
"time"

argocdcommon "github.com/argoproj/argo-cd/v2/common"
"github.com/stretchr/testify/require"
"k8s.io/utils/pointer"

"github.com/argoproj/gitops-engine/pkg/sync/common"
Expand Down Expand Up @@ -2635,3 +2637,83 @@ func TestGetCAPath(t *testing.T) {
assert.Empty(t, path)
}
}

func TestApplicationSourcePluginParameters_Environ_string(t *testing.T) {
params := ApplicationSourcePluginParameters{
{
Name: "version",
String_: pointer.String("1.2.3"),
},
}
environ, err := params.Environ()
require.NoError(t, err)
assert.Len(t, environ, 2)
assert.Contains(t, environ, "PARAM_VERSION=1.2.3")
paramsJson, err := json.Marshal(params)
require.NoError(t, err)
assert.Contains(t, environ, fmt.Sprintf("ARGOCD_APP_PARAMETERS=%s", paramsJson))
}

func TestApplicationSourcePluginParameters_Environ_array(t *testing.T) {
params := ApplicationSourcePluginParameters{
{
Name: "dependencies",
Array: []string{"redis", "minio"},
},
}
environ, err := params.Environ()
require.NoError(t, err)
assert.Len(t, environ, 3)
assert.Contains(t, environ, "PARAM_DEPENDENCIES_0=redis")
assert.Contains(t, environ, "PARAM_DEPENDENCIES_1=minio")
paramsJson, err := json.Marshal(params)
require.NoError(t, err)
assert.Contains(t, environ, fmt.Sprintf("ARGOCD_APP_PARAMETERS=%s", paramsJson))
}

func TestApplicationSourcePluginParameters_Environ_map(t *testing.T) {
params := ApplicationSourcePluginParameters{
{
Name: "helm-parameters",
Map: map[string]string{
"image.repo": "quay.io/argoproj/argo-cd",
"image.tag": "v2.4.0",
},
},
}
environ, err := params.Environ()
require.NoError(t, err)
assert.Len(t, environ, 3)
assert.Contains(t, environ, "PARAM_HELM_PARAMETERS_IMAGE_REPO=quay.io/argoproj/argo-cd")
assert.Contains(t, environ, "PARAM_HELM_PARAMETERS_IMAGE_TAG=v2.4.0")
paramsJson, err := json.Marshal(params)
require.NoError(t, err)
assert.Contains(t, environ, fmt.Sprintf("ARGOCD_APP_PARAMETERS=%s", paramsJson))
}

func TestApplicationSourcePluginParameters_Environ_all(t *testing.T) {
// Technically there's no rule against specifying multiple types as values. It's up to the CMP how to handle them.
// Name collisions can happen for the convenience env vars. When in doubt, CMP authors should use the JSON env var.
params := ApplicationSourcePluginParameters{
{
Name: "some-name",
String_: pointer.String("1.2.3"),
Array: []string{"redis", "minio"},
Map: map[string]string{
"image.repo": "quay.io/argoproj/argo-cd",
"image.tag": "v2.4.0",
},
},
}
environ, err := params.Environ()
require.NoError(t, err)
assert.Len(t, environ, 6)
assert.Contains(t, environ, "PARAM_SOME_NAME=1.2.3")
assert.Contains(t, environ, "PARAM_SOME_NAME_0=redis")
assert.Contains(t, environ, "PARAM_SOME_NAME_1=minio")
assert.Contains(t, environ, "PARAM_SOME_NAME_IMAGE_REPO=quay.io/argoproj/argo-cd")
assert.Contains(t, environ, "PARAM_SOME_NAME_IMAGE_TAG=v2.4.0")
paramsJson, err := json.Marshal(params)
require.NoError(t, err)
assert.Contains(t, environ, fmt.Sprintf("ARGOCD_APP_PARAMETERS=%s", paramsJson))
}