github.com/argoproj/argo-cd/v2@v2.10.9/applicationset/generators/matrix.go (about) 1 package generators 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/imdario/mergo" 8 9 "github.com/argoproj/argo-cd/v2/applicationset/utils" 10 argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" 11 12 log "github.com/sirupsen/logrus" 13 ) 14 15 var _ Generator = (*MatrixGenerator)(nil) 16 17 var ( 18 ErrMoreThanTwoGenerators = fmt.Errorf("found more than two generators, Matrix support only two") 19 ErrLessThanTwoGenerators = fmt.Errorf("found less than two generators, Matrix support only two") 20 ErrMoreThenOneInnerGenerators = fmt.Errorf("found more than one generator in matrix.Generators") 21 ) 22 23 type MatrixGenerator struct { 24 // The inner generators supported by the matrix generator (cluster, git, list...) 25 supportedGenerators map[string]Generator 26 } 27 28 func NewMatrixGenerator(supportedGenerators map[string]Generator) Generator { 29 m := &MatrixGenerator{ 30 supportedGenerators: supportedGenerators, 31 } 32 return m 33 } 34 35 func (m *MatrixGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]interface{}, error) { 36 37 if appSetGenerator.Matrix == nil { 38 return nil, EmptyAppSetGeneratorError 39 } 40 41 if len(appSetGenerator.Matrix.Generators) < 2 { 42 return nil, ErrLessThanTwoGenerators 43 } 44 45 if len(appSetGenerator.Matrix.Generators) > 2 { 46 return nil, ErrMoreThanTwoGenerators 47 } 48 49 res := []map[string]interface{}{} 50 51 g0, err := m.getParams(appSetGenerator.Matrix.Generators[0], appSet, nil) 52 if err != nil { 53 return nil, fmt.Errorf("error failed to get params for first generator in matrix generator: %w", err) 54 } 55 for _, a := range g0 { 56 g1, err := m.getParams(appSetGenerator.Matrix.Generators[1], appSet, a) 57 if err != nil { 58 return nil, fmt.Errorf("failed to get params for second generator in the matrix generator: %w", err) 59 } 60 for _, b := range g1 { 61 62 if appSet.Spec.GoTemplate { 63 tmp := map[string]interface{}{} 64 if err := mergo.Merge(&tmp, b, mergo.WithOverride); err != nil { 65 return nil, fmt.Errorf("failed to merge params from the second generator in the matrix generator with temp map: %w", err) 66 } 67 if err := mergo.Merge(&tmp, a, mergo.WithOverride); err != nil { 68 return nil, fmt.Errorf("failed to merge params from the second generator in the matrix generator with the first: %w", err) 69 } 70 res = append(res, tmp) 71 } else { 72 val, err := utils.CombineStringMaps(a, b) 73 if err != nil { 74 return nil, fmt.Errorf("failed to combine string maps with merging params for the matrix generator: %w", err) 75 } 76 res = append(res, utils.ConvertToMapStringInterface(val)) 77 } 78 } 79 } 80 81 return res, nil 82 } 83 84 func (m *MatrixGenerator) getParams(appSetBaseGenerator argoprojiov1alpha1.ApplicationSetNestedGenerator, appSet *argoprojiov1alpha1.ApplicationSet, params map[string]interface{}) ([]map[string]interface{}, error) { 85 matrixGen, err := getMatrixGenerator(appSetBaseGenerator) 86 if err != nil { 87 return nil, err 88 } 89 if matrixGen != nil && !appSet.Spec.ApplyNestedSelectors { 90 foundSelector := dropDisabledNestedSelectors(matrixGen.Generators) 91 if foundSelector { 92 log.Warnf("AppSet '%v' defines selector on nested matrix generator's generator without enabling them via 'spec.applyNestedSelectors', ignoring nested selectors", appSet.Name) 93 } 94 } 95 mergeGen, err := getMergeGenerator(appSetBaseGenerator) 96 if err != nil { 97 return nil, fmt.Errorf("error retrieving merge generator: %w", err) 98 } 99 if mergeGen != nil && !appSet.Spec.ApplyNestedSelectors { 100 foundSelector := dropDisabledNestedSelectors(mergeGen.Generators) 101 if foundSelector { 102 log.Warnf("AppSet '%v' defines selector on nested merge generator's generator without enabling them via 'spec.applyNestedSelectors', ignoring nested selectors", appSet.Name) 103 } 104 } 105 106 t, err := Transform( 107 argoprojiov1alpha1.ApplicationSetGenerator{ 108 List: appSetBaseGenerator.List, 109 Clusters: appSetBaseGenerator.Clusters, 110 Git: appSetBaseGenerator.Git, 111 SCMProvider: appSetBaseGenerator.SCMProvider, 112 ClusterDecisionResource: appSetBaseGenerator.ClusterDecisionResource, 113 PullRequest: appSetBaseGenerator.PullRequest, 114 Plugin: appSetBaseGenerator.Plugin, 115 Matrix: matrixGen, 116 Merge: mergeGen, 117 Selector: appSetBaseGenerator.Selector, 118 }, 119 m.supportedGenerators, 120 argoprojiov1alpha1.ApplicationSetTemplate{}, 121 appSet, 122 params) 123 124 if err != nil { 125 return nil, fmt.Errorf("child generator returned an error on parameter generation: %v", err) 126 } 127 128 if len(t) == 0 { 129 return nil, fmt.Errorf("child generator generated no parameters") 130 } 131 132 if len(t) > 1 { 133 return nil, ErrMoreThenOneInnerGenerators 134 } 135 136 return t[0].Params, nil 137 } 138 139 const maxDuration time.Duration = 1<<63 - 1 140 141 func (m *MatrixGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) time.Duration { 142 res := maxDuration 143 var found bool 144 145 for _, r := range appSetGenerator.Matrix.Generators { 146 matrixGen, _ := getMatrixGenerator(r) 147 mergeGen, _ := getMergeGenerator(r) 148 base := &argoprojiov1alpha1.ApplicationSetGenerator{ 149 List: r.List, 150 Clusters: r.Clusters, 151 Git: r.Git, 152 PullRequest: r.PullRequest, 153 Plugin: r.Plugin, 154 SCMProvider: r.SCMProvider, 155 ClusterDecisionResource: r.ClusterDecisionResource, 156 Matrix: matrixGen, 157 Merge: mergeGen, 158 } 159 generators := GetRelevantGenerators(base, m.supportedGenerators) 160 161 for _, g := range generators { 162 temp := g.GetRequeueAfter(base) 163 if temp < res && temp != NoRequeueAfter { 164 found = true 165 res = temp 166 } 167 } 168 } 169 170 if found { 171 return res 172 } else { 173 return NoRequeueAfter 174 } 175 176 } 177 178 func getMatrixGenerator(r argoprojiov1alpha1.ApplicationSetNestedGenerator) (*argoprojiov1alpha1.MatrixGenerator, error) { 179 if r.Matrix == nil { 180 return nil, nil 181 } 182 matrix, err := argoprojiov1alpha1.ToNestedMatrixGenerator(r.Matrix) 183 if err != nil { 184 return nil, err 185 } 186 return matrix.ToMatrixGenerator(), nil 187 } 188 189 func (m *MatrixGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) *argoprojiov1alpha1.ApplicationSetTemplate { 190 return &appSetGenerator.Matrix.Template 191 }