github.com/argoproj/argo-cd@v1.8.7/util/argo/normalizers/diff_normalizer.go (about)

     1  package normalizers
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	"github.com/argoproj/gitops-engine/pkg/diff"
     7  	jsonpatch "github.com/evanphx/json-patch"
     8  	log "github.com/sirupsen/logrus"
     9  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    10  	"k8s.io/apimachinery/pkg/runtime/schema"
    11  
    12  	"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
    13  	"github.com/argoproj/argo-cd/util/glob"
    14  )
    15  
    16  type normalizerPatch struct {
    17  	groupKind schema.GroupKind
    18  	namespace string
    19  	name      string
    20  	patch     jsonpatch.Patch
    21  }
    22  
    23  type ignoreNormalizer struct {
    24  	patches []normalizerPatch
    25  }
    26  
    27  // NewIgnoreNormalizer creates diff normalizer which removes ignored fields according to given application spec and resource overrides
    28  func NewIgnoreNormalizer(ignore []v1alpha1.ResourceIgnoreDifferences, overrides map[string]v1alpha1.ResourceOverride) (diff.Normalizer, error) {
    29  	for key, override := range overrides {
    30  		group, kind, err := getGroupKindForOverrideKey(key)
    31  		if err != nil {
    32  			log.Warn(err)
    33  		}
    34  		if len(override.IgnoreDifferences.JSONPointers) > 0 {
    35  			ignore = append(ignore, v1alpha1.ResourceIgnoreDifferences{
    36  				Group:        group,
    37  				Kind:         kind,
    38  				JSONPointers: override.IgnoreDifferences.JSONPointers,
    39  			})
    40  		}
    41  	}
    42  	patches := make([]normalizerPatch, 0)
    43  	for i := range ignore {
    44  		for _, path := range ignore[i].JSONPointers {
    45  			patchData, err := json.Marshal([]map[string]string{{"op": "remove", "path": path}})
    46  			if err != nil {
    47  				return nil, err
    48  			}
    49  			patch, err := jsonpatch.DecodePatch(patchData)
    50  			if err != nil {
    51  				return nil, err
    52  			}
    53  			patches = append(patches, normalizerPatch{
    54  				groupKind: schema.GroupKind{Group: ignore[i].Group, Kind: ignore[i].Kind},
    55  				name:      ignore[i].Name,
    56  				namespace: ignore[i].Namespace,
    57  				patch:     patch,
    58  			})
    59  		}
    60  
    61  	}
    62  	return &ignoreNormalizer{patches: patches}, nil
    63  }
    64  
    65  // Normalize removes fields from supplied resource using json paths from matching items of specified resources ignored differences list
    66  func (n *ignoreNormalizer) Normalize(un *unstructured.Unstructured) error {
    67  	matched := make([]normalizerPatch, 0)
    68  	for _, patch := range n.patches {
    69  		groupKind := un.GroupVersionKind().GroupKind()
    70  
    71  		if glob.Match(patch.groupKind.Group, groupKind.Group) &&
    72  			glob.Match(patch.groupKind.Kind, groupKind.Kind) &&
    73  			(patch.name == "" || patch.name == un.GetName()) &&
    74  			(patch.namespace == "" || patch.namespace == un.GetNamespace()) {
    75  
    76  			matched = append(matched, patch)
    77  		}
    78  	}
    79  	if len(matched) == 0 {
    80  		return nil
    81  	}
    82  
    83  	docData, err := json.Marshal(un)
    84  	if err != nil {
    85  		return err
    86  	}
    87  
    88  	for _, patch := range matched {
    89  		patchedData, err := patch.patch.Apply(docData)
    90  		if err != nil {
    91  			log.Debugf("Failed to apply normalization: %v", err)
    92  			continue
    93  		}
    94  		docData = patchedData
    95  	}
    96  
    97  	err = json.Unmarshal(docData, un)
    98  	if err != nil {
    99  		return err
   100  	}
   101  	return nil
   102  }