summaryrefslogtreecommitdiff
path: root/cmd/podman/shared
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman/shared')
-rw-r--r--cmd/podman/shared/container.go887
-rw-r--r--cmd/podman/shared/create.go981
-rw-r--r--cmd/podman/shared/create_cli.go192
-rw-r--r--cmd/podman/shared/create_cli_test.go19
-rw-r--r--cmd/podman/shared/funcs.go121
-rw-r--r--cmd/podman/shared/funcs_linux_test.go119
-rw-r--r--cmd/podman/shared/funcs_test.go53
-rw-r--r--cmd/podman/shared/intermediate.go479
-rw-r--r--cmd/podman/shared/intermediate_novarlink.go70
-rw-r--r--cmd/podman/shared/intermediate_varlink.go440
-rw-r--r--cmd/podman/shared/parallel.go112
-rw-r--r--cmd/podman/shared/parse/parse.go188
-rw-r--r--cmd/podman/shared/parse/parse_test.go152
-rw-r--r--cmd/podman/shared/pod.go279
-rw-r--r--cmd/podman/shared/volumes_shared.go109
-rw-r--r--cmd/podman/shared/workers.go138
16 files changed, 0 insertions, 4339 deletions
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
deleted file mode 100644
index b5a1e7104..000000000
--- a/cmd/podman/shared/container.go
+++ /dev/null
@@ -1,887 +0,0 @@
-package shared
-
-import (
- "context"
- "fmt"
- "io"
- "os"
- "path/filepath"
- "regexp"
- "sort"
- "strconv"
- "strings"
- "sync"
- "time"
-
- "github.com/containers/image/v5/types"
- "github.com/containers/libpod/libpod"
- "github.com/containers/libpod/libpod/define"
- "github.com/containers/libpod/libpod/image"
- "github.com/containers/libpod/pkg/timetype"
- "github.com/containers/libpod/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 appned 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 execucted 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
-}
diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go
deleted file mode 100644
index f8178a841..000000000
--- a/cmd/podman/shared/create.go
+++ /dev/null
@@ -1,981 +0,0 @@
-package shared
-
-import (
- "context"
- "encoding/json"
- "fmt"
- "io"
- "os"
- "path/filepath"
- goruntime "runtime"
- "strconv"
- "strings"
- "syscall"
- "time"
-
- "github.com/containers/image/v5/manifest"
- "github.com/containers/libpod/cmd/podman/shared/parse"
- "github.com/containers/libpod/libpod"
- "github.com/containers/libpod/libpod/define"
- "github.com/containers/libpod/libpod/image"
- ann "github.com/containers/libpod/pkg/annotations"
- "github.com/containers/libpod/pkg/autoupdate"
- envLib "github.com/containers/libpod/pkg/env"
- "github.com/containers/libpod/pkg/errorhandling"
- "github.com/containers/libpod/pkg/inspect"
- ns "github.com/containers/libpod/pkg/namespaces"
- "github.com/containers/libpod/pkg/rootless"
- "github.com/containers/libpod/pkg/seccomp"
- cc "github.com/containers/libpod/pkg/spec"
- systemdGen "github.com/containers/libpod/pkg/systemd/generate"
- "github.com/containers/libpod/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"
-)
-
-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(runtime, createConfig, ctx, 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"))
- }
- if x && (command[0] == "/usr/sbin/init" || command[0] == "/sbin/init" || (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(r *libpod.Runtime, createConfig *cc.CreateConfig, ctx context.Context, pod *libpod.Pod) (*libpod.Container, error) {
- runtimeSpec, options, err := createConfig.MakeContainerConfig(r, pod)
- if err != nil {
- return nil, err
- }
-
- // Set the CreateCommand explicitly. Some (future) consumers of libpod
- // might not want to set it.
- options = append(options, libpod.WithCreateCommand())
-
- 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
-}
diff --git a/cmd/podman/shared/create_cli.go b/cmd/podman/shared/create_cli.go
deleted file mode 100644
index 10e27350b..000000000
--- a/cmd/podman/shared/create_cli.go
+++ /dev/null
@@ -1,192 +0,0 @@
-package shared
-
-import (
- "fmt"
- "strings"
-
- "github.com/containers/libpod/pkg/cgroups"
- cc "github.com/containers/libpod/pkg/spec"
- "github.com/containers/libpod/pkg/sysinfo"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-// validateSysctl validates a sysctl and returns it.
-func validateSysctl(strSlice []string) (map[string]string, error) {
- sysctl := make(map[string]string)
- validSysctlMap := map[string]bool{
- "kernel.msgmax": true,
- "kernel.msgmnb": true,
- "kernel.msgmni": true,
- "kernel.sem": true,
- "kernel.shmall": true,
- "kernel.shmmax": true,
- "kernel.shmmni": true,
- "kernel.shm_rmid_forced": true,
- }
- validSysctlPrefixes := []string{
- "net.",
- "fs.mqueue.",
- }
-
- for _, val := range strSlice {
- foundMatch := false
- arr := strings.Split(val, "=")
- if len(arr) < 2 {
- return nil, errors.Errorf("%s is invalid, sysctl values must be in the form of KEY=VALUE", val)
- }
- if validSysctlMap[arr[0]] {
- sysctl[arr[0]] = arr[1]
- continue
- }
-
- for _, prefix := range validSysctlPrefixes {
- if strings.HasPrefix(arr[0], prefix) {
- sysctl[arr[0]] = arr[1]
- foundMatch = true
- break
- }
- }
- if !foundMatch {
- return nil, errors.Errorf("sysctl '%s' is not whitelisted", arr[0])
- }
- }
- return sysctl, 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/cmd/podman/shared/create_cli_test.go b/cmd/podman/shared/create_cli_test.go
deleted file mode 100644
index a045962cb..000000000
--- a/cmd/podman/shared/create_cli_test.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package shared
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestValidateSysctl(t *testing.T) {
- strSlice := []string{"net.core.test1=4", "kernel.msgmax=2"}
- result, _ := validateSysctl(strSlice)
- assert.Equal(t, result["net.core.test1"], "4")
-}
-
-func TestValidateSysctlBadSysctl(t *testing.T) {
- strSlice := []string{"BLAU=BLUE", "GELB^YELLOW"}
- _, err := validateSysctl(strSlice)
- assert.Error(t, err)
-}
diff --git a/cmd/podman/shared/funcs.go b/cmd/podman/shared/funcs.go
deleted file mode 100644
index 404d0f288..000000000
--- a/cmd/podman/shared/funcs.go
+++ /dev/null
@@ -1,121 +0,0 @@
-package shared
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/containers/image/v5/types"
- "github.com/containers/libpod/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/cmd/podman/shared/funcs_linux_test.go b/cmd/podman/shared/funcs_linux_test.go
deleted file mode 100644
index 88571153f..000000000
--- a/cmd/podman/shared/funcs_linux_test.go
+++ /dev/null
@@ -1,119 +0,0 @@
-package shared
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestGenerateCommand(t *testing.T) {
- inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo \"hello world\""
- correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo hello world"
- newCommand, err := GenerateCommand(inputCommand, "foo", "bar", "")
- assert.Nil(t, err)
- assert.Equal(t, "hello world", newCommand[11])
- assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
-}
-
-func TestGenerateCommandCheckSubstitution(t *testing.T) {
- type subsTest struct {
- input string
- expected string
- shouldFail bool
- }
-
- absTmpFile, err := ioutil.TempFile("", "podmanRunlabelTestAbsolutePath")
- assert.Nil(t, err, "error creating tempfile")
- defer os.Remove(absTmpFile.Name())
-
- relTmpFile, err := ioutil.TempFile("./", "podmanRunlabelTestRelativePath")
- assert.Nil(t, err, "error creating tempfile")
- defer os.Remove(relTmpFile.Name())
- relTmpCmd, err := filepath.Abs(relTmpFile.Name())
- assert.Nil(t, err, "error getting absolute path for relative tmpfile")
-
- // this has a (low) potential of race conditions but no other way
- removedTmpFile, err := ioutil.TempFile("", "podmanRunlabelTestRemove")
- assert.Nil(t, err, "error creating tempfile")
- os.Remove(removedTmpFile.Name())
-
- absTmpCmd := fmt.Sprintf("%s --flag1 --flag2 --args=foo", absTmpFile.Name())
- tests := []subsTest{
- {
- input: "docker run -it alpine:latest",
- expected: "/proc/self/exe run -it alpine:latest",
- shouldFail: false,
- },
- {
- input: "podman run -it alpine:latest",
- expected: "/proc/self/exe run -it alpine:latest",
- shouldFail: false,
- },
- {
- input: absTmpCmd,
- expected: absTmpCmd,
- shouldFail: false,
- },
- {
- input: "./" + relTmpFile.Name(),
- expected: relTmpCmd,
- shouldFail: false,
- },
- {
- input: "ls -la",
- expected: "ls -la",
- shouldFail: false,
- },
- {
- input: removedTmpFile.Name(),
- expected: "",
- shouldFail: true,
- },
- }
-
- for _, test := range tests {
- newCommand, err := GenerateCommand(test.input, "foo", "bar", "")
- if test.shouldFail {
- assert.NotNil(t, err)
- } else {
- assert.Nil(t, err)
- }
- assert.Equal(t, test.expected, strings.Join(newCommand, " "))
- }
-}
-
-func TestGenerateCommandPath(t *testing.T) {
- inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
- correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install"
- newCommand, _ := GenerateCommand(inputCommand, "foo", "bar", "")
- assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
-}
-
-func TestGenerateCommandNoSetName(t *testing.T) {
- inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
- correctCommand := "/proc/self/exe run -it --name foo -e NAME=foo -e IMAGE=foo foo echo install"
- newCommand, err := GenerateCommand(inputCommand, "foo", "", "")
- assert.Nil(t, err)
- assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
-}
-
-func TestGenerateCommandNoName(t *testing.T) {
- inputCommand := "docker run -it -e IMAGE=IMAGE IMAGE echo install"
- correctCommand := "/proc/self/exe run -it -e IMAGE=foo foo echo install"
- newCommand, err := GenerateCommand(inputCommand, "foo", "", "")
- assert.Nil(t, err)
- assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
-}
-
-func TestGenerateCommandAlreadyPodman(t *testing.T) {
- inputCommand := "podman run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
- correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install"
- newCommand, err := GenerateCommand(inputCommand, "foo", "bar", "")
- assert.Nil(t, err)
- assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
-}
diff --git a/cmd/podman/shared/funcs_test.go b/cmd/podman/shared/funcs_test.go
deleted file mode 100644
index dd856166e..000000000
--- a/cmd/podman/shared/funcs_test.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package shared
-
-import (
- "testing"
-
- "github.com/containers/libpod/pkg/util"
- "github.com/stretchr/testify/assert"
-)
-
-var (
- name = "foo"
- imageName = "bar"
-)
-
-func TestGenerateRunEnvironment(t *testing.T) {
- opts := make(map[string]string)
- opts["opt1"] = "one"
- opts["opt2"] = "two"
- opts["opt3"] = "three"
- envs := GenerateRunEnvironment(name, imageName, opts)
- assert.True(t, util.StringInSlice("OPT1=one", envs))
- assert.True(t, util.StringInSlice("OPT2=two", envs))
- assert.True(t, util.StringInSlice("OPT3=three", envs))
-}
-
-func TestGenerateRunEnvironmentNoOpts(t *testing.T) {
- opts := make(map[string]string)
- envs := GenerateRunEnvironment(name, imageName, opts)
- assert.False(t, util.StringInSlice("OPT1=", envs))
- assert.False(t, util.StringInSlice("OPT2=", envs))
- assert.False(t, util.StringInSlice("OPT3=", envs))
-}
-
-func TestGenerateRunEnvironmentSingleOpt(t *testing.T) {
- opts := make(map[string]string)
- opts["opt1"] = "one"
- envs := GenerateRunEnvironment(name, imageName, opts)
- assert.True(t, util.StringInSlice("OPT1=one", envs))
- assert.False(t, util.StringInSlice("OPT2=", envs))
- assert.False(t, util.StringInSlice("OPT3=", envs))
-}
-
-func TestGenerateRunEnvironmentName(t *testing.T) {
- opts := make(map[string]string)
- envs := GenerateRunEnvironment(name, imageName, opts)
- assert.True(t, util.StringInSlice("NAME=foo", envs))
-}
-
-func TestGenerateRunEnvironmentImage(t *testing.T) {
- opts := make(map[string]string)
- envs := GenerateRunEnvironment(name, imageName, opts)
- assert.True(t, util.StringInSlice("IMAGE=bar", envs))
-}
diff --git a/cmd/podman/shared/intermediate.go b/cmd/podman/shared/intermediate.go
deleted file mode 100644
index e76750042..000000000
--- a/cmd/podman/shared/intermediate.go
+++ /dev/null
@@ -1,479 +0,0 @@
-package shared
-
-import (
- "github.com/containers/libpod/cmd/podman/cliconfig"
- "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 }
-
-func newCreateResult(c *cliconfig.PodmanCommand, flag string) createResult {
- return createResult{
- Flag: flag,
- Changed: c.IsSet(flag),
- }
-}
-
-func newCRStringSlice(c *cliconfig.PodmanCommand, flag string) CRStringSlice {
- return CRStringSlice{
- Val: c.StringSlice(flag),
- createResult: newCreateResult(c, flag),
- }
-}
-
-func newCRString(c *cliconfig.PodmanCommand, flag string) CRString {
- return CRString{
- Val: c.String(flag),
- createResult: newCreateResult(c, flag),
- }
-}
-
-func newCRUint64(c *cliconfig.PodmanCommand, flag string) CRUint64 {
- return CRUint64{
- Val: c.Uint64(flag),
- createResult: newCreateResult(c, flag),
- }
-}
-
-func newCRFloat64(c *cliconfig.PodmanCommand, flag string) CRFloat64 {
- return CRFloat64{
- Val: c.Float64(flag),
- createResult: newCreateResult(c, flag),
- }
-}
-
-func newCRBool(c *cliconfig.PodmanCommand, flag string) CRBool {
- return CRBool{
- Val: c.Bool(flag),
- createResult: newCreateResult(c, flag),
- }
-}
-
-func newCRInt64(c *cliconfig.PodmanCommand, flag string) CRInt64 {
- return CRInt64{
- Val: c.Int64(flag),
- createResult: newCreateResult(c, flag),
- }
-}
-
-func newCRUint(c *cliconfig.PodmanCommand, flag string) CRUint {
- return CRUint{
- Val: c.Uint(flag),
- createResult: newCreateResult(c, flag),
- }
-}
-
-func newCRInt(c *cliconfig.PodmanCommand, flag string) CRInt {
- return CRInt{
- Val: c.Int(flag),
- createResult: newCreateResult(c, flag),
- }
-}
-
-func newCRStringArray(c *cliconfig.PodmanCommand, flag string) CRStringArray {
- return CRStringArray{
- Val: c.StringArray(flag),
- createResult: newCreateResult(c, flag),
- }
-}
-
-// NewIntermediateLayer creates a GenericCLIResults from a create or run cli-command
-func NewIntermediateLayer(c *cliconfig.PodmanCommand, remote bool) GenericCLIResults {
- m := make(map[string]GenericCLIResult)
-
- m["add-host"] = newCRStringSlice(c, "add-host")
- m["annotation"] = newCRStringSlice(c, "annotation")
- m["attach"] = newCRStringSlice(c, "attach")
- m["blkio-weight"] = newCRString(c, "blkio-weight")
- m["blkio-weight-device"] = newCRStringSlice(c, "blkio-weight-device")
- m["cap-add"] = newCRStringSlice(c, "cap-add")
- m["cap-drop"] = newCRStringSlice(c, "cap-drop")
- m["cgroupns"] = newCRString(c, "cgroupns")
- m["cgroups"] = newCRString(c, "cgroups")
- m["cgroup-parent"] = newCRString(c, "cgroup-parent")
- m["cidfile"] = newCRString(c, "cidfile")
- m["conmon-pidfile"] = newCRString(c, "conmon-pidfile")
- m["cpu-period"] = newCRUint64(c, "cpu-period")
- m["cpu-quota"] = newCRInt64(c, "cpu-quota")
- m["cpu-rt-period"] = newCRUint64(c, "cpu-rt-period")
- m["cpu-rt-runtime"] = newCRInt64(c, "cpu-rt-runtime")
- m["cpu-shares"] = newCRUint64(c, "cpu-shares")
- m["cpus"] = newCRFloat64(c, "cpus")
- m["cpuset-cpus"] = newCRString(c, "cpuset-cpus")
- m["cpuset-mems"] = newCRString(c, "cpuset-mems")
- m["detach"] = newCRBool(c, "detach")
- m["detach-keys"] = newCRString(c, "detach-keys")
- m["device"] = newCRStringSlice(c, "device")
- m["device-cgroup-rule"] = newCRStringSlice(c, "device-cgroup-rule")
- m["device-read-bps"] = newCRStringSlice(c, "device-read-bps")
- m["device-read-iops"] = newCRStringSlice(c, "device-read-iops")
- m["device-write-bps"] = newCRStringSlice(c, "device-write-bps")
- m["device-write-iops"] = newCRStringSlice(c, "device-write-iops")
- m["dns"] = newCRStringSlice(c, "dns")
- m["dns-opt"] = newCRStringSlice(c, "dns-opt")
- m["dns-search"] = newCRStringSlice(c, "dns-search")
- m["entrypoint"] = newCRString(c, "entrypoint")
- m["env"] = newCRStringArray(c, "env")
- m["env-file"] = newCRStringSlice(c, "env-file")
- m["expose"] = newCRStringSlice(c, "expose")
- m["gidmap"] = newCRStringSlice(c, "gidmap")
- m["group-add"] = newCRStringSlice(c, "group-add")
- m["help"] = newCRBool(c, "help")
- m["healthcheck-command"] = newCRString(c, "health-cmd")
- m["healthcheck-interval"] = newCRString(c, "health-interval")
- m["healthcheck-retries"] = newCRUint(c, "health-retries")
- m["healthcheck-start-period"] = newCRString(c, "health-start-period")
- m["healthcheck-timeout"] = newCRString(c, "health-timeout")
- m["hostname"] = newCRString(c, "hostname")
- m["image-volume"] = newCRString(c, "image-volume")
- m["init"] = newCRBool(c, "init")
- m["init-path"] = newCRString(c, "init-path")
- m["interactive"] = newCRBool(c, "interactive")
- m["ip"] = newCRString(c, "ip")
- m["ipc"] = newCRString(c, "ipc")
- m["kernel-memory"] = newCRString(c, "kernel-memory")
- m["label"] = newCRStringArray(c, "label")
- m["label-file"] = newCRStringSlice(c, "label-file")
- m["log-driver"] = newCRString(c, "log-driver")
- m["log-opt"] = newCRStringSlice(c, "log-opt")
- m["mac-address"] = newCRString(c, "mac-address")
- m["memory"] = newCRString(c, "memory")
- m["memory-reservation"] = newCRString(c, "memory-reservation")
- m["memory-swap"] = newCRString(c, "memory-swap")
- m["memory-swappiness"] = newCRInt64(c, "memory-swappiness")
- m["name"] = newCRString(c, "name")
- m["network"] = newCRString(c, "network")
- m["no-healthcheck"] = newCRBool(c, "no-healthcheck")
- m["no-hosts"] = newCRBool(c, "no-hosts")
- m["oom-kill-disable"] = newCRBool(c, "oom-kill-disable")
- m["oom-score-adj"] = newCRInt(c, "oom-score-adj")
- m["override-arch"] = newCRString(c, "override-arch")
- m["override-os"] = newCRString(c, "override-os")
- m["pid"] = newCRString(c, "pid")
- m["pids-limit"] = newCRInt64(c, "pids-limit")
- m["pod"] = newCRString(c, "pod")
- m["privileged"] = newCRBool(c, "privileged")
- m["publish"] = newCRStringSlice(c, "publish")
- m["publish-all"] = newCRBool(c, "publish-all")
- m["pull"] = newCRString(c, "pull")
- m["quiet"] = newCRBool(c, "quiet")
- m["read-only"] = newCRBool(c, "read-only")
- m["read-only-tmpfs"] = newCRBool(c, "read-only-tmpfs")
- m["restart"] = newCRString(c, "restart")
- m["rm"] = newCRBool(c, "rm")
- m["rootfs"] = newCRBool(c, "rootfs")
- m["security-opt"] = newCRStringArray(c, "security-opt")
- m["shm-size"] = newCRString(c, "shm-size")
- m["stop-signal"] = newCRString(c, "stop-signal")
- m["stop-timeout"] = newCRUint(c, "stop-timeout")
- m["storage-opt"] = newCRStringSlice(c, "storage-opt")
- m["subgidname"] = newCRString(c, "subgidname")
- m["subuidname"] = newCRString(c, "subuidname")
- m["sysctl"] = newCRStringSlice(c, "sysctl")
- m["systemd"] = newCRString(c, "systemd")
- m["tmpfs"] = newCRStringArray(c, "tmpfs")
- m["tty"] = newCRBool(c, "tty")
- m["uidmap"] = newCRStringSlice(c, "uidmap")
- m["ulimit"] = newCRStringSlice(c, "ulimit")
- m["user"] = newCRString(c, "user")
- m["userns"] = newCRString(c, "userns")
- m["uts"] = newCRString(c, "uts")
- m["mount"] = newCRStringArray(c, "mount")
- m["volume"] = newCRStringArray(c, "volume")
- m["volumes-from"] = newCRStringSlice(c, "volumes-from")
- m["workdir"] = newCRString(c, "workdir")
- m["seccomp-policy"] = newCRString(c, "seccomp-policy")
- // global flag
- if !remote {
- m["authfile"] = newCRString(c, "authfile")
- m["cgroupns"] = newCRString(c, "cgroupns")
- m["env-host"] = newCRBool(c, "env-host")
- m["http-proxy"] = newCRBool(c, "http-proxy")
- m["trace"] = newCRBool(c, "trace")
- m["syslog"] = newCRBool(c, "syslog")
- }
-
- return GenericCLIResults{m, c.InputArgs}
-}
diff --git a/cmd/podman/shared/intermediate_novarlink.go b/cmd/podman/shared/intermediate_novarlink.go
deleted file mode 100644
index c6f011fe0..000000000
--- a/cmd/podman/shared/intermediate_novarlink.go
+++ /dev/null
@@ -1,70 +0,0 @@
-// +build !varlink
-// +build !remoteclient
-
-package shared
-
-/*
-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.
-*/
-
-// ToString wrapper for build without varlink
-func (c CRStringSlice) ToVarlink() interface{} {
- var v interface{}
- return v
-}
-
-// ToString wrapper for build without varlink
-func (c CRString) ToVarlink() interface{} {
- var v interface{}
- return v
-}
-
-// ToString wrapper for build without varlink
-func (c CRBool) ToVarlink() interface{} {
- var v interface{}
- return v
-}
-
-// ToString wrapper for build without varlink
-func (c CRUint64) ToVarlink() interface{} {
- var v interface{}
- return v
-}
-
-// ToString wrapper for build without varlink
-func (c CRInt64) ToVarlink() interface{} {
- var v interface{}
- return v
-}
-
-// ToString wrapper for build without varlink
-func (c CRFloat64) ToVarlink() interface{} {
- var v interface{}
- return v
-}
-
-// ToString wrapper for build without varlink
-func (c CRUint) ToVarlink() interface{} {
- var v interface{}
- return v
-}
-
-// ToString wrapper for build without varlink
-func (c CRStringArray) ToVarlink() interface{} {
- var v interface{}
- return v
-}
-
-// ToString wrapper for build without varlink
-func (c CRInt) ToVarlink() interface{} {
- var v interface{}
- return v
-}
diff --git a/cmd/podman/shared/intermediate_varlink.go b/cmd/podman/shared/intermediate_varlink.go
deleted file mode 100644
index 82594fb40..000000000
--- a/cmd/podman/shared/intermediate_varlink.go
+++ /dev/null
@@ -1,440 +0,0 @@
-// +build varlink remoteclient
-
-package shared
-
-import (
- "github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/pkg/rootless"
- iopodman "github.com/containers/libpod/pkg/varlink"
- "github.com/pkg/errors"
-)
-
-// 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 {
-
- defaultContainerConfig := 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"
- }
-
- 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", &cliconfig.DefaultHealthCheckInterval)
- m["healthcheck-retries"] = uintFromVarlink(opts.HealthcheckRetries, "healthcheck-retries", &cliconfig.DefaultHealthCheckRetries)
- m["healthcheck-start-period"] = stringFromVarlink(opts.HealthcheckStartPeriod, "healthcheck-start-period", &cliconfig.DefaultHealthCheckStartPeriod)
- m["healthcheck-timeout"] = stringFromVarlink(opts.HealthcheckTimeout, "healthcheck-timeout", &cliconfig.DefaultHealthCheckTimeout)
- m["hostname"] = stringFromVarlink(opts.Hostname, "hostname", nil)
- m["image-volume"] = stringFromVarlink(opts.ImageVolume, "image-volume", &cliconfig.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", &defaultContainerConfig.Containers.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/cmd/podman/shared/parallel.go b/cmd/podman/shared/parallel.go
deleted file mode 100644
index eb1d40073..000000000
--- a/cmd/podman/shared/parallel.go
+++ /dev/null
@@ -1,112 +0,0 @@
-package shared
-
-import (
- "runtime"
- "sync"
-)
-
-type pFunc func() error
-
-// ParallelWorkerInput is a struct used to pass in a slice of parallel funcs to be
-// performed on a container ID
-type ParallelWorkerInput struct {
- ContainerID string
- ParallelFunc pFunc
-}
-
-type containerError struct {
- ContainerID string
- Err error
-}
-
-// ParallelWorker is a "threaded" worker that takes jobs from the channel "queue"
-func ParallelWorker(wg *sync.WaitGroup, jobs <-chan ParallelWorkerInput, results chan<- containerError) {
- for j := range jobs {
- err := j.ParallelFunc()
- results <- containerError{ContainerID: j.ContainerID, Err: err}
- wg.Done()
- }
-}
-
-// ParallelExecuteWorkerPool takes container jobs and performs them in parallel. The worker
-// int determines how many workers/threads should be premade.
-func ParallelExecuteWorkerPool(workers int, functions []ParallelWorkerInput) (map[string]error, int) {
- var (
- wg sync.WaitGroup
- errorCount int
- )
-
- resultChan := make(chan containerError, len(functions))
- results := make(map[string]error)
- paraJobs := make(chan ParallelWorkerInput, len(functions))
-
- // If we have more workers than functions, match up the number of workers and functions
- if workers > len(functions) {
- workers = len(functions)
- }
-
- // Create the workers
- for w := 1; w <= workers; w++ {
- go ParallelWorker(&wg, paraJobs, resultChan)
- }
-
- // Add jobs to the workers
- for _, j := range functions {
- j := j
- wg.Add(1)
- paraJobs <- j
- }
-
- close(paraJobs)
- wg.Wait()
-
- close(resultChan)
- for ctrError := range resultChan {
- results[ctrError.ContainerID] = ctrError.Err
- if ctrError.Err != nil {
- errorCount += 1
- }
- }
-
- return results, errorCount
-}
-
-// 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/cmd/podman/shared/parse/parse.go b/cmd/podman/shared/parse/parse.go
deleted file mode 100644
index 03cda268c..000000000
--- a/cmd/podman/shared/parse/parse.go
+++ /dev/null
@@ -1,188 +0,0 @@
-//nolint
-// most of these validate and parse functions have been taken from projectatomic/docker
-// and modified for cri-o
-package parse
-
-import (
- "bufio"
- "fmt"
- "net"
- "net/url"
- "os"
- "regexp"
- "strings"
-
- "github.com/pkg/errors"
-)
-
-const (
- Protocol_TCP Protocol = 0
- Protocol_UDP Protocol = 1
-)
-
-type Protocol int32
-
-// PortMapping specifies the port mapping configurations of a sandbox.
-type PortMapping struct {
- // Protocol of the port mapping.
- Protocol Protocol `protobuf:"varint,1,opt,name=protocol,proto3,enum=runtime.Protocol" json:"protocol,omitempty"`
- // Port number within the container. Default: 0 (not specified).
- ContainerPort int32 `protobuf:"varint,2,opt,name=container_port,json=containerPort,proto3" json:"container_port,omitempty"`
- // Port number on the host. Default: 0 (not specified).
- HostPort int32 `protobuf:"varint,3,opt,name=host_port,json=hostPort,proto3" json:"host_port,omitempty"`
- // Host IP.
- HostIp string `protobuf:"bytes,4,opt,name=host_ip,json=hostIp,proto3" json:"host_ip,omitempty"`
-}
-
-// Note: for flags that are in the form <number><unit>, use the RAMInBytes function
-// from the units package in docker/go-units/size.go
-
-var (
- whiteSpaces = " \t"
- alphaRegexp = regexp.MustCompile(`[a-zA-Z]`)
- domainRegexp = regexp.MustCompile(`^(:?(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]))(:?\.(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])))*)\.?\s*$`)
-)
-
-// validateExtraHost validates that the specified string is a valid extrahost and returns it.
-// ExtraHost is in the form of name:ip where the ip has to be a valid ip (ipv4 or ipv6).
-// for add-host flag
-func ValidateExtraHost(val string) (string, error) { //nolint
- // allow for IPv6 addresses in extra hosts by only splitting on first ":"
- arr := strings.SplitN(val, ":", 2)
- if len(arr) != 2 || len(arr[0]) == 0 {
- return "", fmt.Errorf("bad format for add-host: %q", val)
- }
- if _, err := validateIPAddress(arr[1]); err != nil {
- return "", fmt.Errorf("invalid IP address in add-host: %q", arr[1])
- }
- return val, nil
-}
-
-// validateIPAddress validates an Ip address.
-// for dns, ip, and ip6 flags also
-func validateIPAddress(val string) (string, error) {
- var ip = net.ParseIP(strings.TrimSpace(val))
- if ip != nil {
- return ip.String(), nil
- }
- return "", fmt.Errorf("%s is not an ip address", val)
-}
-
-func ValidateDomain(val string) (string, error) {
- if alphaRegexp.FindString(val) == "" {
- return "", fmt.Errorf("%s is not a valid domain", val)
- }
- ns := domainRegexp.FindSubmatch([]byte(val))
- if len(ns) > 0 && len(ns[1]) < 255 {
- return string(ns[1]), nil
- }
- return "", fmt.Errorf("%s is not a valid domain", val)
-}
-
-// GetAllLabels retrieves all labels given a potential label file and a number
-// of labels provided from the command line.
-func GetAllLabels(labelFile, inputLabels []string) (map[string]string, error) {
- labels := make(map[string]string)
- for _, file := range labelFile {
- // Use of parseEnvFile still seems safe, as it's missing the
- // extra parsing logic of parseEnv.
- // There's an argument that we SHOULD be doing that parsing for
- // all environment variables, even those sourced from files, but
- // that would require a substantial rework.
- if err := parseEnvFile(labels, file); err != nil {
- // FIXME: parseEnvFile is using parseEnv, so we need to add extra
- // logic for labels.
- return nil, err
- }
- }
- for _, label := range inputLabels {
- split := strings.SplitN(label, "=", 2)
- if split[0] == "" {
- return nil, errors.Errorf("invalid label format: %q", label)
- }
- value := ""
- if len(split) > 1 {
- value = split[1]
- }
- labels[split[0]] = value
- }
- return labels, nil
-}
-
-func parseEnv(env map[string]string, line string) error {
- data := strings.SplitN(line, "=", 2)
-
- // catch invalid variables such as "=" or "=A"
- if data[0] == "" {
- return errors.Errorf("invalid environment variable: %q", line)
- }
-
- // trim the front of a variable, but nothing else
- name := strings.TrimLeft(data[0], whiteSpaces)
- if strings.ContainsAny(name, whiteSpaces) {
- return errors.Errorf("name %q has white spaces, poorly formatted name", name)
- }
-
- if len(data) > 1 {
- env[name] = data[1]
- } else {
- if strings.HasSuffix(name, "*") {
- name = strings.TrimSuffix(name, "*")
- for _, e := range os.Environ() {
- part := strings.SplitN(e, "=", 2)
- if len(part) < 2 {
- continue
- }
- if strings.HasPrefix(part[0], name) {
- env[part[0]] = part[1]
- }
- }
- } else {
- // if only a pass-through variable is given, clean it up.
- if val, ok := os.LookupEnv(name); ok {
- env[name] = val
- }
- }
- }
- return nil
-}
-
-// parseEnvFile reads a file with environment variables enumerated by lines
-func parseEnvFile(env map[string]string, filename string) error {
- fh, err := os.Open(filename)
- if err != nil {
- return err
- }
- defer fh.Close()
-
- scanner := bufio.NewScanner(fh)
- for scanner.Scan() {
- // trim the line from all leading whitespace first
- line := strings.TrimLeft(scanner.Text(), whiteSpaces)
- // line is not empty, and not starting with '#'
- if len(line) > 0 && !strings.HasPrefix(line, "#") {
- if err := parseEnv(env, line); err != nil {
- return err
- }
- }
- }
- return scanner.Err()
-}
-
-// ValidateFileName returns an error if filename contains ":"
-// as it is currently not supported
-func ValidateFileName(filename string) error {
- if strings.Contains(filename, ":") {
- return errors.Errorf("invalid filename (should not contain ':') %q", filename)
- }
- return nil
-}
-
-// ValidURL checks a string urlStr is a url or not
-func ValidURL(urlStr string) error {
- _, err := url.ParseRequestURI(urlStr)
- if err != nil {
- return errors.Wrapf(err, "invalid url path: %q", urlStr)
- }
- return nil
-}
diff --git a/cmd/podman/shared/parse/parse_test.go b/cmd/podman/shared/parse/parse_test.go
deleted file mode 100644
index a6ddc2be9..000000000
--- a/cmd/podman/shared/parse/parse_test.go
+++ /dev/null
@@ -1,152 +0,0 @@
-//nolint
-// most of these validate and parse functions have been taken from projectatomic/docker
-// and modified for cri-o
-package parse
-
-import (
- "io/ioutil"
- "os"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- Var1 = []string{"ONE=1", "TWO=2"}
-)
-
-func createTmpFile(content []byte) (string, error) {
- tmpfile, err := ioutil.TempFile(os.TempDir(), "unittest")
- if err != nil {
- return "", err
- }
-
- if _, err := tmpfile.Write(content); err != nil {
- return "", err
-
- }
- if err := tmpfile.Close(); err != nil {
- return "", err
- }
- return tmpfile.Name(), nil
-}
-
-func TestValidateExtraHost(t *testing.T) {
- type args struct {
- val string
- }
- tests := []struct {
- name string
- args args
- want string
- wantErr bool
- }{
- //2001:0db8:85a3:0000:0000:8a2e:0370:7334
- {name: "good-ipv4", args: args{val: "foobar:192.168.1.1"}, want: "foobar:192.168.1.1", wantErr: false},
- {name: "bad-ipv4", args: args{val: "foobar:999.999.999.99"}, want: "", wantErr: true},
- {name: "bad-ipv4", args: args{val: "foobar:999.999.999"}, want: "", wantErr: true},
- {name: "noname-ipv4", args: args{val: "192.168.1.1"}, want: "", wantErr: true},
- {name: "noname-ipv4", args: args{val: ":192.168.1.1"}, want: "", wantErr: true},
- {name: "noip", args: args{val: "foobar:"}, want: "", wantErr: true},
- {name: "noip", args: args{val: "foobar"}, want: "", wantErr: true},
- {name: "good-ipv6", args: args{val: "foobar:2001:0db8:85a3:0000:0000:8a2e:0370:7334"}, want: "foobar:2001:0db8:85a3:0000:0000:8a2e:0370:7334", wantErr: false},
- {name: "bad-ipv6", args: args{val: "foobar:0db8:85a3:0000:0000:8a2e:0370:7334"}, want: "", wantErr: true},
- {name: "bad-ipv6", args: args{val: "foobar:0db8:85a3:0000:0000:8a2e:0370:7334.0000.0000.000"}, want: "", wantErr: true},
- {name: "noname-ipv6", args: args{val: "2001:0db8:85a3:0000:0000:8a2e:0370:7334"}, want: "", wantErr: true},
- {name: "noname-ipv6", args: args{val: ":2001:0db8:85a3:0000:0000:8a2e:0370:7334"}, want: "", wantErr: true},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := ValidateExtraHost(tt.args.val)
- if (err != nil) != tt.wantErr {
- t.Errorf("ValidateExtraHost() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if got != tt.want {
- t.Errorf("ValidateExtraHost() = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func Test_validateIPAddress(t *testing.T) {
- type args struct {
- val string
- }
- tests := []struct {
- name string
- args args
- want string
- wantErr bool
- }{
- {name: "ipv4-good", args: args{val: "192.168.1.1"}, want: "192.168.1.1", wantErr: false},
- {name: "ipv4-bad", args: args{val: "192.168.1.1.1"}, want: "", wantErr: true},
- {name: "ipv4-bad", args: args{val: "192."}, want: "", wantErr: true},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := validateIPAddress(tt.args.val)
- if (err != nil) != tt.wantErr {
- t.Errorf("validateIPAddress() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if got != tt.want {
- t.Errorf("validateIPAddress() = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func TestValidateFileName(t *testing.T) {
- type args struct {
- filename string
- }
- tests := []struct {
- name string
- args args
- wantErr bool
- }{
- {name: "good", args: args{filename: "/some/rand/path"}, wantErr: false},
- {name: "good", args: args{filename: "some/rand/path"}, wantErr: false},
- {name: "good", args: args{filename: "/"}, wantErr: false},
- {name: "bad", args: args{filename: "/:"}, wantErr: true},
- {name: "bad", args: args{filename: ":/"}, wantErr: true},
- {name: "bad", args: args{filename: "/some/rand:/path"}, wantErr: true},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- if err := ValidateFileName(tt.args.filename); (err != nil) != tt.wantErr {
- t.Errorf("ValidateFileName() error = %v, wantErr %v", err, tt.wantErr)
- }
- })
- }
-}
-
-func TestGetAllLabels(t *testing.T) {
- fileLabels := []string{}
- labels, _ := GetAllLabels(fileLabels, Var1)
- assert.Equal(t, len(labels), 2)
-}
-
-func TestGetAllLabelsBadKeyValue(t *testing.T) {
- inLabels := []string{"=badValue", "="}
- fileLabels := []string{}
- _, err := GetAllLabels(fileLabels, inLabels)
- assert.Error(t, err, assert.AnError)
-}
-
-func TestGetAllLabelsBadLabelFile(t *testing.T) {
- fileLabels := []string{"/foobar5001/be"}
- _, err := GetAllLabels(fileLabels, Var1)
- assert.Error(t, err, assert.AnError)
-}
-
-func TestGetAllLabelsFile(t *testing.T) {
- content := []byte("THREE=3")
- tFile, err := createTmpFile(content)
- defer os.Remove(tFile)
- assert.NoError(t, err)
- fileLabels := []string{tFile}
- result, _ := GetAllLabels(fileLabels, Var1)
- assert.Equal(t, len(result), 3)
-}
diff --git a/cmd/podman/shared/pod.go b/cmd/podman/shared/pod.go
deleted file mode 100644
index 50bd88e08..000000000
--- a/cmd/podman/shared/pod.go
+++ /dev/null
@@ -1,279 +0,0 @@
-package shared
-
-import (
- "strconv"
- "strings"
-
- "github.com/containers/libpod/libpod"
- "github.com/containers/libpod/libpod/define"
- "github.com/containers/libpod/pkg/util"
- "github.com/cri-o/ocicni/pkg/ocicni"
- "github.com/docker/go-connections/nat"
- "github.com/pkg/errors"
-)
-
-// TODO GetPodStatus and CreatePodStatusResults should removed once the adapter
-// and shared packages are reworked. It has now been duplicated in libpod proper.
-
-// GetPodStatus determines the status of the pod based on the
-// statuses of the containers in the pod.
-// Returns a string representation of the pod status
-func GetPodStatus(pod *libpod.Pod) (string, error) {
- ctrStatuses, err := pod.Status()
- if err != nil {
- return define.PodStateErrored, err
- }
- return CreatePodStatusResults(ctrStatuses)
-}
-
-func CreatePodStatusResults(ctrStatuses map[string]define.ContainerStatus) (string, error) {
- ctrNum := len(ctrStatuses)
- if ctrNum == 0 {
- return define.PodStateCreated, nil
- }
- statuses := map[string]int{
- define.PodStateStopped: 0,
- define.PodStateRunning: 0,
- define.PodStatePaused: 0,
- define.PodStateCreated: 0,
- define.PodStateErrored: 0,
- }
- for _, ctrStatus := range ctrStatuses {
- switch ctrStatus {
- case define.ContainerStateExited:
- fallthrough
- case define.ContainerStateStopped:
- statuses[define.PodStateStopped]++
- case define.ContainerStateRunning:
- statuses[define.PodStateRunning]++
- case define.ContainerStatePaused:
- statuses[define.PodStatePaused]++
- case define.ContainerStateCreated, define.ContainerStateConfigured:
- statuses[define.PodStateCreated]++
- default:
- statuses[define.PodStateErrored]++
- }
- }
-
- switch {
- case statuses[define.PodStateRunning] > 0:
- return define.PodStateRunning, nil
- case statuses[define.PodStatePaused] == ctrNum:
- return define.PodStatePaused, nil
- case statuses[define.PodStateStopped] == ctrNum:
- return define.PodStateExited, nil
- case statuses[define.PodStateStopped] > 0:
- return define.PodStateStopped, nil
- case statuses[define.PodStateErrored] > 0:
- return define.PodStateErrored, nil
- default:
- return define.PodStateCreated, 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
-}
-
-// 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
-}
-
-// GetPodsWithFilters uses the cliconfig to categorize if the latest pod is required.
-func GetPodsWithFilters(r *libpod.Runtime, filters string) ([]*libpod.Pod, error) {
- filterFuncs, err := GenerateFilterFunction(r, strings.Split(filters, ","))
- if err != nil {
- return nil, err
- }
- return FilterAllPodsWithFilterFunc(r, filterFuncs...)
-}
-
-// FilterAllPodsWithFilterFunc retrieves all pods
-// Filters can be provided which will determine which pods are included in the
-// output. Multiple filters are handled by ANDing their output, so only pods
-// matching all filters are returned
-func FilterAllPodsWithFilterFunc(r *libpod.Runtime, filters ...libpod.PodFilter) ([]*libpod.Pod, error) {
- pods, err := r.Pods(filters...)
- if err != nil {
- return nil, err
- }
- return pods, nil
-}
-
-// GenerateFilterFunction basically gets the filters based on the input by the user
-// and filter the pod list based on the criteria.
-func GenerateFilterFunction(r *libpod.Runtime, filters []string) ([]libpod.PodFilter, error) {
- var filterFuncs []libpod.PodFilter
- 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 := generatePodFilterFuncs(filterSplit[0], filterSplit[1])
- if err != nil {
- return nil, errors.Wrapf(err, "invalid filter")
- }
- filterFuncs = append(filterFuncs, generatedFunc)
- }
-
- return filterFuncs, nil
-}
-func generatePodFilterFuncs(filter, filterValue string) (
- func(pod *libpod.Pod) bool, error) {
- switch filter {
- case "ctr-ids":
- return func(p *libpod.Pod) bool {
- ctrIds, err := p.AllContainersByID()
- if err != nil {
- return false
- }
- return util.StringInSlice(filterValue, ctrIds)
- }, nil
- case "ctr-names":
- return func(p *libpod.Pod) bool {
- ctrs, err := p.AllContainers()
- if err != nil {
- return false
- }
- for _, ctr := range ctrs {
- if filterValue == ctr.Name() {
- return true
- }
- }
- return false
- }, nil
- case "ctr-number":
- return func(p *libpod.Pod) bool {
- ctrIds, err := p.AllContainersByID()
- if err != nil {
- return false
- }
-
- fVint, err2 := strconv.Atoi(filterValue)
- if err2 != nil {
- return false
- }
- return len(ctrIds) == fVint
- }, nil
- case "ctr-status":
- if !util.StringInSlice(filterValue,
- []string{"created", "restarting", "running", "paused",
- "exited", "unknown"}) {
- return nil, errors.Errorf("%s is not a valid status", filterValue)
- }
- return func(p *libpod.Pod) bool {
- ctr_statuses, err := p.Status()
- if err != nil {
- return false
- }
- for _, ctr_status := range ctr_statuses {
- state := ctr_status.String()
- if ctr_status == define.ContainerStateConfigured {
- state = "created"
- }
- if state == filterValue {
- return true
- }
- }
- return false
- }, nil
- case "id":
- return func(p *libpod.Pod) bool {
- return strings.Contains(p.ID(), filterValue)
- }, nil
- case "name":
- return func(p *libpod.Pod) bool {
- return strings.Contains(p.Name(), filterValue)
- }, nil
- case "status":
- if !util.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created"}) {
- return nil, errors.Errorf("%s is not a valid pod status", filterValue)
- }
- return func(p *libpod.Pod) bool {
- status, err := p.GetPodStatus()
- if err != nil {
- return false
- }
- if strings.ToLower(status) == filterValue {
- return true
- }
- return false
- }, nil
- case "label":
- var filterArray = strings.SplitN(filterValue, "=", 2)
- var filterKey = filterArray[0]
- if len(filterArray) > 1 {
- filterValue = filterArray[1]
- } else {
- filterValue = ""
- }
- return func(p *libpod.Pod) bool {
- for labelKey, labelValue := range p.Labels() {
- if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) {
- return true
- }
- }
- return false
- }, nil
- }
- return nil, errors.Errorf("%s is an invalid filter", filter)
-}
-
-var DefaultKernelNamespaces = "cgroup,ipc,net,uts"
diff --git a/cmd/podman/shared/volumes_shared.go b/cmd/podman/shared/volumes_shared.go
deleted file mode 100644
index 74c0ce011..000000000
--- a/cmd/podman/shared/volumes_shared.go
+++ /dev/null
@@ -1,109 +0,0 @@
-package shared
-
-import (
- "context"
- "strconv"
- "strings"
-
- "github.com/containers/libpod/libpod"
- "github.com/containers/libpod/libpod/define"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-// 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
-}
-
-// Handle volume options from CLI.
-// Parse "o" option to find UID, GID.
-func ParseVolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) {
- libpodOptions := []libpod.VolumeCreateOption{}
- volumeOptions := make(map[string]string)
-
- for key, value := range opts {
- switch key {
- case "o":
- // o has special handling to parse out UID, GID.
- // These are separate Libpod options.
- splitVal := strings.Split(value, ",")
- finalVal := []string{}
- for _, o := range splitVal {
- // Options will be formatted as either "opt" or
- // "opt=value"
- splitO := strings.SplitN(o, "=", 2)
- switch strings.ToLower(splitO[0]) {
- case "uid":
- if len(splitO) != 2 {
- return nil, errors.Wrapf(define.ErrInvalidArg, "uid option must provide a UID")
- }
- intUID, err := strconv.Atoi(splitO[1])
- if err != nil {
- return nil, errors.Wrapf(err, "cannot convert UID %s to integer", splitO[1])
- }
- logrus.Debugf("Removing uid= from options and adding WithVolumeUID for UID %d", intUID)
- libpodOptions = append(libpodOptions, libpod.WithVolumeUID(intUID))
- case "gid":
- if len(splitO) != 2 {
- return nil, errors.Wrapf(define.ErrInvalidArg, "gid option must provide a GID")
- }
- intGID, err := strconv.Atoi(splitO[1])
- if err != nil {
- return nil, errors.Wrapf(err, "cannot convert GID %s to integer", splitO[1])
- }
- logrus.Debugf("Removing gid= from options and adding WithVolumeGID for GID %d", intGID)
- libpodOptions = append(libpodOptions, libpod.WithVolumeGID(intGID))
- default:
- finalVal = append(finalVal, o)
- }
- }
- if len(finalVal) > 0 {
- volumeOptions[key] = strings.Join(finalVal, ",")
- }
- default:
- volumeOptions[key] = value
- }
- }
-
- if len(volumeOptions) > 0 {
- libpodOptions = append(libpodOptions, libpod.WithVolumeOptions(volumeOptions))
- }
-
- return libpodOptions, nil
-}
diff --git a/cmd/podman/shared/workers.go b/cmd/podman/shared/workers.go
deleted file mode 100644
index a9d6bb77e..000000000
--- a/cmd/podman/shared/workers.go
+++ /dev/null
@@ -1,138 +0,0 @@
-package shared
-
-import (
- "reflect"
- "runtime"
- "strings"
- "sync"
-
- "github.com/sirupsen/logrus"
-)
-
-// JobFunc provides the function signature for the pool'ed functions
-type JobFunc func() error
-
-// Job defines the function to run
-type Job struct {
- ID string
- Fn JobFunc
-}
-
-// JobResult defines the results from the function ran
-type JobResult struct {
- Job Job
- Err error
-}
-
-// Pool defines the worker pool and queues
-type Pool struct {
- id string
- wg *sync.WaitGroup
- jobs chan Job
- results chan JobResult
- size int
- capacity int
-}
-
-// NewPool creates and initializes a new Pool
-func NewPool(id string, size int, capacity int) *Pool {
- var wg sync.WaitGroup
-
- // min for int...
- s := size
- if s > capacity {
- s = capacity
- }
-
- return &Pool{
- id,
- &wg,
- make(chan Job, capacity),
- make(chan JobResult, capacity),
- s,
- capacity,
- }
-}
-
-// Add Job to pool for parallel processing
-func (p *Pool) Add(job Job) {
- p.wg.Add(1)
- p.jobs <- job
-}
-
-// Run the Job's in the pool, gather and return results
-func (p *Pool) Run() ([]string, map[string]error, error) {
- var (
- ok = []string{}
- failures = map[string]error{}
- )
-
- for w := 0; w < p.size; w++ {
- w := w
- go p.newWorker(w)
- }
- close(p.jobs)
- p.wg.Wait()
-
- close(p.results)
- for r := range p.results {
- if r.Err == nil {
- ok = append(ok, r.Job.ID)
- } else {
- failures[r.Job.ID] = r.Err
- }
- }
-
- if logrus.GetLevel() == logrus.DebugLevel {
- for i, f := range failures {
- logrus.Debugf("Pool[%s, %s: %s]", p.id, i, f.Error())
- }
- }
-
- return ok, failures, nil
-}
-
-// newWorker creates new parallel workers to monitor jobs channel from Pool
-func (p *Pool) newWorker(slot int) {
- for job := range p.jobs {
- err := job.Fn()
- p.results <- JobResult{job, err}
- if logrus.GetLevel() == logrus.DebugLevel {
- n := strings.Split(runtime.FuncForPC(reflect.ValueOf(job.Fn).Pointer()).Name(), ".")
- logrus.Debugf("Worker#%d finished job %s/%s (%v)", slot, n[2:], job.ID, err)
- }
- p.wg.Done()
- }
-}
-
-// DefaultPoolSize 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 DefaultPoolSize(name string) int {
- numCpus := runtime.NumCPU()
- switch name {
- case "init":
- fallthrough
- case "kill":
- fallthrough
- case "pause":
- fallthrough
- case "rm":
- fallthrough
- case "unpause":
- if numCpus <= 3 {
- return numCpus * 3
- }
- return numCpus * 4
- case "ps":
- return 8
- case "restart":
- return numCpus * 2
- case "stop":
- if numCpus <= 2 {
- return 4
- } else {
- return numCpus * 3
- }
- }
- return 3
-}