oci: allow to specify what runtimes support JSON

add a new configuration `runtime_supports_json` to list what OCI
runtimes support the --log-format=json option.  If the runtime is not
listed here, libpod will redirect stdout/stderr from the runtime
process.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano
2019-06-13 14:21:13 +02:00
parent 6e4ce54d33
commit 13e1afdb02
4 changed files with 27 additions and 8 deletions

View File

@ -106,6 +106,10 @@ num_locks = 2048
# Default OCI runtime # Default OCI runtime
runtime = "runc" 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) # Paths to look for a valid OCI runtime (runc, runv, etc)
[runtimes] [runtimes]
runc = [ runc = [

View File

@ -58,6 +58,7 @@ type OCIRuntime struct {
logSizeMax int64 logSizeMax int64
noPivot bool noPivot bool
reservePorts bool reservePorts bool
supportsJSON bool
} }
// syncInfo is used to return data from monitor process to daemon // syncInfo is used to return data from monitor process to daemon
@ -75,7 +76,7 @@ type ociError struct {
} }
// Make a new OCI runtime with provided options // 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 := new(OCIRuntime)
runtime.name = oruntime.Name runtime.name = oruntime.Name
runtime.path = oruntime.Paths[0] runtime.path = oruntime.Paths[0]
@ -86,6 +87,7 @@ func newOCIRuntime(oruntime OCIRuntimePath, conmonPath string, conmonEnv []strin
runtime.logSizeMax = logSizeMax runtime.logSizeMax = logSizeMax
runtime.noPivot = noPivotRoot runtime.noPivot = noPivotRoot
runtime.reservePorts = reservePorts runtime.reservePorts = reservePorts
runtime.supportsJSON = supportsJSON
runtime.exitsDir = filepath.Join(runtime.tmpDir, "exits") runtime.exitsDir = filepath.Join(runtime.tmpDir, "exits")
runtime.socketsDir = filepath.Join(runtime.tmpDir, "socket") runtime.socketsDir = filepath.Join(runtime.tmpDir, "socket")

View File

@ -223,7 +223,7 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
args = append(args, "-b", ctr.bundlePath()) args = append(args, "-b", ctr.bundlePath())
args = append(args, "-p", filepath.Join(ctr.state.RunDir, "pidfile")) args = append(args, "-p", filepath.Join(ctr.state.RunDir, "pidfile"))
args = append(args, "--exit-dir", r.exitsDir) args = append(args, "--exit-dir", r.exitsDir)
if logLevel != logrus.DebugLevel { if logLevel != logrus.DebugLevel && r.supportsJSON {
args = append(args, "--runtime-arg", "--log-format=json", "--runtime-arg", "--log", fmt.Sprintf("--runtime-arg=%s", ociLog)) args = append(args, "--runtime-arg", "--log-format=json", "--runtime-arg", "--log", fmt.Sprintf("--runtime-arg=%s", ociLog))
} }
if ctr.config.ConmonPidFile != "" { if ctr.config.ConmonPidFile != "" {
@ -423,11 +423,13 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
} }
logrus.Debugf("Received container pid: %d", ss.si.Pid) logrus.Debugf("Received container pid: %d", ss.si.Pid)
if ss.si.Pid == -1 { if ss.si.Pid == -1 {
data, err := ioutil.ReadFile(ociLog) if r.supportsJSON {
if err == nil { data, err := ioutil.ReadFile(ociLog)
var ociErr ociError if err == nil {
if err := json.Unmarshal(data, &ociErr); err == nil { var ociErr ociError
return errors.Wrapf(ErrOCIRuntime, "%s", strings.Trim(ociErr.Msg, "\n")) 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 we failed to parse the JSON errors, then print the output as it is

View File

@ -151,6 +151,8 @@ type RuntimeConfig struct {
OCIRuntime string `toml:"runtime"` OCIRuntime string `toml:"runtime"`
// OCIRuntimes are the set of configured OCI runtimes (default is runc) // OCIRuntimes are the set of configured OCI runtimes (default is runc)
OCIRuntimes map[string][]string `toml:"runtimes"` 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 // RuntimePath is the path to OCI runtime binary for launching
// containers. // containers.
// The first path pointing to a valid file will be used // 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 // Make an OCI runtime to perform container operations
ociRuntime, err := newOCIRuntime(runtime.ociRuntimePath, ociRuntime, err := newOCIRuntime(runtime.ociRuntimePath,
runtime.conmonPath, runtime.config.ConmonEnvVars, runtime.conmonPath, runtime.config.ConmonEnvVars,
runtime.config.CgroupManager, runtime.config.TmpDir, runtime.config.CgroupManager, runtime.config.TmpDir,
runtime.config.MaxLogSize, runtime.config.NoPivotRoot, runtime.config.MaxLogSize, runtime.config.NoPivotRoot,
runtime.config.EnablePortReservation) runtime.config.EnablePortReservation,
supportsJSON)
if err != nil { if err != nil {
return err return err
} }