summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/adapter/containers_remote.go31
-rw-r--r--pkg/adapter/pods.go173
-rw-r--r--pkg/adapter/pods_remote.go231
-rw-r--r--pkg/spec/createconfig.go12
-rw-r--r--pkg/spec/spec.go58
-rw-r--r--pkg/varlinkapi/pods.go4
6 files changed, 502 insertions, 7 deletions
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index 9623304e5..3f43a6905 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -4,6 +4,7 @@ package adapter
import (
"encoding/json"
+ "github.com/containers/libpod/cmd/podman/shared"
iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
@@ -48,3 +49,33 @@ func (c *Container) Config() *libpod.ContainerConfig {
}
return c.Runtime.Config(c.ID())
}
+
+// Name returns the name of the container
+func (c *Container) Name() string {
+ return c.config.Name
+}
+
+// BatchContainerOp is wrapper func to mimic shared's function with a similar name meant for libpod
+func BatchContainerOp(ctr *Container, opts shared.PsOptions) (shared.BatchContainerStruct, error) {
+ // TODO If pod ps ever shows container's sizes, re-enable this code; otherwise it isn't needed
+ // and would be a perf hit
+ //data, err := ctr.Inspect(true)
+ //if err != nil {
+ // return shared.BatchContainerStruct{}, err
+ //}
+ //
+ //size := new(shared.ContainerSize)
+ //size.RootFsSize = data.SizeRootFs
+ //size.RwSize = data.SizeRw
+
+ bcs := shared.BatchContainerStruct{
+ ConConfig: ctr.config,
+ ConState: ctr.state.State,
+ ExitCode: ctr.state.ExitCode,
+ Pid: ctr.state.PID,
+ StartedTime: ctr.state.StartedTime,
+ ExitedTime: ctr.state.FinishedTime,
+ //Size: size,
+ }
+ return bcs, nil
+}
diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go
index f2bcbd473..706a8fe96 100644
--- a/pkg/adapter/pods.go
+++ b/pkg/adapter/pods.go
@@ -4,10 +4,12 @@ package adapter
import (
"context"
- "github.com/containers/libpod/pkg/adapter/shortcuts"
+ "strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/adapter/shortcuts"
)
// Pod ...
@@ -45,6 +47,21 @@ func (r *LocalRuntime) GetLatestPod() (*Pod, error) {
return &pod, err
}
+// GetAllPods gets all pods and wraps it in an adapter pod
+func (r *LocalRuntime) GetAllPods() ([]*Pod, error) {
+ var pods []*Pod
+ allPods, err := r.Runtime.GetAllPods()
+ if err != nil {
+ return nil, err
+ }
+ for _, p := range allPods {
+ pod := Pod{}
+ pod.Pod = p
+ pods = append(pods, &pod)
+ }
+ return pods, nil
+}
+
// LookupPod gets a pod by name or id and wraps it in an adapter pod
func (r *LocalRuntime) LookupPod(nameOrID string) (*Pod, error) {
pod := Pod{}
@@ -150,3 +167,157 @@ func (r *LocalRuntime) StartPods(ctx context.Context, cli *cliconfig.PodStartVal
}
return podids, errs
}
+
+// CreatePod is a wrapper for libpod and creating a new pod from the cli context
+func (r *LocalRuntime) CreatePod(ctx context.Context, cli *cliconfig.PodCreateValues, labels map[string]string) (string, error) {
+ var (
+ options []libpod.PodCreateOption
+ err error
+ )
+
+ if cli.Flag("cgroup-parent").Changed {
+ options = append(options, libpod.WithPodCgroupParent(cli.CgroupParent))
+ }
+
+ if len(labels) != 0 {
+ options = append(options, libpod.WithPodLabels(labels))
+ }
+
+ if cli.Flag("name").Changed {
+ options = append(options, libpod.WithPodName(cli.Name))
+ }
+
+ if cli.Infra {
+ options = append(options, libpod.WithInfraContainer())
+ nsOptions, err := shared.GetNamespaceOptions(strings.Split(cli.Share, ","))
+ if err != nil {
+ return "", err
+ }
+ options = append(options, nsOptions...)
+ }
+
+ if len(cli.Publish) > 0 {
+ portBindings, err := shared.CreatePortBindings(cli.Publish)
+ if err != nil {
+ return "", err
+ }
+ options = append(options, libpod.WithInfraContainerPorts(portBindings))
+
+ }
+ // always have containers use pod cgroups
+ // User Opt out is not yet supported
+ options = append(options, libpod.WithPodCgroups())
+
+ pod, err := r.NewPod(ctx, options...)
+ if err != nil {
+ return "", err
+ }
+ return pod.ID(), nil
+}
+
+// GetPodStatus is a wrapper to get the status of a local libpod pod
+func (p *Pod) GetPodStatus() (string, error) {
+ return shared.GetPodStatus(p.Pod)
+}
+
+// BatchContainerOp is a wrapper for the shared function of the same name
+func BatchContainerOp(ctr *libpod.Container, opts shared.PsOptions) (shared.BatchContainerStruct, error) {
+ return shared.BatchContainerOp(ctr, opts)
+}
+
+// PausePods is a wrapper for pausing pods via libpod
+func (r *LocalRuntime) PausePods(c *cliconfig.PodPauseValues) ([]string, map[string]error, []error) {
+ var (
+ pauseIDs []string
+ pauseErrors []error
+ )
+ containerErrors := make(map[string]error)
+
+ pods, err := shortcuts.GetPodsByContext(c.All, c.Latest, c.InputArgs, r.Runtime)
+ if err != nil {
+ pauseErrors = append(pauseErrors, err)
+ return nil, containerErrors, pauseErrors
+ }
+
+ for _, pod := range pods {
+ ctrErrs, err := pod.Pause()
+ if err != nil {
+ pauseErrors = append(pauseErrors, err)
+ continue
+ }
+ if ctrErrs != nil {
+ for ctr, err := range ctrErrs {
+ containerErrors[ctr] = err
+ }
+ continue
+ }
+ pauseIDs = append(pauseIDs, pod.ID())
+
+ }
+ return pauseIDs, containerErrors, pauseErrors
+}
+
+// UnpausePods is a wrapper for unpausing pods via libpod
+func (r *LocalRuntime) UnpausePods(c *cliconfig.PodUnpauseValues) ([]string, map[string]error, []error) {
+ var (
+ unpauseIDs []string
+ unpauseErrors []error
+ )
+ containerErrors := make(map[string]error)
+
+ pods, err := shortcuts.GetPodsByContext(c.All, c.Latest, c.InputArgs, r.Runtime)
+ if err != nil {
+ unpauseErrors = append(unpauseErrors, err)
+ return nil, containerErrors, unpauseErrors
+ }
+
+ for _, pod := range pods {
+ ctrErrs, err := pod.Unpause()
+ if err != nil {
+ unpauseErrors = append(unpauseErrors, err)
+ continue
+ }
+ if ctrErrs != nil {
+ for ctr, err := range ctrErrs {
+ containerErrors[ctr] = err
+ }
+ continue
+ }
+ unpauseIDs = append(unpauseIDs, pod.ID())
+
+ }
+ return unpauseIDs, containerErrors, unpauseErrors
+}
+
+// RestartPods is a wrapper to restart pods via libpod
+func (r *LocalRuntime) RestartPods(ctx context.Context, c *cliconfig.PodRestartValues) ([]string, map[string]error, []error) {
+ var (
+ restartIDs []string
+ restartErrors []error
+ )
+ containerErrors := make(map[string]error)
+
+ pods, err := shortcuts.GetPodsByContext(c.All, c.Latest, c.InputArgs, r.Runtime)
+ if err != nil {
+ restartErrors = append(restartErrors, err)
+ return nil, containerErrors, restartErrors
+ }
+
+ for _, pod := range pods {
+ ctrErrs, err := pod.Restart(ctx)
+ if err != nil {
+ restartErrors = append(restartErrors, err)
+ continue
+ }
+ if ctrErrs != nil {
+ for ctr, err := range ctrErrs {
+ containerErrors[ctr] = err
+ }
+ continue
+ }
+ restartIDs = append(restartIDs, pod.ID())
+
+ }
+ return restartIDs, containerErrors, restartErrors
+
+}
diff --git a/pkg/adapter/pods_remote.go b/pkg/adapter/pods_remote.go
index 04484780a..220f7163f 100644
--- a/pkg/adapter/pods_remote.go
+++ b/pkg/adapter/pods_remote.go
@@ -5,8 +5,11 @@ package adapter
import (
"context"
"encoding/json"
+ "strings"
+ "time"
"github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/pkg/errors"
@@ -168,3 +171,231 @@ func (r *LocalRuntime) StartPods(ctx context.Context, cli *cliconfig.PodStartVal
}
return startPods, startErrs
}
+
+// CreatePod creates a pod for the remote client over a varlink connection
+func (r *LocalRuntime) CreatePod(ctx context.Context, cli *cliconfig.PodCreateValues, labels map[string]string) (string, error) {
+ pc := iopodman.PodCreate{
+ Name: cli.Name,
+ CgroupParent: cli.CgroupParent,
+ Labels: labels,
+ Share: strings.Split(cli.Share, ","),
+ Infra: cli.Infra,
+ InfraCommand: cli.InfraCommand,
+ InfraImage: cli.InfraCommand,
+ Publish: cli.Publish,
+ }
+
+ return iopodman.CreatePod().Call(r.Conn, pc)
+}
+
+// GetAllPods is a helper function that gets all pods for the remote client
+func (r *LocalRuntime) GetAllPods() ([]*Pod, error) {
+ var pods []*Pod
+ podIDs, err := iopodman.GetPodsByContext().Call(r.Conn, true, false, []string{})
+ if err != nil {
+ return nil, err
+ }
+ for _, p := range podIDs {
+ pod, err := r.LookupPod(p)
+ if err != nil {
+ return nil, err
+ }
+ pods = append(pods, pod)
+ }
+ return pods, nil
+}
+
+// ID returns the id of a remote pod
+func (p *Pod) ID() string {
+ return p.config.ID
+}
+
+// Name returns the name of the remote pod
+func (p *Pod) Name() string {
+ return p.config.Name
+}
+
+// AllContainersByID returns a slice of a pod's container IDs
+func (p *Pod) AllContainersByID() ([]string, error) {
+ var containerIDs []string
+ for _, ctr := range p.containers {
+ containerIDs = append(containerIDs, ctr.ID)
+ }
+ return containerIDs, nil
+}
+
+// AllContainers returns a pods containers
+func (p *Pod) AllContainers() ([]*Container, error) {
+ var containers []*Container
+ for _, ctr := range p.containers {
+ container, err := p.Runtime.LookupContainer(ctr.ID)
+ if err != nil {
+ return nil, err
+ }
+ containers = append(containers, container)
+ }
+ return containers, nil
+}
+
+// Status ...
+func (p *Pod) Status() (map[string]libpod.ContainerStatus, error) {
+ ctrs := make(map[string]libpod.ContainerStatus)
+ for _, i := range p.containers {
+ var status libpod.ContainerStatus
+ switch i.State {
+ case "exited":
+ status = libpod.ContainerStateExited
+ case "stopped":
+ status = libpod.ContainerStateStopped
+ case "running":
+ status = libpod.ContainerStateRunning
+ case "paused":
+ status = libpod.ContainerStatePaused
+ case "created":
+ status = libpod.ContainerStateCreated
+ case "configured":
+ status = libpod.ContainerStateConfigured
+ default:
+ status = libpod.ContainerStateUnknown
+ }
+ ctrs[i.ID] = status
+ }
+ return ctrs, nil
+}
+
+// GetPodStatus is a wrapper to get the string version of the status
+func (p *Pod) GetPodStatus() (string, error) {
+ ctrStatuses, err := p.Status()
+ if err != nil {
+ return "", err
+ }
+ return shared.CreatePodStatusResults(ctrStatuses)
+}
+
+// InfraContainerID returns the ID of the infra container in a pod
+func (p *Pod) InfraContainerID() (string, error) {
+ return p.state.InfraContainerID, nil
+}
+
+// CreatedTime returns the time the container was created as a time.Time
+func (p *Pod) CreatedTime() time.Time {
+ return p.config.CreatedTime
+}
+
+// SharesPID ....
+func (p *Pod) SharesPID() bool {
+ return p.config.UsePodPID
+}
+
+// SharesIPC returns whether containers in pod
+// default to use IPC namespace of first container in pod
+func (p *Pod) SharesIPC() bool {
+ return p.config.UsePodIPC
+}
+
+// SharesNet returns whether containers in pod
+// default to use network namespace of first container in pod
+func (p *Pod) SharesNet() bool {
+ return p.config.UsePodNet
+}
+
+// SharesMount returns whether containers in pod
+// default to use PID namespace of first container in pod
+func (p *Pod) SharesMount() bool {
+ return p.config.UsePodMount
+}
+
+// SharesUser returns whether containers in pod
+// default to use user namespace of first container in pod
+func (p *Pod) SharesUser() bool {
+ return p.config.UsePodUser
+}
+
+// SharesUTS returns whether containers in pod
+// default to use UTS namespace of first container in pod
+func (p *Pod) SharesUTS() bool {
+ return p.config.UsePodUTS
+}
+
+// SharesCgroup returns whether containers in the pod will default to this pod's
+// cgroup instead of the default libpod parent
+func (p *Pod) SharesCgroup() bool {
+ return p.config.UsePodCgroup
+}
+
+// CgroupParent returns the pod's CGroup parent
+func (p *Pod) CgroupParent() string {
+ return p.config.CgroupParent
+}
+
+// PausePods pauses a pod using varlink and the remote client
+func (r *LocalRuntime) PausePods(c *cliconfig.PodPauseValues) ([]string, map[string]error, []error) {
+ var (
+ pauseIDs []string
+ pauseErrors []error
+ )
+ containerErrors := make(map[string]error)
+
+ pods, err := iopodman.GetPodsByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)
+ if err != nil {
+ pauseErrors = append(pauseErrors, err)
+ return nil, containerErrors, pauseErrors
+ }
+ for _, pod := range pods {
+ reply, err := iopodman.PausePod().Call(r.Conn, pod)
+ if err != nil {
+ pauseErrors = append(pauseErrors, err)
+ continue
+ }
+ pauseIDs = append(pauseIDs, reply)
+ }
+ return pauseIDs, nil, pauseErrors
+}
+
+// UnpausePods unpauses a pod using varlink and the remote client
+func (r *LocalRuntime) UnpausePods(c *cliconfig.PodUnpauseValues) ([]string, map[string]error, []error) {
+ var (
+ unpauseIDs []string
+ unpauseErrors []error
+ )
+ containerErrors := make(map[string]error)
+
+ pods, err := iopodman.GetPodsByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)
+ if err != nil {
+ unpauseErrors = append(unpauseErrors, err)
+ return nil, containerErrors, unpauseErrors
+ }
+ for _, pod := range pods {
+ reply, err := iopodman.UnpausePod().Call(r.Conn, pod)
+ if err != nil {
+ unpauseErrors = append(unpauseErrors, err)
+ continue
+ }
+ unpauseIDs = append(unpauseIDs, reply)
+ }
+ return unpauseIDs, nil, unpauseErrors
+}
+
+// RestartPods restarts pods using varlink and the remote client
+func (r *LocalRuntime) RestartPods(ctx context.Context, c *cliconfig.PodRestartValues) ([]string, map[string]error, []error) {
+ var (
+ restartIDs []string
+ restartErrors []error
+ )
+ containerErrors := make(map[string]error)
+
+ pods, err := iopodman.GetPodsByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)
+ if err != nil {
+ restartErrors = append(restartErrors, err)
+ return nil, containerErrors, restartErrors
+ }
+ for _, pod := range pods {
+ reply, err := iopodman.RestartPod().Call(r.Conn, pod)
+ if err != nil {
+ restartErrors = append(restartErrors, err)
+ continue
+ }
+ restartIDs = append(restartIDs, reply)
+ }
+ return restartIDs, nil, restartErrors
+}
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index 8da44a2f0..31039bfdf 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -240,7 +240,7 @@ func (c *CreateConfig) GetVolumeMounts(specMounts []spec.Mount) ([]spec.Mount, e
}
for vol := range c.BuiltinImgVolumes {
- if libpod.MountExists(specMounts, vol) {
+ if libpod.MountExists(specMounts, vol) || libpod.MountExists(m, vol) {
continue
}
@@ -446,7 +446,15 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime, pod *l
}
if IsNS(string(c.NetMode)) {
- // pass
+ split := strings.SplitN(string(c.NetMode), ":", 2)
+ if len(split[0]) != 2 {
+ return nil, errors.Errorf("invalid user defined network namespace %q", c.NetMode.UserDefined())
+ }
+ _, err := os.Stat(split[1])
+ if err != nil {
+ return nil, err
+ }
+ options = append(options, libpod.WithNetNS(portBindings, false, string(c.NetMode), networks))
} else if c.NetMode.IsContainer() {
connectedCtr, err := c.Runtime.LookupContainer(c.NetMode.Container())
if err != nil {
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index 76b8963ff..28a636fa6 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -3,10 +3,12 @@ package createconfig
import (
"os"
"path"
+ "path/filepath"
"strings"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/storage/pkg/mount"
+ pmount "github.com/containers/storage/pkg/mount"
"github.com/docker/docker/daemon/caps"
"github.com/docker/go-units"
"github.com/opencontainers/runc/libcontainer/user"
@@ -392,9 +394,65 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint
configSpec.Linux.Resources = &spec.LinuxResources{}
}
+ // Make sure that the bind mounts keep options like nosuid, noexec, nodev.
+ mounts, err := pmount.GetMounts()
+ if err != nil {
+ return nil, err
+ }
+ for i := range configSpec.Mounts {
+ m := &configSpec.Mounts[i]
+ isBind := false
+ for _, o := range m.Options {
+ if o == "bind" || o == "rbind" {
+ isBind = true
+ break
+ }
+ }
+ if !isBind {
+ continue
+ }
+ mount, err := findMount(m.Source, mounts)
+ if err != nil {
+ return nil, err
+ }
+ if mount == nil {
+ continue
+ }
+ next_option:
+ for _, o := range strings.Split(mount.Opts, ",") {
+ if o == "nosuid" || o == "noexec" || o == "nodev" {
+ for _, e := range m.Options {
+ if e == o {
+ continue next_option
+ }
+ }
+ m.Options = append(m.Options, o)
+ }
+ }
+ }
+
return configSpec, nil
}
+func findMount(target string, mounts []*pmount.Info) (*pmount.Info, error) {
+ var err error
+ target, err = filepath.Abs(target)
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot resolve %s", target)
+ }
+ var bestSoFar *pmount.Info
+ for _, i := range mounts {
+ if bestSoFar != nil && len(bestSoFar.Mountpoint) > len(i.Mountpoint) {
+ // Won't be better than what we have already found
+ continue
+ }
+ if strings.HasPrefix(target, i.Mountpoint) {
+ bestSoFar = i
+ }
+ }
+ return bestSoFar, nil
+}
+
func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator) {
if config.PidMode.IsHost() && rootless.IsRootless() {
return
diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go
index ceeed6681..4ca4c4270 100644
--- a/pkg/varlinkapi/pods.go
+++ b/pkg/varlinkapi/pods.go
@@ -14,10 +14,6 @@ import (
// CreatePod ...
func (i *LibpodAPI) CreatePod(call iopodman.VarlinkCall, create iopodman.PodCreate) error {
var options []libpod.PodCreateOption
-
- if create.InfraCommand != "" || create.InfraImage != "" {
- return call.ReplyErrorOccurred("the infra-command and infra-image options are not supported yet")
- }
if create.CgroupParent != "" {
options = append(options, libpod.WithPodCgroupParent(create.CgroupParent))
}