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