From 43a1686598c92c9e2a839909b8b5edb9f1b0f00f Mon Sep 17 00:00:00 2001 From: baude Date: Sat, 23 Feb 2019 19:36:19 -0600 Subject: podman-remote create|ps enable the podman-remote client to be able to create and list pods on a remote system. Signed-off-by: baude --- pkg/adapter/containers_remote.go | 31 ++++++++ pkg/adapter/pods.go | 76 ++++++++++++++++++- pkg/adapter/pods_remote.go | 159 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 265 insertions(+), 1 deletion(-) (limited to 'pkg/adapter') 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..0cb602ecc 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,60 @@ 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) +} diff --git a/pkg/adapter/pods_remote.go b/pkg/adapter/pods_remote.go index 04484780a..767043a5f 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,159 @@ 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 +} -- cgit v1.2.3-54-g00ecf