summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.tool/lint1
-rw-r--r--Dockerfile6
-rw-r--r--Dockerfile.centos6
-rw-r--r--Dockerfile.fedora6
-rw-r--r--cmd/podman/exec.go7
-rw-r--r--cmd/podman/main_remote.go8
-rw-r--r--libpod.conf4
-rw-r--r--libpod/container.go4
-rw-r--r--libpod/container_api.go2
-rw-r--r--libpod/container_internal_linux.go2
-rw-r--r--libpod/errors.go3
-rw-r--r--libpod/oci.go12
-rw-r--r--libpod/oci_linux.go20
-rw-r--r--libpod/pod.go6
-rw-r--r--libpod/runtime.go13
-rw-r--r--libpod/volume.go1
16 files changed, 63 insertions, 38 deletions
diff --git a/.tool/lint b/.tool/lint
index 01f44311d..67dfd4b28 100755
--- a/.tool/lint
+++ b/.tool/lint
@@ -39,7 +39,6 @@ ${LINTER} \
--exclude='.*_test\.go:.*error return value not checked.*\(errcheck\)$'\
--exclude='duplicate of.*_test.go.*\(dupl\)$'\
--exclude='cmd\/client\/.*\.go.*\(dupl\)$'\
- --exclude='libpod\/.*_easyjson.go:.*'\
--exclude='vendor\/.*'\
--exclude='podman\/.*'\
--exclude='server\/seccomp\/.*\.go.*$'\
diff --git a/Dockerfile b/Dockerfile
index d729c00dc..0f2249dc2 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -90,12 +90,6 @@ RUN set -x \
&& export GOPATH=/go \
&& go get github.com/onsi/gomega/...
-# Install easyjson
-RUN set -x \
- && export GOPATH=/go \
- && go get -u github.com/mailru/easyjson/... \
- && install -D -m 755 "$GOPATH"/bin/easyjson /usr/bin/
-
# Install latest stable criu version
RUN set -x \
&& cd /tmp \
diff --git a/Dockerfile.centos b/Dockerfile.centos
index c1d93d5d3..7f4cef963 100644
--- a/Dockerfile.centos
+++ b/Dockerfile.centos
@@ -49,12 +49,6 @@ RUN set -x \
&& export GOPATH=/go \
&& go get github.com/onsi/gomega/...
-# Install easyjson
-RUN set -x \
- && export GOPATH=/go \
- && go get -u github.com/mailru/easyjson/... \
- && install -D -m 755 "$GOPATH"/bin/easyjson /usr/bin/
-
# Install conmon
ENV CONMON_COMMIT 59952292a3b07ac125575024ae21956efe0ecdfb
RUN set -x \
diff --git a/Dockerfile.fedora b/Dockerfile.fedora
index d7c2d07e1..5ea82c967 100644
--- a/Dockerfile.fedora
+++ b/Dockerfile.fedora
@@ -53,12 +53,6 @@ RUN set -x \
&& export GOPATH=/go \
&& go get github.com/onsi/gomega/...
-# Install easyjson
-RUN set -x \
- && export GOPATH=/go \
- && go get -u github.com/mailru/easyjson/... \
- && install -D -m 755 "$GOPATH"/bin/easyjson /usr/bin/
-
# Install conmon
ENV CONMON_COMMIT 59952292a3b07ac125575024ae21956efe0ecdfb
RUN set -x \
diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go
index deff44a92..0684da842 100644
--- a/cmd/podman/exec.go
+++ b/cmd/podman/exec.go
@@ -125,5 +125,10 @@ func execCmd(c *cliconfig.ExecValues) error {
streams.AttachError = true
streams.AttachInput = true
- return ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir, streams, c.PreserveFDs)
+ err = ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir, streams, c.PreserveFDs)
+ if errors.Cause(err) == libpod.ErrCtrStateInvalid {
+ exitCode = 126
+ }
+
+ return err
}
diff --git a/cmd/podman/main_remote.go b/cmd/podman/main_remote.go
index de6c2c760..1b9430e92 100644
--- a/cmd/podman/main_remote.go
+++ b/cmd/podman/main_remote.go
@@ -3,15 +3,21 @@
package main
import (
+ "os/user"
+
"github.com/spf13/cobra"
)
const remote = true
func init() {
+ var username string
+ if curruser, err := user.Current(); err == nil {
+ username = curruser.Username
+ }
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.ConnectionName, "connection", "", "remote connection name")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.RemoteConfigFilePath, "remote-config-path", "", "alternate path for configuration file")
- rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.RemoteUserName, "username", "", "username on the remote host")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.RemoteUserName, "username", username, "username on the remote host")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.RemoteHost, "remote-host", "", "remote host")
// TODO maybe we allow the altering of this for bridge connections?
//rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.VarlinkAddress, "varlink-address", adapter.DefaultAddress, "address of the varlink socket")
diff --git a/libpod.conf b/libpod.conf
index ce6b95cda..45e955c36 100644
--- a/libpod.conf
+++ b/libpod.conf
@@ -106,6 +106,10 @@ num_locks = 2048
# Default OCI runtime
runtime = "runc"
+# List of the OCI runtimes that support --format=json. When json is supported
+# libpod will use it for reporting nicer errors.
+runtime_supports_json = ["runc"]
+
# Paths to look for a valid OCI runtime (runc, runv, etc)
[runtimes]
runc = [
diff --git a/libpod/container.go b/libpod/container.go
index c8ab42fc3..68c4cd6b0 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -135,7 +135,6 @@ const (
// assume that their callers handled this requirement. Generally speaking, if a
// function takes the container lock and accesses any part of state, it should
// syncContainer() immediately after locking.
-// ffjson: skip
type Container struct {
config *ContainerConfig
@@ -161,7 +160,6 @@ type Container struct {
// ContainerState contains the current state of the container
// It is stored on disk in a tmpfs and recreated on reboot
-// easyjson:json
type ContainerState struct {
// The current state of the running container
State ContainerStatus `json:"state"`
@@ -222,7 +220,6 @@ type ContainerState struct {
}
// ExecSession contains information on an active exec session
-// easyjson:json
type ExecSession struct {
ID string `json:"id"`
Command []string `json:"command"`
@@ -232,7 +229,6 @@ type ExecSession struct {
// ContainerConfig contains all information that was used to create the
// container. It may not be changed once created.
// It is stored, read-only, on disk
-// easyjson:json
type ContainerConfig struct {
Spec *spec.Spec `json:"spec"`
ID string `json:"id"`
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 1894780de..52d3afc0a 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -241,7 +241,7 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir
// TODO can probably relax this once we track exec sessions
if conState != ContainerStateRunning {
- return errors.Errorf("cannot exec into container that is not running")
+ return errors.Wrapf(ErrCtrStateInvalid, "cannot exec into container that is not running")
}
if privileged || c.config.Privileged {
capList = caps.GetAllCapabilities()
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 4acc77afa..0be5427d9 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1000,7 +1000,7 @@ func (c *Container) generateResolvConf() (string, error) {
nameservers := resolvconf.GetNameservers(resolv.Content)
// slirp4netns has a built in DNS server.
if c.config.NetMode.IsSlirp4netns() {
- nameservers = append(nameservers, "10.0.2.3")
+ nameservers = append([]string{"10.0.2.3"}, nameservers...)
}
if len(c.config.DNSServer) > 0 {
// We store DNS servers as net.IP, so need to convert to string
diff --git a/libpod/errors.go b/libpod/errors.go
index dd82d0796..cca0935ec 100644
--- a/libpod/errors.go
+++ b/libpod/errors.go
@@ -96,4 +96,7 @@ var (
// ErrOSNotSupported indicates the function is not available on the particular
// OS.
ErrOSNotSupported = errors.New("No support for this OS yet")
+
+ // ErrOCIRuntime indicates an error from the OCI runtime
+ ErrOCIRuntime = errors.New("OCI runtime error")
)
diff --git a/libpod/oci.go b/libpod/oci.go
index 7138108c5..dcb72fc1b 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -58,6 +58,7 @@ type OCIRuntime struct {
logSizeMax int64
noPivot bool
reservePorts bool
+ supportsJSON bool
}
// syncInfo is used to return data from monitor process to daemon
@@ -66,8 +67,16 @@ type syncInfo struct {
Message string `json:"message,omitempty"`
}
+// ociError is used to parse the OCI runtime JSON log. It is not part of the
+// OCI runtime specifications, it follows what runc does
+type ociError struct {
+ Level string `json:"level,omitempty"`
+ Time string `json:"time,omitempty"`
+ Msg string `json:"msg,omitempty"`
+}
+
// Make a new OCI runtime with provided options
-func newOCIRuntime(oruntime OCIRuntimePath, conmonPath string, conmonEnv []string, cgroupManager string, tmpDir string, logSizeMax int64, noPivotRoot bool, reservePorts bool) (*OCIRuntime, error) {
+func newOCIRuntime(oruntime OCIRuntimePath, conmonPath string, conmonEnv []string, cgroupManager string, tmpDir string, logSizeMax int64, noPivotRoot bool, reservePorts bool, supportsJSON bool) (*OCIRuntime, error) {
runtime := new(OCIRuntime)
runtime.name = oruntime.Name
runtime.path = oruntime.Paths[0]
@@ -78,6 +87,7 @@ func newOCIRuntime(oruntime OCIRuntimePath, conmonPath string, conmonEnv []strin
runtime.logSizeMax = logSizeMax
runtime.noPivot = noPivotRoot
runtime.reservePorts = reservePorts
+ runtime.supportsJSON = supportsJSON
runtime.exitsDir = filepath.Join(runtime.tmpDir, "exits")
runtime.socketsDir = filepath.Join(runtime.tmpDir, "socket")
diff --git a/libpod/oci_linux.go b/libpod/oci_linux.go
index 7c1c18052..9bbefdb06 100644
--- a/libpod/oci_linux.go
+++ b/libpod/oci_linux.go
@@ -6,6 +6,7 @@ import (
"bufio"
"bytes"
"fmt"
+ "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -208,6 +209,9 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
defer parentPipe.Close()
defer parentStartPipe.Close()
+ ociLog := filepath.Join(ctr.state.RunDir, "oci-log")
+ logLevel := logrus.GetLevel()
+
args := []string{}
if r.cgroupManager == SystemdCgroupsManager {
args = append(args, "-s")
@@ -219,6 +223,9 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
args = append(args, "-b", ctr.bundlePath())
args = append(args, "-p", filepath.Join(ctr.state.RunDir, "pidfile"))
args = append(args, "--exit-dir", r.exitsDir)
+ if logLevel != logrus.DebugLevel && r.supportsJSON {
+ args = append(args, "--runtime-arg", "--log-format=json", "--runtime-arg", "--log", fmt.Sprintf("--runtime-arg=%s", ociLog))
+ }
if ctr.config.ConmonPidFile != "" {
args = append(args, "--conmon-pidfile", ctr.config.ConmonPidFile)
}
@@ -248,7 +255,6 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
args = append(args, "--no-pivot")
}
- logLevel := logrus.GetLevel()
args = append(args, "--log-level", logLevel.String())
if logLevel == logrus.DebugLevel {
@@ -417,8 +423,18 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
}
logrus.Debugf("Received container pid: %d", ss.si.Pid)
if ss.si.Pid == -1 {
+ if r.supportsJSON {
+ data, err := ioutil.ReadFile(ociLog)
+ if err == nil {
+ var ociErr ociError
+ if err := json.Unmarshal(data, &ociErr); err == nil {
+ return errors.Wrapf(ErrOCIRuntime, "%s", strings.Trim(ociErr.Msg, "\n"))
+ }
+ }
+ }
+ // If we failed to parse the JSON errors, then print the output as it is
if ss.si.Message != "" {
- return errors.Wrapf(ErrInternal, "container create failed: %s", ss.si.Message)
+ return errors.Wrapf(ErrOCIRuntime, "%s", ss.si.Message)
}
return errors.Wrapf(ErrInternal, "container create failed")
}
diff --git a/libpod/pod.go b/libpod/pod.go
index 4ce697402..c319c449f 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -18,7 +18,6 @@ import (
// assume their callers handled this requirement. Generally speaking, if a
// function takes the pod lock and accesses any part of state, it should
// updatePod() immediately after locking.
-// ffjson: skip
// Pod represents a group of containers that may share namespaces
type Pod struct {
config *PodConfig
@@ -30,7 +29,6 @@ type Pod struct {
}
// PodConfig represents a pod's static configuration
-// easyjson:json
type PodConfig struct {
ID string `json:"id"`
Name string `json:"name"`
@@ -66,7 +64,6 @@ type PodConfig struct {
}
// podState represents a pod's state
-// easyjson:json
type podState struct {
// CgroupPath is the path to the pod's CGroup
CgroupPath string `json:"cgroupPath"`
@@ -77,7 +74,6 @@ type podState struct {
// PodInspect represents the data we want to display for
// podman pod inspect
-// easyjson:json
type PodInspect struct {
Config *PodConfig
State *PodInspectState
@@ -85,14 +81,12 @@ type PodInspect struct {
}
// PodInspectState contains inspect data on the pod's state
-// easyjson:json
type PodInspectState struct {
CgroupPath string `json:"cgroupPath"`
InfraContainerID string `json:"infraContainerID"`
}
// PodContainerInfo keeps information on a container in a pod
-// easyjson:json
type PodContainerInfo struct {
ID string `json:"id"`
State string `json:"state"`
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 098607b63..24bb5f61c 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -151,6 +151,8 @@ type RuntimeConfig struct {
OCIRuntime string `toml:"runtime"`
// OCIRuntimes are the set of configured OCI runtimes (default is runc)
OCIRuntimes map[string][]string `toml:"runtimes"`
+ // RuntimeSupportsJSON is the list of the OCI runtimes that support --format=json
+ RuntimeSupportsJSON []string `toml:"runtime_supports_json"`
// RuntimePath is the path to OCI runtime binary for launching
// containers.
// The first path pointing to a valid file will be used
@@ -830,12 +832,21 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) {
}
}
+ supportsJSON := false
+ for _, r := range runtime.config.RuntimeSupportsJSON {
+ if r == runtime.config.OCIRuntime {
+ supportsJSON = true
+ break
+ }
+ }
+
// Make an OCI runtime to perform container operations
ociRuntime, err := newOCIRuntime(runtime.ociRuntimePath,
runtime.conmonPath, runtime.config.ConmonEnvVars,
runtime.config.CgroupManager, runtime.config.TmpDir,
runtime.config.MaxLogSize, runtime.config.NoPivotRoot,
- runtime.config.EnablePortReservation)
+ runtime.config.EnablePortReservation,
+ supportsJSON)
if err != nil {
return err
}
diff --git a/libpod/volume.go b/libpod/volume.go
index 0b37d44ef..9ed2ff087 100644
--- a/libpod/volume.go
+++ b/libpod/volume.go
@@ -10,7 +10,6 @@ type Volume struct {
}
// VolumeConfig holds the volume's config information
-//easyjson:json
type VolumeConfig struct {
// Name of the volume
Name string `json:"name"`