summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-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
33 files changed, 1062 insertions, 547 deletions
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,