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