Skip to content

Commit

Permalink
Merge pull request moby#9705 from acbodine/9311-truncindex-error-dupl…
Browse files Browse the repository at this point in the history
…icate-id-on-ambiguous-id

Closes moby#9311 Handles container id/name collisions against daemon functionalities according to moby#8069
  • Loading branch information
crosbymichael committed Feb 6, 2015
2 parents a982432 + d25a653 commit 34c804a
Show file tree
Hide file tree
Showing 32 changed files with 464 additions and 296 deletions.
6 changes: 6 additions & 0 deletions api/client/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,12 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
for _, name := range cmd.Args() {
obj, _, err := readBody(cli.call("GET", "/containers/"+name+"/json", nil, false))
if err != nil {
if strings.Contains(err.Error(), "Too many") {
fmt.Fprintf(cli.err, "Error: %s", err.Error())
status = 1
continue
}

obj, _, err = readBody(cli.call("GET", "/images/"+name+"/json", nil, false))
if err != nil {
if strings.Contains(err.Error(), "No such") {
Expand Down
2 changes: 1 addition & 1 deletion api/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -1114,7 +1114,7 @@ func postContainersCopy(eng *engine.Engine, version version.Version, w http.Resp
w.Header().Set("Content-Type", "application/x-tar")
if err := job.Run(); err != nil {
log.Errorf("%s", err.Error())
if strings.Contains(strings.ToLower(err.Error()), "no such container") {
if strings.Contains(strings.ToLower(err.Error()), "no such id") {
w.WriteHeader(http.StatusNotFound)
} else if strings.Contains(err.Error(), "no such file or directory") {
return fmt.Errorf("Could not find the file %s in container %s", origResource, vars["name"])
Expand Down
12 changes: 8 additions & 4 deletions builder/internals.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ func (b *Builder) commit(id string, autoCmd []string, comment string) error {
}
defer container.Unmount()
}
container := b.Daemon.Get(id)
if container == nil {
return fmt.Errorf("An error occured while creating the container")
container, err := b.Daemon.Get(id)
if err != nil {
return err
}

// Note: Actually copy the struct
Expand Down Expand Up @@ -710,7 +710,11 @@ func fixPermissions(source, destination string, uid, gid int, destExisted bool)

func (b *Builder) clearTmp() {
for c := range b.TmpContainers {
tmp := b.Daemon.Get(c)
tmp, err := b.Daemon.Get(c)
if err != nil {
fmt.Fprint(b.OutStream, err.Error())
}

if err := b.Daemon.Destroy(tmp); err != nil {
fmt.Fprintf(b.OutStream, "Error removing intermediate container %s: %s\n", utils.TruncateID(c), err.Error())
return
Expand Down
6 changes: 3 additions & 3 deletions daemon/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ func (daemon *Daemon) ContainerAttach(job *engine.Job) engine.Status {
stderr = job.GetenvBool("stderr")
)

container := daemon.Get(name)
if container == nil {
return job.Errorf("No such container: %s", name)
container, err := daemon.Get(name)
if err != nil {
return job.Error(err)
}

//logs
Expand Down
37 changes: 21 additions & 16 deletions daemon/changes.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,29 @@ func (daemon *Daemon) ContainerChanges(job *engine.Job) engine.Status {
return job.Errorf("Usage: %s CONTAINER", job.Name)
}
name := job.Args[0]
if container := daemon.Get(name); container != nil {
outs := engine.NewTable("", 0)
changes, err := container.Changes()
if err != nil {
return job.Error(err)
}
for _, change := range changes {
out := &engine.Env{}
if err := out.Import(change); err != nil {
return job.Error(err)
}
outs.Add(out)
}
if _, err := outs.WriteListTo(job.Stdout); err != nil {

container, error := daemon.Get(name)
if error != nil {
return job.Error(error)
}

outs := engine.NewTable("", 0)
changes, err := container.Changes()
if err != nil {
return job.Error(err)
}

for _, change := range changes {
out := &engine.Env{}
if err := out.Import(change); err != nil {
return job.Error(err)
}
} else {
return job.Errorf("No such container: %s", name)
outs.Add(out)
}

if _, err := outs.WriteListTo(job.Stdout); err != nil {
return job.Error(err)
}

return engine.StatusOK
}
6 changes: 3 additions & 3 deletions daemon/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ func (daemon *Daemon) ContainerCommit(job *engine.Job) engine.Status {
}
name := job.Args[0]

container := daemon.Get(name)
if container == nil {
return job.Errorf("No such container: %s", name)
container, err := daemon.Get(name)
if err != nil {
return job.Error(err)
}

var (
Expand Down
19 changes: 12 additions & 7 deletions daemon/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,12 @@ func (container *Container) updateParentsHosts() error {
if ref.ParentID == "0" {
continue
}
c := container.daemon.Get(ref.ParentID)

c, err := container.daemon.Get(ref.ParentID)
if err != nil {
log.Error(err)
}

if c != nil && !container.daemon.config.DisableNetwork && container.hostConfig.NetworkMode.IsPrivate() {
log.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, container.NetworkSettings.IPAddress)
if err := etchosts.Update(c.HostsPath, container.NetworkSettings.IPAddress, ref.Name); err != nil {
Expand Down Expand Up @@ -1395,9 +1400,9 @@ func (container *Container) GetMountLabel() string {

func (container *Container) getIpcContainer() (*Container, error) {
containerID := container.hostConfig.IpcMode.Container()
c := container.daemon.Get(containerID)
if c == nil {
return nil, fmt.Errorf("no such container to join IPC: %s", containerID)
c, err := container.daemon.Get(containerID)
if err != nil {
return nil, err
}
if !c.IsRunning() {
return nil, fmt.Errorf("cannot join IPC of a non running container: %s", containerID)
Expand All @@ -1412,9 +1417,9 @@ func (container *Container) getNetworkedContainer() (*Container, error) {
if len(parts) != 2 {
return nil, fmt.Errorf("no container specified to join network")
}
nc := container.daemon.Get(parts[1])
if nc == nil {
return nil, fmt.Errorf("no such container to join network: %s", parts[1])
nc, err := container.daemon.Get(parts[1])
if err != nil {
return nil, err
}
if !nc.IsRunning() {
return nil, fmt.Errorf("cannot join network of a non running container: %s", parts[1])
Expand Down
23 changes: 12 additions & 11 deletions daemon/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,19 @@ func (daemon *Daemon) ContainerCopy(job *engine.Job) engine.Status {
resource = job.Args[1]
)

if container := daemon.Get(name); container != nil {
container, err := daemon.Get(name)
if err != nil {
return job.Error(err)
}

data, err := container.Copy(resource)
if err != nil {
return job.Error(err)
}
defer data.Close()
data, err := container.Copy(resource)
if err != nil {
return job.Error(err)
}
defer data.Close()

if _, err := io.Copy(job.Stdout, data); err != nil {
return job.Error(err)
}
return engine.StatusOK
if _, err := io.Copy(job.Stdout, data); err != nil {
return job.Error(err)
}
return job.Errorf("No such container: %s", name)
return engine.StatusOK
}
6 changes: 3 additions & 3 deletions daemon/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ func (daemon *Daemon) GenerateSecurityOpt(ipcMode runconfig.IpcMode, pidMode run
return label.DisableSecOpt(), nil
}
if ipcContainer := ipcMode.Container(); ipcContainer != "" {
c := daemon.Get(ipcContainer)
if c == nil {
return nil, fmt.Errorf("no such container to join IPC: %s", ipcContainer)
c, err := daemon.Get(ipcContainer)
if err != nil {
return nil, err
}
if !c.IsRunning() {
return nil, fmt.Errorf("cannot join IPC of a non running container: %s", ipcContainer)
Expand Down
58 changes: 36 additions & 22 deletions daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,28 +155,39 @@ func (daemon *Daemon) Install(eng *engine.Engine) error {
return nil
}

// Get looks for a container by the specified ID or name, and returns it.
// If the container is not found, or if an error occurs, nil is returned.
func (daemon *Daemon) Get(name string) *Container {
id, err := daemon.idIndex.Get(name)
if err == nil {
return daemon.containers.Get(id)
// Get looks for a container with the provided prefix
func (daemon *Daemon) Get(prefix string) (*Container, error) {
if containerByID := daemon.containers.Get(prefix); containerByID != nil {

// prefix is an exact match to a full container ID
return containerByID, nil
}

if c, _ := daemon.GetByName(name); c != nil {
return c
// Either GetByName finds an entity matching prefix exactly, or it doesn't.
// Check value of containerByName and ignore any errors
containerByName, _ := daemon.GetByName(prefix)
containerId, indexError := daemon.idIndex.Get(prefix)

if containerByName != nil {

// prefix is an exact match to a full container Name
return containerByName, nil
}

if err == truncindex.ErrDuplicateID {
log.Errorf("Short ID %s is ambiguous: please retry with more characters or use the full ID.\n", name)
if containerId != "" {

// prefix is a fuzzy match to a container ID
return daemon.containers.Get(containerId), nil
}
return nil

return nil, indexError
}

// Exists returns a true if a container of the specified ID or name exists,
// false otherwise.
func (daemon *Daemon) Exists(id string) bool {
return daemon.Get(id) != nil
c, _ := daemon.Get(id)
return c != nil
}

func (daemon *Daemon) containerRoot(id string) string {
Expand Down Expand Up @@ -715,9 +726,9 @@ func (daemon *Daemon) Children(name string) (map[string]*Container, error) {
children := make(map[string]*Container)

err = daemon.containerGraph.Walk(name, func(p string, e *graphdb.Entity) error {
c := daemon.Get(e.ID())
if c == nil {
return fmt.Errorf("Could not get container for name %s and id %s", e.ID(), p)
c, err := daemon.Get(e.ID())
if err != nil {
return err
}
children[p] = c
return nil
Expand Down Expand Up @@ -754,7 +765,10 @@ func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig.
if err != nil {
return err
}
child := daemon.Get(parts["name"])
child, err := daemon.Get(parts["name"])
if err != nil {
return err
}
if child == nil {
return fmt.Errorf("Could not get container for %s", parts["name"])
}
Expand Down Expand Up @@ -1100,18 +1114,18 @@ func (daemon *Daemon) Stats(c *Container) (*execdriver.ResourceStats, error) {
}

func (daemon *Daemon) SubscribeToContainerStats(name string) (chan interface{}, error) {
c := daemon.Get(name)
if c == nil {
return nil, fmt.Errorf("no such container")
c, err := daemon.Get(name)
if err != nil {
return nil, err
}
ch := daemon.statsCollector.collect(c)
return ch, nil
}

func (daemon *Daemon) UnsubscribeToContainerStats(name string, ch chan interface{}) error {
c := daemon.Get(name)
if c == nil {
return fmt.Errorf("no such container")
c, err := daemon.Get(name)
if err != nil {
return err
}
daemon.statsCollector.unsubscribe(c, ch)
return nil
Expand Down
Loading

0 comments on commit 34c804a

Please sign in to comment.