@@ -17,6 +17,8 @@ limitations under the License.
1717package controllers
1818
1919import (
20+ "bufio"
21+ "bytes"
2022 "context"
2123 "errors"
2224 "fmt"
@@ -25,6 +27,7 @@ import (
2527 "os/exec"
2628 "path"
2729 "strings"
30+ "text/template"
2831 "time"
2932
3033 "github.com/go-logr/logr"
@@ -198,6 +201,16 @@ func (r *KustomizationReconciler) sync(
198201 ), err
199202 }
200203
204+ // generate kustomization.yaml
205+ err = r .generate (kustomization , tmpDir )
206+ if err != nil {
207+ return kustomizev1 .KustomizationNotReady (
208+ kustomization ,
209+ kustomizev1 .BuildFailedReason ,
210+ "kustomize create failed" ,
211+ ), err
212+ }
213+
201214 // kustomize build
202215 err = r .build (kustomization , tmpDir )
203216 if err != nil {
@@ -263,6 +276,108 @@ func (r *KustomizationReconciler) download(kustomization kustomizev1.Kustomizati
263276 return nil
264277}
265278
279+ func (r * KustomizationReconciler ) generate (kustomization kustomizev1.Kustomization , tmpDir string ) error {
280+ if ! kustomization .Spec .Generate {
281+ return nil
282+ }
283+
284+ timeout := kustomization .GetTimeout () + (time .Second * 1 )
285+ ctx , cancel := context .WithTimeout (context .Background (), timeout )
286+ defer cancel ()
287+
288+ dirPath := path .Join (tmpDir , kustomization .Spec .Path )
289+ cmd := fmt .Sprintf ("cd %s && kustomize create --autodetect --recursive" , dirPath )
290+ command := exec .CommandContext (ctx , "/bin/sh" , "-c" , cmd )
291+ output , err := command .CombinedOutput ()
292+ if err != nil {
293+ if errors .Is (err , context .DeadlineExceeded ) {
294+ return err
295+ }
296+ return fmt .Errorf ("kustomize create failed: %s" , string (output ))
297+ }
298+
299+ if err := r .generateLabelTransformer (kustomization , dirPath ); err != nil {
300+ return err
301+ }
302+
303+ return nil
304+ }
305+
306+ func (r * KustomizationReconciler ) generateLabelTransformer (kustomization kustomizev1.Kustomization , dirPath string ) error {
307+ labelTransformer := `
308+ apiVersion: builtin
309+ kind: LabelTransformer
310+ metadata:
311+ name: labels
312+ labels:
313+ {{- range $key, $value := . }}
314+ {{ $key }}: {{ $value }}
315+ {{- end }}
316+ fieldSpecs:
317+ - path: metadata/labels
318+ create: true
319+ `
320+
321+ transformers := `
322+ transformers:
323+ - gc-labels.yaml
324+ `
325+
326+ prune := kustomization .Spec .Prune
327+ if prune == "" {
328+ return nil
329+ }
330+
331+ // transform prune into label selectors
332+ selectors := make (map [string ]string )
333+ for _ , ls := range strings .Split (prune , "," ) {
334+ if kv := strings .Split (ls , "=" ); len (kv ) == 2 {
335+ selectors [kv [0 ]] = kv [1 ]
336+ }
337+ }
338+
339+ t , err := template .New ("tmpl" ).Parse (labelTransformer )
340+ if err != nil {
341+ return fmt .Errorf ("labelTransformer template parsing failed: %w" , err )
342+ }
343+
344+ var data bytes.Buffer
345+ writer := bufio .NewWriter (& data )
346+ if err := t .Execute (writer , selectors ); err != nil {
347+ return fmt .Errorf ("labelTransformer template excution failed: %w" , err )
348+ }
349+
350+ if err := writer .Flush (); err != nil {
351+ return fmt .Errorf ("labelTransformer flush failed: %w" , err )
352+ }
353+
354+ file , err := os .Create (path .Join (dirPath , "gc-labels.yaml" ))
355+ if err != nil {
356+ return fmt .Errorf ("labelTransformer create failed: %w" , err )
357+ }
358+ defer file .Close ()
359+
360+ if _ , err := file .WriteString (data .String ()); err != nil {
361+ return fmt .Errorf ("labelTransformer write failed: %w" , err )
362+ }
363+
364+ if err := file .Sync (); err != nil {
365+ return fmt .Errorf ("labelTransformer sync failed: %w" , err )
366+ }
367+
368+ kfile , err := os .OpenFile (path .Join (dirPath , "kustomization.yaml" ), os .O_APPEND | os .O_CREATE | os .O_WRONLY , 0644 )
369+ if err != nil {
370+ return fmt .Errorf ("kustomization file open failed: %w" , err )
371+ }
372+ defer kfile .Close ()
373+
374+ if _ , err := kfile .WriteString (transformers ); err != nil {
375+ return fmt .Errorf ("kustomization file append failed: %w" , err )
376+ }
377+
378+ return nil
379+ }
380+
266381func (r * KustomizationReconciler ) build (kustomization kustomizev1.Kustomization , tmpDir string ) error {
267382 timeout := kustomization .GetTimeout () + (time .Second * 1 )
268383 ctx , cancel := context .WithTimeout (context .Background (), timeout )
0 commit comments