github.com/jlmeeker/kismatic@v1.10.1-0.20180612190640-57f9005a1f1a/integration-tests/install.go (about) 1 package integration_tests 2 3 import ( 4 "bufio" 5 "crypto/tls" 6 "fmt" 7 "html/template" 8 "net/http" 9 "os" 10 "os/exec" 11 "path/filepath" 12 "time" 13 14 homedir "github.com/mitchellh/go-homedir" 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/gomega" 17 ) 18 19 func leaveIt() bool { 20 return os.Getenv("LEAVE_ARTIFACTS") != "" 21 } 22 23 func GetSSHKeyFile() (string, error) { 24 dir, err := homedir.Dir() 25 if err != nil { 26 return "", err 27 } 28 return filepath.Join(dir, ".ssh", "kismatic-integration-testing.pem"), nil 29 } 30 31 type installOptions struct { 32 disablePackageInstallation bool 33 disableDockerInstallation bool 34 disconnectedInstallation bool 35 dockerRegistryServer string 36 dockerRegistryCAPath string 37 dockerRegistryUsername string 38 dockerRegistryPassword string 39 modifyHostsFiles bool 40 httpProxy string 41 httpsProxy string 42 noProxy string 43 dockerStorageDriver string 44 serviceCIDR string 45 disableCNI bool 46 cniProvider string 47 dnsProvider string 48 heapsterReplicas int 49 heapsterInfluxdbPVC string 50 cloudProvider string 51 kubeAPIServerOptions map[string]string 52 kubeControllerManagerOptions map[string]string 53 kubeSchedulerOptions map[string]string 54 kubeProxyOptions map[string]string 55 kubeletOptions map[string]string 56 } 57 58 func installKismaticMini(node NodeDeets, sshKey string) error { 59 sshUser := node.SSHUser 60 plan := PlanAWS{ 61 Etcd: []NodeDeets{node}, 62 Master: []NodeDeets{node}, 63 Worker: []NodeDeets{node}, 64 Ingress: []NodeDeets{node}, 65 Storage: []NodeDeets{node}, 66 MasterNodeFQDN: node.PublicIP, 67 MasterNodeShortName: node.PublicIP, 68 SSHKeyFile: sshKey, 69 SSHUser: sshUser, 70 } 71 return installKismaticWithPlan(plan) 72 } 73 74 func resetKismatic() error { 75 By("Resetting Cluster") 76 cmd := exec.Command("./kismatic", "reset", "-f", "kismatic-testing.yaml", "--force") 77 cmd.Stdout = os.Stdout 78 cmd.Stderr = os.Stderr 79 return cmd.Run() 80 } 81 82 func installKismatic(nodes provisionedNodes, installOpts installOptions, sshKey string) error { 83 return installKismaticWithPlan(buildPlan(nodes, installOpts, sshKey)) 84 } 85 86 func validateKismatic(nodes provisionedNodes, installOpts installOptions, sshKey string) error { 87 return validateKismaticWithPlan(buildPlan(nodes, installOpts, sshKey)) 88 } 89 90 func buildPlan(nodes provisionedNodes, installOpts installOptions, sshKey string) PlanAWS { 91 sshUser := nodes.master[0].SSHUser 92 masterDNS := nodes.master[0].PublicIP 93 disableHelm := false 94 if nodes.dnsRecord != nil && nodes.dnsRecord.Name != "" { 95 masterDNS = nodes.dnsRecord.Name 96 // disable helm if using Route53 97 disableHelm = true 98 } 99 plan := PlanAWS{ 100 DisablePackageInstallation: installOpts.disablePackageInstallation, 101 DisableDockerInstallation: installOpts.disableDockerInstallation, 102 DisconnectedInstallation: installOpts.disconnectedInstallation, 103 Etcd: nodes.etcd, 104 Master: nodes.master, 105 Worker: nodes.worker, 106 Ingress: nodes.ingress, 107 Storage: nodes.storage, 108 MasterNodeFQDN: masterDNS, 109 MasterNodeShortName: masterDNS, 110 SSHKeyFile: sshKey, 111 SSHUser: sshUser, 112 DockerRegistryCAPath: installOpts.dockerRegistryCAPath, 113 DockerRegistryServer: installOpts.dockerRegistryServer, 114 DockerRegistryUsername: installOpts.dockerRegistryUsername, 115 DockerRegistryPassword: installOpts.dockerRegistryPassword, 116 ModifyHostsFiles: installOpts.modifyHostsFiles, 117 HTTPProxy: installOpts.httpProxy, 118 HTTPSProxy: installOpts.httpsProxy, 119 NoProxy: installOpts.noProxy, 120 DockerStorageDriver: installOpts.dockerStorageDriver, 121 ServiceCIDR: installOpts.serviceCIDR, 122 DisableCNI: installOpts.disableCNI, 123 CNIProvider: installOpts.cniProvider, 124 DNSProvider: installOpts.dnsProvider, 125 DisableHelm: disableHelm, 126 HeapsterReplicas: installOpts.heapsterReplicas, 127 HeapsterInfluxdbPVC: installOpts.heapsterInfluxdbPVC, 128 CloudProvider: installOpts.cloudProvider, 129 KubeAPIServerOptions: installOpts.kubeAPIServerOptions, 130 KubeControllerManagerOptions: installOpts.kubeControllerManagerOptions, 131 KubeSchedulerOptions: installOpts.kubeSchedulerOptions, 132 KubeProxyOptions: installOpts.kubeProxyOptions, 133 KubeletOptions: installOpts.kubeletOptions, 134 } 135 return plan 136 } 137 138 func installKismaticWithPlan(plan PlanAWS) error { 139 writePlanFile(plan) 140 141 By("Punch it Chewie!") 142 cmd := exec.Command("./kismatic", "install", "apply", "-f", "kismatic-testing.yaml") 143 cmd.Stdout = os.Stdout 144 cmd.Stderr = os.Stderr 145 146 if err := cmd.Run(); err != nil { 147 // run diagnostics on error 148 fmt.Println("----- Running diagnose command -----") 149 diagsCmd := exec.Command("./kismatic", "diagnose", "-f", "kismatic-testing.yaml") 150 diagsCmd.Stdout = os.Stdout 151 diagsCmd.Stderr = os.Stderr 152 if errDiags := diagsCmd.Run(); errDiags != nil { 153 fmt.Printf("ERROR: error running diagnose command: %v", errDiags) 154 } 155 return err 156 } 157 return nil 158 } 159 160 func validateKismaticWithPlan(plan PlanAWS) error { 161 writePlanFile(plan) 162 163 By("Validate Plan") 164 cmd := exec.Command("./kismatic", "install", "validate", "-f", "kismatic-testing.yaml") 165 cmd.Stdout = os.Stdout 166 cmd.Stderr = os.Stderr 167 return cmd.Run() 168 } 169 170 func writePlanFile(plan PlanAWS) { 171 By("Building a template") 172 template, err := template.New("planAWSOverlay").Parse(planAWSOverlay) 173 FailIfError(err, "Couldn't parse template") 174 175 path := "kismatic-testing.yaml" 176 _, err = os.Stat(path) 177 // create file if not exists 178 if os.IsNotExist(err) { 179 f, err := os.Create(path) 180 FailIfError(err, "Error creating plan") 181 defer f.Close() 182 w := bufio.NewWriter(f) 183 err = template.Execute(w, &plan) 184 FailIfError(err, "Error filling in plan template") 185 w.Flush() 186 } 187 } 188 189 func installKismaticWithABadNode() { 190 By("Building a template") 191 template, err := template.New("planAWSOverlay").Parse(planAWSOverlay) 192 FailIfError(err, "Couldn't parse template") 193 194 By("Faking infrastructure") 195 fakeNode := NodeDeets{ 196 id: "FakeId", 197 PublicIP: "10.0.0.0", 198 Hostname: "FakeHostname", 199 } 200 201 By("Building a plan to set up an overlay network cluster on this hardware") 202 sshKey, err := GetSSHKeyFile() 203 FailIfError(err, "Error getting SSH Key file") 204 plan := PlanAWS{ 205 Etcd: []NodeDeets{fakeNode}, 206 Master: []NodeDeets{fakeNode}, 207 Worker: []NodeDeets{fakeNode}, 208 Ingress: []NodeDeets{fakeNode}, 209 MasterNodeFQDN: "yep.nope", 210 MasterNodeShortName: "yep", 211 SSHUser: "Billy Rubin", 212 SSHKeyFile: sshKey, 213 } 214 By("Writing plan file out to disk") 215 f, err := os.Create("kismatic-testing.yaml") 216 FailIfError(err, "Error waiting for nodes") 217 defer f.Close() 218 w := bufio.NewWriter(f) 219 err = template.Execute(w, &plan) 220 FailIfError(err, "Error filling in plan template") 221 w.Flush() 222 f.Close() 223 224 By("Validing our plan") 225 cmd := exec.Command("./kismatic", "install", "validate", "-f", f.Name()) 226 cmd.Stdout = os.Stdout 227 cmd.Stderr = os.Stderr 228 err = cmd.Run() 229 if err == nil { 230 Fail("Validation succeeeded even though it shouldn't have") 231 } 232 233 By("Well, try it anyway") 234 cmd = exec.Command("./kismatic", "install", "apply", "-f", f.Name()) 235 cmd.Stdout = os.Stdout 236 cmd.Stderr = os.Stderr 237 err = cmd.Run() 238 if err == nil { 239 Fail("Application succeeeded even though it shouldn't have") 240 } 241 } 242 243 func completesInTime(dothis func(), howLong time.Duration) bool { 244 c1 := make(chan string, 1) 245 go func() { 246 dothis() 247 c1 <- "completed" 248 }() 249 250 select { 251 case <-c1: 252 return true 253 case <-time.After(howLong): 254 return false 255 } 256 } 257 258 func canAccessDashboard(url string) error { 259 tr := &http.Transport{ 260 TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 261 } 262 client := http.Client{ 263 Timeout: 1000 * time.Millisecond, 264 Transport: tr, 265 } 266 req, err := http.NewRequest(http.MethodGet, url, nil) 267 if err != nil { 268 return fmt.Errorf("Could not create request for ingress via %s, %v", url, err) 269 } 270 // Access the dashboard a few times to hit all replicas 271 for i := 0; i < 3; i++ { 272 resp, err := client.Do(req) 273 if err != nil { 274 return fmt.Errorf("Could not reach ingress via %s, %v", url, err) 275 } 276 if resp.StatusCode != 200 { 277 return fmt.Errorf("Ingress status code is not 200, got %d vi %s", resp.StatusCode, url) 278 } 279 } 280 281 return nil 282 } 283 284 func FailIfError(err error, message ...interface{}) { 285 Expect(err).ToNot(HaveOccurred(), message...) 286 } 287 288 func FailIfSuccess(err error) { 289 if err == nil { 290 Fail("Expected failure") 291 } 292 } 293 294 func FileExists(path string) bool { 295 if _, err := os.Stat(path); os.IsNotExist(err) { 296 return false 297 } 298 return true 299 }