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