github.com/argoproj/argo-cd/v2@v2.10.5/test/e2e/cluster_generator_test.go (about)

     1  package e2e
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/argoproj/argo-cd/v2/test/e2e/fixture"
     8  
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  
    11  	"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
    12  	argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
    13  	. "github.com/argoproj/argo-cd/v2/test/e2e/fixture/applicationsets"
    14  	"github.com/argoproj/argo-cd/v2/test/e2e/fixture/applicationsets/utils"
    15  
    16  	"github.com/argoproj/argo-cd/v2/pkg/apis/application"
    17  )
    18  
    19  func TestSimpleClusterGeneratorExternalNamespace(t *testing.T) {
    20  
    21  	var externalNamespace = string(utils.ArgoCDExternalNamespace)
    22  
    23  	expectedApp := argov1alpha1.Application{
    24  		TypeMeta: metav1.TypeMeta{
    25  			Kind:       "Application",
    26  			APIVersion: "argoproj.io/v1alpha1",
    27  		},
    28  		ObjectMeta: metav1.ObjectMeta{
    29  			Name:       "cluster1-guestbook",
    30  			Namespace:  externalNamespace,
    31  			Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
    32  		},
    33  		Spec: argov1alpha1.ApplicationSpec{
    34  			Project: "default",
    35  			Source: &argov1alpha1.ApplicationSource{
    36  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
    37  				TargetRevision: "HEAD",
    38  				Path:           "guestbook",
    39  			},
    40  			Destination: argov1alpha1.ApplicationDestination{
    41  				Name:      "cluster1",
    42  				Namespace: "guestbook",
    43  			},
    44  		},
    45  	}
    46  
    47  	var expectedAppNewNamespace *argov1alpha1.Application
    48  	var expectedAppNewMetadata *argov1alpha1.Application
    49  
    50  	Given(t).
    51  		// Create a ClusterGenerator-based ApplicationSet
    52  		When().
    53  		CreateClusterSecret("my-secret", "cluster1", "https://kubernetes.default.svc").
    54  		SwitchToExternalNamespace(utils.ArgoCDExternalNamespace).
    55  		CreateNamespace(externalNamespace).
    56  		Create(v1alpha1.ApplicationSet{ObjectMeta: metav1.ObjectMeta{
    57  			Name: "simple-cluster-generator",
    58  		},
    59  			Spec: v1alpha1.ApplicationSetSpec{
    60  				Template: v1alpha1.ApplicationSetTemplate{
    61  					ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"},
    62  					Spec: argov1alpha1.ApplicationSpec{
    63  						Project: "default",
    64  						Source: &argov1alpha1.ApplicationSource{
    65  							RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
    66  							TargetRevision: "HEAD",
    67  							Path:           "guestbook",
    68  						},
    69  						Destination: argov1alpha1.ApplicationDestination{
    70  							Name: "{{name}}",
    71  							// Server:    "{{server}}",
    72  							Namespace: "guestbook",
    73  						},
    74  					},
    75  				},
    76  				Generators: []v1alpha1.ApplicationSetGenerator{
    77  					{
    78  						Clusters: &v1alpha1.ClusterGenerator{
    79  							Selector: metav1.LabelSelector{
    80  								MatchLabels: map[string]string{
    81  									"argocd.argoproj.io/secret-type": "cluster",
    82  								},
    83  							},
    84  						},
    85  					},
    86  				},
    87  			},
    88  		}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{expectedApp})).
    89  
    90  		// Update the ApplicationSet template namespace, and verify it updates the Applications
    91  		When().
    92  		And(func() {
    93  			expectedAppNewNamespace = expectedApp.DeepCopy()
    94  			expectedAppNewNamespace.Spec.Destination.Namespace = "guestbook2"
    95  		}).
    96  		Update(func(appset *v1alpha1.ApplicationSet) {
    97  			appset.Spec.Template.Spec.Destination.Namespace = "guestbook2"
    98  		}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{*expectedAppNewNamespace})).
    99  
   100  		// Update the metadata fields in the appset template, and make sure it propagates to the apps
   101  		When().
   102  		And(func() {
   103  			expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
   104  			expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
   105  			expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
   106  				"label-key": "label-value",
   107  			}
   108  		}).
   109  		Update(func(appset *v1alpha1.ApplicationSet) {
   110  			appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
   111  			appset.Spec.Template.Labels = map[string]string{
   112  				"label-key": "label-value",
   113  			}
   114  		}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{*expectedAppNewMetadata})).
   115  
   116  		// Delete the ApplicationSet, and verify it deletes the Applications
   117  		When().
   118  		Delete().Then().Expect(ApplicationsDoNotExist([]argov1alpha1.Application{*expectedAppNewNamespace}))
   119  }
   120  
   121  func TestSimpleClusterGenerator(t *testing.T) {
   122  
   123  	expectedApp := argov1alpha1.Application{
   124  		TypeMeta: metav1.TypeMeta{
   125  			Kind:       application.ApplicationKind,
   126  			APIVersion: "argoproj.io/v1alpha1",
   127  		},
   128  		ObjectMeta: metav1.ObjectMeta{
   129  			Name:       "cluster1-guestbook",
   130  			Namespace:  fixture.TestNamespace(),
   131  			Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
   132  		},
   133  		Spec: argov1alpha1.ApplicationSpec{
   134  			Project: "default",
   135  			Source: &argov1alpha1.ApplicationSource{
   136  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   137  				TargetRevision: "HEAD",
   138  				Path:           "guestbook",
   139  			},
   140  			Destination: argov1alpha1.ApplicationDestination{
   141  				Name:      "cluster1",
   142  				Namespace: "guestbook",
   143  			},
   144  		},
   145  	}
   146  
   147  	var expectedAppNewNamespace *argov1alpha1.Application
   148  	var expectedAppNewMetadata *argov1alpha1.Application
   149  
   150  	Given(t).
   151  		// Create a ClusterGenerator-based ApplicationSet
   152  		When().
   153  		CreateClusterSecret("my-secret", "cluster1", "https://kubernetes.default.svc").
   154  		Create(v1alpha1.ApplicationSet{ObjectMeta: metav1.ObjectMeta{
   155  			Name: "simple-cluster-generator",
   156  		},
   157  			Spec: v1alpha1.ApplicationSetSpec{
   158  				Template: v1alpha1.ApplicationSetTemplate{
   159  					ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"},
   160  					Spec: argov1alpha1.ApplicationSpec{
   161  						Project: "default",
   162  						Source: &argov1alpha1.ApplicationSource{
   163  							RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   164  							TargetRevision: "HEAD",
   165  							Path:           "guestbook",
   166  						},
   167  						Destination: argov1alpha1.ApplicationDestination{
   168  							Name: "{{name}}",
   169  							// Server:    "{{server}}",
   170  							Namespace: "guestbook",
   171  						},
   172  					},
   173  				},
   174  				Generators: []v1alpha1.ApplicationSetGenerator{
   175  					{
   176  						Clusters: &v1alpha1.ClusterGenerator{
   177  							Selector: metav1.LabelSelector{
   178  								MatchLabels: map[string]string{
   179  									"argocd.argoproj.io/secret-type": "cluster",
   180  								},
   181  							},
   182  						},
   183  					},
   184  				},
   185  			},
   186  		}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{expectedApp})).
   187  
   188  		// Update the ApplicationSet template namespace, and verify it updates the Applications
   189  		When().
   190  		And(func() {
   191  			expectedAppNewNamespace = expectedApp.DeepCopy()
   192  			expectedAppNewNamespace.Spec.Destination.Namespace = "guestbook2"
   193  		}).
   194  		Update(func(appset *v1alpha1.ApplicationSet) {
   195  			appset.Spec.Template.Spec.Destination.Namespace = "guestbook2"
   196  		}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{*expectedAppNewNamespace})).
   197  
   198  		// Update the metadata fields in the appset template, and make sure it propagates to the apps
   199  		When().
   200  		And(func() {
   201  			expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
   202  			expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
   203  			expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
   204  		}).
   205  		Update(func(appset *v1alpha1.ApplicationSet) {
   206  			appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
   207  			appset.Spec.Template.Labels = map[string]string{"label-key": "label-value"}
   208  		}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{*expectedAppNewMetadata})).
   209  
   210  		// Delete the ApplicationSet, and verify it deletes the Applications
   211  		When().
   212  		Delete().Then().Expect(ApplicationsDoNotExist([]argov1alpha1.Application{*expectedAppNewNamespace}))
   213  }
   214  
   215  func TestClusterGeneratorWithLocalCluster(t *testing.T) {
   216  	expectedAppTemplate := argov1alpha1.Application{
   217  		TypeMeta: metav1.TypeMeta{
   218  			Kind:       application.ApplicationKind,
   219  			APIVersion: "argoproj.io/v1alpha1",
   220  		},
   221  		ObjectMeta: metav1.ObjectMeta{
   222  			Name:       "in-cluster-guestbook",
   223  			Namespace:  fixture.TestNamespace(),
   224  			Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
   225  		},
   226  		Spec: argov1alpha1.ApplicationSpec{
   227  			Project: "default",
   228  			Source: &argov1alpha1.ApplicationSource{
   229  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   230  				TargetRevision: "HEAD",
   231  				Path:           "guestbook",
   232  			},
   233  			// Destination comes from appDestination below
   234  		},
   235  	}
   236  
   237  	tests := []struct {
   238  		name              string
   239  		appsetDestination argov1alpha1.ApplicationDestination
   240  		appDestination    argov1alpha1.ApplicationDestination
   241  	}{
   242  		{
   243  			name: "specify local cluster by server field",
   244  			appDestination: argov1alpha1.ApplicationDestination{
   245  				Server:    "https://kubernetes.default.svc",
   246  				Namespace: "guestbook",
   247  			},
   248  			appsetDestination: argov1alpha1.ApplicationDestination{
   249  				Server:    "{{server}}",
   250  				Namespace: "guestbook",
   251  			},
   252  		},
   253  		{
   254  			name: "specify local cluster by name field",
   255  			appDestination: argov1alpha1.ApplicationDestination{
   256  				Name:      "in-cluster",
   257  				Namespace: "guestbook",
   258  			},
   259  			appsetDestination: argov1alpha1.ApplicationDestination{
   260  				Name:      "{{name}}",
   261  				Namespace: "guestbook",
   262  			},
   263  		},
   264  	}
   265  
   266  	for _, test := range tests {
   267  		t.Run(test.name, func(t *testing.T) {
   268  			var expectedAppNewNamespace *argov1alpha1.Application
   269  			var expectedAppNewMetadata *argov1alpha1.Application
   270  
   271  			// Create the expected application from the template, and copy in the destination from the test case
   272  			expectedApp := *expectedAppTemplate.DeepCopy()
   273  			expectedApp.Spec.Destination = test.appDestination
   274  
   275  			Given(t).
   276  				// Create a ClusterGenerator-based ApplicationSet
   277  				When().
   278  				Create(v1alpha1.ApplicationSet{ObjectMeta: metav1.ObjectMeta{
   279  					Name: "in-cluster-generator",
   280  				},
   281  					Spec: v1alpha1.ApplicationSetSpec{
   282  						Template: v1alpha1.ApplicationSetTemplate{
   283  							ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"},
   284  							Spec: argov1alpha1.ApplicationSpec{
   285  								Project: "default",
   286  								Source: &argov1alpha1.ApplicationSource{
   287  									RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   288  									TargetRevision: "HEAD",
   289  									Path:           "guestbook",
   290  								},
   291  								Destination: test.appsetDestination,
   292  							},
   293  						},
   294  						Generators: []v1alpha1.ApplicationSetGenerator{
   295  							{
   296  								Clusters: &v1alpha1.ClusterGenerator{},
   297  							},
   298  						},
   299  					},
   300  				}).Then().ExpectWithDuration(ApplicationsExist([]argov1alpha1.Application{expectedApp}), 8*time.Minute).
   301  
   302  				// Update the ApplicationSet template namespace, and verify it updates the Applications
   303  				When().
   304  				And(func() {
   305  					expectedAppNewNamespace = expectedApp.DeepCopy()
   306  					expectedAppNewNamespace.Spec.Destination.Namespace = "guestbook2"
   307  				}).
   308  				Update(func(appset *v1alpha1.ApplicationSet) {
   309  					appset.Spec.Template.Spec.Destination.Namespace = "guestbook2"
   310  				}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{*expectedAppNewNamespace})).
   311  
   312  				// Update the metadata fields in the appset template, and make sure it propagates to the apps
   313  				When().
   314  				And(func() {
   315  					expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
   316  					expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
   317  					expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
   318  				}).
   319  				Update(func(appset *v1alpha1.ApplicationSet) {
   320  					appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
   321  					appset.Spec.Template.Labels = map[string]string{"label-key": "label-value"}
   322  				}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{*expectedAppNewMetadata})).
   323  
   324  				// Delete the ApplicationSet, and verify it deletes the Applications
   325  				When().
   326  				Delete().Then().Expect(ApplicationsDoNotExist([]argov1alpha1.Application{*expectedAppNewNamespace}))
   327  		})
   328  	}
   329  }
   330  
   331  func TestSimpleClusterGeneratorAddingCluster(t *testing.T) {
   332  
   333  	expectedAppTemplate := argov1alpha1.Application{
   334  		TypeMeta: metav1.TypeMeta{
   335  			Kind:       application.ApplicationKind,
   336  			APIVersion: "argoproj.io/v1alpha1",
   337  		},
   338  		ObjectMeta: metav1.ObjectMeta{
   339  			Name:       "{{name}}-guestbook",
   340  			Namespace:  fixture.TestNamespace(),
   341  			Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
   342  		},
   343  		Spec: argov1alpha1.ApplicationSpec{
   344  			Project: "default",
   345  			Source: &argov1alpha1.ApplicationSource{
   346  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   347  				TargetRevision: "HEAD",
   348  				Path:           "guestbook",
   349  			},
   350  			Destination: argov1alpha1.ApplicationDestination{
   351  				Name:      "{{name}}",
   352  				Namespace: "guestbook",
   353  			},
   354  		},
   355  	}
   356  
   357  	expectedAppCluster1 := *expectedAppTemplate.DeepCopy()
   358  	expectedAppCluster1.Spec.Destination.Name = "cluster1"
   359  	expectedAppCluster1.ObjectMeta.Name = "cluster1-guestbook"
   360  
   361  	expectedAppCluster2 := *expectedAppTemplate.DeepCopy()
   362  	expectedAppCluster2.Spec.Destination.Name = "cluster2"
   363  	expectedAppCluster2.ObjectMeta.Name = "cluster2-guestbook"
   364  
   365  	Given(t).
   366  		// Create a ClusterGenerator-based ApplicationSet
   367  		When().
   368  		CreateClusterSecret("my-secret", "cluster1", "https://kubernetes.default.svc").
   369  		Create(v1alpha1.ApplicationSet{ObjectMeta: metav1.ObjectMeta{
   370  			Name: "simple-cluster-generator",
   371  		},
   372  			Spec: v1alpha1.ApplicationSetSpec{
   373  				Template: v1alpha1.ApplicationSetTemplate{
   374  					ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"},
   375  					Spec: argov1alpha1.ApplicationSpec{
   376  						Project: "default",
   377  						Source: &argov1alpha1.ApplicationSource{
   378  							RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   379  							TargetRevision: "HEAD",
   380  							Path:           "guestbook",
   381  						},
   382  						Destination: argov1alpha1.ApplicationDestination{
   383  							Name: "{{name}}",
   384  							// Server:    "{{server}}",
   385  							Namespace: "guestbook",
   386  						},
   387  					},
   388  				},
   389  				Generators: []v1alpha1.ApplicationSetGenerator{
   390  					{
   391  						Clusters: &v1alpha1.ClusterGenerator{
   392  							Selector: metav1.LabelSelector{
   393  								MatchLabels: map[string]string{
   394  									"argocd.argoproj.io/secret-type": "cluster",
   395  								},
   396  							},
   397  						},
   398  					},
   399  				},
   400  			},
   401  		}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{expectedAppCluster1})).
   402  
   403  		// Update the ApplicationSet template namespace, and verify it updates the Applications
   404  		When().
   405  		CreateClusterSecret("my-secret2", "cluster2", "https://kubernetes.default.svc").
   406  		Then().Expect(ApplicationsExist([]argov1alpha1.Application{expectedAppCluster1, expectedAppCluster2})).
   407  
   408  		// Delete the ApplicationSet, and verify it deletes the Applications
   409  		When().
   410  		Delete().Then().Expect(ApplicationsDoNotExist([]argov1alpha1.Application{expectedAppCluster1, expectedAppCluster2}))
   411  }
   412  
   413  func TestSimpleClusterGeneratorDeletingCluster(t *testing.T) {
   414  
   415  	expectedAppTemplate := argov1alpha1.Application{
   416  		TypeMeta: metav1.TypeMeta{
   417  			Kind:       application.ApplicationKind,
   418  			APIVersion: "argoproj.io/v1alpha1",
   419  		},
   420  		ObjectMeta: metav1.ObjectMeta{
   421  			Name:       "{{name}}-guestbook",
   422  			Namespace:  fixture.TestNamespace(),
   423  			Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
   424  		},
   425  		Spec: argov1alpha1.ApplicationSpec{
   426  			Project: "default",
   427  			Source: &argov1alpha1.ApplicationSource{
   428  				RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   429  				TargetRevision: "HEAD",
   430  				Path:           "guestbook",
   431  			},
   432  			Destination: argov1alpha1.ApplicationDestination{
   433  				Name:      "{{name}}",
   434  				Namespace: "guestbook",
   435  			},
   436  		},
   437  	}
   438  
   439  	expectedAppCluster1 := *expectedAppTemplate.DeepCopy()
   440  	expectedAppCluster1.Spec.Destination.Name = "cluster1"
   441  	expectedAppCluster1.ObjectMeta.Name = "cluster1-guestbook"
   442  
   443  	expectedAppCluster2 := *expectedAppTemplate.DeepCopy()
   444  	expectedAppCluster2.Spec.Destination.Name = "cluster2"
   445  	expectedAppCluster2.ObjectMeta.Name = "cluster2-guestbook"
   446  
   447  	Given(t).
   448  		// Create a ClusterGenerator-based ApplicationSet
   449  		When().
   450  		CreateClusterSecret("my-secret", "cluster1", "https://kubernetes.default.svc").
   451  		CreateClusterSecret("my-secret2", "cluster2", "https://kubernetes.default.svc").
   452  		Create(v1alpha1.ApplicationSet{ObjectMeta: metav1.ObjectMeta{
   453  			Name: "simple-cluster-generator",
   454  		},
   455  			Spec: v1alpha1.ApplicationSetSpec{
   456  				Template: v1alpha1.ApplicationSetTemplate{
   457  					ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"},
   458  					Spec: argov1alpha1.ApplicationSpec{
   459  						Project: "default",
   460  						Source: &argov1alpha1.ApplicationSource{
   461  							RepoURL:        "https://github.com/argoproj/argocd-example-apps.git",
   462  							TargetRevision: "HEAD",
   463  							Path:           "guestbook",
   464  						},
   465  						Destination: argov1alpha1.ApplicationDestination{
   466  							Name: "{{name}}",
   467  							// Server:    "{{server}}",
   468  							Namespace: "guestbook",
   469  						},
   470  					},
   471  				},
   472  				Generators: []v1alpha1.ApplicationSetGenerator{
   473  					{
   474  						Clusters: &v1alpha1.ClusterGenerator{
   475  							Selector: metav1.LabelSelector{
   476  								MatchLabels: map[string]string{
   477  									"argocd.argoproj.io/secret-type": "cluster",
   478  								},
   479  							},
   480  						},
   481  					},
   482  				},
   483  			},
   484  		}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{expectedAppCluster1, expectedAppCluster2})).
   485  
   486  		// Update the ApplicationSet template namespace, and verify it updates the Applications
   487  		When().
   488  		DeleteClusterSecret("my-secret2").
   489  		Then().Expect(ApplicationsExist([]argov1alpha1.Application{expectedAppCluster1})).
   490  		Expect(ApplicationsDoNotExist([]argov1alpha1.Application{expectedAppCluster2})).
   491  
   492  		// Delete the ApplicationSet, and verify it deletes the Applications
   493  		When().
   494  		Delete().Then().Expect(ApplicationsDoNotExist([]argov1alpha1.Application{expectedAppCluster1}))
   495  }