@@ -21,15 +21,20 @@ import (
2121const (
2222 ManuallyControlledAnnKey = "ext.packaging.carvel.dev/manually-controlled"
2323
24- HelmTemplateOverlayNameKey = "ext.packaging.carvel.dev/helm-template-name"
25- HelmTemplateOverlayNameSpaceKey = "ext.packaging.carvel.dev/helm-template-namespace"
24+ HelmTemplateOverlayNameKey = "ext.packaging.carvel.dev/helm-template-name"
25+ HelmTemplateOverlayNameKeyFmt = "ext.packaging.carvel.dev/helm-%d-template-name"
26+ HelmTemplateOverlayNameSpaceKey = "ext.packaging.carvel.dev/helm-template-namespace"
27+ HelmTemplateOverlayNameSpaceKeyFmt = "ext.packaging.carvel.dev/helm-%d-template-namespace"
2628
2729 // Resulting secret names are sorted deterministically by suffix
28- ExtYttPathsFromSecretNameAnnKey = "ext.packaging.carvel.dev/ytt-paths-from-secret-name"
29- ExtHelmPathsFromSecretNameAnnKey = "ext.packaging.carvel.dev/helm-template-values-from-secret-name"
30+ ExtYttPathsFromSecretNameAnnKey = "ext.packaging.carvel.dev/ytt-paths-from-secret-name"
31+ ExtYttPathsFromSecretNameAnnKeyFmt = "ext.packaging.carvel.dev/ytt-%d-paths-from-secret-name"
32+ ExtHelmPathsFromSecretNameAnnKey = "ext.packaging.carvel.dev/helm-template-values-from-secret-name"
33+ ExtHelmPathsFromSecretNameAnnKeyFmt = "ext.packaging.carvel.dev/helm-%d-template-values-from-secret-name"
3034
3135 // ExtYttDataValuesOverlaysAnnKey if set, adds the pkgi's values secrets as overlays/paths, not as values, to the app
32- ExtYttDataValuesOverlaysAnnKey = "ext.packaging.carvel.dev/ytt-data-values-overlays"
36+ ExtYttDataValuesOverlaysAnnKey = "ext.packaging.carvel.dev/ytt-data-values-overlays"
37+ ExtYttDataValuesOverlaysAnnKeyFmt = "ext.packaging.carvel.dev/ytt-%d-data-values-overlays"
3338
3439 ExtFetchSecretNameAnnKeyFmt = "ext.packaging.carvel.dev/fetch-%d-secret-name"
3540)
@@ -101,21 +106,10 @@ func NewApp(existingApp *v1alpha1.App, pkgInstall *pkgingv1alpha1.PackageInstall
101106 }
102107
103108 templatesPatcher := templateStepsPatcher {
104- yttPatcher : & yttStepPatcher {
105- addValuesAsInlinePaths : pkgiHasAnnotation (pkgInstall , ExtYttDataValuesOverlaysAnnKey ),
106- additionalPaths : secretNamesFromAnn (pkgInstall , ExtYttPathsFromSecretNameAnnKey ),
107- },
108- helmPatcher : & helmStepPatcher {
109- additionalPaths : secretNamesFromAnn (pkgInstall , ExtHelmPathsFromSecretNameAnnKey ),
110- name : pkgiAnnotationValue (pkgInstall , HelmTemplateOverlayNameKey ),
111- namespace : pkgiAnnotationValue (pkgInstall , HelmTemplateOverlayNameSpaceKey ),
112- },
113- cuePatcher : & cueStepPatcher {},
114-
115109 templateSteps : desiredApp .Spec .Template ,
116110 values : pkgInstall .Spec .Values ,
111+ annotations : pkgInstall .Annotations ,
117112 }
118-
119113 if err := templatesPatcher .patch (); err != nil {
120114 return & v1alpha1.App {}, err
121115 }
@@ -136,63 +130,10 @@ const (
136130 stepClassCue stepClass = "cue"
137131)
138132
139- type yttStepPatcher struct {
140- addValuesAsInlinePaths bool // TODO: support multiple ytt steps
141- additionalPaths []string // TODO: support multiple ytt steps
142- }
143-
144- func (yp * yttStepPatcher ) addValues (yttStep * kcv1alpha1.AppTemplateYtt , value pkgingv1alpha1.PackageInstallValues ) {
145- if yp .addValuesAsInlinePaths {
146- addSecretAsInlinePath (& yttStep .Inline , value .SecretRef .Name )
147- } else {
148- addSecretAsValueSource (& yttStep .ValuesFrom , value .SecretRef .Name )
149- }
150- }
151-
152- func (yp * yttStepPatcher ) addPaths (yttStep * kcv1alpha1.AppTemplateYtt ) {
153- for _ , secretName := range yp .additionalPaths {
154- addSecretAsInlinePath (& yttStep .Inline , secretName )
155- }
156- }
157-
158- type helmStepPatcher struct {
159- additionalPaths []string
160- name string // TODO: support multiple helm steps
161- namespace string // TODO: support multiple helm steps
162- }
163-
164- func (hp * helmStepPatcher ) addValues (helmStep * kcv1alpha1.AppTemplateHelmTemplate , value pkgingv1alpha1.PackageInstallValues ) {
165- addSecretAsValueSource (& helmStep .ValuesFrom , value .SecretRef .Name )
166- }
167-
168- func (hp * helmStepPatcher ) addPaths (helmStep * kcv1alpha1.AppTemplateHelmTemplate ) {
169- for _ , secretName := range hp .additionalPaths {
170- addSecretAsValueSource (& helmStep .ValuesFrom , secretName )
171- }
172- }
173-
174- func (hp * helmStepPatcher ) setNameAndNamespace (helmStep * kcv1alpha1.AppTemplateHelmTemplate ) {
175- if hp .name != "" {
176- helmStep .Name = hp .name
177- }
178- if hp .namespace != "" {
179- helmStep .Namespace = hp .namespace
180- }
181- }
182-
183- type cueStepPatcher struct {}
184-
185- func (cp * cueStepPatcher ) addValues (cueStep * kcv1alpha1.AppTemplateCue , value pkgingv1alpha1.PackageInstallValues ) {
186- addSecretAsValueSource (& cueStep .ValuesFrom , value .SecretRef .Name )
187- }
188-
189133type templateStepsPatcher struct {
190134 templateSteps []kcv1alpha1.AppTemplate
191135 values []pkgingv1alpha1.PackageInstallValues
192-
193- yttPatcher * yttStepPatcher
194- helmPatcher * helmStepPatcher
195- cuePatcher * cueStepPatcher
136+ annotations map [string ]string
196137
197138 classifiedSteps [][]stepClass
198139 once sync.Once
@@ -266,6 +207,18 @@ func (p *templateStepsPatcher) defaultStepIdxs(stepIdxs []int, class stepClass)
266207}
267208
268209func (p * templateStepsPatcher ) patch () error {
210+ if err := p .patchFromValues (); err != nil {
211+ return err
212+ }
213+ p .patchFromYttAnnotations ()
214+ p .patchFromHelmAnnotations ()
215+
216+ return nil
217+ }
218+
219+ // patchFromValues patches all 'valueable' template steps with values from the
220+ // packageInstall
221+ func (p * templateStepsPatcher ) patchFromValues () error {
269222 for _ , values := range p .values {
270223 stepIdxs , err := p .defaultStepIdxs (values .TemplateSteps , stepClassValueable )
271224 if err != nil {
@@ -284,36 +237,108 @@ func (p *templateStepsPatcher) patch() error {
284237
285238 switch {
286239 case p .stepHasClass (stepIdx , stepClassYtt ):
287- p .yttPatcher .addValues (templateStep .Ytt , values )
240+ // ytt is a bit special: when we find the indexed annotation (or the
241+ // naked one for the first ytt step) to apply the values as inline
242+ // paths on the app, we do so; else, by default, we apply the pkgi's
243+ // values as values on the app.
244+ valuesAsPath := false
245+ if firstYttStepIdx , ok := p .firstOf (stepClassYtt ); ok && stepIdx == firstYttStepIdx {
246+ if _ , ok := p .annotations [ExtYttDataValuesOverlaysAnnKey ]; ok {
247+ valuesAsPath = true
248+ }
249+ }
250+ if _ , ok := p .annotations [fmt .Sprintf (ExtYttDataValuesOverlaysAnnKeyFmt , stepIdx )]; ok {
251+ valuesAsPath = true
252+ }
253+ if valuesAsPath {
254+ addSecretAsInlinePath (& templateStep .Ytt .Inline , values .SecretRef .Name )
255+ } else {
256+ addSecretAsValueSource (& templateStep .Ytt .ValuesFrom , values .SecretRef .Name )
257+ }
288258
289259 case p .stepHasClass (stepIdx , stepClassHelm ):
290- p . helmPatcher . addValues ( templateStep .HelmTemplate , values )
260+ addSecretAsValueSource ( & templateStep .HelmTemplate . ValuesFrom , values . SecretRef . Name )
291261
292262 case p .stepHasClass (stepIdx , stepClassCue ):
293- p . cuePatcher . addValues ( templateStep .Cue , values )
263+ addSecretAsValueSource ( & templateStep .Cue . ValuesFrom , values . SecretRef . Name )
294264 }
295265 }
296266 }
297267
268+ return nil
269+ }
270+
271+ // patchFromYttAnnotations patches ytt template steps with values from
272+ // annotations from the packageInstall
273+ func (p * templateStepsPatcher ) patchFromYttAnnotations () {
274+ firstYttIdx , hasYtt := p .firstOf (stepClassYtt )
275+
276+ if ! hasYtt {
277+ return
278+ }
279+
280+ patcher := func (ts * kcv1alpha1.AppTemplateYtt , pathsAnno string ) {
281+ for _ , secretName := range secretNamesFromAnn (p .annotations , pathsAnno ) {
282+ addSecretAsInlinePath (& ts .Inline , secretName )
283+ }
284+ }
285+
298286 for _ , stepIdx := range p .getClassifiedSteps (stepClassYtt ) {
299- p .yttPatcher .addPaths (p .templateSteps [stepIdx ].Ytt )
300- break // TODO: support multiple ytt steps
287+ ts := p .templateSteps [stepIdx ].Ytt
288+
289+ if stepIdx == firstYttIdx {
290+ // annotations that are not indexed are only applied to the first ytt
291+ // step, so that we are backwards compatible
292+ patcher (ts , ExtYttPathsFromSecretNameAnnKey )
293+ }
294+
295+ patcher (ts , fmt .Sprintf (ExtYttPathsFromSecretNameAnnKeyFmt , stepIdx ))
296+ }
297+ }
298+
299+ // patchFromHelmAnnotations patches helm template steps with values from
300+ // annotations from the packageInstall
301+ func (p * templateStepsPatcher ) patchFromHelmAnnotations () {
302+ firstHelmIdx , hasHelm := p .firstOf (stepClassHelm )
303+
304+ if ! hasHelm {
305+ return
301306 }
307+
308+ patcher := func (ts * kcv1alpha1.AppTemplateHelmTemplate , nameAnno , namespaceAnno , pathsAnno string ) {
309+ if name , ok := p .annotations [nameAnno ]; ok && name != "" {
310+ ts .Name = name
311+ }
312+ if namespace , ok := p .annotations [namespaceAnno ]; ok && namespace != "" {
313+ ts .Namespace = namespace
314+ }
315+ for _ , secretName := range secretNamesFromAnn (p .annotations , pathsAnno ) {
316+ addSecretAsValueSource (& ts .ValuesFrom , secretName )
317+ }
318+ }
319+
302320 for _ , stepIdx := range p .getClassifiedSteps (stepClassHelm ) {
303321 ts := p .templateSteps [stepIdx ].HelmTemplate
304- p .helmPatcher .addPaths (ts )
305- p .helmPatcher .setNameAndNamespace (ts )
306- break // TODO: support multiple helm steps
307- }
308322
309- return nil
323+ if stepIdx == firstHelmIdx {
324+ // annotations that are not indexed are only applied to the first helm
325+ // step, so that we are backwards compatible
326+ patcher (ts , HelmTemplateOverlayNameKey , HelmTemplateOverlayNameSpaceKey , ExtHelmPathsFromSecretNameAnnKey )
327+ }
328+
329+ patcher (ts ,
330+ fmt .Sprintf (HelmTemplateOverlayNameKeyFmt , stepIdx ),
331+ fmt .Sprintf (HelmTemplateOverlayNameSpaceKeyFmt , stepIdx ),
332+ fmt .Sprintf (ExtHelmPathsFromSecretNameAnnKeyFmt , stepIdx ),
333+ )
334+ }
310335}
311336
312- func secretNamesFromAnn (installedPkg * pkgingv1alpha1. PackageInstall , annKey string ) []string {
337+ func secretNamesFromAnn (annotations map [ string ] string , annKey string ) []string {
313338 var suffixes []string
314339 suffixToSecretName := map [string ]string {}
315340
316- for ann , secretName := range installedPkg . Annotations {
341+ for ann , secretName := range annotations {
317342 if ann == annKey {
318343 suffix := ""
319344 suffixToSecretName [suffix ] = secretName
@@ -334,18 +359,6 @@ func secretNamesFromAnn(installedPkg *pkgingv1alpha1.PackageInstall, annKey stri
334359 return result
335360}
336361
337- func pkgiAnnotationValue (pkgi * pkgingv1alpha1.PackageInstall , key string ) string {
338- if anno , found := pkgi .Annotations [key ]; found {
339- return anno
340- }
341- return ""
342- }
343-
344- func pkgiHasAnnotation (pkgi * pkgingv1alpha1.PackageInstall , key string ) bool {
345- _ , found := pkgi .Annotations [key ]
346- return found
347- }
348-
349362// addSecretAsInlinePath adds a secret as an inline path to the provided inline
350363// fetches. If the inline fetch is nil, it is initialized.
351364func addSecretAsInlinePath (inline * * kcv1alpha1.AppFetchInline , secretName string ) {
0 commit comments