44 "bytes"
55 "crypto/sha256"
66 "encoding/hex"
7+ "errors"
78 "fmt"
89 "os"
910 "path"
@@ -12,6 +13,7 @@ import (
1213
1314 "sigs.k8s.io/kustomize/api/konfig"
1415 "sigs.k8s.io/kustomize/api/types"
16+ "sigs.k8s.io/kustomize/kyaml/kio"
1517 "sigs.k8s.io/kustomize/kyaml/order"
1618 kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
1719
@@ -345,43 +347,83 @@ func writeKustomization(app *v1alpha1.Application, wbc *WriteBackConfig, gitC gi
345347}
346348
347349// updateKustomizeFile reads the kustomization file at path, applies the filter to it, and writes the result back
348- // to the file. This is the same behavior as kyaml.UpdateFile, but it preserves the original order
349- // of YAML fields to minimize git diffs.
350+ // to the file. This is the same behavior as kyaml.UpdateFile, but it preserves the original order of YAML fields
351+ // and indentation of YAML sequences to minimize git diffs.
350352func updateKustomizeFile (filter kyaml.Filter , path string ) (error , bool ) {
351- // Read the yaml
352- y , err := kyaml .ReadFile (path )
353+ // Open the input file for read
354+ yRaw , err := os .ReadFile (path )
353355 if err != nil {
354356 return err , false
355357 }
356358
357- originalData , err := y .String ()
359+ // Read the yaml document from bytes
360+ originalYSlice , err := kio .FromBytes (yRaw )
358361 if err != nil {
359362 return err , false
360363 }
361364
365+ // Check that we are dealing with a single document
366+ if len (originalYSlice ) != 1 {
367+ return errors .New ("target parameter file should contain a single YAML document" ), false
368+ }
369+ originalY := originalYSlice [0 ]
370+
371+ // Get the (parsed) original document
372+ originalData , err := originalY .String ()
373+ if err != nil {
374+ return err , false
375+ }
376+
377+ // Create a reader, preserving indentation of sequences
378+ var out bytes.Buffer
379+ rw := & kio.ByteReadWriter {
380+ Reader : bytes .NewBuffer (yRaw ),
381+ Writer : & out ,
382+ PreserveSeqIndent : true ,
383+ }
384+
385+ // Read from input buffer
386+ newYSlice , err := rw .Read ()
387+ if err != nil {
388+ return err , false
389+ }
390+ // We can safely assume we have a single document from the previous check
391+ newY := newYSlice [0 ]
392+
362393 // Update the yaml
363- yCpy := y .Copy ()
364- if err := yCpy .PipeE (filter ); err != nil {
394+ if err := newY .PipeE (filter ); err != nil {
365395 return err , false
366396 }
367397
368398 // Preserve the original order of fields
369- if err := order .SyncOrder (y , yCpy ); err != nil {
399+ if err := order .SyncOrder (originalY , newY ); err != nil {
370400 return err , false
371401 }
372402
373- override , err := yCpy .String ()
403+ // Write the yaml document to the output buffer
404+ if err = rw .Write ([]* kyaml.RNode {newY }); err != nil {
405+ return err , false
406+ }
407+
408+ // newY contains metadata used by kio to preserve sequence indentation,
409+ // hence we need to parse the output buffer instead
410+ newParsedY , err := kyaml .Parse (out .String ())
411+ if err != nil {
412+ return err , false
413+ }
414+ newData , err := newParsedY .String ()
374415 if err != nil {
375416 return err , false
376417 }
377418
378- if originalData == override {
419+ // Compare the updated document with the original document
420+ if originalData == newData {
379421 log .Debugf ("target parameter file and marshaled data are the same, skipping commit." )
380422 return nil , true
381423 }
382424
383- // Write the yaml
384- if err := os .WriteFile (path , [] byte ( override ), 0600 ); err != nil {
425+ // Write to file the changes
426+ if err := os .WriteFile (path , out . Bytes ( ), 0600 ); err != nil {
385427 return err , false
386428 }
387429
0 commit comments