github.com/fcwu/docker@v1.4.2-0.20150115145920-2a69ca89f0df/integration-cli/utils.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"math/rand"
     9  	"net/http"
    10  	"net/http/httptest"
    11  	"os"
    12  	"os/exec"
    13  	"reflect"
    14  	"strings"
    15  	"syscall"
    16  	"time"
    17  
    18  	"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
    19  )
    20  
    21  func getExitCode(err error) (int, error) {
    22  	exitCode := 0
    23  	if exiterr, ok := err.(*exec.ExitError); ok {
    24  		if procExit := exiterr.Sys().(syscall.WaitStatus); ok {
    25  			return procExit.ExitStatus(), nil
    26  		}
    27  	}
    28  	return exitCode, fmt.Errorf("failed to get exit code")
    29  }
    30  
    31  func processExitCode(err error) (exitCode int) {
    32  	if err != nil {
    33  		var exiterr error
    34  		if exitCode, exiterr = getExitCode(err); exiterr != nil {
    35  			// TODO: Fix this so we check the error's text.
    36  			// we've failed to retrieve exit code, so we set it to 127
    37  			exitCode = 127
    38  		}
    39  	}
    40  	return
    41  }
    42  
    43  func runCommandWithOutput(cmd *exec.Cmd) (output string, exitCode int, err error) {
    44  	exitCode = 0
    45  	out, err := cmd.CombinedOutput()
    46  	exitCode = processExitCode(err)
    47  	output = string(out)
    48  	return
    49  }
    50  
    51  func runCommandWithStdoutStderr(cmd *exec.Cmd) (stdout string, stderr string, exitCode int, err error) {
    52  	var (
    53  		stderrBuffer, stdoutBuffer bytes.Buffer
    54  	)
    55  	exitCode = 0
    56  	cmd.Stderr = &stderrBuffer
    57  	cmd.Stdout = &stdoutBuffer
    58  	err = cmd.Run()
    59  	exitCode = processExitCode(err)
    60  
    61  	stdout = stdoutBuffer.String()
    62  	stderr = stderrBuffer.String()
    63  	return
    64  }
    65  
    66  var ErrCmdTimeout = fmt.Errorf("command timed out")
    67  
    68  func runCommandWithOutputAndTimeout(cmd *exec.Cmd, timeout time.Duration) (output string, exitCode int, err error) {
    69  	done := make(chan error)
    70  	go func() {
    71  		output, exitCode, err = runCommandWithOutput(cmd)
    72  		if err != nil || exitCode != 0 {
    73  			done <- fmt.Errorf("failed to run command: %s", err)
    74  			return
    75  		}
    76  		done <- nil
    77  	}()
    78  	select {
    79  	case <-time.After(timeout):
    80  		killFailed := cmd.Process.Kill()
    81  		if killFailed == nil {
    82  			fmt.Printf("failed to kill (pid=%d): %v\n", cmd.Process.Pid, err)
    83  		}
    84  		err = ErrCmdTimeout
    85  	case <-done:
    86  		break
    87  	}
    88  	return
    89  }
    90  
    91  func runCommand(cmd *exec.Cmd) (exitCode int, err error) {
    92  	exitCode = 0
    93  	err = cmd.Run()
    94  	exitCode = processExitCode(err)
    95  	return
    96  }
    97  
    98  func logDone(message string) {
    99  	fmt.Printf("[PASSED]: %s\n", message)
   100  }
   101  
   102  func stripTrailingCharacters(target string) string {
   103  	return strings.TrimSpace(target)
   104  }
   105  
   106  func unmarshalJSON(data []byte, result interface{}) error {
   107  	err := json.Unmarshal(data, result)
   108  	if err != nil {
   109  		return err
   110  	}
   111  
   112  	return nil
   113  }
   114  
   115  func convertSliceOfStringsToMap(input []string) map[string]struct{} {
   116  	output := make(map[string]struct{})
   117  	for _, v := range input {
   118  		output[v] = struct{}{}
   119  	}
   120  	return output
   121  }
   122  
   123  func waitForContainer(contID string, args ...string) error {
   124  	args = append([]string{"run", "--name", contID}, args...)
   125  	cmd := exec.Command(dockerBinary, args...)
   126  	if _, err := runCommand(cmd); err != nil {
   127  		return err
   128  	}
   129  
   130  	if err := waitRun(contID); err != nil {
   131  		return err
   132  	}
   133  
   134  	return nil
   135  }
   136  
   137  func waitRun(contID string) error {
   138  	after := time.After(5 * time.Second)
   139  
   140  	for {
   141  		cmd := exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", contID)
   142  		out, _, err := runCommandWithOutput(cmd)
   143  		if err != nil {
   144  			return fmt.Errorf("error executing docker inspect: %v", err)
   145  		}
   146  
   147  		if strings.Contains(out, "true") {
   148  			break
   149  		}
   150  
   151  		select {
   152  		case <-after:
   153  			return fmt.Errorf("container did not come up in time")
   154  		default:
   155  		}
   156  
   157  		time.Sleep(100 * time.Millisecond)
   158  	}
   159  
   160  	return nil
   161  }
   162  
   163  func compareDirectoryEntries(e1 []os.FileInfo, e2 []os.FileInfo) error {
   164  	var (
   165  		e1Entries = make(map[string]struct{})
   166  		e2Entries = make(map[string]struct{})
   167  	)
   168  	for _, e := range e1 {
   169  		e1Entries[e.Name()] = struct{}{}
   170  	}
   171  	for _, e := range e2 {
   172  		e2Entries[e.Name()] = struct{}{}
   173  	}
   174  	if !reflect.DeepEqual(e1Entries, e2Entries) {
   175  		return fmt.Errorf("entries differ")
   176  	}
   177  	return nil
   178  }
   179  
   180  func ListTar(f io.Reader) ([]string, error) {
   181  	tr := tar.NewReader(f)
   182  	var entries []string
   183  
   184  	for {
   185  		th, err := tr.Next()
   186  		if err == io.EOF {
   187  			// end of tar archive
   188  			return entries, nil
   189  		}
   190  		if err != nil {
   191  			return entries, err
   192  		}
   193  		entries = append(entries, th.Name)
   194  	}
   195  }
   196  
   197  type FileServer struct {
   198  	*httptest.Server
   199  }
   200  
   201  func fileServer(files map[string]string) (*FileServer, error) {
   202  	var handler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
   203  		if filePath, found := files[r.URL.Path]; found {
   204  			http.ServeFile(w, r, filePath)
   205  		} else {
   206  			http.Error(w, http.StatusText(404), 404)
   207  		}
   208  	}
   209  
   210  	for _, file := range files {
   211  		if _, err := os.Stat(file); err != nil {
   212  			return nil, err
   213  		}
   214  	}
   215  	server := httptest.NewServer(handler)
   216  	return &FileServer{
   217  		Server: server,
   218  	}, nil
   219  }
   220  
   221  func copyWithCP(source, target string) error {
   222  	copyCmd := exec.Command("cp", "-rp", source, target)
   223  	out, exitCode, err := runCommandWithOutput(copyCmd)
   224  	if err != nil || exitCode != 0 {
   225  		return fmt.Errorf("failed to copy: error: %q ,output: %q", err, out)
   226  	}
   227  	return nil
   228  }
   229  
   230  func makeRandomString(n int) string {
   231  	// make a really long string
   232  	letters := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
   233  	b := make([]byte, n)
   234  	for i := range b {
   235  		b[i] = letters[rand.Intn(len(letters))]
   236  	}
   237  	return string(b)
   238  }
   239  
   240  // Reads chunkSize bytes from reader after every interval.
   241  // Returns total read bytes.
   242  func consumeWithSpeed(reader io.Reader, chunkSize int, interval time.Duration, stop chan bool) (n int, err error) {
   243  	buffer := make([]byte, chunkSize)
   244  	for {
   245  		select {
   246  		case <-stop:
   247  			return
   248  		default:
   249  			var readBytes int
   250  			readBytes, err = reader.Read(buffer)
   251  			n += readBytes
   252  			if err != nil {
   253  				if err == io.EOF {
   254  					err = nil
   255  				}
   256  				return
   257  			}
   258  			time.Sleep(interval)
   259  		}
   260  	}
   261  }