github.com/kubernetes-incubator/kube-aws@v0.16.4/test/integration/plugin_test.go (about) 1 package integration 2 3 import ( 4 "os" 5 "reflect" 6 "regexp" 7 "strings" 8 "testing" 9 10 "github.com/google/go-cmp/cmp" 11 "github.com/kubernetes-incubator/kube-aws/core/root" 12 "github.com/kubernetes-incubator/kube-aws/core/root/config" 13 "github.com/kubernetes-incubator/kube-aws/pkg/api" 14 "github.com/kubernetes-incubator/kube-aws/pkg/model" 15 "github.com/kubernetes-incubator/kube-aws/plugin" 16 "github.com/kubernetes-incubator/kube-aws/test/helper" 17 ) 18 19 func TestPlugin(t *testing.T) { 20 kubeAwsSettings := newKubeAwsSettingsFromEnv(t) 21 22 s3URI, s3URIExists := os.LookupEnv("KUBE_AWS_S3_DIR_URI") 23 24 if !s3URIExists || s3URI == "" { 25 s3URI = "s3://mybucket/mydir" 26 t.Logf(`Falling back s3URI to a stub value "%s" for tests of validating stack templates. No assets will actually be uploaded to S3`, s3URI) 27 } 28 29 minimalValidConfigYaml := kubeAwsSettings.minimumValidClusterYamlWithAZ("c") 30 31 validCases := []struct { 32 context string 33 clusterYaml string 34 plugins []helper.TestPlugin 35 assertConfig []ConfigTester 36 assertCluster []ClusterTester 37 }{ 38 { 39 context: "WithAddons", 40 clusterYaml: minimalValidConfigYaml + ` 41 42 43 kubeAwsPlugins: 44 myPlugin: 45 enabled: true 46 queue: 47 name: baz1 48 oidc: 49 issuer: 50 url: "https://login.example.com/" 51 systemdTemplateValue: "elvis123" 52 53 worker: 54 nodePools: 55 - name: pool1 56 kubeAwsPlugins: 57 myPlugin: 58 enabled: true 59 queue: 60 name: baz2 61 `, 62 plugins: []helper.TestPlugin{ 63 helper.TestPlugin{ 64 Name: "my-plugin", 65 Files: map[string]string{ 66 "assets/controller/baz.txt": "controller-baz", 67 "assets/etcd/baz.txt": "etcd-baz", 68 "assets/worker/baz.txt": "worker-baz", 69 }, 70 Yaml: ` 71 metadata: 72 name: my-plugin 73 version: 0.0.1 74 spec: 75 cluster: 76 # This is the defaults for the values passed to templates like: 77 # * cloudformation.stacks.{controlPlane,nodePool,root}.resources.append and 78 # * kubernetes.apiserer.flags[].value 79 # 80 # The defaults can be overridden from cluster.yaml via: 81 # * kubeAwsPlugins.pluginName.* and 82 # * worker.nodePools[].kubeAwsPlugins.pluginName.* 83 values: 84 queue: 85 name: bar 86 oidc: 87 issuer: 88 url: unspecified 89 cloudformation: 90 stacks: 91 controlPlane: 92 resources: 93 content: | 94 { 95 "QueueFromMyPlugin": { 96 "Type": "AWS::SQS::Queue", 97 "Properties": { 98 "QueueName": {{quote .Values.queue.name}} 99 } 100 } 101 } 102 tags: 103 content: | 104 { 105 "Tags": [ 106 { 107 "Key": "control/tag", 108 "PropagateAtLaunch": "false", 109 "Value": "" 110 } 111 ] 112 } 113 outputs: 114 content: | 115 { 116 "ControlStack": { 117 "Description": "ControlStack", 118 "Value": "ControlOutput" 119 } 120 } 121 nodePool: 122 resources: 123 content: | 124 { 125 "QueueFromMyPlugin": { 126 "Type": "AWS::SQS::Queue", 127 "Properties": { 128 "QueueName": {{quote .Values.queue.name}} 129 } 130 } 131 } 132 tags: 133 content: | 134 { 135 "Tags": [ 136 { 137 "Key": "nodepool/tag", 138 "PropagateAtLaunch": "false", 139 "Value": "" 140 } 141 ] 142 } 143 outputs: 144 content: | 145 { 146 "NodeStack": { 147 "Description": "NodeStack", 148 "Value": "NodeOutput" 149 } 150 } 151 root: 152 resources: 153 content: | 154 { 155 "QueueFromMyPlugin": { 156 "Type": "AWS::SQS::Queue", 157 "Properties": { 158 "QueueName": {{quote .Values.queue.name}} 159 } 160 } 161 } 162 etcd: 163 resources: 164 content: | 165 { 166 "QueueFromMyPlugin": { 167 "Type": "AWS::SQS::Queue", 168 "Properties": { 169 "QueueName": {{quote .Values.queue.name}} 170 } 171 } 172 } 173 outputs: 174 content: | 175 { 176 "EtcdStack": { 177 "Description": "EtcdStack", 178 "Value": "EtcdOutput" 179 } 180 } 181 network: 182 resources: 183 content: | 184 { 185 "QueueFromMyPlugin": { 186 "Type": "AWS::SQS::Queue", 187 "Properties": { 188 "QueueName": {{quote .Values.queue.name}} 189 } 190 } 191 } 192 outputs: 193 content: | 194 { 195 "NetworkStack": { 196 "Description": "NetworkStack", 197 "Value": "NetworkOutput" 198 } 199 } 200 kubernetes: 201 controllerManager: 202 flags: 203 - name: "secure-port" 204 value: "11257" 205 kubelet: 206 flags: 207 - name: "healthz-bind-address" 208 value: "0.0.0.0" 209 kubeScheduler: 210 flags: 211 - name: "secure-port" 212 value: "11259" 213 kubeProxy: 214 config: 215 metricsBindAddress: "0.0.0.0" 216 apiserver: 217 flags: 218 - name: "oidc-issuer-url" 219 value: "{{ .Values.oidc.issuer.url}}" 220 volumes: 221 - name: "mycreds" 222 path: "/etc/my/creds" 223 machine: 224 roles: 225 controller: 226 iam: 227 policy: 228 statements: 229 - actions: 230 - "ec2:Describe*" 231 effect: "Allow" 232 resources: 233 - "*" 234 kubelet: 235 nodeLabels: 236 role: controller 237 systemd: 238 units: 239 - name: save-queue-name.service 240 content: | 241 [Unit] {{ .Values.systemdTemplateValue }} 242 files: 243 - path: /var/kube-aws/bar.txt 244 permissions: 0644 245 content: controller-bar 246 - path: /var/kube-aws/baz.txt 247 permissions: 0644 248 source: 249 path: assets/controller/baz.txt 250 etcd: 251 iam: 252 policy: 253 statements: 254 - actions: 255 - "ec2:Describe*" 256 effect: "Allow" 257 resources: 258 - "*" 259 systemd: 260 units: 261 - name: save-queue-name.service 262 content: | 263 [Unit] {{ .Values.systemdTemplateValue }} 264 files: 265 - path: /var/kube-aws/bar.txt 266 permissions: 0644 267 content: etcd-bar 268 - path: /var/kube-aws/baz.txt 269 permissions: 0644 270 source: 271 path: assets/etcd/baz.txt 272 worker: 273 iam: 274 policy: 275 statements: 276 - actions: 277 - "ec2:*" 278 effect: "Allow" 279 resources: 280 - "*" 281 kubelet: 282 nodeLabels: 283 role: worker 284 featureGates: 285 Accelerators: "true" 286 systemd: 287 units: 288 - name: save-queue-name.service 289 content: | 290 [Unit] {{ .Values.systemdTemplateValue }} 291 files: 292 - path: /var/kube-aws/bar.txt 293 permissions: 0644 294 content: worker-bar 295 - path: /var/kube-aws/baz.txt 296 permissions: 0644 297 source: 298 path: assets/worker/baz.txt 299 `, 300 }, 301 }, 302 assertConfig: []ConfigTester{ 303 func(c *config.Config, t *testing.T) { 304 cp := c.PluginConfigs["myPlugin"] 305 306 if !cp.Enabled { 307 t.Errorf("The plugin should have been enabled: %+v", cp) 308 } 309 310 if q, ok := cp.Values["queue"].(map[string]interface{}); ok { 311 if m, ok := q["name"].(string); ok { 312 if m != "baz1" { 313 t.Errorf("The plugin should have queue.name set to \"baz1\", but was set to \"%s\"", m) 314 } 315 } 316 } 317 318 np := c.NodePools[0].Plugins["myPlugin"] 319 320 if !np.Enabled { 321 t.Errorf("The plugin should have been enabled: %+v", np) 322 } 323 324 if q, ok := np.Values["queue"].(map[string]interface{}); ok { 325 if m, ok := q["name"].(string); ok { 326 if m != "baz2" { 327 t.Errorf("The plugin should have queue.name set to \"baz2\", but was set to \"%s\"", m) 328 } 329 } 330 } 331 }, 332 }, 333 assertCluster: []ClusterTester{ 334 func(c *root.Cluster, t *testing.T) { 335 cp := c.ControlPlane() 336 np := c.NodePools()[0] 337 etcd := c.Etcd() 338 network := c.Network() 339 340 { 341 e := api.CustomFile{ 342 Path: "/var/kube-aws/bar.txt", 343 Permissions: 0644, 344 Content: "controller-bar", 345 } 346 a := cp.Config.Controller.CustomFiles[0] 347 if !reflect.DeepEqual(e, a) { 348 t.Errorf("Unexpected controller custom file from plugin: expected=%v actual=%v", e, a) 349 } 350 } 351 { 352 e := api.CustomFile{ 353 Path: "/var/kube-aws/baz.txt", 354 Permissions: 0644, 355 Content: "controller-baz", 356 } 357 a := cp.Config.Controller.CustomFiles[1] 358 if !reflect.DeepEqual(e, a) { 359 t.Errorf("Unexpected controller custom file from plugin: expected=%v actual=%v", e, a) 360 } 361 } 362 { 363 e := api.IAMPolicyStatements{ 364 api.IAMPolicyStatement{ 365 Effect: "Allow", 366 Actions: []string{"ec2:Describe*"}, 367 Resources: []string{"*"}, 368 }, 369 } 370 a := cp.Config.Controller.IAMConfig.Policy.Statements 371 if !reflect.DeepEqual(e, a) { 372 t.Errorf("Unexpected controller iam policy statements from plugin: expected=%v actual=%v", e, a) 373 } 374 } 375 376 { 377 e := api.CustomFile{ 378 Path: "/var/kube-aws/bar.txt", 379 Permissions: 0644, 380 Content: "etcd-bar", 381 } 382 a := etcd.Config.Etcd.CustomFiles[0] 383 if !reflect.DeepEqual(e, a) { 384 t.Errorf("Unexpected etcd custom file from plugin: expected=%v actual=%v", e, a) 385 } 386 } 387 { 388 e := api.CustomFile{ 389 Path: "/var/kube-aws/baz.txt", 390 Permissions: 0644, 391 Content: "etcd-baz", 392 } 393 a := etcd.Config.Etcd.CustomFiles[1] 394 if !reflect.DeepEqual(e, a) { 395 t.Errorf("Unexpected etcd custom file from plugin: expected=%v actual=%v", e, a) 396 } 397 } 398 { 399 e := api.IAMPolicyStatements{ 400 api.IAMPolicyStatement{ 401 Effect: "Allow", 402 Actions: []string{"ec2:Describe*"}, 403 Resources: []string{"*"}, 404 }, 405 } 406 a := etcd.Config.Etcd.IAMConfig.Policy.Statements 407 if !reflect.DeepEqual(e, a) { 408 t.Errorf("Unexpected etcd iam policy statements from plugin: expected=%v actual=%v", e, a) 409 } 410 } 411 412 { 413 e := api.CustomFile{ 414 Path: "/var/kube-aws/bar.txt", 415 Permissions: 0644, 416 Content: "worker-bar", 417 } 418 a := np.NodePoolConfig.CustomFiles[0] 419 if !reflect.DeepEqual(e, a) { 420 t.Errorf("Unexpected worker custom file from plugin: expected=%v actual=%v", e, a) 421 } 422 } 423 { 424 e := api.CustomFile{ 425 Path: "/var/kube-aws/baz.txt", 426 Permissions: 0644, 427 Content: "worker-baz", 428 } 429 a := np.NodePoolConfig.CustomFiles[1] 430 if !reflect.DeepEqual(e, a) { 431 t.Errorf("Unexpected worker custom file from plugin: expected=%v actual=%v", e, a) 432 } 433 } 434 { 435 e := api.IAMPolicyStatements{ 436 api.IAMPolicyStatement{ 437 Effect: "Allow", 438 Actions: []string{"ec2:*"}, 439 Resources: []string{"*"}, 440 }, 441 } 442 a := np.NodePoolConfig.IAMConfig.Policy.Statements 443 if diff := cmp.Diff(a, e); diff != "" { 444 t.Errorf("Unexpected worker iam policy statements from plugin: %s", diff) 445 } 446 } 447 448 // A kube-aws plugin can inject systemd units - which are evaluated as templates 449 controllerUserdataS3Part := cp.UserData["Controller"].Parts[api.USERDATA_S3].Asset.Content 450 if !strings.Contains(controllerUserdataS3Part, "save-queue-name.service") { 451 t.Errorf("Invalid controller userdata: missing systemd unit save-queue-name.service: %v", controllerUserdataS3Part) 452 } 453 if !strings.Contains(controllerUserdataS3Part, "elvis123") { 454 t.Errorf("Invalid controller userdata: systemd unit not templated: %v", controllerUserdataS3Part) 455 } 456 457 etcdUserdataS3Part := etcd.UserData["Etcd"].Parts[api.USERDATA_S3].Asset.Content 458 if !strings.Contains(etcdUserdataS3Part, "save-queue-name.service") { 459 t.Errorf("Invalid etcd userdata: missing systemd unit save-queue-name.service: %v", etcdUserdataS3Part) 460 } 461 if !strings.Contains(etcdUserdataS3Part, "elvis123") { 462 t.Errorf("Invalid etcd userdata: systemd unit not templated: %v", etcdUserdataS3Part) 463 } 464 465 workerUserdataS3Part := np.UserData["Worker"].Parts[api.USERDATA_S3].Asset.Content 466 if !strings.Contains(workerUserdataS3Part, "save-queue-name.service") { 467 t.Errorf("Invalid worker userdata: missing systemd unit save-queue-name.service: %v", workerUserdataS3Part) 468 } 469 if !strings.Contains(workerUserdataS3Part, "elvis123") { 470 t.Errorf("Invalid worker userdata: systemd unit not templated: %v", workerUserdataS3Part) 471 } 472 473 // A kube-aws plugin can inject custom cfn stack resources 474 controlPlaneStackTemplate, err := cp.RenderStackTemplateAsString() 475 if err != nil { 476 t.Errorf("failed to render control-plane stack template: %v", err) 477 } 478 if !strings.Contains(controlPlaneStackTemplate, "QueueFromMyPlugin") { 479 t.Errorf("Invalid control-plane stack template: missing resource QueueFromMyPlugin: %v", controlPlaneStackTemplate) 480 } 481 if !strings.Contains(controlPlaneStackTemplate, `"QueueName":"baz1"`) { 482 t.Errorf("Invalid control-plane stack template: missing QueueName baz1: %v", controlPlaneStackTemplate) 483 } 484 if !strings.Contains(controlPlaneStackTemplate, `"Action":["ec2:Describe*"]`) { 485 t.Errorf("Invalid control-plane stack template: missing iam policy statement ec2:Describe*: %v", controlPlaneStackTemplate) 486 } 487 488 // A kube-aws plugin can inject custom cfn stack resources into the etcd stack 489 etcdStackTemplate, err := etcd.RenderStackTemplateAsString() 490 491 if err != nil { 492 t.Errorf("failed to render control-plane stack template: %v", err) 493 } 494 if !strings.Contains(etcdStackTemplate, "QueueFromMyPlugin") { 495 t.Errorf("Invalid etcd stack template: missing resource QueueFromMyPlugin: %v", etcdStackTemplate) 496 } 497 if !strings.Contains(etcdStackTemplate, `"QueueName":"baz1"`) { 498 t.Errorf("Invalid etcd stack template: missing QueueName baz1: %v", etcdStackTemplate) 499 } 500 if !strings.Contains(etcdStackTemplate, `"Action":["ec2:Describe*"]`) { 501 t.Errorf("Invalid etcd stack template: missing iam policy statement ec2:Describe*: %v", etcdStackTemplate) 502 } 503 504 // A kube-aws plugin can inject custom cfn stack resources into the network stack 505 networkStackTemplate, err := network.RenderStackTemplateAsString() 506 507 if err != nil { 508 t.Errorf("failed to render control-plane stack template: %v", err) 509 } 510 if !strings.Contains(networkStackTemplate, "QueueFromMyPlugin") { 511 t.Errorf("Invalid networks stack template: missing resource QueueFromMyPlugin: %v", networkStackTemplate) 512 } 513 if !strings.Contains(networkStackTemplate, `"QueueName":"baz1"`) { 514 t.Errorf("Invalid network stack template: missing QueueName baz1: %v", networkStackTemplate) 515 } 516 517 rootStackTemplate, err := c.RenderStackTemplateAsString() 518 if err != nil { 519 t.Errorf("failed to render root stack template: %v", err) 520 } 521 if !strings.Contains(rootStackTemplate, "QueueFromMyPlugin") { 522 t.Errorf("Invalid root stack template: missing resource QueueFromMyPlugin: %v", rootStackTemplate) 523 } 524 if !strings.Contains(rootStackTemplate, `"QueueName":"baz1"`) { 525 t.Errorf("Invalid root stack template: missing QueueName baz1: %v", rootStackTemplate) 526 } 527 528 nodePoolStackTemplate, err := np.RenderStackTemplateAsString() 529 if err != nil { 530 t.Errorf("failed to render worker node pool stack template: %v", err) 531 } 532 if !strings.Contains(nodePoolStackTemplate, "QueueFromMyPlugin") { 533 t.Errorf("Invalid worker node pool stack template: missing resource QueueFromMyPlugin: %v", nodePoolStackTemplate) 534 } 535 if !strings.Contains(nodePoolStackTemplate, `"QueueName":"baz2"`) { 536 t.Errorf("Invalid worker node pool stack template: missing QueueName baz2: %v", nodePoolStackTemplate) 537 } 538 if !strings.Contains(nodePoolStackTemplate, `"Action":["ec2:*"]`) { 539 t.Errorf("Invalid worker node pool stack template: missing iam policy statement ec2:*: %v", nodePoolStackTemplate) 540 } 541 542 // A kube-aws plugin can inject control plane and node pool tags 543 if !strings.Contains(controlPlaneStackTemplate, `"Key":"control/tag"`) { 544 t.Errorf("Invalid control-plane stack template: missing tag control/tag: %v", controlPlaneStackTemplate) 545 } 546 if !strings.Contains(nodePoolStackTemplate, `"Key":"nodepool/tag"`) { 547 t.Errorf("Invalid node-pool stack template: missing tag nodepool/tag: %v", nodePoolStackTemplate) 548 } 549 550 // A kube-aws plugin can inject cfn outputs 551 if !strings.Contains(controlPlaneStackTemplate, `"Value":"ControlOutput"`) { 552 t.Errorf("Invalid control-plane stack template: missing output ControlOutput: %v", controlPlaneStackTemplate) 553 } 554 if !strings.Contains(nodePoolStackTemplate, `"Value":"NodeOutput"`) { 555 t.Errorf("Invalid node-pool stack template: missing output NodeOutput: %v", nodePoolStackTemplate) 556 } 557 if !strings.Contains(etcdStackTemplate, `"Value":"EtcdOutput"`) { 558 t.Errorf("Invalid etcd stack template: missing output EtcdOutput: %v", etcdStackTemplate) 559 } 560 if !strings.Contains(networkStackTemplate, `"Value":"NetworkOutput"`) { 561 t.Errorf("Invalid network stack template: missing output Network: %v", networkStackTemplate) 562 } 563 564 // A kube-aws plugin can inject node labels 565 if !strings.Contains(controllerUserdataS3Part, "role=controller") { 566 t.Error("missing controller node label: role=controller") 567 } 568 569 if !strings.Contains(workerUserdataS3Part, "role=worker") { 570 t.Error("missing worker node label: role=worker") 571 } 572 573 // A kube-aws plugin can activate feature gates 574 if match, _ := regexp.MatchString(`Accelerators: true`, workerUserdataS3Part); !match { 575 t.Error("missing worker feature gate: Accelerators: true") 576 } 577 578 // A kube-aws plugin can add volume mounts to apiserver pod 579 if !strings.Contains(controllerUserdataS3Part, `mountPath: "/etc/my/creds"`) { 580 t.Errorf("missing apiserver volume mount: /etc/my/creds") 581 } 582 583 // A kube-aws plugin can add volumes to apiserver pod 584 if !strings.Contains(controllerUserdataS3Part, `path: "/etc/my/creds"`) { 585 t.Errorf("missing apiserver volume: /etc/my/creds") 586 } 587 588 // A kube-aws plugin can add flags to apiserver 589 if !strings.Contains(controllerUserdataS3Part, `--oidc-issuer-url=https://login.example.com/`) { 590 t.Errorf("missing apiserver flag: --oidc-issuer-url=https://login.example.com/") 591 } 592 593 // A kube-aws plugin can add flags to the kube-controllermanager 594 if !strings.Contains(controllerUserdataS3Part, `--secure-port=11259`) { 595 t.Errorf("missing kube-controllermanager flag: --secure-port=11259") 596 } 597 598 // A kube-aws plugin can add flags to the kubescheduler 599 if !strings.Contains(controllerUserdataS3Part, `- --secure-port=11259`) { 600 t.Errorf("missing kubescheduler flag: --secure-port=11259") 601 } 602 603 // A kube-aws plugin can add flags to the kubelet in the controller 604 if !strings.Contains(controllerUserdataS3Part, `--healthz-bind-address=0.0.0.0`) { 605 t.Errorf("missing kubelet flag: --healthz-bind-address=0.0.0.0") 606 } 607 608 // A kube-aws plugin can add flags to the kubelet in the workers 609 if !strings.Contains(workerUserdataS3Part, `--healthz-bind-address=0.0.0.0`) { 610 t.Errorf("missing kubelet flag: --healthz-bind-address=0.0.0.0") 611 } 612 613 // A kube-aws plugin can add flags to the kubeproxy 614 if !strings.Contains(controllerUserdataS3Part, `metricsBindAddress: 0.0.0.0`) { 615 t.Errorf("missing kubeproxy config item: metricsBindAddress: 0.0.0.0") 616 } 617 }, 618 }, 619 }, 620 } 621 622 for _, validCase := range validCases { 623 t.Run(validCase.context, func(t *testing.T) { 624 helper.WithPlugins(t, validCase.plugins, func() { 625 plugins, err := plugin.LoadAll() 626 if err != nil { 627 t.Errorf("failed to load plugins: %v", err) 628 t.FailNow() 629 } 630 if len(plugins) != len(validCase.plugins) { 631 t.Errorf("failed to load plugins: expected %d plugins but loaded %d plugins", len(validCase.plugins), len(plugins)) 632 t.FailNow() 633 } 634 635 configBytes := validCase.clusterYaml 636 providedConfig, err := config.ConfigFromBytes([]byte(configBytes), plugins) 637 if err != nil { 638 t.Errorf("failed to parse config %s: %+v", configBytes, err) 639 t.FailNow() 640 } 641 642 t.Run("AssertConfig", func(t *testing.T) { 643 for _, assertion := range validCase.assertConfig { 644 assertion(providedConfig, t) 645 } 646 }) 647 648 helper.WithDummyCredentials(func(dummyAssetsDir string) { 649 var stackTemplateOptions = root.NewOptions(false, false) 650 stackTemplateOptions.AssetsDir = dummyAssetsDir 651 stackTemplateOptions.ControllerTmplFile = "../../builtin/files/userdata/cloud-config-controller" 652 stackTemplateOptions.WorkerTmplFile = "../../builtin/files/userdata/cloud-config-worker" 653 stackTemplateOptions.EtcdTmplFile = "../../builtin/files/userdata/cloud-config-etcd" 654 stackTemplateOptions.RootStackTemplateTmplFile = "../../builtin/files/stack-templates/root.json.tmpl" 655 stackTemplateOptions.NodePoolStackTemplateTmplFile = "../../builtin/files/stack-templates/node-pool.json.tmpl" 656 stackTemplateOptions.ControlPlaneStackTemplateTmplFile = "../../builtin/files/stack-templates/control-plane.json.tmpl" 657 stackTemplateOptions.EtcdStackTemplateTmplFile = "../../builtin/files/stack-templates/etcd.json.tmpl" 658 stackTemplateOptions.NetworkStackTemplateTmplFile = "../../builtin/files/stack-templates/network.json.tmpl" 659 660 cl, err := root.CompileClusterFromConfig(providedConfig, stackTemplateOptions, false) 661 if err != nil { 662 t.Errorf("failed to create cluster driver : %v", err) 663 t.FailNow() 664 } 665 cl.Context = &model.Context{ 666 ProvidedEncryptService: helper.DummyEncryptService{}, 667 ProvidedCFInterrogator: helper.DummyCFInterrogator{}, 668 ProvidedEC2Interrogator: helper.DummyEC2Interrogator{}, 669 StackTemplateGetter: helper.DummyStackTemplateGetter{}, 670 } 671 672 _, err = cl.EnsureAllAssetsGenerated() 673 if err != nil { 674 t.Errorf("%v", err) 675 t.FailNow() 676 } 677 678 t.Run("AssertCluster", func(t *testing.T) { 679 for _, assertion := range validCase.assertCluster { 680 assertion(cl, t) 681 } 682 }) 683 684 t.Run("ValidateTemplates", func(t *testing.T) { 685 if err := cl.ValidateTemplates(); err != nil { 686 t.Errorf("failed to render stack template: %v", err) 687 } 688 }) 689 690 if os.Getenv("KUBE_AWS_INTEGRATION_TEST") == "" { 691 t.Skipf("`export KUBE_AWS_INTEGRATION_TEST=1` is required to run integration tests. Skipping.") 692 t.SkipNow() 693 } else { 694 t.Run("ValidateStack", func(t *testing.T) { 695 if !s3URIExists { 696 t.Errorf("failed to obtain value for KUBE_AWS_S3_DIR_URI") 697 t.FailNow() 698 } 699 700 report, err := cl.ValidateStack() 701 702 if err != nil { 703 t.Errorf("failed to validate stack: %s %v", report, err) 704 } 705 }) 706 } 707 }) 708 }) 709 }) 710 } 711 }