summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--changelog.txt7
-rw-r--r--cmd/podmanV2/containers/mount.go3
-rw-r--r--cmd/podmanV2/containers/stop.go2
-rw-r--r--cmd/podmanV2/containers/wait.go2
-rw-r--r--cmd/podmanV2/images/history.go9
-rw-r--r--cmd/podmanV2/images/inspect.go3
-rw-r--r--cmd/podmanV2/images/rm.go8
-rw-r--r--cmd/podmanV2/images/rmi.go1
-rw-r--r--cmd/podmanV2/main.go33
-rw-r--r--cmd/podmanV2/registry/config.go59
-rw-r--r--cmd/podmanV2/registry/registry.go38
-rw-r--r--cmd/podmanV2/registry/remote.go2
-rw-r--r--cmd/podmanV2/root.go168
-rw-r--r--cmd/podmanV2/system/events.go104
-rwxr-xr-xcontrib/cirrus/logformatter8
-rw-r--r--contrib/spec/podman.spec.in2
-rw-r--r--go.mod2
-rw-r--r--go.sum2
-rw-r--r--pkg/api/handlers/libpod/pods.go3
-rw-r--r--pkg/api/handlers/types.go25
-rw-r--r--pkg/autoupdate/autoupdate.go25
-rw-r--r--pkg/domain/entities/engine.go319
-rw-r--r--pkg/domain/entities/engine_container.go3
-rw-r--r--pkg/domain/entities/engine_image.go3
-rw-r--r--pkg/domain/entities/images.go13
-rw-r--r--pkg/domain/entities/types.go10
-rw-r--r--pkg/domain/infra/abi/containers.go6
-rw-r--r--pkg/domain/infra/abi/events.go18
-rw-r--r--pkg/domain/infra/abi/images.go12
-rw-r--r--pkg/domain/infra/abi/pods.go6
-rw-r--r--pkg/domain/infra/abi/system.go154
-rw-r--r--pkg/domain/infra/runtime_abi.go4
-rw-r--r--pkg/domain/infra/runtime_image_proxy.go2
-rw-r--r--pkg/domain/infra/runtime_libpod.go58
-rw-r--r--pkg/domain/infra/runtime_proxy.go2
-rw-r--r--pkg/domain/infra/runtime_tunnel.go4
-rw-r--r--pkg/domain/infra/tunnel/containers.go5
-rw-r--r--pkg/domain/infra/tunnel/events.go31
-rw-r--r--pkg/domain/infra/tunnel/images.go5
-rw-r--r--pkg/specgen/config_linux_nocgo.go11
-rw-r--r--pkg/specgen/generate/config_linux_cgo.go (renamed from pkg/specgen/config_linux_cgo.go)5
-rw-r--r--pkg/specgen/generate/config_linux_nocgo.go14
-rw-r--r--pkg/specgen/generate/container_create.go14
-rw-r--r--pkg/specgen/generate/namespaces.go417
-rw-r--r--pkg/specgen/generate/oci.go (renamed from pkg/specgen/oci.go)19
-rw-r--r--pkg/specgen/generate/pod_create.go (renamed from pkg/specgen/pod_create.go)18
-rw-r--r--pkg/specgen/generate/storage.go (renamed from pkg/specgen/storage.go)8
-rw-r--r--pkg/specgen/namespaces.go379
-rw-r--r--pkg/specgen/pod_validate.go3
-rw-r--r--pkg/specgen/specgen.go11
-rw-r--r--pkg/util/utils.go2
-rwxr-xr-xtest/apiv2/test-apiv22
-rw-r--r--vendor/github.com/containers/common/pkg/config/config.go4
-rw-r--r--vendor/github.com/containers/common/pkg/config/containers.conf10
-rw-r--r--vendor/github.com/containers/common/pkg/config/default.go3
-rw-r--r--vendor/modules.txt2
-rw-r--r--version/version.go2
58 files changed, 1437 insertions, 650 deletions
diff --git a/README.md b/README.md
index d5f682ee2..8cc010a45 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
Libpod provides a library for applications looking to use the Container Pod concept,
popularized by Kubernetes. Libpod also contains the Pod Manager tool `(Podman)`. Podman manages pods, containers, container images, and container volumes.
-* [Latest Version: 1.8.2](https://github.com/containers/libpod/releases/latest)
+* [Latest Version: 1.9.0](https://github.com/containers/libpod/releases/latest)
* [Continuous Integration:](contrib/cirrus/README.md) [![Build Status](https://api.cirrus-ci.com/github/containers/libpod.svg)](https://cirrus-ci.com/github/containers/libpod/master)
* [GoDoc: ![GoDoc](https://godoc.org/github.com/containers/libpod/libpod?status.svg)](https://godoc.org/github.com/containers/libpod/libpod)
* Automated continuous release downloads (including remote-client):
diff --git a/changelog.txt b/changelog.txt
index 3d0d431d2..95f8d5b47 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,10 @@
+- Changelog for v1.9.0 (2020-04-15)
+ * podmanV2: fix nil deref
+ * v2specgen prune libpod
+ * More system test fixes on regressions
+ * Add support for the global flags and config files
+ * Bump to v1.9.0-dev
+
- Changelog for v1.9.0-rc2 (2020-04-14)
* Update release notes for v1.9.0-RC2
* v2podman ps revert structure changes
diff --git a/cmd/podmanV2/containers/mount.go b/cmd/podmanV2/containers/mount.go
index c2f5ae987..4f7b95d98 100644
--- a/cmd/podmanV2/containers/mount.go
+++ b/cmd/podmanV2/containers/mount.go
@@ -31,6 +31,9 @@ var (
Args: func(cmd *cobra.Command, args []string) error {
return parse.CheckAllLatestAndCIDFile(cmd, args, true, false)
},
+ Annotations: map[string]string{
+ registry.RootRequired: "true",
+ },
}
)
diff --git a/cmd/podmanV2/containers/stop.go b/cmd/podmanV2/containers/stop.go
index d6f31352f..53ec2934d 100644
--- a/cmd/podmanV2/containers/stop.go
+++ b/cmd/podmanV2/containers/stop.go
@@ -46,7 +46,7 @@ func init() {
flags.StringArrayVarP(&stopOptions.CIDFiles, "cidfile", "", nil, "Read the container ID from the file")
flags.BoolVarP(&stopOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.UintVarP(&stopTimeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
- if registry.EngineOptions.EngineMode == entities.ABIMode {
+ if registry.PodmanOptions.EngineMode == entities.ABIMode {
_ = flags.MarkHidden("latest")
_ = flags.MarkHidden("cidfile")
_ = flags.MarkHidden("ignore")
diff --git a/cmd/podmanV2/containers/wait.go b/cmd/podmanV2/containers/wait.go
index 2171f2073..3d11c581e 100644
--- a/cmd/podmanV2/containers/wait.go
+++ b/cmd/podmanV2/containers/wait.go
@@ -44,7 +44,7 @@ func init() {
flags.DurationVarP(&waitOptions.Interval, "interval", "i", time.Duration(250), "Milliseconds to wait before polling for completion")
flags.BoolVarP(&waitOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.StringVar(&waitCondition, "condition", "stopped", "Condition to wait on")
- if registry.EngineOptions.EngineMode == entities.ABIMode {
+ if registry.PodmanOptions.EngineMode == entities.ABIMode {
// TODO: This is the same as V1. We could skip creating the flag altogether in V2...
_ = flags.MarkHidden("latest")
}
diff --git a/cmd/podmanV2/images/history.go b/cmd/podmanV2/images/history.go
index 48575b33a..e3bb7a051 100644
--- a/cmd/podmanV2/images/history.go
+++ b/cmd/podmanV2/images/history.go
@@ -53,7 +53,7 @@ func init() {
flags := historyCmd.Flags()
flags.StringVar(&opts.format, "format", "", "Change the output to JSON or a Go template")
- flags.BoolVarP(&opts.human, "human", "H", false, "Display sizes and dates in human readable format")
+ flags.BoolVarP(&opts.human, "human", "H", true, "Display sizes and dates in human readable format")
flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Do not truncate the output")
flags.BoolVar(&opts.noTrunc, "notruncate", false, "Do not truncate the output")
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Display the numeric IDs only")
@@ -79,7 +79,7 @@ func history(cmd *cobra.Command, args []string) error {
layers := make([]layer, len(results.Layers))
for i, l := range results.Layers {
layers[i].ImageHistoryLayer = l
- layers[i].Created = time.Unix(l.Created, 0).Format(time.RFC3339)
+ layers[i].Created = l.Created.Format(time.RFC3339)
}
json := jsoniter.ConfigCompatibleWithStandardLibrary
enc := json.NewEncoder(os.Stdout)
@@ -129,7 +129,10 @@ type historyreporter struct {
}
func (h historyreporter) Created() string {
- return units.HumanDuration(time.Since(time.Unix(h.ImageHistoryLayer.Created, 0))) + " ago"
+ if opts.human {
+ return units.HumanDuration(time.Since(h.ImageHistoryLayer.Created)) + " ago"
+ }
+ return h.ImageHistoryLayer.Created.Format(time.RFC3339)
}
func (h historyreporter) Size() string {
diff --git a/cmd/podmanV2/images/inspect.go b/cmd/podmanV2/images/inspect.go
index d7f6b0ee1..2ee2d86ee 100644
--- a/cmd/podmanV2/images/inspect.go
+++ b/cmd/podmanV2/images/inspect.go
@@ -67,7 +67,6 @@ func inspect(cmd *cobra.Command, args []string) error {
}
return nil
}
-
row := inspectFormat(inspectOpts.Format)
format := "{{range . }}" + row + "{{end}}"
tmpl, err := template.New("inspect").Parse(format)
@@ -77,7 +76,7 @@ func inspect(cmd *cobra.Command, args []string) error {
w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
defer func() { _ = w.Flush() }()
- err = tmpl.Execute(w, results)
+ err = tmpl.Execute(w, results.Images)
if err != nil {
return err
}
diff --git a/cmd/podmanV2/images/rm.go b/cmd/podmanV2/images/rm.go
index bb5880de3..6784182d9 100644
--- a/cmd/podmanV2/images/rm.go
+++ b/cmd/podmanV2/images/rm.go
@@ -8,6 +8,7 @@ import (
"github.com/containers/libpod/pkg/domain/entities"
"github.com/pkg/errors"
"github.com/spf13/cobra"
+ "github.com/spf13/pflag"
)
var (
@@ -33,11 +34,13 @@ func init() {
Parent: imageCmd,
})
- flags := rmCmd.Flags()
+ imageRemoveFlagSet(rmCmd.Flags())
+}
+
+func imageRemoveFlagSet(flags *pflag.FlagSet) {
flags.BoolVarP(&imageOpts.All, "all", "a", false, "Remove all images")
flags.BoolVarP(&imageOpts.Force, "force", "f", false, "Force Removal of the image")
}
-
func rm(cmd *cobra.Command, args []string) error {
if len(args) < 1 && !imageOpts.All {
@@ -46,7 +49,6 @@ func rm(cmd *cobra.Command, args []string) error {
if len(args) > 0 && imageOpts.All {
return errors.Errorf("when using the --all switch, you may not pass any images names or IDs")
}
-
report, err := registry.ImageEngine().Delete(registry.GetContext(), args, imageOpts)
if err != nil {
switch {
diff --git a/cmd/podmanV2/images/rmi.go b/cmd/podmanV2/images/rmi.go
index 7f9297bc9..973763966 100644
--- a/cmd/podmanV2/images/rmi.go
+++ b/cmd/podmanV2/images/rmi.go
@@ -27,4 +27,5 @@ func init() {
})
rmiCmd.SetHelpTemplate(registry.HelpTemplate())
rmiCmd.SetUsageTemplate(registry.UsageTemplate())
+ imageRemoveFlagSet(rmiCmd.Flags())
}
diff --git a/cmd/podmanV2/main.go b/cmd/podmanV2/main.go
index fe3cd9f16..cfe20d1c1 100644
--- a/cmd/podmanV2/main.go
+++ b/cmd/podmanV2/main.go
@@ -3,8 +3,6 @@ package main
import (
"os"
"reflect"
- "runtime"
- "strings"
_ "github.com/containers/libpod/cmd/podmanV2/containers"
_ "github.com/containers/libpod/cmd/podmanV2/healthcheck"
@@ -14,36 +12,13 @@ import (
"github.com/containers/libpod/cmd/podmanV2/registry"
_ "github.com/containers/libpod/cmd/podmanV2/system"
_ "github.com/containers/libpod/cmd/podmanV2/volumes"
- "github.com/containers/libpod/libpod"
- "github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/storage/pkg/reexec"
- "github.com/sirupsen/logrus"
)
func init() {
- if err := libpod.SetXdgDirs(); err != nil {
- logrus.Errorf(err.Error())
- os.Exit(1)
- }
-
- switch runtime.GOOS {
- case "darwin":
- fallthrough
- case "windows":
- registry.EngineOptions.EngineMode = entities.TunnelMode
- case "linux":
- registry.EngineOptions.EngineMode = entities.ABIMode
- default:
- logrus.Errorf("%s is not a supported OS", runtime.GOOS)
- os.Exit(1)
- }
-
- // TODO: Is there a Cobra way to "peek" at os.Args?
- for _, v := range os.Args {
- if strings.HasPrefix(v, "--remote") {
- registry.EngineOptions.EngineMode = entities.TunnelMode
- }
- }
+ // This is the bootstrap configuration, if user gives
+ // CLI flags parts of this configuration may be overwritten
+ registry.PodmanOptions = registry.NewPodmanConfig()
}
func main() {
@@ -53,7 +28,7 @@ func main() {
return
}
for _, c := range registry.Commands {
- if Contains(registry.EngineOptions.EngineMode, c.Mode) {
+ if Contains(registry.PodmanOptions.EngineMode, c.Mode) {
parent := rootCmd
if c.Parent != nil {
parent = c.Parent
diff --git a/cmd/podmanV2/registry/config.go b/cmd/podmanV2/registry/config.go
new file mode 100644
index 000000000..e68009a50
--- /dev/null
+++ b/cmd/podmanV2/registry/config.go
@@ -0,0 +1,59 @@
+package registry
+
+import (
+ "os"
+ "runtime"
+ "strings"
+
+ "github.com/containers/common/pkg/config"
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/sirupsen/logrus"
+)
+
+const (
+ RootRequired = "RootRequired"
+)
+
+var (
+ PodmanOptions entities.PodmanConfig
+)
+
+// NewPodmanConfig creates a PodmanConfig from the environment
+func NewPodmanConfig() entities.PodmanConfig {
+ if err := libpod.SetXdgDirs(); err != nil {
+ logrus.Errorf(err.Error())
+ os.Exit(1)
+ }
+
+ var mode entities.EngineMode
+ switch runtime.GOOS {
+ case "darwin":
+ fallthrough
+ case "windows":
+ mode = entities.TunnelMode
+ case "linux":
+ mode = entities.ABIMode
+ default:
+ logrus.Errorf("%s is not a supported OS", runtime.GOOS)
+ os.Exit(1)
+ }
+
+ // cobra.Execute() may not be called yet, so we peek at os.Args.
+ for _, v := range os.Args {
+ // Prefix checking works because of how default EngineMode's
+ // have been defined.
+ if strings.HasPrefix(v, "--remote=") {
+ mode = entities.TunnelMode
+ }
+ }
+
+ // FIXME: for rootless, where to get the path
+ // TODO:
+ cfg, err := config.NewConfig("")
+ if err != nil {
+ logrus.Error("Failed to obtain podman configuration")
+ os.Exit(1)
+ }
+ return entities.PodmanConfig{Config: cfg, EngineMode: mode}
+}
diff --git a/cmd/podmanV2/registry/registry.go b/cmd/podmanV2/registry/registry.go
index 07c2b33ff..5ef6a10d8 100644
--- a/cmd/podmanV2/registry/registry.go
+++ b/cmd/podmanV2/registry/registry.go
@@ -29,8 +29,9 @@ var (
exitCode = ExecErrorCodeGeneric
imageEngine entities.ImageEngine
- Commands []CliCommand
- EngineOptions entities.EngineOptions
+ // Commands holds the cobra.Commands to present to the user, including
+ // parent if not a child of "root"
+ Commands []CliCommand
)
func SetExitCode(code int) {
@@ -83,8 +84,8 @@ func ImageEngine() entities.ImageEngine {
// NewImageEngine is a wrapper for building an ImageEngine to be used for PreRunE functions
func NewImageEngine(cmd *cobra.Command, args []string) (entities.ImageEngine, error) {
if imageEngine == nil {
- EngineOptions.FlagSet = cmd.Flags()
- engine, err := infra.NewImageEngine(EngineOptions)
+ PodmanOptions.FlagSet = cmd.Flags()
+ engine, err := infra.NewImageEngine(PodmanOptions)
if err != nil {
return nil, err
}
@@ -100,8 +101,8 @@ func ContainerEngine() entities.ContainerEngine {
// NewContainerEngine is a wrapper for building an ContainerEngine to be used for PreRunE functions
func NewContainerEngine(cmd *cobra.Command, args []string) (entities.ContainerEngine, error) {
if containerEngine == nil {
- EngineOptions.FlagSet = cmd.Flags()
- engine, err := infra.NewContainerEngine(EngineOptions)
+ PodmanOptions.FlagSet = cmd.Flags()
+ engine, err := infra.NewContainerEngine(PodmanOptions)
if err != nil {
return nil, err
}
@@ -125,24 +126,17 @@ func IdOrLatestArgs(cmd *cobra.Command, args []string) error {
return nil
}
-type podmanContextKey string
-
-var podmanFactsKey = podmanContextKey("engineOptions")
-
-func NewOptions(ctx context.Context, facts *entities.EngineOptions) context.Context {
- return context.WithValue(ctx, podmanFactsKey, facts)
-}
-
-func Options(cmd *cobra.Command) (*entities.EngineOptions, error) {
- if f, ok := cmd.Context().Value(podmanFactsKey).(*entities.EngineOptions); ok {
- return f, errors.New("Command Context ")
- }
- return nil, nil
-}
-
func GetContext() context.Context {
if cliCtx == nil {
- cliCtx = context.TODO()
+ cliCtx = context.Background()
}
return cliCtx
}
+
+type ContextOptionsKey string
+
+const PodmanOptionsKey ContextOptionsKey = "PodmanOptions"
+
+func GetContextWithOptions() context.Context {
+ return context.WithValue(GetContext(), PodmanOptionsKey, PodmanOptions)
+}
diff --git a/cmd/podmanV2/registry/remote.go b/cmd/podmanV2/registry/remote.go
index 32a231ac4..5378701e7 100644
--- a/cmd/podmanV2/registry/remote.go
+++ b/cmd/podmanV2/registry/remote.go
@@ -5,5 +5,5 @@ import (
)
func IsRemote() bool {
- return EngineOptions.EngineMode == entities.TunnelMode
+ return PodmanOptions.EngineMode == entities.TunnelMode
}
diff --git a/cmd/podmanV2/root.go b/cmd/podmanV2/root.go
index 6fc12f57e..0639257ea 100644
--- a/cmd/podmanV2/root.go
+++ b/cmd/podmanV2/root.go
@@ -1,29 +1,37 @@
package main
import (
+ "context"
"fmt"
"log/syslog"
"os"
"path"
+ "runtime/pprof"
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/pkg/tracing"
"github.com/containers/libpod/version"
+ "github.com/opentracing/opentracing-go"
+ "github.com/pkg/errors"
"github.com/sirupsen/logrus"
logrusSyslog "github.com/sirupsen/logrus/hooks/syslog"
"github.com/spf13/cobra"
+ "github.com/spf13/pflag"
)
var (
rootCmd = &cobra.Command{
- Use: path.Base(os.Args[0]),
- Long: "Manage pods, containers and images",
- SilenceUsage: true,
- SilenceErrors: true,
- TraverseChildren: true,
- PersistentPreRunE: preRunE,
- RunE: registry.SubCommandExists,
- Version: version.Version,
+ Use: path.Base(os.Args[0]),
+ Long: "Manage pods, containers and images",
+ SilenceUsage: true,
+ SilenceErrors: true,
+ TraverseChildren: true,
+ PersistentPreRunE: preRunE,
+ RunE: registry.SubCommandExists,
+ PersistentPostRunE: postRunE,
+ Version: version.Version,
}
logLevels = entities.NewStringSet("debug", "info", "warn", "error", "fatal", "panic")
@@ -32,30 +40,73 @@ var (
)
func init() {
- // Override default --help information of `--version` global flag}
- var dummyVersion bool
- // TODO had to disable shorthand -v for version due to -v rm with volume
- rootCmd.PersistentFlags().BoolVar(&dummyVersion, "version", false, "Version of Podman")
- rootCmd.PersistentFlags().StringVarP(&registry.EngineOptions.Uri, "remote", "r", "", "URL to access Podman service")
- rootCmd.PersistentFlags().StringSliceVar(&registry.EngineOptions.Identities, "identity", []string{}, "path to SSH identity file")
- rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "error", fmt.Sprintf("Log messages above specified level (%s)", logLevels.String()))
- rootCmd.PersistentFlags().BoolVar(&useSyslog, "syslog", false, "Output logging information to syslog as well as the console (default false)")
-
cobra.OnInitialize(
- logging,
+ rootlessHook,
+ loggingHook,
syslogHook,
)
+
+ rootFlags(registry.PodmanOptions, rootCmd.PersistentFlags())
+}
+
+func Execute() {
+ if err := rootCmd.ExecuteContext(registry.GetContextWithOptions()); err != nil {
+ logrus.Error(err)
+ } else if registry.GetExitCode() == registry.ExecErrorCodeGeneric {
+ // The exitCode modified from registry.ExecErrorCodeGeneric,
+ // indicates an application
+ // running inside of a container failed, as opposed to the
+ // podman command failed. Must exit with that exit code
+ // otherwise command exited correctly.
+ registry.SetExitCode(0)
+ }
+ os.Exit(registry.GetExitCode())
}
-func preRunE(cmd *cobra.Command, args []string) error {
+func preRunE(cmd *cobra.Command, _ []string) error {
+ // Update PodmanOptions now that we "know" more
+ // TODO: pass in path overriding configuration file
+ registry.PodmanOptions = registry.NewPodmanConfig()
+
cmd.SetHelpTemplate(registry.HelpTemplate())
cmd.SetUsageTemplate(registry.UsageTemplate())
+
+ if cmd.Flag("cpu-profile").Changed {
+ f, err := os.Create(registry.PodmanOptions.CpuProfile)
+ if err != nil {
+ return errors.Wrapf(err, "unable to create cpu profiling file %s",
+ registry.PodmanOptions.CpuProfile)
+ }
+ if err := pprof.StartCPUProfile(f); err != nil {
+ return err
+ }
+ }
+
+ if cmd.Flag("trace").Changed {
+ tracer, closer := tracing.Init("podman")
+ opentracing.SetGlobalTracer(tracer)
+ registry.PodmanOptions.SpanCloser = closer
+
+ registry.PodmanOptions.Span = tracer.StartSpan("before-context")
+ registry.PodmanOptions.SpanCtx = opentracing.ContextWithSpan(context.Background(), registry.PodmanOptions.Span)
+ }
return nil
}
-func logging() {
+func postRunE(cmd *cobra.Command, args []string) error {
+ if cmd.Flag("cpu-profile").Changed {
+ pprof.StopCPUProfile()
+ }
+ if cmd.Flag("trace").Changed {
+ registry.PodmanOptions.Span.Finish()
+ registry.PodmanOptions.SpanCloser.Close()
+ }
+ return nil
+}
+
+func loggingHook() {
if !logLevels.Contains(logLevel) {
- fmt.Fprintf(os.Stderr, "Log Level \"%s\" is not supported, choose from: %s\n", logLevel, logLevels.String())
+ logrus.Errorf("Log Level \"%s\" is not supported, choose from: %s", logLevel, logLevels.String())
os.Exit(1)
}
@@ -83,17 +134,68 @@ func syslogHook() {
}
}
-func Execute() {
- o := registry.NewOptions(rootCmd.Context(), &registry.EngineOptions)
- if err := rootCmd.ExecuteContext(o); err != nil {
- fmt.Fprintln(os.Stderr, "Error:", err.Error())
- } else if registry.GetExitCode() == registry.ExecErrorCodeGeneric {
- // The exitCode modified from registry.ExecErrorCodeGeneric,
- // indicates an application
- // running inside of a container failed, as opposed to the
- // podman command failed. Must exit with that exit code
- // otherwise command exited correctly.
- registry.SetExitCode(0)
+func rootlessHook() {
+ if rootless.IsRootless() {
+ logrus.Error("rootless mode is currently not supported. Support will return ASAP.")
}
- os.Exit(registry.GetExitCode())
+ // ce, err := registry.NewContainerEngine(rootCmd, []string{})
+ // if err != nil {
+ // logrus.WithError(err).Fatal("failed to obtain container engine")
+ // }
+ // ce.SetupRootLess(rootCmd)
+}
+
+func rootFlags(opts entities.PodmanConfig, flags *pflag.FlagSet) {
+ // V2 flags
+ flags.StringVarP(&opts.Uri, "remote", "r", "", "URL to access Podman service")
+ flags.StringSliceVar(&opts.Identities, "identity", []string{}, "path to SSH identity file")
+
+ // Override default --help information of `--version` global flag
+ // TODO: restore -v option for version without breaking -v for volumes
+ var dummyVersion bool
+ flags.BoolVar(&dummyVersion, "version", false, "Version of Podman")
+
+ cfg := opts.Config
+ flags.StringVar(&cfg.Engine.CgroupManager, "cgroup-manager", cfg.Engine.CgroupManager, opts.CGroupUsage)
+ flags.StringVar(&opts.CpuProfile, "cpu-profile", "", "Path for the cpu profiling results")
+ flags.StringVar(&opts.ConmonPath, "conmon", "", "Path of the conmon binary")
+ flags.StringVar(&cfg.Engine.NetworkCmdPath, "network-cmd-path", cfg.Engine.NetworkCmdPath, "Path to the command for configuring the network")
+ flags.StringVar(&cfg.Network.NetworkConfigDir, "cni-config-dir", cfg.Network.NetworkConfigDir, "Path of the configuration directory for CNI networks")
+ flags.StringVar(&cfg.Containers.DefaultMountsFile, "default-mounts-file", cfg.Containers.DefaultMountsFile, "Path to default mounts file")
+ flags.StringVar(&cfg.Engine.EventsLogger, "events-backend", cfg.Engine.EventsLogger, `Events backend to use ("file"|"journald"|"none")`)
+ flags.StringSliceVar(&cfg.Engine.HooksDir, "hooks-dir", cfg.Engine.HooksDir, "Set the OCI hooks directory path (may be set multiple times)")
+ flags.IntVar(&opts.MaxWorks, "max-workers", 0, "The maximum number of workers for parallel operations")
+ flags.StringVar(&cfg.Engine.Namespace, "namespace", cfg.Engine.Namespace, "Set the libpod namespace, used to create separate views of the containers and pods on the system")
+ flags.StringVar(&cfg.Engine.StaticDir, "root", "", "Path to the root directory in which data, including images, is stored")
+ flags.StringVar(&opts.Runroot, "runroot", "", "Path to the 'run directory' where all state information is stored")
+ flags.StringVar(&opts.RuntimePath, "runtime", "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc")
+ // -s is deprecated due to conflict with -s on subcommands
+ flags.StringVar(&opts.StorageDriver, "storage-driver", "", "Select which storage driver is used to manage storage of images and containers (default is overlay)")
+ flags.StringArrayVar(&opts.StorageOpts, "storage-opt", []string{}, "Used to pass an option to the storage driver")
+
+ flags.StringVar(&opts.Engine.TmpDir, "tmpdir", "", "Path to the tmp directory for libpod state content.\n\nNote: use the environment variable 'TMPDIR' to change the temporary storage location for container images, '/var/tmp'.\n")
+ flags.BoolVar(&opts.Trace, "trace", false, "Enable opentracing output (default false)")
+
+ // Override default --help information of `--help` global flag
+ var dummyHelp bool
+ flags.BoolVar(&dummyHelp, "help", false, "Help for podman")
+ flags.StringVar(&logLevel, "log-level", logLevel, fmt.Sprintf("Log messages above specified level (%s)", logLevels.String()))
+
+ // Hide these flags for both ABI and Tunneling
+ for _, f := range []string{
+ "cpu-profile",
+ "default-mounts-file",
+ "max-workers",
+ "trace",
+ } {
+ if err := flags.MarkHidden(f); err != nil {
+ logrus.Warnf("unable to mark %s flag as hidden", f)
+ }
+ }
+
+ // Only create these flags for ABI connections
+ if !registry.IsRemote() {
+ flags.BoolVar(&useSyslog, "syslog", false, "Output logging information to syslog as well as the console (default false)")
+ }
+
}
diff --git a/cmd/podmanV2/system/events.go b/cmd/podmanV2/system/events.go
new file mode 100644
index 000000000..9fd27e2c1
--- /dev/null
+++ b/cmd/podmanV2/system/events.go
@@ -0,0 +1,104 @@
+package system
+
+import (
+ "bufio"
+ "context"
+ "html/template"
+ "os"
+
+ "github.com/containers/buildah/pkg/formats"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/libpod/events"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ eventsDescription = "Monitor podman events"
+ eventsCommand = &cobra.Command{
+ Use: "events",
+ Args: cobra.NoArgs,
+ Short: "Show podman events",
+ Long: eventsDescription,
+ PersistentPreRunE: preRunE,
+ RunE: eventsCmd,
+ Example: `podman events
+ podman events --filter event=create
+ podman events --since 1h30s`,
+ }
+)
+
+var (
+ eventOptions entities.EventsOptions
+ eventFormat string
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: eventsCommand,
+ })
+ flags := eventsCommand.Flags()
+ flags.StringArrayVar(&eventOptions.Filter, "filter", []string{}, "filter output")
+ flags.StringVar(&eventFormat, "format", "", "format the output using a Go template")
+ flags.BoolVar(&eventOptions.Stream, "stream", true, "stream new events; for testing only")
+ flags.StringVar(&eventOptions.Since, "since", "", "show all events created since timestamp")
+ flags.StringVar(&eventOptions.Until, "until", "", "show all events until timestamp")
+ _ = flags.MarkHidden("stream")
+}
+
+func eventsCmd(cmd *cobra.Command, args []string) error {
+ var (
+ err error
+ eventsError error
+ tmpl *template.Template
+ )
+ if eventFormat != formats.JSONString {
+ tmpl, err = template.New("events").Parse(eventFormat)
+ if err != nil {
+ return err
+ }
+ }
+ if len(eventOptions.Since) > 0 || len(eventOptions.Until) > 0 {
+ eventOptions.FromStart = true
+ }
+ eventChannel := make(chan *events.Event)
+ eventOptions.EventChan = eventChannel
+
+ go func() {
+ eventsError = registry.ContainerEngine().Events(context.Background(), eventOptions)
+ }()
+ if eventsError != nil {
+ return eventsError
+ }
+
+ w := bufio.NewWriter(os.Stdout)
+ for event := range eventChannel {
+ switch {
+ case eventFormat == formats.JSONString:
+ jsonStr, err := event.ToJSONString()
+ if err != nil {
+ return errors.Wrapf(err, "unable to format json")
+ }
+ if _, err := w.Write([]byte(jsonStr)); err != nil {
+ return err
+ }
+ case len(eventFormat) > 0:
+ if err := tmpl.Execute(w, event); err != nil {
+ return err
+ }
+ default:
+ if _, err := w.Write([]byte(event.ToHumanReadable())); err != nil {
+ return err
+ }
+ }
+ if _, err := w.Write([]byte("\n")); err != nil {
+ return err
+ }
+ if err := w.Flush(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/contrib/cirrus/logformatter b/contrib/cirrus/logformatter
index 6a86f6a49..738d2e19d 100755
--- a/contrib/cirrus/logformatter
+++ b/contrib/cirrus/logformatter
@@ -220,8 +220,8 @@ END_HTML
$cirrus_task = $1;
}
- # BATS handling
- if ($line =~ /^1\.\.\d+$/) {
+ # BATS handling (used also for apiv2 tests, which emit TAP output)
+ if ($line =~ /^1\.\.\d+$/ || $line =~ m!/test-apiv2!) {
$looks_like_bats = 1;
}
if ($looks_like_bats) {
@@ -234,6 +234,10 @@ END_HTML
elsif ($line =~ /^#\s/) { $css = 'log' }
if ($css) {
+ # Make it linkable, e.g. foo.html#t--00001
+ if ($line =~ /^(not\s+)?ok\s+(\d+)/) {
+ $line = sprintf("<a name='t--%05d'>%s</a>", $2, $line);
+ }
$line = "<span class='bats-$css'>$line</span>";
}
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index a63c15940..afc50f854 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -48,7 +48,7 @@ Epoch: 99
%else
Epoch: 0
%endif
-Version: 1.9.0
+Version: 2.0.0
Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
Summary: Manage Pods, Containers and Container Images
License: ASL 2.0
diff --git a/go.mod b/go.mod
index 08e52e83b..bfc30b198 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921
github.com/containernetworking/plugins v0.8.5
github.com/containers/buildah v1.14.8
- github.com/containers/common v0.8.1
+ github.com/containers/common v0.9.0
github.com/containers/conmon v2.0.14+incompatible
github.com/containers/image/v5 v5.4.3
github.com/containers/psgo v1.4.0
diff --git a/go.sum b/go.sum
index 2ca41f042..9940f4119 100644
--- a/go.sum
+++ b/go.sum
@@ -67,6 +67,8 @@ github.com/containers/buildah v1.14.8 h1:JbMI0QSOmyZ30Mr2633uCXAj+Fajgh/EFS9xX/Y
github.com/containers/buildah v1.14.8/go.mod h1:ytEjHJQnRXC1ygXMyc0FqYkjcoCydqBQkOdxbH563QU=
github.com/containers/common v0.8.1 h1:1IUwAtZ4mC7GYRr4AC23cHf2oXCuoLzTUoSzIkSgnYw=
github.com/containers/common v0.8.1/go.mod h1:VxDJbaA1k6N1TNv9Rt6bQEF4hyKVHNfOfGA5L91ADEs=
+github.com/containers/common v0.9.0 h1:mN4P8VK6e7lqQSl7oywfEnhMtSzi8DhkE2QaJHJp88w=
+github.com/containers/common v0.9.0/go.mod h1:9YGKPwu6NFYQG2NtSP9bRhNGA8mgd1mUCCkOU2tr+Pc=
github.com/containers/conmon v2.0.14+incompatible h1:knU1O1QxXy5YxtjMQVKEyCajROaehizK9FHaICl+P5Y=
github.com/containers/conmon v2.0.14+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.4.3 h1:zn2HR7uu4hpvT5QQHgjqonOzKDuM1I1UHUEmzZT5sbs=
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index a890169a1..81cab1ede 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/specgen"
+ "github.com/containers/libpod/pkg/specgen/generate"
"github.com/containers/libpod/pkg/util"
"github.com/gorilla/schema"
"github.com/pkg/errors"
@@ -27,7 +28,7 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Failed to decode specgen", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen"))
return
}
- pod, err := psg.MakePod(runtime)
+ pod, err := generate.MakePod(&psg, runtime)
if err != nil {
http_code := http.StatusInternalServerError
if errors.Cause(err) == define.ErrPodExists {
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index f1c932ebc..0fe6ae6a7 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -180,6 +180,31 @@ type ExecCreateResponse struct {
docker.IDResponse
}
+func (e *Event) ToLibpodEvent() *events.Event {
+ exitCode, err := strconv.Atoi(e.Actor.Attributes["containerExitCode"])
+ if err != nil {
+ return nil
+ }
+ status, err := events.StringToStatus(e.Action)
+ if err != nil {
+ return nil
+ }
+ t, err := events.StringToType(e.Type)
+ if err != nil {
+ return nil
+ }
+ lp := events.Event{
+ ContainerExitCode: exitCode,
+ ID: e.Actor.ID,
+ Image: e.Actor.Attributes["image"],
+ Name: e.Actor.Attributes["name"],
+ Status: status,
+ Time: time.Unix(e.Time, e.TimeNano),
+ Type: t,
+ }
+ return &lp
+}
+
func EventToApiEvent(e *events.Event) *Event {
return &Event{dockerEvents.Message{
Type: e.Type.String(),
diff --git a/pkg/autoupdate/autoupdate.go b/pkg/autoupdate/autoupdate.go
index 7c243eb00..78d5ac474 100644
--- a/pkg/autoupdate/autoupdate.go
+++ b/pkg/autoupdate/autoupdate.go
@@ -201,18 +201,25 @@ func imageContainersMap(runtime *libpod.Runtime) (map[string][]*libpod.Container
if state != define.ContainerStateRunning {
continue
}
+
// Only update containers with the specific label/policy set.
labels := ctr.Labels()
- if value, exists := labels[Label]; exists {
- policy, err := LookupPolicy(value)
- if err != nil {
- errors = append(errors, err)
- continue
- }
- if policy != PolicyNewImage {
- continue
- }
+ value, exists := labels[Label]
+ if !exists {
+ continue
}
+
+ policy, err := LookupPolicy(value)
+ if err != nil {
+ errors = append(errors, err)
+ continue
+ }
+
+ // Skip non-image labels (could be explicitly disabled).
+ if policy != PolicyNewImage {
+ continue
+ }
+
// Now we know that `ctr` is configured for auto updates.
id, _ := ctr.Image()
imageMap[id] = append(imageMap[id], allContainers[i])
diff --git a/pkg/domain/entities/engine.go b/pkg/domain/entities/engine.go
index c14348529..3b971a1e8 100644
--- a/pkg/domain/entities/engine.go
+++ b/pkg/domain/entities/engine.go
@@ -1,13 +1,23 @@
package entities
import (
- "os/user"
- "path/filepath"
+ "context"
+ "fmt"
+ "io"
+ "os"
+ "github.com/containers/buildah/pkg/parse"
"github.com/containers/common/pkg/config"
+ "github.com/containers/common/pkg/sysinfo"
+ "github.com/containers/libpod/pkg/apparmor"
+ "github.com/containers/libpod/pkg/cgroups"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/opencontainers/selinux/go-selinux"
+ "github.com/opentracing/opentracing-go"
"github.com/spf13/pflag"
)
+// EngineMode is the connection type podman is using to access libpod
type EngineMode string
const (
@@ -15,78 +25,243 @@ const (
TunnelMode = EngineMode("tunnel")
)
+// Convert EngineMode to String
func (m EngineMode) String() string {
return string(m)
}
-type EngineOptions struct {
- Uri string
- Identities []string
- FlagSet *pflag.FlagSet
- EngineMode EngineMode
-
- CGroupManager string
- CniConfigDir string
- ConmonPath string
- DefaultMountsFile string
- EventsBackend string
- HooksDir []string
- MaxWorks int
- Namespace string
- Root string
- Runroot string
- Runtime string
- StorageDriver string
- StorageOpts []string
- Syslog bool
- Trace bool
- NetworkCmdPath string
-
- Config string
- CpuProfile string
- LogLevel string
- TmpDir string
-
- RemoteUserName string
- RemoteHost string
- VarlinkAddress string
- ConnectionName string
- RemoteConfigFilePath string
- Port int
- IdentityFile string
- IgnoreHosts bool
-}
-
-func NewEngineOptions() (EngineOptions, error) {
- u, _ := user.Current()
- return EngineOptions{
- CGroupManager: config.SystemdCgroupsManager,
- CniConfigDir: "",
- Config: "",
- ConmonPath: filepath.Join("usr", "bin", "conmon"),
- ConnectionName: "",
- CpuProfile: "",
- DefaultMountsFile: "",
- EventsBackend: "",
- HooksDir: nil,
- IdentityFile: "",
- IgnoreHosts: false,
- LogLevel: "",
- MaxWorks: 0,
- Namespace: "",
- NetworkCmdPath: "",
- Port: 0,
- RemoteConfigFilePath: "",
- RemoteHost: "",
- RemoteUserName: "",
- Root: "",
- Runroot: filepath.Join("run", "user", u.Uid),
- Runtime: "",
- StorageDriver: "overlayfs",
- StorageOpts: nil,
- Syslog: false,
- TmpDir: filepath.Join("run", "user", u.Uid, "libpod", "tmp"),
- Trace: false,
- VarlinkAddress: "",
- }, nil
+// PodmanConfig combines the defaults and settings from the file system with the
+// flags given in os.Args. Some runtime state is also stored here.
+type PodmanConfig struct {
+ *config.Config
+ *pflag.FlagSet
+
+ CGroupUsage string // rootless code determines Usage message
+ ConmonPath string // --conmon flag will set Engine.ConmonPath
+ CpuProfile string // Hidden: Should CPU profile be taken
+ EngineMode EngineMode // ABI or Tunneling mode
+ Identities []string // ssh identities for connecting to server
+ MaxWorks int // maximum number of parallel threads
+ RuntimePath string // --runtime flag will set Engine.RuntimePath
+ SpanCloser io.Closer // Close() for tracing object
+ SpanCtx context.Context // context to use when tracing
+ Span opentracing.Span // tracing object
+ Syslog bool // write to StdOut and Syslog, not supported when tunneling
+ Trace bool // Hidden: Trace execution
+ Uri string // URI to API Service
+
+ Runroot string
+ StorageDriver string
+ StorageOpts []string
+}
+
+// DefaultSecurityOptions: getter for security options from configuration
+func (c PodmanConfig) DefaultSecurityOptions() []string {
+ securityOpts := []string{}
+ if c.Containers.SeccompProfile != "" && c.Containers.SeccompProfile != parse.SeccompDefaultPath {
+ securityOpts = append(securityOpts, fmt.Sprintf("seccomp=%s", c.Containers.SeccompProfile))
+ }
+ if apparmor.IsEnabled() && c.Containers.ApparmorProfile != "" {
+ securityOpts = append(securityOpts, fmt.Sprintf("apparmor=%s", c.Containers.ApparmorProfile))
+ }
+ if selinux.GetEnabled() && !c.Containers.EnableLabeling {
+ securityOpts = append(securityOpts, fmt.Sprintf("label=%s", selinux.DisableSecOpt()[0]))
+ }
+ return securityOpts
+}
+
+// DefaultSysctls
+func (c PodmanConfig) DefaultSysctls() []string {
+ return c.Containers.DefaultSysctls
+}
+
+func (c PodmanConfig) DefaultVolumes() []string {
+ return c.Containers.Volumes
+}
+
+func (c PodmanConfig) DefaultDevices() []string {
+ return c.Containers.Devices
+}
+
+func (c PodmanConfig) DefaultDNSServers() []string {
+ return c.Containers.DNSServers
+}
+
+func (c PodmanConfig) DefaultDNSSearches() []string {
+ return c.Containers.DNSSearches
+}
+
+func (c PodmanConfig) DefaultDNSOptions() []string {
+ return c.Containers.DNSOptions
+}
+
+func (c PodmanConfig) DefaultEnv() []string {
+ return c.Containers.Env
+}
+
+func (c PodmanConfig) DefaultInitPath() string {
+ return c.Containers.InitPath
+}
+
+func (c PodmanConfig) DefaultIPCNS() string {
+ return c.Containers.IPCNS
}
+
+func (c PodmanConfig) DefaultPidNS() string {
+ return c.Containers.PidNS
+}
+
+func (c PodmanConfig) DefaultNetNS() string {
+ if c.Containers.NetNS == "private" && rootless.IsRootless() {
+ return "slirp4netns"
+ }
+ return c.Containers.NetNS
+}
+
+func (c PodmanConfig) DefaultCgroupNS() string {
+ return c.Containers.CgroupNS
+}
+
+func (c PodmanConfig) DefaultUTSNS() string {
+ return c.Containers.UTSNS
+}
+
+func (c PodmanConfig) DefaultShmSize() string {
+ return c.Containers.ShmSize
+}
+
+func (c PodmanConfig) DefaultUlimits() []string {
+ return c.Containers.DefaultUlimits
+}
+
+func (c PodmanConfig) DefaultUserNS() string {
+ if v, found := os.LookupEnv("PODMAN_USERNS"); found {
+ return v
+ }
+ return c.Containers.UserNS
+}
+
+func (c PodmanConfig) DefaultPidsLimit() int64 {
+ if rootless.IsRootless() {
+ cgroup2, _ := cgroups.IsCgroup2UnifiedMode()
+ if cgroup2 {
+ return c.Containers.PidsLimit
+ }
+ }
+ return sysinfo.GetDefaultPidsLimit()
+}
+
+func (c PodmanConfig) DefaultPidsDescription() string {
+ return "Tune container pids limit (set 0 for unlimited)"
+}
+
+func (c PodmanConfig) DefaultDetachKeys() string {
+ return c.Engine.DetachKeys
+}
+
+// TODO: Remove in rootless support PR
+// // EngineOptions holds the environment for running the engines
+// type EngineOptions struct {
+// // Introduced with V2
+// Uri string
+// Identities []string
+// FlagSet *pflag.FlagSet
+// EngineMode EngineMode
+// CGroupUsage string
+//
+// // Introduced with V1
+// CGroupManager string // config.EngineConfig
+// CniConfigDir string // config.NetworkConfig.NetworkConfigDir
+// ConmonPath string // config.EngineConfig
+// DefaultMountsFile string // config.ContainersConfig
+// EventsBackend string // config.EngineConfig.EventsLogger
+// HooksDir []string // config.EngineConfig
+// MaxWorks int
+// Namespace string // config.EngineConfig
+// Root string //
+// Runroot string // config.EngineConfig.StorageConfigRunRootSet??
+// Runtime string // config.EngineConfig.OCIRuntime
+// StorageDriver string // config.EngineConfig.StorageConfigGraphDriverNameSet??
+// StorageOpts []string
+// Syslog bool
+// Trace bool
+// NetworkCmdPath string // config.EngineConfig
+//
+// Config string
+// CpuProfile string
+// LogLevel string
+// TmpDir string // config.EngineConfig
+//
+// RemoteUserName string // deprecated
+// RemoteHost string // deprecated
+// VarlinkAddress string // deprecated
+// ConnectionName string
+// RemoteConfigFilePath string
+// Port int // deprecated
+// IdentityFile string // deprecated
+// IgnoreHosts bool
+// }
+//
+// func NewEngineOptions(opts EngineOptions) (EngineOptions, error) {
+// ctnrCfg, err := config.Default()
+// if err != nil {
+// logrus.Error(err)
+// os.Exit(1)
+// }
+//
+// cgroupManager := ctnrCfg.Engine.CgroupManager
+// cgroupUsage := `Cgroup manager to use ("cgroupfs"|"systemd")`
+// cgroupv2, _ := cgroups.IsCgroup2UnifiedMode()
+// cniPluginDir := ctnrCfg.Network.CNIPluginDirs[0]
+//
+// cfg, err := config.NewConfig("")
+// if err != nil {
+// logrus.Errorf("Error loading container config %v\n", err)
+// os.Exit(1)
+// }
+// cfg.CheckCgroupsAndAdjustConfig()
+//
+// if rootless.IsRootless() {
+// if !cgroupv2 {
+// cgroupManager = ""
+// cgroupUsage = "Cgroup manager is not supported in rootless mode"
+// }
+// cniPluginDir = ""
+// }
+//
+// return EngineOptions{
+// CGroupManager: cgroupManager,
+// CGroupUsage: cgroupUsage,
+// CniConfigDir: cniPluginDir,
+// Config: opts.Config, // TODO: deprecate
+// ConmonPath: opts.ConmonPath,
+// ConnectionName: opts.ConnectionName,
+// CpuProfile: opts.CpuProfile,
+// DefaultMountsFile: ctnrCfg.Containers.DefaultMountsFile,
+// EngineMode: opts.EngineMode,
+// EventsBackend: ctnrCfg.Engine.EventsLogger,
+// FlagSet: opts.FlagSet, // TODO: deprecate
+// HooksDir: append(ctnrCfg.Engine.HooksDir[:0:0], ctnrCfg.Engine.HooksDir...),
+// Identities: append(opts.Identities[:0:0], opts.Identities...),
+// IdentityFile: opts.IdentityFile, // TODO: deprecate
+// IgnoreHosts: opts.IgnoreHosts,
+// LogLevel: opts.LogLevel,
+// MaxWorks: opts.MaxWorks,
+// Namespace: ctnrCfg.Engine.Namespace,
+// NetworkCmdPath: ctnrCfg.Engine.NetworkCmdPath,
+// Port: opts.Port,
+// RemoteConfigFilePath: opts.RemoteConfigFilePath,
+// RemoteHost: opts.RemoteHost, // TODO: deprecate
+// RemoteUserName: opts.RemoteUserName, // TODO: deprecate
+// Root: opts.Root,
+// Runroot: opts.Runroot,
+// Runtime: opts.Runtime,
+// StorageDriver: opts.StorageDriver,
+// StorageOpts: append(opts.StorageOpts[:0:0], opts.StorageOpts...),
+// Syslog: opts.Syslog,
+// TmpDir: opts.TmpDir,
+// Trace: opts.Trace,
+// Uri: opts.Uri,
+// VarlinkAddress: opts.VarlinkAddress,
+// }, nil
+// }
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index cf66f6ac2..5fdb9a8a6 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -3,11 +3,13 @@ package entities
import (
"context"
+ "github.com/containers/common/pkg/config"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/specgen"
)
type ContainerEngine interface {
+ Config(ctx context.Context) (*config.Config, error)
ContainerAttach(ctx context.Context, nameOrId string, options AttachOptions) error
ContainerCheckpoint(ctx context.Context, namesOrIds []string, options CheckpointOptions) ([]*CheckpointReport, error)
ContainerCleanup(ctx context.Context, namesOrIds []string, options ContainerCleanupOptions) ([]*ContainerCleanupReport, error)
@@ -34,6 +36,7 @@ type ContainerEngine interface {
ContainerUnmount(ctx context.Context, nameOrIds []string, options ContainerUnmountOptions) ([]*ContainerUnmountReport, error)
ContainerUnpause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error)
+ Events(ctx context.Context, opts EventsOptions) error
HealthCheckRun(ctx context.Context, nameOrId string, options HealthCheckOptions) (*define.HealthCheckResults, error)
Info(ctx context.Context) (*define.Info, error)
PodCreate(ctx context.Context, opts PodCreateOptions) (*PodCreateReport, error)
diff --git a/pkg/domain/entities/engine_image.go b/pkg/domain/entities/engine_image.go
index 3110898a8..3a051ab9b 100644
--- a/pkg/domain/entities/engine_image.go
+++ b/pkg/domain/entities/engine_image.go
@@ -2,9 +2,12 @@ package entities
import (
"context"
+
+ "github.com/containers/common/pkg/config"
)
type ImageEngine interface {
+ Config(ctx context.Context) (*config.Config, error)
Delete(ctx context.Context, nameOrId []string, opts ImageDeleteOptions) (*ImageDeleteReport, error)
Diff(ctx context.Context, nameOrId string, options DiffOptions) (*DiffReport, error)
Exists(ctx context.Context, nameOrId string) (*BoolReport, error)
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index 53a5f4951..78ebb8805 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -2,6 +2,7 @@ package entities
import (
"net/url"
+ "time"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/types"
@@ -99,12 +100,12 @@ type ImageDeleteReport struct {
type ImageHistoryOptions struct{}
type ImageHistoryLayer struct {
- ID string `json:"Id"`
- Created int64 `json:",omitempty"`
- CreatedBy string `json:",omitempty"`
- Tags []string `json:",omitempty"`
- Size int64 `json:",omitempty"`
- Comment string `json:",omitempty"`
+ ID string `json:"id"`
+ Created time.Time `json:"created,omitempty"`
+ CreatedBy string `json:",omitempty"`
+ Tags []string `json:"tags,omitempty"`
+ Size int64 `json:"size"`
+ Comment string `json:"comment,omitempty"`
}
type ImageHistoryReport struct {
diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go
index 7e35957f4..91ae00764 100644
--- a/pkg/domain/entities/types.go
+++ b/pkg/domain/entities/types.go
@@ -3,6 +3,7 @@ package entities
import (
"net"
+ "github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/pkg/specgen"
"github.com/containers/storage/pkg/archive"
"github.com/cri-o/ocicni/pkg/ocicni"
@@ -62,3 +63,12 @@ type DiffOptions struct {
type DiffReport struct {
Changes []archive.Change
}
+
+type EventsOptions struct {
+ FromStart bool
+ EventChan chan *events.Event
+ Filter []string
+ Stream bool
+ Since string
+ Until string
+}
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 92668190c..f464df3ac 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -12,6 +12,7 @@ import (
"sync"
"github.com/containers/buildah"
+ "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/manifest"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
@@ -893,3 +894,8 @@ func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIds []str
}
return reports, nil
}
+
+// GetConfig returns a copy of the configuration used by the runtime
+func (ic *ContainerEngine) Config(_ context.Context) (*config.Config, error) {
+ return ic.Libpod.GetConfig()
+}
diff --git a/pkg/domain/infra/abi/events.go b/pkg/domain/infra/abi/events.go
new file mode 100644
index 000000000..9540a5b96
--- /dev/null
+++ b/pkg/domain/infra/abi/events.go
@@ -0,0 +1,18 @@
+//+build ABISupport
+
+package abi
+
+import (
+ "context"
+
+ "github.com/containers/libpod/libpod/events"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/sirupsen/logrus"
+)
+
+func (ic *ContainerEngine) Events(ctx context.Context, opts entities.EventsOptions) error {
+ readOpts := events.ReadOptions{FromStart: opts.FromStart, Stream: opts.Stream, Filters: opts.Filter, EventChannel: opts.EventChan, Since: opts.Since, Until: opts.Until}
+ err := ic.Libpod.Events(readOpts)
+ logrus.Error(err)
+ return err
+}
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 402bbb45e..9467c14d4 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -9,6 +9,7 @@ import (
"os"
"strings"
+ "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker"
dockerarchive "github.com/containers/image/v5/docker/archive"
"github.com/containers/image/v5/docker/reference"
@@ -45,7 +46,9 @@ func (ir *ImageEngine) Delete(ctx context.Context, nameOrId []string, opts entit
if err != nil {
return &report, errors.Wrapf(err, "unable to query local images")
}
-
+ if len(targets) == 0 {
+ return &report, nil
+ }
if len(targets) > 0 && len(targets) == len(previousTargets) {
return &report, errors.New("unable to delete all images; re-run the rmi command again.")
}
@@ -142,7 +145,7 @@ func (ir *ImageEngine) History(ctx context.Context, nameOrId string, opts entiti
func ToDomainHistoryLayer(layer *libpodImage.History) entities.ImageHistoryLayer {
l := entities.ImageHistoryLayer{}
l.ID = layer.ID
- l.Created = layer.Created.Unix()
+ l.Created = *layer.Created
l.CreatedBy = layer.CreatedBy
copy(l.Tags, layer.Tags)
l.Size = layer.Size
@@ -460,3 +463,8 @@ func (ir *ImageEngine) Search(ctx context.Context, term string, opts entities.Im
return reports, nil
}
+
+// GetConfig returns a copy of the configuration used by the runtime
+func (ir *ImageEngine) Config(_ context.Context) (*config.Config, error) {
+ return ir.Libpod.GetConfig()
+}
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index c3e5d59bc..bb637de3e 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -5,13 +5,13 @@ package abi
import (
"context"
- lpfilters "github.com/containers/libpod/libpod/filters"
-
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
+ lpfilters "github.com/containers/libpod/libpod/filters"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/signal"
"github.com/containers/libpod/pkg/specgen"
+ "github.com/containers/libpod/pkg/specgen/generate"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -246,7 +246,7 @@ func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, optio
func (ic *ContainerEngine) PodCreate(ctx context.Context, opts entities.PodCreateOptions) (*entities.PodCreateReport, error) {
podSpec := specgen.NewPodSpecGenerator()
opts.ToPodSpecGen(podSpec)
- pod, err := podSpec.MakePod(ic.Libpod)
+ pod, err := generate.MakePod(podSpec, ic.Libpod)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index adec94f6c..10872144b 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -4,17 +4,28 @@ package abi
import (
"context"
+ "fmt"
+ "io/ioutil"
"net"
+ "os"
+ "strconv"
"strings"
+ "syscall"
+ "github.com/containers/common/pkg/config"
"github.com/containers/libpod/libpod/define"
api "github.com/containers/libpod/pkg/api/server"
+ "github.com/containers/libpod/pkg/cgroups"
"github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/pkg/util"
iopodman "github.com/containers/libpod/pkg/varlink"
iopodmanAPI "github.com/containers/libpod/pkg/varlinkapi"
+ "github.com/containers/libpod/utils"
"github.com/containers/libpod/version"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
+ "github.com/spf13/cobra"
"github.com/varlink/go/varlink"
)
@@ -88,3 +99,146 @@ func (ic *ContainerEngine) VarlinkService(_ context.Context, opts entities.Servi
}
return nil
}
+
+func (ic *ContainerEngine) SetupRootless(cmd *cobra.Command) error {
+ // do it only after podman has already re-execed and running with uid==0.
+ if os.Geteuid() == 0 {
+ ownsCgroup, err := cgroups.UserOwnsCurrentSystemdCgroup()
+ if err != nil {
+ logrus.Warnf("Failed to detect the owner for the current cgroup: %v", err)
+ }
+ if !ownsCgroup {
+ conf, err := ic.Config(context.Background())
+ if err != nil {
+ return err
+ }
+ unitName := fmt.Sprintf("podman-%d.scope", os.Getpid())
+ if err := utils.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil {
+ if conf.Engine.CgroupManager == config.SystemdCgroupsManager {
+ logrus.Warnf("Failed to add podman to systemd sandbox cgroup: %v", err)
+ } else {
+ logrus.Debugf("Failed to add podman to systemd sandbox cgroup: %v", err)
+ }
+ }
+ }
+ }
+
+ if !executeCommandInUserNS(cmd) {
+ return nil
+ }
+
+ pausePidPath, err := util.GetRootlessPauseProcessPidPath()
+ if err != nil {
+ return errors.Wrapf(err, "could not get pause process pid file path")
+ }
+
+ became, ret, err := rootless.TryJoinPauseProcess(pausePidPath)
+ if err != nil {
+ return err
+ }
+ if became {
+ os.Exit(ret)
+ }
+
+ // if there is no pid file, try to join existing containers, and create a pause process.
+ ctrs, err := ic.Libpod.GetRunningContainers()
+ if err != nil {
+ logrus.WithError(err).Fatal("")
+ }
+
+ paths := []string{}
+ for _, ctr := range ctrs {
+ paths = append(paths, ctr.Config().ConmonPidFile)
+ }
+
+ became, ret, err = rootless.TryJoinFromFilePaths(pausePidPath, true, paths)
+ if err := movePauseProcessToScope(); err != nil {
+ conf, err := ic.Config(context.Background())
+ if err != nil {
+ return err
+ }
+ if conf.Engine.CgroupManager == config.SystemdCgroupsManager {
+ logrus.Warnf("Failed to add pause process to systemd sandbox cgroup: %v", err)
+ } else {
+ logrus.Debugf("Failed to add pause process to systemd sandbox cgroup: %v", err)
+ }
+ }
+ if err != nil {
+ logrus.WithError(err).Fatal("")
+ }
+ if became {
+ os.Exit(ret)
+ }
+ return nil
+}
+
+// Most podman commands when run in rootless mode, need to be executed in the
+// users usernamespace. This function is updated with a list of commands that
+// should NOT be run within the user namespace.
+func executeCommandInUserNS(cmd *cobra.Command) bool {
+ return os.Geteuid() == 0
+ // if os.Geteuid() == 0 {
+ // return false
+ // }
+ // switch cmd {
+ // case _migrateCommand,
+ // _mountCommand,
+ // _renumberCommand,
+ // _searchCommand,
+ // _versionCommand:
+ // return false
+ // }
+ // return true
+}
+
+func movePauseProcessToScope() error {
+ pausePidPath, err := util.GetRootlessPauseProcessPidPath()
+ if err != nil {
+ return errors.Wrapf(err, "could not get pause process pid file path")
+ }
+
+ data, err := ioutil.ReadFile(pausePidPath)
+ if err != nil {
+ return errors.Wrapf(err, "cannot read pause pid file")
+ }
+ pid, err := strconv.ParseUint(string(data), 10, 0)
+ if err != nil {
+ return errors.Wrapf(err, "cannot parse pid file %s", pausePidPath)
+ }
+
+ return utils.RunUnderSystemdScope(int(pid), "user.slice", "podman-pause.scope")
+}
+
+func setRLimits() error { // nolint:deadcode,unused
+ rlimits := new(syscall.Rlimit)
+ rlimits.Cur = 1048576
+ rlimits.Max = 1048576
+ if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
+ if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
+ return errors.Wrapf(err, "error getting rlimits")
+ }
+ rlimits.Cur = rlimits.Max
+ if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
+ return errors.Wrapf(err, "error setting new rlimits")
+ }
+ }
+ return nil
+}
+
+func setUMask() { // nolint:deadcode,unused
+ // Be sure we can create directories with 0755 mode.
+ syscall.Umask(0022)
+}
+
+// checkInput can be used to verify any of the globalopt values
+func checkInput() error { // nolint:deadcode,unused
+ return nil
+}
+
+// func getCNIPluginsDir() string {
+// if rootless.IsRootless() {
+// return ""
+// }
+//
+// return registry.PodmanOptions.Network.CNIPluginDirs[0]
+// }
diff --git a/pkg/domain/infra/runtime_abi.go b/pkg/domain/infra/runtime_abi.go
index f11026571..0dbcf2ad2 100644
--- a/pkg/domain/infra/runtime_abi.go
+++ b/pkg/domain/infra/runtime_abi.go
@@ -12,7 +12,7 @@ import (
)
// NewContainerEngine factory provides a libpod runtime for container-related operations
-func NewContainerEngine(facts entities.EngineOptions) (entities.ContainerEngine, error) {
+func NewContainerEngine(facts entities.PodmanConfig) (entities.ContainerEngine, error) {
switch facts.EngineMode {
case entities.ABIMode:
r, err := NewLibpodRuntime(facts.FlagSet, facts)
@@ -25,7 +25,7 @@ func NewContainerEngine(facts entities.EngineOptions) (entities.ContainerEngine,
}
// NewContainerEngine factory provides a libpod runtime for image-related operations
-func NewImageEngine(facts entities.EngineOptions) (entities.ImageEngine, error) {
+func NewImageEngine(facts entities.PodmanConfig) (entities.ImageEngine, error) {
switch facts.EngineMode {
case entities.ABIMode:
r, err := NewLibpodImageRuntime(facts.FlagSet, facts)
diff --git a/pkg/domain/infra/runtime_image_proxy.go b/pkg/domain/infra/runtime_image_proxy.go
index befc66b9a..45c5425a3 100644
--- a/pkg/domain/infra/runtime_image_proxy.go
+++ b/pkg/domain/infra/runtime_image_proxy.go
@@ -12,7 +12,7 @@ import (
// ContainerEngine Image Proxy will be EOL'ed after podmanV2 is separated from libpod repo
-func NewLibpodImageRuntime(flags *pflag.FlagSet, opts entities.EngineOptions) (entities.ImageEngine, error) {
+func NewLibpodImageRuntime(flags *pflag.FlagSet, opts entities.PodmanConfig) (entities.ImageEngine, error) {
r, err := GetRuntime(context.Background(), flags, opts)
if err != nil {
return nil, err
diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go
index d59759707..9cf374e2e 100644
--- a/pkg/domain/infra/runtime_libpod.go
+++ b/pkg/domain/infra/runtime_libpod.go
@@ -1,3 +1,5 @@
+// build: ABISupport
+
package infra
import (
@@ -22,68 +24,70 @@ type engineOpts struct {
migrate bool
noStore bool
withFDS bool
- flags entities.EngineOptions
+ config entities.PodmanConfig
}
// GetRuntimeMigrate gets a libpod runtime that will perform a migration of existing containers
-func GetRuntimeMigrate(ctx context.Context, fs *flag.FlagSet, ef entities.EngineOptions, newRuntime string) (*libpod.Runtime, error) {
+func GetRuntimeMigrate(ctx context.Context, fs *flag.FlagSet, cfg entities.PodmanConfig, newRuntime string) (*libpod.Runtime, error) {
return getRuntime(ctx, fs, &engineOpts{
name: newRuntime,
renumber: false,
migrate: true,
noStore: false,
withFDS: true,
- flags: ef,
+ config: cfg,
})
}
// GetRuntimeDisableFDs gets a libpod runtime that will disable sd notify
-func GetRuntimeDisableFDs(ctx context.Context, fs *flag.FlagSet, ef entities.EngineOptions) (*libpod.Runtime, error) {
+func GetRuntimeDisableFDs(ctx context.Context, fs *flag.FlagSet, cfg entities.PodmanConfig) (*libpod.Runtime, error) {
return getRuntime(ctx, fs, &engineOpts{
renumber: false,
migrate: false,
noStore: false,
withFDS: false,
- flags: ef,
+ config: cfg,
})
}
// GetRuntimeRenumber gets a libpod runtime that will perform a lock renumber
-func GetRuntimeRenumber(ctx context.Context, fs *flag.FlagSet, ef entities.EngineOptions) (*libpod.Runtime, error) {
+func GetRuntimeRenumber(ctx context.Context, fs *flag.FlagSet, cfg entities.PodmanConfig) (*libpod.Runtime, error) {
return getRuntime(ctx, fs, &engineOpts{
renumber: true,
migrate: false,
noStore: false,
withFDS: true,
- flags: ef,
+ config: cfg,
})
}
// GetRuntime generates a new libpod runtime configured by command line options
-func GetRuntime(ctx context.Context, flags *flag.FlagSet, ef entities.EngineOptions) (*libpod.Runtime, error) {
+func GetRuntime(ctx context.Context, flags *flag.FlagSet, cfg entities.PodmanConfig) (*libpod.Runtime, error) {
return getRuntime(ctx, flags, &engineOpts{
renumber: false,
migrate: false,
noStore: false,
withFDS: true,
- flags: ef,
+ config: cfg,
})
}
// GetRuntimeNoStore generates a new libpod runtime configured by command line options
-func GetRuntimeNoStore(ctx context.Context, fs *flag.FlagSet, ef entities.EngineOptions) (*libpod.Runtime, error) {
+func GetRuntimeNoStore(ctx context.Context, fs *flag.FlagSet, cfg entities.PodmanConfig) (*libpod.Runtime, error) {
return getRuntime(ctx, fs, &engineOpts{
renumber: false,
migrate: false,
noStore: true,
withFDS: true,
- flags: ef,
+ config: cfg,
})
}
func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpod.Runtime, error) {
options := []libpod.RuntimeOption{}
storageOpts := storage.StoreOptions{}
+ cfg := opts.config
+
storageSet := false
uidmapFlag := fs.Lookup("uidmap")
@@ -109,25 +113,25 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo
if fs.Changed("root") {
storageSet = true
- storageOpts.GraphRoot = opts.flags.Root
+ storageOpts.GraphRoot = cfg.Engine.StaticDir
}
if fs.Changed("runroot") {
storageSet = true
- storageOpts.RunRoot = opts.flags.Runroot
+ storageOpts.RunRoot = cfg.Runroot
}
if len(storageOpts.RunRoot) > 50 {
return nil, errors.New("the specified runroot is longer than 50 characters")
}
if fs.Changed("storage-driver") {
storageSet = true
- storageOpts.GraphDriverName = opts.flags.StorageDriver
+ storageOpts.GraphDriverName = cfg.StorageDriver
// Overriding the default storage driver caused GraphDriverOptions from storage.conf to be ignored
storageOpts.GraphDriverOptions = []string{}
}
// This should always be checked after storage-driver is checked
- if len(opts.flags.StorageOpts) > 0 {
+ if len(cfg.StorageOpts) > 0 {
storageSet = true
- storageOpts.GraphDriverOptions = opts.flags.StorageOpts
+ storageOpts.GraphDriverOptions = cfg.StorageOpts
}
if opts.migrate {
options = append(options, libpod.WithMigrate())
@@ -151,30 +155,30 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo
// TODO CLI flags for image config?
// TODO CLI flag for signature policy?
- if len(opts.flags.Namespace) > 0 {
- options = append(options, libpod.WithNamespace(opts.flags.Namespace))
+ if len(cfg.Engine.Namespace) > 0 {
+ options = append(options, libpod.WithNamespace(cfg.Engine.Namespace))
}
if fs.Changed("runtime") {
- options = append(options, libpod.WithOCIRuntime(opts.flags.Runtime))
+ options = append(options, libpod.WithOCIRuntime(cfg.RuntimePath))
}
if fs.Changed("conmon") {
- options = append(options, libpod.WithConmonPath(opts.flags.ConmonPath))
+ options = append(options, libpod.WithConmonPath(cfg.ConmonPath))
}
if fs.Changed("tmpdir") {
- options = append(options, libpod.WithTmpDir(opts.flags.TmpDir))
+ options = append(options, libpod.WithTmpDir(cfg.Engine.TmpDir))
}
if fs.Changed("network-cmd-path") {
- options = append(options, libpod.WithNetworkCmdPath(opts.flags.NetworkCmdPath))
+ options = append(options, libpod.WithNetworkCmdPath(cfg.Engine.NetworkCmdPath))
}
if fs.Changed("events-backend") {
- options = append(options, libpod.WithEventsLogger(opts.flags.EventsBackend))
+ options = append(options, libpod.WithEventsLogger(cfg.Engine.EventsLogger))
}
if fs.Changed("cgroup-manager") {
- options = append(options, libpod.WithCgroupManager(opts.flags.CGroupManager))
+ options = append(options, libpod.WithCgroupManager(cfg.Engine.CgroupManager))
} else {
unified, err := cgroups.IsCgroup2UnifiedMode()
if err != nil {
@@ -189,13 +193,13 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo
// TODO flag to set libpod tmp dir?
if fs.Changed("cni-config-dir") {
- options = append(options, libpod.WithCNIConfigDir(opts.flags.CniConfigDir))
+ options = append(options, libpod.WithCNIConfigDir(cfg.Network.NetworkConfigDir))
}
if fs.Changed("default-mounts-file") {
- options = append(options, libpod.WithDefaultMountsFile(opts.flags.DefaultMountsFile))
+ options = append(options, libpod.WithDefaultMountsFile(cfg.Containers.DefaultMountsFile))
}
if fs.Changed("hooks-dir") {
- options = append(options, libpod.WithHooksDir(opts.flags.HooksDir...))
+ options = append(options, libpod.WithHooksDir(cfg.Engine.HooksDir...))
}
// TODO flag to set CNI plugins dir?
diff --git a/pkg/domain/infra/runtime_proxy.go b/pkg/domain/infra/runtime_proxy.go
index 2e38c74b9..18f716ea0 100644
--- a/pkg/domain/infra/runtime_proxy.go
+++ b/pkg/domain/infra/runtime_proxy.go
@@ -12,7 +12,7 @@ import (
// ContainerEngine Proxy will be EOL'ed after podmanV2 is separated from libpod repo
-func NewLibpodRuntime(flags *flag.FlagSet, opts entities.EngineOptions) (entities.ContainerEngine, error) {
+func NewLibpodRuntime(flags *flag.FlagSet, opts entities.PodmanConfig) (entities.ContainerEngine, error) {
r, err := GetRuntime(context.Background(), flags, opts)
if err != nil {
return nil, err
diff --git a/pkg/domain/infra/runtime_tunnel.go b/pkg/domain/infra/runtime_tunnel.go
index dc04b4e53..129fdeb2c 100644
--- a/pkg/domain/infra/runtime_tunnel.go
+++ b/pkg/domain/infra/runtime_tunnel.go
@@ -11,7 +11,7 @@ import (
"github.com/containers/libpod/pkg/domain/infra/tunnel"
)
-func NewContainerEngine(facts entities.EngineOptions) (entities.ContainerEngine, error) {
+func NewContainerEngine(facts entities.PodmanConfig) (entities.ContainerEngine, error) {
switch facts.EngineMode {
case entities.ABIMode:
return nil, fmt.Errorf("direct runtime not supported")
@@ -23,7 +23,7 @@ func NewContainerEngine(facts entities.EngineOptions) (entities.ContainerEngine,
}
// NewImageEngine factory provides a libpod runtime for image-related operations
-func NewImageEngine(facts entities.EngineOptions) (entities.ImageEngine, error) {
+func NewImageEngine(facts entities.PodmanConfig) (entities.ImageEngine, error) {
switch facts.EngineMode {
case entities.ABIMode:
return nil, fmt.Errorf("direct image runtime not supported")
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index f59d4eb0a..05b62efcf 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -5,6 +5,7 @@ import (
"io"
"os"
+ "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/bindings/containers"
@@ -362,3 +363,7 @@ func (ic *ContainerEngine) ContainerMount(ctx context.Context, nameOrIds []strin
func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIds []string, options entities.ContainerUnmountOptions) ([]*entities.ContainerUnmountReport, error) {
return nil, errors.New("unmounting containers is not supported for remote clients")
}
+
+func (ic *ContainerEngine) Config(_ context.Context) (*config.Config, error) {
+ return config.Default()
+}
diff --git a/pkg/domain/infra/tunnel/events.go b/pkg/domain/infra/tunnel/events.go
new file mode 100644
index 000000000..46d88341a
--- /dev/null
+++ b/pkg/domain/infra/tunnel/events.go
@@ -0,0 +1,31 @@
+package tunnel
+
+import (
+ "context"
+ "strings"
+
+ "github.com/containers/libpod/pkg/api/handlers"
+ "github.com/containers/libpod/pkg/bindings/system"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+)
+
+func (ic *ContainerEngine) Events(ctx context.Context, opts entities.EventsOptions) error {
+ filters := make(map[string][]string)
+ if len(opts.Filter) > 0 {
+ for _, filter := range opts.Filter {
+ split := strings.Split(filter, "=")
+ if len(split) < 2 {
+ return errors.Errorf("invalid filter %q", filter)
+ }
+ filters[split[0]] = append(filters[split[0]], strings.Join(split[1:], "="))
+ }
+ }
+ binChan := make(chan handlers.Event)
+ go func() {
+ for e := range binChan {
+ opts.EventChan <- e.ToLibpodEvent()
+ }
+ }()
+ return system.Events(ic.ClientCxt, binChan, nil, &opts.Since, &opts.Until, filters)
+}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 54f2e8334..7d40e0327 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
+ "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
images "github.com/containers/libpod/pkg/bindings/images"
"github.com/containers/libpod/pkg/domain/entities"
@@ -254,3 +255,7 @@ func (ir *ImageEngine) Diff(ctx context.Context, nameOrId string, _ entities.Dif
func (ir *ImageEngine) Search(ctx context.Context, term string, opts entities.ImageSearchOptions) ([]entities.ImageSearchReport, error) {
return images.Search(ir.ClientCxt, term, opts)
}
+
+func (ir *ImageEngine) Config(_ context.Context) (*config.Config, error) {
+ return config.Default()
+}
diff --git a/pkg/specgen/config_linux_nocgo.go b/pkg/specgen/config_linux_nocgo.go
deleted file mode 100644
index fc0c58c37..000000000
--- a/pkg/specgen/config_linux_nocgo.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// +build linux,!cgo
-
-package specgen
-
-import (
- spec "github.com/opencontainers/runtime-spec/specs-go"
-)
-
-func (s *SpecGenerator) getSeccompConfig(configSpec *spec.Spec) (*spec.LinuxSeccomp, error) {
- return nil, nil
-}
diff --git a/pkg/specgen/config_linux_cgo.go b/pkg/specgen/generate/config_linux_cgo.go
index ef6c6e951..b06ef5c9a 100644
--- a/pkg/specgen/config_linux_cgo.go
+++ b/pkg/specgen/generate/config_linux_cgo.go
@@ -1,6 +1,6 @@
// +build linux,cgo
-package specgen
+package generate
import (
"context"
@@ -8,13 +8,14 @@ import (
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/seccomp"
+ "github.com/containers/libpod/pkg/specgen"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
goSeccomp "github.com/seccomp/containers-golang"
"github.com/sirupsen/logrus"
)
-func (s *SpecGenerator) getSeccompConfig(configSpec *spec.Spec, img *image.Image) (*spec.LinuxSeccomp, error) {
+func getSeccompConfig(s *specgen.SpecGenerator, configSpec *spec.Spec, img *image.Image) (*spec.LinuxSeccomp, error) {
var seccompConfig *spec.LinuxSeccomp
var err error
scp, err := seccomp.LookupPolicy(s.SeccompPolicy)
diff --git a/pkg/specgen/generate/config_linux_nocgo.go b/pkg/specgen/generate/config_linux_nocgo.go
new file mode 100644
index 000000000..fc8ed206d
--- /dev/null
+++ b/pkg/specgen/generate/config_linux_nocgo.go
@@ -0,0 +1,14 @@
+// +build linux,!cgo
+
+package generate
+
+import (
+ "errors"
+
+ "github.com/containers/libpod/pkg/specgen"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+)
+
+func (s *specgen.SpecGenerator) getSeccompConfig(configSpec *spec.Spec) (*spec.LinuxSeccomp, error) {
+ return nil, errors.New("not implemented")
+}
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index aad59a861..264e0ff8e 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -40,7 +40,7 @@ func MakeContainer(rt *libpod.Runtime, s *specgen.SpecGenerator) (*libpod.Contai
options = append(options, libpod.WithRootFSFromImage(newImage.ID(), s.Image, s.RawImageName))
- runtimeSpec, err := s.ToOCISpec(rt, newImage)
+ runtimeSpec, err := SpecGenToOCI(s, rt, newImage)
if err != nil {
return nil, err
}
@@ -80,7 +80,15 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator) ([]lib
options = append(options, libpod.WithUserVolumes(destinations))
if len(s.Volumes) != 0 {
- options = append(options, libpod.WithNamedVolumes(s.Volumes))
+ var volumes []*libpod.ContainerNamedVolume
+ for _, v := range s.Volumes {
+ volumes = append(volumes, &libpod.ContainerNamedVolume{
+ Name: v.Name,
+ Dest: v.Dest,
+ Options: v.Options,
+ })
+ }
+ options = append(options, libpod.WithNamedVolumes(volumes))
}
if len(s.Command) != 0 {
@@ -115,7 +123,7 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator) ([]lib
options = append(options, libpod.WithPrivileged(s.Privileged))
// Get namespace related options
- namespaceOptions, err := s.GenerateNamespaceContainerOpts(rt)
+ namespaceOptions, err := GenerateNamespaceContainerOpts(s, rt)
if err != nil {
return nil, err
}
diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go
new file mode 100644
index 000000000..cdd7d86da
--- /dev/null
+++ b/pkg/specgen/generate/namespaces.go
@@ -0,0 +1,417 @@
+package generate
+
+import (
+ "os"
+
+ "github.com/containers/common/pkg/capabilities"
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/specgen"
+ "github.com/cri-o/ocicni/pkg/ocicni"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-tools/generate"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+func GenerateNamespaceContainerOpts(s *specgen.SpecGenerator, rt *libpod.Runtime) ([]libpod.CtrCreateOption, error) {
+ var portBindings []ocicni.PortMapping
+ options := make([]libpod.CtrCreateOption, 0)
+
+ // Cgroups
+ switch {
+ case s.CgroupNS.IsPrivate():
+ ns := s.CgroupNS.Value
+ if _, err := os.Stat(ns); err != nil {
+ return nil, err
+ }
+ case s.CgroupNS.IsContainer():
+ connectedCtr, err := rt.LookupContainer(s.CgroupNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", s.CgroupNS.Value)
+ }
+ options = append(options, libpod.WithCgroupNSFrom(connectedCtr))
+ // TODO
+ //default:
+ // return nil, errors.New("cgroup name only supports private and container")
+ }
+
+ if s.CgroupParent != "" {
+ options = append(options, libpod.WithCgroupParent(s.CgroupParent))
+ }
+
+ if s.CgroupsMode != "" {
+ options = append(options, libpod.WithCgroupsMode(s.CgroupsMode))
+ }
+
+ // ipc
+ switch {
+ case s.IpcNS.IsHost():
+ options = append(options, libpod.WithShmDir("/dev/shm"))
+ case s.IpcNS.IsContainer():
+ connectedCtr, err := rt.LookupContainer(s.IpcNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", s.IpcNS.Value)
+ }
+ options = append(options, libpod.WithIPCNSFrom(connectedCtr))
+ options = append(options, libpod.WithShmDir(connectedCtr.ShmDir()))
+ }
+
+ // pid
+ if s.PidNS.IsContainer() {
+ connectedCtr, err := rt.LookupContainer(s.PidNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", s.PidNS.Value)
+ }
+ options = append(options, libpod.WithPIDNSFrom(connectedCtr))
+ }
+
+ // uts
+ switch {
+ case s.UtsNS.IsPod():
+ connectedPod, err := rt.LookupPod(s.UtsNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "pod %q not found", s.UtsNS.Value)
+ }
+ options = append(options, libpod.WithUTSNSFromPod(connectedPod))
+ case s.UtsNS.IsContainer():
+ connectedCtr, err := rt.LookupContainer(s.UtsNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", s.UtsNS.Value)
+ }
+
+ options = append(options, libpod.WithUTSNSFrom(connectedCtr))
+ }
+
+ if s.UseImageHosts {
+ options = append(options, libpod.WithUseImageHosts())
+ } else if len(s.HostAdd) > 0 {
+ options = append(options, libpod.WithHosts(s.HostAdd))
+ }
+
+ // User
+
+ switch {
+ case s.UserNS.IsPath():
+ ns := s.UserNS.Value
+ if ns == "" {
+ return nil, errors.Errorf("invalid empty user-defined user namespace")
+ }
+ _, err := os.Stat(ns)
+ if err != nil {
+ return nil, err
+ }
+ if s.IDMappings != nil {
+ options = append(options, libpod.WithIDMappings(*s.IDMappings))
+ }
+ case s.UserNS.IsContainer():
+ connectedCtr, err := rt.LookupContainer(s.UserNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", s.UserNS.Value)
+ }
+ options = append(options, libpod.WithUserNSFrom(connectedCtr))
+ default:
+ if s.IDMappings != nil {
+ options = append(options, libpod.WithIDMappings(*s.IDMappings))
+ }
+ }
+
+ options = append(options, libpod.WithUser(s.User))
+ options = append(options, libpod.WithGroups(s.Groups))
+
+ if len(s.PortMappings) > 0 {
+ portBindings = s.PortMappings
+ }
+
+ switch {
+ case s.NetNS.IsPath():
+ ns := s.NetNS.Value
+ if ns == "" {
+ return nil, errors.Errorf("invalid empty user-defined network namespace")
+ }
+ _, err := os.Stat(ns)
+ if err != nil {
+ return nil, err
+ }
+ case s.NetNS.IsContainer():
+ connectedCtr, err := rt.LookupContainer(s.NetNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", s.NetNS.Value)
+ }
+ options = append(options, libpod.WithNetNSFrom(connectedCtr))
+ case !s.NetNS.IsHost() && s.NetNS.NSMode != specgen.NoNetwork:
+ postConfigureNetNS := !s.UserNS.IsHost()
+ options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, string(s.NetNS.NSMode), s.CNINetworks))
+ }
+
+ if len(s.DNSSearch) > 0 {
+ options = append(options, libpod.WithDNSSearch(s.DNSSearch))
+ }
+ if len(s.DNSServer) > 0 {
+ // TODO I'm not sure how we are going to handle this given the input
+ if len(s.DNSServer) == 1 { //&& strings.ToLower(s.DNSServer[0].) == "none" {
+ options = append(options, libpod.WithUseImageResolvConf())
+ } else {
+ var dnsServers []string
+ for _, d := range s.DNSServer {
+ dnsServers = append(dnsServers, d.String())
+ }
+ options = append(options, libpod.WithDNS(dnsServers))
+ }
+ }
+ if len(s.DNSOption) > 0 {
+ options = append(options, libpod.WithDNSOption(s.DNSOption))
+ }
+ if s.StaticIP != nil {
+ options = append(options, libpod.WithStaticIP(*s.StaticIP))
+ }
+
+ if s.StaticMAC != nil {
+ options = append(options, libpod.WithStaticMAC(*s.StaticMAC))
+ }
+ return options, nil
+}
+
+func pidConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator) error {
+ if s.PidNS.IsPath() {
+ return g.AddOrReplaceLinuxNamespace(string(spec.PIDNamespace), s.PidNS.Value)
+ }
+ if s.PidNS.IsHost() {
+ return g.RemoveLinuxNamespace(string(spec.PIDNamespace))
+ }
+ if s.PidNS.IsContainer() {
+ logrus.Debugf("using container %s pidmode", s.PidNS.Value)
+ }
+ if s.PidNS.IsPod() {
+ logrus.Debug("using pod pidmode")
+ }
+ return nil
+}
+
+func utsConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, runtime *libpod.Runtime) error {
+ hostname := s.Hostname
+ var err error
+ if hostname == "" {
+ switch {
+ case s.UtsNS.IsContainer():
+ utsCtr, err := runtime.LookupContainer(s.UtsNS.Value)
+ if err != nil {
+ return errors.Wrapf(err, "unable to retrieve hostname from dependency container %s", s.UtsNS.Value)
+ }
+ hostname = utsCtr.Hostname()
+ case s.NetNS.IsHost() || s.UtsNS.IsHost():
+ hostname, err = os.Hostname()
+ if err != nil {
+ return errors.Wrap(err, "unable to retrieve hostname of the host")
+ }
+ default:
+ logrus.Debug("No hostname set; container's hostname will default to runtime default")
+ }
+ }
+ g.RemoveHostname()
+ if s.Hostname != "" || !s.UtsNS.IsHost() {
+ // Set the hostname in the OCI configuration only
+ // if specified by the user or if we are creating
+ // a new UTS namespace.
+ g.SetHostname(hostname)
+ }
+ g.AddProcessEnv("HOSTNAME", hostname)
+
+ if s.UtsNS.IsPath() {
+ return g.AddOrReplaceLinuxNamespace(string(spec.UTSNamespace), s.UtsNS.Value)
+ }
+ if s.UtsNS.IsHost() {
+ return g.RemoveLinuxNamespace(string(spec.UTSNamespace))
+ }
+ if s.UtsNS.IsContainer() {
+ logrus.Debugf("using container %s utsmode", s.UtsNS.Value)
+ }
+ return nil
+}
+
+func ipcConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator) error {
+ if s.IpcNS.IsPath() {
+ return g.AddOrReplaceLinuxNamespace(string(spec.IPCNamespace), s.IpcNS.Value)
+ }
+ if s.IpcNS.IsHost() {
+ return g.RemoveLinuxNamespace(s.IpcNS.Value)
+ }
+ if s.IpcNS.IsContainer() {
+ logrus.Debugf("Using container %s ipcmode", s.IpcNS.Value)
+ }
+ return nil
+}
+
+func cgroupConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator) error {
+ if s.CgroupNS.IsPath() {
+ return g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), s.CgroupNS.Value)
+ }
+ if s.CgroupNS.IsHost() {
+ return g.RemoveLinuxNamespace(s.CgroupNS.Value)
+ }
+ if s.CgroupNS.IsPrivate() {
+ return g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), "")
+ }
+ if s.CgroupNS.IsContainer() {
+ logrus.Debugf("Using container %s cgroup mode", s.CgroupNS.Value)
+ }
+ return nil
+}
+
+func networkConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator) error {
+ switch {
+ case s.NetNS.IsHost():
+ logrus.Debug("Using host netmode")
+ if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil {
+ return err
+ }
+
+ case s.NetNS.NSMode == specgen.NoNetwork:
+ logrus.Debug("Using none netmode")
+ case s.NetNS.NSMode == specgen.Bridge:
+ logrus.Debug("Using bridge netmode")
+ case s.NetNS.IsContainer():
+ logrus.Debugf("using container %s netmode", s.NetNS.Value)
+ case s.NetNS.IsPath():
+ logrus.Debug("Using ns netmode")
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), s.NetNS.Value); err != nil {
+ return err
+ }
+ case s.NetNS.IsPod():
+ logrus.Debug("Using pod netmode, unless pod is not sharing")
+ case s.NetNS.NSMode == specgen.Slirp:
+ logrus.Debug("Using slirp4netns netmode")
+ default:
+ return errors.Errorf("unknown network mode")
+ }
+
+ if g.Config.Annotations == nil {
+ g.Config.Annotations = make(map[string]string)
+ }
+
+ if s.PublishImagePorts {
+ g.Config.Annotations[libpod.InspectAnnotationPublishAll] = libpod.InspectResponseTrue
+ } else {
+ g.Config.Annotations[libpod.InspectAnnotationPublishAll] = libpod.InspectResponseFalse
+ }
+
+ return nil
+}
+
+func userConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator) error {
+ if s.UserNS.IsPath() {
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), s.UserNS.Value); err != nil {
+ return err
+ }
+ // runc complains if no mapping is specified, even if we join another ns. So provide a dummy mapping
+ g.AddLinuxUIDMapping(uint32(0), uint32(0), uint32(1))
+ g.AddLinuxGIDMapping(uint32(0), uint32(0), uint32(1))
+ }
+
+ if s.IDMappings != nil {
+ if (len(s.IDMappings.UIDMap) > 0 || len(s.IDMappings.GIDMap) > 0) && !s.UserNS.IsHost() {
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), ""); err != nil {
+ return err
+ }
+ }
+ for _, uidmap := range s.IDMappings.UIDMap {
+ g.AddLinuxUIDMapping(uint32(uidmap.HostID), uint32(uidmap.ContainerID), uint32(uidmap.Size))
+ }
+ for _, gidmap := range s.IDMappings.GIDMap {
+ g.AddLinuxGIDMapping(uint32(gidmap.HostID), uint32(gidmap.ContainerID), uint32(gidmap.Size))
+ }
+ }
+ return nil
+}
+
+func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, newImage *image.Image) error {
+ // HANDLE CAPABILITIES
+ // NOTE: Must happen before SECCOMP
+ if s.Privileged {
+ g.SetupPrivileged(true)
+ }
+
+ useNotRoot := func(user string) bool {
+ if user == "" || user == "root" || user == "0" {
+ return false
+ }
+ return true
+ }
+ configSpec := g.Config
+ var err error
+ var caplist []string
+ bounding := configSpec.Process.Capabilities.Bounding
+ if useNotRoot(s.User) {
+ configSpec.Process.Capabilities.Bounding = caplist
+ }
+ caplist, err = capabilities.MergeCapabilities(configSpec.Process.Capabilities.Bounding, s.CapAdd, s.CapDrop)
+ if err != nil {
+ return err
+ }
+
+ configSpec.Process.Capabilities.Bounding = caplist
+ configSpec.Process.Capabilities.Permitted = caplist
+ configSpec.Process.Capabilities.Inheritable = caplist
+ configSpec.Process.Capabilities.Effective = caplist
+ configSpec.Process.Capabilities.Ambient = caplist
+ if useNotRoot(s.User) {
+ caplist, err = capabilities.MergeCapabilities(bounding, s.CapAdd, s.CapDrop)
+ if err != nil {
+ return err
+ }
+ }
+ configSpec.Process.Capabilities.Bounding = caplist
+
+ // HANDLE SECCOMP
+ if s.SeccompProfilePath != "unconfined" {
+ seccompConfig, err := getSeccompConfig(s, configSpec, newImage)
+ if err != nil {
+ return err
+ }
+ configSpec.Linux.Seccomp = seccompConfig
+ }
+
+ // Clear default Seccomp profile from Generator for privileged containers
+ if s.SeccompProfilePath == "unconfined" || s.Privileged {
+ configSpec.Linux.Seccomp = nil
+ }
+
+ g.SetRootReadonly(s.ReadOnlyFilesystem)
+ for sysctlKey, sysctlVal := range s.Sysctl {
+ g.AddLinuxSysctl(sysctlKey, sysctlVal)
+ }
+
+ return nil
+}
+
+// GetNamespaceOptions transforms a slice of kernel namespaces
+// into a slice of pod create options. Currently, not all
+// kernel namespaces are supported, and they will be returned in an error
+func GetNamespaceOptions(ns []string) ([]libpod.PodCreateOption, error) {
+ var options []libpod.PodCreateOption
+ var erroredOptions []libpod.PodCreateOption
+ for _, toShare := range ns {
+ switch toShare {
+ case "cgroup":
+ options = append(options, libpod.WithPodCgroups())
+ case "net":
+ options = append(options, libpod.WithPodNet())
+ case "mnt":
+ return erroredOptions, errors.Errorf("Mount sharing functionality not supported on pod level")
+ case "pid":
+ options = append(options, libpod.WithPodPID())
+ case "user":
+ return erroredOptions, errors.Errorf("User sharing functionality not supported on pod level")
+ case "ipc":
+ options = append(options, libpod.WithPodIPC())
+ case "uts":
+ options = append(options, libpod.WithPodUTS())
+ case "":
+ case "none":
+ return erroredOptions, nil
+ default:
+ return erroredOptions, errors.Errorf("Invalid kernel namespace to share: %s. Options are: net, pid, ipc, uts or none", toShare)
+ }
+ }
+ return options, nil
+}
diff --git a/pkg/specgen/oci.go b/pkg/specgen/generate/oci.go
index 0756782b4..4bc4d2327 100644
--- a/pkg/specgen/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -1,4 +1,4 @@
-package specgen
+package generate
import (
"strings"
@@ -7,11 +7,12 @@ import (
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/rootless"
createconfig "github.com/containers/libpod/pkg/spec"
+ "github.com/containers/libpod/pkg/specgen"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
)
-func (s *SpecGenerator) ToOCISpec(rt *libpod.Runtime, newImage *image.Image) (*spec.Spec, error) {
+func SpecGenToOCI(s *specgen.SpecGenerator, rt *libpod.Runtime, newImage *image.Image) (*spec.Spec, error) {
var (
inUserNS bool
)
@@ -183,32 +184,32 @@ func (s *SpecGenerator) ToOCISpec(rt *libpod.Runtime, newImage *image.Image) (*s
// NAMESPACES
- if err := s.pidConfigureGenerator(&g); err != nil {
+ if err := pidConfigureGenerator(s, &g); err != nil {
return nil, err
}
- if err := s.userConfigureGenerator(&g); err != nil {
+ if err := userConfigureGenerator(s, &g); err != nil {
return nil, err
}
- if err := s.networkConfigureGenerator(&g); err != nil {
+ if err := networkConfigureGenerator(s, &g); err != nil {
return nil, err
}
- if err := s.utsConfigureGenerator(&g, rt); err != nil {
+ if err := utsConfigureGenerator(s, &g, rt); err != nil {
return nil, err
}
- if err := s.ipcConfigureGenerator(&g); err != nil {
+ if err := ipcConfigureGenerator(s, &g); err != nil {
return nil, err
}
- if err := s.cgroupConfigureGenerator(&g); err != nil {
+ if err := cgroupConfigureGenerator(s, &g); err != nil {
return nil, err
}
configSpec := g.Config
- if err := s.securityConfigureGenerator(&g, newImage); err != nil {
+ if err := securityConfigureGenerator(s, &g, newImage); err != nil {
return nil, err
}
diff --git a/pkg/specgen/pod_create.go b/pkg/specgen/generate/pod_create.go
index 06aa24e22..292f9b155 100644
--- a/pkg/specgen/pod_create.go
+++ b/pkg/specgen/generate/pod_create.go
@@ -1,31 +1,31 @@
-package specgen
+package generate
import (
"context"
- "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/specgen"
"github.com/sirupsen/logrus"
)
-func (p *PodSpecGenerator) MakePod(rt *libpod.Runtime) (*libpod.Pod, error) {
- if err := p.validate(); err != nil {
+func MakePod(p *specgen.PodSpecGenerator, rt *libpod.Runtime) (*libpod.Pod, error) {
+ if err := p.Validate(); err != nil {
return nil, err
}
- options, err := p.createPodOptions()
+ options, err := createPodOptions(p)
if err != nil {
return nil, err
}
return rt.NewPod(context.Background(), options...)
}
-func (p *PodSpecGenerator) createPodOptions() ([]libpod.PodCreateOption, error) {
+func createPodOptions(p *specgen.PodSpecGenerator) ([]libpod.PodCreateOption, error) {
var (
options []libpod.PodCreateOption
)
if !p.NoInfra {
options = append(options, libpod.WithInfraContainer())
- nsOptions, err := shared.GetNamespaceOptions(p.SharedNamespaces)
+ nsOptions, err := GetNamespaceOptions(p.SharedNamespaces)
if err != nil {
return nil, err
}
@@ -62,9 +62,9 @@ func (p *PodSpecGenerator) createPodOptions() ([]libpod.PodCreateOption, error)
options = append(options, libpod.WithPodUseImageResolvConf())
}
switch p.NetNS.NSMode {
- case Bridge:
+ case specgen.Bridge:
logrus.Debugf("Pod using default network mode")
- case Host:
+ case specgen.Host:
logrus.Debugf("Pod will use host networking")
options = append(options, libpod.WithPodHostNetwork())
default:
diff --git a/pkg/specgen/storage.go b/pkg/specgen/generate/storage.go
index 1b903f608..c9a36ed46 100644
--- a/pkg/specgen/storage.go
+++ b/pkg/specgen/generate/storage.go
@@ -1,4 +1,4 @@
-package specgen
+package generate
//nolint
@@ -8,9 +8,9 @@ import (
"path/filepath"
"strings"
- "github.com/containers/libpod/libpod"
-
"github.com/containers/buildah/pkg/parse"
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/specgen"
"github.com/containers/libpod/pkg/util"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
@@ -38,7 +38,7 @@ var (
// TODO: Named volume options - should we default to rprivate? It bakes into a
// bind mount under the hood...
// TODO: handle options parsing/processing via containers/storage/pkg/mount
-func (s *SpecGenerator) parseVolumes(mounts, volMounts, tmpMounts []string) error { //nolint
+func parseVolumes(s *specgen.SpecGenerator, mounts, volMounts, tmpMounts []string) error { //nolint
// TODO this needs to come from the image and erquires a runtime
diff --git a/pkg/specgen/namespaces.go b/pkg/specgen/namespaces.go
index 2a7bb3495..2ef5bc229 100644
--- a/pkg/specgen/namespaces.go
+++ b/pkg/specgen/namespaces.go
@@ -1,16 +1,7 @@
package specgen
import (
- "os"
-
- "github.com/containers/common/pkg/capabilities"
- "github.com/containers/libpod/libpod"
- "github.com/containers/libpod/libpod/image"
- "github.com/cri-o/ocicni/pkg/ocicni"
- spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/opencontainers/runtime-tools/generate"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
)
type NamespaceMode string
@@ -105,373 +96,3 @@ func (n *Namespace) validate() error {
}
return nil
}
-
-func (s *SpecGenerator) GenerateNamespaceContainerOpts(rt *libpod.Runtime) ([]libpod.CtrCreateOption, error) {
- var portBindings []ocicni.PortMapping
- options := make([]libpod.CtrCreateOption, 0)
-
- // Cgroups
- switch {
- case s.CgroupNS.IsPrivate():
- ns := s.CgroupNS.Value
- if _, err := os.Stat(ns); err != nil {
- return nil, err
- }
- case s.CgroupNS.IsContainer():
- connectedCtr, err := rt.LookupContainer(s.CgroupNS.Value)
- if err != nil {
- return nil, errors.Wrapf(err, "container %q not found", s.CgroupNS.Value)
- }
- options = append(options, libpod.WithCgroupNSFrom(connectedCtr))
- // TODO
- //default:
- // return nil, errors.New("cgroup name only supports private and container")
- }
-
- if s.CgroupParent != "" {
- options = append(options, libpod.WithCgroupParent(s.CgroupParent))
- }
-
- if s.CgroupsMode != "" {
- options = append(options, libpod.WithCgroupsMode(s.CgroupsMode))
- }
-
- // ipc
- switch {
- case s.IpcNS.IsHost():
- options = append(options, libpod.WithShmDir("/dev/shm"))
- case s.IpcNS.IsContainer():
- connectedCtr, err := rt.LookupContainer(s.IpcNS.Value)
- if err != nil {
- return nil, errors.Wrapf(err, "container %q not found", s.IpcNS.Value)
- }
- options = append(options, libpod.WithIPCNSFrom(connectedCtr))
- options = append(options, libpod.WithShmDir(connectedCtr.ShmDir()))
- }
-
- // pid
- if s.PidNS.IsContainer() {
- connectedCtr, err := rt.LookupContainer(s.PidNS.Value)
- if err != nil {
- return nil, errors.Wrapf(err, "container %q not found", s.PidNS.Value)
- }
- options = append(options, libpod.WithPIDNSFrom(connectedCtr))
- }
-
- // uts
- switch {
- case s.UtsNS.IsPod():
- connectedPod, err := rt.LookupPod(s.UtsNS.Value)
- if err != nil {
- return nil, errors.Wrapf(err, "pod %q not found", s.UtsNS.Value)
- }
- options = append(options, libpod.WithUTSNSFromPod(connectedPod))
- case s.UtsNS.IsContainer():
- connectedCtr, err := rt.LookupContainer(s.UtsNS.Value)
- if err != nil {
- return nil, errors.Wrapf(err, "container %q not found", s.UtsNS.Value)
- }
-
- options = append(options, libpod.WithUTSNSFrom(connectedCtr))
- }
-
- if s.UseImageHosts {
- options = append(options, libpod.WithUseImageHosts())
- } else if len(s.HostAdd) > 0 {
- options = append(options, libpod.WithHosts(s.HostAdd))
- }
-
- // User
-
- switch {
- case s.UserNS.IsPath():
- ns := s.UserNS.Value
- if ns == "" {
- return nil, errors.Errorf("invalid empty user-defined user namespace")
- }
- _, err := os.Stat(ns)
- if err != nil {
- return nil, err
- }
- if s.IDMappings != nil {
- options = append(options, libpod.WithIDMappings(*s.IDMappings))
- }
- case s.UserNS.IsContainer():
- connectedCtr, err := rt.LookupContainer(s.UserNS.Value)
- if err != nil {
- return nil, errors.Wrapf(err, "container %q not found", s.UserNS.Value)
- }
- options = append(options, libpod.WithUserNSFrom(connectedCtr))
- default:
- if s.IDMappings != nil {
- options = append(options, libpod.WithIDMappings(*s.IDMappings))
- }
- }
-
- options = append(options, libpod.WithUser(s.User))
- options = append(options, libpod.WithGroups(s.Groups))
-
- if len(s.PortMappings) > 0 {
- portBindings = s.PortMappings
- }
-
- switch {
- case s.NetNS.IsPath():
- ns := s.NetNS.Value
- if ns == "" {
- return nil, errors.Errorf("invalid empty user-defined network namespace")
- }
- _, err := os.Stat(ns)
- if err != nil {
- return nil, err
- }
- case s.NetNS.IsContainer():
- connectedCtr, err := rt.LookupContainer(s.NetNS.Value)
- if err != nil {
- return nil, errors.Wrapf(err, "container %q not found", s.NetNS.Value)
- }
- options = append(options, libpod.WithNetNSFrom(connectedCtr))
- case !s.NetNS.IsHost() && s.NetNS.NSMode != NoNetwork:
- postConfigureNetNS := !s.UserNS.IsHost()
- options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, string(s.NetNS.NSMode), s.CNINetworks))
- }
-
- if len(s.DNSSearch) > 0 {
- options = append(options, libpod.WithDNSSearch(s.DNSSearch))
- }
- if len(s.DNSServer) > 0 {
- // TODO I'm not sure how we are going to handle this given the input
- if len(s.DNSServer) == 1 { //&& strings.ToLower(s.DNSServer[0].) == "none" {
- options = append(options, libpod.WithUseImageResolvConf())
- } else {
- var dnsServers []string
- for _, d := range s.DNSServer {
- dnsServers = append(dnsServers, d.String())
- }
- options = append(options, libpod.WithDNS(dnsServers))
- }
- }
- if len(s.DNSOption) > 0 {
- options = append(options, libpod.WithDNSOption(s.DNSOption))
- }
- if s.StaticIP != nil {
- options = append(options, libpod.WithStaticIP(*s.StaticIP))
- }
-
- if s.StaticMAC != nil {
- options = append(options, libpod.WithStaticMAC(*s.StaticMAC))
- }
- return options, nil
-}
-
-func (s *SpecGenerator) pidConfigureGenerator(g *generate.Generator) error {
- if s.PidNS.IsPath() {
- return g.AddOrReplaceLinuxNamespace(string(spec.PIDNamespace), s.PidNS.Value)
- }
- if s.PidNS.IsHost() {
- return g.RemoveLinuxNamespace(string(spec.PIDNamespace))
- }
- if s.PidNS.IsContainer() {
- logrus.Debugf("using container %s pidmode", s.PidNS.Value)
- }
- if s.PidNS.IsPod() {
- logrus.Debug("using pod pidmode")
- }
- return nil
-}
-
-func (s *SpecGenerator) utsConfigureGenerator(g *generate.Generator, runtime *libpod.Runtime) error {
- hostname := s.Hostname
- var err error
- if hostname == "" {
- switch {
- case s.UtsNS.IsContainer():
- utsCtr, err := runtime.LookupContainer(s.UtsNS.Value)
- if err != nil {
- return errors.Wrapf(err, "unable to retrieve hostname from dependency container %s", s.UtsNS.Value)
- }
- hostname = utsCtr.Hostname()
- case s.NetNS.IsHost() || s.UtsNS.IsHost():
- hostname, err = os.Hostname()
- if err != nil {
- return errors.Wrap(err, "unable to retrieve hostname of the host")
- }
- default:
- logrus.Debug("No hostname set; container's hostname will default to runtime default")
- }
- }
- g.RemoveHostname()
- if s.Hostname != "" || !s.UtsNS.IsHost() {
- // Set the hostname in the OCI configuration only
- // if specified by the user or if we are creating
- // a new UTS namespace.
- g.SetHostname(hostname)
- }
- g.AddProcessEnv("HOSTNAME", hostname)
-
- if s.UtsNS.IsPath() {
- return g.AddOrReplaceLinuxNamespace(string(spec.UTSNamespace), s.UtsNS.Value)
- }
- if s.UtsNS.IsHost() {
- return g.RemoveLinuxNamespace(string(spec.UTSNamespace))
- }
- if s.UtsNS.IsContainer() {
- logrus.Debugf("using container %s utsmode", s.UtsNS.Value)
- }
- return nil
-}
-
-func (s *SpecGenerator) ipcConfigureGenerator(g *generate.Generator) error {
- if s.IpcNS.IsPath() {
- return g.AddOrReplaceLinuxNamespace(string(spec.IPCNamespace), s.IpcNS.Value)
- }
- if s.IpcNS.IsHost() {
- return g.RemoveLinuxNamespace(s.IpcNS.Value)
- }
- if s.IpcNS.IsContainer() {
- logrus.Debugf("Using container %s ipcmode", s.IpcNS.Value)
- }
- return nil
-}
-
-func (s *SpecGenerator) cgroupConfigureGenerator(g *generate.Generator) error {
- if s.CgroupNS.IsPath() {
- return g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), s.CgroupNS.Value)
- }
- if s.CgroupNS.IsHost() {
- return g.RemoveLinuxNamespace(s.CgroupNS.Value)
- }
- if s.CgroupNS.IsPrivate() {
- return g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), "")
- }
- if s.CgroupNS.IsContainer() {
- logrus.Debugf("Using container %s cgroup mode", s.CgroupNS.Value)
- }
- return nil
-}
-
-func (s *SpecGenerator) networkConfigureGenerator(g *generate.Generator) error {
- switch {
- case s.NetNS.IsHost():
- logrus.Debug("Using host netmode")
- if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil {
- return err
- }
-
- case s.NetNS.NSMode == NoNetwork:
- logrus.Debug("Using none netmode")
- case s.NetNS.NSMode == Bridge:
- logrus.Debug("Using bridge netmode")
- case s.NetNS.IsContainer():
- logrus.Debugf("using container %s netmode", s.NetNS.Value)
- case s.NetNS.IsPath():
- logrus.Debug("Using ns netmode")
- if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), s.NetNS.Value); err != nil {
- return err
- }
- case s.NetNS.IsPod():
- logrus.Debug("Using pod netmode, unless pod is not sharing")
- case s.NetNS.NSMode == Slirp:
- logrus.Debug("Using slirp4netns netmode")
- default:
- return errors.Errorf("unknown network mode")
- }
-
- if g.Config.Annotations == nil {
- g.Config.Annotations = make(map[string]string)
- }
-
- if s.PublishImagePorts {
- g.Config.Annotations[libpod.InspectAnnotationPublishAll] = libpod.InspectResponseTrue
- } else {
- g.Config.Annotations[libpod.InspectAnnotationPublishAll] = libpod.InspectResponseFalse
- }
-
- return nil
-}
-
-func (s *SpecGenerator) userConfigureGenerator(g *generate.Generator) error {
- if s.UserNS.IsPath() {
- if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), s.UserNS.Value); err != nil {
- return err
- }
- // runc complains if no mapping is specified, even if we join another ns. So provide a dummy mapping
- g.AddLinuxUIDMapping(uint32(0), uint32(0), uint32(1))
- g.AddLinuxGIDMapping(uint32(0), uint32(0), uint32(1))
- }
-
- if s.IDMappings != nil {
- if (len(s.IDMappings.UIDMap) > 0 || len(s.IDMappings.GIDMap) > 0) && !s.UserNS.IsHost() {
- if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), ""); err != nil {
- return err
- }
- }
- for _, uidmap := range s.IDMappings.UIDMap {
- g.AddLinuxUIDMapping(uint32(uidmap.HostID), uint32(uidmap.ContainerID), uint32(uidmap.Size))
- }
- for _, gidmap := range s.IDMappings.GIDMap {
- g.AddLinuxGIDMapping(uint32(gidmap.HostID), uint32(gidmap.ContainerID), uint32(gidmap.Size))
- }
- }
- return nil
-}
-
-func (s *SpecGenerator) securityConfigureGenerator(g *generate.Generator, newImage *image.Image) error {
- // HANDLE CAPABILITIES
- // NOTE: Must happen before SECCOMP
- if s.Privileged {
- g.SetupPrivileged(true)
- }
-
- useNotRoot := func(user string) bool {
- if user == "" || user == "root" || user == "0" {
- return false
- }
- return true
- }
- configSpec := g.Config
- var err error
- var caplist []string
- bounding := configSpec.Process.Capabilities.Bounding
- if useNotRoot(s.User) {
- configSpec.Process.Capabilities.Bounding = caplist
- }
- caplist, err = capabilities.MergeCapabilities(configSpec.Process.Capabilities.Bounding, s.CapAdd, s.CapDrop)
- if err != nil {
- return err
- }
-
- configSpec.Process.Capabilities.Bounding = caplist
- configSpec.Process.Capabilities.Permitted = caplist
- configSpec.Process.Capabilities.Inheritable = caplist
- configSpec.Process.Capabilities.Effective = caplist
- configSpec.Process.Capabilities.Ambient = caplist
- if useNotRoot(s.User) {
- caplist, err = capabilities.MergeCapabilities(bounding, s.CapAdd, s.CapDrop)
- if err != nil {
- return err
- }
- }
- configSpec.Process.Capabilities.Bounding = caplist
-
- // HANDLE SECCOMP
- if s.SeccompProfilePath != "unconfined" {
- seccompConfig, err := s.getSeccompConfig(configSpec, newImage)
- if err != nil {
- return err
- }
- configSpec.Linux.Seccomp = seccompConfig
- }
-
- // Clear default Seccomp profile from Generator for privileged containers
- if s.SeccompProfilePath == "unconfined" || s.Privileged {
- configSpec.Linux.Seccomp = nil
- }
-
- g.SetRootReadonly(s.ReadOnlyFilesystem)
- for sysctlKey, sysctlVal := range s.Sysctl {
- g.AddLinuxSysctl(sysctlKey, sysctlVal)
- }
-
- return nil
-}
diff --git a/pkg/specgen/pod_validate.go b/pkg/specgen/pod_validate.go
index 92026309f..9e9659fa9 100644
--- a/pkg/specgen/pod_validate.go
+++ b/pkg/specgen/pod_validate.go
@@ -15,7 +15,8 @@ func exclusivePodOptions(opt1, opt2 string) error {
return errors.Wrapf(ErrInvalidPodSpecConfig, "%s and %s are mutually exclusive pod options", opt1, opt2)
}
-func (p *PodSpecGenerator) validate() error {
+// Validate verifies the input is valid
+func (p *PodSpecGenerator) Validate() error {
// PodBasicConfig
if p.NoInfra {
if len(p.InfraCommand) > 0 {
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
index 2e6dd9c1d..8482ef2c9 100644
--- a/pkg/specgen/specgen.go
+++ b/pkg/specgen/specgen.go
@@ -4,8 +4,6 @@ import (
"net"
"syscall"
- "github.com/containers/libpod/libpod"
-
"github.com/containers/image/v5/manifest"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/storage"
@@ -174,7 +172,7 @@ type ContainerStorageConfig struct {
// These will supersede Image Volumes and VolumesFrom volumes where
// there are conflicts.
// Optional.
- Volumes []*libpod.ContainerNamedVolume `json:"volumes,omitempty"`
+ Volumes []*Volumes `json:"volumes,omitempty"`
// Devices are devices that will be added to the container.
// Optional.
Devices []spec.LinuxDevice `json:"devices,omitempty"`
@@ -403,6 +401,13 @@ type SpecGenerator struct {
ContainerHealthCheckConfig
}
+// Volumes is a temporary struct to hold input from the User
+type Volumes struct {
+ Name string
+ Dest string
+ Options []string
+}
+
// NewSpecGenerator returns a SpecGenerator struct given one of two mandatory inputs
func NewSpecGenerator(image string) *SpecGenerator {
networkConfig := ContainerNetworkConfig{
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index 372c7c53b..1051ed311 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -516,6 +516,8 @@ func ParseInputTime(inputTime string) (time.Time, error) {
}
// GetGlobalOpts checks all global flags and generates the command string
+// FIXME: Port input to config.Config
+// TODO: Is there a "better" way to reverse values to flags? This seems brittle.
func GetGlobalOpts(c *cliconfig.RunlabelValues) string {
globalFlags := map[string]bool{
"cgroup-manager": true, "cni-config-dir": true, "conmon": true, "default-mounts-file": true,
diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2
index b101be012..1af76b4be 100755
--- a/test/apiv2/test-apiv2
+++ b/test/apiv2/test-apiv2
@@ -355,7 +355,7 @@ done
if [ -n "$service_pid" ]; then
kill $service_pid
- wait -f $service_pid
+ wait $service_pid
fi
test_count=$(<$testcounter_file)
diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go
index b65db2722..ef21f1d9f 100644
--- a/vendor/github.com/containers/common/pkg/config/config.go
+++ b/vendor/github.com/containers/common/pkg/config/config.go
@@ -271,6 +271,10 @@ type EngineConfig struct {
// running containers without CGroups.
RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroupv2"`
+ // RuntimeSupportsKVM is a list of OCI runtimes that support
+ // KVM separation for conatainers.
+ RuntimeSupportsKVM []string `toml:"runtime_supports_kvm"`
+
// SetOptions contains a subset of config options. It's used to indicate if
// a given option has either been set by the user or by the parsed
// configuration file. If not, the corresponding option might be
diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf
index 067be429e..fbc691f1d 100644
--- a/vendor/github.com/containers/common/pkg/config/containers.conf
+++ b/vendor/github.com/containers/common/pkg/config/containers.conf
@@ -347,6 +347,14 @@
#
# runtime_supports_json = ["crun", "runc", "kata"]
+# List of the OCI runtimes that supports running containers without cgroups.
+#
+# runtime_supports_nocgroups = ["crun"]
+
+# List of the OCI runtimes that supports running containers with KVM Separation.
+#
+# runtime_supports_kvm = ["kata"]
+
# Paths to look for a valid OCI runtime (runc, runv, kata, etc)
[engine.runtimes]
# runc = [
@@ -376,6 +384,8 @@
# "/usr/local/sbin/kata-runtime",
# "/sbin/kata-runtime",
# "/bin/kata-runtime",
+# "/usr/bin/kata-qemu",
+# "/usr/bin/kata-fc",
# ]
# Number of seconds to wait for container to exit before sending kill signal.
diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go
index 78bfd8a28..5f3af1f8d 100644
--- a/vendor/github.com/containers/common/pkg/config/default.go
+++ b/vendor/github.com/containers/common/pkg/config/default.go
@@ -246,6 +246,8 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
"/usr/local/sbin/kata-runtime",
"/sbin/kata-runtime",
"/bin/kata-runtime",
+ "/usr/bin/kata-qemu",
+ "/usr/bin/kata-fc",
},
}
c.ConmonEnvVars = []string{
@@ -267,6 +269,7 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
"runc",
}
c.RuntimeSupportsNoCgroups = []string{"crun"}
+ c.RuntimeSupportsKVM = []string{"kata", "kata-runtime", "kata-qemu", "kata-fc"}
c.InitPath = DefaultInitPath
c.NoPivotRoot = false
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 535090e81..9aa167530 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -82,7 +82,7 @@ github.com/containers/buildah/pkg/secrets
github.com/containers/buildah/pkg/supplemented
github.com/containers/buildah/pkg/umask
github.com/containers/buildah/util
-# github.com/containers/common v0.8.1
+# github.com/containers/common v0.9.0
github.com/containers/common/pkg/apparmor
github.com/containers/common/pkg/capabilities
github.com/containers/common/pkg/cgroupv2
diff --git a/version/version.go b/version/version.go
index 06457e3ea..fe602d8e1 100644
--- a/version/version.go
+++ b/version/version.go
@@ -4,7 +4,7 @@ package version
// NOTE: remember to bump the version at the top
// of the top-level README.md file when this is
// bumped.
-const Version = "1.9.0-dev"
+const Version = "2.0.0-dev"
// RemoteAPIVersion is the version for the remote
// client API. It is used to determine compatibility