github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/pkg/varlinkapi/util.go (about)

     1  // +build varlink
     2  
     3  package varlinkapi
     4  
     5  import (
     6  	"context"
     7  	"strconv"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/containers/buildah"
    12  	"github.com/containers/podman/v2/libpod"
    13  	"github.com/containers/podman/v2/libpod/define"
    14  	"github.com/containers/podman/v2/pkg/channel"
    15  	iopodman "github.com/containers/podman/v2/pkg/varlink"
    16  	"github.com/containers/storage/pkg/archive"
    17  )
    18  
    19  // getContext returns a non-nil, empty context
    20  func getContext() context.Context {
    21  	return context.TODO()
    22  }
    23  
    24  func makeListContainer(containerID string, batchInfo BatchContainerStruct) iopodman.Container {
    25  	var (
    26  		mounts []iopodman.ContainerMount
    27  		ports  []iopodman.ContainerPortMappings
    28  	)
    29  	ns := GetNamespaces(batchInfo.Pid)
    30  
    31  	for _, mount := range batchInfo.ConConfig.Spec.Mounts {
    32  		m := iopodman.ContainerMount{
    33  			Destination: mount.Destination,
    34  			Type:        mount.Type,
    35  			Source:      mount.Source,
    36  			Options:     mount.Options,
    37  		}
    38  		mounts = append(mounts, m)
    39  	}
    40  
    41  	for _, pm := range batchInfo.ConConfig.PortMappings {
    42  		p := iopodman.ContainerPortMappings{
    43  			Host_port:      strconv.Itoa(int(pm.HostPort)),
    44  			Host_ip:        pm.HostIP,
    45  			Protocol:       pm.Protocol,
    46  			Container_port: strconv.Itoa(int(pm.ContainerPort)),
    47  		}
    48  		ports = append(ports, p)
    49  
    50  	}
    51  
    52  	// If we find this needs to be done for other container endpoints, we should
    53  	// convert this to a separate function or a generic map from struct function.
    54  	namespace := iopodman.ContainerNameSpace{
    55  		User:   ns.User,
    56  		Uts:    ns.UTS,
    57  		Pidns:  ns.PIDNS,
    58  		Pid:    ns.PID,
    59  		Cgroup: ns.Cgroup,
    60  		Net:    ns.NET,
    61  		Mnt:    ns.MNT,
    62  		Ipc:    ns.IPC,
    63  	}
    64  
    65  	lc := iopodman.Container{
    66  		Id:               containerID,
    67  		Image:            batchInfo.ConConfig.RootfsImageName,
    68  		Imageid:          batchInfo.ConConfig.RootfsImageID,
    69  		Command:          batchInfo.ConConfig.Spec.Process.Args,
    70  		Createdat:        batchInfo.ConConfig.CreatedTime.Format(time.RFC3339),
    71  		Runningfor:       time.Since(batchInfo.ConConfig.CreatedTime).String(),
    72  		Status:           batchInfo.ConState.String(),
    73  		Ports:            ports,
    74  		Names:            batchInfo.ConConfig.Name,
    75  		Labels:           batchInfo.ConConfig.Labels,
    76  		Mounts:           mounts,
    77  		Containerrunning: batchInfo.ConState == define.ContainerStateRunning,
    78  		Namespaces:       namespace,
    79  	}
    80  	if batchInfo.Size != nil {
    81  		lc.Rootfssize = batchInfo.Size.RootFsSize
    82  		lc.Rwsize = batchInfo.Size.RwSize
    83  	}
    84  	return lc
    85  }
    86  
    87  func makeListPodContainers(containerID string, batchInfo BatchContainerStruct) iopodman.ListPodContainerInfo {
    88  	lc := iopodman.ListPodContainerInfo{
    89  		Id:     containerID,
    90  		Status: batchInfo.ConState.String(),
    91  		Name:   batchInfo.ConConfig.Name,
    92  	}
    93  	return lc
    94  }
    95  
    96  func makeListPod(pod *libpod.Pod, batchInfo PsOptions) (iopodman.ListPodData, error) {
    97  	var listPodsContainers []iopodman.ListPodContainerInfo
    98  	var errPodData = iopodman.ListPodData{}
    99  	status, err := pod.GetPodStatus()
   100  	if err != nil {
   101  		return errPodData, err
   102  	}
   103  	containers, err := pod.AllContainers()
   104  	if err != nil {
   105  		return errPodData, err
   106  	}
   107  	for _, ctr := range containers {
   108  		batchInfo, err := BatchContainerOp(ctr, batchInfo)
   109  		if err != nil {
   110  			return errPodData, err
   111  		}
   112  
   113  		listPodsContainers = append(listPodsContainers, makeListPodContainers(ctr.ID(), batchInfo))
   114  	}
   115  	listPod := iopodman.ListPodData{
   116  		Createdat:          pod.CreatedTime().Format(time.RFC3339),
   117  		Id:                 pod.ID(),
   118  		Name:               pod.Name(),
   119  		Status:             status,
   120  		Cgroup:             pod.CgroupParent(),
   121  		Numberofcontainers: strconv.Itoa(len(listPodsContainers)),
   122  		Containersinfo:     listPodsContainers,
   123  	}
   124  	return listPod, nil
   125  }
   126  
   127  func handlePodCall(call iopodman.VarlinkCall, pod *libpod.Pod, ctrErrs map[string]error, err error) error {
   128  	if err != nil && ctrErrs == nil {
   129  		return call.ReplyErrorOccurred(err.Error())
   130  	}
   131  	if ctrErrs != nil {
   132  		containerErrs := make([]iopodman.PodContainerErrorData, len(ctrErrs))
   133  		for ctr, reason := range ctrErrs {
   134  			ctrErr := iopodman.PodContainerErrorData{Containerid: ctr, Reason: reason.Error()}
   135  			containerErrs = append(containerErrs, ctrErr)
   136  		}
   137  		return call.ReplyPodContainerError(pod.ID(), containerErrs)
   138  	}
   139  
   140  	return nil
   141  }
   142  
   143  func stringCompressionToArchiveType(s string) archive.Compression {
   144  	switch strings.ToUpper(s) {
   145  	case "BZIP2":
   146  		return archive.Bzip2
   147  	case "GZIP":
   148  		return archive.Gzip
   149  	case "XZ":
   150  		return archive.Xz
   151  	}
   152  	return archive.Uncompressed
   153  }
   154  
   155  func stringPullPolicyToType(s string) buildah.PullPolicy {
   156  	switch strings.ToUpper(s) {
   157  	case "PULLIFMISSING":
   158  		return buildah.PullIfMissing
   159  	case "PULLALWAYS":
   160  		return buildah.PullAlways
   161  	case "PULLNEVER":
   162  		return buildah.PullNever
   163  	}
   164  	return buildah.PullIfMissing
   165  }
   166  
   167  func derefBool(inBool *bool) bool {
   168  	if inBool == nil {
   169  		return false
   170  	}
   171  	return *inBool
   172  }
   173  
   174  func derefString(in *string) string {
   175  	if in == nil {
   176  		return ""
   177  	}
   178  	return *in
   179  }
   180  
   181  func makePsOpts(inOpts iopodman.PsOpts) PsOptions {
   182  	last := 0
   183  	if inOpts.Last != nil {
   184  		lastT := *inOpts.Last
   185  		last = int(lastT)
   186  	}
   187  	return PsOptions{
   188  		All:       inOpts.All,
   189  		Last:      last,
   190  		Latest:    derefBool(inOpts.Latest),
   191  		NoTrunc:   derefBool(inOpts.NoTrunc),
   192  		Pod:       derefBool(inOpts.Pod),
   193  		Size:      derefBool(inOpts.Size),
   194  		Sort:      derefString(inOpts.Sort),
   195  		Namespace: true,
   196  		Sync:      derefBool(inOpts.Sync),
   197  	}
   198  }
   199  
   200  // forwardOutput is a helper method for varlink endpoints that employ both more and without
   201  // more.  it is capable of sending updates as the output writer gets them or append them
   202  // all to a log.  the chan error is the error from the libpod call so we can honor
   203  // and error event in that case.
   204  func forwardOutput(log []string, c chan error, wantsMore bool, output channel.WriteCloser, reply func(br iopodman.MoreResponse) error) ([]string, error) {
   205  	done := false
   206  	for {
   207  		select {
   208  		// We need to check if the libpod func being called has returned an
   209  		// error yet
   210  		case err := <-c:
   211  			if err != nil {
   212  				return nil, err
   213  			}
   214  			done = true
   215  		// if no error is found, we pull what we can from the log writer and
   216  		// append it to log string slice
   217  		case line := <-output.Chan():
   218  			log = append(log, string(line))
   219  			// If the end point is being used in more mode, send what we have
   220  			if wantsMore {
   221  				br := iopodman.MoreResponse{
   222  					Logs: log,
   223  				}
   224  				if err := reply(br); err != nil {
   225  					return nil, err
   226  				}
   227  				// "reset" the log to empty because we are sending what we
   228  				// get as we get it
   229  				log = []string{}
   230  			}
   231  		}
   232  		if done {
   233  			break
   234  		}
   235  	}
   236  	return log, nil
   237  }