github.com/argoproj/argo-cd/v3@v3.2.1/test/e2e/applicationset_test.go (about)

     1  package e2e
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"testing"
    10  
    11  	"github.com/google/uuid"
    12  
    13  	corev1 "k8s.io/api/core/v1"
    14  	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    15  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    16  	"k8s.io/apimachinery/pkg/runtime"
    17  
    18  	"github.com/argoproj/argo-cd/v3/common"
    19  	"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
    20  	"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
    21  
    22  	"github.com/stretchr/testify/assert"
    23  	"github.com/stretchr/testify/require"
    24  
    25  	. "github.com/argoproj/argo-cd/v3/test/e2e/fixture/applicationsets"
    26  	"github.com/argoproj/argo-cd/v3/test/e2e/fixture/applicationsets/utils"
    27  
    28  	"github.com/argoproj/argo-cd/v3/pkg/apis/application"
    29  )
    30  
    31  var ExpectedConditions = []v1alpha1.ApplicationSetCondition{
    32  	{
    33  		Type:    v1alpha1.ApplicationSetConditionErrorOccurred,
    34  		Status:  v1alpha1.ApplicationSetConditionStatusFalse,
    35  		Message: "All applications have been generated successfully",
    36  		Reason:  v1alpha1.ApplicationSetReasonApplicationSetUpToDate,
    37  	},
    38  	{
    39  		Type:    v1alpha1.ApplicationSetConditionParametersGenerated,
    40  		Status:  v1alpha1.ApplicationSetConditionStatusTrue,
    41  		Message: "Successfully generated parameters for all Applications",
    42  		Reason:  v1alpha1.ApplicationSetReasonParametersGenerated,
    43  	},
    44  	{
    45  		Type:    v1alpha1.ApplicationSetConditionResourcesUpToDate,
    46  		Status:  v1alpha1.ApplicationSetConditionStatusTrue,
    47  		Message: "All applications have been generated successfully",
    48  		Reason:  v1alpha1.ApplicationSetReasonApplicationSetUpToDate,
    49  	},
    50  }
    51  
    52  func TestSimpleListGeneratorExternalNamespace(t *testing.T) {
    53  	externalNamespace := string(utils.ArgoCDExternalNamespace)
    54  
    55  	expectedApp := v1alpha1.Application{
    56  		TypeMeta: metav1.TypeMeta{
    57  			Kind:       "Application",
    58  			APIVersion: "argoproj.io/v1alpha1",
    59  		},
    60  		ObjectMeta: metav1.ObjectMeta{
    61  			Name:       "my-cluster-guestbook",
    62  			Namespace:  externalNamespace,
    63  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
    64  		},
    65  		Spec: v1alpha1.ApplicationSpec{
    66  			Project: "default",
    67  			Source: &v1alpha1.ApplicationSource{
    68  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
    69  				TargetRevision: "HEAD",
    70  				Path:           "guestbook",
    71  			},
    72  			Destination: v1alpha1.ApplicationDestination{
    73  				Server:    "https://kubernetes.default.svc",
    74  				Namespace: "guestbook",
    75  			},
    76  		},
    77  	}
    78  	var expectedAppNewNamespace *v1alpha1.Application
    79  	var expectedAppNewMetadata *v1alpha1.Application
    80  
    81  	Given(t).
    82  		// Create a ListGenerator-based ApplicationSet
    83  		When().
    84  		SwitchToExternalNamespace(utils.ArgoCDExternalNamespace).
    85  		CreateNamespace(externalNamespace).Create(v1alpha1.ApplicationSet{
    86  		ObjectMeta: metav1.ObjectMeta{
    87  			Name:      "simple-list-generator-external",
    88  			Namespace: externalNamespace,
    89  		},
    90  		Spec: v1alpha1.ApplicationSetSpec{
    91  			GoTemplate: true,
    92  			Template: v1alpha1.ApplicationSetTemplate{
    93  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{.cluster}}-guestbook"},
    94  				Spec: v1alpha1.ApplicationSpec{
    95  					Project: "default",
    96  					Source: &v1alpha1.ApplicationSource{
    97  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
    98  						TargetRevision: "HEAD",
    99  						Path:           "guestbook",
   100  					},
   101  					Destination: v1alpha1.ApplicationDestination{
   102  						Server:    "{{.url}}",
   103  						Namespace: "guestbook",
   104  					},
   105  				},
   106  			},
   107  			Generators: []v1alpha1.ApplicationSetGenerator{
   108  				{
   109  					List: &v1alpha1.ListGenerator{
   110  						Elements: []apiextensionsv1.JSON{{
   111  							Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc"}`),
   112  						}},
   113  					},
   114  				},
   115  			},
   116  		},
   117  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
   118  
   119  		// Update the ApplicationSet template namespace, and verify it updates the Applications
   120  		When().
   121  		And(func() {
   122  			expectedAppNewNamespace = expectedApp.DeepCopy()
   123  			expectedAppNewNamespace.Spec.Destination.Namespace = "guestbook2"
   124  		}).
   125  		Update(func(appset *v1alpha1.ApplicationSet) {
   126  			appset.Spec.Template.Spec.Destination.Namespace = "guestbook2"
   127  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewNamespace})).
   128  
   129  		// Update the metadata fields in the appset template, and make sure it propagates to the apps
   130  		When().
   131  		And(func() {
   132  			expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
   133  			expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
   134  			expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
   135  				"label-key": "label-value",
   136  			}
   137  		}).
   138  		Update(func(appset *v1alpha1.ApplicationSet) {
   139  			appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
   140  			appset.Spec.Template.Labels = map[string]string{
   141  				"label-key": "label-value",
   142  			}
   143  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewMetadata})).
   144  
   145  		// verify the ApplicationSet status conditions were set correctly
   146  		Expect(ApplicationSetHasConditions("simple-list-generator-external", ExpectedConditions)).
   147  
   148  		// Delete the ApplicationSet, and verify it deletes the Applications
   149  		When().
   150  		Delete().Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{*expectedAppNewMetadata}))
   151  }
   152  
   153  func TestSimpleListGeneratorExternalNamespaceNoConflict(t *testing.T) {
   154  	externalNamespace := string(utils.ArgoCDExternalNamespace)
   155  	externalNamespace2 := string(utils.ArgoCDExternalNamespace2)
   156  
   157  	expectedApp := v1alpha1.Application{
   158  		TypeMeta: metav1.TypeMeta{
   159  			Kind:       "Application",
   160  			APIVersion: "argoproj.io/v1alpha1",
   161  		},
   162  		ObjectMeta: metav1.ObjectMeta{
   163  			Name:       "my-cluster-guestbook",
   164  			Namespace:  externalNamespace,
   165  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
   166  		},
   167  		Spec: v1alpha1.ApplicationSpec{
   168  			Project: "default",
   169  			Source: &v1alpha1.ApplicationSource{
   170  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   171  				TargetRevision: "HEAD",
   172  				Path:           "guestbook",
   173  			},
   174  			Destination: v1alpha1.ApplicationDestination{
   175  				Server:    "https://kubernetes.default.svc",
   176  				Namespace: "guestbook",
   177  			},
   178  		},
   179  	}
   180  
   181  	expectedAppExternalNamespace2 := v1alpha1.Application{
   182  		TypeMeta: metav1.TypeMeta{
   183  			Kind:       "Application",
   184  			APIVersion: "argoproj.io/v1alpha1",
   185  		},
   186  		ObjectMeta: metav1.ObjectMeta{
   187  			Name:       "my-cluster-guestbook",
   188  			Namespace:  externalNamespace2,
   189  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
   190  		},
   191  		Spec: v1alpha1.ApplicationSpec{
   192  			Project: "default",
   193  			Source: &v1alpha1.ApplicationSource{
   194  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   195  				TargetRevision: "HEAD",
   196  				Path:           "guestbook",
   197  			},
   198  			Destination: v1alpha1.ApplicationDestination{
   199  				Server:    "https://kubernetes.default.svc",
   200  				Namespace: "guestbook",
   201  			},
   202  		},
   203  	}
   204  
   205  	var expectedAppNewNamespace *v1alpha1.Application
   206  	var expectedAppNewMetadata *v1alpha1.Application
   207  
   208  	Given(t).
   209  		// Create a ListGenerator-based ApplicationSet
   210  		When().
   211  		SwitchToExternalNamespace(utils.ArgoCDExternalNamespace2).
   212  		CreateNamespace(externalNamespace2).Create(v1alpha1.ApplicationSet{
   213  		ObjectMeta: metav1.ObjectMeta{
   214  			Name:      "simple-list-generator-external",
   215  			Namespace: externalNamespace2,
   216  		},
   217  		Spec: v1alpha1.ApplicationSetSpec{
   218  			GoTemplate: true,
   219  			Template: v1alpha1.ApplicationSetTemplate{
   220  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{.cluster}}-guestbook"},
   221  				Spec: v1alpha1.ApplicationSpec{
   222  					Project: "default",
   223  					Source: &v1alpha1.ApplicationSource{
   224  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   225  						TargetRevision: "HEAD",
   226  						Path:           "guestbook",
   227  					},
   228  					Destination: v1alpha1.ApplicationDestination{
   229  						Server:    "{{.url}}",
   230  						Namespace: "guestbook",
   231  					},
   232  				},
   233  			},
   234  			Generators: []v1alpha1.ApplicationSetGenerator{
   235  				{
   236  					List: &v1alpha1.ListGenerator{
   237  						Elements: []apiextensionsv1.JSON{{
   238  							Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc"}`),
   239  						}},
   240  					},
   241  				},
   242  			},
   243  		},
   244  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedAppExternalNamespace2})).
   245  		When().
   246  		SwitchToExternalNamespace(utils.ArgoCDExternalNamespace).
   247  		CreateNamespace(externalNamespace).Create(v1alpha1.ApplicationSet{
   248  		ObjectMeta: metav1.ObjectMeta{
   249  			Name:      "simple-list-generator-external",
   250  			Namespace: externalNamespace,
   251  		},
   252  		Spec: v1alpha1.ApplicationSetSpec{
   253  			GoTemplate: true,
   254  			Template: v1alpha1.ApplicationSetTemplate{
   255  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{.cluster}}-guestbook"},
   256  				Spec: v1alpha1.ApplicationSpec{
   257  					Project: "default",
   258  					Source: &v1alpha1.ApplicationSource{
   259  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   260  						TargetRevision: "HEAD",
   261  						Path:           "guestbook",
   262  					},
   263  					Destination: v1alpha1.ApplicationDestination{
   264  						Server:    "{{.url}}",
   265  						Namespace: "guestbook",
   266  					},
   267  				},
   268  			},
   269  			Generators: []v1alpha1.ApplicationSetGenerator{
   270  				{
   271  					List: &v1alpha1.ListGenerator{
   272  						Elements: []apiextensionsv1.JSON{{
   273  							Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc"}`),
   274  						}},
   275  					},
   276  				},
   277  			},
   278  		},
   279  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
   280  		When().
   281  		SwitchToExternalNamespace(utils.ArgoCDExternalNamespace2).
   282  		Then().
   283  		Expect(ApplicationsExist([]v1alpha1.Application{expectedAppExternalNamespace2})).
   284  		When().
   285  		SwitchToExternalNamespace(utils.ArgoCDExternalNamespace).
   286  		Then().
   287  		// Update the ApplicationSet template namespace, and verify it updates the Applications
   288  		When().
   289  		And(func() {
   290  			expectedAppNewNamespace = expectedApp.DeepCopy()
   291  			expectedAppNewNamespace.Spec.Destination.Namespace = "guestbook2"
   292  		}).
   293  		Update(func(appset *v1alpha1.ApplicationSet) {
   294  			appset.Spec.Template.Spec.Destination.Namespace = "guestbook2"
   295  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewNamespace})).
   296  		When().
   297  		SwitchToExternalNamespace(utils.ArgoCDExternalNamespace2).
   298  		Then().
   299  		Expect(ApplicationsExist([]v1alpha1.Application{expectedAppExternalNamespace2})).
   300  		When().
   301  		SwitchToExternalNamespace(utils.ArgoCDExternalNamespace).
   302  		Then().
   303  		// Update the metadata fields in the appset template, and make sure it propagates to the apps
   304  		When().
   305  		And(func() {
   306  			expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
   307  			expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
   308  			expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
   309  				"label-key": "label-value",
   310  			}
   311  		}).
   312  		Update(func(appset *v1alpha1.ApplicationSet) {
   313  			appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
   314  			appset.Spec.Template.Labels = map[string]string{
   315  				"label-key": "label-value",
   316  			}
   317  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewMetadata})).
   318  
   319  		// verify the ApplicationSet status conditions were set correctly
   320  		Expect(ApplicationSetHasConditions("simple-list-generator-external", ExpectedConditions)).
   321  		When().
   322  		SwitchToExternalNamespace(utils.ArgoCDExternalNamespace2).
   323  		Then().
   324  		Expect(ApplicationsExist([]v1alpha1.Application{expectedAppExternalNamespace2})).
   325  		When().
   326  		SwitchToExternalNamespace(utils.ArgoCDExternalNamespace).
   327  		Then().
   328  		// Delete the ApplicationSet, and verify it deletes the Applications
   329  		When().
   330  		Delete().Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{*expectedAppNewMetadata})).
   331  		When().
   332  		SwitchToExternalNamespace(utils.ArgoCDExternalNamespace2).
   333  		Then().
   334  		Expect(ApplicationsExist([]v1alpha1.Application{expectedAppExternalNamespace2})).
   335  		When().
   336  		Delete().Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{expectedAppExternalNamespace2}))
   337  }
   338  
   339  func TestSimpleListGenerator(t *testing.T) {
   340  	expectedApp := v1alpha1.Application{
   341  		TypeMeta: metav1.TypeMeta{
   342  			Kind:       application.ApplicationKind,
   343  			APIVersion: "argoproj.io/v1alpha1",
   344  		},
   345  		ObjectMeta: metav1.ObjectMeta{
   346  			Name:       "my-cluster-guestbook",
   347  			Namespace:  fixture.TestNamespace(),
   348  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
   349  		},
   350  		Spec: v1alpha1.ApplicationSpec{
   351  			Project: "default",
   352  			Source: &v1alpha1.ApplicationSource{
   353  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   354  				TargetRevision: "HEAD",
   355  				Path:           "guestbook",
   356  			},
   357  			Destination: v1alpha1.ApplicationDestination{
   358  				Server:    "https://kubernetes.default.svc",
   359  				Namespace: "guestbook",
   360  			},
   361  		},
   362  	}
   363  	var expectedAppNewNamespace *v1alpha1.Application
   364  	var expectedAppNewMetadata *v1alpha1.Application
   365  
   366  	Given(t).
   367  		// Create a ListGenerator-based ApplicationSet
   368  		When().Create(v1alpha1.ApplicationSet{
   369  		ObjectMeta: metav1.ObjectMeta{
   370  			Name: "simple-list-generator",
   371  		},
   372  		Spec: v1alpha1.ApplicationSetSpec{
   373  			Template: v1alpha1.ApplicationSetTemplate{
   374  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{cluster}}-guestbook"},
   375  				Spec: v1alpha1.ApplicationSpec{
   376  					Project: "default",
   377  					Source: &v1alpha1.ApplicationSource{
   378  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   379  						TargetRevision: "HEAD",
   380  						Path:           "guestbook",
   381  					},
   382  					Destination: v1alpha1.ApplicationDestination{
   383  						Server:    "{{url}}",
   384  						Namespace: "guestbook",
   385  					},
   386  				},
   387  			},
   388  			Generators: []v1alpha1.ApplicationSetGenerator{
   389  				{
   390  					List: &v1alpha1.ListGenerator{
   391  						Elements: []apiextensionsv1.JSON{{
   392  							Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc"}`),
   393  						}},
   394  					},
   395  				},
   396  			},
   397  		},
   398  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
   399  
   400  		// Update the ApplicationSet template namespace, and verify it updates the Applications
   401  		When().
   402  		And(func() {
   403  			expectedAppNewNamespace = expectedApp.DeepCopy()
   404  			expectedAppNewNamespace.Spec.Destination.Namespace = "guestbook2"
   405  		}).
   406  		Update(func(appset *v1alpha1.ApplicationSet) {
   407  			appset.Spec.Template.Spec.Destination.Namespace = "guestbook2"
   408  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewNamespace})).
   409  
   410  		// Update the metadata fields in the appset template, and make sure it propagates to the apps
   411  		When().
   412  		And(func() {
   413  			expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
   414  			expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
   415  			expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
   416  		}).
   417  		Update(func(appset *v1alpha1.ApplicationSet) {
   418  			appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
   419  			appset.Spec.Template.Labels = map[string]string{"label-key": "label-value"}
   420  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewMetadata})).
   421  
   422  		// verify the ApplicationSet status conditions were set correctly
   423  		Expect(ApplicationSetHasConditions("simple-list-generator", ExpectedConditions)).
   424  
   425  		// Delete the ApplicationSet, and verify it deletes the Applications
   426  		When().
   427  		Delete().Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{*expectedAppNewMetadata}))
   428  }
   429  
   430  func TestSimpleListGeneratorGoTemplate(t *testing.T) {
   431  	expectedApp := v1alpha1.Application{
   432  		TypeMeta: metav1.TypeMeta{
   433  			Kind:       application.ApplicationKind,
   434  			APIVersion: "argoproj.io/v1alpha1",
   435  		},
   436  		ObjectMeta: metav1.ObjectMeta{
   437  			Name:       "my-cluster-guestbook",
   438  			Namespace:  fixture.TestNamespace(),
   439  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
   440  		},
   441  		Spec: v1alpha1.ApplicationSpec{
   442  			Project: "default",
   443  			Source: &v1alpha1.ApplicationSource{
   444  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   445  				TargetRevision: "HEAD",
   446  				Path:           "guestbook",
   447  			},
   448  			Destination: v1alpha1.ApplicationDestination{
   449  				Server:    "https://kubernetes.default.svc",
   450  				Namespace: "guestbook",
   451  			},
   452  		},
   453  	}
   454  	var expectedAppNewNamespace *v1alpha1.Application
   455  	var expectedAppNewMetadata *v1alpha1.Application
   456  
   457  	Given(t).
   458  		// Create a ListGenerator-based ApplicationSet
   459  		When().Create(v1alpha1.ApplicationSet{
   460  		ObjectMeta: metav1.ObjectMeta{
   461  			Name: "simple-list-generator",
   462  		},
   463  		Spec: v1alpha1.ApplicationSetSpec{
   464  			GoTemplate: true,
   465  			Template: v1alpha1.ApplicationSetTemplate{
   466  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{.cluster}}-guestbook"},
   467  				Spec: v1alpha1.ApplicationSpec{
   468  					Project: "default",
   469  					Source: &v1alpha1.ApplicationSource{
   470  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   471  						TargetRevision: "HEAD",
   472  						Path:           "guestbook",
   473  					},
   474  					Destination: v1alpha1.ApplicationDestination{
   475  						Server:    "{{.url}}",
   476  						Namespace: "guestbook",
   477  					},
   478  				},
   479  			},
   480  			Generators: []v1alpha1.ApplicationSetGenerator{
   481  				{
   482  					List: &v1alpha1.ListGenerator{
   483  						Elements: []apiextensionsv1.JSON{{
   484  							Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc"}`),
   485  						}},
   486  					},
   487  				},
   488  			},
   489  		},
   490  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
   491  
   492  		// Update the ApplicationSet template namespace, and verify it updates the Applications
   493  		When().
   494  		And(func() {
   495  			expectedAppNewNamespace = expectedApp.DeepCopy()
   496  			expectedAppNewNamespace.Spec.Destination.Namespace = "guestbook2"
   497  		}).
   498  		Update(func(appset *v1alpha1.ApplicationSet) {
   499  			appset.Spec.Template.Spec.Destination.Namespace = "guestbook2"
   500  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewNamespace})).
   501  
   502  		// Update the metadata fields in the appset template, and make sure it propagates to the apps
   503  		When().
   504  		And(func() {
   505  			expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
   506  			expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
   507  			expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
   508  		}).
   509  		Update(func(appset *v1alpha1.ApplicationSet) {
   510  			appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
   511  			appset.Spec.Template.Labels = map[string]string{"label-key": "label-value"}
   512  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewMetadata})).
   513  
   514  		// verify the ApplicationSet status conditions were set correctly
   515  		Expect(ApplicationSetHasConditions("simple-list-generator", ExpectedConditions)).
   516  
   517  		// Delete the ApplicationSet, and verify it deletes the Applications
   518  		When().
   519  		Delete().Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{*expectedAppNewMetadata}))
   520  }
   521  
   522  func TestRenderHelmValuesObject(t *testing.T) {
   523  	expectedApp := v1alpha1.Application{
   524  		TypeMeta: metav1.TypeMeta{
   525  			Kind:       application.ApplicationKind,
   526  			APIVersion: "argoproj.io/v1alpha1",
   527  		},
   528  		ObjectMeta: metav1.ObjectMeta{
   529  			Name:       "my-cluster-guestbook",
   530  			Namespace:  fixture.TestNamespace(),
   531  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
   532  		},
   533  		Spec: v1alpha1.ApplicationSpec{
   534  			Project: "default",
   535  			Source: &v1alpha1.ApplicationSource{
   536  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   537  				TargetRevision: "HEAD",
   538  				Path:           "helm-guestbook",
   539  				Helm: &v1alpha1.ApplicationSourceHelm{
   540  					ValuesObject: &runtime.RawExtension{
   541  						// This will always be converted as yaml
   542  						Raw: []byte(`{"some":{"string":"Hello world"}}`),
   543  					},
   544  				},
   545  			},
   546  			Destination: v1alpha1.ApplicationDestination{
   547  				Server:    "https://kubernetes.default.svc",
   548  				Namespace: "guestbook",
   549  			},
   550  		},
   551  	}
   552  
   553  	Given(t).
   554  		// Create a ListGenerator-based ApplicationSet
   555  		When().Create(v1alpha1.ApplicationSet{
   556  		ObjectMeta: metav1.ObjectMeta{
   557  			Name: "test-values-object",
   558  		},
   559  		Spec: v1alpha1.ApplicationSetSpec{
   560  			GoTemplate: true,
   561  			Template: v1alpha1.ApplicationSetTemplate{
   562  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{.cluster}}-guestbook"},
   563  				Spec: v1alpha1.ApplicationSpec{
   564  					Project: "default",
   565  					Source: &v1alpha1.ApplicationSource{
   566  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   567  						TargetRevision: "HEAD",
   568  						Path:           "helm-guestbook",
   569  						Helm: &v1alpha1.ApplicationSourceHelm{
   570  							ValuesObject: &runtime.RawExtension{
   571  								Raw: []byte(`{"some":{"string":"{{.test}}"}}`),
   572  							},
   573  						},
   574  					},
   575  					Destination: v1alpha1.ApplicationDestination{
   576  						Server:    "{{.url}}",
   577  						Namespace: "guestbook",
   578  					},
   579  				},
   580  			},
   581  			Generators: []v1alpha1.ApplicationSetGenerator{
   582  				{
   583  					List: &v1alpha1.ListGenerator{
   584  						Elements: []apiextensionsv1.JSON{{
   585  							Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc", "test": "Hello world"}`),
   586  						}},
   587  					},
   588  				},
   589  			},
   590  		},
   591  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
   592  		// Delete the ApplicationSet, and verify it deletes the Applications
   593  		When().
   594  		Delete().Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{expectedApp}))
   595  }
   596  
   597  func TestTemplatePatch(t *testing.T) {
   598  	expectedApp := v1alpha1.Application{
   599  		TypeMeta: metav1.TypeMeta{
   600  			Kind:       application.ApplicationKind,
   601  			APIVersion: "argoproj.io/v1alpha1",
   602  		},
   603  		ObjectMeta: metav1.ObjectMeta{
   604  			Name:       "my-cluster-guestbook",
   605  			Namespace:  fixture.TestNamespace(),
   606  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
   607  			Annotations: map[string]string{
   608  				"annotation-some-key": "annotation-some-value",
   609  			},
   610  		},
   611  		Spec: v1alpha1.ApplicationSpec{
   612  			Project: "default",
   613  			Source: &v1alpha1.ApplicationSource{
   614  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   615  				TargetRevision: "HEAD",
   616  				Path:           "guestbook",
   617  			},
   618  			Destination: v1alpha1.ApplicationDestination{
   619  				Server:    "https://kubernetes.default.svc",
   620  				Namespace: "guestbook",
   621  			},
   622  			SyncPolicy: &v1alpha1.SyncPolicy{
   623  				SyncOptions: v1alpha1.SyncOptions{"CreateNamespace=true"},
   624  			},
   625  		},
   626  	}
   627  
   628  	templatePatch := `{
   629  		"metadata": {
   630  			"annotations": {
   631  				{{- range $k, $v := .annotations }}
   632  				"{{ $k }}": "{{ $v }}"
   633  				{{- end }}
   634  			}
   635  		},
   636  		{{- if .createNamespace }}
   637  		"spec": {
   638  			"syncPolicy": {
   639  				"syncOptions": [
   640  					"CreateNamespace=true"
   641  				]
   642  			}
   643  		}
   644  		{{- end }}
   645  	}
   646  	`
   647  
   648  	var expectedAppNewNamespace *v1alpha1.Application
   649  	var expectedAppNewMetadata *v1alpha1.Application
   650  
   651  	Given(t).
   652  		// Create a ListGenerator-based ApplicationSet
   653  		When().Create(v1alpha1.ApplicationSet{
   654  		ObjectMeta: metav1.ObjectMeta{
   655  			Name: "patch-template",
   656  		},
   657  		Spec: v1alpha1.ApplicationSetSpec{
   658  			GoTemplate: true,
   659  			Template: v1alpha1.ApplicationSetTemplate{
   660  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{.cluster}}-guestbook"},
   661  				Spec: v1alpha1.ApplicationSpec{
   662  					Project: "default",
   663  					Source: &v1alpha1.ApplicationSource{
   664  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   665  						TargetRevision: "HEAD",
   666  						Path:           "guestbook",
   667  					},
   668  					Destination: v1alpha1.ApplicationDestination{
   669  						Server:    "{{.url}}",
   670  						Namespace: "guestbook",
   671  					},
   672  				},
   673  			},
   674  			TemplatePatch: &templatePatch,
   675  			Generators: []v1alpha1.ApplicationSetGenerator{
   676  				{
   677  					List: &v1alpha1.ListGenerator{
   678  						Elements: []apiextensionsv1.JSON{{
   679  							Raw: []byte(`{
   680  									"cluster": "my-cluster",
   681  									"url": "https://kubernetes.default.svc",
   682  									"createNamespace": true,
   683  									"annotations": {
   684  										"annotation-some-key": "annotation-some-value"
   685  									}
   686  								}`),
   687  						}},
   688  					},
   689  				},
   690  			},
   691  		},
   692  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
   693  
   694  		// Update the ApplicationSet template namespace, and verify it updates the Applications
   695  		When().
   696  		And(func() {
   697  			expectedAppNewNamespace = expectedApp.DeepCopy()
   698  			expectedAppNewNamespace.Spec.Destination.Namespace = "guestbook2"
   699  		}).
   700  		Update(func(appset *v1alpha1.ApplicationSet) {
   701  			appset.Spec.Template.Spec.Destination.Namespace = "guestbook2"
   702  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewNamespace})).
   703  
   704  		// Update the metadata fields in the appset template, and make sure it propagates to the apps
   705  		When().
   706  		And(func() {
   707  			expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
   708  			expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
   709  				"label-key": "label-value",
   710  			}
   711  		}).
   712  		Update(func(appset *v1alpha1.ApplicationSet) {
   713  			appset.Spec.Template.Labels = map[string]string{"label-key": "label-value"}
   714  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewMetadata})).
   715  
   716  		// verify the ApplicationSet status conditions were set correctly
   717  		Expect(ApplicationSetHasConditions("patch-template", ExpectedConditions)).
   718  
   719  		// Delete the ApplicationSet, and verify it deletes the Applications
   720  		When().
   721  		Delete().Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{*expectedAppNewMetadata}))
   722  }
   723  
   724  func TestUpdateHelmValuesObject(t *testing.T) {
   725  	expectedApp := v1alpha1.Application{
   726  		TypeMeta: metav1.TypeMeta{
   727  			Kind:       application.ApplicationKind,
   728  			APIVersion: "argoproj.io/v1alpha1",
   729  		},
   730  		ObjectMeta: metav1.ObjectMeta{
   731  			Name:       "my-cluster-guestbook",
   732  			Namespace:  fixture.TestNamespace(),
   733  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
   734  		},
   735  		Spec: v1alpha1.ApplicationSpec{
   736  			Project: "default",
   737  			Source: &v1alpha1.ApplicationSource{
   738  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   739  				TargetRevision: "HEAD",
   740  				Path:           "helm-guestbook",
   741  				Helm: &v1alpha1.ApplicationSourceHelm{
   742  					ValuesObject: &runtime.RawExtension{
   743  						// This will always be converted as yaml
   744  						Raw: []byte(`{"some":{"foo":"bar"}}`),
   745  					},
   746  				},
   747  			},
   748  			Destination: v1alpha1.ApplicationDestination{
   749  				Server:    "https://kubernetes.default.svc",
   750  				Namespace: "guestbook",
   751  			},
   752  		},
   753  	}
   754  
   755  	Given(t).
   756  		// Create a ListGenerator-based ApplicationSet
   757  		When().Create(v1alpha1.ApplicationSet{
   758  		ObjectMeta: metav1.ObjectMeta{
   759  			Name: "test-values-object-patch",
   760  		},
   761  		Spec: v1alpha1.ApplicationSetSpec{
   762  			GoTemplate: true,
   763  			Template: v1alpha1.ApplicationSetTemplate{
   764  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{.cluster}}-guestbook"},
   765  				Spec: v1alpha1.ApplicationSpec{
   766  					Project: "default",
   767  					Source: &v1alpha1.ApplicationSource{
   768  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   769  						TargetRevision: "HEAD",
   770  						Path:           "helm-guestbook",
   771  						Helm: &v1alpha1.ApplicationSourceHelm{
   772  							ValuesObject: &runtime.RawExtension{
   773  								Raw: []byte(`{"some":{"string":"{{.test}}"}}`),
   774  							},
   775  						},
   776  					},
   777  					Destination: v1alpha1.ApplicationDestination{
   778  						Server:    "{{.url}}",
   779  						Namespace: "guestbook",
   780  					},
   781  				},
   782  			},
   783  			Generators: []v1alpha1.ApplicationSetGenerator{
   784  				{
   785  					List: &v1alpha1.ListGenerator{
   786  						Elements: []apiextensionsv1.JSON{{
   787  							Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc", "test": "Hello world"}`),
   788  						}},
   789  					},
   790  				},
   791  			},
   792  		},
   793  	}).Then().
   794  		Expect(ApplicationSetHasConditions("test-values-object-patch", ExpectedConditions)).
   795  		When().
   796  		// Update the app spec with some knew ValuesObject to force a merge
   797  		Update(func(as *v1alpha1.ApplicationSet) {
   798  			as.Spec.Template.Spec.Source.Helm.ValuesObject = &runtime.RawExtension{
   799  				Raw: []byte(`{"some":{"foo":"bar"}}`),
   800  			}
   801  		}).
   802  		Then().
   803  		Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
   804  		When().
   805  		// Delete the ApplicationSet, and verify it deletes the Applications
   806  		Delete().Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{expectedApp}))
   807  }
   808  
   809  func TestSyncPolicyCreateUpdate(t *testing.T) {
   810  	expectedApp := v1alpha1.Application{
   811  		TypeMeta: metav1.TypeMeta{
   812  			Kind:       "Application",
   813  			APIVersion: "argoproj.io/v1alpha1",
   814  		},
   815  		ObjectMeta: metav1.ObjectMeta{
   816  			Name:       "my-cluster-guestbook-sync-policy-create-update",
   817  			Namespace:  utils.ArgoCDNamespace,
   818  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
   819  		},
   820  		Spec: v1alpha1.ApplicationSpec{
   821  			Project: "default",
   822  			Source: &v1alpha1.ApplicationSource{
   823  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   824  				TargetRevision: "HEAD",
   825  				Path:           "guestbook",
   826  			},
   827  			Destination: v1alpha1.ApplicationDestination{
   828  				Server:    "https://kubernetes.default.svc",
   829  				Namespace: "guestbook",
   830  			},
   831  		},
   832  	}
   833  	var expectedAppNewNamespace *v1alpha1.Application
   834  	var expectedAppNewMetadata *v1alpha1.Application
   835  
   836  	Given(t).
   837  		// Create a ListGenerator-based ApplicationSet
   838  		When().Create(v1alpha1.ApplicationSet{
   839  		ObjectMeta: metav1.ObjectMeta{
   840  			Name: "sync-policy-create-update",
   841  		},
   842  		Spec: v1alpha1.ApplicationSetSpec{
   843  			GoTemplate: true,
   844  			Template: v1alpha1.ApplicationSetTemplate{
   845  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{
   846  					Name:       "{{.cluster}}-guestbook-sync-policy-create-update",
   847  					Finalizers: []string{v1alpha1.ResourcesFinalizerName},
   848  				},
   849  				Spec: v1alpha1.ApplicationSpec{
   850  					Project: "default",
   851  					Source: &v1alpha1.ApplicationSource{
   852  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   853  						TargetRevision: "HEAD",
   854  						Path:           "guestbook",
   855  					},
   856  					Destination: v1alpha1.ApplicationDestination{
   857  						Server:    "{{.url}}",
   858  						Namespace: "guestbook",
   859  					},
   860  				},
   861  			},
   862  			Generators: []v1alpha1.ApplicationSetGenerator{
   863  				{
   864  					List: &v1alpha1.ListGenerator{
   865  						Elements: []apiextensionsv1.JSON{{
   866  							Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc"}`),
   867  						}},
   868  					},
   869  				},
   870  			},
   871  		},
   872  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
   873  
   874  		// Update the ApplicationSet template namespace, and verify it updates the Applications
   875  		When().
   876  		And(func() {
   877  			expectedAppNewNamespace = expectedApp.DeepCopy()
   878  			expectedAppNewNamespace.Spec.Destination.Namespace = "guestbook2"
   879  		}).
   880  		Update(func(appset *v1alpha1.ApplicationSet) {
   881  			appset.Spec.Template.Spec.Destination.Namespace = "guestbook2"
   882  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewNamespace})).
   883  
   884  		// Update the metadata fields in the appset template
   885  		// Update as well the policy
   886  		// As policy is create-update, updates must reflected
   887  		When().
   888  		And(func() {
   889  			expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
   890  			expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
   891  			expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
   892  				"label-key": "label-value",
   893  			}
   894  		}).
   895  		Update(func(appset *v1alpha1.ApplicationSet) {
   896  			appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
   897  			appset.Spec.Template.Labels = map[string]string{
   898  				"label-key": "label-value",
   899  			}
   900  			applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicyCreateUpdate
   901  			appset.Spec.SyncPolicy = &v1alpha1.ApplicationSetSyncPolicy{
   902  				ApplicationsSync: &applicationsSyncPolicy,
   903  			}
   904  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewMetadata})).
   905  
   906  		// Update the list and remove element
   907  		// As policy is create-update, app deletion must not be reflected
   908  		When().
   909  		Update(func(appset *v1alpha1.ApplicationSet) {
   910  			appset.Spec.Generators = []v1alpha1.ApplicationSetGenerator{}
   911  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewMetadata})).
   912  
   913  		// verify the ApplicationSet status conditions were set correctly
   914  		Expect(ApplicationSetHasConditions("sync-policy-create-update", ExpectedConditions)).
   915  
   916  		// Delete the ApplicationSet, and verify it not deletes the Applications
   917  		// As policy is create-update, AppSet controller will remove all generated applications's ownerReferences on delete AppSet
   918  		// So AppSet deletion will be reflected, but all the applications it generates will still exist
   919  		When().
   920  		Delete().Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewMetadata}))
   921  }
   922  
   923  func TestSyncPolicyCreateDelete(t *testing.T) {
   924  	expectedApp := v1alpha1.Application{
   925  		TypeMeta: metav1.TypeMeta{
   926  			Kind:       "Application",
   927  			APIVersion: "argoproj.io/v1alpha1",
   928  		},
   929  		ObjectMeta: metav1.ObjectMeta{
   930  			Name:       "my-cluster-guestbook-sync-policy-create-delete",
   931  			Namespace:  utils.ArgoCDNamespace,
   932  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
   933  		},
   934  		Spec: v1alpha1.ApplicationSpec{
   935  			Project: "default",
   936  			Source: &v1alpha1.ApplicationSource{
   937  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   938  				TargetRevision: "HEAD",
   939  				Path:           "guestbook",
   940  			},
   941  			Destination: v1alpha1.ApplicationDestination{
   942  				Server:    "https://kubernetes.default.svc",
   943  				Namespace: "guestbook",
   944  			},
   945  		},
   946  	}
   947  	var expectedAppNewNamespace *v1alpha1.Application
   948  
   949  	Given(t).
   950  		// Create a ListGenerator-based ApplicationSet
   951  		When().Create(v1alpha1.ApplicationSet{
   952  		ObjectMeta: metav1.ObjectMeta{
   953  			Name: "sync-policy-create-delete",
   954  		},
   955  		Spec: v1alpha1.ApplicationSetSpec{
   956  			GoTemplate: true,
   957  			Template: v1alpha1.ApplicationSetTemplate{
   958  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{.cluster}}-guestbook-sync-policy-create-delete"},
   959  				Spec: v1alpha1.ApplicationSpec{
   960  					Project: "default",
   961  					Source: &v1alpha1.ApplicationSource{
   962  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   963  						TargetRevision: "HEAD",
   964  						Path:           "guestbook",
   965  					},
   966  					Destination: v1alpha1.ApplicationDestination{
   967  						Server:    "{{.url}}",
   968  						Namespace: "guestbook",
   969  					},
   970  				},
   971  			},
   972  			Generators: []v1alpha1.ApplicationSetGenerator{
   973  				{
   974  					List: &v1alpha1.ListGenerator{
   975  						Elements: []apiextensionsv1.JSON{{
   976  							Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc"}`),
   977  						}},
   978  					},
   979  				},
   980  			},
   981  		},
   982  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
   983  
   984  		// Update the ApplicationSet template namespace, and verify it updates the Applications
   985  		When().
   986  		And(func() {
   987  			expectedAppNewNamespace = expectedApp.DeepCopy()
   988  			expectedAppNewNamespace.Spec.Destination.Namespace = "guestbook2"
   989  		}).
   990  		Update(func(appset *v1alpha1.ApplicationSet) {
   991  			appset.Spec.Template.Spec.Destination.Namespace = "guestbook2"
   992  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewNamespace})).
   993  
   994  		// Update the metadata fields in the appset template
   995  		// Update as well the policy
   996  		// As policy is create-delete, updates must not be reflected
   997  		When().
   998  		Update(func(appset *v1alpha1.ApplicationSet) {
   999  			appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
  1000  			appset.Spec.Template.Labels = map[string]string{"label-key": "label-value"}
  1001  			applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicyCreateDelete
  1002  			appset.Spec.SyncPolicy = &v1alpha1.ApplicationSetSyncPolicy{
  1003  				ApplicationsSync: &applicationsSyncPolicy,
  1004  			}
  1005  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewNamespace})).
  1006  
  1007  		// Update the list and remove element
  1008  		// As policy is create-delete, app deletion must be reflected
  1009  		When().
  1010  		Update(func(appset *v1alpha1.ApplicationSet) {
  1011  			appset.Spec.Generators = []v1alpha1.ApplicationSetGenerator{}
  1012  		}).Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{*expectedAppNewNamespace})).
  1013  
  1014  		// verify the ApplicationSet status conditions were set correctly
  1015  		Expect(ApplicationSetHasConditions("sync-policy-create-delete", ExpectedConditions)).
  1016  
  1017  		// Delete the ApplicationSet
  1018  		When().
  1019  		Delete().Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{*expectedAppNewNamespace}))
  1020  }
  1021  
  1022  func TestSyncPolicyCreateOnly(t *testing.T) {
  1023  	expectedApp := v1alpha1.Application{
  1024  		TypeMeta: metav1.TypeMeta{
  1025  			Kind:       "Application",
  1026  			APIVersion: "argoproj.io/v1alpha1",
  1027  		},
  1028  		ObjectMeta: metav1.ObjectMeta{
  1029  			Name:       "my-cluster-guestbook-sync-policy-create-only",
  1030  			Namespace:  utils.ArgoCDNamespace,
  1031  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
  1032  		},
  1033  		Spec: v1alpha1.ApplicationSpec{
  1034  			Project: "default",
  1035  			Source: &v1alpha1.ApplicationSource{
  1036  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
  1037  				TargetRevision: "HEAD",
  1038  				Path:           "guestbook",
  1039  			},
  1040  			Destination: v1alpha1.ApplicationDestination{
  1041  				Server:    "https://kubernetes.default.svc",
  1042  				Namespace: "guestbook",
  1043  			},
  1044  		},
  1045  	}
  1046  	var expectedAppNewNamespace *v1alpha1.Application
  1047  
  1048  	Given(t).
  1049  		// Create a ListGenerator-based ApplicationSet
  1050  		When().Create(v1alpha1.ApplicationSet{
  1051  		ObjectMeta: metav1.ObjectMeta{
  1052  			Name: "sync-policy-create-only",
  1053  		},
  1054  		Spec: v1alpha1.ApplicationSetSpec{
  1055  			GoTemplate: true,
  1056  			Template: v1alpha1.ApplicationSetTemplate{
  1057  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{
  1058  					Name:       "{{.cluster}}-guestbook-sync-policy-create-only",
  1059  					Finalizers: []string{v1alpha1.ResourcesFinalizerName},
  1060  				},
  1061  				Spec: v1alpha1.ApplicationSpec{
  1062  					Project: "default",
  1063  					Source: &v1alpha1.ApplicationSource{
  1064  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
  1065  						TargetRevision: "HEAD",
  1066  						Path:           "guestbook",
  1067  					},
  1068  					Destination: v1alpha1.ApplicationDestination{
  1069  						Server:    "{{.url}}",
  1070  						Namespace: "guestbook",
  1071  					},
  1072  				},
  1073  			},
  1074  			Generators: []v1alpha1.ApplicationSetGenerator{
  1075  				{
  1076  					List: &v1alpha1.ListGenerator{
  1077  						Elements: []apiextensionsv1.JSON{{
  1078  							Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc"}`),
  1079  						}},
  1080  					},
  1081  				},
  1082  			},
  1083  		},
  1084  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
  1085  
  1086  		// Update the ApplicationSet template namespace, and verify it updates the Applications
  1087  		When().
  1088  		And(func() {
  1089  			expectedAppNewNamespace = expectedApp.DeepCopy()
  1090  			expectedAppNewNamespace.Spec.Destination.Namespace = "guestbook2"
  1091  		}).
  1092  		Update(func(appset *v1alpha1.ApplicationSet) {
  1093  			appset.Spec.Template.Spec.Destination.Namespace = "guestbook2"
  1094  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewNamespace})).
  1095  
  1096  		// Update the metadata fields in the appset template
  1097  		// Update as well the policy
  1098  		// As policy is create-only, updates must not be reflected
  1099  		When().
  1100  		Update(func(appset *v1alpha1.ApplicationSet) {
  1101  			appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
  1102  			appset.Spec.Template.Labels = map[string]string{"label-key": "label-value"}
  1103  			applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicyCreateOnly
  1104  			appset.Spec.SyncPolicy = &v1alpha1.ApplicationSetSyncPolicy{
  1105  				ApplicationsSync: &applicationsSyncPolicy,
  1106  			}
  1107  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewNamespace})).
  1108  
  1109  		// Update the list and remove element
  1110  		// As policy is create-only, app deletion must not be reflected
  1111  		When().
  1112  		Update(func(appset *v1alpha1.ApplicationSet) {
  1113  			appset.Spec.Generators = []v1alpha1.ApplicationSetGenerator{}
  1114  		}).Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewNamespace})).
  1115  
  1116  		// verify the ApplicationSet status conditions were set correctly
  1117  		Expect(ApplicationSetHasConditions("sync-policy-create-only", ExpectedConditions)).
  1118  
  1119  		// Delete the ApplicationSet, and verify it not deletes the Applications
  1120  		// As policy is create-update, AppSet controller will remove all generated applications's ownerReferences on delete AppSet
  1121  		// So AppSet deletion will be reflected, but all the applications it generates will still exist
  1122  		When().
  1123  		Delete().Then().Expect(ApplicationsExist([]v1alpha1.Application{*expectedAppNewNamespace}))
  1124  }
  1125  
  1126  func githubSCMMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
  1127  	t.Helper()
  1128  	return func(w http.ResponseWriter, r *http.Request) {
  1129  		w.Header().Set("Content-Type", "application/json")
  1130  		switch r.RequestURI {
  1131  		case "/api/v3/orgs/argoproj/repos?per_page=100":
  1132  			_, err := io.WriteString(w, `[
  1133  				{
  1134  				  "id": 1296269,
  1135  				  "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
  1136  				  "name": "argo-cd",
  1137  				  "full_name": "argoproj/argo-cd",
  1138  				  "owner": {
  1139  					"login": "argoproj",
  1140  					"id": 1,
  1141  					"node_id": "MDQ6VXNlcjE=",
  1142  					"avatar_url": "https://github.com/images/error/argoproj_happy.gif",
  1143  					"gravatar_id": "",
  1144  					"url": "https://api.github.com/users/argoproj",
  1145  					"html_url": "https://github.com/argoproj",
  1146  					"followers_url": "https://api.github.com/users/argoproj/followers",
  1147  					"following_url": "https://api.github.com/users/argoproj/following{/other_user}",
  1148  					"gists_url": "https://api.github.com/users/argoproj/gists{/gist_id}",
  1149  					"starred_url": "https://api.github.com/users/argoproj/starred{/owner}{/repo}",
  1150  					"subscriptions_url": "https://api.github.com/users/argoproj/subscriptions",
  1151  					"organizations_url": "https://api.github.com/users/argoproj/orgs",
  1152  					"repos_url": "https://api.github.com/users/argoproj/repos",
  1153  					"events_url": "https://api.github.com/users/argoproj/events{/privacy}",
  1154  					"received_events_url": "https://api.github.com/users/argoproj/received_events",
  1155  					"type": "User",
  1156  					"site_admin": false
  1157  				  },
  1158  				  "private": false,
  1159  				  "html_url": "https://github.com/argoproj/argo-cd",
  1160  				  "description": "This your first repo!",
  1161  				  "fork": false,
  1162  				  "url": "https://api.github.com/repos/argoproj/argo-cd",
  1163  				  "archive_url": "https://api.github.com/repos/argoproj/argo-cd/{archive_format}{/ref}",
  1164  				  "assignees_url": "https://api.github.com/repos/argoproj/argo-cd/assignees{/user}",
  1165  				  "blobs_url": "https://api.github.com/repos/argoproj/argo-cd/git/blobs{/sha}",
  1166  				  "branches_url": "https://api.github.com/repos/argoproj/argo-cd/branches{/branch}",
  1167  				  "collaborators_url": "https://api.github.com/repos/argoproj/argo-cd/collaborators{/collaborator}",
  1168  				  "comments_url": "https://api.github.com/repos/argoproj/argo-cd/comments{/number}",
  1169  				  "commits_url": "https://api.github.com/repos/argoproj/argo-cd/commits{/sha}",
  1170  				  "compare_url": "https://api.github.com/repos/argoproj/argo-cd/compare/{base}...{head}",
  1171  				  "contents_url": "https://api.github.com/repos/argoproj/argo-cd/contents/{path}",
  1172  				  "contributors_url": "https://api.github.com/repos/argoproj/argo-cd/contributors",
  1173  				  "deployments_url": "https://api.github.com/repos/argoproj/argo-cd/deployments",
  1174  				  "downloads_url": "https://api.github.com/repos/argoproj/argo-cd/downloads",
  1175  				  "events_url": "https://api.github.com/repos/argoproj/argo-cd/events",
  1176  				  "forks_url": "https://api.github.com/repos/argoproj/argo-cd/forks",
  1177  				  "git_commits_url": "https://api.github.com/repos/argoproj/argo-cd/git/commits{/sha}",
  1178  				  "git_refs_url": "https://api.github.com/repos/argoproj/argo-cd/git/refs{/sha}",
  1179  				  "git_tags_url": "https://api.github.com/repos/argoproj/argo-cd/git/tags{/sha}",
  1180  				  "git_url": "git:github.com/argoproj/argo-cd.git",
  1181  				  "issue_comment_url": "https://api.github.com/repos/argoproj/argo-cd/issues/comments{/number}",
  1182  				  "issue_events_url": "https://api.github.com/repos/argoproj/argo-cd/issues/events{/number}",
  1183  				  "issues_url": "https://api.github.com/repos/argoproj/argo-cd/issues{/number}",
  1184  				  "keys_url": "https://api.github.com/repos/argoproj/argo-cd/keys{/key_id}",
  1185  				  "labels_url": "https://api.github.com/repos/argoproj/argo-cd/labels{/name}",
  1186  				  "languages_url": "https://api.github.com/repos/argoproj/argo-cd/languages",
  1187  				  "merges_url": "https://api.github.com/repos/argoproj/argo-cd/merges",
  1188  				  "milestones_url": "https://api.github.com/repos/argoproj/argo-cd/milestones{/number}",
  1189  				  "notifications_url": "https://api.github.com/repos/argoproj/argo-cd/notifications{?since,all,participating}",
  1190  				  "pulls_url": "https://api.github.com/repos/argoproj/argo-cd/pulls{/number}",
  1191  				  "releases_url": "https://api.github.com/repos/argoproj/argo-cd/releases{/id}",
  1192  				  "ssh_url": "git@github.com:argoproj/argo-cd.git",
  1193  				  "stargazers_url": "https://api.github.com/repos/argoproj/argo-cd/stargazers",
  1194  				  "statuses_url": "https://api.github.com/repos/argoproj/argo-cd/statuses/{sha}",
  1195  				  "subscribers_url": "https://api.github.com/repos/argoproj/argo-cd/subscribers",
  1196  				  "subscription_url": "https://api.github.com/repos/argoproj/argo-cd/subscription",
  1197  				  "tags_url": "https://api.github.com/repos/argoproj/argo-cd/tags",
  1198  				  "teams_url": "https://api.github.com/repos/argoproj/argo-cd/teams",
  1199  				  "trees_url": "https://api.github.com/repos/argoproj/argo-cd/git/trees{/sha}",
  1200  				  "clone_url": "https://github.com/argoproj/argo-cd.git",
  1201  				  "mirror_url": "git:git.example.com/argoproj/argo-cd",
  1202  				  "hooks_url": "https://api.github.com/repos/argoproj/argo-cd/hooks",
  1203  				  "svn_url": "https://svn.github.com/argoproj/argo-cd",
  1204  				  "homepage": "https://github.com",
  1205  				  "language": null,
  1206  				  "forks_count": 9,
  1207  				  "stargazers_count": 80,
  1208  				  "watchers_count": 80,
  1209  				  "size": 108,
  1210  				  "default_branch": "master",
  1211  				  "open_issues_count": 0,
  1212  				  "is_template": false,
  1213  				  "topics": [
  1214  					"argoproj",
  1215  					"atom",
  1216  					"electron",
  1217  					"api"
  1218  				  ],
  1219  				  "has_issues": true,
  1220  				  "has_projects": true,
  1221  				  "has_wiki": true,
  1222  				  "has_pages": false,
  1223  				  "has_downloads": true,
  1224  				  "archived": false,
  1225  				  "disabled": false,
  1226  				  "visibility": "public",
  1227  				  "pushed_at": "2011-01-26T19:06:43Z",
  1228  				  "created_at": "2011-01-26T19:01:12Z",
  1229  				  "updated_at": "2011-01-26T19:14:43Z",
  1230  				  "permissions": {
  1231  					"admin": false,
  1232  					"push": false,
  1233  					"pull": true
  1234  				  },
  1235  				  "template_repository": null
  1236  				}
  1237  			  ]`)
  1238  			if err != nil {
  1239  				t.Fail()
  1240  			}
  1241  		case "/api/v3/repos/argoproj/argo-cd/branches?per_page=100":
  1242  			_, err := io.WriteString(w, `[
  1243  				{
  1244  				  "name": "master",
  1245  				  "commit": {
  1246  					"sha": "c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc",
  1247  					"url": "https://api.github.com/repos/argoproj/argo-cd/commits/c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc"
  1248  				  },
  1249  				  "protected": true,
  1250  				  "protection": {
  1251  					"required_status_checks": {
  1252  					  "enforcement_level": "non_admins",
  1253  					  "contexts": [
  1254  						"ci-test",
  1255  						"linter"
  1256  					  ]
  1257  					}
  1258  				  },
  1259  				  "protection_url": "https://api.github.com/repos/argoproj/hello-world/branches/master/protection"
  1260  				}
  1261  			  ]
  1262  			`)
  1263  			if err != nil {
  1264  				t.Fail()
  1265  			}
  1266  		case "/api/v3/repos/argoproj/argo-cd/contents/pkg?ref=master":
  1267  			_, err := io.WriteString(w, `{
  1268  				"type": "file",
  1269  				"encoding": "base64",
  1270  				"size": 5362,
  1271  				"name": "pkg/",
  1272  				"path": "pkg/",
  1273  				"content": "encoded content ...",
  1274  				"sha": "3d21ec53a331a6f037a91c368710b99387d012c1",
  1275  				"url": "https://api.github.com/repos/octokit/octokit.rb/contents/README.md",
  1276  				"git_url": "https://api.github.com/repos/octokit/octokit.rb/git/blobs/3d21ec53a331a6f037a91c368710b99387d012c1",
  1277  				"html_url": "https://github.com/octokit/octokit.rb/blob/master/README.md",
  1278  				"download_url": "https://raw.githubusercontent.com/octokit/octokit.rb/master/README.md",
  1279  				"_links": {
  1280  				  "git": "https://api.github.com/repos/octokit/octokit.rb/git/blobs/3d21ec53a331a6f037a91c368710b99387d012c1",
  1281  				  "self": "https://api.github.com/repos/octokit/octokit.rb/contents/README.md",
  1282  				  "html": "https://github.com/octokit/octokit.rb/blob/master/README.md"
  1283  				}
  1284  			  }`)
  1285  			if err != nil {
  1286  				t.Fail()
  1287  			}
  1288  		case "/api/v3/repos/argoproj/argo-cd/branches/master":
  1289  			_, err := io.WriteString(w, `{
  1290  				"name": "master",
  1291  				"commit": {
  1292  				  "sha": "c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc",
  1293  				  "url": "https://api.github.com/repos/octocat/Hello-World/commits/c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc"
  1294  				},
  1295  				"protected": true,
  1296  				"protection": {
  1297  				  "required_status_checks": {
  1298  					"enforcement_level": "non_admins",
  1299  					"contexts": [
  1300  					  "ci-test",
  1301  					  "linter"
  1302  					]
  1303  				  }
  1304  				},
  1305  				"protection_url": "https://api.github.com/repos/octocat/hello-world/branches/master/protection"
  1306  			  }`)
  1307  			if err != nil {
  1308  				t.Fail()
  1309  			}
  1310  		default:
  1311  			w.WriteHeader(http.StatusNotFound)
  1312  		}
  1313  	}
  1314  }
  1315  
  1316  func testServerWithPort(t *testing.T, port int, handler http.Handler) *httptest.Server {
  1317  	t.Helper()
  1318  	// Use mocked API response to avoid rate-limiting.
  1319  	l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
  1320  	require.NoError(t, err, "Unable to start server")
  1321  
  1322  	ts := httptest.NewUnstartedServer(handler)
  1323  
  1324  	ts.Listener.Close()
  1325  	ts.Listener = l
  1326  
  1327  	return ts
  1328  }
  1329  
  1330  func TestSimpleSCMProviderGenerator(t *testing.T) {
  1331  	ts := testServerWithPort(t, 8341, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1332  		githubSCMMockHandler(t)(w, r)
  1333  	}))
  1334  	ts.Start()
  1335  	defer ts.Close()
  1336  
  1337  	expectedApp := v1alpha1.Application{
  1338  		TypeMeta: metav1.TypeMeta{
  1339  			Kind:       application.ApplicationKind,
  1340  			APIVersion: "argoproj.io/v1alpha1",
  1341  		},
  1342  		ObjectMeta: metav1.ObjectMeta{
  1343  			Name:       "argo-cd-guestbook",
  1344  			Namespace:  fixture.TestNamespace(),
  1345  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
  1346  		},
  1347  		Spec: v1alpha1.ApplicationSpec{
  1348  			Project: "default",
  1349  			Source: &v1alpha1.ApplicationSource{
  1350  				RepoURL:        "git@github.com:argoproj/argo-cd.git",
  1351  				TargetRevision: "master",
  1352  				Path:           "guestbook",
  1353  			},
  1354  			Destination: v1alpha1.ApplicationDestination{
  1355  				Server:    "https://kubernetes.default.svc",
  1356  				Namespace: "guestbook",
  1357  			},
  1358  		},
  1359  	}
  1360  
  1361  	// Because you can't &"".
  1362  	repoMatch := "argo-cd"
  1363  
  1364  	Given(t).
  1365  		// Create an SCMProviderGenerator-based ApplicationSet
  1366  		When().Create(v1alpha1.ApplicationSet{
  1367  		ObjectMeta: metav1.ObjectMeta{
  1368  			Name: "simple-scm-provider-generator",
  1369  		},
  1370  		Spec: v1alpha1.ApplicationSetSpec{
  1371  			Template: v1alpha1.ApplicationSetTemplate{
  1372  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{ repository }}-guestbook"},
  1373  				Spec: v1alpha1.ApplicationSpec{
  1374  					Project: "default",
  1375  					Source: &v1alpha1.ApplicationSource{
  1376  						RepoURL:        "{{ url }}",
  1377  						TargetRevision: "{{ branch }}",
  1378  						Path:           "guestbook",
  1379  					},
  1380  					Destination: v1alpha1.ApplicationDestination{
  1381  						Server:    "https://kubernetes.default.svc",
  1382  						Namespace: "guestbook",
  1383  					},
  1384  				},
  1385  			},
  1386  			Generators: []v1alpha1.ApplicationSetGenerator{
  1387  				{
  1388  					SCMProvider: &v1alpha1.SCMProviderGenerator{
  1389  						Github: &v1alpha1.SCMProviderGeneratorGithub{
  1390  							Organization: "argoproj",
  1391  							API:          ts.URL,
  1392  						},
  1393  						Filters: []v1alpha1.SCMProviderGeneratorFilter{
  1394  							{
  1395  								RepositoryMatch: &repoMatch,
  1396  							},
  1397  						},
  1398  					},
  1399  				},
  1400  			},
  1401  		},
  1402  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp}))
  1403  }
  1404  
  1405  func TestSimpleSCMProviderGeneratorGoTemplate(t *testing.T) {
  1406  	ts := testServerWithPort(t, 8342, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1407  		githubSCMMockHandler(t)(w, r)
  1408  	}))
  1409  	ts.Start()
  1410  	defer ts.Close()
  1411  
  1412  	expectedApp := v1alpha1.Application{
  1413  		TypeMeta: metav1.TypeMeta{
  1414  			Kind:       application.ApplicationKind,
  1415  			APIVersion: "argoproj.io/v1alpha1",
  1416  		},
  1417  		ObjectMeta: metav1.ObjectMeta{
  1418  			Name:       "argo-cd-guestbook",
  1419  			Namespace:  fixture.TestNamespace(),
  1420  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
  1421  		},
  1422  		Spec: v1alpha1.ApplicationSpec{
  1423  			Project: "default",
  1424  			Source: &v1alpha1.ApplicationSource{
  1425  				RepoURL:        "git@github.com:argoproj/argo-cd.git",
  1426  				TargetRevision: "master",
  1427  				Path:           "guestbook",
  1428  			},
  1429  			Destination: v1alpha1.ApplicationDestination{
  1430  				Server:    "https://kubernetes.default.svc",
  1431  				Namespace: "guestbook",
  1432  			},
  1433  		},
  1434  	}
  1435  
  1436  	// Because you can't &"".
  1437  	repoMatch := "argo-cd"
  1438  
  1439  	Given(t).
  1440  		// Create an SCMProviderGenerator-based ApplicationSet
  1441  		When().Create(v1alpha1.ApplicationSet{
  1442  		ObjectMeta: metav1.ObjectMeta{
  1443  			Name: "simple-scm-provider-generator",
  1444  		},
  1445  		Spec: v1alpha1.ApplicationSetSpec{
  1446  			GoTemplate: true,
  1447  			Template: v1alpha1.ApplicationSetTemplate{
  1448  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{ .repository }}-guestbook"},
  1449  				Spec: v1alpha1.ApplicationSpec{
  1450  					Project: "default",
  1451  					Source: &v1alpha1.ApplicationSource{
  1452  						RepoURL:        "{{ .url }}",
  1453  						TargetRevision: "{{ .branch }}",
  1454  						Path:           "guestbook",
  1455  					},
  1456  					Destination: v1alpha1.ApplicationDestination{
  1457  						Server:    "https://kubernetes.default.svc",
  1458  						Namespace: "guestbook",
  1459  					},
  1460  				},
  1461  			},
  1462  			Generators: []v1alpha1.ApplicationSetGenerator{
  1463  				{
  1464  					SCMProvider: &v1alpha1.SCMProviderGenerator{
  1465  						Github: &v1alpha1.SCMProviderGeneratorGithub{
  1466  							Organization: "argoproj",
  1467  							API:          ts.URL,
  1468  						},
  1469  						Filters: []v1alpha1.SCMProviderGeneratorFilter{
  1470  							{
  1471  								RepositoryMatch: &repoMatch,
  1472  							},
  1473  						},
  1474  					},
  1475  				},
  1476  			},
  1477  		},
  1478  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp}))
  1479  }
  1480  
  1481  func TestSCMProviderGeneratorSCMProviderNotAllowed(t *testing.T) {
  1482  	expectedApp := v1alpha1.Application{
  1483  		TypeMeta: metav1.TypeMeta{
  1484  			Kind:       application.ApplicationKind,
  1485  			APIVersion: "argoproj.io/v1alpha1",
  1486  		},
  1487  		ObjectMeta: metav1.ObjectMeta{
  1488  			Name:       "argo-cd-guestbook",
  1489  			Namespace:  fixture.TestNamespace(),
  1490  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
  1491  		},
  1492  		Spec: v1alpha1.ApplicationSpec{
  1493  			Project: "default",
  1494  			Source: &v1alpha1.ApplicationSource{
  1495  				RepoURL:        "git@github.com:argoproj/argo-cd.git",
  1496  				TargetRevision: "master",
  1497  				Path:           "guestbook",
  1498  			},
  1499  			Destination: v1alpha1.ApplicationDestination{
  1500  				Server:    "https://kubernetes.default.svc",
  1501  				Namespace: "guestbook",
  1502  			},
  1503  		},
  1504  	}
  1505  
  1506  	// Because you can't &"".
  1507  	repoMatch := "argo-cd"
  1508  
  1509  	Given(t).
  1510  		// Create an SCMProviderGenerator-based ApplicationSet
  1511  		When().Create(v1alpha1.ApplicationSet{
  1512  		ObjectMeta: metav1.ObjectMeta{
  1513  			Name: "scm-provider-generator-scm-provider-not-allowed",
  1514  		},
  1515  		Spec: v1alpha1.ApplicationSetSpec{
  1516  			GoTemplate: true,
  1517  			Template: v1alpha1.ApplicationSetTemplate{
  1518  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{ .repository }}-guestbook"},
  1519  				Spec: v1alpha1.ApplicationSpec{
  1520  					Project: "default",
  1521  					Source: &v1alpha1.ApplicationSource{
  1522  						RepoURL:        "{{ .url }}",
  1523  						TargetRevision: "{{ .branch }}",
  1524  						Path:           "guestbook",
  1525  					},
  1526  					Destination: v1alpha1.ApplicationDestination{
  1527  						Server:    "https://kubernetes.default.svc",
  1528  						Namespace: "guestbook",
  1529  					},
  1530  				},
  1531  			},
  1532  			Generators: []v1alpha1.ApplicationSetGenerator{
  1533  				{
  1534  					SCMProvider: &v1alpha1.SCMProviderGenerator{
  1535  						Github: &v1alpha1.SCMProviderGeneratorGithub{
  1536  							Organization: "argoproj",
  1537  							API:          "http://myservice.mynamespace.svc.cluster.local",
  1538  						},
  1539  						Filters: []v1alpha1.SCMProviderGeneratorFilter{
  1540  							{
  1541  								RepositoryMatch: &repoMatch,
  1542  							},
  1543  						},
  1544  					},
  1545  				},
  1546  			},
  1547  		},
  1548  	}).Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{expectedApp})).
  1549  		And(func() {
  1550  			// app should be listed
  1551  			output, err := fixture.RunCli("appset", "get", "scm-provider-generator-scm-provider-not-allowed")
  1552  			require.NoError(t, err)
  1553  			assert.Contains(t, output, "scm provider not allowed")
  1554  		})
  1555  }
  1556  
  1557  func TestCustomApplicationFinalizers(t *testing.T) {
  1558  	expectedApp := v1alpha1.Application{
  1559  		TypeMeta: metav1.TypeMeta{
  1560  			Kind:       application.ApplicationKind,
  1561  			APIVersion: "argoproj.io/v1alpha1",
  1562  		},
  1563  		ObjectMeta: metav1.ObjectMeta{
  1564  			Name:       "my-cluster-guestbook",
  1565  			Namespace:  fixture.TestNamespace(),
  1566  			Finalizers: []string{v1alpha1.BackgroundPropagationPolicyFinalizer},
  1567  		},
  1568  		Spec: v1alpha1.ApplicationSpec{
  1569  			Project: "default",
  1570  			Source: &v1alpha1.ApplicationSource{
  1571  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
  1572  				TargetRevision: "HEAD",
  1573  				Path:           "guestbook",
  1574  			},
  1575  			Destination: v1alpha1.ApplicationDestination{
  1576  				Server:    "https://kubernetes.default.svc",
  1577  				Namespace: "guestbook",
  1578  			},
  1579  		},
  1580  	}
  1581  
  1582  	Given(t).
  1583  		// Create a ListGenerator-based ApplicationSet
  1584  		When().Create(v1alpha1.ApplicationSet{
  1585  		ObjectMeta: metav1.ObjectMeta{
  1586  			Name: "simple-list-generator",
  1587  		},
  1588  		Spec: v1alpha1.ApplicationSetSpec{
  1589  			Template: v1alpha1.ApplicationSetTemplate{
  1590  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{
  1591  					Name:       "{{cluster}}-guestbook",
  1592  					Finalizers: []string{v1alpha1.BackgroundPropagationPolicyFinalizer},
  1593  				},
  1594  				Spec: v1alpha1.ApplicationSpec{
  1595  					Project: "default",
  1596  					Source: &v1alpha1.ApplicationSource{
  1597  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
  1598  						TargetRevision: "HEAD",
  1599  						Path:           "guestbook",
  1600  					},
  1601  					Destination: v1alpha1.ApplicationDestination{
  1602  						Server:    "{{url}}",
  1603  						Namespace: "guestbook",
  1604  					},
  1605  				},
  1606  			},
  1607  			Generators: []v1alpha1.ApplicationSetGenerator{
  1608  				{
  1609  					List: &v1alpha1.ListGenerator{
  1610  						Elements: []apiextensionsv1.JSON{{
  1611  							Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc"}`),
  1612  						}},
  1613  					},
  1614  				},
  1615  			},
  1616  		},
  1617  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
  1618  
  1619  		// Delete the ApplicationSet, and verify it deletes the Applications
  1620  		When().
  1621  		Delete().Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{expectedApp}))
  1622  }
  1623  
  1624  func TestCustomApplicationFinalizersGoTemplate(t *testing.T) {
  1625  	expectedApp := v1alpha1.Application{
  1626  		TypeMeta: metav1.TypeMeta{
  1627  			Kind:       application.ApplicationKind,
  1628  			APIVersion: "argoproj.io/v1alpha1",
  1629  		},
  1630  		ObjectMeta: metav1.ObjectMeta{
  1631  			Name:       "my-cluster-guestbook",
  1632  			Namespace:  fixture.TestNamespace(),
  1633  			Finalizers: []string{v1alpha1.BackgroundPropagationPolicyFinalizer},
  1634  		},
  1635  		Spec: v1alpha1.ApplicationSpec{
  1636  			Project: "default",
  1637  			Source: &v1alpha1.ApplicationSource{
  1638  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
  1639  				TargetRevision: "HEAD",
  1640  				Path:           "guestbook",
  1641  			},
  1642  			Destination: v1alpha1.ApplicationDestination{
  1643  				Server:    "https://kubernetes.default.svc",
  1644  				Namespace: "guestbook",
  1645  			},
  1646  		},
  1647  	}
  1648  
  1649  	Given(t).
  1650  		// Create a ListGenerator-based ApplicationSet
  1651  		When().Create(v1alpha1.ApplicationSet{
  1652  		ObjectMeta: metav1.ObjectMeta{
  1653  			Name: "simple-list-generator",
  1654  		},
  1655  		Spec: v1alpha1.ApplicationSetSpec{
  1656  			GoTemplate: true,
  1657  			Template: v1alpha1.ApplicationSetTemplate{
  1658  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{
  1659  					Name:       "{{.cluster}}-guestbook",
  1660  					Finalizers: []string{v1alpha1.BackgroundPropagationPolicyFinalizer},
  1661  				},
  1662  				Spec: v1alpha1.ApplicationSpec{
  1663  					Project: "default",
  1664  					Source: &v1alpha1.ApplicationSource{
  1665  						RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
  1666  						TargetRevision: "HEAD",
  1667  						Path:           "guestbook",
  1668  					},
  1669  					Destination: v1alpha1.ApplicationDestination{
  1670  						Server:    "{{.url}}",
  1671  						Namespace: "guestbook",
  1672  					},
  1673  				},
  1674  			},
  1675  			Generators: []v1alpha1.ApplicationSetGenerator{
  1676  				{
  1677  					List: &v1alpha1.ListGenerator{
  1678  						Elements: []apiextensionsv1.JSON{{
  1679  							Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc"}`),
  1680  						}},
  1681  					},
  1682  				},
  1683  			},
  1684  		},
  1685  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
  1686  
  1687  		// Delete the ApplicationSet, and verify it deletes the Applications
  1688  		When().
  1689  		Delete().Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{expectedApp}))
  1690  }
  1691  
  1692  func githubPullMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
  1693  	t.Helper()
  1694  	return func(w http.ResponseWriter, r *http.Request) {
  1695  		w.Header().Set("Content-Type", "application/json")
  1696  		switch r.RequestURI {
  1697  		case "/api/v3/repos/applicationset-test-org/argocd-example-apps/pulls?per_page=100":
  1698  			_, err := io.WriteString(w, `[
  1699    {
  1700      "number": 1,
  1701      "title": "title1",
  1702      "labels": [
  1703        {
  1704          "name": "preview"
  1705        }
  1706      ],
  1707  	"base": {
  1708  		"ref": "master",
  1709  		"sha": "7a4a5c987fdfb2b0629e9dbf5f31636c69ba4775"
  1710  	},
  1711      "head": {
  1712        "ref": "pull-request",
  1713        "sha": "824a5c987fdfb2b0629e9dbf5f31636c69ba4772"
  1714      },
  1715  	"user": {
  1716  	  "login": "testName"
  1717  	}
  1718    }
  1719  ]`)
  1720  			if err != nil {
  1721  				t.Fail()
  1722  			}
  1723  		default:
  1724  			w.WriteHeader(http.StatusNotFound)
  1725  		}
  1726  	}
  1727  }
  1728  
  1729  func TestSimpleSCMProviderGeneratorTokenRefStrictOk(t *testing.T) {
  1730  	secretName := uuid.New().String()
  1731  
  1732  	ts := testServerWithPort(t, 8341, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1733  		githubSCMMockHandler(t)(w, r)
  1734  	}))
  1735  
  1736  	ts.Start()
  1737  	defer ts.Close()
  1738  
  1739  	expectedApp := v1alpha1.Application{
  1740  		TypeMeta: metav1.TypeMeta{
  1741  			Kind:       application.ApplicationKind,
  1742  			APIVersion: "argoproj.io/v1alpha1",
  1743  		},
  1744  		ObjectMeta: metav1.ObjectMeta{
  1745  			Name:       "argo-cd-guestbook",
  1746  			Namespace:  fixture.TestNamespace(),
  1747  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
  1748  		},
  1749  		Spec: v1alpha1.ApplicationSpec{
  1750  			Project: "default",
  1751  			Source: &v1alpha1.ApplicationSource{
  1752  				RepoURL:        "git@github.com:argoproj/argo-cd.git",
  1753  				TargetRevision: "master",
  1754  				Path:           "guestbook",
  1755  			},
  1756  			Destination: v1alpha1.ApplicationDestination{
  1757  				Server:    "https://kubernetes.default.svc",
  1758  				Namespace: "guestbook",
  1759  			},
  1760  		},
  1761  	}
  1762  
  1763  	// Because you can't &"".
  1764  	repoMatch := "argo-cd"
  1765  
  1766  	Given(t).
  1767  		And(func() {
  1768  			_, err := utils.GetE2EFixtureK8sClient(t).KubeClientset.CoreV1().Secrets(fixture.TestNamespace()).Create(t.Context(), &corev1.Secret{
  1769  				ObjectMeta: metav1.ObjectMeta{
  1770  					Namespace: fixture.TestNamespace(),
  1771  					Name:      secretName,
  1772  					Labels: map[string]string{
  1773  						common.LabelKeySecretType: common.LabelValueSecretTypeSCMCreds,
  1774  					},
  1775  				},
  1776  				Data: map[string][]byte{
  1777  					"hello": []byte("world"),
  1778  				},
  1779  			}, metav1.CreateOptions{})
  1780  
  1781  			assert.NoError(t, err)
  1782  		}).
  1783  		// Create an SCMProviderGenerator-based ApplicationSet
  1784  		When().Create(v1alpha1.ApplicationSet{
  1785  		ObjectMeta: metav1.ObjectMeta{
  1786  			Name: "simple-scm-provider-generator-strict",
  1787  		},
  1788  		Spec: v1alpha1.ApplicationSetSpec{
  1789  			Template: v1alpha1.ApplicationSetTemplate{
  1790  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{ repository }}-guestbook"},
  1791  				Spec: v1alpha1.ApplicationSpec{
  1792  					Project: "default",
  1793  					Source: &v1alpha1.ApplicationSource{
  1794  						RepoURL:        "{{ url }}",
  1795  						TargetRevision: "{{ branch }}",
  1796  						Path:           "guestbook",
  1797  					},
  1798  					Destination: v1alpha1.ApplicationDestination{
  1799  						Server:    "https://kubernetes.default.svc",
  1800  						Namespace: "guestbook",
  1801  					},
  1802  				},
  1803  			},
  1804  			Generators: []v1alpha1.ApplicationSetGenerator{
  1805  				{
  1806  					SCMProvider: &v1alpha1.SCMProviderGenerator{
  1807  						Github: &v1alpha1.SCMProviderGeneratorGithub{
  1808  							Organization: "argoproj",
  1809  							API:          ts.URL,
  1810  							TokenRef: &v1alpha1.SecretRef{
  1811  								SecretName: secretName,
  1812  								Key:        "hello",
  1813  							},
  1814  						},
  1815  						Filters: []v1alpha1.SCMProviderGeneratorFilter{
  1816  							{
  1817  								RepositoryMatch: &repoMatch,
  1818  							},
  1819  						},
  1820  					},
  1821  				},
  1822  			},
  1823  		},
  1824  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp})).
  1825  		When().And(func() {
  1826  		err := utils.GetE2EFixtureK8sClient(t).KubeClientset.CoreV1().Secrets(fixture.TestNamespace()).Delete(t.Context(), secretName, metav1.DeleteOptions{})
  1827  		assert.NoError(t, err)
  1828  	})
  1829  }
  1830  
  1831  func TestSimpleSCMProviderGeneratorTokenRefStrictKo(t *testing.T) {
  1832  	secretName := uuid.New().String()
  1833  
  1834  	ts := testServerWithPort(t, 8341, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1835  		githubSCMMockHandler(t)(w, r)
  1836  	}))
  1837  
  1838  	ts.Start()
  1839  	defer ts.Close()
  1840  
  1841  	expectedApp := v1alpha1.Application{
  1842  		TypeMeta: metav1.TypeMeta{
  1843  			Kind:       application.ApplicationKind,
  1844  			APIVersion: "argoproj.io/v1alpha1",
  1845  		},
  1846  		ObjectMeta: metav1.ObjectMeta{
  1847  			Name:       "argo-cd-guestbook",
  1848  			Namespace:  fixture.TestNamespace(),
  1849  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
  1850  			Labels: map[string]string{
  1851  				common.LabelKeyAppInstance: "simple-scm-provider-generator-strict-ko",
  1852  			},
  1853  		},
  1854  		Spec: v1alpha1.ApplicationSpec{
  1855  			Project: "default",
  1856  			Source: &v1alpha1.ApplicationSource{
  1857  				RepoURL:        "git@github.com:argoproj/argo-cd.git",
  1858  				TargetRevision: "master",
  1859  				Path:           "guestbook",
  1860  			},
  1861  			Destination: v1alpha1.ApplicationDestination{
  1862  				Server:    "https://kubernetes.default.svc",
  1863  				Namespace: "guestbook",
  1864  			},
  1865  		},
  1866  	}
  1867  
  1868  	// Because you can't &"".
  1869  	repoMatch := "argo-cd"
  1870  
  1871  	Given(t).
  1872  		And(func() {
  1873  			_, err := utils.GetE2EFixtureK8sClient(t).KubeClientset.CoreV1().Secrets(fixture.TestNamespace()).Create(t.Context(), &corev1.Secret{
  1874  				ObjectMeta: metav1.ObjectMeta{
  1875  					Namespace: fixture.TestNamespace(),
  1876  					Name:      secretName,
  1877  					Labels: map[string]string{
  1878  						// Try to exfiltrate cluster secret
  1879  						common.LabelKeySecretType: common.LabelValueSecretTypeCluster,
  1880  					},
  1881  				},
  1882  				Data: map[string][]byte{
  1883  					"hello": []byte("world"),
  1884  				},
  1885  			}, metav1.CreateOptions{})
  1886  
  1887  			assert.NoError(t, err)
  1888  		}).
  1889  		// Create an SCMProviderGenerator-based ApplicationSet
  1890  		When().Create(v1alpha1.ApplicationSet{
  1891  		ObjectMeta: metav1.ObjectMeta{
  1892  			Name: "simple-scm-provider-generator-strict-ko",
  1893  		},
  1894  		Spec: v1alpha1.ApplicationSetSpec{
  1895  			Template: v1alpha1.ApplicationSetTemplate{
  1896  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{ repository }}-guestbook"},
  1897  				Spec: v1alpha1.ApplicationSpec{
  1898  					Project: "default",
  1899  					Source: &v1alpha1.ApplicationSource{
  1900  						RepoURL:        "{{ url }}",
  1901  						TargetRevision: "{{ branch }}",
  1902  						Path:           "guestbook",
  1903  					},
  1904  					Destination: v1alpha1.ApplicationDestination{
  1905  						Server:    "https://kubernetes.default.svc",
  1906  						Namespace: "guestbook",
  1907  					},
  1908  				},
  1909  			},
  1910  			Generators: []v1alpha1.ApplicationSetGenerator{
  1911  				{
  1912  					SCMProvider: &v1alpha1.SCMProviderGenerator{
  1913  						Github: &v1alpha1.SCMProviderGeneratorGithub{
  1914  							Organization: "argoproj",
  1915  							API:          ts.URL,
  1916  							TokenRef: &v1alpha1.SecretRef{
  1917  								SecretName: secretName,
  1918  								Key:        "hello",
  1919  							},
  1920  						},
  1921  						Filters: []v1alpha1.SCMProviderGeneratorFilter{
  1922  							{
  1923  								RepositoryMatch: &repoMatch,
  1924  							},
  1925  						},
  1926  					},
  1927  				},
  1928  			},
  1929  		},
  1930  	}).Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{expectedApp})).
  1931  		When().
  1932  		And(func() {
  1933  			// app should be listed
  1934  			output, err := fixture.RunCli("appset", "get", "simple-scm-provider-generator-strict-ko")
  1935  			require.NoError(t, err)
  1936  			assert.Contains(t, output, fmt.Sprintf("scm provider: error fetching Github token: secret %s/%s is not a valid SCM creds secret", fixture.TestNamespace(), secretName))
  1937  			err2 := utils.GetE2EFixtureK8sClient(t).KubeClientset.CoreV1().Secrets(fixture.TestNamespace()).Delete(t.Context(), secretName, metav1.DeleteOptions{})
  1938  			assert.NoError(t, err2)
  1939  		})
  1940  }
  1941  
  1942  func TestSimplePullRequestGenerator(t *testing.T) {
  1943  	ts := testServerWithPort(t, 8343, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1944  		githubPullMockHandler(t)(w, r)
  1945  	}))
  1946  
  1947  	ts.Start()
  1948  	defer ts.Close()
  1949  
  1950  	expectedApp := v1alpha1.Application{
  1951  		TypeMeta: metav1.TypeMeta{
  1952  			Kind:       application.ApplicationKind,
  1953  			APIVersion: "argoproj.io/v1alpha1",
  1954  		},
  1955  		ObjectMeta: metav1.ObjectMeta{
  1956  			Name:       "guestbook-1",
  1957  			Namespace:  fixture.TestNamespace(),
  1958  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
  1959  		},
  1960  		Spec: v1alpha1.ApplicationSpec{
  1961  			Project: "default",
  1962  			Source: &v1alpha1.ApplicationSource{
  1963  				RepoURL:        "git@github.com:applicationset-test-org/argocd-example-apps.git",
  1964  				TargetRevision: "824a5c987fdfb2b0629e9dbf5f31636c69ba4772",
  1965  				Path:           "kustomize-guestbook",
  1966  				Kustomize: &v1alpha1.ApplicationSourceKustomize{
  1967  					NamePrefix: "guestbook-1",
  1968  				},
  1969  			},
  1970  			Destination: v1alpha1.ApplicationDestination{
  1971  				Server:    "https://kubernetes.default.svc",
  1972  				Namespace: "guestbook-pull-request",
  1973  			},
  1974  		},
  1975  	}
  1976  
  1977  	Given(t).
  1978  		// Create an PullRequestGenerator-based ApplicationSet
  1979  		When().Create(v1alpha1.ApplicationSet{
  1980  		ObjectMeta: metav1.ObjectMeta{
  1981  			Name: "simple-pull-request-generator",
  1982  		},
  1983  		Spec: v1alpha1.ApplicationSetSpec{
  1984  			Template: v1alpha1.ApplicationSetTemplate{
  1985  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "guestbook-{{ number }}"},
  1986  				Spec: v1alpha1.ApplicationSpec{
  1987  					Project: "default",
  1988  					Source: &v1alpha1.ApplicationSource{
  1989  						RepoURL:        "git@github.com:applicationset-test-org/argocd-example-apps.git",
  1990  						TargetRevision: "{{ head_sha }}",
  1991  						Path:           "kustomize-guestbook",
  1992  						Kustomize: &v1alpha1.ApplicationSourceKustomize{
  1993  							NamePrefix: "guestbook-{{ number }}",
  1994  						},
  1995  					},
  1996  					Destination: v1alpha1.ApplicationDestination{
  1997  						Server:    "https://kubernetes.default.svc",
  1998  						Namespace: "guestbook-{{ branch }}",
  1999  					},
  2000  				},
  2001  			},
  2002  			Generators: []v1alpha1.ApplicationSetGenerator{
  2003  				{
  2004  					PullRequest: &v1alpha1.PullRequestGenerator{
  2005  						Github: &v1alpha1.PullRequestGeneratorGithub{
  2006  							API:   ts.URL,
  2007  							Owner: "applicationset-test-org",
  2008  							Repo:  "argocd-example-apps",
  2009  							Labels: []string{
  2010  								"preview",
  2011  							},
  2012  						},
  2013  					},
  2014  				},
  2015  			},
  2016  		},
  2017  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp}))
  2018  }
  2019  
  2020  func TestSimplePullRequestGeneratorGoTemplate(t *testing.T) {
  2021  	ts := testServerWithPort(t, 8344, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  2022  		githubPullMockHandler(t)(w, r)
  2023  	}))
  2024  
  2025  	ts.Start()
  2026  	defer ts.Close()
  2027  
  2028  	expectedApp := v1alpha1.Application{
  2029  		TypeMeta: metav1.TypeMeta{
  2030  			Kind:       application.ApplicationKind,
  2031  			APIVersion: "argoproj.io/v1alpha1",
  2032  		},
  2033  		ObjectMeta: metav1.ObjectMeta{
  2034  			Name:       "guestbook-1",
  2035  			Namespace:  fixture.TestNamespace(),
  2036  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
  2037  			Labels:     map[string]string{"app": "preview"},
  2038  		},
  2039  		Spec: v1alpha1.ApplicationSpec{
  2040  			Project: "default",
  2041  			Source: &v1alpha1.ApplicationSource{
  2042  				RepoURL:        "git@github.com:applicationset-test-org/argocd-example-apps.git",
  2043  				TargetRevision: "824a5c987fdfb2b0629e9dbf5f31636c69ba4772",
  2044  				Path:           "kustomize-guestbook",
  2045  				Kustomize: &v1alpha1.ApplicationSourceKustomize{
  2046  					NamePrefix: "guestbook-1",
  2047  				},
  2048  			},
  2049  			Destination: v1alpha1.ApplicationDestination{
  2050  				Server:    "https://kubernetes.default.svc",
  2051  				Namespace: "guestbook-pull-request",
  2052  			},
  2053  		},
  2054  	}
  2055  
  2056  	Given(t).
  2057  		// Create an PullRequestGenerator-based ApplicationSet
  2058  		When().Create(v1alpha1.ApplicationSet{
  2059  		ObjectMeta: metav1.ObjectMeta{
  2060  			Name: "simple-pull-request-generator",
  2061  		},
  2062  		Spec: v1alpha1.ApplicationSetSpec{
  2063  			GoTemplate: true,
  2064  			Template: v1alpha1.ApplicationSetTemplate{
  2065  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{
  2066  					Name:   "guestbook-{{ .number }}",
  2067  					Labels: map[string]string{"app": "{{index .labels 0}}"},
  2068  				},
  2069  				Spec: v1alpha1.ApplicationSpec{
  2070  					Project: "default",
  2071  					Source: &v1alpha1.ApplicationSource{
  2072  						RepoURL:        "git@github.com:applicationset-test-org/argocd-example-apps.git",
  2073  						TargetRevision: "{{ .head_sha }}",
  2074  						Path:           "kustomize-guestbook",
  2075  						Kustomize: &v1alpha1.ApplicationSourceKustomize{
  2076  							NamePrefix: "guestbook-{{ .number }}",
  2077  						},
  2078  					},
  2079  					Destination: v1alpha1.ApplicationDestination{
  2080  						Server:    "https://kubernetes.default.svc",
  2081  						Namespace: "guestbook-{{ .branch }}",
  2082  					},
  2083  				},
  2084  			},
  2085  			Generators: []v1alpha1.ApplicationSetGenerator{
  2086  				{
  2087  					PullRequest: &v1alpha1.PullRequestGenerator{
  2088  						Github: &v1alpha1.PullRequestGeneratorGithub{
  2089  							API:   ts.URL,
  2090  							Owner: "applicationset-test-org",
  2091  							Repo:  "argocd-example-apps",
  2092  							Labels: []string{
  2093  								"preview",
  2094  							},
  2095  						},
  2096  					},
  2097  				},
  2098  			},
  2099  		},
  2100  	}).Then().Expect(ApplicationsExist([]v1alpha1.Application{expectedApp}))
  2101  }
  2102  
  2103  func TestPullRequestGeneratorNotAllowedSCMProvider(t *testing.T) {
  2104  	expectedApp := v1alpha1.Application{
  2105  		TypeMeta: metav1.TypeMeta{
  2106  			Kind:       application.ApplicationKind,
  2107  			APIVersion: "argoproj.io/v1alpha1",
  2108  		},
  2109  		ObjectMeta: metav1.ObjectMeta{
  2110  			Name:       "guestbook-1",
  2111  			Namespace:  fixture.TestNamespace(),
  2112  			Finalizers: []string{v1alpha1.ResourcesFinalizerName},
  2113  			Labels: map[string]string{
  2114  				"app": "preview",
  2115  			},
  2116  		},
  2117  		Spec: v1alpha1.ApplicationSpec{
  2118  			Project: "default",
  2119  			Source: &v1alpha1.ApplicationSource{
  2120  				RepoURL:        "git@github.com:applicationset-test-org/argocd-example-apps.git",
  2121  				TargetRevision: "824a5c987fdfb2b0629e9dbf5f31636c69ba4772",
  2122  				Path:           "kustomize-guestbook",
  2123  				Kustomize: &v1alpha1.ApplicationSourceKustomize{
  2124  					NamePrefix: "guestbook-1",
  2125  				},
  2126  			},
  2127  			Destination: v1alpha1.ApplicationDestination{
  2128  				Server:    "https://kubernetes.default.svc",
  2129  				Namespace: "guestbook-pull-request",
  2130  			},
  2131  		},
  2132  	}
  2133  
  2134  	Given(t).
  2135  		// Create an PullRequestGenerator-based ApplicationSet
  2136  		When().Create(v1alpha1.ApplicationSet{
  2137  		ObjectMeta: metav1.ObjectMeta{
  2138  			Name: "pull-request-generator-not-allowed-scm",
  2139  		},
  2140  		Spec: v1alpha1.ApplicationSetSpec{
  2141  			GoTemplate: true,
  2142  			Template: v1alpha1.ApplicationSetTemplate{
  2143  				ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{
  2144  					Name:   "guestbook-{{ .number }}",
  2145  					Labels: map[string]string{"app": "{{index .labels 0}}"},
  2146  				},
  2147  				Spec: v1alpha1.ApplicationSpec{
  2148  					Project: "default",
  2149  					Source: &v1alpha1.ApplicationSource{
  2150  						RepoURL:        "git@github.com:applicationset-test-org/argocd-example-apps.git",
  2151  						TargetRevision: "{{ .head_sha }}",
  2152  						Path:           "kustomize-guestbook",
  2153  						Kustomize: &v1alpha1.ApplicationSourceKustomize{
  2154  							NamePrefix: "guestbook-{{ .number }}",
  2155  						},
  2156  					},
  2157  					Destination: v1alpha1.ApplicationDestination{
  2158  						Server:    "https://kubernetes.default.svc",
  2159  						Namespace: "guestbook-{{ .branch }}",
  2160  					},
  2161  				},
  2162  			},
  2163  			Generators: []v1alpha1.ApplicationSetGenerator{
  2164  				{
  2165  					PullRequest: &v1alpha1.PullRequestGenerator{
  2166  						Github: &v1alpha1.PullRequestGeneratorGithub{
  2167  							API:   "http://myservice.mynamespace.svc.cluster.local",
  2168  							Owner: "applicationset-test-org",
  2169  							Repo:  "argocd-example-apps",
  2170  							Labels: []string{
  2171  								"preview",
  2172  							},
  2173  						},
  2174  					},
  2175  				},
  2176  			},
  2177  		},
  2178  	}).Then().Expect(ApplicationsDoNotExist([]v1alpha1.Application{expectedApp})).
  2179  		And(func() {
  2180  			// app should be listed
  2181  			output, err := fixture.RunCli("appset", "get", "pull-request-generator-not-allowed-scm")
  2182  			require.NoError(t, err)
  2183  			assert.Contains(t, output, "scm provider not allowed")
  2184  		})
  2185  }