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 }