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