summaryrefslogtreecommitdiff
path: root/pkg/varlinkapi
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2020-12-01 15:30:06 +0100
committerGitHub <noreply@github.com>2020-12-01 15:30:06 +0100
commite3f0b7db7508f1e1ecfdb23adb53531c89a29b99 (patch)
treec14bd42ae7fe6fd90679455efe932bd37d1f7a24 /pkg/varlinkapi
parent1316b2927be632ff717d9f7fd6a1633198c1ccaf (diff)
parentf62a356515e387b0bbcf1f08b4831d139c2039b7 (diff)
downloadpodman-e3f0b7db7508f1e1ecfdb23adb53531c89a29b99.tar.gz
podman-e3f0b7db7508f1e1ecfdb23adb53531c89a29b99.tar.bz2
podman-e3f0b7db7508f1e1ecfdb23adb53531c89a29b99.zip
Merge pull request #8400 from rhatdan/varlink
Remove varlink support from podman
Diffstat (limited to 'pkg/varlinkapi')
-rw-r--r--pkg/varlinkapi/attach.go144
-rw-r--r--pkg/varlinkapi/config.go22
-rw-r--r--pkg/varlinkapi/container.go928
-rw-r--r--pkg/varlinkapi/containers.go912
-rw-r--r--pkg/varlinkapi/containers_create.go17
-rw-r--r--pkg/varlinkapi/create.go1155
-rw-r--r--pkg/varlinkapi/events.go56
-rw-r--r--pkg/varlinkapi/funcs.go121
-rw-r--r--pkg/varlinkapi/generate.go30
-rw-r--r--pkg/varlinkapi/images.go1037
-rw-r--r--pkg/varlinkapi/intermediate.go289
-rw-r--r--pkg/varlinkapi/intermediate_varlink.go457
-rw-r--r--pkg/varlinkapi/mount.go49
-rw-r--r--pkg/varlinkapi/pods.go389
-rw-r--r--pkg/varlinkapi/remote_client.go29
-rw-r--r--pkg/varlinkapi/shortcuts.go66
-rw-r--r--pkg/varlinkapi/system.go129
-rw-r--r--pkg/varlinkapi/transfers.go80
-rw-r--r--pkg/varlinkapi/util.go237
-rw-r--r--pkg/varlinkapi/virtwriter/virtwriter.go204
-rw-r--r--pkg/varlinkapi/volumes.go165
21 files changed, 0 insertions, 6516 deletions
diff --git a/pkg/varlinkapi/attach.go b/pkg/varlinkapi/attach.go
deleted file mode 100644
index 38354a790..000000000
--- a/pkg/varlinkapi/attach.go
+++ /dev/null
@@ -1,144 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- "bufio"
- "context"
- "io"
-
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/libpod/define"
- "github.com/containers/podman/v2/libpod/events"
- iopodman "github.com/containers/podman/v2/pkg/varlink"
- "github.com/containers/podman/v2/pkg/varlinkapi/virtwriter"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
- "k8s.io/client-go/tools/remotecommand"
-)
-
-func setupStreams(call iopodman.VarlinkCall) (*bufio.Reader, *bufio.Writer, *io.PipeReader, *io.PipeWriter, *define.AttachStreams) {
-
- // These are the varlink sockets
- reader := call.Call.Reader
- writer := call.Call.Writer
-
- // This pipe is used to pass stdin from the client to the input stream
- // once the msg has been "decoded"
- pr, pw := io.Pipe()
-
- stdoutWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.ToStdout)
- // TODO if runc ever starts passing stderr, we can too
- // stderrWriter := NewVirtWriteCloser(writer, ToStderr)
-
- streams := define.AttachStreams{
- OutputStream: stdoutWriter,
- InputStream: bufio.NewReader(pr),
- // Runc eats the error stream
- ErrorStream: stdoutWriter,
- AttachInput: true,
- AttachOutput: true,
- // Runc eats the error stream
- AttachError: true,
- }
- return reader, writer, pr, pw, &streams
-}
-
-// Attach connects to a containers console
-func (i *VarlinkAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys string, start bool) error {
- var finalErr error
- resize := make(chan remotecommand.TerminalSize)
- errChan := make(chan error)
-
- if !call.WantsUpgrade() {
- return call.ReplyErrorOccurred("client must use upgraded connection to attach")
- }
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- state, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if !start && state != define.ContainerStateRunning {
- return call.ReplyErrorOccurred("container must be running to attach")
- }
-
- // ACK the client upgrade request
- if err := call.ReplyAttach(); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- reader, writer, _, pw, streams := setupStreams(call)
- go func() {
- if err := virtwriter.Reader(reader, nil, nil, pw, resize, nil); err != nil {
- errChan <- err
- }
- }()
-
- if state == define.ContainerStateRunning {
- finalErr = attach(ctr, streams, detachKeys, resize, errChan)
- } else {
- finalErr = startAndAttach(ctr, streams, detachKeys, resize, errChan)
- }
-
- exitCode := define.ExitCode(finalErr)
- if finalErr != define.ErrDetach && finalErr != nil {
- logrus.Error(finalErr)
- } else {
- if ecode, err := ctr.Wait(); err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
- // Check events
- event, err := i.Runtime.GetLastContainerEvent(context.Background(), ctr.ID(), events.Exited)
- if err != nil {
- logrus.Errorf("Cannot get exit code: %v", err)
- exitCode = define.ExecErrorCodeNotFound
- } else {
- exitCode = event.ContainerExitCode
- }
- } else {
- exitCode = define.ExitCode(err)
- }
- } else {
- exitCode = int(ecode)
- }
- }
-
- if ctr.AutoRemove() {
- err := i.Runtime.RemoveContainer(getContext(), ctr, false, false)
- if err != nil {
- logrus.Errorf("Failed to remove container %s: %s", ctr.ID(), err.Error())
- }
- }
-
- if err = virtwriter.HangUp(writer, uint32(exitCode)); err != nil {
- logrus.Errorf("Failed to HANG-UP attach to %s: %s", ctr.ID(), err.Error())
- }
- return call.Writer.Flush()
-}
-
-func attach(ctr *libpod.Container, streams *define.AttachStreams, detachKeys string, resize chan remotecommand.TerminalSize, errChan chan error) error {
- go func() {
- if err := ctr.Attach(streams, detachKeys, resize); err != nil {
- errChan <- err
- }
- }()
- attachError := <-errChan
- return attachError
-}
-
-func startAndAttach(ctr *libpod.Container, streams *define.AttachStreams, detachKeys string, resize chan remotecommand.TerminalSize, errChan chan error) error {
- var finalErr error
- attachChan, err := ctr.StartAndAttach(getContext(), streams, detachKeys, resize, false)
- if err != nil {
- return err
- }
- select {
- case attachChanErr := <-attachChan:
- finalErr = attachChanErr
- case chanError := <-errChan:
- finalErr = chanError
- }
- return finalErr
-}
diff --git a/pkg/varlinkapi/config.go b/pkg/varlinkapi/config.go
deleted file mode 100644
index 50e6fb833..000000000
--- a/pkg/varlinkapi/config.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- "github.com/containers/podman/v2/libpod"
- iopodman "github.com/containers/podman/v2/pkg/varlink"
- "github.com/spf13/cobra"
-)
-
-// VarlinkAPI is the basic varlink struct for libpod
-type VarlinkAPI struct {
- Cli *cobra.Command
- iopodman.VarlinkInterface
- Runtime *libpod.Runtime
-}
-
-// New creates a new varlink client
-func New(cli *cobra.Command, runtime *libpod.Runtime) *iopodman.VarlinkInterface {
- lp := VarlinkAPI{Cli: cli, Runtime: runtime}
- return iopodman.VarlinkNew(&lp)
-}
diff --git a/pkg/varlinkapi/container.go b/pkg/varlinkapi/container.go
deleted file mode 100644
index c4e8c1feb..000000000
--- a/pkg/varlinkapi/container.go
+++ /dev/null
@@ -1,928 +0,0 @@
-package varlinkapi
-
-import (
- "context"
- "fmt"
- "io"
- "os"
- "path/filepath"
- "regexp"
- "runtime"
- "sort"
- "strconv"
- "strings"
- "sync"
- "time"
-
- "github.com/containers/image/v5/types"
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/libpod/define"
- "github.com/containers/podman/v2/libpod/image"
- "github.com/containers/podman/v2/pkg/timetype"
- "github.com/containers/podman/v2/pkg/util"
- "github.com/cri-o/ocicni/pkg/ocicni"
- "github.com/docker/go-units"
- "github.com/google/shlex"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
- v1 "k8s.io/api/core/v1"
-)
-
-const (
- cidTruncLength = 12
- podTruncLength = 12
- iidTruncLength = 12
- cmdTruncLength = 17
-)
-
-// PsOptions describes the struct being formed for ps.
-type PsOptions struct {
- All bool
- Format string
- Last int
- Latest bool
- NoTrunc bool
- Pod bool
- Quiet bool
- Size bool
- Sort string
- Namespace bool
- Sync bool
-}
-
-// BatchContainerStruct is the return object from BatchContainer and contains
-// container related information.
-type BatchContainerStruct struct {
- ConConfig *libpod.ContainerConfig
- ConState define.ContainerStatus
- ExitCode int32
- Exited bool
- Pid int
- StartedTime time.Time
- ExitedTime time.Time
- Size *ContainerSize
-}
-
-// PsContainerOutput is the struct being returned from a parallel
-// batch operation.
-type PsContainerOutput struct {
- ID string
- Image string
- ImageID string
- Command string
- Created string
- Ports string
- Names string
- IsInfra bool
- Status string
- State define.ContainerStatus
- Pid int
- Size *ContainerSize
- Pod string
- PodName string
- CreatedAt time.Time
- ExitedAt time.Time
- StartedAt time.Time
- Labels map[string]string
- PID string
- Cgroup string
- IPC string
- MNT string
- NET string
- PIDNS string
- User string
- UTS string
- Mounts string
-}
-
-// Namespace describes output for ps namespace.
-type Namespace struct {
- PID string `json:"pid,omitempty"`
- Cgroup string `json:"cgroup,omitempty"`
- IPC string `json:"ipc,omitempty"`
- MNT string `json:"mnt,omitempty"`
- NET string `json:"net,omitempty"`
- PIDNS string `json:"pidns,omitempty"`
- User string `json:"user,omitempty"`
- UTS string `json:"uts,omitempty"`
-}
-
-// ContainerSize holds the size of the container's root filesystem and top
-// read-write layer.
-type ContainerSize struct {
- RootFsSize int64 `json:"rootFsSize"`
- RwSize int64 `json:"rwSize"`
-}
-
-// NewBatchContainer runs a batch process under one lock to get container information and only
-// be called in PBatch.
-func NewBatchContainer(r *libpod.Runtime, ctr *libpod.Container, opts PsOptions) (PsContainerOutput, error) {
- var (
- conState define.ContainerStatus
- command string
- created string
- status string
- exitedAt time.Time
- startedAt time.Time
- exitCode int32
- err error
- pid int
- size *ContainerSize
- ns *Namespace
- pso PsContainerOutput
- )
- batchErr := ctr.Batch(func(c *libpod.Container) error {
- if opts.Sync {
- if err := c.Sync(); err != nil {
- return err
- }
- }
-
- conState, err = c.State()
- if err != nil {
- return errors.Wrapf(err, "unable to obtain container state")
- }
- command = strings.Join(c.Command(), " ")
- created = units.HumanDuration(time.Since(c.CreatedTime())) + " ago"
-
- exitCode, _, err = c.ExitCode()
- if err != nil {
- return errors.Wrapf(err, "unable to obtain container exit code")
- }
- startedAt, err = c.StartedTime()
- if err != nil {
- logrus.Errorf("error getting started time for %q: %v", c.ID(), err)
- }
- exitedAt, err = c.FinishedTime()
- if err != nil {
- logrus.Errorf("error getting exited time for %q: %v", c.ID(), err)
- }
- if opts.Namespace {
- pid, err = c.PID()
- if err != nil {
- return errors.Wrapf(err, "unable to obtain container pid")
- }
- ns = GetNamespaces(pid)
- }
- if opts.Size {
- size = new(ContainerSize)
-
- rootFsSize, err := c.RootFsSize()
- if err != nil {
- logrus.Errorf("error getting root fs size for %q: %v", c.ID(), err)
- }
-
- rwSize, err := c.RWSize()
- if err != nil {
- logrus.Errorf("error getting rw size for %q: %v", c.ID(), err)
- }
-
- size.RootFsSize = rootFsSize
- size.RwSize = rwSize
- }
-
- return nil
- })
-
- if batchErr != nil {
- return pso, batchErr
- }
-
- switch conState.String() {
- case define.ContainerStateExited.String():
- fallthrough
- case define.ContainerStateStopped.String():
- exitedSince := units.HumanDuration(time.Since(exitedAt))
- status = fmt.Sprintf("Exited (%d) %s ago", exitCode, exitedSince)
- case define.ContainerStateRunning.String():
- status = "Up " + units.HumanDuration(time.Since(startedAt)) + " ago"
- case define.ContainerStatePaused.String():
- status = "Paused"
- case define.ContainerStateCreated.String(), define.ContainerStateConfigured.String():
- status = "Created"
- case define.ContainerStateRemoving.String():
- status = "Removing"
- default:
- status = "Error"
- }
-
- imageID, imageName := ctr.Image()
- cid := ctr.ID()
- podID := ctr.PodID()
- if !opts.NoTrunc {
- cid = cid[0:cidTruncLength]
- if len(podID) > podTruncLength {
- podID = podID[0:podTruncLength]
- }
- if len(command) > cmdTruncLength {
- command = command[0:cmdTruncLength] + "..."
- }
- if len(imageID) > iidTruncLength {
- imageID = imageID[0:iidTruncLength]
- }
- }
-
- ports, err := ctr.PortMappings()
- if err != nil {
- logrus.Errorf("unable to lookup namespace container for %s", ctr.ID())
- }
-
- pso.ID = cid
- pso.Image = imageName
- pso.ImageID = imageID
- pso.Command = command
- pso.Created = created
- pso.Ports = portsToString(ports)
- pso.Names = ctr.Name()
- pso.IsInfra = ctr.IsInfra()
- pso.Status = status
- pso.State = conState
- pso.Pid = pid
- pso.Size = size
- pso.ExitedAt = exitedAt
- pso.CreatedAt = ctr.CreatedTime()
- pso.StartedAt = startedAt
- pso.Labels = ctr.Labels()
- pso.Mounts = strings.Join(ctr.UserVolumes(), " ")
-
- // Add pod name and pod ID if requested by user.
- // No need to look up the pod if its ID is empty.
- if opts.Pod && len(podID) > 0 {
- // The pod name is not in the container definition
- // so we need to retrieve it using the pod ID.
- var podName string
- pod, err := r.LookupPod(podID)
- if err != nil {
- logrus.Errorf("unable to lookup pod for container %s", ctr.ID())
- } else {
- podName = pod.Name()
- }
-
- pso.Pod = podID
- pso.PodName = podName
- }
-
- if opts.Namespace {
- pso.Cgroup = ns.Cgroup
- pso.IPC = ns.IPC
- pso.MNT = ns.MNT
- pso.NET = ns.NET
- pso.User = ns.User
- pso.UTS = ns.UTS
- pso.PIDNS = ns.PIDNS
- }
-
- return pso, nil
-}
-
-type batchFunc func() (PsContainerOutput, error)
-
-type workerInput struct {
- parallelFunc batchFunc
- opts PsOptions
- cid string
- job int
-}
-
-// worker is a "threaded" worker that takes jobs from the channel "queue".
-func worker(wg *sync.WaitGroup, jobs <-chan workerInput, results chan<- PsContainerOutput, errors chan<- error) {
- for j := range jobs {
- r, err := j.parallelFunc()
- // If we find an error, we return just the error.
- if err != nil {
- errors <- err
- } else {
- // Return the result.
- results <- r
- }
- wg.Done()
- }
-}
-
-// GenerateContainerFilterFuncs return ContainerFilter functions based of filter.
-func GenerateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime) (func(container *libpod.Container) bool, error) {
- switch filter {
- case "id":
- return func(c *libpod.Container) bool {
- return strings.Contains(c.ID(), filterValue)
- }, nil
- case "label":
- var filterArray = strings.SplitN(filterValue, "=", 2)
- var filterKey = filterArray[0]
- if len(filterArray) > 1 {
- filterValue = filterArray[1]
- } else {
- filterValue = ""
- }
- return func(c *libpod.Container) bool {
- for labelKey, labelValue := range c.Labels() {
- if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) {
- return true
- }
- }
- return false
- }, nil
- case "name":
- return func(c *libpod.Container) bool {
- match, err := regexp.MatchString(filterValue, c.Name())
- if err != nil {
- return false
- }
- return match
- }, nil
- case "exited":
- exitCode, err := strconv.ParseInt(filterValue, 10, 32)
- if err != nil {
- return nil, errors.Wrapf(err, "exited code out of range %q", filterValue)
- }
- return func(c *libpod.Container) bool {
- ec, exited, err := c.ExitCode()
- if ec == int32(exitCode) && err == nil && exited {
- return true
- }
- return false
- }, nil
- case "status":
- if !util.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) {
- return nil, errors.Errorf("%s is not a valid status", filterValue)
- }
- return func(c *libpod.Container) bool {
- status, err := c.State()
- if err != nil {
- return false
- }
- if filterValue == "stopped" {
- filterValue = "exited"
- }
- state := status.String()
- if status == define.ContainerStateConfigured {
- state = "created"
- } else if status == define.ContainerStateStopped {
- state = "exited"
- }
- return state == filterValue
- }, nil
- case "ancestor":
- // This needs to refine to match docker
- // - ancestor=(<image-name>[:tag]|<image-id>| ⟨image@digest⟩) - containers created from an image or a descendant.
- return func(c *libpod.Container) bool {
- containerConfig := c.Config()
- if strings.Contains(containerConfig.RootfsImageID, filterValue) || strings.Contains(containerConfig.RootfsImageName, filterValue) {
- return true
- }
- return false
- }, nil
- case "before":
- ctr, err := r.LookupContainer(filterValue)
- if err != nil {
- return nil, errors.Errorf("unable to find container by name or id of %s", filterValue)
- }
- containerConfig := ctr.Config()
- createTime := containerConfig.CreatedTime
- return func(c *libpod.Container) bool {
- cc := c.Config()
- return createTime.After(cc.CreatedTime)
- }, nil
- case "since":
- ctr, err := r.LookupContainer(filterValue)
- if err != nil {
- return nil, errors.Errorf("unable to find container by name or id of %s", filterValue)
- }
- containerConfig := ctr.Config()
- createTime := containerConfig.CreatedTime
- return func(c *libpod.Container) bool {
- cc := c.Config()
- return createTime.Before(cc.CreatedTime)
- }, nil
- case "volume":
- //- volume=(<volume-name>|<mount-point-destination>)
- return func(c *libpod.Container) bool {
- containerConfig := c.Config()
- var dest string
- arr := strings.Split(filterValue, ":")
- source := arr[0]
- if len(arr) == 2 {
- dest = arr[1]
- }
- for _, mount := range containerConfig.Spec.Mounts {
- if dest != "" && (mount.Source == source && mount.Destination == dest) {
- return true
- }
- if dest == "" && mount.Source == source {
- return true
- }
- }
- return false
- }, nil
- case "health":
- return func(c *libpod.Container) bool {
- hcStatus, err := c.HealthCheckStatus()
- if err != nil {
- return false
- }
- return hcStatus == filterValue
- }, nil
- case "until":
- ts, err := timetype.GetTimestamp(filterValue, time.Now())
- if err != nil {
- return nil, err
- }
- seconds, nanoseconds, err := timetype.ParseTimestamps(ts, 0)
- if err != nil {
- return nil, err
- }
- until := time.Unix(seconds, nanoseconds)
- return func(c *libpod.Container) bool {
- if !until.IsZero() && c.CreatedTime().After((until)) {
- return true
- }
- return false
- }, nil
- }
- return nil, errors.Errorf("%s is an invalid filter", filter)
-}
-
-// GetPsContainerOutput returns a slice of containers specifically for ps output.
-func GetPsContainerOutput(r *libpod.Runtime, opts PsOptions, filters []string, maxWorkers int) ([]PsContainerOutput, error) {
- var (
- filterFuncs []libpod.ContainerFilter
- outputContainers []*libpod.Container
- )
-
- if len(filters) > 0 {
- for _, f := range filters {
- filterSplit := strings.SplitN(f, "=", 2)
- if len(filterSplit) < 2 {
- return nil, errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
- }
- generatedFunc, err := GenerateContainerFilterFuncs(filterSplit[0], filterSplit[1], r)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid filter")
- }
- filterFuncs = append(filterFuncs, generatedFunc)
- }
- }
- if !opts.Latest {
- // Get all containers.
- containers, err := r.GetContainers(filterFuncs...)
- if err != nil {
- return nil, err
- }
-
- // We only want the last few containers.
- if opts.Last > 0 && opts.Last <= len(containers) {
- return nil, errors.Errorf("--last not yet supported")
- } else {
- outputContainers = containers
- }
- } else {
- // Get just the latest container.
- // Ignore filters.
- latestCtr, err := r.GetLatestContainer()
- if err != nil {
- return nil, err
- }
-
- outputContainers = []*libpod.Container{latestCtr}
- }
-
- pss := PBatch(r, outputContainers, maxWorkers, opts)
- return pss, nil
-}
-
-// PBatch performs batch operations on a container in parallel. It spawns the
-// number of workers relative to the number of parallel operations desired.
-func PBatch(r *libpod.Runtime, containers []*libpod.Container, workers int, opts PsOptions) []PsContainerOutput {
- var wg sync.WaitGroup
- psResults := []PsContainerOutput{}
-
- // If the number of containers in question is less than the number of
- // proposed parallel operations, we shouldn't spawn so many workers.
- if workers > len(containers) {
- workers = len(containers)
- }
-
- jobs := make(chan workerInput, len(containers))
- results := make(chan PsContainerOutput, len(containers))
- batchErrors := make(chan error, len(containers))
-
- // Create the workers.
- for w := 1; w <= workers; w++ {
- go worker(&wg, jobs, results, batchErrors)
- }
-
- // Add jobs to the workers.
- for i, j := range containers {
- j := j
- wg.Add(1)
- f := func() (PsContainerOutput, error) {
- return NewBatchContainer(r, j, opts)
- }
- jobs <- workerInput{
- parallelFunc: f,
- opts: opts,
- cid: j.ID(),
- job: i,
- }
- }
- close(jobs)
- wg.Wait()
- close(results)
- close(batchErrors)
- for err := range batchErrors {
- logrus.Errorf("unable to get container info: %q", err)
- }
- for res := range results {
- // We sort out running vs non-running here to save lots of copying
- // later.
- if !opts.All && !opts.Latest && opts.Last < 1 {
- if !res.IsInfra && res.State == define.ContainerStateRunning {
- psResults = append(psResults, res)
- }
- } else {
- psResults = append(psResults, res)
- }
- }
- return psResults
-}
-
-// BatchContainerOp is used in ps to reduce performance hits by "batching"
-// locks.
-func BatchContainerOp(ctr *libpod.Container, opts PsOptions) (BatchContainerStruct, error) {
- var (
- conConfig *libpod.ContainerConfig
- conState define.ContainerStatus
- err error
- exitCode int32
- exited bool
- pid int
- size *ContainerSize
- startedTime time.Time
- exitedTime time.Time
- )
-
- batchErr := ctr.Batch(func(c *libpod.Container) error {
- conConfig = c.Config()
- conState, err = c.State()
- if err != nil {
- return errors.Wrapf(err, "unable to obtain container state")
- }
-
- exitCode, exited, err = c.ExitCode()
- if err != nil {
- return errors.Wrapf(err, "unable to obtain container exit code")
- }
- startedTime, err = c.StartedTime()
- if err != nil {
- logrus.Errorf("error getting started time for %q: %v", c.ID(), err)
- }
- exitedTime, err = c.FinishedTime()
- if err != nil {
- logrus.Errorf("error getting exited time for %q: %v", c.ID(), err)
- }
-
- if !opts.Size && !opts.Namespace {
- return nil
- }
-
- if opts.Namespace {
- pid, err = c.PID()
- if err != nil {
- return errors.Wrapf(err, "unable to obtain container pid")
- }
- }
- if opts.Size {
- size = new(ContainerSize)
-
- rootFsSize, err := c.RootFsSize()
- if err != nil {
- logrus.Errorf("error getting root fs size for %q: %v", c.ID(), err)
- }
-
- rwSize, err := c.RWSize()
- if err != nil {
- logrus.Errorf("error getting rw size for %q: %v", c.ID(), err)
- }
-
- size.RootFsSize = rootFsSize
- size.RwSize = rwSize
- }
- return nil
- })
- if batchErr != nil {
- return BatchContainerStruct{}, batchErr
- }
- return BatchContainerStruct{
- ConConfig: conConfig,
- ConState: conState,
- ExitCode: exitCode,
- Exited: exited,
- Pid: pid,
- StartedTime: startedTime,
- ExitedTime: exitedTime,
- Size: size,
- }, nil
-}
-
-// GetNamespaces returns a populated namespace struct.
-func GetNamespaces(pid int) *Namespace {
- ctrPID := strconv.Itoa(pid)
- cgroup, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "cgroup"))
- ipc, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "ipc"))
- mnt, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "mnt"))
- net, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "net"))
- pidns, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "pid"))
- user, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "user"))
- uts, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "uts"))
-
- return &Namespace{
- PID: ctrPID,
- Cgroup: cgroup,
- IPC: ipc,
- MNT: mnt,
- NET: net,
- PIDNS: pidns,
- User: user,
- UTS: uts,
- }
-}
-
-// GetNamespaceInfo is an exported wrapper for getNamespaceInfo
-func GetNamespaceInfo(path string) (string, error) {
- return getNamespaceInfo(path)
-}
-
-func getNamespaceInfo(path string) (string, error) {
- val, err := os.Readlink(path)
- if err != nil {
- return "", errors.Wrapf(err, "error getting info from %q", path)
- }
- return getStrFromSquareBrackets(val), nil
-}
-
-// getStrFromSquareBrackets gets the string inside [] from a string.
-func getStrFromSquareBrackets(cmd string) string {
- reg := regexp.MustCompile(`.*\[|\].*`)
- arr := strings.Split(reg.ReplaceAllLiteralString(cmd, ""), ",")
- return strings.Join(arr, ",")
-}
-
-func comparePorts(i, j ocicni.PortMapping) bool {
- if i.ContainerPort != j.ContainerPort {
- return i.ContainerPort < j.ContainerPort
- }
-
- if i.HostIP != j.HostIP {
- return i.HostIP < j.HostIP
- }
-
- if i.HostPort != j.HostPort {
- return i.HostPort < j.HostPort
- }
-
- return i.Protocol < j.Protocol
-}
-
-// formatGroup returns the group as <IP:startPort:lastPort->startPort:lastPort/Proto>
-// e.g 0.0.0.0:1000-1006->1000-1006/tcp.
-func formatGroup(key string, start, last int32) string {
- parts := strings.Split(key, "/")
- groupType := parts[0]
- var ip string
- if len(parts) > 1 {
- ip = parts[0]
- groupType = parts[1]
- }
- group := strconv.Itoa(int(start))
- if start != last {
- group = fmt.Sprintf("%s-%d", group, last)
- }
- if ip != "" {
- group = fmt.Sprintf("%s:%s->%s", ip, group, group)
- }
- return fmt.Sprintf("%s/%s", group, groupType)
-}
-
-// portsToString converts the ports used to a string of the from "port1, port2"
-// and also groups a continuous list of ports into a readable format.
-func portsToString(ports []ocicni.PortMapping) string {
- type portGroup struct {
- first int32
- last int32
- }
- var portDisplay []string
- if len(ports) == 0 {
- return ""
- }
- //Sort the ports, so grouping continuous ports become easy.
- sort.Slice(ports, func(i, j int) bool {
- return comparePorts(ports[i], ports[j])
- })
-
- // portGroupMap is used for grouping continuous ports.
- portGroupMap := make(map[string]*portGroup)
- var groupKeyList []string
-
- for _, v := range ports {
-
- hostIP := v.HostIP
- if hostIP == "" {
- hostIP = "0.0.0.0"
- }
- // If hostPort and containerPort are not same, consider as individual port.
- if v.ContainerPort != v.HostPort {
- portDisplay = append(portDisplay, fmt.Sprintf("%s:%d->%d/%s", hostIP, v.HostPort, v.ContainerPort, v.Protocol))
- continue
- }
-
- portMapKey := fmt.Sprintf("%s/%s", hostIP, v.Protocol)
-
- portgroup, ok := portGroupMap[portMapKey]
- if !ok {
- portGroupMap[portMapKey] = &portGroup{first: v.ContainerPort, last: v.ContainerPort}
- // This list is required to traverse portGroupMap.
- groupKeyList = append(groupKeyList, portMapKey)
- continue
- }
-
- if portgroup.last == (v.ContainerPort - 1) {
- portgroup.last = v.ContainerPort
- continue
- }
- }
- // For each portMapKey, format group list and append to output string.
- for _, portKey := range groupKeyList {
- group := portGroupMap[portKey]
- portDisplay = append(portDisplay, formatGroup(portKey, group.first, group.last))
- }
- return strings.Join(portDisplay, ", ")
-}
-
-// GetRunlabel is a helper function for runlabel; it gets the image if needed and begins the
-// construction of the runlabel output and environment variables.
-func GetRunlabel(label string, runlabelImage string, ctx context.Context, runtime *libpod.Runtime, pull bool, inputCreds string, dockerRegistryOptions image.DockerRegistryOptions, authfile string, signaturePolicyPath string, output io.Writer) (string, string, error) {
- var (
- newImage *image.Image
- err error
- imageName string
- )
- if pull {
- var registryCreds *types.DockerAuthConfig
- if inputCreds != "" {
- creds, err := util.ParseRegistryCreds(inputCreds)
- if err != nil {
- return "", "", err
- }
- registryCreds = creds
- }
- dockerRegistryOptions.DockerRegistryCreds = registryCreds
- newImage, err = runtime.ImageRuntime().New(ctx, runlabelImage, signaturePolicyPath, authfile, output, &dockerRegistryOptions, image.SigningOptions{}, &label, util.PullImageMissing)
- } else {
- newImage, err = runtime.ImageRuntime().NewFromLocal(runlabelImage)
- }
- if err != nil {
- return "", "", errors.Wrapf(err, "unable to find image")
- }
-
- if len(newImage.Names()) < 1 {
- imageName = newImage.ID()
- } else {
- imageName = newImage.Names()[0]
- }
-
- runLabel, err := newImage.GetLabel(ctx, label)
- return runLabel, imageName, err
-}
-
-// GenerateRunlabelCommand generates the command that will eventually be executed by Podman.
-func GenerateRunlabelCommand(runLabel, imageName, name string, opts map[string]string, extraArgs []string, globalOpts string) ([]string, []string, error) {
- // If no name is provided, we use the image's basename instead.
- if name == "" {
- baseName, err := image.GetImageBaseName(imageName)
- if err != nil {
- return nil, nil, err
- }
- name = baseName
- }
- // The user provided extra arguments that need to be tacked onto the label's command.
- if len(extraArgs) > 0 {
- runLabel = fmt.Sprintf("%s %s", runLabel, strings.Join(extraArgs, " "))
- }
- cmd, err := GenerateCommand(runLabel, imageName, name, globalOpts)
- if err != nil {
- return nil, nil, errors.Wrapf(err, "unable to generate command")
- }
- env := GenerateRunEnvironment(name, imageName, opts)
- env = append(env, "PODMAN_RUNLABEL_NESTED=1")
-
- envmap := envSliceToMap(env)
-
- envmapper := func(k string) string {
- switch k {
- case "OPT1":
- return envmap["OPT1"]
- case "OPT2":
- return envmap["OPT2"]
- case "OPT3":
- return envmap["OPT3"]
- case "PWD":
- // I would prefer to use os.getenv but it appears PWD is not in the os env list.
- d, err := os.Getwd()
- if err != nil {
- logrus.Error("unable to determine current working directory")
- return ""
- }
- return d
- }
- return ""
- }
- newS := os.Expand(strings.Join(cmd, " "), envmapper)
- cmd, err = shlex.Split(newS)
- if err != nil {
- return nil, nil, err
- }
- return cmd, env, nil
-}
-
-func envSliceToMap(env []string) map[string]string {
- m := make(map[string]string)
- for _, i := range env {
- split := strings.Split(i, "=")
- m[split[0]] = strings.Join(split[1:], " ")
- }
- return m
-}
-
-// GenerateKube generates kubernetes yaml based on a pod or container.
-func GenerateKube(name string, service bool, r *libpod.Runtime) (*v1.Pod, *v1.Service, error) {
- var (
- pod *libpod.Pod
- podYAML *v1.Pod
- err error
- container *libpod.Container
- servicePorts []v1.ServicePort
- serviceYAML v1.Service
- )
- // Get the container in question.
- container, err = r.LookupContainer(name)
- if err != nil {
- pod, err = r.LookupPod(name)
- if err != nil {
- return nil, nil, err
- }
- podYAML, servicePorts, err = pod.GenerateForKube()
- } else {
- if len(container.Dependencies()) > 0 {
- return nil, nil, errors.Wrapf(define.ErrNotImplemented, "containers with dependencies")
- }
- podYAML, err = container.GenerateForKube()
- }
- if err != nil {
- return nil, nil, err
- }
-
- if service {
- serviceYAML = libpod.GenerateKubeServiceFromV1Pod(podYAML, servicePorts)
- }
- return podYAML, &serviceYAML, nil
-}
-
-// Parallelize provides the maximum number of parallel workers (int) as calculated by a basic
-// heuristic. This can be overridden by the --max-workers primary switch to podman.
-func Parallelize(job string) int {
- numCpus := runtime.NumCPU()
- switch job {
- case "kill":
- if numCpus <= 3 {
- return numCpus * 3
- }
- return numCpus * 4
- case "pause":
- if numCpus <= 3 {
- return numCpus * 3
- }
- return numCpus * 4
- case "ps":
- return 8
- case "restart":
- return numCpus * 2
- case "rm":
- if numCpus <= 3 {
- return numCpus * 3
- } else {
- return numCpus * 4
- }
- case "stop":
- if numCpus <= 2 {
- return 4
- } else {
- return numCpus * 3
- }
- case "unpause":
- if numCpus <= 3 {
- return numCpus * 3
- }
- return numCpus * 4
- }
- return 3
-}
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
deleted file mode 100644
index fef3b6476..000000000
--- a/pkg/varlinkapi/containers.go
+++ /dev/null
@@ -1,912 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- "bufio"
- "encoding/json"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "strings"
- "sync"
- "syscall"
- "time"
-
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/libpod/define"
- "github.com/containers/podman/v2/libpod/logs"
- "github.com/containers/podman/v2/pkg/cgroups"
- "github.com/containers/podman/v2/pkg/rootless"
- iopodman "github.com/containers/podman/v2/pkg/varlink"
- "github.com/containers/podman/v2/pkg/varlinkapi/virtwriter"
- "github.com/containers/storage/pkg/archive"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
- "k8s.io/client-go/tools/remotecommand"
-)
-
-// ListContainers ...
-func (i *VarlinkAPI) ListContainers(call iopodman.VarlinkCall) error {
- var (
- listContainers []iopodman.Container
- )
-
- containers, err := i.Runtime.GetAllContainers()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- opts := PsOptions{
- Namespace: true,
- Size: true,
- }
- for _, ctr := range containers {
- batchInfo, err := BatchContainerOp(ctr, opts)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- listContainers = append(listContainers, makeListContainer(ctr.ID(), batchInfo))
- }
- return call.ReplyListContainers(listContainers)
-}
-
-func (i *VarlinkAPI) Ps(call iopodman.VarlinkCall, opts iopodman.PsOpts) error {
- var (
- containers []iopodman.PsContainer
- )
- maxWorkers := Parallelize("ps")
- psOpts := makePsOpts(opts)
- filters := []string{}
- if opts.Filters != nil {
- filters = *opts.Filters
- }
- psContainerOutputs, err := GetPsContainerOutput(i.Runtime, psOpts, filters, maxWorkers)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- for _, ctr := range psContainerOutputs {
- container := iopodman.PsContainer{
- Id: ctr.ID,
- Image: ctr.Image,
- Command: ctr.Command,
- Created: ctr.Created,
- Ports: ctr.Ports,
- Names: ctr.Names,
- IsInfra: ctr.IsInfra,
- Status: ctr.Status,
- State: ctr.State.String(),
- PidNum: int64(ctr.Pid),
- Pod: ctr.Pod,
- CreatedAt: ctr.CreatedAt.Format(time.RFC3339Nano),
- ExitedAt: ctr.ExitedAt.Format(time.RFC3339Nano),
- StartedAt: ctr.StartedAt.Format(time.RFC3339Nano),
- Labels: ctr.Labels,
- NsPid: ctr.PID,
- Cgroup: ctr.Cgroup,
- Ipc: ctr.Cgroup,
- Mnt: ctr.MNT,
- Net: ctr.NET,
- PidNs: ctr.PIDNS,
- User: ctr.User,
- Uts: ctr.UTS,
- Mounts: ctr.Mounts,
- }
- if ctr.Size != nil {
- container.RootFsSize = ctr.Size.RootFsSize
- container.RwSize = ctr.Size.RwSize
- }
- containers = append(containers, container)
- }
- return call.ReplyPs(containers)
-}
-
-// GetContainer ...
-func (i *VarlinkAPI) GetContainer(call iopodman.VarlinkCall, id string) error {
- ctr, err := i.Runtime.LookupContainer(id)
- if err != nil {
- return call.ReplyContainerNotFound(id, err.Error())
- }
- opts := PsOptions{
- Namespace: true,
- Size: true,
- }
- batchInfo, err := BatchContainerOp(ctr, opts)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyGetContainer(makeListContainer(ctr.ID(), batchInfo))
-}
-
-// getContainersByContext returns a slice of container ids based on all, latest, or a list
-func (i *VarlinkAPI) GetContainersByContext(call iopodman.VarlinkCall, all, latest bool, input []string) error {
- var ids []string
-
- ctrs, err := getContainersByContext(all, latest, input, i.Runtime)
- if err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
- return call.ReplyContainerNotFound("", err.Error())
- }
- return call.ReplyErrorOccurred(err.Error())
- }
-
- for _, c := range ctrs {
- ids = append(ids, c.ID())
- }
- return call.ReplyGetContainersByContext(ids)
-}
-
-// GetContainersByStatus returns a slice of containers filtered by a libpod status
-func (i *VarlinkAPI) GetContainersByStatus(call iopodman.VarlinkCall, statuses []string) error {
- var (
- filterFuncs []libpod.ContainerFilter
- containers []iopodman.Container
- )
- for _, status := range statuses {
- lpstatus, err := define.StringToContainerStatus(status)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- filterFuncs = append(filterFuncs, func(c *libpod.Container) bool {
- state, _ := c.State()
- return state == lpstatus
- })
- }
- filteredContainers, err := i.Runtime.GetContainers(filterFuncs...)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- opts := PsOptions{Size: true, Namespace: true}
- for _, ctr := range filteredContainers {
- batchInfo, err := BatchContainerOp(ctr, opts)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- containers = append(containers, makeListContainer(ctr.ID(), batchInfo))
- }
- return call.ReplyGetContainersByStatus(containers)
-}
-
-// InspectContainer ...
-func (i *VarlinkAPI) InspectContainer(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- data, err := ctr.Inspect(true)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- b, err := json.Marshal(data)
- if err != nil {
- return call.ReplyErrorOccurred(fmt.Sprintf("unable to serialize"))
- }
- return call.ReplyInspectContainer(string(b))
-}
-
-// ListContainerProcesses ...
-func (i *VarlinkAPI) ListContainerProcesses(call iopodman.VarlinkCall, name string, opts []string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- containerState, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if containerState != define.ContainerStateRunning {
- return call.ReplyErrorOccurred(fmt.Sprintf("container %s is not running", name))
- }
- var psArgs []string
- psOpts := []string{"user", "pid", "ppid", "pcpu", "etime", "tty", "time", "comm"}
- if len(opts) > 1 {
- psOpts = opts
- }
- psArgs = append(psArgs, psOpts...)
- psOutput, err := ctr.GetContainerPidInformation(psArgs)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- return call.ReplyListContainerProcesses(psOutput)
-}
-
-// GetContainerLogs ...
-func (i *VarlinkAPI) GetContainerLogs(call iopodman.VarlinkCall, name string) error {
- var logs []string
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- logPath := ctr.LogPath()
-
- containerState, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if _, err := os.Stat(logPath); err != nil {
- if containerState == define.ContainerStateConfigured {
- return call.ReplyGetContainerLogs(logs)
- }
- }
- file, err := os.Open(logPath)
- if err != nil {
- return errors.Wrapf(err, "unable to read container log file")
- }
- defer file.Close()
- reader := bufio.NewReader(file)
- if call.WantsMore() {
- call.Continues = true
- }
- for {
- line, err := reader.ReadString('\n')
- // We've read the entire file
- if err == io.EOF {
- if !call.WantsMore() {
- // If this is a non-following log request, we return what we have
- break
- } else {
- // If we want to follow, return what we have, wipe the slice, and make
- // sure the container is still running before iterating.
- call.ReplyGetContainerLogs(logs)
- logs = []string{}
- time.Sleep(1 * time.Second)
- state, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if state != define.ContainerStateRunning && state != define.ContainerStatePaused {
- return call.ReplyErrorOccurred(fmt.Sprintf("%s is no longer running", ctr.ID()))
- }
-
- }
- } else if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- } else {
- logs = append(logs, line)
- }
- }
-
- call.Continues = false
-
- return call.ReplyGetContainerLogs(logs)
-}
-
-// ListContainerChanges ...
-func (i *VarlinkAPI) ListContainerChanges(call iopodman.VarlinkCall, name string) error {
- changes, err := i.Runtime.GetDiff("", name)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- result := iopodman.ContainerChanges{}
- for _, change := range changes {
- switch change.Kind {
- case archive.ChangeModify:
- result.Changed = append(result.Changed, change.Path)
- case archive.ChangeDelete:
- result.Deleted = append(result.Deleted, change.Path)
- case archive.ChangeAdd:
- result.Added = append(result.Added, change.Path)
- }
- }
- return call.ReplyListContainerChanges(result)
-}
-
-// ExportContainer ...
-func (i *VarlinkAPI) ExportContainer(call iopodman.VarlinkCall, name, outPath string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- outputFile, err := ioutil.TempFile("", "varlink_recv")
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- defer outputFile.Close()
- if outPath == "" {
- outPath = outputFile.Name()
- }
- if err := ctr.Export(outPath); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyExportContainer(outPath)
-
-}
-
-// GetContainerStats ...
-func (i *VarlinkAPI) GetContainerStats(call iopodman.VarlinkCall, name string) error {
- if rootless.IsRootless() {
- cgroupv2, err := cgroups.IsCgroup2UnifiedMode()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if !cgroupv2 {
- return call.ReplyErrRequiresCgroupsV2ForRootless("rootless containers cannot report container stats")
- }
- }
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- containerStats, err := ctr.GetContainerStats(&define.ContainerStats{})
- if err != nil {
- if errors.Cause(err) == define.ErrCtrStateInvalid {
- return call.ReplyNoContainerRunning()
- }
- return call.ReplyErrorOccurred(err.Error())
- }
- cs := iopodman.ContainerStats{
- Id: ctr.ID(),
- Name: ctr.Name(),
- Cpu: containerStats.CPU,
- Cpu_nano: int64(containerStats.CPUNano),
- System_nano: int64(containerStats.SystemNano),
- Mem_usage: int64(containerStats.MemUsage),
- Mem_limit: int64(containerStats.MemLimit),
- Mem_perc: containerStats.MemPerc,
- Net_input: int64(containerStats.NetInput),
- Net_output: int64(containerStats.NetOutput),
- Block_input: int64(containerStats.BlockInput),
- Block_output: int64(containerStats.BlockOutput),
- Pids: int64(containerStats.PIDs),
- }
- return call.ReplyGetContainerStats(cs)
-}
-
-// StartContainer ...
-func (i *VarlinkAPI) StartContainer(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- state, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if state == define.ContainerStateRunning || state == define.ContainerStatePaused {
- return call.ReplyErrorOccurred("container is already running or paused")
- }
- recursive := false
- if ctr.PodID() != "" {
- recursive = true
- }
- if err := ctr.Start(getContext(), recursive); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyStartContainer(ctr.ID())
-}
-
-// InitContainer initializes the container given by Varlink.
-func (i *VarlinkAPI) InitContainer(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := ctr.Init(getContext(), false); err != nil {
- if errors.Cause(err) == define.ErrCtrStateInvalid {
- return call.ReplyInvalidState(ctr.ID(), err.Error())
- }
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyInitContainer(ctr.ID())
-}
-
-// StopContainer ...
-func (i *VarlinkAPI) StopContainer(call iopodman.VarlinkCall, name string, timeout int64) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := ctr.StopWithTimeout(uint(timeout)); err != nil {
- if errors.Cause(err) == define.ErrCtrStopped {
- return call.ReplyErrCtrStopped(ctr.ID())
- }
- if errors.Cause(err) == define.ErrCtrStateInvalid {
- return call.ReplyInvalidState(ctr.ID(), err.Error())
- }
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyStopContainer(ctr.ID())
-}
-
-// RestartContainer ...
-func (i *VarlinkAPI) RestartContainer(call iopodman.VarlinkCall, name string, timeout int64) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := ctr.RestartWithTimeout(getContext(), uint(timeout)); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyRestartContainer(ctr.ID())
-}
-
-// ContainerExists looks in local storage for the existence of a container
-func (i *VarlinkAPI) ContainerExists(call iopodman.VarlinkCall, name string) error {
- _, err := i.Runtime.LookupContainer(name)
- if errors.Cause(err) == define.ErrNoSuchCtr {
- return call.ReplyContainerExists(1)
- }
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyContainerExists(0)
-}
-
-// KillContainer kills a running container. If you want to use the default SIGTERM signal, just send a -1
-// for the signal arg.
-func (i *VarlinkAPI) KillContainer(call iopodman.VarlinkCall, name string, signal int64) error {
- killSignal := uint(syscall.SIGTERM)
- if signal != -1 {
- killSignal = uint(signal)
- }
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := ctr.Kill(killSignal); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyKillContainer(ctr.ID())
-}
-
-// PauseContainer ...
-func (i *VarlinkAPI) PauseContainer(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := ctr.Pause(); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyPauseContainer(ctr.ID())
-}
-
-// UnpauseContainer ...
-func (i *VarlinkAPI) UnpauseContainer(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := ctr.Unpause(); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyUnpauseContainer(ctr.ID())
-}
-
-// WaitContainer ...
-func (i *VarlinkAPI) WaitContainer(call iopodman.VarlinkCall, name string, interval int64) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- exitCode, err := ctr.WaitWithInterval(time.Duration(interval))
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyWaitContainer(int64(exitCode))
-}
-
-// RemoveContainer ...
-func (i *VarlinkAPI) RemoveContainer(call iopodman.VarlinkCall, name string, force bool, removeVolumes bool) error {
- ctx := getContext()
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := i.Runtime.RemoveContainer(ctx, ctr, force, removeVolumes); err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
- return call.ReplyContainerExists(1)
- }
- if errors.Cause(err) == define.ErrCtrStateInvalid {
- return call.ReplyInvalidState(ctr.ID(), err.Error())
- }
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyRemoveContainer(ctr.ID())
-}
-
-// EvictContainer ...
-func (i *VarlinkAPI) EvictContainer(call iopodman.VarlinkCall, name string, removeVolumes bool) error {
- ctx := getContext()
- id, err := i.Runtime.EvictContainer(ctx, name, removeVolumes)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyEvictContainer(id)
-}
-
-// DeleteStoppedContainers ...
-func (i *VarlinkAPI) DeleteStoppedContainers(call iopodman.VarlinkCall) error {
- ctx := getContext()
- var deletedContainers []string
- containers, err := i.Runtime.GetAllContainers()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- for _, ctr := range containers {
- state, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if state != define.ContainerStateRunning {
- if err := i.Runtime.RemoveContainer(ctx, ctr, false, false); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- deletedContainers = append(deletedContainers, ctr.ID())
- }
- }
- return call.ReplyDeleteStoppedContainers(deletedContainers)
-}
-
-// GetAttachSockets ...
-func (i *VarlinkAPI) GetAttachSockets(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
-
- status, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- // If the container hasn't been run, we need to run init
- // so the conmon sockets get created.
- if status == define.ContainerStateConfigured || status == define.ContainerStateStopped {
- if err := ctr.Init(getContext(), false); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- }
-
- sockPath, err := ctr.AttachSocketPath()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- s := iopodman.Sockets{
- Container_id: ctr.ID(),
- Io_socket: sockPath,
- Control_socket: ctr.ControlSocketPath(),
- }
- return call.ReplyGetAttachSockets(s)
-}
-
-// ContainerCheckpoint ...
-func (i *VarlinkAPI) ContainerCheckpoint(call iopodman.VarlinkCall, name string, keep, leaveRunning, tcpEstablished bool) error {
- ctx := getContext()
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
-
- options := libpod.ContainerCheckpointOptions{
- Keep: keep,
- TCPEstablished: tcpEstablished,
- KeepRunning: leaveRunning,
- }
- if err := ctr.Checkpoint(ctx, options); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyContainerCheckpoint(ctr.ID())
-}
-
-// ContainerRestore ...
-func (i *VarlinkAPI) ContainerRestore(call iopodman.VarlinkCall, name string, keep, tcpEstablished bool) error {
- ctx := getContext()
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
-
- options := libpod.ContainerCheckpointOptions{
- Keep: keep,
- TCPEstablished: tcpEstablished,
- }
- if err := ctr.Restore(ctx, options); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyContainerRestore(ctr.ID())
-}
-
-// ContainerConfig returns just the container.config struct
-func (i *VarlinkAPI) ContainerConfig(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- config := ctr.Config()
- b, err := json.Marshal(config)
- if err != nil {
- return call.ReplyErrorOccurred("unable to serialize container config")
- }
- return call.ReplyContainerConfig(string(b))
-}
-
-// ContainerArtifacts returns an untouched container's artifact in string format
-func (i *VarlinkAPI) ContainerArtifacts(call iopodman.VarlinkCall, name, artifactName string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- artifacts, err := ctr.GetArtifact(artifactName)
- if err != nil {
- return call.ReplyErrorOccurred("unable to get container artifacts")
- }
- b, err := json.Marshal(artifacts)
- if err != nil {
- return call.ReplyErrorOccurred("unable to serialize container artifacts")
- }
- return call.ReplyContainerArtifacts(string(b))
-}
-
-// ContainerInspectData returns the inspect data of a container in string format
-func (i *VarlinkAPI) ContainerInspectData(call iopodman.VarlinkCall, name string, size bool) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- data, err := ctr.Inspect(size)
- if err != nil {
- return call.ReplyErrorOccurred("unable to inspect container")
- }
- b, err := json.Marshal(data)
- if err != nil {
- return call.ReplyErrorOccurred("unable to serialize container inspect data")
- }
- return call.ReplyContainerInspectData(string(b))
-
-}
-
-// ContainerStateData returns a container's state data in string format
-func (i *VarlinkAPI) ContainerStateData(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- data, err := ctr.ContainerState()
- if err != nil {
- return call.ReplyErrorOccurred("unable to obtain container state")
- }
- b, err := json.Marshal(data)
- if err != nil {
- return call.ReplyErrorOccurred("unable to serialize container inspect data")
- }
- return call.ReplyContainerStateData(string(b))
-}
-
-// GetContainerStatsWithHistory is a varlink endpoint that returns container stats based on current and
-// previous statistics
-func (i *VarlinkAPI) GetContainerStatsWithHistory(call iopodman.VarlinkCall, prevStats iopodman.ContainerStats) error {
- con, err := i.Runtime.LookupContainer(prevStats.Id)
- if err != nil {
- return call.ReplyContainerNotFound(prevStats.Id, err.Error())
- }
- previousStats := ContainerStatsToLibpodContainerStats(prevStats)
- stats, err := con.GetContainerStats(&previousStats)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- cStats := iopodman.ContainerStats{
- Id: stats.ContainerID,
- Name: stats.Name,
- Cpu: stats.CPU,
- Cpu_nano: int64(stats.CPUNano),
- System_nano: int64(stats.SystemNano),
- Mem_usage: int64(stats.MemUsage),
- Mem_limit: int64(stats.MemLimit),
- Mem_perc: stats.MemPerc,
- Net_input: int64(stats.NetInput),
- Net_output: int64(stats.NetOutput),
- Block_input: int64(stats.BlockInput),
- Block_output: int64(stats.BlockOutput),
- Pids: int64(stats.PIDs),
- }
- return call.ReplyGetContainerStatsWithHistory(cStats)
-}
-
-// Spec ...
-func (i *VarlinkAPI) Spec(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- spec := ctr.Spec()
- b, err := json.Marshal(spec)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- return call.ReplySpec(string(b))
-}
-
-// GetContainersLogs is the varlink endpoint to obtain one or more container logs
-func (i *VarlinkAPI) GetContainersLogs(call iopodman.VarlinkCall, names []string, follow, latest bool, since string, tail int64, timestamps bool) error {
- var wg sync.WaitGroup
- if call.WantsMore() {
- call.Continues = true
- }
- sinceTime, err := time.Parse(time.RFC3339Nano, since)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- options := logs.LogOptions{
- Follow: follow,
- Since: sinceTime,
- Tail: tail,
- Timestamps: timestamps,
- }
-
- options.WaitGroup = &wg
- if len(names) > 1 {
- options.Multi = true
- }
- tailLen := int(tail)
- if tailLen < 0 {
- tailLen = 0
- }
- logChannel := make(chan *logs.LogLine, tailLen*len(names)+1)
- containers, err := getContainersByContext(false, latest, names, i.Runtime)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if err := i.Runtime.Log(getContext(), containers, &options, logChannel); err != nil {
- return err
- }
- go func() {
- wg.Wait()
- close(logChannel)
- }()
- for line := range logChannel {
- call.ReplyGetContainersLogs(newPodmanLogLine(line))
- if !call.Continues {
- break
- }
-
- }
- return call.ReplyGetContainersLogs(iopodman.LogLine{})
-}
-
-func newPodmanLogLine(line *logs.LogLine) iopodman.LogLine {
- return iopodman.LogLine{
- Device: line.Device,
- ParseLogType: line.ParseLogType,
- Time: line.Time.Format(time.RFC3339Nano),
- Msg: line.Msg,
- Cid: line.CID,
- }
-}
-
-// Top displays information about a container's running processes
-func (i *VarlinkAPI) Top(call iopodman.VarlinkCall, nameOrID string, descriptors []string) error {
- ctr, err := i.Runtime.LookupContainer(nameOrID)
- if err != nil {
- return call.ReplyContainerNotFound(ctr.ID(), err.Error())
- }
- topInfo, err := ctr.Top(descriptors)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyTop(topInfo)
-}
-
-// ExecContainer is the varlink endpoint to execute a command in a container
-func (i *VarlinkAPI) ExecContainer(call iopodman.VarlinkCall, opts iopodman.ExecOpts) error {
- if !call.WantsUpgrade() {
- return call.ReplyErrorOccurred("client must use upgraded connection to exec")
- }
-
- ctr, err := i.Runtime.LookupContainer(opts.Name)
- if err != nil {
- return call.ReplyContainerNotFound(opts.Name, err.Error())
- }
-
- state, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(
- fmt.Sprintf("exec failed to obtain container %s state: %s", ctr.ID(), err.Error()))
- }
-
- if state != define.ContainerStateRunning {
- return call.ReplyErrorOccurred(
- fmt.Sprintf("exec requires a running container, %s is %s", ctr.ID(), state.String()))
- }
-
- // ACK the client upgrade request
- call.ReplyExecContainer()
-
- envs := make(map[string]string)
- if opts.Env != nil {
- // HACK: The Varlink API uses the old []string format for env,
- // storage as "k=v". Split on the = and turn into the new map
- // format.
- for _, env := range *opts.Env {
- splitEnv := strings.SplitN(env, "=", 2)
- if len(splitEnv) == 1 {
- logrus.Errorf("Got badly-formatted environment variable %q in exec", env)
- continue
- }
- envs[splitEnv[0]] = splitEnv[1]
- }
- }
-
- var user string
- if opts.User != nil {
- user = *opts.User
- }
-
- var workDir string
- if opts.Workdir != nil {
- workDir = *opts.Workdir
- }
-
- resizeChan := make(chan remotecommand.TerminalSize)
-
- reader, writer, _, pipeWriter, streams := setupStreams(call)
-
- type ExitCodeError struct {
- ExitCode uint32
- Error error
- }
- ecErrChan := make(chan ExitCodeError, 1)
-
- go func() {
- if err := virtwriter.Reader(reader, nil, nil, pipeWriter, resizeChan, nil); err != nil {
- ecErrChan <- ExitCodeError{
- define.ExecErrorCodeGeneric,
- err,
- }
- }
- }()
-
- execConfig := new(libpod.ExecConfig)
- execConfig.Command = opts.Cmd
- execConfig.Terminal = opts.Tty
- execConfig.Privileged = opts.Privileged
- execConfig.Environment = envs
- execConfig.User = user
- execConfig.WorkDir = workDir
- execConfig.DetachKeys = opts.DetachKeys
-
- go func() {
- ec, err := ctr.Exec(execConfig, streams, resizeChan)
- if err != nil {
- logrus.Errorf(err.Error())
- }
- ecErrChan <- ExitCodeError{
- uint32(ec),
- err,
- }
- }()
-
- ecErr := <-ecErrChan
-
- exitCode := define.TranslateExecErrorToExitCode(int(ecErr.ExitCode), ecErr.Error)
-
- if err = virtwriter.HangUp(writer, uint32(exitCode)); err != nil {
- logrus.Errorf("ExecContainer failed to HANG-UP on %s: %s", ctr.ID(), err.Error())
- }
-
- if err := call.Writer.Flush(); err != nil {
- logrus.Errorf("Exec Container err: %s", err.Error())
- }
-
- return ecErr.Error
-}
-
-// HealthCheckRun executes defined container's healthcheck command and returns the container's health status.
-func (i *VarlinkAPI) HealthCheckRun(call iopodman.VarlinkCall, nameOrID string) error {
- hcStatus, err := i.Runtime.HealthCheck(nameOrID)
- if err != nil && hcStatus != define.HealthCheckFailure {
- return call.ReplyErrorOccurred(err.Error())
- }
- status := define.HealthCheckUnhealthy
- if hcStatus == define.HealthCheckSuccess {
- status = define.HealthCheckHealthy
- }
- return call.ReplyHealthCheckRun(status)
-}
diff --git a/pkg/varlinkapi/containers_create.go b/pkg/varlinkapi/containers_create.go
deleted file mode 100644
index 771e58089..000000000
--- a/pkg/varlinkapi/containers_create.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- iopodman "github.com/containers/podman/v2/pkg/varlink"
-)
-
-// CreateContainer ...
-func (i *VarlinkAPI) CreateContainer(call iopodman.VarlinkCall, config iopodman.Create) error {
- generic := VarlinkCreateToGeneric(config)
- ctr, _, err := CreateContainer(getContext(), &generic, i.Runtime)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyCreateContainer(ctr.ID())
-}
diff --git a/pkg/varlinkapi/create.go b/pkg/varlinkapi/create.go
deleted file mode 100644
index e9309a2d4..000000000
--- a/pkg/varlinkapi/create.go
+++ /dev/null
@@ -1,1155 +0,0 @@
-package varlinkapi
-
-import (
- "context"
- "encoding/json"
- "fmt"
- "io"
- "os"
- "path/filepath"
- goruntime "runtime"
- "strconv"
- "strings"
- "syscall"
- "time"
-
- "github.com/containers/common/pkg/sysinfo"
- "github.com/containers/image/v5/manifest"
- "github.com/containers/podman/v2/cmd/podman/parse"
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/libpod/define"
- "github.com/containers/podman/v2/libpod/image"
- ann "github.com/containers/podman/v2/pkg/annotations"
- "github.com/containers/podman/v2/pkg/autoupdate"
- "github.com/containers/podman/v2/pkg/cgroups"
- envLib "github.com/containers/podman/v2/pkg/env"
- "github.com/containers/podman/v2/pkg/errorhandling"
- "github.com/containers/podman/v2/pkg/inspect"
- ns "github.com/containers/podman/v2/pkg/namespaces"
- "github.com/containers/podman/v2/pkg/rootless"
- "github.com/containers/podman/v2/pkg/seccomp"
- cc "github.com/containers/podman/v2/pkg/spec"
- systemdGen "github.com/containers/podman/v2/pkg/systemd/generate"
- "github.com/containers/podman/v2/pkg/util"
- "github.com/docker/go-connections/nat"
- "github.com/docker/go-units"
- "github.com/opentracing/opentracing-go"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-var DefaultKernelNamespaces = "cgroup,ipc,net,uts"
-
-func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.Runtime) (*libpod.Container, *cc.CreateConfig, error) {
- var (
- healthCheck *manifest.Schema2HealthConfig
- err error
- cidFile *os.File
- )
- if c.Bool("trace") {
- span, _ := opentracing.StartSpanFromContext(ctx, "createContainer")
- defer span.Finish()
- }
- if c.Bool("rm") && c.String("restart") != "" && c.String("restart") != "no" {
- return nil, nil, errors.Errorf("the --rm option conflicts with --restart")
- }
-
- rtc, err := runtime.GetConfig()
- if err != nil {
- return nil, nil, err
- }
- rootfs := ""
- if c.Bool("rootfs") {
- rootfs = c.InputArgs[0]
- }
-
- if c.IsSet("cidfile") {
- cidFile, err = util.OpenExclusiveFile(c.String("cidfile"))
- if err != nil && os.IsExist(err) {
- return nil, nil, errors.Errorf("container id file exists. Ensure another container is not using it or delete %s", c.String("cidfile"))
- }
- if err != nil {
- return nil, nil, errors.Errorf("error opening cidfile %s", c.String("cidfile"))
- }
- defer errorhandling.CloseQuiet(cidFile)
- defer errorhandling.SyncQuiet(cidFile)
- }
-
- imageName := ""
- rawImageName := ""
- var imageData *inspect.ImageData = nil
-
- // Set the storage if there is no rootfs specified
- if rootfs == "" {
- var writer io.Writer
- if !c.Bool("quiet") {
- writer = os.Stderr
- }
-
- if len(c.InputArgs) != 0 {
- rawImageName = c.InputArgs[0]
- } else {
- return nil, nil, errors.Errorf("error, image name not provided")
- }
-
- pullType, err := util.ValidatePullType(c.String("pull"))
- if err != nil {
- return nil, nil, err
- }
-
- overrideOS := c.String("override-os")
- overrideArch := c.String("override-arch")
- dockerRegistryOptions := image.DockerRegistryOptions{
- OSChoice: overrideOS,
- ArchitectureChoice: overrideArch,
- }
-
- newImage, err := runtime.ImageRuntime().New(ctx, rawImageName, rtc.Engine.SignaturePolicyPath, c.String("authfile"), writer, &dockerRegistryOptions, image.SigningOptions{}, nil, pullType)
- if err != nil {
- return nil, nil, err
- }
- imageData, err = newImage.InspectNoSize(ctx)
- if err != nil {
- return nil, nil, err
- }
-
- if overrideOS == "" && imageData.Os != goruntime.GOOS {
- logrus.Infof("Using %q (OS) image on %q host", imageData.Os, goruntime.GOOS)
- }
-
- if overrideArch == "" && imageData.Architecture != goruntime.GOARCH {
- logrus.Infof("Using %q (architecture) on %q host", imageData.Architecture, goruntime.GOARCH)
- }
-
- names := newImage.Names()
- if len(names) > 0 {
- imageName = names[0]
- } else {
- imageName = newImage.ID()
- }
-
- // if the user disabled the healthcheck with "none" or the no-healthcheck
- // options is provided, we skip adding it
- healthCheckCommandInput := c.String("healthcheck-command")
-
- // the user didn't disable the healthcheck but did pass in a healthcheck command
- // now we need to make a healthcheck from the commandline input
- if healthCheckCommandInput != "none" && !c.Bool("no-healthcheck") {
- if len(healthCheckCommandInput) > 0 {
- healthCheck, err = makeHealthCheckFromCli(c)
- if err != nil {
- return nil, nil, errors.Wrapf(err, "unable to create healthcheck")
- }
- } else {
- // the user did not disable the health check and did not pass in a healthcheck
- // command as input. so now we add healthcheck if it exists AND is correct mediatype
- _, mediaType, err := newImage.Manifest(ctx)
- if err != nil {
- return nil, nil, errors.Wrapf(err, "unable to determine mediatype of image %s", newImage.ID())
- }
- if mediaType == manifest.DockerV2Schema2MediaType {
- healthCheck, err = newImage.GetHealthCheck(ctx)
- if err != nil {
- return nil, nil, errors.Wrapf(err, "unable to get healthcheck for %s", c.InputArgs[0])
- }
-
- if healthCheck != nil {
- hcCommand := healthCheck.Test
- if len(hcCommand) < 1 || hcCommand[0] == "" || hcCommand[0] == "NONE" {
- // disable health check
- healthCheck = nil
- } else {
- // apply defaults if image doesn't override them
- if healthCheck.Interval == 0 {
- healthCheck.Interval = 30 * time.Second
- }
- if healthCheck.Timeout == 0 {
- healthCheck.Timeout = 30 * time.Second
- }
- /* Docker default is 0s, so the following would be a no-op
- if healthCheck.StartPeriod == 0 {
- healthCheck.StartPeriod = 0 * time.Second
- }
- */
- if healthCheck.Retries == 0 {
- healthCheck.Retries = 3
- }
- }
- }
- }
- }
- }
- }
-
- createConfig, err := ParseCreateOpts(ctx, c, runtime, imageName, rawImageName, imageData)
- if err != nil {
- return nil, nil, err
- }
-
- // (VR): Ideally we perform the checks _before_ pulling the image but that
- // would require some bigger code refactoring of `ParseCreateOpts` and the
- // logic here. But as the creation code will be consolidated in the future
- // and given auto updates are experimental, we can live with that for now.
- // In the end, the user may only need to correct the policy or the raw image
- // name.
- autoUpdatePolicy, autoUpdatePolicySpecified := createConfig.Labels[autoupdate.Label]
- if autoUpdatePolicySpecified {
- if _, err := autoupdate.LookupPolicy(autoUpdatePolicy); err != nil {
- return nil, nil, err
- }
- // Now we need to make sure we're having a fully-qualified image reference.
- if rootfs != "" {
- return nil, nil, errors.Errorf("auto updates do not work with --rootfs")
- }
- // Make sure the input image is a docker.
- if err := autoupdate.ValidateImageReference(rawImageName); err != nil {
- return nil, nil, err
- }
- }
-
- // Because parseCreateOpts does derive anything from the image, we add health check
- // at this point. The rest is done by WithOptions.
- createConfig.HealthCheck = healthCheck
-
- // TODO: Should be able to return this from ParseCreateOpts
- var pod *libpod.Pod
- if createConfig.Pod != "" {
- pod, err = runtime.LookupPod(createConfig.Pod)
- if err != nil {
- return nil, nil, errors.Wrapf(err, "error looking up pod to join")
- }
- }
-
- ctr, err := CreateContainerFromCreateConfig(ctx, runtime, createConfig, pod)
- if err != nil {
- return nil, nil, err
- }
- if cidFile != nil {
- _, err = cidFile.WriteString(ctr.ID())
- if err != nil {
- logrus.Error(err)
- }
-
- }
-
- logrus.Debugf("New container created %q", ctr.ID())
- return ctr, createConfig, nil
-}
-
-func configureEntrypoint(c *GenericCLIResults, data *inspect.ImageData) []string {
- entrypoint := []string{}
- if c.IsSet("entrypoint") {
- // Force entrypoint to ""
- if c.String("entrypoint") == "" {
- return entrypoint
- }
- // Check if entrypoint specified is json
- if err := json.Unmarshal([]byte(c.String("entrypoint")), &entrypoint); err == nil {
- return entrypoint
- }
- // Return entrypoint as a single command
- return []string{c.String("entrypoint")}
- }
- if data != nil {
- return data.Config.Entrypoint
- }
- return entrypoint
-}
-
-func configurePod(c *GenericCLIResults, runtime *libpod.Runtime, namespaces map[string]string, podName string) (map[string]string, string, error) {
- pod, err := runtime.LookupPod(podName)
- if err != nil {
- return namespaces, "", err
- }
- podInfraID, err := pod.InfraContainerID()
- if err != nil {
- return namespaces, "", err
- }
- hasUserns := false
- if podInfraID != "" {
- podCtr, err := runtime.GetContainer(podInfraID)
- if err != nil {
- return namespaces, "", err
- }
- mappings, err := podCtr.IDMappings()
- if err != nil {
- return namespaces, "", err
- }
- hasUserns = len(mappings.UIDMap) > 0
- }
-
- if (namespaces["pid"] == cc.Pod) || (!c.IsSet("pid") && pod.SharesPID()) {
- namespaces["pid"] = fmt.Sprintf("container:%s", podInfraID)
- }
- if (namespaces["net"] == cc.Pod) || (!c.IsSet("net") && !c.IsSet("network") && pod.SharesNet()) {
- namespaces["net"] = fmt.Sprintf("container:%s", podInfraID)
- }
- if hasUserns && (namespaces["user"] == cc.Pod) || (!c.IsSet("user") && pod.SharesUser()) {
- namespaces["user"] = fmt.Sprintf("container:%s", podInfraID)
- }
- if (namespaces["ipc"] == cc.Pod) || (!c.IsSet("ipc") && pod.SharesIPC()) {
- namespaces["ipc"] = fmt.Sprintf("container:%s", podInfraID)
- }
- if (namespaces["uts"] == cc.Pod) || (!c.IsSet("uts") && pod.SharesUTS()) {
- namespaces["uts"] = fmt.Sprintf("container:%s", podInfraID)
- }
- return namespaces, podInfraID, nil
-}
-
-// Parses CLI options related to container creation into a config which can be
-// parsed into an OCI runtime spec
-func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.Runtime, imageName string, rawImageName string, data *inspect.ImageData) (*cc.CreateConfig, error) {
- var (
- inputCommand, command []string
- memoryLimit, memoryReservation, memorySwap, memoryKernel int64
- blkioWeight uint16
- namespaces map[string]string
- )
-
- idmappings, err := util.ParseIDMapping(ns.UsernsMode(c.String("userns")), c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidname"), c.String("subgidname"))
- if err != nil {
- return nil, err
- }
-
- imageID := ""
-
- inputCommand = c.InputArgs[1:]
- if data != nil {
- imageID = data.ID
- }
-
- rootfs := ""
- if c.Bool("rootfs") {
- rootfs = c.InputArgs[0]
- }
-
- if c.String("memory") != "" {
- memoryLimit, err = units.RAMInBytes(c.String("memory"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for memory")
- }
- }
- if c.String("memory-reservation") != "" {
- memoryReservation, err = units.RAMInBytes(c.String("memory-reservation"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for memory-reservation")
- }
- }
- if c.String("memory-swap") != "" {
- if c.String("memory-swap") == "-1" {
- memorySwap = -1
- } else {
- memorySwap, err = units.RAMInBytes(c.String("memory-swap"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for memory-swap")
- }
- }
- }
- if c.String("kernel-memory") != "" {
- memoryKernel, err = units.RAMInBytes(c.String("kernel-memory"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for kernel-memory")
- }
- }
- if c.String("blkio-weight") != "" {
- u, err := strconv.ParseUint(c.String("blkio-weight"), 10, 16)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for blkio-weight")
- }
- blkioWeight = uint16(u)
- }
-
- tty := c.Bool("tty")
-
- if c.Changed("cpu-period") && c.Changed("cpus") {
- return nil, errors.Errorf("--cpu-period and --cpus cannot be set together")
- }
- if c.Changed("cpu-quota") && c.Changed("cpus") {
- return nil, errors.Errorf("--cpu-quota and --cpus cannot be set together")
- }
-
- if c.Bool("no-hosts") && c.Changed("add-host") {
- return nil, errors.Errorf("--no-hosts and --add-host cannot be set together")
- }
-
- // EXPOSED PORTS
- var portBindings map[nat.Port][]nat.PortBinding
- if data != nil {
- portBindings, err = cc.ExposedPorts(c.StringSlice("expose"), c.StringSlice("publish"), c.Bool("publish-all"), data.Config.ExposedPorts)
- if err != nil {
- return nil, err
- }
- }
-
- // Kernel Namespaces
- // TODO Fix handling of namespace from pod
- // Instead of integrating here, should be done in libpod
- // However, that also involves setting up security opts
- // when the pod's namespace is integrated
- namespaces = map[string]string{
- "cgroup": c.String("cgroupns"),
- "pid": c.String("pid"),
- "net": c.String("network"),
- "ipc": c.String("ipc"),
- "user": c.String("userns"),
- "uts": c.String("uts"),
- }
-
- originalPodName := c.String("pod")
- podName := strings.Replace(originalPodName, "new:", "", 1)
- // after we strip out :new, make sure there is something left for a pod name
- if len(podName) < 1 && c.IsSet("pod") {
- return nil, errors.Errorf("new pod name must be at least one character")
- }
-
- // If we are adding a container to a pod, we would like to add an annotation for the infra ID
- // so kata containers can share VMs inside the pod
- var podInfraID string
- if c.IsSet("pod") {
- if strings.HasPrefix(originalPodName, "new:") {
- // pod does not exist; lets make it
- var podOptions []libpod.PodCreateOption
- podOptions = append(podOptions, libpod.WithPodName(podName), libpod.WithInfraContainer(), libpod.WithPodCgroups())
- if len(portBindings) > 0 {
- ociPortBindings, err := cc.NatToOCIPortBindings(portBindings)
- if err != nil {
- return nil, err
- }
- podOptions = append(podOptions, libpod.WithInfraContainerPorts(ociPortBindings))
- }
-
- podNsOptions, err := GetNamespaceOptions(strings.Split(DefaultKernelNamespaces, ","))
- if err != nil {
- return nil, err
- }
- podOptions = append(podOptions, podNsOptions...)
- // make pod
- pod, err := runtime.NewPod(ctx, podOptions...)
- if err != nil {
- return nil, err
- }
- logrus.Debugf("pod %s created by new container request", pod.ID())
-
- // The container now cannot have port bindings; so we reset the map
- portBindings = make(map[nat.Port][]nat.PortBinding)
- }
- namespaces, podInfraID, err = configurePod(c, runtime, namespaces, podName)
- if err != nil {
- return nil, err
- }
- }
-
- pidMode := ns.PidMode(namespaces["pid"])
- if !cc.Valid(string(pidMode), pidMode) {
- return nil, errors.Errorf("--pid %q is not valid", c.String("pid"))
- }
-
- usernsMode := ns.UsernsMode(namespaces["user"])
- if !cc.Valid(string(usernsMode), usernsMode) {
- return nil, errors.Errorf("--userns %q is not valid", namespaces["user"])
- }
-
- utsMode := ns.UTSMode(namespaces["uts"])
- if !cc.Valid(string(utsMode), utsMode) {
- return nil, errors.Errorf("--uts %q is not valid", namespaces["uts"])
- }
-
- cgroupMode := ns.CgroupMode(namespaces["cgroup"])
- if !cgroupMode.Valid() {
- return nil, errors.Errorf("--cgroup %q is not valid", namespaces["cgroup"])
- }
-
- ipcMode := ns.IpcMode(namespaces["ipc"])
- if !cc.Valid(string(ipcMode), ipcMode) {
- return nil, errors.Errorf("--ipc %q is not valid", ipcMode)
- }
-
- // Make sure if network is set to container namespace, port binding is not also being asked for
- netMode := ns.NetworkMode(namespaces["net"])
- if netMode.IsContainer() {
- if len(portBindings) > 0 {
- return nil, errors.Errorf("cannot set port bindings on an existing container network namespace")
- }
- }
-
- // USER
- user := c.String("user")
- if user == "" {
- switch {
- case usernsMode.IsKeepID():
- user = fmt.Sprintf("%d:%d", rootless.GetRootlessUID(), rootless.GetRootlessGID())
- case data == nil:
- user = "0"
- default:
- user = data.Config.User
- }
- }
-
- // STOP SIGNAL
- stopSignal := syscall.SIGTERM
- signalString := ""
- if data != nil {
- signalString = data.Config.StopSignal
- }
- if c.IsSet("stop-signal") {
- signalString = c.String("stop-signal")
- }
- if signalString != "" {
- stopSignal, err = util.ParseSignal(signalString)
- if err != nil {
- return nil, err
- }
- }
-
- // ENVIRONMENT VARIABLES
- //
- // Precedence order (higher index wins):
- // 1) env-host, 2) image data, 3) env-file, 4) env
- env := map[string]string{
- "container": "podman",
- }
-
- // First transform the os env into a map. We need it for the labels later in
- // any case.
- osEnv, err := envLib.ParseSlice(os.Environ())
- if err != nil {
- return nil, errors.Wrap(err, "error parsing host environment variables")
- }
-
- // Start with env-host
-
- if c.Bool("env-host") {
- env = envLib.Join(env, osEnv)
- }
-
- // Image data overrides any previous variables
- if data != nil {
- configEnv, err := envLib.ParseSlice(data.Config.Env)
- if err != nil {
- return nil, errors.Wrap(err, "error passing image environment variables")
- }
- env = envLib.Join(env, configEnv)
- }
-
- // env-file overrides any previous variables
- if c.IsSet("env-file") {
- for _, f := range c.StringSlice("env-file") {
- fileEnv, err := envLib.ParseFile(f)
- if err != nil {
- return nil, err
- }
- // File env is overridden by env.
- env = envLib.Join(env, fileEnv)
- }
- }
-
- if c.IsSet("env") {
- // env overrides any previous variables
- cmdlineEnv := c.StringSlice("env")
- if len(cmdlineEnv) > 0 {
- parsedEnv, err := envLib.ParseSlice(cmdlineEnv)
- if err != nil {
- return nil, err
- }
- env = envLib.Join(env, parsedEnv)
- }
- }
-
- // LABEL VARIABLES
- labels, err := parse.GetAllLabels(c.StringSlice("label-file"), c.StringArray("label"))
- if err != nil {
- return nil, errors.Wrapf(err, "unable to process labels")
- }
- if data != nil {
- for key, val := range data.Config.Labels {
- if _, ok := labels[key]; !ok {
- labels[key] = val
- }
- }
- }
-
- if systemdUnit, exists := osEnv[systemdGen.EnvVariable]; exists {
- labels[systemdGen.EnvVariable] = systemdUnit
- }
-
- // ANNOTATIONS
- annotations := make(map[string]string)
-
- // First, add our default annotations
- annotations[ann.TTY] = "false"
- if tty {
- annotations[ann.TTY] = "true"
- }
-
- // in the event this container is in a pod, and the pod has an infra container
- // we will want to configure it as a type "container" instead defaulting to
- // the behavior of a "sandbox" container
- // In Kata containers:
- // - "sandbox" is the annotation that denotes the container should use its own
- // VM, which is the default behavior
- // - "container" denotes the container should join the VM of the SandboxID
- // (the infra container)
- if podInfraID != "" {
- annotations[ann.SandboxID] = podInfraID
- annotations[ann.ContainerType] = ann.ContainerTypeContainer
- }
-
- if data != nil {
- // Next, add annotations from the image
- for key, value := range data.Annotations {
- annotations[key] = value
- }
- }
- // Last, add user annotations
- for _, annotation := range c.StringSlice("annotation") {
- splitAnnotation := strings.SplitN(annotation, "=", 2)
- if len(splitAnnotation) < 2 {
- return nil, errors.Errorf("Annotations must be formatted KEY=VALUE")
- }
- annotations[splitAnnotation[0]] = splitAnnotation[1]
- }
-
- // WORKING DIRECTORY
- workDir := "/"
- if c.IsSet("workdir") {
- workDir = c.String("workdir")
- } else if data != nil && data.Config.WorkingDir != "" {
- workDir = data.Config.WorkingDir
- }
-
- userCommand := []string{}
- entrypoint := configureEntrypoint(c, data)
- // Build the command
- // If we have an entry point, it goes first
- if len(entrypoint) > 0 {
- command = entrypoint
- }
- if len(inputCommand) > 0 {
- // User command overrides data CMD
- command = append(command, inputCommand...)
- userCommand = append(userCommand, inputCommand...)
- } else if data != nil && len(data.Config.Cmd) > 0 && !c.IsSet("entrypoint") {
- // If not user command, add CMD
- command = append(command, data.Config.Cmd...)
- userCommand = append(userCommand, data.Config.Cmd...)
- }
-
- if data != nil && len(command) == 0 {
- return nil, errors.Errorf("No command specified on command line or as CMD or ENTRYPOINT in this image")
- }
-
- // SHM Size
- shmSize, err := units.FromHumanSize(c.String("shm-size"))
- if err != nil {
- return nil, errors.Wrapf(err, "unable to translate --shm-size")
- }
-
- if c.IsSet("add-host") {
- // Verify the additional hosts are in correct format
- for _, host := range c.StringSlice("add-host") {
- if _, err := parse.ValidateExtraHost(host); err != nil {
- return nil, err
- }
- }
- }
-
- var (
- dnsSearches []string
- dnsServers []string
- dnsOptions []string
- )
- if c.Changed("dns-search") {
- dnsSearches = c.StringSlice("dns-search")
- // Check for explicit dns-search domain of ''
- if len(dnsSearches) == 0 {
- return nil, errors.Errorf("'' is not a valid domain")
- }
- // Validate domains are good
- for _, dom := range dnsSearches {
- if dom == "." {
- if len(dnsSearches) > 1 {
- return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'")
- }
- continue
- }
- if _, err := parse.ValidateDomain(dom); err != nil {
- return nil, err
- }
- }
- }
- if c.IsSet("dns") {
- dnsServers = append(dnsServers, c.StringSlice("dns")...)
- }
- if c.IsSet("dns-opt") {
- dnsOptions = c.StringSlice("dns-opt")
- }
-
- var ImageVolumes map[string]struct{}
- if data != nil && c.String("image-volume") != "ignore" {
- ImageVolumes = data.Config.Volumes
- }
-
- var imageVolType = map[string]string{
- "bind": "",
- "tmpfs": "",
- "ignore": "",
- }
- if _, ok := imageVolType[c.String("image-volume")]; !ok {
- return nil, errors.Errorf("invalid image-volume type %q. Pick one of bind, tmpfs, or ignore", c.String("image-volume"))
- }
-
- systemd := c.String("systemd") == "always"
- if !systemd && command != nil {
- x, err := strconv.ParseBool(c.String("systemd"))
- if err != nil {
- return nil, errors.Wrapf(err, "cannot parse bool %s", c.String("systemd"))
- }
- useSystemdCommands := map[string]bool{
- "/sbin/init": true,
- "/usr/sbin/init": true,
- "/usr/local/sbin/init": true,
- }
- if x && (useSystemdCommands[command[0]] || (filepath.Base(command[0]) == "systemd")) {
- systemd = true
- }
- }
- if systemd {
- if signalString == "" {
- stopSignal, err = util.ParseSignal("RTMIN+3")
- if err != nil {
- return nil, errors.Wrapf(err, "error parsing systemd signal")
- }
- }
- }
- // This is done because cobra cannot have two aliased flags. So we have to check
- // both
- memorySwappiness := c.Int64("memory-swappiness")
-
- logDriver := define.KubernetesLogging
- if c.Changed("log-driver") {
- logDriver = c.String("log-driver")
- }
-
- pidsLimit := c.Int64("pids-limit")
- if c.String("cgroups") == "disabled" && !c.Changed("pids-limit") {
- pidsLimit = -1
- }
-
- pid := &cc.PidConfig{
- PidMode: pidMode,
- }
- ipc := &cc.IpcConfig{
- IpcMode: ipcMode,
- }
-
- cgroup := &cc.CgroupConfig{
- Cgroups: c.String("cgroups"),
- Cgroupns: c.String("cgroupns"),
- CgroupParent: c.String("cgroup-parent"),
- CgroupMode: cgroupMode,
- }
-
- userns := &cc.UserConfig{
- GroupAdd: c.StringSlice("group-add"),
- IDMappings: idmappings,
- UsernsMode: usernsMode,
- User: user,
- }
-
- uts := &cc.UtsConfig{
- UtsMode: utsMode,
- NoHosts: c.Bool("no-hosts"),
- HostAdd: c.StringSlice("add-host"),
- Hostname: c.String("hostname"),
- }
- net := &cc.NetworkConfig{
- DNSOpt: dnsOptions,
- DNSSearch: dnsSearches,
- DNSServers: dnsServers,
- HTTPProxy: c.Bool("http-proxy"),
- MacAddress: c.String("mac-address"),
- Network: c.String("network"),
- NetMode: netMode,
- IPAddress: c.String("ip"),
- Publish: c.StringSlice("publish"),
- PublishAll: c.Bool("publish-all"),
- PortBindings: portBindings,
- }
-
- sysctl := map[string]string{}
- if c.Changed("sysctl") {
- sysctl, err = util.ValidateSysctls(c.StringSlice("sysctl"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for sysctl")
- }
- }
-
- secConfig := &cc.SecurityConfig{
- CapAdd: c.StringSlice("cap-add"),
- CapDrop: c.StringSlice("cap-drop"),
- Privileged: c.Bool("privileged"),
- ReadOnlyRootfs: c.Bool("read-only"),
- ReadOnlyTmpfs: c.Bool("read-only-tmpfs"),
- Sysctl: sysctl,
- }
-
- var securityOpt []string
- if c.Changed("security-opt") {
- securityOpt = c.StringArray("security-opt")
- }
- if err := secConfig.SetSecurityOpts(runtime, securityOpt); err != nil {
- return nil, err
- }
-
- // SECCOMP
- if data != nil {
- if value, exists := labels[seccomp.ContainerImageLabel]; exists {
- secConfig.SeccompProfileFromImage = value
- }
- }
- if policy, err := seccomp.LookupPolicy(c.String("seccomp-policy")); err != nil {
- return nil, err
- } else {
- secConfig.SeccompPolicy = policy
- }
- rtc, err := runtime.GetConfig()
- if err != nil {
- return nil, err
- }
- volumes := rtc.Containers.Volumes
- if c.Changed("volume") {
- volumes = append(volumes, c.StringSlice("volume")...)
- }
-
- devices := rtc.Containers.Devices
- if c.Changed("device") {
- devices = append(devices, c.StringSlice("device")...)
- }
-
- config := &cc.CreateConfig{
- Annotations: annotations,
- BuiltinImgVolumes: ImageVolumes,
- ConmonPidFile: c.String("conmon-pidfile"),
- ImageVolumeType: c.String("image-volume"),
- CidFile: c.String("cidfile"),
- Command: command,
- UserCommand: userCommand,
- Detach: c.Bool("detach"),
- Devices: devices,
- Entrypoint: entrypoint,
- Env: env,
- // ExposedPorts: ports,
- Init: c.Bool("init"),
- InitPath: c.String("init-path"),
- Image: imageName,
- RawImageName: rawImageName,
- ImageID: imageID,
- Interactive: c.Bool("interactive"),
- // IP6Address: c.String("ipv6"), // Not implemented yet - needs CNI support for static v6
- Labels: labels,
- // LinkLocalIP: c.StringSlice("link-local-ip"), // Not implemented yet
- LogDriver: logDriver,
- LogDriverOpt: c.StringSlice("log-opt"),
- Name: c.String("name"),
- // NetworkAlias: c.StringSlice("network-alias"), // Not implemented - does this make sense in Podman?
- Pod: podName,
- Quiet: c.Bool("quiet"),
- Resources: cc.CreateResourceConfig{
- BlkioWeight: blkioWeight,
- BlkioWeightDevice: c.StringSlice("blkio-weight-device"),
- CPUShares: c.Uint64("cpu-shares"),
- CPUPeriod: c.Uint64("cpu-period"),
- CPUsetCPUs: c.String("cpuset-cpus"),
- CPUsetMems: c.String("cpuset-mems"),
- CPUQuota: c.Int64("cpu-quota"),
- CPURtPeriod: c.Uint64("cpu-rt-period"),
- CPURtRuntime: c.Int64("cpu-rt-runtime"),
- CPUs: c.Float64("cpus"),
- DeviceCgroupRules: c.StringSlice("device-cgroup-rule"),
- DeviceReadBps: c.StringSlice("device-read-bps"),
- DeviceReadIOps: c.StringSlice("device-read-iops"),
- DeviceWriteBps: c.StringSlice("device-write-bps"),
- DeviceWriteIOps: c.StringSlice("device-write-iops"),
- DisableOomKiller: c.Bool("oom-kill-disable"),
- ShmSize: shmSize,
- Memory: memoryLimit,
- MemoryReservation: memoryReservation,
- MemorySwap: memorySwap,
- MemorySwappiness: int(memorySwappiness),
- KernelMemory: memoryKernel,
- OomScoreAdj: c.Int("oom-score-adj"),
- PidsLimit: pidsLimit,
- Ulimit: c.StringSlice("ulimit"),
- },
- RestartPolicy: c.String("restart"),
- Rm: c.Bool("rm"),
- Security: *secConfig,
- StopSignal: stopSignal,
- StopTimeout: c.Uint("stop-timeout"),
- Systemd: systemd,
- Tmpfs: c.StringArray("tmpfs"),
- Tty: tty,
- MountsFlag: c.StringArray("mount"),
- Volumes: volumes,
- WorkDir: workDir,
- Rootfs: rootfs,
- VolumesFrom: c.StringSlice("volumes-from"),
- Syslog: c.Bool("syslog"),
-
- Pid: *pid,
- Ipc: *ipc,
- Cgroup: *cgroup,
- User: *userns,
- Uts: *uts,
- Network: *net,
- }
-
- warnings, err := verifyContainerResources(config, false)
- if err != nil {
- return nil, err
- }
- for _, warning := range warnings {
- fmt.Fprintln(os.Stderr, warning)
- }
- return config, nil
-}
-
-func CreateContainerFromCreateConfig(ctx context.Context, r *libpod.Runtime, createConfig *cc.CreateConfig, pod *libpod.Pod) (*libpod.Container, error) {
- runtimeSpec, options, err := createConfig.MakeContainerConfig(r, pod)
- if err != nil {
- return nil, err
- }
-
- ctr, err := r.NewContainer(ctx, runtimeSpec, options...)
- if err != nil {
- return nil, err
- }
- return ctr, nil
-}
-
-func makeHealthCheckFromCli(c *GenericCLIResults) (*manifest.Schema2HealthConfig, error) {
- inCommand := c.String("healthcheck-command")
- inInterval := c.String("healthcheck-interval")
- inRetries := c.Uint("healthcheck-retries")
- inTimeout := c.String("healthcheck-timeout")
- inStartPeriod := c.String("healthcheck-start-period")
-
- // Every healthcheck requires a command
- if len(inCommand) == 0 {
- return nil, errors.New("Must define a healthcheck command for all healthchecks")
- }
-
- // first try to parse option value as JSON array of strings...
- cmd := []string{}
- err := json.Unmarshal([]byte(inCommand), &cmd)
- if err != nil {
- // ...otherwise pass it to "/bin/sh -c" inside the container
- cmd = []string{"CMD-SHELL", inCommand}
- }
- hc := manifest.Schema2HealthConfig{
- Test: cmd,
- }
-
- if inInterval == "disable" {
- inInterval = "0"
- }
- intervalDuration, err := time.ParseDuration(inInterval)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid healthcheck-interval %s ", inInterval)
- }
-
- hc.Interval = intervalDuration
-
- if inRetries < 1 {
- return nil, errors.New("healthcheck-retries must be greater than 0.")
- }
- hc.Retries = int(inRetries)
- timeoutDuration, err := time.ParseDuration(inTimeout)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid healthcheck-timeout %s", inTimeout)
- }
- if timeoutDuration < time.Duration(1) {
- return nil, errors.New("healthcheck-timeout must be at least 1 second")
- }
- hc.Timeout = timeoutDuration
-
- startPeriodDuration, err := time.ParseDuration(inStartPeriod)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid healthcheck-start-period %s", inStartPeriod)
- }
- if startPeriodDuration < time.Duration(0) {
- return nil, errors.New("healthcheck-start-period must be 0 seconds or greater")
- }
- hc.StartPeriod = startPeriodDuration
-
- return &hc, 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
-}
-
-func addWarning(warnings []string, msg string) []string {
- logrus.Warn(msg)
- return append(warnings, msg)
-}
-
-func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, error) {
- warnings := []string{}
-
- cgroup2, err := cgroups.IsCgroup2UnifiedMode()
- if err != nil || cgroup2 {
- return warnings, err
- }
-
- sysInfo := sysinfo.New(true)
-
- // memory subsystem checks and adjustments
- if config.Resources.Memory > 0 && !sysInfo.MemoryLimit {
- warnings = addWarning(warnings, "Your kernel does not support memory limit capabilities or the cgroup is not mounted. Limitation discarded.")
- config.Resources.Memory = 0
- config.Resources.MemorySwap = -1
- }
- if config.Resources.Memory > 0 && config.Resources.MemorySwap != -1 && !sysInfo.SwapLimit {
- warnings = addWarning(warnings, "Your kernel does not support swap limit capabilities,or the cgroup is not mounted. Memory limited without swap.")
- config.Resources.MemorySwap = -1
- }
- if config.Resources.Memory > 0 && config.Resources.MemorySwap > 0 && config.Resources.MemorySwap < config.Resources.Memory {
- return warnings, fmt.Errorf("minimum memoryswap limit should be larger than memory limit, see usage")
- }
- if config.Resources.Memory == 0 && config.Resources.MemorySwap > 0 && !update {
- return warnings, fmt.Errorf("you should always set the memory limit when using memoryswap limit, see usage")
- }
- if config.Resources.MemorySwappiness != -1 {
- if !sysInfo.MemorySwappiness {
- msg := "Your kernel does not support memory swappiness capabilities, or the cgroup is not mounted. Memory swappiness discarded."
- warnings = addWarning(warnings, msg)
- config.Resources.MemorySwappiness = -1
- } else {
- swappiness := config.Resources.MemorySwappiness
- if swappiness < -1 || swappiness > 100 {
- return warnings, fmt.Errorf("invalid value: %v, valid memory swappiness range is 0-100", swappiness)
- }
- }
- }
- if config.Resources.MemoryReservation > 0 && !sysInfo.MemoryReservation {
- warnings = addWarning(warnings, "Your kernel does not support memory soft limit capabilities or the cgroup is not mounted. Limitation discarded.")
- config.Resources.MemoryReservation = 0
- }
- if config.Resources.Memory > 0 && config.Resources.MemoryReservation > 0 && config.Resources.Memory < config.Resources.MemoryReservation {
- return warnings, fmt.Errorf("minimum memory limit cannot be less than memory reservation limit, see usage")
- }
- if config.Resources.KernelMemory > 0 && !sysInfo.KernelMemory {
- warnings = addWarning(warnings, "Your kernel does not support kernel memory limit capabilities or the cgroup is not mounted. Limitation discarded.")
- config.Resources.KernelMemory = 0
- }
- if config.Resources.DisableOomKiller && !sysInfo.OomKillDisable {
- // only produce warnings if the setting wasn't to *disable* the OOM Kill; no point
- // warning the caller if they already wanted the feature to be off
- warnings = addWarning(warnings, "Your kernel does not support OomKillDisable. OomKillDisable discarded.")
- config.Resources.DisableOomKiller = false
- }
-
- if config.Resources.PidsLimit != 0 && !sysInfo.PidsLimit {
- warnings = addWarning(warnings, "Your kernel does not support pids limit capabilities or the cgroup is not mounted. PIDs limit discarded.")
- config.Resources.PidsLimit = 0
- }
-
- if config.Resources.CPUShares > 0 && !sysInfo.CPUShares {
- warnings = addWarning(warnings, "Your kernel does not support CPU shares or the cgroup is not mounted. Shares discarded.")
- config.Resources.CPUShares = 0
- }
- if config.Resources.CPUPeriod > 0 && !sysInfo.CPUCfsPeriod {
- warnings = addWarning(warnings, "Your kernel does not support CPU cfs period or the cgroup is not mounted. Period discarded.")
- config.Resources.CPUPeriod = 0
- }
- if config.Resources.CPUPeriod != 0 && (config.Resources.CPUPeriod < 1000 || config.Resources.CPUPeriod > 1000000) {
- return warnings, fmt.Errorf("CPU cfs period cannot be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000)")
- }
- if config.Resources.CPUQuota > 0 && !sysInfo.CPUCfsQuota {
- warnings = addWarning(warnings, "Your kernel does not support CPU cfs quota or the cgroup is not mounted. Quota discarded.")
- config.Resources.CPUQuota = 0
- }
- if config.Resources.CPUQuota > 0 && config.Resources.CPUQuota < 1000 {
- return warnings, fmt.Errorf("CPU cfs quota cannot be less than 1ms (i.e. 1000)")
- }
- // cpuset subsystem checks and adjustments
- if (config.Resources.CPUsetCPUs != "" || config.Resources.CPUsetMems != "") && !sysInfo.Cpuset {
- warnings = addWarning(warnings, "Your kernel does not support cpuset or the cgroup is not mounted. CPUset discarded.")
- config.Resources.CPUsetCPUs = ""
- config.Resources.CPUsetMems = ""
- }
- cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(config.Resources.CPUsetCPUs)
- if err != nil {
- return warnings, fmt.Errorf("invalid value %s for cpuset cpus", config.Resources.CPUsetCPUs)
- }
- if !cpusAvailable {
- return warnings, fmt.Errorf("requested CPUs are not available - requested %s, available: %s", config.Resources.CPUsetCPUs, sysInfo.Cpus)
- }
- memsAvailable, err := sysInfo.IsCpusetMemsAvailable(config.Resources.CPUsetMems)
- if err != nil {
- return warnings, fmt.Errorf("invalid value %s for cpuset mems", config.Resources.CPUsetMems)
- }
- if !memsAvailable {
- return warnings, fmt.Errorf("requested memory nodes are not available - requested %s, available: %s", config.Resources.CPUsetMems, sysInfo.Mems)
- }
-
- // blkio subsystem checks and adjustments
- if config.Resources.BlkioWeight > 0 && !sysInfo.BlkioWeight {
- warnings = addWarning(warnings, "Your kernel does not support Block I/O weight or the cgroup is not mounted. Weight discarded.")
- config.Resources.BlkioWeight = 0
- }
- if config.Resources.BlkioWeight > 0 && (config.Resources.BlkioWeight < 10 || config.Resources.BlkioWeight > 1000) {
- return warnings, fmt.Errorf("range of blkio weight is from 10 to 1000")
- }
- if len(config.Resources.BlkioWeightDevice) > 0 && !sysInfo.BlkioWeightDevice {
- warnings = addWarning(warnings, "Your kernel does not support Block I/O weight_device or the cgroup is not mounted. Weight-device discarded.")
- config.Resources.BlkioWeightDevice = []string{}
- }
- if len(config.Resources.DeviceReadBps) > 0 && !sysInfo.BlkioReadBpsDevice {
- warnings = addWarning(warnings, "Your kernel does not support BPS Block I/O read limit or the cgroup is not mounted. Block I/O BPS read limit discarded")
- config.Resources.DeviceReadBps = []string{}
- }
- if len(config.Resources.DeviceWriteBps) > 0 && !sysInfo.BlkioWriteBpsDevice {
- warnings = addWarning(warnings, "Your kernel does not support BPS Block I/O write limit or the cgroup is not mounted. Block I/O BPS write limit discarded.")
- config.Resources.DeviceWriteBps = []string{}
- }
- if len(config.Resources.DeviceReadIOps) > 0 && !sysInfo.BlkioReadIOpsDevice {
- warnings = addWarning(warnings, "Your kernel does not support IOPS Block read limit or the cgroup is not mounted. Block I/O IOPS read limit discarded.")
- config.Resources.DeviceReadIOps = []string{}
- }
- if len(config.Resources.DeviceWriteIOps) > 0 && !sysInfo.BlkioWriteIOpsDevice {
- warnings = addWarning(warnings, "Your kernel does not support IOPS Block I/O write limit or the cgroup is not mounted. Block I/O IOPS write limit discarded.")
- config.Resources.DeviceWriteIOps = []string{}
- }
-
- return warnings, nil
-}
diff --git a/pkg/varlinkapi/events.go b/pkg/varlinkapi/events.go
deleted file mode 100644
index 8628b1ce6..000000000
--- a/pkg/varlinkapi/events.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- "context"
- "time"
-
- "github.com/containers/podman/v2/libpod/events"
- iopodman "github.com/containers/podman/v2/pkg/varlink"
-)
-
-// GetEvents is a remote endpoint to get events from the event log
-func (i *VarlinkAPI) GetEvents(call iopodman.VarlinkCall, filter []string, since string, until string) error {
- var (
- fromStart bool
- eventsError error
- event *events.Event
- stream bool
- )
- if call.WantsMore() {
- stream = true
- call.Continues = true
- }
- if len(since) > 0 || len(until) > 0 {
- fromStart = true
- }
- eventChannel := make(chan *events.Event)
- go func() {
- readOpts := events.ReadOptions{FromStart: fromStart, Stream: stream, Filters: filter, EventChannel: eventChannel}
- eventsError = i.Runtime.Events(context.Background(), readOpts)
- }()
- if eventsError != nil {
- return call.ReplyErrorOccurred(eventsError.Error())
- }
- for {
- event = <-eventChannel
- if event == nil {
- call.Continues = false
- break
- }
- call.ReplyGetEvents(iopodman.Event{
- Id: event.ID,
- Image: event.Image,
- Name: event.Name,
- Status: string(event.Status),
- Time: event.Time.Format(time.RFC3339Nano),
- Type: string(event.Type),
- })
- if !call.Continues {
- // For a one-shot on events, we break out here
- break
- }
- }
- return nil
-}
diff --git a/pkg/varlinkapi/funcs.go b/pkg/varlinkapi/funcs.go
deleted file mode 100644
index 8fb8a7ea0..000000000
--- a/pkg/varlinkapi/funcs.go
+++ /dev/null
@@ -1,121 +0,0 @@
-package varlinkapi
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/containers/image/v5/types"
- "github.com/containers/podman/v2/libpod/image"
- "github.com/google/shlex"
- "github.com/pkg/errors"
-)
-
-func GetSystemContext(authfile string) (*types.SystemContext, error) {
- if authfile != "" {
- if _, err := os.Stat(authfile); err != nil {
- return nil, errors.Wrapf(err, "error checking authfile path %s", authfile)
- }
- }
- return image.GetSystemContext("", authfile, false), nil
-}
-
-func substituteCommand(cmd string) (string, error) {
- var (
- newCommand string
- )
-
- // Replace cmd with "/proc/self/exe" if "podman" or "docker" is being
- // used. If "/usr/bin/docker" is provided, we also sub in podman.
- // Otherwise, leave the command unchanged.
- if cmd == "podman" || filepath.Base(cmd) == "docker" {
- newCommand = "/proc/self/exe"
- } else {
- newCommand = cmd
- }
-
- // If cmd is an absolute or relative path, check if the file exists.
- // Throw an error if it doesn't exist.
- if strings.Contains(newCommand, "/") || strings.HasPrefix(newCommand, ".") {
- res, err := filepath.Abs(newCommand)
- if err != nil {
- return "", err
- }
- if _, err := os.Stat(res); !os.IsNotExist(err) {
- return res, nil
- } else if err != nil {
- return "", err
- }
- }
-
- return newCommand, nil
-}
-
-// GenerateCommand takes a label (string) and converts it to an executable command
-func GenerateCommand(command, imageName, name, globalOpts string) ([]string, error) {
- var (
- newCommand []string
- )
- if name == "" {
- name = imageName
- }
-
- cmd, err := shlex.Split(command)
- if err != nil {
- return nil, err
- }
-
- prog, err := substituteCommand(cmd[0])
- if err != nil {
- return nil, err
- }
- newCommand = append(newCommand, prog)
-
- for _, arg := range cmd[1:] {
- var newArg string
- switch arg {
- case "IMAGE":
- newArg = imageName
- case "$IMAGE":
- newArg = imageName
- case "IMAGE=IMAGE":
- newArg = fmt.Sprintf("IMAGE=%s", imageName)
- case "IMAGE=$IMAGE":
- newArg = fmt.Sprintf("IMAGE=%s", imageName)
- case "NAME":
- newArg = name
- case "NAME=NAME":
- newArg = fmt.Sprintf("NAME=%s", name)
- case "NAME=$NAME":
- newArg = fmt.Sprintf("NAME=%s", name)
- case "$NAME":
- newArg = name
- case "$GLOBAL_OPTS":
- newArg = globalOpts
- default:
- newArg = arg
- }
- newCommand = append(newCommand, newArg)
- }
- return newCommand, nil
-}
-
-// GenerateRunEnvironment merges the current environment variables with optional
-// environment variables provided by the user
-func GenerateRunEnvironment(name, imageName string, opts map[string]string) []string {
- newEnv := os.Environ()
- newEnv = append(newEnv, fmt.Sprintf("NAME=%s", name))
- newEnv = append(newEnv, fmt.Sprintf("IMAGE=%s", imageName))
-
- if opts["opt1"] != "" {
- newEnv = append(newEnv, fmt.Sprintf("OPT1=%s", opts["opt1"]))
- }
- if opts["opt2"] != "" {
- newEnv = append(newEnv, fmt.Sprintf("OPT2=%s", opts["opt2"]))
- }
- if opts["opt3"] != "" {
- newEnv = append(newEnv, fmt.Sprintf("OPT3=%s", opts["opt3"]))
- }
- return newEnv
-}
diff --git a/pkg/varlinkapi/generate.go b/pkg/varlinkapi/generate.go
deleted file mode 100644
index bbc16dae5..000000000
--- a/pkg/varlinkapi/generate.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- "encoding/json"
-
- iopodman "github.com/containers/podman/v2/pkg/varlink"
-)
-
-// GenerateKube ...
-func (i *VarlinkAPI) GenerateKube(call iopodman.VarlinkCall, name string, service bool) error {
- pod, serv, err := GenerateKube(name, service, i.Runtime)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- podB, err := json.Marshal(pod)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- servB, err := json.Marshal(serv)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- return call.ReplyGenerateKube(iopodman.KubePodService{
- Pod: string(podB),
- Service: string(servB),
- })
-}
diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go
deleted file mode 100644
index af6c43fec..000000000
--- a/pkg/varlinkapi/images.go
+++ /dev/null
@@ -1,1037 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
- "time"
-
- "github.com/containers/buildah"
- "github.com/containers/buildah/imagebuildah"
- dockerarchive "github.com/containers/image/v5/docker/archive"
- "github.com/containers/image/v5/manifest"
- "github.com/containers/image/v5/transports/alltransports"
- "github.com/containers/image/v5/types"
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/libpod/define"
- "github.com/containers/podman/v2/libpod/image"
- "github.com/containers/podman/v2/pkg/channel"
- "github.com/containers/podman/v2/pkg/util"
- iopodman "github.com/containers/podman/v2/pkg/varlink"
- "github.com/containers/podman/v2/utils"
- "github.com/containers/storage/pkg/archive"
- v1 "github.com/opencontainers/image-spec/specs-go/v1"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-// ListImagesWithFilters returns a list of images that have been filtered
-func (i *VarlinkAPI) ListImagesWithFilters(call iopodman.VarlinkCall, filters []string) error {
- images, err := i.Runtime.ImageRuntime().GetImagesWithFilters(filters)
- if err != nil {
- return call.ReplyErrorOccurred(fmt.Sprintf("unable to get list of images %q", err))
- }
- imageList, err := imagesToImageList(images)
- if err != nil {
- return call.ReplyErrorOccurred("unable to parse response " + err.Error())
- }
- return call.ReplyListImagesWithFilters(imageList)
-}
-
-// imagesToImageList converts a slice of Images to an imagelist for varlink responses
-func imagesToImageList(images []*image.Image) ([]iopodman.Image, error) {
- var imageList []iopodman.Image
- for _, img := range images {
- labels, _ := img.Labels(getContext())
- containers, _ := img.Containers()
- repoDigests, err := img.RepoDigests()
- if err != nil {
- return nil, err
- }
-
- size, _ := img.Size(getContext())
- isParent, err := img.IsParent(context.TODO())
- if err != nil {
- return nil, err
- }
-
- i := iopodman.Image{
- Id: img.ID(),
- Digest: string(img.Digest()),
- ParentId: img.Parent,
- RepoTags: img.Names(),
- RepoDigests: repoDigests,
- Created: img.Created().Format(time.RFC3339),
- Size: int64(*size),
- VirtualSize: img.VirtualSize,
- Containers: int64(len(containers)),
- Labels: labels,
- IsParent: isParent,
- ReadOnly: img.IsReadOnly(),
- History: img.NamesHistory(),
- }
- imageList = append(imageList, i)
- }
- return imageList, nil
-}
-
-// ListImages lists all the images in the store
-// It requires no inputs.
-func (i *VarlinkAPI) ListImages(call iopodman.VarlinkCall) error {
- images, err := i.Runtime.ImageRuntime().GetImages()
- if err != nil {
- return call.ReplyErrorOccurred("unable to get list of images " + err.Error())
- }
- imageList, err := imagesToImageList(images)
- if err != nil {
- return call.ReplyErrorOccurred("unable to parse response " + err.Error())
- }
- return call.ReplyListImages(imageList)
-}
-
-// GetImage returns a single image in the form of a Image
-func (i *VarlinkAPI) GetImage(call iopodman.VarlinkCall, id string) error {
- newImage, err := i.Runtime.ImageRuntime().NewFromLocal(id)
- if err != nil {
- return call.ReplyImageNotFound(id, err.Error())
- }
- labels, err := newImage.Labels(getContext())
- if err != nil {
- return err
- }
- containers, err := newImage.Containers()
- if err != nil {
- return err
- }
- repoDigests, err := newImage.RepoDigests()
- if err != nil {
- return err
- }
- size, err := newImage.Size(getContext())
- if err != nil {
- return err
- }
-
- il := iopodman.Image{
- Id: newImage.ID(),
- ParentId: newImage.Parent,
- RepoTags: newImage.Names(),
- RepoDigests: repoDigests,
- Created: newImage.Created().Format(time.RFC3339),
- Size: int64(*size),
- VirtualSize: newImage.VirtualSize,
- Containers: int64(len(containers)),
- Labels: labels,
- TopLayer: newImage.TopLayer(),
- ReadOnly: newImage.IsReadOnly(),
- History: newImage.NamesHistory(),
- }
- return call.ReplyGetImage(il)
-}
-
-// BuildImage ...
-func (i *VarlinkAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildInfo) error {
- var (
- namespace []buildah.NamespaceOption
- imageID string
- err error
- )
-
- contextDir := config.ContextDir
-
- newContextDir, err := ioutil.TempDir("", "buildTarball")
- if err != nil {
- call.ReplyErrorOccurred("unable to create tempdir")
- }
- logrus.Debugf("created new context dir at %s", newContextDir)
-
- reader, err := os.Open(contextDir)
- if err != nil {
- logrus.Errorf("failed to open the context dir tar file")
- return call.ReplyErrorOccurred(fmt.Sprintf("unable to open context dir tar file %s", contextDir))
- }
- defer reader.Close()
- if err := archive.Untar(reader, newContextDir, &archive.TarOptions{}); err != nil {
- logrus.Errorf("fail to untar the context dir tarball (%s) to the context dir (%s)", contextDir, newContextDir)
- return call.ReplyErrorOccurred(fmt.Sprintf("unable to untar context dir %s", contextDir))
- }
- logrus.Debugf("untar of %s successful", contextDir)
- defer func() {
- if err := os.Remove(contextDir); err != nil {
- logrus.Error(err)
- }
- if err := os.RemoveAll(newContextDir); err != nil {
- logrus.Errorf("unable to delete directory '%s': %q", newContextDir, err)
- }
- }()
-
- systemContext := types.SystemContext{}
- // All output (stdout, stderr) is captured in output as well
- var output bytes.Buffer
-
- commonOpts := &buildah.CommonBuildOptions{
- AddHost: config.BuildOptions.AddHosts,
- CgroupParent: config.BuildOptions.CgroupParent,
- CPUPeriod: uint64(config.BuildOptions.CpuPeriod),
- CPUQuota: config.BuildOptions.CpuQuota,
- CPUSetCPUs: config.BuildOptions.CpusetCpus,
- CPUSetMems: config.BuildOptions.CpusetMems,
- Memory: config.BuildOptions.Memory,
- MemorySwap: config.BuildOptions.MemorySwap,
- ShmSize: config.BuildOptions.ShmSize,
- Ulimit: config.BuildOptions.Ulimit,
- Volumes: config.BuildOptions.Volume,
- }
-
- options := imagebuildah.BuildOptions{
- AddCapabilities: config.AddCapabilities,
- AdditionalTags: config.AdditionalTags,
- Annotations: config.Annotations,
- Architecture: config.Architecture,
- Args: config.BuildArgs,
- CNIConfigDir: config.CniConfigDir,
- CNIPluginPath: config.CniPluginDir,
- CommonBuildOpts: commonOpts,
- Compression: stringCompressionToArchiveType(config.Compression),
- ContextDirectory: newContextDir,
- DefaultMountsFilePath: config.DefaultsMountFilePath,
- Devices: config.Devices,
- Err: &output,
- ForceRmIntermediateCtrs: config.ForceRmIntermediateCtrs,
- IIDFile: config.Iidfile,
- Labels: config.Label,
- Layers: config.Layers,
- NamespaceOptions: namespace,
- NoCache: config.Nocache,
- OS: config.Os,
- Out: &output,
- Output: config.Output,
- OutputFormat: config.OutputFormat,
- PullPolicy: stringPullPolicyToType(config.PullPolicy),
- Quiet: config.Quiet,
- RemoveIntermediateCtrs: config.RemoteIntermediateCtrs,
- ReportWriter: &output,
- RuntimeArgs: config.RuntimeArgs,
- SignBy: config.SignBy,
- Squash: config.Squash,
- SystemContext: &systemContext,
- Target: config.Target,
- TransientMounts: config.TransientMounts,
- }
-
- if call.WantsMore() {
- call.Continues = true
- } else {
- return call.ReplyErrorOccurred("endpoint requires a more connection")
- }
-
- var newPathDockerFiles []string
-
- for _, d := range config.Dockerfiles {
- if strings.HasPrefix(d, "http://") ||
- strings.HasPrefix(d, "https://") ||
- strings.HasPrefix(d, "git://") ||
- strings.HasPrefix(d, "github.com/") {
- newPathDockerFiles = append(newPathDockerFiles, d)
- continue
- }
- base := filepath.Base(d)
- newPathDockerFiles = append(newPathDockerFiles, filepath.Join(newContextDir, base))
- }
-
- c := make(chan error)
- go func() {
- iid, _, err := i.Runtime.Build(getContext(), options, newPathDockerFiles...)
- imageID = iid
- c <- err
- close(c)
- }()
-
- var log []string
- done := false
- for {
- outputLine, err := output.ReadString('\n')
- if err == nil {
- log = append(log, outputLine)
- if call.WantsMore() {
- // we want to reply with what we have
- br := iopodman.MoreResponse{
- Logs: log,
- }
- call.ReplyBuildImage(br)
- log = []string{}
- }
- continue
- } else if err == io.EOF {
- select {
- case err := <-c:
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- done = true
- default:
- if call.WantsMore() {
- time.Sleep(1 * time.Second)
- break
- }
- }
- } else {
- return call.ReplyErrorOccurred(err.Error())
- }
- if done {
- break
- }
- }
- call.Continues = false
-
- br := iopodman.MoreResponse{
- Logs: log,
- Id: imageID,
- }
- return call.ReplyBuildImage(br)
-}
-
-// InspectImage returns an image's inspect information as a string that can be serialized.
-// Requires an image ID or name
-func (i *VarlinkAPI) InspectImage(call iopodman.VarlinkCall, name string) error {
- newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
- if err != nil {
- return call.ReplyImageNotFound(name, err.Error())
- }
- inspectInfo, err := newImage.Inspect(getContext())
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- b, err := json.Marshal(inspectInfo)
- if err != nil {
- return call.ReplyErrorOccurred(fmt.Sprintf("unable to serialize"))
- }
- return call.ReplyInspectImage(string(b))
-}
-
-// HistoryImage returns the history of the image's layers
-// Requires an image or name
-func (i *VarlinkAPI) HistoryImage(call iopodman.VarlinkCall, name string) error {
- newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
- if err != nil {
- return call.ReplyImageNotFound(name, err.Error())
- }
- history, err := newImage.History(getContext())
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- var histories []iopodman.ImageHistory
- for _, hist := range history {
- imageHistory := iopodman.ImageHistory{
- Id: hist.ID,
- Created: hist.Created.Format(time.RFC3339),
- CreatedBy: hist.CreatedBy,
- Tags: newImage.Names(),
- Size: hist.Size,
- Comment: hist.Comment,
- }
- histories = append(histories, imageHistory)
- }
- return call.ReplyHistoryImage(histories)
-}
-
-// PushImage pushes an local image to registry
-func (i *VarlinkAPI) PushImage(call iopodman.VarlinkCall, name, tag string, compress bool, format string, removeSignatures bool, signBy string) error {
- var (
- manifestType string
- )
- newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
- if err != nil {
- return call.ReplyImageNotFound(name, err.Error())
- }
- destname := name
- if tag != "" {
- destname = tag
- }
- dockerRegistryOptions := image.DockerRegistryOptions{}
- if format != "" {
- switch format {
- case "oci": // nolint
- manifestType = v1.MediaTypeImageManifest
- case "v2s1":
- manifestType = manifest.DockerV2Schema1SignedMediaType
- case "v2s2", "docker":
- manifestType = manifest.DockerV2Schema2MediaType
- default:
- return call.ReplyErrorOccurred(fmt.Sprintf("unknown format %q. Choose on of the supported formats: 'oci', 'v2s1', or 'v2s2'", format))
- }
- }
- so := image.SigningOptions{
- RemoveSignatures: removeSignatures,
- SignBy: signBy,
- }
-
- if call.WantsMore() {
- call.Continues = true
- }
-
- output := bytes.NewBuffer([]byte{})
- c := make(chan error)
- go func() {
- writer := bytes.NewBuffer([]byte{})
- err := newImage.PushImageToHeuristicDestination(getContext(), destname, manifestType, "", "", "", writer, compress, so, &dockerRegistryOptions, nil)
- if err != nil {
- c <- err
- }
- _, err = io.CopyBuffer(output, writer, nil)
- c <- err
- close(c)
- }()
-
- // TODO When pull output gets fixed for the remote client, we need to look into how we can turn below
- // into something re-usable. it is in build too
- var log []string
- done := false
- for {
- line, err := output.ReadString('\n')
- if err == nil {
- log = append(log, line)
- continue
- } else if err == io.EOF {
- select {
- case err := <-c:
- if err != nil {
- logrus.Errorf("reading of output during push failed for %s", newImage.ID())
- return call.ReplyErrorOccurred(err.Error())
- }
- done = true
- default:
- if !call.WantsMore() {
- break
- }
- br := iopodman.MoreResponse{
- Logs: log,
- Id: newImage.ID(),
- }
- call.ReplyPushImage(br)
- log = []string{}
- }
- } else {
- return call.ReplyErrorOccurred(err.Error())
- }
- if done {
- break
- }
- }
- call.Continues = false
-
- br := iopodman.MoreResponse{
- Logs: log,
- Id: newImage.ID(),
- }
- return call.ReplyPushImage(br)
-}
-
-// TagImage accepts an image name and tag as strings and tags an image in the local store.
-func (i *VarlinkAPI) TagImage(call iopodman.VarlinkCall, name, tag string) error {
- newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
- if err != nil {
- return call.ReplyImageNotFound(name, err.Error())
- }
- if err := newImage.TagImage(tag); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyTagImage(newImage.ID())
-}
-
-// UntagImage accepts an image name and tag as strings and removes the tag from the local store.
-func (i *VarlinkAPI) UntagImage(call iopodman.VarlinkCall, name, tag string) error {
- newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
- if err != nil {
- return call.ReplyImageNotFound(name, err.Error())
- }
- if err := newImage.UntagImage(tag); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyUntagImage(newImage.ID())
-}
-
-// RemoveImage accepts a image name or ID as a string and force bool to determine if it should
-// remove the image even if being used by stopped containers
-func (i *VarlinkAPI) RemoveImage(call iopodman.VarlinkCall, name string, force bool) error {
- ctx := getContext()
- newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
- if err != nil {
- return call.ReplyImageNotFound(name, err.Error())
- }
- _, err = i.Runtime.RemoveImage(ctx, newImage, force)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyRemoveImage(newImage.ID())
-}
-
-// RemoveImageWithResponse accepts an image name and force bool. It returns details about what
-// was done in removeimageresponse struct.
-func (i *VarlinkAPI) RemoveImageWithResponse(call iopodman.VarlinkCall, name string, force bool) error {
- ir := iopodman.RemoveImageResponse{}
- ctx := getContext()
- newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
- if err != nil {
- return call.ReplyImageNotFound(name, err.Error())
- }
- response, err := i.Runtime.RemoveImage(ctx, newImage, force)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- ir.Untagged = append(ir.Untagged, response.Untagged...)
- ir.Deleted = response.Deleted
- return call.ReplyRemoveImageWithResponse(ir)
-}
-
-// SearchImages searches all registries configured in /etc/containers/registries.conf for an image
-// Requires an image name and a search limit as int
-func (i *VarlinkAPI) SearchImages(call iopodman.VarlinkCall, query string, limit *int64, filter iopodman.ImageSearchFilter) error {
- // Transform all arguments to proper types first
- argLimit := 0
- argIsOfficial := types.OptionalBoolUndefined
- argIsAutomated := types.OptionalBoolUndefined
- if limit != nil {
- argLimit = int(*limit)
- }
- if filter.Is_official != nil {
- argIsOfficial = types.NewOptionalBool(*filter.Is_official)
- }
- if filter.Is_automated != nil {
- argIsAutomated = types.NewOptionalBool(*filter.Is_automated)
- }
-
- // Transform a SearchFilter the backend can deal with
- sFilter := image.SearchFilter{
- IsOfficial: argIsOfficial,
- IsAutomated: argIsAutomated,
- Stars: int(filter.Star_count),
- }
-
- searchOptions := image.SearchOptions{
- Limit: argLimit,
- Filter: sFilter,
- }
- results, err := image.SearchImages(query, searchOptions)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- var imageResults []iopodman.ImageSearchResult
- for _, result := range results {
- i := iopodman.ImageSearchResult{
- Registry: result.Index,
- Description: result.Description,
- Is_official: result.Official == "[OK]",
- Is_automated: result.Automated == "[OK]",
- Name: result.Name,
- Star_count: int64(result.Stars),
- }
- imageResults = append(imageResults, i)
- }
- return call.ReplySearchImages(imageResults)
-}
-
-// DeleteUnusedImages deletes any images that do not have containers associated with it.
-// TODO Filters are not implemented
-func (i *VarlinkAPI) DeleteUnusedImages(call iopodman.VarlinkCall) error {
- images, err := i.Runtime.ImageRuntime().GetImages()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- var deletedImages []string
- for _, img := range images {
- containers, err := img.Containers()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if len(containers) == 0 {
- if err := img.Remove(context.TODO(), false); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- deletedImages = append(deletedImages, img.ID())
- }
- }
- return call.ReplyDeleteUnusedImages(deletedImages)
-}
-
-// Commit ...
-func (i *VarlinkAPI) Commit(call iopodman.VarlinkCall, name, imageName string, changes []string, author, message string, pause bool, manifestType string) error {
- var (
- newImage *image.Image
- log []string
- mimeType string
- )
- output := channel.NewWriter(make(chan []byte))
- channelClose := func() {
- if err := output.Close(); err != nil {
- logrus.Errorf("failed to close channel writer: %q", err)
- }
- }
- defer channelClose()
-
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- rtc, err := i.Runtime.GetConfig()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- sc := image.GetSystemContext(rtc.Engine.SignaturePolicyPath, "", false)
- switch manifestType {
- case "oci", "": // nolint
- mimeType = buildah.OCIv1ImageManifest
- case "docker":
- mimeType = manifest.DockerV2Schema2MediaType
- default:
- return call.ReplyErrorOccurred(fmt.Sprintf("unrecognized image format %q", manifestType))
- }
- coptions := buildah.CommitOptions{
- SignaturePolicyPath: rtc.Engine.SignaturePolicyPath,
- ReportWriter: output,
- SystemContext: sc,
- PreferredManifestType: mimeType,
- }
- options := libpod.ContainerCommitOptions{
- CommitOptions: coptions,
- Pause: pause,
- Message: message,
- Changes: changes,
- Author: author,
- }
-
- if call.WantsMore() {
- call.Continues = true
- }
-
- c := make(chan error)
-
- go func() {
- newImage, err = ctr.Commit(getContext(), imageName, options)
- if err != nil {
- c <- err
- }
- c <- nil
- close(c)
- }()
-
- // reply is the func being sent to the output forwarder. in this case it is replying
- // with a more response struct
- reply := func(br iopodman.MoreResponse) error {
- return call.ReplyCommit(br)
- }
- log, err = forwardOutput(log, c, call.WantsMore(), output, reply)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- call.Continues = false
- br := iopodman.MoreResponse{
- Logs: log,
- Id: newImage.ID(),
- }
- return call.ReplyCommit(br)
-}
-
-// ImportImage imports an image from a tarball to the image store
-func (i *VarlinkAPI) ImportImage(call iopodman.VarlinkCall, source, reference, message string, changes []string, delete bool) error {
- configChanges, err := util.GetImageConfig(changes)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- history := []v1.History{
- {Comment: message},
- }
- config := v1.Image{
- Config: configChanges.ImageConfig,
- History: history,
- }
- newImage, err := i.Runtime.ImageRuntime().Import(getContext(), source, reference, nil, image.SigningOptions{}, config)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if delete {
- if err := os.Remove(source); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- }
-
- return call.ReplyImportImage(newImage.ID())
-}
-
-// ExportImage exports an image to the provided destination
-// destination must have the transport type!!
-func (i *VarlinkAPI) ExportImage(call iopodman.VarlinkCall, name, destination string, compress bool, tags []string) error {
- newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
- if err != nil {
- return call.ReplyImageNotFound(name, err.Error())
- }
-
- additionalTags, err := image.GetAdditionalTags(tags)
- if err != nil {
- return err
- }
-
- if err := newImage.PushImageToHeuristicDestination(getContext(), destination, "", "", "", "", nil, compress, image.SigningOptions{}, &image.DockerRegistryOptions{}, additionalTags); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyExportImage(newImage.ID())
-}
-
-// PullImage pulls an image from a registry to the image store.
-func (i *VarlinkAPI) PullImage(call iopodman.VarlinkCall, name string, creds iopodman.AuthConfig) error {
- var (
- imageID string
- err error
- )
- dockerRegistryOptions := image.DockerRegistryOptions{
- DockerRegistryCreds: &types.DockerAuthConfig{
- Username: creds.Username,
- Password: creds.Password,
- },
- }
-
- so := image.SigningOptions{}
-
- if call.WantsMore() {
- call.Continues = true
- }
- output := channel.NewWriter(make(chan []byte))
- channelClose := func() {
- if err := output.Close(); err != nil {
- logrus.Errorf("failed to close channel writer: %q", err)
- }
- }
- defer channelClose()
- c := make(chan error)
- defer close(c)
-
- go func() {
- var foundError bool
- if strings.HasPrefix(name, dockerarchive.Transport.Name()+":") {
- srcRef, err := alltransports.ParseImageName(name)
- if err != nil {
- c <- errors.Wrapf(err, "error parsing %q", name)
- }
- newImage, err := i.Runtime.ImageRuntime().LoadFromArchiveReference(getContext(), srcRef, "", output)
- if err != nil {
- foundError = true
- c <- errors.Wrapf(err, "error pulling image from %q", name)
- } else {
- imageID = newImage[0].ID()
- }
- } else {
- newImage, err := i.Runtime.ImageRuntime().New(getContext(), name, "", "", output, &dockerRegistryOptions, so, nil, util.PullImageMissing)
- if err != nil {
- foundError = true
- c <- errors.Wrapf(err, "unable to pull %s", name)
- } else {
- imageID = newImage.ID()
- }
- }
- if !foundError {
- c <- nil
- }
- }()
-
- var log []string
- reply := func(br iopodman.MoreResponse) error {
- return call.ReplyPullImage(br)
- }
- log, err = forwardOutput(log, c, call.WantsMore(), output, reply)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- call.Continues = false
- br := iopodman.MoreResponse{
- Logs: log,
- Id: imageID,
- }
- return call.ReplyPullImage(br)
-}
-
-// ImageExists returns bool as to whether the input image exists in local storage
-func (i *VarlinkAPI) ImageExists(call iopodman.VarlinkCall, name string) error {
- _, err := i.Runtime.ImageRuntime().NewFromLocal(name)
- if errors.Cause(err) == image.ErrNoSuchImage {
- return call.ReplyImageExists(1)
- }
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyImageExists(0)
-}
-
-// ContainerRunlabel ...
-func (i *VarlinkAPI) ContainerRunlabel(call iopodman.VarlinkCall, input iopodman.Runlabel) error {
- ctx := getContext()
- dockerRegistryOptions := image.DockerRegistryOptions{}
- stdErr := os.Stderr
- stdOut := os.Stdout
- stdIn := os.Stdin
-
- runLabel, imageName, err := GetRunlabel(input.Label, input.Image, ctx, i.Runtime, input.Pull, "", dockerRegistryOptions, input.Authfile, "", nil)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if runLabel == "" {
- return call.ReplyErrorOccurred(fmt.Sprintf("%s does not contain the label %s", input.Image, input.Label))
- }
-
- cmd, env, err := GenerateRunlabelCommand(runLabel, imageName, input.Name, input.Opts, input.ExtraArgs, "")
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if err := utils.ExecCmdWithStdStreams(stdIn, stdOut, stdErr, env, cmd[0], cmd[1:]...); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyContainerRunlabel()
-}
-
-// ImagesPrune ....
-func (i *VarlinkAPI) ImagesPrune(call iopodman.VarlinkCall, all bool, filter []string) error {
- prunedImages, err := i.Runtime.ImageRuntime().PruneImages(context.TODO(), all, []string{})
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyImagesPrune(prunedImages)
-}
-
-// ImageSave ....
-func (i *VarlinkAPI) ImageSave(call iopodman.VarlinkCall, options iopodman.ImageSaveOptions) error {
- newImage, err := i.Runtime.ImageRuntime().NewFromLocal(options.Name)
- if err != nil {
- if errors.Cause(err) == define.ErrNoSuchImage {
- return call.ReplyImageNotFound(options.Name, err.Error())
- }
- return call.ReplyErrorOccurred(err.Error())
- }
-
- // Determine if we are dealing with a tarball or dir
- var output string
- outputToDir := false
- if options.Format == "oci-archive" || options.Format == "docker-archive" {
- tempfile, err := ioutil.TempFile("", "varlink_send")
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- output = tempfile.Name()
- tempfile.Close()
- } else {
- var err error
- outputToDir = true
- output, err = ioutil.TempDir("", "varlink_send")
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- }
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if call.WantsMore() {
- call.Continues = true
- }
-
- saveOutput := bytes.NewBuffer([]byte{})
- c := make(chan error)
- go func() {
- err := newImage.Save(getContext(), options.Name, options.Format, output, options.MoreTags, options.Quiet, options.Compress, true)
- c <- err
- close(c)
- }()
- var log []string
- done := false
- for {
- line, err := saveOutput.ReadString('\n')
- if err == nil {
- log = append(log, line)
- continue
- } else if err == io.EOF {
- select {
- case err := <-c:
- if err != nil {
- logrus.Errorf("reading of output during save failed for %s", newImage.ID())
- return call.ReplyErrorOccurred(err.Error())
- }
- done = true
- default:
- if !call.WantsMore() {
- break
- }
- br := iopodman.MoreResponse{
- Logs: log,
- }
- call.ReplyImageSave(br)
- log = []string{}
- }
- } else {
- return call.ReplyErrorOccurred(err.Error())
- }
- if done {
- break
- }
- }
- call.Continues = false
-
- sendfile := output
- // Image has been saved to `output`
- if outputToDir {
- // If the output is a directory, we need to tar up the directory to send it back
- // Create a tempfile for the directory tarball
- outputFile, err := ioutil.TempFile("", "varlink_save_dir")
- if err != nil {
- return err
- }
- defer outputFile.Close()
- if err := utils.TarToFilesystem(output, outputFile); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- sendfile = outputFile.Name()
- }
- br := iopodman.MoreResponse{
- Logs: log,
- Id: sendfile,
- }
- return call.ReplyPushImage(br)
-}
-
-// LoadImage ...
-func (i *VarlinkAPI) LoadImage(call iopodman.VarlinkCall, name, inputFile string, deleteInputFile, quiet bool) error {
- var (
- names string
- writer io.Writer
- err error
- )
- if !quiet {
- writer = os.Stderr
- }
-
- if call.WantsMore() {
- call.Continues = true
- }
- output := bytes.NewBuffer([]byte{})
-
- c := make(chan error)
- go func() {
- names, err = i.Runtime.LoadImage(getContext(), name, inputFile, writer, "")
- c <- err
- close(c)
- }()
-
- var log []string
- done := false
- for {
- line, err := output.ReadString('\n')
- if err == nil {
- log = append(log, line)
- continue
- } else if err == io.EOF {
- select {
- case err := <-c:
- if err != nil {
- logrus.Error(err)
- return call.ReplyErrorOccurred(err.Error())
- }
- done = true
- default:
- if !call.WantsMore() {
- break
- }
- br := iopodman.MoreResponse{
- Logs: log,
- }
- call.ReplyLoadImage(br)
- log = []string{}
- }
- } else {
- return call.ReplyErrorOccurred(err.Error())
- }
- if done {
- break
- }
- }
- call.Continues = false
-
- br := iopodman.MoreResponse{
- Logs: log,
- Id: names,
- }
- if deleteInputFile {
- if err := os.Remove(inputFile); err != nil {
- logrus.Errorf("unable to delete input file %s", inputFile)
- }
- }
- return call.ReplyLoadImage(br)
-}
-
-// Diff ...
-func (i *VarlinkAPI) Diff(call iopodman.VarlinkCall, name string) error {
- var response []iopodman.DiffInfo
- changes, err := i.Runtime.GetDiff("", name)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- for _, change := range changes {
- response = append(response, iopodman.DiffInfo{Path: change.Path, ChangeType: change.Kind.String()})
- }
- return call.ReplyDiff(response)
-}
-
-// GetLayersMapWithImageInfo is a development only endpoint to obtain layer information for an image.
-func (i *VarlinkAPI) GetLayersMapWithImageInfo(call iopodman.VarlinkCall) error {
- layerInfo, err := image.GetLayersMapWithImageInfo(i.Runtime.ImageRuntime())
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- b, err := json.Marshal(layerInfo)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyGetLayersMapWithImageInfo(string(b))
-}
-
-// BuildImageHierarchyMap ...
-func (i *VarlinkAPI) BuildImageHierarchyMap(call iopodman.VarlinkCall, name string) error {
- img, err := i.Runtime.ImageRuntime().NewFromLocal(name)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- imageInfo := &image.InfoImage{
- ID: img.ID(),
- Tags: img.Names(),
- }
- layerInfo, err := image.GetLayersMapWithImageInfo(i.Runtime.ImageRuntime())
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if err := image.BuildImageHierarchyMap(imageInfo, layerInfo, img.TopLayer()); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- b, err := json.Marshal(imageInfo)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyBuildImageHierarchyMap(string(b))
-}
-
-// ImageTree returns the image tree string for the provided image name or ID
-func (i *VarlinkAPI) ImageTree(call iopodman.VarlinkCall, nameOrID string, whatRequires bool) error {
- img, err := i.Runtime.ImageRuntime().NewFromLocal(nameOrID)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- tree, err := img.GenerateTree(whatRequires)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyImageTree(tree)
-}
diff --git a/pkg/varlinkapi/intermediate.go b/pkg/varlinkapi/intermediate.go
deleted file mode 100644
index f04665a86..000000000
--- a/pkg/varlinkapi/intermediate.go
+++ /dev/null
@@ -1,289 +0,0 @@
-package varlinkapi
-
-import (
- "github.com/sirupsen/logrus"
-)
-
-/*
-attention
-
-in this file you will see a lot of struct duplication. this was done because people wanted a strongly typed
-varlink mechanism. this resulted in us creating this intermediate layer that allows us to take the input
-from the cli and make an intermediate layer which can be transferred as strongly typed structures over a varlink
-interface.
-
-we intentionally avoided heavy use of reflection here because we were concerned about performance impacts to the
-non-varlink intermediate layer generation.
-*/
-
-// GenericCLIResult describes the overall interface for dealing with
-// the create command cli in both local and remote uses
-type GenericCLIResult interface {
- IsSet() bool
- Name() string
- Value() interface{}
-}
-
-// CRStringSlice describes a string slice cli struct
-type CRStringSlice struct {
- Val []string
- createResult
-}
-
-// CRString describes a string cli struct
-type CRString struct {
- Val string
- createResult
-}
-
-// CRUint64 describes a uint64 cli struct
-type CRUint64 struct {
- Val uint64
- createResult
-}
-
-// CRFloat64 describes a float64 cli struct
-type CRFloat64 struct {
- Val float64
- createResult
-}
-
-//CRBool describes a bool cli struct
-type CRBool struct {
- Val bool
- createResult
-}
-
-// CRInt64 describes an int64 cli struct
-type CRInt64 struct {
- Val int64
- createResult
-}
-
-// CRUint describes a uint cli struct
-type CRUint struct {
- Val uint
- createResult
-}
-
-// CRInt describes an int cli struct
-type CRInt struct {
- Val int
- createResult
-}
-
-// CRStringArray describes a stringarray cli struct
-type CRStringArray struct {
- Val []string
- createResult
-}
-
-type createResult struct {
- Flag string
- Changed bool
-}
-
-// GenericCLIResults in the intermediate object between the cobra cli
-// and createconfig
-type GenericCLIResults struct {
- results map[string]GenericCLIResult
- InputArgs []string
-}
-
-// IsSet returns a bool if the flag was changed
-func (f GenericCLIResults) IsSet(flag string) bool {
- r := f.findResult(flag)
- if r == nil {
- return false
- }
- return r.IsSet()
-}
-
-// Value returns the value of the cli flag
-func (f GenericCLIResults) Value(flag string) interface{} {
- r := f.findResult(flag)
- if r == nil {
- return ""
- }
- return r.Value()
-}
-
-func (f GenericCLIResults) findResult(flag string) GenericCLIResult {
- val, ok := f.results[flag]
- if ok {
- return val
- }
- logrus.Debugf("unable to find flag %s", flag)
- return nil
-}
-
-// Bool is a wrapper to get a bool value from GenericCLIResults
-func (f GenericCLIResults) Bool(flag string) bool {
- r := f.findResult(flag)
- if r == nil {
- return false
- }
- return r.Value().(bool)
-}
-
-// String is a wrapper to get a string value from GenericCLIResults
-func (f GenericCLIResults) String(flag string) string {
- r := f.findResult(flag)
- if r == nil {
- return ""
- }
- return r.Value().(string)
-}
-
-// Uint is a wrapper to get an uint value from GenericCLIResults
-func (f GenericCLIResults) Uint(flag string) uint {
- r := f.findResult(flag)
- if r == nil {
- return 0
- }
- return r.Value().(uint)
-}
-
-// StringSlice is a wrapper to get a stringslice value from GenericCLIResults
-func (f GenericCLIResults) StringSlice(flag string) []string {
- r := f.findResult(flag)
- if r == nil {
- return []string{}
- }
- return r.Value().([]string)
-}
-
-// StringArray is a wrapper to get a stringslice value from GenericCLIResults
-func (f GenericCLIResults) StringArray(flag string) []string {
- r := f.findResult(flag)
- if r == nil {
- return []string{}
- }
- return r.Value().([]string)
-}
-
-// Uint64 is a wrapper to get an uint64 value from GenericCLIResults
-func (f GenericCLIResults) Uint64(flag string) uint64 {
- r := f.findResult(flag)
- if r == nil {
- return 0
- }
- return r.Value().(uint64)
-}
-
-// Int64 is a wrapper to get an int64 value from GenericCLIResults
-func (f GenericCLIResults) Int64(flag string) int64 {
- r := f.findResult(flag)
- if r == nil {
- return 0
- }
- return r.Value().(int64)
-}
-
-// Int is a wrapper to get an int value from GenericCLIResults
-func (f GenericCLIResults) Int(flag string) int {
- r := f.findResult(flag)
- if r == nil {
- return 0
- }
- return r.Value().(int)
-}
-
-// Float64 is a wrapper to get an float64 value from GenericCLIResults
-func (f GenericCLIResults) Float64(flag string) float64 {
- r := f.findResult(flag)
- if r == nil {
- return 0
- }
- return r.Value().(float64)
-}
-
-// Float64 is a wrapper to get an float64 value from GenericCLIResults
-func (f GenericCLIResults) Changed(flag string) bool {
- r := f.findResult(flag)
- if r == nil {
- return false
- }
- return r.IsSet()
-}
-
-// IsSet ...
-func (c CRStringSlice) IsSet() bool { return c.Changed }
-
-// Name ...
-func (c CRStringSlice) Name() string { return c.Flag }
-
-// Value ...
-func (c CRStringSlice) Value() interface{} { return c.Val }
-
-// IsSet ...
-func (c CRString) IsSet() bool { return c.Changed }
-
-// Name ...
-func (c CRString) Name() string { return c.Flag }
-
-// Value ...
-func (c CRString) Value() interface{} { return c.Val }
-
-// IsSet ...
-func (c CRUint64) IsSet() bool { return c.Changed }
-
-// Name ...
-func (c CRUint64) Name() string { return c.Flag }
-
-// Value ...
-func (c CRUint64) Value() interface{} { return c.Val }
-
-// IsSet ...
-func (c CRFloat64) IsSet() bool { return c.Changed }
-
-// Name ...
-func (c CRFloat64) Name() string { return c.Flag }
-
-// Value ...
-func (c CRFloat64) Value() interface{} { return c.Val }
-
-// IsSet ...
-func (c CRBool) IsSet() bool { return c.Changed }
-
-// Name ...
-func (c CRBool) Name() string { return c.Flag }
-
-// Value ...
-func (c CRBool) Value() interface{} { return c.Val }
-
-// IsSet ...
-func (c CRInt64) IsSet() bool { return c.Changed }
-
-// Name ...
-func (c CRInt64) Name() string { return c.Flag }
-
-// Value ...
-func (c CRInt64) Value() interface{} { return c.Val }
-
-// IsSet ...
-func (c CRUint) IsSet() bool { return c.Changed }
-
-// Name ...
-func (c CRUint) Name() string { return c.Flag }
-
-// Value ...
-func (c CRUint) Value() interface{} { return c.Val }
-
-// IsSet ...
-func (c CRInt) IsSet() bool { return c.Changed }
-
-// Name ...
-func (c CRInt) Name() string { return c.Flag }
-
-// Value ...
-func (c CRInt) Value() interface{} { return c.Val }
-
-// IsSet ...
-func (c CRStringArray) IsSet() bool { return c.Changed }
-
-// Name ...
-func (c CRStringArray) Name() string { return c.Flag }
-
-// Value ...
-func (c CRStringArray) Value() interface{} { return c.Val }
diff --git a/pkg/varlinkapi/intermediate_varlink.go b/pkg/varlinkapi/intermediate_varlink.go
deleted file mode 100644
index 0d74f1a95..000000000
--- a/pkg/varlinkapi/intermediate_varlink.go
+++ /dev/null
@@ -1,457 +0,0 @@
-// +build varlink remoteclient
-
-package varlinkapi
-
-import (
- "github.com/containers/common/pkg/config"
- "github.com/containers/podman/v2/pkg/rootless"
- iopodman "github.com/containers/podman/v2/pkg/varlink"
- "github.com/pkg/errors"
-)
-
-//FIXME these are duplicated here to resolve a circular
-//import with cmd/podman/common.
-var (
- // DefaultHealthCheckInterval default value
- DefaultHealthCheckInterval = "30s"
- // DefaultHealthCheckRetries default value
- DefaultHealthCheckRetries uint = 3
- // DefaultHealthCheckStartPeriod default value
- DefaultHealthCheckStartPeriod = "0s"
- // DefaultHealthCheckTimeout default value
- DefaultHealthCheckTimeout = "30s"
- // DefaultImageVolume default value
- DefaultImageVolume = "bind"
-)
-
-// StringSliceToPtr converts a genericcliresult value into a *[]string
-func StringSliceToPtr(g GenericCLIResult) *[]string {
- if !g.IsSet() {
- return nil
- }
- newT := g.Value().([]string)
- return &newT
-}
-
-// StringToPtr converts a genericcliresult value into a *string
-func StringToPtr(g GenericCLIResult) *string {
- if !g.IsSet() {
- return nil
- }
- newT := g.Value().(string)
- return &newT
-}
-
-// BoolToPtr converts a genericcliresult value into a *bool
-func BoolToPtr(g GenericCLIResult) *bool {
- if !g.IsSet() {
- return nil
- }
- newT := g.Value().(bool)
- return &newT
-}
-
-// AnyIntToInt64Ptr converts a genericcliresult value into an *int64
-func AnyIntToInt64Ptr(g GenericCLIResult) *int64 {
- if !g.IsSet() {
- return nil
- }
- var newT int64
- switch g.Value().(type) {
- case int:
- newT = int64(g.Value().(int))
- case int64:
- newT = g.Value().(int64)
- case uint64:
- newT = int64(g.Value().(uint64))
- case uint:
- newT = int64(g.Value().(uint))
- default:
- panic(errors.Errorf("invalid int type"))
- }
- return &newT
-}
-
-// Float64ToPtr converts a genericcliresult into a *float64
-func Float64ToPtr(g GenericCLIResult) *float64 {
- if !g.IsSet() {
- return nil
- }
- newT := g.Value().(float64)
- return &newT
-}
-
-// MakeVarlink creates a varlink transportable struct from GenericCLIResults
-func (g GenericCLIResults) MakeVarlink() iopodman.Create {
- v := iopodman.Create{
- Args: g.InputArgs,
- AddHost: StringSliceToPtr(g.Find("add-host")),
- Annotation: StringSliceToPtr(g.Find("annotation")),
- Attach: StringSliceToPtr(g.Find("attach")),
- BlkioWeight: StringToPtr(g.Find("blkio-weight")),
- BlkioWeightDevice: StringSliceToPtr(g.Find("blkio-weight-device")),
- CapAdd: StringSliceToPtr(g.Find("cap-add")),
- CapDrop: StringSliceToPtr(g.Find("cap-drop")),
- CgroupParent: StringToPtr(g.Find("cgroup-parent")),
- CidFile: StringToPtr(g.Find("cidfile")),
- ConmonPidfile: StringToPtr(g.Find("conmon-pidfile")),
- CpuPeriod: AnyIntToInt64Ptr(g.Find("cpu-period")),
- CpuQuota: AnyIntToInt64Ptr(g.Find("cpu-quota")),
- CpuRtPeriod: AnyIntToInt64Ptr(g.Find("cpu-rt-period")),
- CpuRtRuntime: AnyIntToInt64Ptr(g.Find("cpu-rt-runtime")),
- CpuShares: AnyIntToInt64Ptr(g.Find("cpu-shares")),
- Cpus: Float64ToPtr(g.Find("cpus")),
- CpuSetCpus: StringToPtr(g.Find("cpuset-cpus")),
- CpuSetMems: StringToPtr(g.Find("cpuset-mems")),
- Detach: BoolToPtr(g.Find("detach")),
- DetachKeys: StringToPtr(g.Find("detach-keys")),
- Device: StringSliceToPtr(g.Find("device")),
- DeviceReadBps: StringSliceToPtr(g.Find("device-read-bps")),
- DeviceReadIops: StringSliceToPtr(g.Find("device-read-iops")),
- DeviceWriteBps: StringSliceToPtr(g.Find("device-write-bps")),
- DeviceWriteIops: StringSliceToPtr(g.Find("device-write-iops")),
- Dns: StringSliceToPtr(g.Find("dns")),
- DnsOpt: StringSliceToPtr(g.Find("dns-opt")),
- DnsSearch: StringSliceToPtr(g.Find("dns-search")),
- Entrypoint: StringToPtr(g.Find("entrypoint")),
- Env: StringSliceToPtr(g.Find("env")),
- EnvFile: StringSliceToPtr(g.Find("env-file")),
- Expose: StringSliceToPtr(g.Find("expose")),
- Gidmap: StringSliceToPtr(g.Find("gidmap")),
- Groupadd: StringSliceToPtr(g.Find("group-add")),
- HealthcheckCommand: StringToPtr(g.Find("healthcheck-command")),
- HealthcheckInterval: StringToPtr(g.Find("healthcheck-interval")),
- HealthcheckRetries: AnyIntToInt64Ptr(g.Find("healthcheck-retries")),
- HealthcheckStartPeriod: StringToPtr(g.Find("healthcheck-start-period")),
- HealthcheckTimeout: StringToPtr(g.Find("healthcheck-timeout")),
- Hostname: StringToPtr(g.Find("hostname")),
- ImageVolume: StringToPtr(g.Find("image-volume")),
- Init: BoolToPtr(g.Find("init")),
- InitPath: StringToPtr(g.Find("init-path")),
- Interactive: BoolToPtr(g.Find("interactive")),
- Ip: StringToPtr(g.Find("ip")),
- Ipc: StringToPtr(g.Find("ipc")),
- KernelMemory: StringToPtr(g.Find("kernel-memory")),
- Label: StringSliceToPtr(g.Find("label")),
- LabelFile: StringSliceToPtr(g.Find("label-file")),
- LogDriver: StringToPtr(g.Find("log-driver")),
- LogOpt: StringSliceToPtr(g.Find("log-opt")),
- MacAddress: StringToPtr(g.Find("mac-address")),
- Memory: StringToPtr(g.Find("memory")),
- MemoryReservation: StringToPtr(g.Find("memory-reservation")),
- MemorySwap: StringToPtr(g.Find("memory-swap")),
- MemorySwappiness: AnyIntToInt64Ptr(g.Find("memory-swappiness")),
- Name: StringToPtr(g.Find("name")),
- Network: StringToPtr(g.Find("network")),
- OomKillDisable: BoolToPtr(g.Find("oom-kill-disable")),
- OomScoreAdj: AnyIntToInt64Ptr(g.Find("oom-score-adj")),
- OverrideOS: StringToPtr(g.Find("override-os")),
- OverrideArch: StringToPtr(g.Find("override-arch")),
- Pid: StringToPtr(g.Find("pid")),
- PidsLimit: AnyIntToInt64Ptr(g.Find("pids-limit")),
- Pod: StringToPtr(g.Find("pod")),
- Privileged: BoolToPtr(g.Find("privileged")),
- Publish: StringSliceToPtr(g.Find("publish")),
- PublishAll: BoolToPtr(g.Find("publish-all")),
- Pull: StringToPtr(g.Find("pull")),
- Quiet: BoolToPtr(g.Find("quiet")),
- Readonly: BoolToPtr(g.Find("read-only")),
- Readonlytmpfs: BoolToPtr(g.Find("read-only-tmpfs")),
- Restart: StringToPtr(g.Find("restart")),
- Rm: BoolToPtr(g.Find("rm")),
- Rootfs: BoolToPtr(g.Find("rootfs")),
- SecurityOpt: StringSliceToPtr(g.Find("security-opt")),
- ShmSize: StringToPtr(g.Find("shm-size")),
- StopSignal: StringToPtr(g.Find("stop-signal")),
- StopTimeout: AnyIntToInt64Ptr(g.Find("stop-timeout")),
- StorageOpt: StringSliceToPtr(g.Find("storage-opt")),
- Subuidname: StringToPtr(g.Find("subuidname")),
- Subgidname: StringToPtr(g.Find("subgidname")),
- Sysctl: StringSliceToPtr(g.Find("sysctl")),
- Systemd: StringToPtr(g.Find("systemd")),
- Tmpfs: StringSliceToPtr(g.Find("tmpfs")),
- Tty: BoolToPtr(g.Find("tty")),
- Uidmap: StringSliceToPtr(g.Find("uidmap")),
- Ulimit: StringSliceToPtr(g.Find("ulimit")),
- User: StringToPtr(g.Find("user")),
- Userns: StringToPtr(g.Find("userns")),
- Uts: StringToPtr(g.Find("uts")),
- Mount: StringSliceToPtr(g.Find("mount")),
- Volume: StringSliceToPtr(g.Find("volume")),
- VolumesFrom: StringSliceToPtr(g.Find("volumes-from")),
- WorkDir: StringToPtr(g.Find("workdir")),
- }
-
- return v
-}
-
-func stringSliceFromVarlink(v *[]string, flagName string, defaultValue *[]string) CRStringSlice {
- cr := CRStringSlice{}
- if v == nil {
- cr.Val = []string{}
- if defaultValue != nil {
- cr.Val = *defaultValue
- }
- cr.Changed = false
- } else {
- cr.Val = *v
- cr.Changed = true
- }
- cr.Flag = flagName
- return cr
-}
-
-func stringFromVarlink(v *string, flagName string, defaultValue *string) CRString {
- cr := CRString{}
- if v == nil {
- cr.Val = ""
- if defaultValue != nil {
- cr.Val = *defaultValue
- }
- cr.Changed = false
- } else {
- cr.Val = *v
- cr.Changed = true
- }
- cr.Flag = flagName
- return cr
-}
-
-func boolFromVarlink(v *bool, flagName string, defaultValue bool) CRBool {
- cr := CRBool{}
- if v == nil {
- // In case a cli bool default value is true
- cr.Val = defaultValue
- cr.Changed = false
- } else {
- cr.Val = *v
- cr.Changed = true
- }
- cr.Flag = flagName
- return cr
-}
-
-func uint64FromVarlink(v *int64, flagName string, defaultValue *uint64) CRUint64 {
- cr := CRUint64{}
- if v == nil {
- cr.Val = 0
- if defaultValue != nil {
- cr.Val = *defaultValue
- }
- cr.Changed = false
- } else {
- cr.Val = uint64(*v)
- cr.Changed = true
- }
- cr.Flag = flagName
- return cr
-}
-
-func int64FromVarlink(v *int64, flagName string, defaultValue *int64) CRInt64 {
- cr := CRInt64{}
- if v == nil {
- cr.Val = 0
- if defaultValue != nil {
- cr.Val = *defaultValue
- }
- cr.Changed = false
- } else {
- cr.Val = *v
- cr.Changed = true
- }
- cr.Flag = flagName
- return cr
-}
-
-func float64FromVarlink(v *float64, flagName string, defaultValue *float64) CRFloat64 {
- cr := CRFloat64{}
- if v == nil {
- cr.Val = 0
- if defaultValue != nil {
- cr.Val = *defaultValue
- }
- cr.Changed = false
- } else {
- cr.Val = *v
- cr.Changed = true
- }
- cr.Flag = flagName
- return cr
-}
-
-func uintFromVarlink(v *int64, flagName string, defaultValue *uint) CRUint {
- cr := CRUint{}
- if v == nil {
- cr.Val = 0
- if defaultValue != nil {
- cr.Val = *defaultValue
- }
- cr.Changed = false
- } else {
- cr.Val = uint(*v)
- cr.Changed = true
- }
- cr.Flag = flagName
- return cr
-}
-
-func stringArrayFromVarlink(v *[]string, flagName string, defaultValue *[]string) CRStringArray {
- cr := CRStringArray{}
- if v == nil {
- cr.Val = []string{}
- if defaultValue != nil {
- cr.Val = *defaultValue
- }
- cr.Changed = false
- } else {
- cr.Val = *v
- cr.Changed = true
- }
- cr.Flag = flagName
- return cr
-}
-
-func intFromVarlink(v *int64, flagName string, defaultValue *int) CRInt {
- cr := CRInt{}
- if v == nil {
- if defaultValue != nil {
- cr.Val = *defaultValue
- }
- cr.Val = 0
- cr.Changed = false
- } else {
- cr.Val = int(*v)
- cr.Changed = true
- }
- cr.Flag = flagName
- return cr
-}
-
-// VarlinkCreateToGeneric creates a GenericCLIResults from the varlink create
-// structure.
-func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults {
- // FIXME this will need to be fixed!!!!! With containers conf
- //containerConfig := cliconfig.GetDefaultConfig()
- // TODO | WARN
- // We do not get a default network over varlink. Unlike the other default values for some cli
- // elements, it seems it gets set to the default anyway.
-
- var memSwapDefault int64 = -1
- netModeDefault := "bridge"
- systemdDefault := "true"
- if rootless.IsRootless() {
- netModeDefault = "slirp4netns"
- }
-
- shmSize := config.DefaultShmSize
-
- m := make(map[string]GenericCLIResult)
- m["add-host"] = stringSliceFromVarlink(opts.AddHost, "add-host", nil)
- m["annotation"] = stringSliceFromVarlink(opts.Annotation, "annotation", nil)
- m["attach"] = stringSliceFromVarlink(opts.Attach, "attach", nil)
- m["blkio-weight"] = stringFromVarlink(opts.BlkioWeight, "blkio-weight", nil)
- m["blkio-weight-device"] = stringSliceFromVarlink(opts.BlkioWeightDevice, "blkio-weight-device", nil)
- m["cap-add"] = stringSliceFromVarlink(opts.CapAdd, "cap-add", nil)
- m["cap-drop"] = stringSliceFromVarlink(opts.CapDrop, "cap-drop", nil)
- m["cgroup-parent"] = stringFromVarlink(opts.CgroupParent, "cgroup-parent", nil)
- m["cidfile"] = stringFromVarlink(opts.CidFile, "cidfile", nil)
- m["conmon-pidfile"] = stringFromVarlink(opts.ConmonPidfile, "conmon-file", nil)
- m["cpu-period"] = uint64FromVarlink(opts.CpuPeriod, "cpu-period", nil)
- m["cpu-quota"] = int64FromVarlink(opts.CpuQuota, "quota", nil)
- m["cpu-rt-period"] = uint64FromVarlink(opts.CpuRtPeriod, "cpu-rt-period", nil)
- m["cpu-rt-runtime"] = int64FromVarlink(opts.CpuRtRuntime, "cpu-rt-quota", nil)
- m["cpu-shares"] = uint64FromVarlink(opts.CpuShares, "cpu-shares", nil)
- m["cpus"] = float64FromVarlink(opts.Cpus, "cpus", nil)
- m["cpuset-cpus"] = stringFromVarlink(opts.CpuSetCpus, "cpuset-cpus", nil)
- m["cpuset-mems"] = stringFromVarlink(opts.CpuSetMems, "cpuset-mems", nil)
- m["detach"] = boolFromVarlink(opts.Detach, "detach", false)
- m["detach-keys"] = stringFromVarlink(opts.DetachKeys, "detach-keys", nil)
- m["device"] = stringSliceFromVarlink(opts.Device, "device", nil)
- m["device-read-bps"] = stringSliceFromVarlink(opts.DeviceReadBps, "device-read-bps", nil)
- m["device-read-iops"] = stringSliceFromVarlink(opts.DeviceReadIops, "device-read-iops", nil)
- m["device-write-bps"] = stringSliceFromVarlink(opts.DeviceWriteBps, "write-device-bps", nil)
- m["device-write-iops"] = stringSliceFromVarlink(opts.DeviceWriteIops, "write-device-iops", nil)
- m["dns"] = stringSliceFromVarlink(opts.Dns, "dns", nil)
- m["dns-opt"] = stringSliceFromVarlink(opts.DnsOpt, "dns-opt", nil)
- m["dns-search"] = stringSliceFromVarlink(opts.DnsSearch, "dns-search", nil)
- m["entrypoint"] = stringFromVarlink(opts.Entrypoint, "entrypoint", nil)
- m["env"] = stringArrayFromVarlink(opts.Env, "env", nil)
- m["env-file"] = stringSliceFromVarlink(opts.EnvFile, "env-file", nil)
- m["expose"] = stringSliceFromVarlink(opts.Expose, "expose", nil)
- m["gidmap"] = stringSliceFromVarlink(opts.Gidmap, "gidmap", nil)
- m["group-add"] = stringSliceFromVarlink(opts.Groupadd, "group-add", nil)
- m["healthcheck-command"] = stringFromVarlink(opts.HealthcheckCommand, "healthcheck-command", nil)
- m["healthcheck-interval"] = stringFromVarlink(opts.HealthcheckInterval, "healthcheck-interval", &DefaultHealthCheckInterval)
- m["healthcheck-retries"] = uintFromVarlink(opts.HealthcheckRetries, "healthcheck-retries", &DefaultHealthCheckRetries)
- m["healthcheck-start-period"] = stringFromVarlink(opts.HealthcheckStartPeriod, "healthcheck-start-period", &DefaultHealthCheckStartPeriod)
- m["healthcheck-timeout"] = stringFromVarlink(opts.HealthcheckTimeout, "healthcheck-timeout", &DefaultHealthCheckTimeout)
- m["hostname"] = stringFromVarlink(opts.Hostname, "hostname", nil)
- m["image-volume"] = stringFromVarlink(opts.ImageVolume, "image-volume", &DefaultImageVolume)
- m["init"] = boolFromVarlink(opts.Init, "init", false)
- m["init-path"] = stringFromVarlink(opts.InitPath, "init-path", nil)
- m["interactive"] = boolFromVarlink(opts.Interactive, "interactive", false)
- m["ip"] = stringFromVarlink(opts.Ip, "ip", nil)
- m["ipc"] = stringFromVarlink(opts.Ipc, "ipc", nil)
- m["kernel-memory"] = stringFromVarlink(opts.KernelMemory, "kernel-memory", nil)
- m["label"] = stringArrayFromVarlink(opts.Label, "label", nil)
- m["label-file"] = stringSliceFromVarlink(opts.LabelFile, "label-file", nil)
- m["log-driver"] = stringFromVarlink(opts.LogDriver, "log-driver", nil)
- m["log-opt"] = stringSliceFromVarlink(opts.LogOpt, "log-opt", nil)
- m["mac-address"] = stringFromVarlink(opts.MacAddress, "mac-address", nil)
- m["memory"] = stringFromVarlink(opts.Memory, "memory", nil)
- m["memory-reservation"] = stringFromVarlink(opts.MemoryReservation, "memory-reservation", nil)
- m["memory-swap"] = stringFromVarlink(opts.MemorySwap, "memory-swap", nil)
- m["memory-swappiness"] = int64FromVarlink(opts.MemorySwappiness, "memory-swappiness", &memSwapDefault)
- m["name"] = stringFromVarlink(opts.Name, "name", nil)
- m["network"] = stringFromVarlink(opts.Network, "network", &netModeDefault)
- m["no-hosts"] = boolFromVarlink(opts.NoHosts, "no-hosts", false)
- m["oom-kill-disable"] = boolFromVarlink(opts.OomKillDisable, "oon-kill-disable", false)
- m["oom-score-adj"] = intFromVarlink(opts.OomScoreAdj, "oom-score-adj", nil)
- m["override-os"] = stringFromVarlink(opts.OverrideOS, "override-os", nil)
- m["override-arch"] = stringFromVarlink(opts.OverrideArch, "override-arch", nil)
- m["pid"] = stringFromVarlink(opts.Pid, "pid", nil)
- m["pids-limit"] = int64FromVarlink(opts.PidsLimit, "pids-limit", nil)
- m["pod"] = stringFromVarlink(opts.Pod, "pod", nil)
- m["privileged"] = boolFromVarlink(opts.Privileged, "privileged", false)
- m["publish"] = stringSliceFromVarlink(opts.Publish, "publish", nil)
- m["publish-all"] = boolFromVarlink(opts.PublishAll, "publish-all", false)
- m["pull"] = stringFromVarlink(opts.Pull, "missing", nil)
- m["quiet"] = boolFromVarlink(opts.Quiet, "quiet", false)
- m["read-only"] = boolFromVarlink(opts.Readonly, "read-only", false)
- m["read-only-tmpfs"] = boolFromVarlink(opts.Readonlytmpfs, "read-only-tmpfs", true)
- m["restart"] = stringFromVarlink(opts.Restart, "restart", nil)
- m["rm"] = boolFromVarlink(opts.Rm, "rm", false)
- m["rootfs"] = boolFromVarlink(opts.Rootfs, "rootfs", false)
- m["security-opt"] = stringArrayFromVarlink(opts.SecurityOpt, "security-opt", nil)
- m["shm-size"] = stringFromVarlink(opts.ShmSize, "shm-size", &shmSize)
- m["stop-signal"] = stringFromVarlink(opts.StopSignal, "stop-signal", nil)
- m["stop-timeout"] = uintFromVarlink(opts.StopTimeout, "stop-timeout", nil)
- m["storage-opt"] = stringSliceFromVarlink(opts.StorageOpt, "storage-opt", nil)
- m["subgidname"] = stringFromVarlink(opts.Subgidname, "subgidname", nil)
- m["subuidname"] = stringFromVarlink(opts.Subuidname, "subuidname", nil)
- m["sysctl"] = stringSliceFromVarlink(opts.Sysctl, "sysctl", nil)
- m["systemd"] = stringFromVarlink(opts.Systemd, "systemd", &systemdDefault)
- m["tmpfs"] = stringSliceFromVarlink(opts.Tmpfs, "tmpfs", nil)
- m["tty"] = boolFromVarlink(opts.Tty, "tty", false)
- m["uidmap"] = stringSliceFromVarlink(opts.Uidmap, "uidmap", nil)
- m["ulimit"] = stringSliceFromVarlink(opts.Ulimit, "ulimit", nil)
- m["user"] = stringFromVarlink(opts.User, "user", nil)
- m["userns"] = stringFromVarlink(opts.Userns, "userns", nil)
- m["uts"] = stringFromVarlink(opts.Uts, "uts", nil)
- m["mount"] = stringArrayFromVarlink(opts.Mount, "mount", nil)
- m["volume"] = stringArrayFromVarlink(opts.Volume, "volume", nil)
- m["volumes-from"] = stringSliceFromVarlink(opts.VolumesFrom, "volumes-from", nil)
- m["workdir"] = stringFromVarlink(opts.WorkDir, "workdir", nil)
-
- gcli := GenericCLIResults{m, opts.Args}
- return gcli
-}
-
-// Find returns a flag from a GenericCLIResults by name
-func (g GenericCLIResults) Find(name string) GenericCLIResult {
- result, ok := g.results[name]
- if ok {
- return result
- }
- panic(errors.Errorf("unable to find generic flag for varlink %s", name))
-}
diff --git a/pkg/varlinkapi/mount.go b/pkg/varlinkapi/mount.go
deleted file mode 100644
index 6fd4de709..000000000
--- a/pkg/varlinkapi/mount.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import iopodman "github.com/containers/podman/v2/pkg/varlink"
-
-// ListContainerMounts ...
-func (i *VarlinkAPI) ListContainerMounts(call iopodman.VarlinkCall) error {
- mounts := make(map[string]string)
- allContainers, err := i.Runtime.GetAllContainers()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- for _, container := range allContainers {
- mounted, mountPoint, err := container.Mounted()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if mounted {
- mounts[container.ID()] = mountPoint
- }
- }
- return call.ReplyListContainerMounts(mounts)
-}
-
-// MountContainer ...
-func (i *VarlinkAPI) MountContainer(call iopodman.VarlinkCall, name string) error {
- container, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- path, err := container.Mount()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyMountContainer(path)
-}
-
-// UnmountContainer ...
-func (i *VarlinkAPI) UnmountContainer(call iopodman.VarlinkCall, name string, force bool) error {
- container, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if err := container.Unmount(force); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyUnmountContainer()
-}
diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go
deleted file mode 100644
index 6d03afb7a..000000000
--- a/pkg/varlinkapi/pods.go
+++ /dev/null
@@ -1,389 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- "context"
- "encoding/json"
- "fmt"
- "strconv"
- "syscall"
-
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/libpod/define"
- iopodman "github.com/containers/podman/v2/pkg/varlink"
- "github.com/cri-o/ocicni/pkg/ocicni"
- "github.com/docker/go-connections/nat"
- "github.com/pkg/errors"
-)
-
-// CreatePod ...
-func (i *VarlinkAPI) CreatePod(call iopodman.VarlinkCall, create iopodman.PodCreate) error {
- var options []libpod.PodCreateOption
- if create.Infra {
- options = append(options, libpod.WithInfraContainer())
- nsOptions, err := GetNamespaceOptions(create.Share)
- if err != nil {
- return err
- }
- options = append(options, nsOptions...)
- }
- if create.CgroupParent != "" {
- options = append(options, libpod.WithPodCgroupParent(create.CgroupParent))
- }
- if len(create.Labels) > 0 {
- options = append(options, libpod.WithPodLabels(create.Labels))
- }
- if create.Name != "" {
- options = append(options, libpod.WithPodName(create.Name))
- }
- if len(create.Share) > 0 && !create.Infra {
- return call.ReplyErrorOccurred("You cannot share kernel namespaces on the pod level without an infra container")
- }
- if len(create.Share) == 0 && create.Infra {
- return call.ReplyErrorOccurred("You must share kernel namespaces to run an infra container")
- }
-
- if len(create.Publish) > 0 {
- if !create.Infra {
- return call.ReplyErrorOccurred("you must have an infra container to publish port bindings to the host")
- }
- portBindings, err := CreatePortBindings(create.Publish)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- options = append(options, libpod.WithInfraContainerPorts(portBindings))
-
- }
- options = append(options, libpod.WithPodCgroups())
-
- pod, err := i.Runtime.NewPod(getContext(), options...)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyCreatePod(pod.ID())
-}
-
-// ListPods ...
-func (i *VarlinkAPI) ListPods(call iopodman.VarlinkCall) error {
- var (
- listPods []iopodman.ListPodData
- )
-
- pods, err := i.Runtime.GetAllPods()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- opts := PsOptions{}
- for _, pod := range pods {
- listPod, err := makeListPod(pod, opts)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- listPods = append(listPods, listPod)
- }
- return call.ReplyListPods(listPods)
-}
-
-// GetPod ...
-func (i *VarlinkAPI) GetPod(call iopodman.VarlinkCall, name string) error {
- pod, err := i.Runtime.LookupPod(name)
- if err != nil {
- return call.ReplyPodNotFound(name, err.Error())
- }
- opts := PsOptions{}
-
- listPod, err := makeListPod(pod, opts)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- return call.ReplyGetPod(listPod)
-}
-
-// GetPodsByStatus returns a slice of pods filtered by a libpod status
-func (i *VarlinkAPI) GetPodsByStatus(call iopodman.VarlinkCall, statuses []string) error {
- filterFuncs := func(p *libpod.Pod) bool {
- state, _ := p.GetPodStatus()
- for _, status := range statuses {
- if state == status {
- return true
- }
- }
- return false
- }
- filteredPods, err := i.Runtime.Pods(filterFuncs)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- podIDs := make([]string, 0, len(filteredPods))
- for _, p := range filteredPods {
- podIDs = append(podIDs, p.ID())
- }
- return call.ReplyGetPodsByStatus(podIDs)
-}
-
-// InspectPod ...
-func (i *VarlinkAPI) InspectPod(call iopodman.VarlinkCall, name string) error {
- pod, err := i.Runtime.LookupPod(name)
- if err != nil {
- return call.ReplyPodNotFound(name, err.Error())
- }
- inspectData, err := pod.Inspect()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- b, err := json.Marshal(&inspectData)
- if err != nil {
- return call.ReplyErrorOccurred("unable to serialize")
- }
- return call.ReplyInspectPod(string(b))
-}
-
-// StartPod ...
-func (i *VarlinkAPI) StartPod(call iopodman.VarlinkCall, name string) error {
- pod, err := i.Runtime.LookupPod(name)
- if err != nil {
- return call.ReplyPodNotFound(name, err.Error())
- }
- ctnrs, err := pod.AllContainers()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if 0 == len(ctnrs) {
- return call.ReplyNoContainersInPod(name)
- }
- ctrErrs, err := pod.Start(getContext())
- callErr := handlePodCall(call, pod, ctrErrs, err)
- if callErr != nil {
- return err
- }
- return call.ReplyStartPod(pod.ID())
-}
-
-// StopPod ...
-func (i *VarlinkAPI) StopPod(call iopodman.VarlinkCall, name string, timeout int64) error {
- pod, err := i.Runtime.LookupPod(name)
- if err != nil {
- return call.ReplyPodNotFound(name, err.Error())
- }
- ctrErrs, err := pod.StopWithTimeout(getContext(), true, int(timeout))
- callErr := handlePodCall(call, pod, ctrErrs, err)
- if callErr != nil {
- return err
- }
- return call.ReplyStopPod(pod.ID())
-}
-
-// RestartPod ...
-func (i *VarlinkAPI) RestartPod(call iopodman.VarlinkCall, name string) error {
- pod, err := i.Runtime.LookupPod(name)
- if err != nil {
- return call.ReplyPodNotFound(name, err.Error())
- }
- ctnrs, err := pod.AllContainers()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if 0 == len(ctnrs) {
- return call.ReplyNoContainersInPod(name)
- }
- ctrErrs, err := pod.Restart(getContext())
- callErr := handlePodCall(call, pod, ctrErrs, err)
- if callErr != nil {
- return err
- }
- return call.ReplyRestartPod(pod.ID())
-}
-
-// KillPod kills the running containers in a pod. If you want to use the default SIGTERM signal,
-// just send a -1 for the signal arg.
-func (i *VarlinkAPI) KillPod(call iopodman.VarlinkCall, name string, signal int64) error {
- killSignal := uint(syscall.SIGTERM)
- if signal != -1 {
- killSignal = uint(signal)
- }
-
- pod, err := i.Runtime.LookupPod(name)
- if err != nil {
- return call.ReplyPodNotFound(name, err.Error())
- }
- ctrErrs, err := pod.Kill(context.TODO(), killSignal)
- callErr := handlePodCall(call, pod, ctrErrs, err)
- if callErr != nil {
- return err
- }
- return call.ReplyKillPod(pod.ID())
-}
-
-// PausePod ...
-func (i *VarlinkAPI) PausePod(call iopodman.VarlinkCall, name string) error {
- pod, err := i.Runtime.LookupPod(name)
- if err != nil {
- return call.ReplyPodNotFound(name, err.Error())
- }
- ctrErrs, err := pod.Pause(context.TODO())
- callErr := handlePodCall(call, pod, ctrErrs, err)
- if callErr != nil {
- return err
- }
- return call.ReplyPausePod(pod.ID())
-}
-
-// UnpausePod ...
-func (i *VarlinkAPI) UnpausePod(call iopodman.VarlinkCall, name string) error {
- pod, err := i.Runtime.LookupPod(name)
- if err != nil {
- return call.ReplyPodNotFound(name, err.Error())
- }
- ctrErrs, err := pod.Unpause(context.TODO())
- callErr := handlePodCall(call, pod, ctrErrs, err)
- if callErr != nil {
- return err
- }
- return call.ReplyUnpausePod(pod.ID())
-}
-
-// RemovePod ...
-func (i *VarlinkAPI) RemovePod(call iopodman.VarlinkCall, name string, force bool) error {
- ctx := getContext()
- pod, err := i.Runtime.LookupPod(name)
- if err != nil {
- return call.ReplyPodNotFound(name, err.Error())
- }
- if err = i.Runtime.RemovePod(ctx, pod, true, force); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- return call.ReplyRemovePod(pod.ID())
-}
-
-// GetPodStats ...
-func (i *VarlinkAPI) GetPodStats(call iopodman.VarlinkCall, name string) error {
- pod, err := i.Runtime.LookupPod(name)
- if err != nil {
- return call.ReplyPodNotFound(name, err.Error())
- }
- prevStats := make(map[string]*define.ContainerStats)
- podStats, err := pod.GetPodStats(prevStats)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if len(podStats) == 0 {
- return call.ReplyNoContainerRunning()
- }
- containersStats := make([]iopodman.ContainerStats, 0)
- for ctrID, containerStats := range podStats {
- cs := iopodman.ContainerStats{
- Id: ctrID,
- Name: containerStats.Name,
- Cpu: containerStats.CPU,
- Cpu_nano: int64(containerStats.CPUNano),
- System_nano: int64(containerStats.SystemNano),
- Mem_usage: int64(containerStats.MemUsage),
- Mem_limit: int64(containerStats.MemLimit),
- Mem_perc: containerStats.MemPerc,
- Net_input: int64(containerStats.NetInput),
- Net_output: int64(containerStats.NetOutput),
- Block_input: int64(containerStats.BlockInput),
- Block_output: int64(containerStats.BlockOutput),
- Pids: int64(containerStats.PIDs),
- }
- containersStats = append(containersStats, cs)
- }
- return call.ReplyGetPodStats(pod.ID(), containersStats)
-}
-
-// getPodsByContext returns a slice of pod ids based on all, latest, or a list
-func (i *VarlinkAPI) GetPodsByContext(call iopodman.VarlinkCall, all, latest bool, input []string) error {
- var podids []string
-
- pods, err := getPodsByContext(all, latest, input, i.Runtime)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- for _, p := range pods {
- podids = append(podids, p.ID())
- }
- return call.ReplyGetPodsByContext(podids)
-}
-
-// PodStateData returns a container's state data in string format
-func (i *VarlinkAPI) PodStateData(call iopodman.VarlinkCall, name string) error {
- pod, err := i.Runtime.LookupPod(name)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- data, err := pod.Inspect()
- if err != nil {
- return call.ReplyErrorOccurred("unable to obtain pod state")
- }
- b, err := json.Marshal(data)
- if err != nil {
- return call.ReplyErrorOccurred("unable to serialize pod inspect data")
- }
- return call.ReplyPodStateData(string(b))
-}
-
-// TopPod provides the top stats for a given or latest pod
-func (i *VarlinkAPI) TopPod(call iopodman.VarlinkCall, name string, latest bool, descriptors []string) error {
- var (
- pod *libpod.Pod
- err error
- )
- if latest {
- name = "latest"
- pod, err = i.Runtime.GetLatestPod()
- } else {
- pod, err = i.Runtime.LookupPod(name)
- }
- if err != nil {
- return call.ReplyPodNotFound(name, err.Error())
- }
-
- podStatus, err := pod.GetPodStatus()
- if err != nil {
- return call.ReplyErrorOccurred(fmt.Sprintf("unable to get status for pod %s", pod.ID()))
- }
- if podStatus != "Running" {
- return call.ReplyErrorOccurred("pod top can only be used on pods with at least one running container")
- }
- reply, err := pod.GetPodPidInformation(descriptors)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyTopPod(reply)
-}
-
-// CreatePortBindings iterates ports mappings and exposed ports into a format CNI understands
-func CreatePortBindings(ports []string) ([]ocicni.PortMapping, error) {
- var portBindings []ocicni.PortMapping
- // The conversion from []string to natBindings is temporary while mheon reworks the port
- // deduplication code. Eventually that step will not be required.
- _, natBindings, err := nat.ParsePortSpecs(ports)
- if err != nil {
- return nil, err
- }
- for containerPb, hostPb := range natBindings {
- var pm ocicni.PortMapping
- pm.ContainerPort = int32(containerPb.Int())
- for _, i := range hostPb {
- var hostPort int
- var err error
- pm.HostIP = i.HostIP
- if i.HostPort == "" {
- hostPort = containerPb.Int()
- } else {
- hostPort, err = strconv.Atoi(i.HostPort)
- if err != nil {
- return nil, errors.Wrapf(err, "unable to convert host port to integer")
- }
- }
-
- pm.HostPort = int32(hostPort)
- pm.Protocol = containerPb.Proto()
- portBindings = append(portBindings, pm)
- }
- }
- return portBindings, nil
-}
diff --git a/pkg/varlinkapi/remote_client.go b/pkg/varlinkapi/remote_client.go
deleted file mode 100644
index 88c11c126..000000000
--- a/pkg/varlinkapi/remote_client.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// +build varlink remoteclient
-
-package varlinkapi
-
-import (
- "github.com/containers/podman/v2/libpod/define"
- iopodman "github.com/containers/podman/v2/pkg/varlink"
-)
-
-// ContainerStatsToLibpodContainerStats converts the varlink containerstats to a libpod
-// container stats
-func ContainerStatsToLibpodContainerStats(stats iopodman.ContainerStats) define.ContainerStats {
- cstats := define.ContainerStats{
- ContainerID: stats.Id,
- Name: stats.Name,
- CPU: stats.Cpu,
- CPUNano: uint64(stats.Cpu_nano),
- SystemNano: uint64(stats.System_nano),
- MemUsage: uint64(stats.Mem_usage),
- MemLimit: uint64(stats.Mem_limit),
- MemPerc: stats.Mem_perc,
- NetInput: uint64(stats.Net_input),
- NetOutput: uint64(stats.Net_output),
- BlockInput: uint64(stats.Block_input),
- BlockOutput: uint64(stats.Block_output),
- PIDs: uint64(stats.Pids),
- }
- return cstats
-}
diff --git a/pkg/varlinkapi/shortcuts.go b/pkg/varlinkapi/shortcuts.go
deleted file mode 100644
index bfb05c0e3..000000000
--- a/pkg/varlinkapi/shortcuts.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package varlinkapi
-
-import (
- "github.com/containers/podman/v2/libpod"
- "github.com/sirupsen/logrus"
-)
-
-// getPodsByContext returns a slice of pods. Note that all, latest and pods are
-// mutually exclusive arguments.
-func getPodsByContext(all, latest bool, pods []string, runtime *libpod.Runtime) ([]*libpod.Pod, error) {
- var outpods []*libpod.Pod
- if all {
- return runtime.GetAllPods()
- }
- if latest {
- p, err := runtime.GetLatestPod()
- if err != nil {
- return nil, err
- }
- outpods = append(outpods, p)
- return outpods, nil
- }
- var err error
- for _, p := range pods {
- pod, e := runtime.LookupPod(p)
- if e != nil {
- // Log all errors here, so callers don't need to.
- logrus.Debugf("Error looking up pod %q: %v", p, e)
- if err == nil {
- err = e
- }
- } else {
- outpods = append(outpods, pod)
- }
- }
- return outpods, err
-}
-
-// getContainersByContext gets pods whether all, latest, or a slice of names/ids
-// is specified.
-func getContainersByContext(all, latest bool, names []string, runtime *libpod.Runtime) (ctrs []*libpod.Container, err error) {
- var ctr *libpod.Container
- ctrs = []*libpod.Container{}
-
- switch {
- case all:
- ctrs, err = runtime.GetAllContainers()
- case latest:
- ctr, err = runtime.GetLatestContainer()
- ctrs = append(ctrs, ctr)
- default:
- for _, n := range names {
- ctr, e := runtime.LookupContainer(n)
- if e != nil {
- // Log all errors here, so callers don't need to.
- logrus.Debugf("Error looking up container %q: %v", n, e)
- if err == nil {
- err = e
- }
- } else {
- ctrs = append(ctrs, ctr)
- }
- }
- }
- return
-}
diff --git a/pkg/varlinkapi/system.go b/pkg/varlinkapi/system.go
deleted file mode 100644
index e5c766a6d..000000000
--- a/pkg/varlinkapi/system.go
+++ /dev/null
@@ -1,129 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- "context"
- "fmt"
- "os"
- goruntime "runtime"
- "strconv"
- "time"
-
- "github.com/containers/image/v5/pkg/sysregistriesv2"
- "github.com/containers/podman/v2/libpod/define"
- iopodman "github.com/containers/podman/v2/pkg/varlink"
- "github.com/sirupsen/logrus"
-)
-
-// GetVersion ...
-func (i *VarlinkAPI) GetVersion(call iopodman.VarlinkCall) error {
- versionInfo, err := define.GetVersion()
- if err != nil {
- return err
- }
-
- int64APIVersion, err := strconv.ParseInt(versionInfo.APIVersion, 10, 64)
- if err != nil {
- return err
- }
-
- return call.ReplyGetVersion(
- versionInfo.Version,
- versionInfo.GoVersion,
- versionInfo.GitCommit,
- time.Unix(versionInfo.Built, 0).Format(time.RFC3339),
- versionInfo.OsArch,
- int64APIVersion,
- )
-}
-
-// GetInfo returns details about the podman host and its stores
-func (i *VarlinkAPI) GetInfo(call iopodman.VarlinkCall) error {
- versionInfo, err := define.GetVersion()
- if err != nil {
- return err
- }
- podmanInfo := iopodman.PodmanInfo{}
- info, err := i.Runtime.Info()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- distribution := iopodman.InfoDistribution{
- Distribution: info.Host.Distribution.Distribution,
- Version: info.Host.Distribution.Version,
- }
- infoHost := iopodman.InfoHost{
- Buildah_version: info.Host.BuildahVersion,
- Distribution: distribution,
- Mem_free: info.Host.MemFree,
- Mem_total: info.Host.MemTotal,
- Swap_free: info.Host.SwapFree,
- Swap_total: info.Host.SwapTotal,
- Arch: info.Host.Arch,
- Cpus: int64(info.Host.CPUs),
- Hostname: info.Host.Hostname,
- Kernel: info.Host.Kernel,
- Os: info.Host.OS,
- Uptime: info.Host.Uptime,
- Eventlogger: info.Host.EventLogger,
- }
- podmanInfo.Host = infoHost
- pmaninfo := iopodman.InfoPodmanBinary{
- Compiler: goruntime.Compiler,
- Go_version: goruntime.Version(),
- Podman_version: versionInfo.Version,
- Git_commit: versionInfo.GitCommit,
- }
-
- graphStatus := iopodman.InfoGraphStatus{
- Backing_filesystem: info.Store.GraphStatus["Backing Filesystem"],
- Native_overlay_diff: info.Store.GraphStatus["Native Overlay Diff"],
- Supports_d_type: info.Store.GraphStatus["Supports d_type"],
- }
- infoStore := iopodman.InfoStore{
- Graph_driver_name: info.Store.GraphDriverName,
- Containers: int64(info.Store.ContainerStore.Number),
- Images: int64(info.Store.ImageStore.Number),
- Run_root: info.Store.RunRoot,
- Graph_root: info.Store.GraphRoot,
- Graph_driver_options: fmt.Sprintf("%v", info.Store.GraphOptions),
- Graph_status: graphStatus,
- }
-
- // Registry information if any is stored as the second list item
- for key, val := range info.Registries {
- if key == "search" {
- podmanInfo.Registries.Search = val.([]string)
- continue
- }
- regData := val.(sysregistriesv2.Registry)
- if regData.Insecure {
- podmanInfo.Registries.Insecure = append(podmanInfo.Registries.Insecure, key)
- }
- if regData.Blocked {
- podmanInfo.Registries.Blocked = append(podmanInfo.Registries.Blocked, key)
- }
- }
- podmanInfo.Store = infoStore
- podmanInfo.Podman = pmaninfo
- return call.ReplyGetInfo(podmanInfo)
-}
-
-// GetVersion ...
-func (i *VarlinkAPI) Reset(call iopodman.VarlinkCall) error {
- if err := i.Runtime.Reset(context.TODO()); err != nil {
- logrus.Errorf("Reset Failed: %v", err)
- if err := call.ReplyErrorOccurred(err.Error()); err != nil {
- logrus.Errorf("Failed to send ReplyErrorOccurred: %v", err)
- }
- os.Exit(define.ExecErrorCodeGeneric)
- }
- if err := call.ReplyReset(); err != nil {
- logrus.Errorf("Failed to send ReplyReset: %v", err)
- os.Exit(define.ExecErrorCodeGeneric)
- }
- os.Exit(0)
- return nil
-}
diff --git a/pkg/varlinkapi/transfers.go b/pkg/varlinkapi/transfers.go
deleted file mode 100644
index a4550a417..000000000
--- a/pkg/varlinkapi/transfers.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- "bufio"
- "io"
- "io/ioutil"
- "os"
-
- iopodman "github.com/containers/podman/v2/pkg/varlink"
- "github.com/sirupsen/logrus"
-)
-
-// SendFile allows a client to send a file to the varlink server
-func (i *VarlinkAPI) SendFile(call iopodman.VarlinkCall, ftype string, length int64) error {
- if !call.WantsUpgrade() {
- return call.ReplyErrorOccurred("client must use upgraded connection to send files")
- }
-
- outputFile, err := ioutil.TempFile("", "varlink_send")
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- defer outputFile.Close()
-
- if err = call.ReplySendFile(outputFile.Name()); err != nil {
- // If an error occurs while sending the reply, return the error
- return err
- }
-
- writer := bufio.NewWriter(outputFile)
- defer writer.Flush()
-
- reader := call.Call.Reader
- if _, err := io.CopyN(writer, reader, length); err != nil {
- return err
- }
-
- logrus.Debugf("successfully received %s", outputFile.Name())
- // Send an ACK to the client
- call.Call.Writer.WriteString(outputFile.Name() + ":")
- call.Call.Writer.Flush()
- return nil
-
-}
-
-// ReceiveFile allows the varlink server to send a file to a client
-func (i *VarlinkAPI) ReceiveFile(call iopodman.VarlinkCall, filepath string, delete bool) error {
- if !call.WantsUpgrade() {
- return call.ReplyErrorOccurred("client must use upgraded connection to send files")
- }
- fs, err := os.Open(filepath)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- fileInfo, err := fs.Stat()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- // Send the file length down to client
- // Varlink connection upgraded
- if err = call.ReplyReceiveFile(fileInfo.Size()); err != nil {
- // If an error occurs while sending the reply, return the error
- return err
- }
-
- reader := bufio.NewReader(fs)
- _, err = reader.WriteTo(call.Writer)
- if err != nil {
- return err
- }
- if delete {
- if err := os.Remove(filepath); err != nil {
- return err
- }
- }
- return call.Writer.Flush()
-}
diff --git a/pkg/varlinkapi/util.go b/pkg/varlinkapi/util.go
deleted file mode 100644
index 7f96965f0..000000000
--- a/pkg/varlinkapi/util.go
+++ /dev/null
@@ -1,237 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- "context"
- "strconv"
- "strings"
- "time"
-
- "github.com/containers/buildah"
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/libpod/define"
- "github.com/containers/podman/v2/pkg/channel"
- iopodman "github.com/containers/podman/v2/pkg/varlink"
- "github.com/containers/storage/pkg/archive"
-)
-
-// getContext returns a non-nil, empty context
-func getContext() context.Context {
- return context.TODO()
-}
-
-func makeListContainer(containerID string, batchInfo BatchContainerStruct) iopodman.Container {
- var (
- mounts []iopodman.ContainerMount
- ports []iopodman.ContainerPortMappings
- )
- ns := GetNamespaces(batchInfo.Pid)
-
- for _, mount := range batchInfo.ConConfig.Spec.Mounts {
- m := iopodman.ContainerMount{
- Destination: mount.Destination,
- Type: mount.Type,
- Source: mount.Source,
- Options: mount.Options,
- }
- mounts = append(mounts, m)
- }
-
- for _, pm := range batchInfo.ConConfig.PortMappings {
- p := iopodman.ContainerPortMappings{
- Host_port: strconv.Itoa(int(pm.HostPort)),
- Host_ip: pm.HostIP,
- Protocol: pm.Protocol,
- Container_port: strconv.Itoa(int(pm.ContainerPort)),
- }
- ports = append(ports, p)
-
- }
-
- // If we find this needs to be done for other container endpoints, we should
- // convert this to a separate function or a generic map from struct function.
- namespace := iopodman.ContainerNameSpace{
- User: ns.User,
- Uts: ns.UTS,
- Pidns: ns.PIDNS,
- Pid: ns.PID,
- Cgroup: ns.Cgroup,
- Net: ns.NET,
- Mnt: ns.MNT,
- Ipc: ns.IPC,
- }
-
- lc := iopodman.Container{
- Id: containerID,
- Image: batchInfo.ConConfig.RootfsImageName,
- Imageid: batchInfo.ConConfig.RootfsImageID,
- Command: batchInfo.ConConfig.Spec.Process.Args,
- Createdat: batchInfo.ConConfig.CreatedTime.Format(time.RFC3339),
- Runningfor: time.Since(batchInfo.ConConfig.CreatedTime).String(),
- Status: batchInfo.ConState.String(),
- Ports: ports,
- Names: batchInfo.ConConfig.Name,
- Labels: batchInfo.ConConfig.Labels,
- Mounts: mounts,
- Containerrunning: batchInfo.ConState == define.ContainerStateRunning,
- Namespaces: namespace,
- }
- if batchInfo.Size != nil {
- lc.Rootfssize = batchInfo.Size.RootFsSize
- lc.Rwsize = batchInfo.Size.RwSize
- }
- return lc
-}
-
-func makeListPodContainers(containerID string, batchInfo BatchContainerStruct) iopodman.ListPodContainerInfo {
- lc := iopodman.ListPodContainerInfo{
- Id: containerID,
- Status: batchInfo.ConState.String(),
- Name: batchInfo.ConConfig.Name,
- }
- return lc
-}
-
-func makeListPod(pod *libpod.Pod, batchInfo PsOptions) (iopodman.ListPodData, error) {
- var listPodsContainers []iopodman.ListPodContainerInfo
- var errPodData = iopodman.ListPodData{}
- status, err := pod.GetPodStatus()
- if err != nil {
- return errPodData, err
- }
- containers, err := pod.AllContainers()
- if err != nil {
- return errPodData, err
- }
- for _, ctr := range containers {
- batchInfo, err := BatchContainerOp(ctr, batchInfo)
- if err != nil {
- return errPodData, err
- }
-
- listPodsContainers = append(listPodsContainers, makeListPodContainers(ctr.ID(), batchInfo))
- }
- listPod := iopodman.ListPodData{
- Createdat: pod.CreatedTime().Format(time.RFC3339),
- Id: pod.ID(),
- Name: pod.Name(),
- Status: status,
- Cgroup: pod.CgroupParent(),
- Numberofcontainers: strconv.Itoa(len(listPodsContainers)),
- Containersinfo: listPodsContainers,
- }
- return listPod, nil
-}
-
-func handlePodCall(call iopodman.VarlinkCall, pod *libpod.Pod, ctrErrs map[string]error, err error) error {
- if err != nil && ctrErrs == nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if ctrErrs != nil {
- containerErrs := make([]iopodman.PodContainerErrorData, len(ctrErrs))
- for ctr, reason := range ctrErrs {
- ctrErr := iopodman.PodContainerErrorData{Containerid: ctr, Reason: reason.Error()}
- containerErrs = append(containerErrs, ctrErr)
- }
- return call.ReplyPodContainerError(pod.ID(), containerErrs)
- }
-
- return nil
-}
-
-func stringCompressionToArchiveType(s string) archive.Compression {
- switch strings.ToUpper(s) {
- case "BZIP2":
- return archive.Bzip2
- case "GZIP":
- return archive.Gzip
- case "XZ":
- return archive.Xz
- }
- return archive.Uncompressed
-}
-
-func stringPullPolicyToType(s string) buildah.PullPolicy {
- switch strings.ToUpper(s) {
- case "PULLIFMISSING":
- return buildah.PullIfMissing
- case "PULLALWAYS":
- return buildah.PullAlways
- case "PULLNEVER":
- return buildah.PullNever
- }
- return buildah.PullIfMissing
-}
-
-func derefBool(inBool *bool) bool {
- if inBool == nil {
- return false
- }
- return *inBool
-}
-
-func derefString(in *string) string {
- if in == nil {
- return ""
- }
- return *in
-}
-
-func makePsOpts(inOpts iopodman.PsOpts) PsOptions {
- last := 0
- if inOpts.Last != nil {
- lastT := *inOpts.Last
- last = int(lastT)
- }
- return PsOptions{
- All: inOpts.All,
- Last: last,
- Latest: derefBool(inOpts.Latest),
- NoTrunc: derefBool(inOpts.NoTrunc),
- Pod: derefBool(inOpts.Pod),
- Size: derefBool(inOpts.Size),
- Sort: derefString(inOpts.Sort),
- Namespace: true,
- Sync: derefBool(inOpts.Sync),
- }
-}
-
-// forwardOutput is a helper method for varlink endpoints that employ both more and without
-// more. it is capable of sending updates as the output writer gets them or append them
-// all to a log. the chan error is the error from the libpod call so we can honor
-// and error event in that case.
-func forwardOutput(log []string, c chan error, wantsMore bool, output channel.WriteCloser, reply func(br iopodman.MoreResponse) error) ([]string, error) {
- done := false
- for {
- select {
- // We need to check if the libpod func being called has returned an
- // error yet
- case err := <-c:
- if err != nil {
- return nil, err
- }
- done = true
- // if no error is found, we pull what we can from the log writer and
- // append it to log string slice
- case line := <-output.Chan():
- log = append(log, string(line))
- // If the end point is being used in more mode, send what we have
- if wantsMore {
- br := iopodman.MoreResponse{
- Logs: log,
- }
- if err := reply(br); err != nil {
- return nil, err
- }
- // "reset" the log to empty because we are sending what we
- // get as we get it
- log = []string{}
- }
- }
- if done {
- break
- }
- }
- return log, nil
-}
diff --git a/pkg/varlinkapi/virtwriter/virtwriter.go b/pkg/varlinkapi/virtwriter/virtwriter.go
deleted file mode 100644
index d96e82a3f..000000000
--- a/pkg/varlinkapi/virtwriter/virtwriter.go
+++ /dev/null
@@ -1,204 +0,0 @@
-package virtwriter
-
-import (
- "bufio"
- "encoding/binary"
- "encoding/json"
- "io"
- "time"
-
- "github.com/pkg/errors"
- "k8s.io/client-go/tools/remotecommand"
-)
-
-// SocketDest is the "key" to where IO should go on the varlink
-// multiplexed socket
-type SocketDest int
-
-const (
- // ToStdout indicates traffic should go stdout
- ToStdout SocketDest = iota
- // ToStdin indicates traffic came from stdin
- ToStdin SocketDest = iota
- // ToStderr indicates traffuc should go to stderr
- ToStderr SocketDest = iota
- // TerminalResize indicates a terminal resize event has occurred
- // and data should be passed to resizer
- TerminalResize SocketDest = iota
- // Quit and detach
- Quit SocketDest = iota
- // HangUpFromClient hangs up from the client
- HangUpFromClient SocketDest = iota
-)
-
-// ErrClientHangup signifies that the client wants to drop its connection from
-// the server.
-var ErrClientHangup = errors.New("client hangup")
-
-// IntToSocketDest returns a socketdest based on integer input
-func IntToSocketDest(i int) SocketDest {
- switch i {
- case ToStdout.Int():
- return ToStdout
- case ToStderr.Int():
- return ToStderr
- case ToStdin.Int():
- return ToStdin
- case TerminalResize.Int():
- return TerminalResize
- case Quit.Int():
- return Quit
- case HangUpFromClient.Int():
- return HangUpFromClient
- default:
- return ToStderr
- }
-}
-
-// Int returns the integer representation of the socket dest
-func (sd SocketDest) Int() int {
- return int(sd)
-}
-
-// VirtWriteCloser are writers for attach which include the dest
-// of the data
-type VirtWriteCloser struct {
- writer *bufio.Writer
- dest SocketDest
-}
-
-// NewVirtWriteCloser is a constructor
-func NewVirtWriteCloser(w *bufio.Writer, dest SocketDest) VirtWriteCloser {
- return VirtWriteCloser{w, dest}
-}
-
-// Close is a required method for a writecloser
-func (v VirtWriteCloser) Close() error {
- return v.writer.Flush()
-}
-
-// Write prepends a header to the input message. The header is
-// 8bytes. Position one contains the destination. Positions
-// 5,6,7,8 are a big-endian encoded uint32 for len of the message.
-func (v VirtWriteCloser) Write(input []byte) (int, error) {
- header := []byte{byte(v.dest), 0, 0, 0}
- // Go makes us define the byte for big endian
- mlen := make([]byte, 4)
- binary.BigEndian.PutUint32(mlen, uint32(len(input)))
- // append the message len to the header
- msg := append(header, mlen...)
- // append the message to the header
- msg = append(msg, input...)
- _, err := v.writer.Write(msg)
- if err != nil {
- return 0, err
- }
- err = v.writer.Flush()
- return len(input), err
-}
-
-// Reader decodes the content that comes over the wire and directs it to the proper destination.
-func Reader(r *bufio.Reader, output, errput, input io.Writer, resize chan remotecommand.TerminalSize, execEcChan chan int) error {
- var messageSize int64
- headerBytes := make([]byte, 8)
-
- if r == nil {
- return errors.Errorf("Reader must not be nil")
- }
- for {
- n, err := io.ReadFull(r, headerBytes)
- if err != nil {
- return errors.Wrapf(err, "Virtual Read failed, %d", n)
- }
- if n < 8 {
- return errors.New("short read and no full header read")
- }
-
- messageSize = int64(binary.BigEndian.Uint32(headerBytes[4:8]))
- switch IntToSocketDest(int(headerBytes[0])) {
- case ToStdout:
- if output != nil {
- _, err := io.CopyN(output, r, messageSize)
- if err != nil {
- return err
- }
- }
- case ToStderr:
- if errput != nil {
- _, err := io.CopyN(errput, r, messageSize)
- if err != nil {
- return err
- }
- }
- case ToStdin:
- if input != nil {
- _, err := io.CopyN(input, r, messageSize)
- if err != nil {
- return err
- }
- }
- case TerminalResize:
- if resize != nil {
- out := make([]byte, messageSize)
- if messageSize > 0 {
- _, err = io.ReadFull(r, out)
-
- if err != nil {
- return err
- }
- }
- // Resize events come over in bytes, need to be reserialized
- resizeEvent := remotecommand.TerminalSize{}
- if err := json.Unmarshal(out, &resizeEvent); err != nil {
- return err
- }
- resize <- resizeEvent
- }
- case Quit:
- out := make([]byte, messageSize)
- if messageSize > 0 {
- _, err = io.ReadFull(r, out)
-
- if err != nil {
- return err
- }
- }
- if execEcChan != nil {
- ecInt := binary.BigEndian.Uint32(out)
- execEcChan <- int(ecInt)
- }
- return nil
- case HangUpFromClient:
- // This sleep allows the pipes to flush themselves before tearing everything down.
- // It makes me sick to do it but after a full day I cannot put my finger on the race
- // that occurs when closing things up. It would require a significant rewrite of code
- // to make the pipes close down properly. Given that we are currently discussing a
- // rewrite of all things remote, this hardly seems worth resolving.
- //
- // reproducer: echo hello | (podman-remote run -i alpine cat)
- time.Sleep(1 * time.Second)
- return ErrClientHangup
- default:
- // Something really went wrong
- return errors.New("unknown multiplex destination")
- }
- }
-}
-
-// HangUp sends message to peer to close connection
-func HangUp(writer *bufio.Writer, ec uint32) (err error) {
- n := 0
- msg := make([]byte, 4)
-
- binary.BigEndian.PutUint32(msg, ec)
-
- writeQuit := NewVirtWriteCloser(writer, Quit)
- if n, err = writeQuit.Write(msg); err != nil {
- return
- }
-
- if n != len(msg) {
- return errors.Errorf("Failed to send complete %s message", string(msg))
- }
- return
-}
diff --git a/pkg/varlinkapi/volumes.go b/pkg/varlinkapi/volumes.go
deleted file mode 100644
index 7cc714ea4..000000000
--- a/pkg/varlinkapi/volumes.go
+++ /dev/null
@@ -1,165 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- "context"
- "encoding/json"
-
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/pkg/domain/infra/abi/parse"
- iopodman "github.com/containers/podman/v2/pkg/varlink"
-)
-
-// VolumeCreate creates a libpod volume based on input from a varlink connection
-func (i *VarlinkAPI) VolumeCreate(call iopodman.VarlinkCall, options iopodman.VolumeCreateOpts) error {
- var volumeOptions []libpod.VolumeCreateOption
-
- if len(options.VolumeName) > 0 {
- volumeOptions = append(volumeOptions, libpod.WithVolumeName(options.VolumeName))
- }
- if len(options.Driver) > 0 {
- volumeOptions = append(volumeOptions, libpod.WithVolumeDriver(options.Driver))
- }
- if len(options.Labels) > 0 {
- volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(options.Labels))
- }
- if len(options.Options) > 0 {
- parsedOptions, err := parse.VolumeOptions(options.Options)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- volumeOptions = append(volumeOptions, parsedOptions...)
- }
- newVolume, err := i.Runtime.NewVolume(getContext(), volumeOptions...)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyVolumeCreate(newVolume.Name())
-}
-
-// VolumeRemove removes volumes by options.All or options.Volumes
-func (i *VarlinkAPI) VolumeRemove(call iopodman.VarlinkCall, options iopodman.VolumeRemoveOpts) error {
- success, failed, err := SharedRemoveVolumes(getContext(), i.Runtime, options.Volumes, options.All, options.Force)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- // Convert map[string]string to map[string]error
- errStrings := make(map[string]string)
- for k, v := range failed {
- errStrings[k] = v.Error()
- }
- return call.ReplyVolumeRemove(success, errStrings)
-}
-
-// GetVolumes returns all the volumes known to the remote system
-func (i *VarlinkAPI) GetVolumes(call iopodman.VarlinkCall, args []string, all bool) error {
- var (
- err error
- reply []*libpod.Volume
- volumes []iopodman.Volume
- )
- if all {
- reply, err = i.Runtime.GetAllVolumes()
- } else {
- for _, v := range args {
- vol, err := i.Runtime.GetVolume(v)
- if err != nil {
- return err
- }
- reply = append(reply, vol)
- }
- }
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- // Build the iopodman.volume struct for the return
- for _, v := range reply {
- newVol := iopodman.Volume{
- Driver: v.Driver(),
- Labels: v.Labels(),
- MountPoint: v.MountPoint(),
- Name: v.Name(),
- Options: v.Options(),
- }
- volumes = append(volumes, newVol)
- }
- return call.ReplyGetVolumes(volumes)
-}
-
-// InspectVolume inspects a single volume, returning its JSON as a string.
-func (i *VarlinkAPI) InspectVolume(call iopodman.VarlinkCall, name string) error {
- vol, err := i.Runtime.LookupVolume(name)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- inspectOut, err := vol.Inspect()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- inspectJSON, err := json.Marshal(inspectOut)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyInspectVolume(string(inspectJSON))
-}
-
-// VolumesPrune removes unused images via a varlink call
-func (i *VarlinkAPI) VolumesPrune(call iopodman.VarlinkCall) error {
- var (
- prunedErrors []string
- prunedNames []string
- )
- responses, err := i.Runtime.PruneVolumes(getContext())
- if err != nil {
- return call.ReplyVolumesPrune([]string{}, []string{err.Error()})
- }
- for k, v := range responses {
- if v == nil {
- prunedNames = append(prunedNames, k)
- } else {
- prunedErrors = append(prunedErrors, v.Error())
- }
- }
- return call.ReplyVolumesPrune(prunedNames, prunedErrors)
-}
-
-// Remove given set of volumes
-func SharedRemoveVolumes(ctx context.Context, runtime *libpod.Runtime, vols []string, all, force bool) ([]string, map[string]error, error) {
- var (
- toRemove []*libpod.Volume
- success []string
- failed map[string]error
- )
-
- failed = make(map[string]error)
-
- if all {
- vols, err := runtime.Volumes()
- if err != nil {
- return nil, nil, err
- }
- toRemove = vols
- } else {
- for _, v := range vols {
- vol, err := runtime.LookupVolume(v)
- if err != nil {
- failed[v] = err
- continue
- }
- toRemove = append(toRemove, vol)
- }
- }
-
- // We could parallelize this, but I haven't heard anyone complain about
- // performance here yet, so hold off.
- for _, vol := range toRemove {
- if err := runtime.RemoveVolume(ctx, vol, force); err != nil {
- failed[vol.Name()] = err
- continue
- }
- success = append(success, vol.Name())
- }
-
- return success, failed, nil
-}