Skip to content

Commit

Permalink
fix(appset): Post selector with Go templates in ApplicationSet (cherr…
Browse files Browse the repository at this point in the history
…y-pick #13584) (#13824)

* fix(appset): Post selector with Go templates in ApplicationSet (#13584)

* fixes #12524

Signed-off-by: Lewis Marsden-Lambert <lewis.lambert@zserve.co.uk>

* refactor keepOnlyStringLabels function into more generic map flattening function

Signed-off-by: Lewis Marsden-Lambert <lewis.lambert@zserve.co.uk>

* updated USERS.md

Signed-off-by: Lewis Marsden-Lambert <lewis.marsden-lambert@smartpension.co.uk>

* use flatten library to replace custom flatten function

Signed-off-by: Lewis Marsden-Lambert <lewis.marsden-lambert@smartpension.co.uk>

---------

Signed-off-by: Lewis Marsden-Lambert <lewis.lambert@zserve.co.uk>
Signed-off-by: Lewis Marsden-Lambert <lewis.marsden-lambert@smartpension.co.uk>

* fixed tests

Signed-off-by: Lewis Marsden-Lambert <lewis.lambert@zserve.co.uk>

* fixed missing import

Signed-off-by: Lewis Marsden-Lambert <lewis.lambert@zserve.co.uk>

---------

Signed-off-by: Lewis Marsden-Lambert <lewis.lambert@zserve.co.uk>
Signed-off-by: Lewis Marsden-Lambert <lewis.marsden-lambert@smartpension.co.uk>
  • Loading branch information
m13t committed Jun 1, 2023
1 parent 801e195 commit 431dc6c
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 13 deletions.
1 change: 1 addition & 0 deletions USERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Schwarz IT](https://jobs.schwarz/it-mission)
1. [Skit](https://skit.ai/)
1. [Skyscanner](https://www.skyscanner.net/)
1. [Smart Pension](https://www.smartpension.co.uk/)
1. [Smilee.io](https://smilee.io)
1. [Snapp](https://snapp.ir/)
1. [Snyk](https://snyk.io/)
Expand Down
39 changes: 26 additions & 13 deletions applicationset/generators/generator_spec_processor.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package generators

import (
"fmt"
"reflect"

"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/jeremywohl/flatten"

"k8s.io/apimachinery/pkg/labels"

Expand Down Expand Up @@ -72,8 +74,17 @@ func Transform(requestedGenerator argoprojiov1alpha1.ApplicationSetGenerator, al
}
var filterParams []map[string]interface{}
for _, param := range params {
flatParam, err := flattenParameters(param)
if err != nil {
log.WithError(err).WithField("generator", g).
Error("error flattening params")
if firstError == nil {
firstError = err
}
continue
}

if requestedGenerator.Selector != nil && !selector.Matches(labels.Set(keepOnlyStringValues(param))) {
if requestedGenerator.Selector != nil && !selector.Matches(labels.Set(flatParam)) {
continue
}
filterParams = append(filterParams, param)
Expand All @@ -88,18 +99,6 @@ func Transform(requestedGenerator argoprojiov1alpha1.ApplicationSetGenerator, al
return res, firstError
}

func keepOnlyStringValues(in map[string]interface{}) map[string]string {
var out map[string]string = map[string]string{}

for key, value := range in {
if _, ok := value.(string); ok {
out[key] = value.(string)
}
}

return out
}

func GetRelevantGenerators(requestedGenerator *argoprojiov1alpha1.ApplicationSetGenerator, generators map[string]Generator) []Generator {
var res []Generator

Expand All @@ -122,6 +121,20 @@ func GetRelevantGenerators(requestedGenerator *argoprojiov1alpha1.ApplicationSet
return res
}

func flattenParameters(in map[string]interface{}) (map[string]string, error) {
flat, err := flatten.Flatten(in, "", flatten.DotStyle)
if err != nil {
return nil, err
}

out := make(map[string]string, len(flat))
for k, v := range flat {
out[k] = fmt.Sprintf("%v", v)
}

return out, nil
}

func mergeGeneratorTemplate(g Generator, requestedGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetTemplate argoprojiov1alpha1.ApplicationSetTemplate) (argoprojiov1alpha1.ApplicationSetTemplate, error) {
// Make a copy of the value from `GetTemplate()` before merge, rather than copying directly into
// the provided parameter (which will touch the original resource object returned by client-go)
Expand Down
83 changes: 83 additions & 0 deletions applicationset/generators/generator_spec_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,89 @@ func TestMatchValues(t *testing.T) {
}
}

func TestMatchValuesGoTemplate(t *testing.T) {
testCases := []struct {
name string
elements []apiextensionsv1.JSON
selector *metav1.LabelSelector
expected []map[string]interface{}
}{
{
name: "no filter",
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url"}`)}},
selector: &metav1.LabelSelector{},
expected: []map[string]interface{}{{"cluster": "cluster", "url": "url"}},
},
{
name: "nil",
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url"}`)}},
selector: nil,
expected: []map[string]interface{}{{"cluster": "cluster", "url": "url"}},
},
{
name: "values.foo should be foo but is ignore element",
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":{"foo":"bar"}}`)}},
selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"values.foo": "foo",
},
},
expected: []map[string]interface{}{},
},
{
name: "values.foo should be bar",
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":{"foo":"bar"}}`)}},
selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"values.foo": "bar",
},
},
expected: []map[string]interface{}{{"cluster": "cluster", "url": "url", "values": map[string]interface{}{"foo": "bar"}}},
},
{
name: "values.0 should be bar",
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":["bar"]}`)}},
selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"values.0": "bar",
},
},
expected: []map[string]interface{}{{"cluster": "cluster", "url": "url", "values": []interface{}{"bar"}}},
},
}

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
var listGenerator = NewListGenerator()
var data = map[string]Generator{
"List": listGenerator,
}

applicationSetInfo := argov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argov1alpha1.ApplicationSetSpec{
GoTemplate: true,
},
}

results, err := Transform(argov1alpha1.ApplicationSetGenerator{
Selector: testCase.selector,
List: &argov1alpha1.ListGenerator{
Elements: testCase.elements,
Template: emptyTemplate(),
}},
data,
emptyTemplate(),
&applicationSetInfo, nil)

assert.NoError(t, err)
assert.ElementsMatch(t, testCase.expected, results[0].Params)
})
}
}

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

0 comments on commit 431dc6c

Please sign in to comment.