| ... | ... |
@@ -153,7 +153,7 @@ func (cli *DockerCli) CmdPs(args ...string) error {
|
| 153 | 153 |
|
| 154 | 154 |
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", ID, image, command, |
| 155 | 155 |
units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(container.Created), 0))), |
| 156 |
- container.Status, api.NewDisplayablePorts(container.Ports), strings.Join(names, ",")) |
|
| 156 |
+ container.Status, api.DisplayablePorts(container.Ports), strings.Join(names, ",")) |
|
| 157 | 157 |
|
| 158 | 158 |
if *size {
|
| 159 | 159 |
if container.SizeRootFs > 0 {
|
| ... | ... |
@@ -10,7 +10,6 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
"github.com/Sirupsen/logrus" |
| 12 | 12 |
"github.com/docker/docker/api/types" |
| 13 |
- "github.com/docker/docker/engine" |
|
| 14 | 13 |
"github.com/docker/docker/pkg/parsers" |
| 15 | 14 |
"github.com/docker/docker/pkg/version" |
| 16 | 15 |
"github.com/docker/libtrust" |
| ... | ... |
@@ -32,65 +31,13 @@ func ValidateHost(val string) (string, error) {
|
| 32 | 32 |
return host, nil |
| 33 | 33 |
} |
| 34 | 34 |
|
| 35 |
-// TODO remove, used on < 1.5 in getContainersJSON |
|
| 36 |
-// TODO this can go away when we get rid of engine.table |
|
| 37 |
-func DisplayablePorts(ports *engine.Table) string {
|
|
| 38 |
- var ( |
|
| 39 |
- result = []string{}
|
|
| 40 |
- hostMappings = []string{}
|
|
| 41 |
- firstInGroupMap map[string]int |
|
| 42 |
- lastInGroupMap map[string]int |
|
| 43 |
- ) |
|
| 44 |
- firstInGroupMap = make(map[string]int) |
|
| 45 |
- lastInGroupMap = make(map[string]int) |
|
| 46 |
- ports.SetKey("PrivatePort")
|
|
| 47 |
- ports.Sort() |
|
| 48 |
- for _, port := range ports.Data {
|
|
| 49 |
- var ( |
|
| 50 |
- current = port.GetInt("PrivatePort")
|
|
| 51 |
- portKey = port.Get("Type")
|
|
| 52 |
- firstInGroup int |
|
| 53 |
- lastInGroup int |
|
| 54 |
- ) |
|
| 55 |
- if port.Get("IP") != "" {
|
|
| 56 |
- if port.GetInt("PublicPort") != current {
|
|
| 57 |
- hostMappings = append(hostMappings, fmt.Sprintf("%s:%d->%d/%s", port.Get("IP"), port.GetInt("PublicPort"), port.GetInt("PrivatePort"), port.Get("Type")))
|
|
| 58 |
- continue |
|
| 59 |
- } |
|
| 60 |
- portKey = fmt.Sprintf("%s/%s", port.Get("IP"), port.Get("Type"))
|
|
| 61 |
- } |
|
| 62 |
- firstInGroup = firstInGroupMap[portKey] |
|
| 63 |
- lastInGroup = lastInGroupMap[portKey] |
|
| 64 |
- |
|
| 65 |
- if firstInGroup == 0 {
|
|
| 66 |
- firstInGroupMap[portKey] = current |
|
| 67 |
- lastInGroupMap[portKey] = current |
|
| 68 |
- continue |
|
| 69 |
- } |
|
| 70 |
- |
|
| 71 |
- if current == (lastInGroup + 1) {
|
|
| 72 |
- lastInGroupMap[portKey] = current |
|
| 73 |
- continue |
|
| 74 |
- } |
|
| 75 |
- result = append(result, FormGroup(portKey, firstInGroup, lastInGroup)) |
|
| 76 |
- firstInGroupMap[portKey] = current |
|
| 77 |
- lastInGroupMap[portKey] = current |
|
| 78 |
- } |
|
| 79 |
- for portKey, firstInGroup := range firstInGroupMap {
|
|
| 80 |
- result = append(result, FormGroup(portKey, firstInGroup, lastInGroupMap[portKey])) |
|
| 81 |
- } |
|
| 82 |
- result = append(result, hostMappings...) |
|
| 83 |
- return strings.Join(result, ", ") |
|
| 84 |
-} |
|
| 85 |
- |
|
| 86 | 35 |
type ByPrivatePort []types.Port |
| 87 | 36 |
|
| 88 | 37 |
func (r ByPrivatePort) Len() int { return len(r) }
|
| 89 | 38 |
func (r ByPrivatePort) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
| 90 | 39 |
func (r ByPrivatePort) Less(i, j int) bool { return r[i].PrivatePort < r[j].PrivatePort }
|
| 91 | 40 |
|
| 92 |
-// TODO Rename to DisplayablePorts (remove "New") when engine.Table goes away |
|
| 93 |
-func NewDisplayablePorts(ports []types.Port) string {
|
|
| 41 |
+func DisplayablePorts(ports []types.Port) string {
|
|
| 94 | 42 |
var ( |
| 95 | 43 |
result = []string{}
|
| 96 | 44 |
hostMappings = []string{}
|
| ... | ... |
@@ -482,42 +482,32 @@ func getContainersTop(eng *engine.Engine, version version.Version, w http.Respon |
| 482 | 482 |
} |
| 483 | 483 |
|
| 484 | 484 |
func getContainersJSON(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
| 485 |
- if err := parseForm(r); err != nil {
|
|
| 485 |
+ var err error |
|
| 486 |
+ if err = parseForm(r); err != nil {
|
|
| 486 | 487 |
return err |
| 487 | 488 |
} |
| 488 |
- var ( |
|
| 489 |
- err error |
|
| 490 |
- outs *engine.Table |
|
| 491 |
- job = eng.Job("containers")
|
|
| 492 |
- ) |
|
| 493 |
- |
|
| 494 |
- job.Setenv("all", r.Form.Get("all"))
|
|
| 495 |
- job.Setenv("size", r.Form.Get("size"))
|
|
| 496 |
- job.Setenv("since", r.Form.Get("since"))
|
|
| 497 |
- job.Setenv("before", r.Form.Get("before"))
|
|
| 498 |
- job.Setenv("limit", r.Form.Get("limit"))
|
|
| 499 |
- job.Setenv("filters", r.Form.Get("filters"))
|
|
| 500 | 489 |
|
| 501 |
- if version.GreaterThanOrEqualTo("1.5") {
|
|
| 502 |
- streamJSON(job, w, false) |
|
| 503 |
- } else if outs, err = job.Stdout.AddTable(); err != nil {
|
|
| 504 |
- return err |
|
| 505 |
- } |
|
| 506 |
- if err = job.Run(); err != nil {
|
|
| 507 |
- return err |
|
| 490 |
+ config := &daemon.ContainersConfig{
|
|
| 491 |
+ All: r.Form.Get("all") == "1",
|
|
| 492 |
+ Size: r.Form.Get("size") == "1",
|
|
| 493 |
+ Since: r.Form.Get("since"),
|
|
| 494 |
+ Before: r.Form.Get("before"),
|
|
| 495 |
+ Filters: r.Form.Get("filters"),
|
|
| 508 | 496 |
} |
| 509 |
- if version.LessThan("1.5") { // Convert to legacy format
|
|
| 510 |
- for _, out := range outs.Data {
|
|
| 511 |
- ports := engine.NewTable("", 0)
|
|
| 512 |
- ports.ReadListFrom([]byte(out.Get("Ports")))
|
|
| 513 |
- out.Set("Ports", api.DisplayablePorts(ports))
|
|
| 514 |
- } |
|
| 515 |
- w.Header().Set("Content-Type", "application/json")
|
|
| 516 |
- if _, err = outs.WriteListTo(w); err != nil {
|
|
| 497 |
+ |
|
| 498 |
+ if tmpLimit := r.Form.Get("limit"); tmpLimit != "" {
|
|
| 499 |
+ config.Limit, err = strconv.Atoi(tmpLimit) |
|
| 500 |
+ if err != nil {
|
|
| 517 | 501 |
return err |
| 518 | 502 |
} |
| 519 | 503 |
} |
| 520 |
- return nil |
|
| 504 |
+ |
|
| 505 |
+ containers, err := getDaemon(eng).Containers(config) |
|
| 506 |
+ if err != nil {
|
|
| 507 |
+ return err |
|
| 508 |
+ } |
|
| 509 |
+ |
|
| 510 |
+ return writeJSON(w, http.StatusOK, containers) |
|
| 521 | 511 |
} |
| 522 | 512 |
|
| 523 | 513 |
func getContainersStats(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
| ... | ... |
@@ -122,7 +122,6 @@ func (daemon *Daemon) Install(eng *engine.Engine) error {
|
| 122 | 122 |
"container_rename": daemon.ContainerRename, |
| 123 | 123 |
"container_inspect": daemon.ContainerInspect, |
| 124 | 124 |
"container_stats": daemon.ContainerStats, |
| 125 |
- "containers": daemon.Containers, |
|
| 126 | 125 |
"create": daemon.ContainerCreate, |
| 127 | 126 |
"rm": daemon.ContainerRm, |
| 128 | 127 |
"export": daemon.ContainerExport, |
| ... | ... |
@@ -1,15 +1,12 @@ |
| 1 | 1 |
package daemon |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "encoding/json" |
|
| 5 | 4 |
"errors" |
| 6 | 5 |
"fmt" |
| 7 |
- "sort" |
|
| 8 | 6 |
"strconv" |
| 9 | 7 |
"strings" |
| 10 | 8 |
|
| 11 | 9 |
"github.com/docker/docker/api/types" |
| 12 |
- "github.com/docker/docker/engine" |
|
| 13 | 10 |
"github.com/docker/docker/graph" |
| 14 | 11 |
"github.com/docker/docker/nat" |
| 15 | 12 |
"github.com/docker/docker/pkg/graphdb" |
| ... | ... |
@@ -23,35 +20,35 @@ func (daemon *Daemon) List() []*Container {
|
| 23 | 23 |
return daemon.containers.List() |
| 24 | 24 |
} |
| 25 | 25 |
|
| 26 |
-type ByCreated []types.Container |
|
| 27 |
- |
|
| 28 |
-func (r ByCreated) Len() int { return len(r) }
|
|
| 29 |
-func (r ByCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
|
| 30 |
-func (r ByCreated) Less(i, j int) bool { return r[i].Created < r[j].Created }
|
|
| 26 |
+type ContainersConfig struct {
|
|
| 27 |
+ All bool |
|
| 28 |
+ Since string |
|
| 29 |
+ Before string |
|
| 30 |
+ Limit int |
|
| 31 |
+ Size bool |
|
| 32 |
+ Filters string |
|
| 33 |
+} |
|
| 31 | 34 |
|
| 32 |
-func (daemon *Daemon) Containers(job *engine.Job) error {
|
|
| 35 |
+func (daemon *Daemon) Containers(config *ContainersConfig) ([]*types.Container, error) {
|
|
| 33 | 36 |
var ( |
| 34 | 37 |
foundBefore bool |
| 35 | 38 |
displayed int |
| 36 |
- all = job.GetenvBool("all")
|
|
| 37 |
- since = job.Getenv("since")
|
|
| 38 |
- before = job.Getenv("before")
|
|
| 39 |
- n = job.GetenvInt("limit")
|
|
| 40 |
- size = job.GetenvBool("size")
|
|
| 39 |
+ all = config.All |
|
| 40 |
+ n = config.Limit |
|
| 41 | 41 |
psFilters filters.Args |
| 42 | 42 |
filtExited []int |
| 43 | 43 |
) |
| 44 |
- containers := []types.Container{}
|
|
| 44 |
+ containers := []*types.Container{}
|
|
| 45 | 45 |
|
| 46 |
- psFilters, err := filters.FromParam(job.Getenv("filters"))
|
|
| 46 |
+ psFilters, err := filters.FromParam(config.Filters) |
|
| 47 | 47 |
if err != nil {
|
| 48 |
- return err |
|
| 48 |
+ return nil, err |
|
| 49 | 49 |
} |
| 50 | 50 |
if i, ok := psFilters["exited"]; ok {
|
| 51 | 51 |
for _, value := range i {
|
| 52 | 52 |
code, err := strconv.Atoi(value) |
| 53 | 53 |
if err != nil {
|
| 54 |
- return err |
|
| 54 |
+ return nil, err |
|
| 55 | 55 |
} |
| 56 | 56 |
filtExited = append(filtExited, code) |
| 57 | 57 |
} |
| ... | ... |
@@ -71,17 +68,17 @@ func (daemon *Daemon) Containers(job *engine.Job) error {
|
| 71 | 71 |
}, 1) |
| 72 | 72 |
|
| 73 | 73 |
var beforeCont, sinceCont *Container |
| 74 |
- if before != "" {
|
|
| 75 |
- beforeCont, err = daemon.Get(before) |
|
| 74 |
+ if config.Before != "" {
|
|
| 75 |
+ beforeCont, err = daemon.Get(config.Before) |
|
| 76 | 76 |
if err != nil {
|
| 77 |
- return err |
|
| 77 |
+ return nil, err |
|
| 78 | 78 |
} |
| 79 | 79 |
} |
| 80 | 80 |
|
| 81 |
- if since != "" {
|
|
| 82 |
- sinceCont, err = daemon.Get(since) |
|
| 81 |
+ if config.Since != "" {
|
|
| 82 |
+ sinceCont, err = daemon.Get(config.Since) |
|
| 83 | 83 |
if err != nil {
|
| 84 |
- return err |
|
| 84 |
+ return nil, err |
|
| 85 | 85 |
} |
| 86 | 86 |
} |
| 87 | 87 |
|
| ... | ... |
@@ -89,7 +86,7 @@ func (daemon *Daemon) Containers(job *engine.Job) error {
|
| 89 | 89 |
writeCont := func(container *Container) error {
|
| 90 | 90 |
container.Lock() |
| 91 | 91 |
defer container.Unlock() |
| 92 |
- if !container.Running && !all && n <= 0 && since == "" && before == "" {
|
|
| 92 |
+ if !container.Running && !all && n <= 0 && config.Since == "" && config.Before == "" {
|
|
| 93 | 93 |
return nil |
| 94 | 94 |
} |
| 95 | 95 |
if !psFilters.Match("name", container.Name) {
|
| ... | ... |
@@ -104,7 +101,7 @@ func (daemon *Daemon) Containers(job *engine.Job) error {
|
| 104 | 104 |
return nil |
| 105 | 105 |
} |
| 106 | 106 |
|
| 107 |
- if before != "" && !foundBefore {
|
|
| 107 |
+ if config.Before != "" && !foundBefore {
|
|
| 108 | 108 |
if container.ID == beforeCont.ID {
|
| 109 | 109 |
foundBefore = true |
| 110 | 110 |
} |
| ... | ... |
@@ -113,7 +110,7 @@ func (daemon *Daemon) Containers(job *engine.Job) error {
|
| 113 | 113 |
if n > 0 && displayed == n {
|
| 114 | 114 |
return errLast |
| 115 | 115 |
} |
| 116 |
- if since != "" {
|
|
| 116 |
+ if config.Since != "" {
|
|
| 117 | 117 |
if container.ID == sinceCont.ID {
|
| 118 | 118 |
return errLast |
| 119 | 119 |
} |
| ... | ... |
@@ -135,7 +132,7 @@ func (daemon *Daemon) Containers(job *engine.Job) error {
|
| 135 | 135 |
return nil |
| 136 | 136 |
} |
| 137 | 137 |
displayed++ |
| 138 |
- newC := types.Container{
|
|
| 138 |
+ newC := &types.Container{
|
|
| 139 | 139 |
ID: container.ID, |
| 140 | 140 |
Names: names[container.ID], |
| 141 | 141 |
} |
| ... | ... |
@@ -184,7 +181,7 @@ func (daemon *Daemon) Containers(job *engine.Job) error {
|
| 184 | 184 |
} |
| 185 | 185 |
} |
| 186 | 186 |
|
| 187 |
- if size {
|
|
| 187 |
+ if config.Size {
|
|
| 188 | 188 |
sizeRw, sizeRootFs := container.GetSize() |
| 189 | 189 |
newC.SizeRw = int(sizeRw) |
| 190 | 190 |
newC.SizeRootFs = int(sizeRootFs) |
| ... | ... |
@@ -197,14 +194,10 @@ func (daemon *Daemon) Containers(job *engine.Job) error {
|
| 197 | 197 |
for _, container := range daemon.List() {
|
| 198 | 198 |
if err := writeCont(container); err != nil {
|
| 199 | 199 |
if err != errLast {
|
| 200 |
- return err |
|
| 200 |
+ return nil, err |
|
| 201 | 201 |
} |
| 202 | 202 |
break |
| 203 | 203 |
} |
| 204 | 204 |
} |
| 205 |
- sort.Sort(sort.Reverse(ByCreated(containers))) |
|
| 206 |
- if err = json.NewEncoder(job.Stdout).Encode(containers); err != nil {
|
|
| 207 |
- return err |
|
| 208 |
- } |
|
| 209 |
- return nil |
|
| 205 |
+ return containers, nil |
|
| 210 | 206 |
} |
| ... | ... |
@@ -6,6 +6,7 @@ import ( |
| 6 | 6 |
"time" |
| 7 | 7 |
|
| 8 | 8 |
"github.com/docker/docker/builder" |
| 9 |
+ "github.com/docker/docker/daemon" |
|
| 9 | 10 |
"github.com/docker/docker/engine" |
| 10 | 11 |
) |
| 11 | 12 |
|
| ... | ... |
@@ -114,21 +115,17 @@ func TestRestartKillWait(t *testing.T) {
|
| 114 | 114 |
|
| 115 | 115 |
id := createTestContainer(eng, config, t) |
| 116 | 116 |
|
| 117 |
- job := eng.Job("containers")
|
|
| 118 |
- job.SetenvBool("all", true)
|
|
| 119 |
- outs, err := job.Stdout.AddListTable() |
|
| 117 |
+ containers, err := runtime.Containers(&daemon.ContainersConfig{All: true})
|
|
| 118 |
+ |
|
| 120 | 119 |
if err != nil {
|
| 121 |
- t.Fatal(err) |
|
| 122 |
- } |
|
| 123 |
- if err := job.Run(); err != nil {
|
|
| 124 |
- t.Fatal(err) |
|
| 120 |
+ t.Errorf("Error getting containers1: %q", err)
|
|
| 125 | 121 |
} |
| 126 | 122 |
|
| 127 |
- if len(outs.Data) != 1 {
|
|
| 128 |
- t.Errorf("Expected 1 container, %v found", len(outs.Data))
|
|
| 123 |
+ if len(containers) != 1 {
|
|
| 124 |
+ t.Errorf("Expected 1 container, %v found", len(containers))
|
|
| 129 | 125 |
} |
| 130 | 126 |
|
| 131 |
- job = eng.Job("start", id)
|
|
| 127 |
+ job := eng.Job("start", id)
|
|
| 132 | 128 |
if err := job.ImportEnv(hostConfig); err != nil {
|
| 133 | 129 |
t.Fatal(err) |
| 134 | 130 |
} |
| ... | ... |
@@ -141,23 +138,19 @@ func TestRestartKillWait(t *testing.T) {
|
| 141 | 141 |
} |
| 142 | 142 |
|
| 143 | 143 |
eng = newTestEngine(t, false, runtime.Config().Root) |
| 144 |
+ runtime = mkDaemonFromEngine(eng, t) |
|
| 145 |
+ |
|
| 146 |
+ containers, err = runtime.Containers(&daemon.ContainersConfig{All: true})
|
|
| 144 | 147 |
|
| 145 |
- job = eng.Job("containers")
|
|
| 146 |
- job.SetenvBool("all", true)
|
|
| 147 |
- outs, err = job.Stdout.AddListTable() |
|
| 148 | 148 |
if err != nil {
|
| 149 |
- t.Fatal(err) |
|
| 149 |
+ t.Errorf("Error getting containers1: %q", err)
|
|
| 150 | 150 |
} |
| 151 |
- if err := job.Run(); err != nil {
|
|
| 152 |
- t.Fatal(err) |
|
| 153 |
- } |
|
| 154 |
- |
|
| 155 |
- if len(outs.Data) != 1 {
|
|
| 156 |
- t.Errorf("Expected 1 container, %v found", len(outs.Data))
|
|
| 151 |
+ if len(containers) != 1 {
|
|
| 152 |
+ t.Errorf("Expected 1 container, %v found", len(containers))
|
|
| 157 | 153 |
} |
| 158 | 154 |
|
| 159 | 155 |
setTimeout(t, "Waiting on stopped container timedout", 5*time.Second, func() {
|
| 160 |
- job = eng.Job("wait", outs.Data[0].Get("Id"))
|
|
| 156 |
+ job = eng.Job("wait", containers[0].ID)
|
|
| 161 | 157 |
if err := job.Run(); err != nil {
|
| 162 | 158 |
t.Fatal(err) |
| 163 | 159 |
} |
| ... | ... |
@@ -166,7 +159,8 @@ func TestRestartKillWait(t *testing.T) {
|
| 166 | 166 |
|
| 167 | 167 |
func TestCreateStartRestartStopStartKillRm(t *testing.T) {
|
| 168 | 168 |
eng := NewTestEngine(t) |
| 169 |
- defer mkDaemonFromEngine(eng, t).Nuke() |
|
| 169 |
+ runtime := mkDaemonFromEngine(eng, t) |
|
| 170 |
+ defer runtime.Nuke() |
|
| 170 | 171 |
|
| 171 | 172 |
config, hostConfig, _, err := parseRun([]string{"-i", unitTestImageID, "/bin/cat"})
|
| 172 | 173 |
if err != nil {
|
| ... | ... |
@@ -174,22 +168,13 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) {
|
| 174 | 174 |
} |
| 175 | 175 |
|
| 176 | 176 |
id := createTestContainer(eng, config, t) |
| 177 |
+ containers, err := runtime.Containers(&daemon.ContainersConfig{All: true})
|
|
| 177 | 178 |
|
| 178 |
- job := eng.Job("containers")
|
|
| 179 |
- job.SetenvBool("all", true)
|
|
| 180 |
- outs, err := job.Stdout.AddListTable() |
|
| 181 |
- if err != nil {
|
|
| 182 |
- t.Fatal(err) |
|
| 183 |
- } |
|
| 184 |
- if err := job.Run(); err != nil {
|
|
| 185 |
- t.Fatal(err) |
|
| 186 |
- } |
|
| 187 |
- |
|
| 188 |
- if len(outs.Data) != 1 {
|
|
| 189 |
- t.Errorf("Expected 1 container, %v found", len(outs.Data))
|
|
| 179 |
+ if len(containers) != 1 {
|
|
| 180 |
+ t.Errorf("Expected 1 container, %v found", len(containers))
|
|
| 190 | 181 |
} |
| 191 | 182 |
|
| 192 |
- job = eng.Job("start", id)
|
|
| 183 |
+ job := eng.Job("start", id)
|
|
| 193 | 184 |
if err := job.ImportEnv(hostConfig); err != nil {
|
| 194 | 185 |
t.Fatal(err) |
| 195 | 186 |
} |
| ... | ... |
@@ -228,18 +213,10 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) {
|
| 228 | 228 |
t.Fatal(err) |
| 229 | 229 |
} |
| 230 | 230 |
|
| 231 |
- job = eng.Job("containers")
|
|
| 232 |
- job.SetenvBool("all", true)
|
|
| 233 |
- outs, err = job.Stdout.AddListTable() |
|
| 234 |
- if err != nil {
|
|
| 235 |
- t.Fatal(err) |
|
| 236 |
- } |
|
| 237 |
- if err := job.Run(); err != nil {
|
|
| 238 |
- t.Fatal(err) |
|
| 239 |
- } |
|
| 231 |
+ containers, err = runtime.Containers(&daemon.ContainersConfig{All: true})
|
|
| 240 | 232 |
|
| 241 |
- if len(outs.Data) != 0 {
|
|
| 242 |
- t.Errorf("Expected 0 container, %v found", len(outs.Data))
|
|
| 233 |
+ if len(containers) != 0 {
|
|
| 234 |
+ t.Errorf("Expected 0 container, %v found", len(containers))
|
|
| 243 | 235 |
} |
| 244 | 236 |
} |
| 245 | 237 |
|