github.com/misfo/deis@v1.0.1-0.20141111224634-e0eee0392b8a/tests/utils/itutils.go (about)

     1  package utils
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"math/rand"
     8  	"net/http"
     9  	"os"
    10  	"os/exec"
    11  	"strings"
    12  	"testing"
    13  	"text/template"
    14  	"time"
    15  
    16  	"github.com/ThomasRooney/gexpect"
    17  )
    18  
    19  // Deis points to the CLI used to run tests.
    20  var Deis = "deis "
    21  
    22  // DeisTestConfig allows tests to be repeated against different
    23  // targets, with different example apps, using specific credentials, and so on.
    24  type DeisTestConfig struct {
    25  	AuthKey     string
    26  	Hosts       string
    27  	Domain      string
    28  	SSHKey      string
    29  	ClusterName string
    30  	UserName    string
    31  	Password    string
    32  	Email       string
    33  	ExampleApp  string
    34  	AppName     string
    35  	ProcessNum  string
    36  	ImageID     string
    37  	Version     string
    38  	AppUser     string
    39  }
    40  
    41  // randomApp is used for the test run if DEIS_TEST_APP isn't set
    42  var randomApp = GetRandomApp()
    43  
    44  // GetGlobalConfig returns a test configuration object.
    45  func GetGlobalConfig() *DeisTestConfig {
    46  	authKey := os.Getenv("DEIS_TEST_AUTH_KEY")
    47  	if authKey == "" {
    48  		authKey = "deis"
    49  	}
    50  	hosts := os.Getenv("DEIS_TEST_HOSTS")
    51  	if hosts == "" {
    52  		hosts = "172.17.8.100"
    53  	}
    54  	domain := os.Getenv("DEIS_TEST_DOMAIN")
    55  	if domain == "" {
    56  		domain = "local.deisapp.com"
    57  	}
    58  	sshKey := os.Getenv("DEIS_TEST_SSH_KEY")
    59  	if sshKey == "" {
    60  		sshKey = "~/.vagrant.d/insecure_private_key"
    61  	}
    62  	exampleApp := os.Getenv("DEIS_TEST_APP")
    63  	if exampleApp == "" {
    64  		exampleApp = randomApp
    65  	}
    66  	var envCfg = DeisTestConfig{
    67  		AuthKey:     authKey,
    68  		Hosts:       hosts,
    69  		Domain:      domain,
    70  		SSHKey:      sshKey,
    71  		ClusterName: "dev",
    72  		UserName:    "test",
    73  		Password:    "asdf1234",
    74  		Email:       "test@test.co.nz",
    75  		ExampleApp:  exampleApp,
    76  		AppName:     "sample",
    77  		ProcessNum:  "2",
    78  		ImageID:     "buildtest",
    79  		Version:     "2",
    80  		AppUser:     "test1",
    81  	}
    82  	return &envCfg
    83  }
    84  
    85  func doCurl(url string) ([]byte, error) {
    86  	response, err := http.Get(url)
    87  	defer response.Body.Close()
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	body, err := ioutil.ReadAll(response.Body)
    93  
    94  	if !strings.Contains(string(body), "Powered by Deis") {
    95  		return nil, fmt.Errorf("App not started (%d)", response.StatusCode)
    96  	}
    97  
    98  	return body, nil
    99  }
   100  
   101  // Curl connects to a Deis endpoint to see if the example app is running.
   102  func Curl(t *testing.T, params *DeisTestConfig) {
   103  	url := "http://" + params.AppName + "." + params.Domain
   104  
   105  	// FIXME: try the curl a few times
   106  	for i := 0; i < 20; i++ {
   107  		body, err := doCurl(url)
   108  		if err == nil {
   109  			fmt.Println(string(body))
   110  			return
   111  		}
   112  		time.Sleep(1 * time.Second)
   113  	}
   114  
   115  	// once more to fail with an error
   116  	body, err := doCurl(url)
   117  	if err != nil {
   118  		t.Fatal(err)
   119  	}
   120  	fmt.Println(string(body))
   121  }
   122  
   123  // AuthCancel tests whether `deis auth:cancel` destroys a user's account.
   124  func AuthCancel(t *testing.T, params *DeisTestConfig) {
   125  	fmt.Println("deis auth:cancel")
   126  	child, err := gexpect.Spawn(Deis + " auth:cancel")
   127  	if err != nil {
   128  		t.Fatalf("command not started\n%v", err)
   129  	}
   130  	fmt.Println("username:")
   131  	err = child.Expect("username:")
   132  	if err != nil {
   133  		t.Fatalf("expect username failed\n%v", err)
   134  	}
   135  	child.SendLine(params.UserName)
   136  	fmt.Print("password:")
   137  	err = child.Expect("password:")
   138  	if err != nil {
   139  		t.Fatalf("expect password failed\n%v", err)
   140  	}
   141  	child.SendLine(params.Password)
   142  	err = child.ExpectRegex("(y/n)")
   143  	if err != nil {
   144  		t.Fatalf("expect cancel \n%v", err)
   145  	}
   146  	child.SendLine("y")
   147  	err = child.Expect("Account cancelled")
   148  	if err != nil {
   149  		t.Fatalf("command executiuon failed\n%v", err)
   150  	}
   151  	child.Close()
   152  }
   153  
   154  // AuthPasswd tests whether `deis auth:passwd` updates a user's password.
   155  func AuthPasswd(t *testing.T, params *DeisTestConfig, password string) {
   156  	fmt.Println("deis auth:passwd")
   157  	child, err := gexpect.Spawn(Deis + " auth:passwd")
   158  	if err != nil {
   159  		t.Fatalf("command not started\n%v", err)
   160  	}
   161  	fmt.Println("current password:")
   162  	err = child.Expect("current password: ")
   163  	if err != nil {
   164  		t.Fatalf("expect password failed\n%v", err)
   165  	}
   166  	child.SendLine(params.Password)
   167  	fmt.Println("new password:")
   168  	err = child.Expect("new password: ")
   169  	if err != nil {
   170  		t.Fatalf("expect password failed\n%v", err)
   171  	}
   172  	child.SendLine(password)
   173  	fmt.Println("new password (confirm):")
   174  	err = child.Expect("new password (confirm): ")
   175  	if err != nil {
   176  		t.Fatalf("expect password failed\n%v", err)
   177  	}
   178  	child.SendLine(password)
   179  	err = child.Expect("Password change succeeded")
   180  	if err != nil {
   181  		t.Fatalf("command executiuon failed\n%v", err)
   182  	}
   183  	child.Close()
   184  }
   185  
   186  // CheckList executes a command and optionally tests whether its output does
   187  // or does not contain a given string.
   188  func CheckList(
   189  	t *testing.T, cmd string, params interface{}, contain string, notflag bool) {
   190  	var cmdBuf bytes.Buffer
   191  	tmpl := template.Must(template.New("cmd").Parse(cmd))
   192  	if err := tmpl.Execute(&cmdBuf, params); err != nil {
   193  		t.Fatal(err)
   194  	}
   195  	cmdString := cmdBuf.String()
   196  	fmt.Println(cmdString)
   197  	var cmdl *exec.Cmd
   198  	if strings.Contains(cmd, "cat") {
   199  		cmdl = exec.Command("sh", "-c", cmdString)
   200  	} else {
   201  		cmdl = exec.Command("sh", "-c", Deis+cmdString)
   202  	}
   203  	stdout, _, err := RunCommandWithStdoutStderr(cmdl)
   204  	if err != nil {
   205  		t.Fatal(err)
   206  	}
   207  	if strings.Contains(stdout.String(), contain) == notflag {
   208  		if notflag {
   209  			t.Fatalf(
   210  				"Didn't expect '%s' in command output:\n%v", contain, stdout)
   211  		}
   212  		t.Fatalf("Expected '%s' in command output:\n%v", contain, stdout)
   213  	}
   214  }
   215  
   216  // Execute takes command string and parameters required to execute the command,
   217  // a failflag to check whether the command is expected to fail, and an expect
   218  // string to check whether the command has failed according to failflag.
   219  //
   220  // If failflag is true and the command failed, check the stdout and stderr for
   221  // the expect string.
   222  func Execute(t *testing.T, cmd string, params interface{}, failFlag bool, expect string) {
   223  	var cmdBuf bytes.Buffer
   224  	tmpl := template.Must(template.New("cmd").Parse(cmd))
   225  	if err := tmpl.Execute(&cmdBuf, params); err != nil {
   226  		t.Fatal(err)
   227  	}
   228  	cmdString := cmdBuf.String()
   229  	fmt.Println(cmdString)
   230  	var cmdl *exec.Cmd
   231  	if strings.Contains(cmd, "git") {
   232  		cmdl = exec.Command("sh", "-c", cmdString)
   233  	} else {
   234  		cmdl = exec.Command("sh", "-c", Deis+cmdString)
   235  	}
   236  
   237  	switch failFlag {
   238  	case true:
   239  		if stdout, stderr, err := RunCommandWithStdoutStderr(cmdl); err != nil {
   240  			if strings.Contains(stdout.String(), expect) || strings.Contains(stderr.String(), expect) {
   241  				fmt.Println("(Error expected...ok)")
   242  			} else {
   243  				t.Fatal(err)
   244  			}
   245  		} else {
   246  			if strings.Contains(stdout.String(), expect) || strings.Contains(stderr.String(), expect) {
   247  				fmt.Println("(Error expected...ok)" + expect)
   248  			} else {
   249  				t.Fatal(err)
   250  			}
   251  		}
   252  	case false:
   253  		if _, _, err := RunCommandWithStdoutStderr(cmdl); err != nil {
   254  			t.Fatal(err)
   255  		} else {
   256  			fmt.Println("ok")
   257  		}
   258  	}
   259  }
   260  
   261  // AppsDestroyTest destroys a Deis app and checks that it was successful.
   262  func AppsDestroyTest(t *testing.T, params *DeisTestConfig) {
   263  	cmd := "apps:destroy --app={{.AppName}} --confirm={{.AppName}}"
   264  	if err := Chdir(params.ExampleApp); err != nil {
   265  		t.Fatal(err)
   266  	}
   267  	Execute(t, cmd, params, false, "")
   268  	if err := Chdir(".."); err != nil {
   269  		t.Fatal(err)
   270  	}
   271  	if err := Rmdir(params.ExampleApp); err != nil {
   272  		t.Fatal(err)
   273  	}
   274  }
   275  
   276  // GetRandomApp returns a known working example app at random for testing.
   277  func GetRandomApp() string {
   278  	rand.Seed(int64(time.Now().Unix()))
   279  	apps := []string{
   280  		"example-clojure-ring",
   281  		// "example-dart",
   282  		"example-dockerfile-python",
   283  		"example-go",
   284  		"example-java-jetty",
   285  		"example-nodejs-express",
   286  		// "example-php",
   287  		"example-play",
   288  		"example-python-django",
   289  		"example-python-flask",
   290  		"example-ruby-sinatra",
   291  		"example-scala",
   292  	}
   293  	return apps[rand.Intn(len(apps))]
   294  }