Remove job from container_inspect

Signed-off-by: Antonio Murdaca <me@runcom.ninja>
This commit is contained in:
Antonio Murdaca 2015-04-13 16:17:14 +02:00
parent 3c9ae03a86
commit 4b9fe9c298
13 changed files with 186 additions and 163 deletions

View file

@ -1,12 +1,13 @@
package client
import (
"encoding/json"
"fmt"
"io"
"net/url"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/engine"
"github.com/docker/docker/api/types"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/signal"
)
@ -30,25 +31,20 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
return err
}
env := engine.Env{}
if err := env.Decode(stream); err != nil {
var c types.ContainerJSON
if err := json.NewDecoder(stream).Decode(&c); err != nil {
return err
}
if !env.GetSubEnv("State").GetBool("Running") {
if !c.State.Running {
return fmt.Errorf("You cannot attach to a stopped container, start it first")
}
var (
config = env.GetSubEnv("Config")
tty = config.GetBool("Tty")
)
if err := cli.CheckTtyInput(!*noStdin, tty); err != nil {
if err := cli.CheckTtyInput(!*noStdin, c.Config.Tty); err != nil {
return err
}
if tty && cli.isTerminalOut {
if c.Config.Tty && cli.isTerminalOut {
if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
logrus.Debugf("Error monitoring TTY size: %s", err)
}
@ -58,7 +54,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
v := url.Values{}
v.Set("stream", "1")
if !*noStdin && config.GetBool("OpenStdin") {
if !*noStdin && c.Config.OpenStdin {
v.Set("stdin", "1")
in = cli.in
}
@ -66,12 +62,12 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
v.Set("stdout", "1")
v.Set("stderr", "1")
if *proxy && !tty {
if *proxy && !c.Config.Tty {
sigc := cli.forwardAllSignals(cmd.Arg(0))
defer signal.StopCatch(sigc)
}
if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), tty, in, cli.out, cli.err, nil, nil); err != nil {
if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), c.Config.Tty, in, cli.out, cli.err, nil, nil); err != nil {
return err
}

View file

@ -1,10 +1,11 @@
package client
import (
"encoding/json"
"fmt"
"net/url"
"github.com/docker/docker/engine"
"github.com/docker/docker/api/types"
flag "github.com/docker/docker/pkg/mflag"
)
@ -29,12 +30,12 @@ func (cli *DockerCli) CmdLogs(args ...string) error {
return err
}
env := engine.Env{}
if err := env.Decode(stream); err != nil {
var c types.ContainerJSON
if err := json.NewDecoder(stream).Decode(&c); err != nil {
return err
}
if env.GetSubEnv("HostConfig").GetSubEnv("LogConfig").Get("Type") != "json-file" {
if c.HostConfig.LogConfig.Type != "json-file" {
return fmt.Errorf("\"logs\" command is supported only for \"json-file\" logging driver")
}
@ -51,5 +52,5 @@ func (cli *DockerCli) CmdLogs(args ...string) error {
}
v.Set("tail", *tail)
return cli.streamHelper("GET", "/containers/"+name+"/logs?"+v.Encode(), env.GetSubEnv("Config").GetBool("Tty"), nil, cli.out, cli.err, nil)
return cli.streamHelper("GET", "/containers/"+name+"/logs?"+v.Encode(), c.Config.Tty, nil, cli.out, cli.err, nil)
}

View file

@ -19,6 +19,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api"
"github.com/docker/docker/api/types"
"github.com/docker/docker/autogen/dockerversion"
"github.com/docker/docker/engine"
"github.com/docker/docker/pkg/jsonmessage"
@ -238,11 +239,12 @@ func waitForExit(cli *DockerCli, containerID string) (int, error) {
return -1, err
}
var out engine.Env
if err := out.Decode(stream); err != nil {
var res types.ContainerWaitResponse
if err := json.NewDecoder(stream).Decode(&res); err != nil {
return -1, err
}
return out.GetInt("StatusCode"), nil
return res.StatusCode, nil
}
// getExitCode perform an inspect on the container. It returns
@ -257,13 +259,12 @@ func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
return false, -1, nil
}
var result engine.Env
if err := result.Decode(stream); err != nil {
var c types.ContainerJSON
if err := json.NewDecoder(stream).Decode(&c); err != nil {
return false, -1, err
}
state := result.GetSubEnv("State")
return state.GetBool("Running"), state.GetInt("ExitCode"), nil
return c.State.Running, c.State.ExitCode, nil
}
// getExecExitCode perform an inspect on the exec command. It returns
@ -278,12 +279,18 @@ func getExecExitCode(cli *DockerCli, execID string) (bool, int, error) {
return false, -1, nil
}
var result engine.Env
if err := result.Decode(stream); err != nil {
//TODO: Should we reconsider having a type in api/types?
//this is a response to exex/id/json not container
var c struct {
Running bool
ExitCode int
}
if err := json.NewDecoder(stream).Decode(&c); err != nil {
return false, -1, err
}
return result.GetBool("Running"), result.GetInt("ExitCode"), nil
return c.Running, c.ExitCode, nil
}
func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {

View file

@ -10,27 +10,16 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/version"
"github.com/docker/libtrust"
)
// Common constants for daemon and client.
const (
APIVERSION version.Version = "1.19" // Current REST API version
DEFAULTHTTPHOST = "127.0.0.1" // Default HTTP Host used if only port is provided to -H flag e.g. docker -d -H tcp://:8080
DEFAULTUNIXSOCKET = "/var/run/docker.sock" // Docker daemon by default always listens on the default unix socket
DefaultDockerfileName string = "Dockerfile" // Default filename with Docker commands, read by docker build
APIVERSION version.Version = "1.19" // Current REST API version
DefaultDockerfileName string = "Dockerfile" // Default filename with Docker commands, read by docker build
)
func ValidateHost(val string) (string, error) {
host, err := parsers.ParseHost(DEFAULTHTTPHOST, DEFAULTUNIXSOCKET, val)
if err != nil {
return val, err
}
return host, nil
}
type ByPrivatePort []types.Port
func (r ByPrivatePort) Len() int { return len(r) }

View file

@ -1210,12 +1210,21 @@ func (s *Server) getContainersByName(eng *engine.Engine, version version.Version
if vars == nil {
return fmt.Errorf("Missing parameter")
}
var job = eng.Job("container_inspect", vars["name"])
name := vars["name"]
if version.LessThan("1.12") {
job.SetenvBool("raw", true)
containerJSONRaw, err := s.daemon.ContainerInspectRaw(name)
if err != nil {
return err
}
return writeJSON(w, http.StatusOK, containerJSONRaw)
}
streamJSON(job.Stdout, w, false)
return job.Run()
containerJSON, err := s.daemon.ContainerInspect(name)
if err != nil {
return err
}
return writeJSON(w, http.StatusOK, containerJSON)
}
func (s *Server) getExecByID(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {

View file

@ -32,41 +32,6 @@ func TesthttpError(t *testing.T) {
}
}
func TestGetContainersByName(t *testing.T) {
eng := engine.New()
name := "container_name"
var called bool
eng.Register("container_inspect", func(job *engine.Job) error {
called = true
if job.Args[0] != name {
t.Errorf("name != '%s': %#v", name, job.Args[0])
}
if api.APIVERSION.LessThan("1.12") && !job.GetenvBool("dirty") {
t.Errorf("dirty env variable not set")
} else if api.APIVERSION.GreaterThanOrEqualTo("1.12") && job.GetenvBool("dirty") {
t.Errorf("dirty env variable set when it shouldn't")
}
v := &engine.Env{}
v.SetBool("dirty", true)
if _, err := v.WriteTo(job.Stdout); err != nil {
return err
}
return nil
})
r := serveRequest("GET", "/containers/"+name+"/json", nil, eng, t)
if !called {
t.Fatal("handler was not called")
}
assertContentType(r, "application/json", t)
var stdoutJson interface{}
if err := json.Unmarshal(r.Body.Bytes(), &stdoutJson); err != nil {
t.Fatalf("%#v", err)
}
if stdoutJson.(map[string]interface{})["dirty"].(float64) != 1 {
t.Fatalf("%#v", stdoutJson)
}
}
func TestGetImagesByName(t *testing.T) {
eng := engine.New()
name := "image_name"

View file

@ -1,6 +1,12 @@
package types
import "github.com/docker/docker/pkg/version"
import (
"time"
"github.com/docker/docker/daemon/network"
"github.com/docker/docker/pkg/version"
"github.com/docker/docker/runconfig"
)
// ContainerCreateResponse contains the information returned to a client on the
// creation of a new container.
@ -162,3 +168,43 @@ type ExecStartCheck struct {
// Check if there's a tty
Tty bool
}
type ContainerState struct {
Running bool
Paused bool
Restarting bool
OOMKilled bool
Dead bool
Pid int
ExitCode int
Error string
StartedAt time.Time
FinishedAt time.Time
}
// GET "/containers/{name:.*}/json"
type ContainerJSON struct {
Id string
Created time.Time
Path string
Args []string
Config *runconfig.Config
State *ContainerState
Image string
NetworkSettings *network.Settings
ResolvConfPath string
HostnamePath string
HostsPath string
LogPath string
Name string
RestartCount int
Driver string
ExecDriver string
MountLabel string
ProcessLabel string
Volumes map[string]string
VolumesRW map[string]bool
AppArmorProfile string
ExecIDs []string
HostConfig *runconfig.HostConfig
}

View file

@ -116,13 +116,6 @@ type Daemon struct {
// Install installs daemon capabilities to eng.
func (daemon *Daemon) Install(eng *engine.Engine) error {
for name, method := range map[string]engine.Handler{
"container_inspect": daemon.ContainerInspect,
} {
if err := eng.Register(name, method); err != nil {
return err
}
}
if err := daemon.Repositories().Install(eng); err != nil {
return err
}

View file

@ -1,83 +1,92 @@
package daemon
import (
"encoding/json"
"fmt"
"github.com/docker/docker/engine"
"github.com/docker/docker/api/types"
"github.com/docker/docker/runconfig"
)
func (daemon *Daemon) ContainerInspect(job *engine.Job) error {
if len(job.Args) != 1 {
return fmt.Errorf("usage: %s NAME", job.Name)
}
name := job.Args[0]
type ContainerJSONRaw struct {
*Container
HostConfig *runconfig.HostConfig
}
func (daemon *Daemon) ContainerInspectRaw(name string) (*ContainerJSONRaw, error) {
container, err := daemon.Get(name)
if err != nil {
return err
return nil, err
}
container.Lock()
defer container.Unlock()
if job.GetenvBool("raw") {
b, err := json.Marshal(&struct {
*Container
HostConfig *runconfig.HostConfig
}{container, container.hostConfig})
if err != nil {
return err
}
job.Stdout.Write(b)
return nil
return &ContainerJSONRaw{container, container.hostConfig}, nil
}
func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error) {
container, err := daemon.Get(name)
if err != nil {
return nil, err
}
out := &engine.Env{}
out.SetJson("Id", container.ID)
out.SetAuto("Created", container.Created)
out.SetJson("Path", container.Path)
out.SetList("Args", container.Args)
out.SetJson("Config", container.Config)
out.SetJson("State", container.State)
out.Set("Image", container.ImageID)
out.SetJson("NetworkSettings", container.NetworkSettings)
out.Set("ResolvConfPath", container.ResolvConfPath)
out.Set("HostnamePath", container.HostnamePath)
out.Set("HostsPath", container.HostsPath)
out.Set("LogPath", container.LogPath)
out.SetJson("Name", container.Name)
out.SetInt("RestartCount", container.RestartCount)
out.Set("Driver", container.Driver)
out.Set("ExecDriver", container.ExecDriver)
out.Set("MountLabel", container.MountLabel)
out.Set("ProcessLabel", container.ProcessLabel)
out.SetJson("Volumes", container.Volumes)
out.SetJson("VolumesRW", container.VolumesRW)
out.SetJson("AppArmorProfile", container.AppArmorProfile)
container.Lock()
defer container.Unlock()
out.SetList("ExecIDs", container.GetExecIDs())
// make a copy to play with
hostConfig := *container.hostConfig
if children, err := daemon.Children(container.Name); err == nil {
for linkAlias, child := range children {
container.hostConfig.Links = append(container.hostConfig.Links, fmt.Sprintf("%s:%s", child.Name, linkAlias))
hostConfig.Links = append(hostConfig.Links, fmt.Sprintf("%s:%s", child.Name, linkAlias))
}
}
// we need this trick to preserve empty log driver, so
// container will use daemon defaults even if daemon change them
if container.hostConfig.LogConfig.Type == "" {
container.hostConfig.LogConfig = daemon.defaultLogConfig
defer func() {
container.hostConfig.LogConfig = runconfig.LogConfig{}
}()
if hostConfig.LogConfig.Type == "" {
hostConfig.LogConfig = daemon.defaultLogConfig
}
out.SetJson("HostConfig", container.hostConfig)
container.hostConfig.Links = nil
if _, err := out.WriteTo(job.Stdout); err != nil {
return err
containerState := &types.ContainerState{
Running: container.State.Running,
Paused: container.State.Paused,
Restarting: container.State.Restarting,
OOMKilled: container.State.OOMKilled,
Dead: container.State.Dead,
Pid: container.State.Pid,
ExitCode: container.State.ExitCode,
Error: container.State.Error,
StartedAt: container.State.StartedAt,
FinishedAt: container.State.FinishedAt,
}
return nil
contJSON := &types.ContainerJSON{
Id: container.ID,
Created: container.Created,
Path: container.Path,
Args: container.Args,
Config: container.Config,
State: containerState,
Image: container.ImageID,
NetworkSettings: container.NetworkSettings,
ResolvConfPath: container.ResolvConfPath,
HostnamePath: container.HostnamePath,
HostsPath: container.HostsPath,
LogPath: container.LogPath,
Name: container.Name,
RestartCount: container.RestartCount,
Driver: container.Driver,
ExecDriver: container.ExecDriver,
MountLabel: container.MountLabel,
ProcessLabel: container.ProcessLabel,
Volumes: container.Volumes,
VolumesRW: container.VolumesRW,
AppArmorProfile: container.AppArmorProfile,
ExecIDs: container.GetExecIDs(),
HostConfig: &hostConfig,
}
return contJSON, nil
}
func (daemon *Daemon) ContainerExecInspect(id string) (*execConfig, error) {

View file

@ -9,9 +9,9 @@ import (
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api"
"github.com/docker/docker/api/client"
"github.com/docker/docker/autogen/dockerversion"
"github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/reexec"
"github.com/docker/docker/pkg/term"
@ -63,9 +63,9 @@ func main() {
defaultHost := os.Getenv("DOCKER_HOST")
if defaultHost == "" || *flDaemon {
// If we do not have a host, default to unix socket
defaultHost = fmt.Sprintf("unix://%s", api.DEFAULTUNIXSOCKET)
defaultHost = fmt.Sprintf("unix://%s", opts.DefaultUnixSocket)
}
defaultHost, err := api.ValidateHost(defaultHost)
defaultHost, err := opts.ValidateHost(defaultHost)
if err != nil {
logrus.Fatal(err)
}

View file

@ -20,7 +20,7 @@ import (
"strings"
"time"
"github.com/docker/docker/api"
"github.com/docker/docker/opts"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/stringutils"
"github.com/go-check/check"
@ -274,7 +274,7 @@ func (d *Daemon) LogfileName() string {
}
func daemonHost() string {
daemonUrlStr := "unix://" + api.DEFAULTUNIXSOCKET
daemonUrlStr := "unix://" + opts.DefaultUnixSocket
if daemonHostVar := os.Getenv("DOCKER_HOST"); daemonHostVar != "" {
daemonUrlStr = daemonHostVar
}

View file

@ -8,16 +8,16 @@ import (
"regexp"
"strings"
"github.com/docker/docker/api"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/ulimit"
"github.com/docker/docker/utils"
)
var (
alphaRegexp = regexp.MustCompile(`[a-zA-Z]`)
domainRegexp = regexp.MustCompile(`^(:?(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]))(:?\.(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])))*)\.?\s*$`)
alphaRegexp = regexp.MustCompile(`[a-zA-Z]`)
domainRegexp = regexp.MustCompile(`^(:?(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]))(:?\.(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])))*)\.?\s*$`)
DefaultHTTPHost = "127.0.0.1" // Default HTTP Host used if only port is provided to -H flag e.g. docker -d -H tcp://:8080
DefaultUnixSocket = "/var/run/docker.sock" // Docker daemon by default always listens on the default unix socket
)
func ListVar(values *[]string, names []string, usage string) {
@ -25,7 +25,7 @@ func ListVar(values *[]string, names []string, usage string) {
}
func HostListVar(values *[]string, names []string, usage string) {
flag.Var(newListOptsRef(values, api.ValidateHost), names, usage)
flag.Var(newListOptsRef(values, ValidateHost), names, usage)
}
func IPListVar(values *[]string, names []string, usage string) {
@ -174,7 +174,7 @@ func ValidateEnv(val string) (string, error) {
if len(arr) > 1 {
return val, nil
}
if !utils.DoesEnvExist(val) {
if !doesEnvExist(val) {
return val, nil
}
return fmt.Sprintf("%s=%s", val, os.Getenv(val)), nil
@ -234,3 +234,21 @@ func ValidateLabel(val string) (string, error) {
}
return val, nil
}
func ValidateHost(val string) (string, error) {
host, err := parsers.ParseHost(DefaultHTTPHost, DefaultUnixSocket, val)
if err != nil {
return val, err
}
return host, nil
}
func doesEnvExist(name string) bool {
for _, entry := range os.Environ() {
parts := strings.SplitN(entry, "=", 2)
if parts[0] == name {
return true
}
}
return false
}

View file

@ -239,16 +239,6 @@ func ReplaceOrAppendEnvValues(defaults, overrides []string) []string {
return defaults
}
func DoesEnvExist(name string) bool {
for _, entry := range os.Environ() {
parts := strings.SplitN(entry, "=", 2)
if parts[0] == name {
return true
}
}
return false
}
// ValidateContextDirectory checks if all the contents of the directory
// can be read and returns an error if some files can't be read
// symlinks which point to non-existing files don't trigger an error