github.com/stchris/docker@v1.4.2-0.20150106053530-1510a324dbd5/integration-cli/docker_api_containers_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io" 7 "io/ioutil" 8 "os" 9 "os/exec" 10 "strings" 11 "testing" 12 13 "github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar" 14 ) 15 16 func TestContainerApiGetAll(t *testing.T) { 17 startCount, err := getContainerCount() 18 if err != nil { 19 t.Fatalf("Cannot query container count: %v", err) 20 } 21 22 name := "getall" 23 runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "true") 24 out, _, err := runCommandWithOutput(runCmd) 25 if err != nil { 26 t.Fatalf("Error on container creation: %v, output: %q", err, out) 27 } 28 29 body, err := sockRequest("GET", "/containers/json?all=1", nil) 30 if err != nil { 31 t.Fatalf("GET all containers sockRequest failed: %v", err) 32 } 33 34 var inspectJSON []struct { 35 Names []string 36 } 37 if err = json.Unmarshal(body, &inspectJSON); err != nil { 38 t.Fatalf("unable to unmarshal response body: %v", err) 39 } 40 41 if len(inspectJSON) != startCount+1 { 42 t.Fatalf("Expected %d container(s), %d found (started with: %d)", startCount+1, len(inspectJSON), startCount) 43 } 44 45 if actual := inspectJSON[0].Names[0]; actual != "/"+name { 46 t.Fatalf("Container Name mismatch. Expected: %q, received: %q\n", "/"+name, actual) 47 } 48 49 deleteAllContainers() 50 51 logDone("container REST API - check GET json/all=1") 52 } 53 54 func TestContainerApiGetExport(t *testing.T) { 55 name := "exportcontainer" 56 runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test") 57 out, _, err := runCommandWithOutput(runCmd) 58 if err != nil { 59 t.Fatalf("Error on container creation: %v, output: %q", err, out) 60 } 61 62 body, err := sockRequest("GET", "/containers/"+name+"/export", nil) 63 if err != nil { 64 t.Fatalf("GET containers/export sockRequest failed: %v", err) 65 } 66 67 found := false 68 for tarReader := tar.NewReader(bytes.NewReader(body)); ; { 69 h, err := tarReader.Next() 70 if err != nil { 71 if err == io.EOF { 72 break 73 } 74 t.Fatal(err) 75 } 76 if h.Name == "test" { 77 found = true 78 break 79 } 80 } 81 82 if !found { 83 t.Fatalf("The created test file has not been found in the exported image") 84 } 85 deleteAllContainers() 86 87 logDone("container REST API - check GET containers/export") 88 } 89 90 func TestContainerApiGetChanges(t *testing.T) { 91 name := "changescontainer" 92 runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "rm", "/etc/passwd") 93 out, _, err := runCommandWithOutput(runCmd) 94 if err != nil { 95 t.Fatalf("Error on container creation: %v, output: %q", err, out) 96 } 97 98 body, err := sockRequest("GET", "/containers/"+name+"/changes", nil) 99 if err != nil { 100 t.Fatalf("GET containers/changes sockRequest failed: %v", err) 101 } 102 103 changes := []struct { 104 Kind int 105 Path string 106 }{} 107 if err = json.Unmarshal(body, &changes); err != nil { 108 t.Fatalf("unable to unmarshal response body: %v", err) 109 } 110 111 // Check the changelog for removal of /etc/passwd 112 success := false 113 for _, elem := range changes { 114 if elem.Path == "/etc/passwd" && elem.Kind == 2 { 115 success = true 116 } 117 } 118 if !success { 119 t.Fatalf("/etc/passwd has been removed but is not present in the diff") 120 } 121 122 deleteAllContainers() 123 124 logDone("container REST API - check GET containers/changes") 125 } 126 127 func TestContainerApiStartVolumeBinds(t *testing.T) { 128 defer deleteAllContainers() 129 name := "testing" 130 config := map[string]interface{}{ 131 "Image": "busybox", 132 "Volumes": map[string]struct{}{"/tmp": {}}, 133 } 134 135 if _, err := sockRequest("POST", "/containers/create?name="+name, config); err != nil && !strings.Contains(err.Error(), "201 Created") { 136 t.Fatal(err) 137 } 138 139 bindPath, err := ioutil.TempDir(os.TempDir(), "test") 140 if err != nil { 141 t.Fatal(err) 142 } 143 144 config = map[string]interface{}{ 145 "Binds": []string{bindPath + ":/tmp"}, 146 } 147 if _, err := sockRequest("POST", "/containers/"+name+"/start", config); err != nil && !strings.Contains(err.Error(), "204 No Content") { 148 t.Fatal(err) 149 } 150 151 pth, err := inspectFieldMap(name, "Volumes", "/tmp") 152 if err != nil { 153 t.Fatal(err) 154 } 155 156 if pth != bindPath { 157 t.Fatalf("expected volume host path to be %s, got %s", bindPath, pth) 158 } 159 160 logDone("container REST API - check volume binds on start") 161 } 162 163 func TestContainerApiStartVolumesFrom(t *testing.T) { 164 defer deleteAllContainers() 165 volName := "voltst" 166 volPath := "/tmp" 167 168 if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", volName, "-v", volPath, "busybox")); err != nil { 169 t.Fatal(out, err) 170 } 171 172 name := "testing" 173 config := map[string]interface{}{ 174 "Image": "busybox", 175 "Volumes": map[string]struct{}{volPath: {}}, 176 } 177 178 if _, err := sockRequest("POST", "/containers/create?name="+name, config); err != nil && !strings.Contains(err.Error(), "201 Created") { 179 t.Fatal(err) 180 } 181 182 config = map[string]interface{}{ 183 "VolumesFrom": []string{volName}, 184 } 185 if _, err := sockRequest("POST", "/containers/"+name+"/start", config); err != nil && !strings.Contains(err.Error(), "204 No Content") { 186 t.Fatal(err) 187 } 188 189 pth, err := inspectFieldMap(name, "Volumes", volPath) 190 if err != nil { 191 t.Fatal(err) 192 } 193 pth2, err := inspectFieldMap(volName, "Volumes", volPath) 194 if err != nil { 195 t.Fatal(err) 196 } 197 198 if pth != pth2 { 199 t.Fatalf("expected volume host path to be %s, got %s", pth, pth2) 200 } 201 202 logDone("container REST API - check VolumesFrom on start") 203 } 204 205 // Ensure that volumes-from has priority over binds/anything else 206 // This is pretty much the same as TestRunApplyVolumesFromBeforeVolumes, except with passing the VolumesFrom and the bind on start 207 func TestVolumesFromHasPriority(t *testing.T) { 208 defer deleteAllContainers() 209 volName := "voltst" 210 volPath := "/tmp" 211 212 if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", volName, "-v", volPath, "busybox")); err != nil { 213 t.Fatal(out, err) 214 } 215 216 name := "testing" 217 config := map[string]interface{}{ 218 "Image": "busybox", 219 "Volumes": map[string]struct{}{volPath: {}}, 220 } 221 222 if _, err := sockRequest("POST", "/containers/create?name="+name, config); err != nil && !strings.Contains(err.Error(), "201 Created") { 223 t.Fatal(err) 224 } 225 226 bindPath, err := ioutil.TempDir(os.TempDir(), "test") 227 if err != nil { 228 t.Fatal(err) 229 } 230 231 config = map[string]interface{}{ 232 "VolumesFrom": []string{volName}, 233 "Binds": []string{bindPath + ":/tmp"}, 234 } 235 if _, err := sockRequest("POST", "/containers/"+name+"/start", config); err != nil && !strings.Contains(err.Error(), "204 No Content") { 236 t.Fatal(err) 237 } 238 239 pth, err := inspectFieldMap(name, "Volumes", volPath) 240 if err != nil { 241 t.Fatal(err) 242 } 243 pth2, err := inspectFieldMap(volName, "Volumes", volPath) 244 if err != nil { 245 t.Fatal(err) 246 } 247 248 if pth != pth2 { 249 t.Fatalf("expected volume host path to be %s, got %s", pth, pth2) 250 } 251 252 logDone("container REST API - check VolumesFrom has priority") 253 }