github.com/argoproj/argo-cd/v3@v3.2.1/applicationset/utils/createOrUpdate_test.go (about)

     1  package utils
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  	"github.com/stretchr/testify/require"
     8  	"gopkg.in/yaml.v3"
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  
    11  	"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
    12  	"github.com/argoproj/argo-cd/v3/util/argo/normalizers"
    13  )
    14  
    15  func Test_applyIgnoreDifferences(t *testing.T) {
    16  	t.Parallel()
    17  
    18  	appMeta := metav1.TypeMeta{
    19  		APIVersion: v1alpha1.ApplicationSchemaGroupVersionKind.GroupVersion().String(),
    20  		Kind:       v1alpha1.ApplicationSchemaGroupVersionKind.Kind,
    21  	}
    22  	testCases := []struct {
    23  		name              string
    24  		ignoreDifferences v1alpha1.ApplicationSetIgnoreDifferences
    25  		foundApp          string
    26  		generatedApp      string
    27  		expectedApp       string
    28  	}{
    29  		{
    30  			name: "empty ignoreDifferences",
    31  			foundApp: `
    32  spec: {}`,
    33  			generatedApp: `
    34  spec: {}`,
    35  			expectedApp: `
    36  spec: {}`,
    37  		},
    38  		{
    39  			// For this use case: https://github.com/argoproj/argo-cd/issues/9101#issuecomment-1191138278
    40  			name: "ignore target revision with jq",
    41  			ignoreDifferences: v1alpha1.ApplicationSetIgnoreDifferences{
    42  				{JQPathExpressions: []string{".spec.source.targetRevision"}},
    43  			},
    44  			foundApp: `
    45  spec:
    46    source:
    47      targetRevision: foo`,
    48  			generatedApp: `
    49  spec:
    50    source:
    51      targetRevision: bar`,
    52  			expectedApp: `
    53  spec:
    54    source:
    55      targetRevision: foo`,
    56  		},
    57  		{
    58  			// For this use case: https://github.com/argoproj/argo-cd/issues/9101#issuecomment-1103593714
    59  			name: "ignore helm parameter with jq",
    60  			ignoreDifferences: v1alpha1.ApplicationSetIgnoreDifferences{
    61  				{JQPathExpressions: []string{`.spec.source.helm.parameters | select(.name == "image.tag")`}},
    62  			},
    63  			foundApp: `
    64  spec:
    65    source:
    66      helm:
    67        parameters:
    68        - name: image.tag
    69          value: test
    70        - name: another
    71          value: value`,
    72  			generatedApp: `
    73  spec:
    74    source:
    75      helm:
    76        parameters:
    77        - name: image.tag
    78          value: v1.0.0
    79        - name: another
    80          value: value`,
    81  			expectedApp: `
    82  spec:
    83    source:
    84      helm:
    85        parameters:
    86        - name: image.tag
    87          value: test
    88        - name: another
    89          value: value`,
    90  		},
    91  		{
    92  			// For this use case: https://github.com/argoproj/argo-cd/issues/9101#issuecomment-1191138278
    93  			name: "ignore auto-sync in appset when it's not in the cluster with jq",
    94  			ignoreDifferences: v1alpha1.ApplicationSetIgnoreDifferences{
    95  				{JQPathExpressions: []string{".spec.syncPolicy.automated"}},
    96  			},
    97  			foundApp: `
    98  spec:
    99    syncPolicy:
   100      retry:
   101        limit: 5`,
   102  			generatedApp: `
   103  spec:
   104    syncPolicy:
   105      automated:
   106        selfHeal: true
   107      retry:
   108        limit: 5`,
   109  			expectedApp: `
   110  spec:
   111    syncPolicy:
   112      retry:
   113        limit: 5`,
   114  		},
   115  		{
   116  			name: "ignore auto-sync in the cluster when it's not in the appset with jq",
   117  			ignoreDifferences: v1alpha1.ApplicationSetIgnoreDifferences{
   118  				{JQPathExpressions: []string{".spec.syncPolicy.automated"}},
   119  			},
   120  			foundApp: `
   121  spec:
   122    syncPolicy:
   123      automated:
   124        selfHeal: true
   125      retry:
   126        limit: 5`,
   127  			generatedApp: `
   128  spec:
   129    syncPolicy:
   130      retry:
   131        limit: 5`,
   132  			expectedApp: `
   133  spec:
   134    syncPolicy:
   135      automated:
   136        selfHeal: true
   137      retry:
   138        limit: 5`,
   139  		},
   140  		{
   141  			// For this use case: https://github.com/argoproj/argo-cd/issues/9101#issuecomment-1420656537
   142  			name: "ignore a one-off annotation with jq",
   143  			ignoreDifferences: v1alpha1.ApplicationSetIgnoreDifferences{
   144  				{JQPathExpressions: []string{`.metadata.annotations | select(.["foo.bar"] == "baz")`}},
   145  			},
   146  			foundApp: `
   147  metadata:
   148    annotations:
   149      foo.bar: baz
   150      some.other: annotation`,
   151  			generatedApp: `
   152  metadata:
   153    annotations:
   154      some.other: annotation`,
   155  			expectedApp: `
   156  metadata:
   157    annotations:
   158      foo.bar: baz
   159      some.other: annotation`,
   160  		},
   161  		{
   162  			// For this use case: https://github.com/argoproj/argo-cd/issues/9101#issuecomment-1515672638
   163  			name: "ignore the source.plugin field with a json pointer",
   164  			ignoreDifferences: v1alpha1.ApplicationSetIgnoreDifferences{
   165  				{JSONPointers: []string{"/spec/source/plugin"}},
   166  			},
   167  			foundApp: `
   168  spec:
   169    source:
   170      plugin:
   171        parameters:
   172        - name: url
   173          string: https://example.com`,
   174  			generatedApp: `
   175  spec:
   176    source:
   177      plugin:
   178        parameters:
   179        - name: url
   180          string: https://example.com/wrong`,
   181  			expectedApp: `
   182  spec:
   183    source:
   184      plugin:
   185        parameters:
   186        - name: url
   187          string: https://example.com`,
   188  		},
   189  		{
   190  			// For this use case: https://github.com/argoproj/argo-cd/pull/14743#issuecomment-1761954799
   191  			name: "ignore parameters added to a multi-source app in the cluster",
   192  			ignoreDifferences: v1alpha1.ApplicationSetIgnoreDifferences{
   193  				{JQPathExpressions: []string{`.spec.sources[] | select(.repoURL | contains("test-repo")).helm.parameters`}},
   194  			},
   195  			foundApp: `
   196  spec:
   197    sources:
   198    - repoURL: https://git.example.com/test-org/test-repo
   199      helm:
   200        parameters:
   201        - name: test
   202          value: hi`,
   203  			generatedApp: `
   204  spec:
   205    sources:
   206    - repoURL: https://git.example.com/test-org/test-repo`,
   207  			expectedApp: `
   208  spec:
   209    sources:
   210    - repoURL: https://git.example.com/test-org/test-repo
   211      helm:
   212        parameters:
   213        - name: test
   214          value: hi`,
   215  		},
   216  	}
   217  
   218  	for _, tc := range testCases {
   219  		tc := tc
   220  		t.Run(tc.name, func(t *testing.T) {
   221  			t.Parallel()
   222  			foundApp := v1alpha1.Application{TypeMeta: appMeta}
   223  			err := yaml.Unmarshal([]byte(tc.foundApp), &foundApp)
   224  			require.NoError(t, err, tc.foundApp)
   225  			generatedApp := v1alpha1.Application{TypeMeta: appMeta}
   226  			err = yaml.Unmarshal([]byte(tc.generatedApp), &generatedApp)
   227  			require.NoError(t, err, tc.generatedApp)
   228  			err = applyIgnoreDifferences(tc.ignoreDifferences, &foundApp, &generatedApp, normalizers.IgnoreNormalizerOpts{})
   229  			require.NoError(t, err)
   230  			yamlFound, err := yaml.Marshal(tc.foundApp)
   231  			require.NoError(t, err)
   232  			yamlExpected, err := yaml.Marshal(tc.expectedApp)
   233  			require.NoError(t, err)
   234  			assert.YAMLEq(t, string(yamlExpected), string(yamlFound))
   235  		})
   236  	}
   237  }