github.com/argoproj/argo-cd/v3@v3.2.1/util/argo/diff/ignore.go (about) 1 package diff 2 3 import ( 4 "fmt" 5 6 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1" 7 "github.com/argoproj/argo-cd/v3/util/glob" 8 ) 9 10 // IgnoreDiffConfig holds the ignore difference configurations defined in argo-cm 11 // as well as in the Application resource. 12 type IgnoreDiffConfig struct { 13 ignores []v1alpha1.ResourceIgnoreDifferences 14 overrides map[string]v1alpha1.ResourceOverride 15 } 16 17 // IgnoreDifference holds the configurations to be used while ignoring differences 18 // from live and desired states. 19 type IgnoreDifference struct { 20 // JSONPointers is a JSON path list following the format defined in RFC4627 (https://datatracker.ietf.org/doc/html/rfc6902#section-3) 21 JSONPointers []string 22 // JQPathExpressions is a JQ path list that will be evaludated during the diff process 23 JQPathExpressions []string 24 // ManagedFieldsManagers is a list of trusted managers. Fields mutated by those managers will take precedence over the 25 // desired state defined in the SCM and won't be displayed in diffs 26 ManagedFieldsManagers []string 27 } 28 29 // NewIgnoreDiffConfig creates a new NewIgnoreDiffConfig. 30 func NewIgnoreDiffConfig(ignores []v1alpha1.ResourceIgnoreDifferences, overrides map[string]v1alpha1.ResourceOverride) *IgnoreDiffConfig { 31 return &IgnoreDiffConfig{ 32 ignores: ignores, 33 overrides: overrides, 34 } 35 } 36 37 // HasIgnoreDifference will verify if the provided resource identifiers have any ignore 38 // difference configurations associated with them. It will first check if there are 39 // system level ignore difference configurations for the current group/kind. If so, this 40 // will be returned taking precedence over Application specific ignore difference 41 // configurations. 42 func (i *IgnoreDiffConfig) HasIgnoreDifference(group, kind, name, namespace string) (bool, *IgnoreDifference) { 43 result := &IgnoreDifference{} 44 found := false 45 ro, ok := i.overrides[fmt.Sprintf("%s/%s", group, kind)] 46 if ok { 47 mergeIgnoreDifferences(overrideToIgnoreDifference(ro), result) 48 found = true 49 } 50 wildOverride, ok := i.overrides["*/*"] 51 if ok { 52 mergeIgnoreDifferences(overrideToIgnoreDifference(wildOverride), result) 53 found = true 54 } 55 56 for _, ignore := range i.ignores { 57 if glob.Match(ignore.Group, group) && 58 glob.Match(ignore.Kind, kind) && 59 (ignore.Name == "" || ignore.Name == name) && 60 (ignore.Namespace == "" || ignore.Namespace == namespace) { 61 mergeIgnoreDifferences(resourceToIgnoreDifference(ignore), result) 62 found = true 63 } 64 } 65 if !found { 66 return found, nil 67 } 68 69 return found, result 70 } 71 72 func overrideToIgnoreDifference(override v1alpha1.ResourceOverride) *IgnoreDifference { 73 return &IgnoreDifference{ 74 JSONPointers: override.IgnoreDifferences.JSONPointers, 75 JQPathExpressions: override.IgnoreDifferences.JQPathExpressions, 76 ManagedFieldsManagers: override.IgnoreDifferences.ManagedFieldsManagers, 77 } 78 } 79 80 func resourceToIgnoreDifference(resource v1alpha1.ResourceIgnoreDifferences) *IgnoreDifference { 81 return &IgnoreDifference{ 82 JSONPointers: resource.JSONPointers, 83 JQPathExpressions: resource.JQPathExpressions, 84 ManagedFieldsManagers: resource.ManagedFieldsManagers, 85 } 86 } 87 88 // mergeIgnoreDifferences will merge all ignores in the given from in target 89 // skipping repeated configs. 90 func mergeIgnoreDifferences(from *IgnoreDifference, target *IgnoreDifference) { 91 for _, jqPath := range from.JQPathExpressions { 92 if !contains(target.JQPathExpressions, jqPath) { 93 target.JQPathExpressions = append(target.JQPathExpressions, jqPath) 94 } 95 } 96 for _, jsonPointer := range from.JSONPointers { 97 if !contains(target.JSONPointers, jsonPointer) { 98 target.JSONPointers = append(target.JSONPointers, jsonPointer) 99 } 100 } 101 for _, manager := range from.ManagedFieldsManagers { 102 if !contains(target.ManagedFieldsManagers, manager) { 103 target.ManagedFieldsManagers = append(target.ManagedFieldsManagers, manager) 104 } 105 } 106 } 107 108 func contains(slice []string, e string) bool { 109 for _, s := range slice { 110 if s == e { 111 return true 112 } 113 } 114 return false 115 }