Skip to content

Commit

Permalink
feat: implement source refs for helm set-file
Browse files Browse the repository at this point in the history
In multi-source applications helm values files can come from other repos
if you use the ref syntax but it is not possible for the --set-file
param to take files from other repos via the ref syntax. This extends
the behavior to cover set-file parameters as well as the values files.
fixes argoproj#13220, refs argoproj#17822

Signed-off-by: Doug Goldstein <cardoe@cardoe.com>
  • Loading branch information
cardoe committed May 7, 2024
1 parent 20fada8 commit 13a7943
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 7 deletions.
4 changes: 2 additions & 2 deletions docs/user-guide/helm.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ source:
value: path/to/file.ext
```
!!! warning "Reference in multiple sources not supported"
Please note that using a multiple sources application will not let you load the file by reference. See [argoproj/argo-cd#13220](https://github.com/argoproj/argo-cd/issues/13220)
!!! warning "Reference in multiple sources not supported prior to ArgoCD 2.12"
Please note that using a multiple sources application will not let you load the file by reference when using ArgoCD versions prior to 2.12
## Helm Release Name
Expand Down
32 changes: 27 additions & 5 deletions reposerver/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,13 @@ func resolveReferencedSources(hasMultipleSources bool, source *v1alpha1.Applicat
return repoRefs, nil
}

for _, valueFile := range source.ValueFiles {
refFileParams := make([]string, 0)
for _, fileParam := range source.FileParameters {
refFileParams = append(refFileParams, fileParam.Path)
}
refCandidates := append(source.ValueFiles, refFileParams...)

for _, valueFile := range refCandidates {
if strings.HasPrefix(valueFile, "$") {
refVar := strings.Split(valueFile, "/")[0]

Expand Down Expand Up @@ -715,8 +721,14 @@ func (s *Service) runManifestGenAsync(ctx context.Context, repoRoot, commitSHA,
if q.HasMultipleSources {
if q.ApplicationSource.Helm != nil {

refFileParams := make([]string, 0)
for _, fileParam := range q.ApplicationSource.Helm.FileParameters {
refFileParams = append(refFileParams, fileParam.Path)
}
refCandidates := append(q.ApplicationSource.Helm.ValueFiles, refFileParams...)

// Checkout every one of the referenced sources to the target revision before generating Manifests
for _, valueFile := range q.ApplicationSource.Helm.ValueFiles {
for _, valueFile := range refCandidates {
if strings.HasPrefix(valueFile, "$") {
refVar := strings.Split(valueFile, "/")[0]

Expand Down Expand Up @@ -1168,9 +1180,19 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie
}
}
for _, p := range appHelm.FileParameters {
resolvedPath, _, err := pathutil.ResolveValueFilePathOrUrl(appPath, repoRoot, env.Envsubst(p.Path), q.GetValuesFileSchemes())
if err != nil {
return nil, fmt.Errorf("error resolving helm value file path: %w", err)
var resolvedPath pathutil.ResolvedFilePath
referencedSource := getReferencedSource(p.Path, q.RefSources)
if referencedSource != nil {
// If the $-prefixed path appears to reference another source, do env substituion _after_ resolving the source
resolvedPath, err = getResolvedRefValueFile(p.Path, env, q.GetValuesFileSchemes(), referencedSource.Repo.Repo, gitRepoPaths)
if err != nil {
return nil, fmt.Errorf("error resolving set-file path: %w", err)
}
} else {
resolvedPath, _, err = pathutil.ResolveValueFilePathOrUrl(appPath, repoRoot, env.Envsubst(p.Path), q.GetValuesFileSchemes())
if err != nil {
return nil, fmt.Errorf("error resolving helm value file path: %w", err)
}
}
templateOpts.SetFile[p.Name] = resolvedPath
}
Expand Down
47 changes: 47 additions & 0 deletions reposerver/repository/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"path"
"path/filepath"
"regexp"
"slices"
"sort"
"strings"
"sync"
Expand Down Expand Up @@ -2208,6 +2209,52 @@ func TestGenerateManifestWithAnnotatedTagsAndMultiSourceApp(t *testing.T) {
}
}

func TestGenerateMultiSourceHelmWithFileParameter(t *testing.T) {

expectedFileContent, err := os.ReadFile("../../util/helm/testdata/external/external-secret.txt")
assert.NoError(t, err)

service := newService(t, "../../util/helm/testdata")

refSources := map[string]*argoappv1.RefTarget{}

refSources["$global"] = &argoappv1.RefTarget{
TargetRevision: "HEAD",
}

manifestRequest := &apiclient.ManifestRequest{
Repo: &argoappv1.Repository{},
ApplicationSource: &argoappv1.ApplicationSource{
Ref: "$global",
Path: "./redis",
TargetRevision: "HEAD",
Helm: &argoappv1.ApplicationSourceHelm{
ValueFiles: []string{"$global/redis/values-production.yaml"},
FileParameters: []argoappv1.HelmFileParameter{{
Name: "passwordContent",
Path: "$global/external/external-secret.txt",
}},
},
},
HasMultipleSources: true,
NoCache: true,
RefSources: refSources,
}

res, err := service.GenerateManifest(context.Background(), manifestRequest)
if err != nil {
t.Errorf("unexpected %s", err)
}

assert.NoError(t, err)

// Check that any of the manifests contains the secret
idx := slices.IndexFunc(res.Manifests, func(content string) bool {
return strings.Contains(content, string(expectedFileContent))
})
assert.GreaterOrEqual(t, idx, 0, "No manifest contains the value set with the helm fileParameters")
}

func TestFindResources(t *testing.T) {
testCases := []struct {
name string
Expand Down

0 comments on commit 13a7943

Please sign in to comment.