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  }