dotcloud/docker

View on GitHub
container/exec.go

Summary

Maintainability
A
0 mins
Test Coverage
package container // import "github.com/docker/docker/container"

import (
    "context"
    "runtime"
    "sync"

    "github.com/containerd/containerd/cio"
    "github.com/containerd/log"
    "github.com/docker/docker/container/stream"
    "github.com/docker/docker/libcontainerd/types"
    "github.com/docker/docker/pkg/stringid"
)

// ExecConfig holds the configurations for execs. The Daemon keeps
// track of both running and finished execs so that they can be
// examined both during and after completion.
type ExecConfig struct {
    sync.Mutex
    Started      chan struct{}
    StreamConfig *stream.Config
    ID           string
    Running      bool
    ExitCode     *int
    OpenStdin    bool
    OpenStderr   bool
    OpenStdout   bool
    CanRemove    bool
    Container    *Container
    DetachKeys   []byte
    Entrypoint   string
    Args         []string
    Tty          bool
    Privileged   bool
    User         string
    WorkingDir   string
    Env          []string
    Process      types.Process
    ConsoleSize  *[2]uint
}

// NewExecConfig initializes the a new exec configuration
func NewExecConfig(c *Container) *ExecConfig {
    return &ExecConfig{
        ID:           stringid.GenerateRandomID(),
        Container:    c,
        StreamConfig: stream.NewConfig(),
        Started:      make(chan struct{}),
    }
}

// InitializeStdio is called by libcontainerd to connect the stdio.
func (c *ExecConfig) InitializeStdio(iop *cio.DirectIO) (cio.IO, error) {
    c.StreamConfig.CopyToPipe(iop)

    if c.StreamConfig.Stdin() == nil && !c.Tty && runtime.GOOS == "windows" {
        if iop.Stdin != nil {
            if err := iop.Stdin.Close(); err != nil {
                log.G(context.TODO()).Errorf("error closing exec stdin: %+v", err)
            }
        }
    }

    return &rio{IO: iop, sc: c.StreamConfig}, nil
}

// CloseStreams closes the stdio streams for the exec
func (c *ExecConfig) CloseStreams() error {
    return c.StreamConfig.CloseStreams()
}

// SetExitCode sets the exec config's exit code
func (c *ExecConfig) SetExitCode(code int) {
    c.ExitCode = &code
}

// ExecStore keeps track of the exec configurations.
type ExecStore struct {
    byID map[string]*ExecConfig
    mu   sync.RWMutex
}

// NewExecStore initializes a new exec store.
func NewExecStore() *ExecStore {
    return &ExecStore{
        byID: make(map[string]*ExecConfig),
    }
}

// Commands returns the exec configurations in the store.
func (e *ExecStore) Commands() map[string]*ExecConfig {
    e.mu.RLock()
    byID := make(map[string]*ExecConfig, len(e.byID))
    for id, config := range e.byID {
        byID[id] = config
    }
    e.mu.RUnlock()
    return byID
}

// Add adds a new exec configuration to the store.
func (e *ExecStore) Add(id string, Config *ExecConfig) {
    e.mu.Lock()
    e.byID[id] = Config
    e.mu.Unlock()
}

// Get returns an exec configuration by its id.
func (e *ExecStore) Get(id string) *ExecConfig {
    e.mu.RLock()
    res := e.byID[id]
    e.mu.RUnlock()
    return res
}

// Delete removes an exec configuration from the store.
func (e *ExecStore) Delete(id string) {
    e.mu.Lock()
    delete(e.byID, id)
    e.mu.Unlock()
}

// List returns the list of exec ids in the store.
func (e *ExecStore) List() []string {
    var IDs []string
    e.mu.RLock()
    for id := range e.byID {
        IDs = append(IDs, id)
    }
    e.mu.RUnlock()
    return IDs
}