github.com/apprenda/kismatic@v1.12.0/integration-tests/install_test.go (about)

     1  package integration_tests
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"time"
     7  
     8  	yaml "gopkg.in/yaml.v2"
     9  
    10  	"os/exec"
    11  
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  var _ = Describe("kismatic", func() {
    17  	BeforeEach(func() {
    18  		dir := setupTestWorkingDir()
    19  		os.Chdir(dir)
    20  	})
    21  
    22  	Describe("calling kismatic with no verb", func() {
    23  		It("should output help text", func() {
    24  			c := exec.Command("./kismatic")
    25  			helpbytes, helperr := c.Output()
    26  			Expect(helperr).To(BeNil())
    27  			helpText := string(helpbytes)
    28  			Expect(helpText).To(ContainSubstring("Usage"))
    29  		})
    30  	})
    31  
    32  	Describe("Calling 'install plan'", func() {
    33  		Context("and just hitting enter", func() {
    34  			It("should result in the output of a well formed default plan file", func() {
    35  				By("Outputing a file")
    36  				c := exec.Command("./kismatic", "install", "plan")
    37  				helpbytes, helperr := c.Output()
    38  				Expect(helperr).To(BeNil())
    39  				helpText := string(helpbytes)
    40  				Expect(helpText).To(ContainSubstring("Generating installation plan file template"))
    41  				Expect(helpText).To(ContainSubstring("3 etcd nodes"))
    42  				Expect(helpText).To(ContainSubstring("2 master nodes"))
    43  				Expect(helpText).To(ContainSubstring("3 worker nodes"))
    44  				Expect(helpText).To(ContainSubstring("2 ingress nodes"))
    45  				Expect(helpText).To(ContainSubstring("0 storage nodes"))
    46  
    47  				Expect(FileExists("kismatic-cluster.yaml")).To(Equal(true))
    48  
    49  				By("Reading generated plan file")
    50  				yamlBytes, err := ioutil.ReadFile("kismatic-cluster.yaml")
    51  				if err != nil {
    52  					Fail("Could not read cluster file")
    53  				}
    54  				yamlBlob := string(yamlBytes)
    55  				planFromYaml := ClusterPlan{}
    56  				unmarshallErr := yaml.Unmarshal([]byte(yamlBlob), &planFromYaml)
    57  				if unmarshallErr != nil {
    58  					Fail("Could not unmarshall cluster yaml: %v")
    59  				}
    60  
    61  				By("Verifying generated plan file")
    62  				Expect(planFromYaml.Etcd.ExpectedCount).To(Equal(3))
    63  				Expect(planFromYaml.Master.ExpectedCount).To(Equal(2))
    64  				Expect(planFromYaml.Worker.ExpectedCount).To(Equal(3))
    65  				Expect(planFromYaml.Ingress.ExpectedCount).To(Equal(2))
    66  				Expect(planFromYaml.Storage.ExpectedCount).To(Equal(0))
    67  			})
    68  		})
    69  	})
    70  
    71  	Describe("calling install apply", func() {
    72  		Context("when targeting non-existent infrastructure", func() {
    73  			It("should fail in a reasonable amount of time", func() {
    74  				if !completesInTime(installKismaticWithABadNode, 600*time.Second) {
    75  					Fail("It shouldn't take 600 seconds for Kismatic to fail with bad nodes.")
    76  				}
    77  			})
    78  		})
    79  
    80  		Context("when deploying a cluster with all node roles", func() {
    81  			installOpts := installOptions{}
    82  			ItOnAWS("should install successfully [slow]", func(aws infrastructureProvisioner) {
    83  				WithInfrastructure(NodeCount{1, 1, 1, 1, 1}, Ubuntu1604LTS, aws, func(nodes provisionedNodes, sshKey string) {
    84  					err := installKismatic(nodes, installOpts, sshKey)
    85  					Expect(err).ToNot(HaveOccurred())
    86  				})
    87  			})
    88  		})
    89  
    90  		Context("when deploying a cluster with all node roles and docker already installed", func() {
    91  			installOpts := installOptions{disableDockerInstallation: true}
    92  			ItOnAWS("should install successfully [slow]", func(aws infrastructureProvisioner) {
    93  				WithInfrastructure(NodeCount{1, 1, 1, 1, 1}, Ubuntu1604LTS, aws, func(nodes provisionedNodes, sshKey string) {
    94  					err := validateKismatic(nodes, installOpts, sshKey)
    95  					if err == nil {
    96  						Fail("Validation should fail when docker.disable = true and docker is not yet installed.")
    97  					}
    98  					InstallDockerPackage(nodes, Ubuntu1604LTS, sshKey)
    99  					err = installKismatic(nodes, installOpts, sshKey)
   100  					Expect(err).ToNot(HaveOccurred())
   101  				})
   102  			})
   103  		})
   104  
   105  		Context("when deploying a cluster with all node roles and cloud-provider on CentOS", func() {
   106  			ItOnAWS("should install successfully [slow]", func(aws infrastructureProvisioner) {
   107  				WithInfrastructure(NodeCount{1, 1, 2, 1, 1}, CentOS7, aws, func(nodes provisionedNodes, sshKey string) {
   108  					testCloudProvider(nodes, sshKey)
   109  				})
   110  			})
   111  		})
   112  
   113  		Context("when deploying a cluster with all node roles and cloud-provider on RHEL", func() {
   114  			ItOnAWS("should install successfully [slow]", func(aws infrastructureProvisioner) {
   115  				WithInfrastructure(NodeCount{1, 1, 2, 1, 1}, RedHat7, aws, func(nodes provisionedNodes, sshKey string) {
   116  					testCloudProvider(nodes, sshKey)
   117  				})
   118  			})
   119  		})
   120  
   121  		Context("when deploying a cluster with all node roles and cloud-provider on Ubuntu", func() {
   122  			ItOnAWS("should install successfully [slow]", func(aws infrastructureProvisioner) {
   123  				WithInfrastructure(NodeCount{1, 1, 2, 1, 1}, Ubuntu1604LTS, aws, func(nodes provisionedNodes, sshKey string) {
   124  					testCloudProvider(nodes, sshKey)
   125  				})
   126  			})
   127  		})
   128  
   129  		Context("when deploying a cluster with all node roles and disabled CNI", func() {
   130  			installOpts := installOptions{
   131  				disableCNI: true,
   132  			}
   133  			ItOnAWS("should install successfully [slow]", func(aws infrastructureProvisioner) {
   134  				WithInfrastructure(NodeCount{1, 1, 1, 1, 1}, Ubuntu1604LTS, aws, func(nodes provisionedNodes, sshKey string) {
   135  					err := installKismatic(nodes, installOpts, sshKey)
   136  					Expect(err).ToNot(HaveOccurred())
   137  				})
   138  			})
   139  		})
   140  
   141  		Context("when targeting CentOS", func() {
   142  			ItOnAWS("should install successfully", func(aws infrastructureProvisioner) {
   143  				WithMiniInfrastructure(CentOS7, aws, func(node NodeDeets, sshKey string) {
   144  					err := installKismaticMini(node, sshKey)
   145  					Expect(err).ToNot(HaveOccurred())
   146  					// Ensure preflight checks are idempotent on CentOS7
   147  					err = runValidate("kismatic-testing.yaml")
   148  					Expect(err).ToNot(HaveOccurred())
   149  					err = resetKismatic()
   150  					Expect(err).ToNot(HaveOccurred())
   151  				})
   152  			})
   153  		})
   154  
   155  		Context("when targeting RHEL", func() {
   156  			ItOnAWS("should install successfully", func(aws infrastructureProvisioner) {
   157  				WithMiniInfrastructure(RedHat7, aws, func(node NodeDeets, sshKey string) {
   158  					err := installKismaticMini(node, sshKey)
   159  					Expect(err).ToNot(HaveOccurred())
   160  					// Ensure preflight checks are idempotent on RedHat7
   161  					err = runValidate("kismatic-testing.yaml")
   162  					Expect(err).ToNot(HaveOccurred())
   163  					err = resetKismatic()
   164  					Expect(err).ToNot(HaveOccurred())
   165  				})
   166  			})
   167  		})
   168  
   169  		Context("when targeting Ubuntu", func() {
   170  			ItOnAWS("should install successfully", func(aws infrastructureProvisioner) {
   171  				WithMiniInfrastructure(Ubuntu1604LTS, aws, func(node NodeDeets, sshKey string) {
   172  					err := installKismaticMini(node, sshKey)
   173  					Expect(err).ToNot(HaveOccurred())
   174  					// Ensure preflight checks are idempotent on Ubuntu 1604
   175  					err = runValidate("kismatic-testing.yaml")
   176  					Expect(err).ToNot(HaveOccurred())
   177  					err = resetKismatic()
   178  					Expect(err).ToNot(HaveOccurred())
   179  				})
   180  			})
   181  		})
   182  
   183  		Context("when using direct-lvm docker storage", func() {
   184  			installOpts := installOptions{
   185  				dockerStorageDriver: "devicemapper",
   186  			}
   187  			Context("when targeting CentOS", func() {
   188  				ItOnAWS("should install successfully", func(aws infrastructureProvisioner) {
   189  					WithMiniInfrastructureAndBlockDevice(CentOS7, aws, func(node NodeDeets, sshKey string) {
   190  						theNode := []NodeDeets{node}
   191  						nodes := provisionedNodes{
   192  							etcd:    theNode,
   193  							master:  theNode,
   194  							worker:  theNode,
   195  							ingress: theNode,
   196  						}
   197  						err := installKismatic(nodes, installOpts, sshKey)
   198  						Expect(err).ToNot(HaveOccurred())
   199  						err = resetKismatic()
   200  						Expect(err).ToNot(HaveOccurred())
   201  					})
   202  				})
   203  			})
   204  
   205  			Context("when targeting RHEL", func() {
   206  				ItOnAWS("should install successfully", func(aws infrastructureProvisioner) {
   207  					WithMiniInfrastructureAndBlockDevice(RedHat7, aws, func(node NodeDeets, sshKey string) {
   208  						theNode := []NodeDeets{node}
   209  						nodes := provisionedNodes{
   210  							etcd:    theNode,
   211  							master:  theNode,
   212  							worker:  theNode,
   213  							ingress: theNode,
   214  						}
   215  						err := installKismatic(nodes, installOpts, sshKey)
   216  						Expect(err).ToNot(HaveOccurred())
   217  						err = resetKismatic()
   218  						Expect(err).ToNot(HaveOccurred())
   219  					})
   220  				})
   221  			})
   222  		})
   223  
   224  		Context("when using overlay2 docker storage", func() {
   225  			installOpts := installOptions{
   226  				dockerStorageDriver: "overlay2",
   227  			}
   228  			Context("when targeting Ubuntu", func() {
   229  				ItOnAWS("should install successfully", func(aws infrastructureProvisioner) {
   230  					WithMiniInfrastructureAndBlockDevice(Ubuntu1604LTS, aws, func(node NodeDeets, sshKey string) {
   231  						theNode := []NodeDeets{node}
   232  						nodes := provisionedNodes{
   233  							etcd:    theNode,
   234  							master:  theNode,
   235  							worker:  theNode,
   236  							ingress: theNode,
   237  						}
   238  						err := installKismatic(nodes, installOpts, sshKey)
   239  						Expect(err).ToNot(HaveOccurred())
   240  					})
   241  				})
   242  			})
   243  		})
   244  
   245  		// TODO add back when --endpoint-reconciler-type=lease
   246  		// Context("when deploying an HA cluster", func() {
   247  		// 	ItOnAWS("should still be a highly available cluster after removing a master node [slow]", func(aws infrastructureProvisioner) {
   248  		// 		WithInfrastructureAndDNS(NodeCount{1, 2, 1, 1, 0}, Ubuntu1604LTS, aws, func(nodes provisionedNodes, sshKey string) {
   249  		// 			// install cluster
   250  		// 			installOpts := installOptions{}
   251  		// 			err := installKismatic(nodes, installOpts, sshKey)
   252  		// 			Expect(err).ToNot(HaveOccurred())
   253  
   254  		// 			By("Removing a Kubernetes master node")
   255  		// 			if err = aws.TerminateNode(nodes.master[0]); err != nil {
   256  		// 				FailIfError(err, "could not remove node")
   257  		// 			}
   258  		// 			By("Re-running Kuberang")
   259  		// 			if err = runViaSSH([]string{"sudo kuberang --kubeconfig /root/.kube/config"}, []NodeDeets{nodes.master[1]}, sshKey, 5*time.Minute); err != nil {
   260  		// 				FailIfError(err, "kuberang error")
   261  		// 			}
   262  		// 		})
   263  		// 	})
   264  		// })
   265  
   266  		// This spec will be used for testing non-destructive kismatic features on
   267  		// a new cluster.
   268  		// This spec is open to modification when new assertions have to be made
   269  		Context("when deploying a skunkworks cluster", func() {
   270  			Context("with Calico as the CNI provider", func() {
   271  				ItOnAWS("should install successfully [slow]", func(aws infrastructureProvisioner) {
   272  					WithInfrastructure(NodeCount{3, 2, 5, 2, 2}, Ubuntu1604LTS, aws, func(nodes provisionedNodes, sshKey string) {
   273  						// reserve 3 of the workers for the add-node test
   274  						allWorkers := nodes.worker
   275  						nodes.worker = allWorkers[0 : len(nodes.worker)-3]
   276  
   277  						// install cluster
   278  						installOpts := installOptions{
   279  							heapsterReplicas:             3,
   280  							heapsterInfluxdbPVC:          "influxdb",
   281  							kubeAPIServerOptions:         map[string]string{"v": "3"},
   282  							kubeControllerManagerOptions: map[string]string{"v": "3"},
   283  							kubeSchedulerOptions:         map[string]string{"v": "3"},
   284  							kubeProxyOptions:             map[string]string{"v": "3"},
   285  							kubeletOptions:               map[string]string{"v": "3"},
   286  						}
   287  						err := installKismatic(nodes, installOpts, sshKey)
   288  						Expect(err).ToNot(HaveOccurred())
   289  
   290  						sub := SubDescribe("Using a running cluster")
   291  						defer sub.Check()
   292  
   293  						sub.It("should allow adding a worker node", func() error {
   294  							newNode := allWorkers[len(allWorkers)-1]
   295  							return addNodeToCluster(newNode, sshKey, []string{"com.integrationtest/worker=true"}, []string{})
   296  						})
   297  
   298  						sub.It("should allow adding a ingress node", func() error {
   299  							newNode := allWorkers[len(allWorkers)-2]
   300  							return addNodeToCluster(newNode, sshKey, []string{"com.integrationtest/worker=true"}, []string{"ingress"})
   301  						})
   302  
   303  						sub.It("should allow adding a storage node", func() error {
   304  							newNode := allWorkers[len(allWorkers)-3]
   305  							return addNodeToCluster(newNode, sshKey, []string{"com.integrationtest/worker=true"}, []string{"storage"})
   306  						})
   307  
   308  						sub.It("should be able to deploy a workload with ingress", func() error {
   309  							return verifyIngressNodes(nodes.master[0], nodes.ingress, sshKey)
   310  						})
   311  
   312  						// Use master[0] public IP
   313  						// sub.It("should have an accessible dashboard", func() error {
   314  						// 	return canAccessDashboard(fmt.Sprintf("https://admin:abbazabba@%s:6443/ui", nodes.master[0].PublicIP))
   315  						// })
   316  
   317  						sub.It("should respect network policies", func() error {
   318  							return verifyNetworkPolicy(nodes.master[0], sshKey)
   319  						})
   320  
   321  						sub.It("should support heapster with persistent storage", func() error {
   322  							return verifyHeapster(nodes.master[0], sshKey)
   323  						})
   324  
   325  						sub.It("should have tiller running", func() error {
   326  							return verifyTiller(nodes.master[0], sshKey)
   327  						})
   328  
   329  						sub.It("nodes should contain expected labels", func() error {
   330  							return containsLabels(nodes, sshKey)
   331  						})
   332  
   333  						sub.It("nodes should contain expected component overrides", func() error {
   334  							return ContainsOverrides(nodes, sshKey)
   335  						})
   336  
   337  						sub.It("should allow for running preflight checks idempotently", func() error {
   338  							return runValidate("kismatic-testing.yaml")
   339  						})
   340  					})
   341  				})
   342  			})
   343  		})
   344  
   345  		Context("when deploying a skunkworks cluster", func() {
   346  			Context("with Weave as the CNI provider", func() {
   347  				ItOnAWS("should install successfully [slow]", func(aws infrastructureProvisioner) {
   348  					WithInfrastructure(NodeCount{3, 2, 5, 2, 2}, Ubuntu1604LTS, aws, func(nodes provisionedNodes, sshKey string) {
   349  						// reserve 3 of the workers for the add-node test
   350  						allWorkers := nodes.worker
   351  						nodes.worker = allWorkers[0 : len(nodes.worker)-3]
   352  
   353  						// install cluster
   354  						installOpts := installOptions{
   355  							heapsterReplicas:    3,
   356  							heapsterInfluxdbPVC: "influxdb",
   357  							cniProvider:         "weave",
   358  						}
   359  						err := installKismatic(nodes, installOpts, sshKey)
   360  						Expect(err).ToNot(HaveOccurred())
   361  
   362  						sub := SubDescribe("Using a running cluster")
   363  						defer sub.Check()
   364  
   365  						sub.It("should allow adding a worker node", func() error {
   366  							newNode := allWorkers[len(allWorkers)-1]
   367  							return addNodeToCluster(newNode, sshKey, []string{"com.integrationtest/worker=true"}, []string{})
   368  						})
   369  
   370  						sub.It("should allow adding a ingress node", func() error {
   371  							newNode := allWorkers[len(allWorkers)-2]
   372  							return addNodeToCluster(newNode, sshKey, []string{"com.integrationtest/worker=true"}, []string{"ingress"})
   373  						})
   374  
   375  						sub.It("should allow adding a storage node", func() error {
   376  							newNode := allWorkers[len(allWorkers)-3]
   377  							return addNodeToCluster(newNode, sshKey, []string{"com.integrationtest/worker=true"}, []string{"storage"})
   378  						})
   379  
   380  						sub.It("should be able to deploy a workload with ingress", func() error {
   381  							return verifyIngressNodes(nodes.master[0], nodes.ingress, sshKey)
   382  						})
   383  
   384  						// Use master[0] public IP
   385  						// sub.It("should have an accessible dashboard", func() error {
   386  						// 	return canAccessDashboard(fmt.Sprintf("https://admin:abbazabba@%s:6443/ui", nodes.master[0].PublicIP))
   387  						// })
   388  
   389  						sub.It("should respect network policies", func() error {
   390  							return verifyNetworkPolicy(nodes.master[0], sshKey)
   391  						})
   392  
   393  						sub.It("should support heapster with persistent storage", func() error {
   394  							return verifyHeapster(nodes.master[0], sshKey)
   395  						})
   396  
   397  						sub.It("should have tiller running", func() error {
   398  							return verifyTiller(nodes.master[0], sshKey)
   399  						})
   400  
   401  						sub.It("nodes should contain expected labels", func() error {
   402  							return containsLabels(nodes, sshKey)
   403  						})
   404  
   405  						sub.It("should allow for running preflight checks idempotently", func() error {
   406  							return runValidate("kismatic-testing.yaml")
   407  						})
   408  					})
   409  				})
   410  			})
   411  		})
   412  
   413  		// Context("when deploying a skunkworks cluster", func() {
   414  		// 	Context("with Contiv as the CNI provider", func() {
   415  		// 		ItOnAWS("should install successfully [slow]", func(aws infrastructureProvisioner) {
   416  		// 			WithInfrastructure(NodeCount{3, 2, 3, 2, 2}, Ubuntu1604LTS, aws, func(nodes provisionedNodes, sshKey string) {
   417  		// 				// reserve 3 of the workers for the add-node test
   418  		// 				allWorkers := nodes.worker
   419  		// 				nodes.worker = allWorkers[0 : len(nodes.worker)-1]
   420  
   421  		// 				// install cluster
   422  		// 				installOpts := installOptions{
   423  		// 					heapsterReplicas:    3,
   424  		// 					heapsterInfluxdbPVC: "influxdb",
   425  		// 					cniProvider:         "contiv",
   426  		// 				}
   427  		// 				err := installKismatic(nodes, installOpts, sshKey)
   428  		// 				Expect(err).ToNot(HaveOccurred())
   429  
   430  		// 				sub := SubDescribe("Using a running cluster")
   431  		// 				defer sub.Check()
   432  
   433  		// 				sub.It("should allow adding a worker node", func() error {
   434  		// 					newNode := allWorkers[len(allWorkers)-1]
   435  		// 					return addNodeToCluster(newNode, sshKey, []string{})
   436  		// 				})
   437  
   438  		// 				// This test is flaky with contiv
   439  		// 				// sub.It("should be able to deploy a workload with ingress", func() error {
   440  		// 				// 	return verifyIngressNodes(nodes.master[0], nodes.ingress, sshKey)
   441  		// 				// })
   442  
   443  		// 				// Use master[0] public IP
   444  		// 				// There is an issue with contiv that prevents this test from passing consistently
   445  		// 				// sub.It("should have an accessible dashboard", func() error {
   446  		// 				// 	return canAccessDashboard(fmt.Sprintf("https://admin:abbazabba@%s:6443/ui", nodes.master[0].PublicIP))
   447  		// 				// })
   448  
   449  		// 				// Contiv does not support the Kubernetes network policy API
   450  		// 				// sub.It("should respect network policies", func() error {
   451  		// 				// 	return verifyNetworkPolicy(nodes.master[0], sshKey)
   452  		// 				// })
   453  
   454  		// 				sub.It("should support heapster with persistent storage", func() error {
   455  		// 					return verifyHeapster(nodes.master[0], sshKey)
   456  		// 				})
   457  
   458  		// 				sub.It("should have tiller running", func() error {
   459  		// 					return verifyTiller(nodes.master[0], sshKey)
   460  		// 				})
   461  		// 			})
   462  		// 		})
   463  		// 	})
   464  		// })
   465  
   466  		Context("when deploying a skunkworks cluster", func() {
   467  			Context("with CoreDNS as the DNS provider", func() {
   468  				ItOnAWS("should install successfully [slow]", func(aws infrastructureProvisioner) {
   469  					WithInfrastructure(NodeCount{3, 2, 5, 2, 2}, Ubuntu1604LTS, aws, func(nodes provisionedNodes, sshKey string) {
   470  						// reserve 3 of the workers for the add-node test
   471  						allWorkers := nodes.worker
   472  						nodes.worker = allWorkers[0 : len(nodes.worker)-3]
   473  
   474  						// install cluster
   475  						installOpts := installOptions{
   476  							heapsterReplicas:    3,
   477  							heapsterInfluxdbPVC: "influxdb",
   478  							dnsProvider:         "coredns",
   479  						}
   480  						err := installKismatic(nodes, installOpts, sshKey)
   481  						Expect(err).ToNot(HaveOccurred())
   482  
   483  						sub := SubDescribe("Using a running cluster")
   484  						defer sub.Check()
   485  
   486  						sub.It("should allow adding a worker node", func() error {
   487  							newNode := allWorkers[len(allWorkers)-1]
   488  							return addNodeToCluster(newNode, sshKey, []string{"com.integrationtest/worker=true"}, []string{})
   489  						})
   490  
   491  						sub.It("should allow adding a ingress node", func() error {
   492  							newNode := allWorkers[len(allWorkers)-2]
   493  							return addNodeToCluster(newNode, sshKey, []string{"com.integrationtest/worker=true"}, []string{"ingress"})
   494  						})
   495  
   496  						sub.It("should allow adding a storage node", func() error {
   497  							newNode := allWorkers[len(allWorkers)-3]
   498  							return addNodeToCluster(newNode, sshKey, []string{"com.integrationtest/worker=true"}, []string{"storage"})
   499  						})
   500  
   501  						sub.It("should be able to deploy a workload with ingress", func() error {
   502  							return verifyIngressNodes(nodes.master[0], nodes.ingress, sshKey)
   503  						})
   504  
   505  						sub.It("should respect network policies", func() error {
   506  							return verifyNetworkPolicy(nodes.master[0], sshKey)
   507  						})
   508  
   509  						sub.It("should support heapster with persistent storage", func() error {
   510  							return verifyHeapster(nodes.master[0], sshKey)
   511  						})
   512  
   513  						sub.It("should have tiller running", func() error {
   514  							return verifyTiller(nodes.master[0], sshKey)
   515  						})
   516  					})
   517  				})
   518  			})
   519  		})
   520  
   521  		ItOnPacket("should install successfully [slow]", func(packet infrastructureProvisioner) {
   522  			WithMiniInfrastructure(Ubuntu1604LTS, packet, func(node NodeDeets, sshKey string) {
   523  				err := installKismaticMini(node, sshKey)
   524  				Expect(err).ToNot(HaveOccurred())
   525  			})
   526  		})
   527  	})
   528  })
   529  
   530  func testCloudProvider(nodes provisionedNodes, sshKey string) {
   531  	installOpts := installOptions{cloudProvider: "aws"}
   532  
   533  	By("installing the cluster")
   534  	err := installKismatic(nodes, installOpts, sshKey)
   535  	Expect(err).ToNot(HaveOccurred())
   536  
   537  	By("test the cloud provider integration")
   538  	err = testAWSCloudProvider(nodes.master[0], sshKey)
   539  	Expect(err).ToNot(HaveOccurred())
   540  }