github.com/titanous/docker@v1.4.1/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  	target = strings.Trim(target, "\n")
   104  	target = strings.Trim(target, " ")
   105  	return target
   106  }
   107  
   108  func unmarshalJSON(data []byte, result interface{}) error {
   109  	err := json.Unmarshal(data, result)
   110  	if err != nil {
   111  		return err
   112  	}
   113  
   114  	return nil
   115  }
   116  
   117  func convertSliceOfStringsToMap(input []string) map[string]struct{} {
   118  	output := make(map[string]struct{})
   119  	for _, v := range input {
   120  		output[v] = struct{}{}
   121  	}
   122  	return output
   123  }
   124  
   125  func waitForContainer(contID string, args ...string) error {
   126  	args = append([]string{"run", "--name", contID}, args...)
   127  	cmd := exec.Command(dockerBinary, args...)
   128  	if _, err := runCommand(cmd); err != nil {
   129  		return err
   130  	}
   131  
   132  	if err := waitRun(contID); err != nil {
   133  		return err
   134  	}
   135  
   136  	return nil
   137  }
   138  
   139  func waitRun(contID string) error {
   140  	after := time.After(5 * time.Second)
   141  
   142  	for {
   143  		cmd := exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", contID)
   144  		out, _, err := runCommandWithOutput(cmd)
   145  		if err != nil {
   146  			return fmt.Errorf("error executing docker inspect: %v", err)
   147  		}
   148  
   149  		if strings.Contains(out, "true") {
   150  			break
   151  		}
   152  
   153  		select {
   154  		case <-after:
   155  			return fmt.Errorf("container did not come up in time")
   156  		default:
   157  		}
   158  
   159  		time.Sleep(100 * time.Millisecond)
   160  	}
   161  
   162  	return nil
   163  }
   164  
   165  func compareDirectoryEntries(e1 []os.FileInfo, e2 []os.FileInfo) error {
   166  	var (
   167  		e1Entries = make(map[string]struct{})
   168  		e2Entries = make(map[string]struct{})
   169  	)
   170  	for _, e := range e1 {
   171  		e1Entries[e.Name()] = struct{}{}
   172  	}
   173  	for _, e := range e2 {
   174  		e2Entries[e.Name()] = struct{}{}
   175  	}
   176  	if !reflect.DeepEqual(e1Entries, e2Entries) {
   177  		return fmt.Errorf("entries differ")
   178  	}
   179  	return nil
   180  }
   181  
   182  func ListTar(f io.Reader) ([]string, error) {
   183  	tr := tar.NewReader(f)
   184  	var entries []string
   185  
   186  	for {
   187  		th, err := tr.Next()
   188  		if err == io.EOF {
   189  			// end of tar archive
   190  			return entries, nil
   191  		}
   192  		if err != nil {
   193  			return entries, err
   194  		}
   195  		entries = append(entries, th.Name)
   196  	}
   197  }
   198  
   199  type FileServer struct {
   200  	*httptest.Server
   201  }
   202  
   203  func fileServer(files map[string]string) (*FileServer, error) {
   204  	var handler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
   205  		if filePath, found := files[r.URL.Path]; found {
   206  			http.ServeFile(w, r, filePath)
   207  		} else {
   208  			http.Error(w, http.StatusText(404), 404)
   209  		}
   210  	}
   211  
   212  	for _, file := range files {
   213  		if _, err := os.Stat(file); err != nil {
   214  			return nil, err
   215  		}
   216  	}
   217  	server := httptest.NewServer(handler)
   218  	return &FileServer{
   219  		Server: server,
   220  	}, nil
   221  }
   222  
   223  func copyWithCP(source, target string) error {
   224  	copyCmd := exec.Command("cp", "-rp", source, target)
   225  	out, exitCode, err := runCommandWithOutput(copyCmd)
   226  	if err != nil || exitCode != 0 {
   227  		return fmt.Errorf("failed to copy: error: %q ,output: %q", err, out)
   228  	}
   229  	return nil
   230  }
   231  
   232  func makeRandomString(n int) string {
   233  	// make a really long string
   234  	letters := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
   235  	b := make([]byte, n)
   236  	for i := range b {
   237  		b[i] = letters[rand.Intn(len(letters))]
   238  	}
   239  	return string(b)
   240  }
   241  
   242  // Reads chunkSize bytes from reader after every interval.
   243  // Returns total read bytes.
   244  func consumeWithSpeed(reader io.Reader, chunkSize int, interval time.Duration, stop chan bool) (n int, err error) {
   245  	buffer := make([]byte, chunkSize)
   246  	for {
   247  		select {
   248  		case <-stop:
   249  			return
   250  		default:
   251  			var readBytes int
   252  			readBytes, err = reader.Read(buffer)
   253  			n += readBytes
   254  			if err != nil {
   255  				if err == io.EOF {
   256  					err = nil
   257  				}
   258  				return
   259  			}
   260  			time.Sleep(interval)
   261  		}
   262  	}
   263  }