Skip to content

Commit

Permalink
Change kustomize edit fix to split patchesStrategicMerge entries befo…
Browse files Browse the repository at this point in the history
…re converting them to patch entries.
  • Loading branch information
brianpursley committed Mar 7, 2023
1 parent 22dbd3e commit 9cd9a24
Show file tree
Hide file tree
Showing 3 changed files with 793 additions and 21 deletions.
144 changes: 132 additions & 12 deletions api/types/kustomization.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ package types

import (
"fmt"
"path/filepath"
"strings"

"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/filesys"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/yaml"
)

Expand Down Expand Up @@ -263,18 +266,9 @@ func (k *Kustomization) FixKustomizationPreMarshalling(fSys filesys.FileSystem)
k.Patches = append(k.Patches, k.PatchesJson6902...)
k.PatchesJson6902 = nil

if k.PatchesStrategicMerge != nil {
for _, patchStrategicMerge := range k.PatchesStrategicMerge {
// check this patch is file path select.
if _, err := fSys.ReadFile(string(patchStrategicMerge)); err == nil {
// path patch
k.Patches = append(k.Patches, Patch{Path: string(patchStrategicMerge)})
} else {
// inline string patch
k.Patches = append(k.Patches, Patch{Patch: string(patchStrategicMerge)})
}
}
k.PatchesStrategicMerge = nil
// Convert patchesStrategicMerge to patches.
if err := k.fixPatchesStrategicMerge(fSys); err != nil {
return err
}

// this fix is not in FixKustomizationPostUnmarshalling because
Expand All @@ -296,6 +290,38 @@ func (k *Kustomization) FixKustomizationPreMarshalling(fSys filesys.FileSystem)
return nil
}

func (k *Kustomization) fixPatchesStrategicMerge(fSys filesys.FileSystem) error {
if k.PatchesStrategicMerge == nil {
return nil
}

for _, patchStrategicMerge := range k.PatchesStrategicMerge {
// check this patch is file path select.
if _, err := fSys.ReadFile(string(patchStrategicMerge)); err == nil {
// path patch
patches, err := splitPatchStrategicMerge(patchStrategicMerge, fSys)
if err != nil {
return err
}
for _, patch := range patches {
k.Patches = append(k.Patches, Patch{Path: string(patch)})
}
} else {
// inline string patch
patches, err := splitInlinePatchStrategicMerge(patchStrategicMerge)
if err != nil {
return err
}
for _, patch := range patches {
k.Patches = append(k.Patches, Patch{Patch: string(patch)})
}
}
}
k.PatchesStrategicMerge = nil

return nil
}

func (k *Kustomization) EnforceFields() []string {
var errs []string
if k.Kind != "" && k.Kind != KustomizationKind && k.Kind != ComponentKind {
Expand All @@ -318,3 +344,97 @@ func (k *Kustomization) Unmarshal(y []byte) error {
}
return nil
}

func splitPatchStrategicMerge(p PatchStrategicMerge, fSys filesys.FileSystem) ([]PatchStrategicMerge, error) {
patchContentBytes, err := fSys.ReadFile(string(p))
if err != nil {
return nil, fmt.Errorf("failed to read file %v: %w", p, err)
}

splitPatchContent, err := kio.SplitDocuments(string(patchContentBytes))
if err != nil {
return nil, fmt.Errorf("failed to split patch file %v: %w", p, err)
}

// If the split resulted in only one document, there is nothing to do, so just return the original patch without any changes.
if len(splitPatchContent) == 1 {
return []PatchStrategicMerge{p}, nil
}

// Find the new patches, removing any empty ones.
var newPatches []string
for _, pc := range splitPatchContent {
trimmedPatchContent := strings.TrimSpace(pc)
if len(trimmedPatchContent) > 0 {
newPatches = append(newPatches, trimmedPatchContent+"\n")
}
}

// If there is only one new patch, that means there was one or more empty ones that were discarded. In this case,
// overwrite the original patch file with the new patch content and return it.
if len(newPatches) == 1 {
err := fSys.WriteFile(string(p), []byte(newPatches[0]))
if err != nil {
return nil, fmt.Errorf("failed to write file %v: %w", p, err)
}
return []PatchStrategicMerge{p}, nil
}

// If there are multiple new patches, create new patch files for each one, remove the original patch file, and
// return the list of new patch files.
result := make([]PatchStrategicMerge, len(newPatches))
for i, newPatchContent := range newPatches {
newPatchPath, err := availableFilename(string(p), i+1, fSys)
if err != nil {
return nil, fmt.Errorf("failed to find available filename for %v: %w", p, err)
}
err = fSys.WriteFile(newPatchPath, []byte(newPatchContent))
if err != nil {
return nil, fmt.Errorf("failed to write file %v: %w", newPatchPath, err)
}
result[i] = PatchStrategicMerge(newPatchPath)
}

err = fSys.RemoveAll(string(p))
if err != nil {
return nil, fmt.Errorf("failed to remove file %v: %w", p, err)
}

return result, nil
}

func splitInlinePatchStrategicMerge(p PatchStrategicMerge) ([]PatchStrategicMerge, error) {
splitPatchContent, err := kio.SplitDocuments(string(p))
if err != nil {
return nil, fmt.Errorf("failed to split inline patch: %w", err)
}

// If the split resulted in only one document, there is nothing to do, so just return the original patch without any changes.
if len(splitPatchContent) == 1 {
return []PatchStrategicMerge{p}, nil
}

// Find the new patches, removing any empty ones.
var newPatches []PatchStrategicMerge
for _, pc := range splitPatchContent {
trimmedPatchContent := strings.TrimSpace(pc)
if len(trimmedPatchContent) > 0 {
newPatches = append(newPatches, PatchStrategicMerge(trimmedPatchContent+"\n"))
}
}
return newPatches, nil
}

// availableFilename returns a filename that does not already exist in the filesystem, by repeatedly appending a suffix
// to the filename until a non-existing filename is found.
func availableFilename(originalFilename string, suffix int, fSys filesys.FileSystem) (string, error) {
ext := filepath.Ext(originalFilename)
base := strings.TrimSuffix(originalFilename, ext)
for i := 0; i < 100; i++ {
base += fmt.Sprintf("-%d", suffix)
if !fSys.Exists(base + ext) {
return base + ext, nil
}
}
return "", fmt.Errorf("unable to find available filename for %s and suffix %d", originalFilename, suffix)
}
Loading

0 comments on commit 9cd9a24

Please sign in to comment.