github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/domain/infra/abi/pods.go (about)

     1  package abi
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/hanks177/podman/v4/libpod"
     7  	"github.com/hanks177/podman/v4/libpod/define"
     8  	"github.com/hanks177/podman/v4/pkg/domain/entities"
     9  	dfilters "github.com/hanks177/podman/v4/pkg/domain/filters"
    10  	"github.com/hanks177/podman/v4/pkg/signal"
    11  	"github.com/hanks177/podman/v4/pkg/specgen/generate"
    12  	"github.com/pkg/errors"
    13  	"github.com/sirupsen/logrus"
    14  )
    15  
    16  // getPodsByContext returns a slice of pods. Note that all, latest and pods are
    17  // mutually exclusive arguments.
    18  func getPodsByContext(all, latest bool, pods []string, runtime *libpod.Runtime) ([]*libpod.Pod, error) {
    19  	var outpods []*libpod.Pod
    20  	if all {
    21  		return runtime.GetAllPods()
    22  	}
    23  	if latest {
    24  		p, err := runtime.GetLatestPod()
    25  		if err != nil {
    26  			return nil, err
    27  		}
    28  		outpods = append(outpods, p)
    29  		return outpods, nil
    30  	}
    31  	var err error
    32  	for _, p := range pods {
    33  		pod, e := runtime.LookupPod(p)
    34  		if e != nil {
    35  			// Log all errors here, so callers don't need to.
    36  			logrus.Debugf("Error looking up pod %q: %v", p, e)
    37  			if err == nil {
    38  				err = e
    39  			}
    40  		} else {
    41  			outpods = append(outpods, pod)
    42  		}
    43  	}
    44  	return outpods, err
    45  }
    46  
    47  func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) {
    48  	_, err := ic.Libpod.LookupPod(nameOrID)
    49  	if err != nil && errors.Cause(err) != define.ErrNoSuchPod {
    50  		return nil, err
    51  	}
    52  	return &entities.BoolReport{Value: err == nil}, nil
    53  }
    54  
    55  func (ic *ContainerEngine) PodKill(ctx context.Context, namesOrIds []string, options entities.PodKillOptions) ([]*entities.PodKillReport, error) {
    56  	reports := []*entities.PodKillReport{}
    57  	sig, err := signal.ParseSignalNameOrNumber(options.Signal)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  	pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	for _, p := range pods {
    67  		report := entities.PodKillReport{Id: p.ID()}
    68  		conErrs, err := p.Kill(ctx, uint(sig))
    69  		if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
    70  			report.Errs = []error{err}
    71  			reports = append(reports, &report)
    72  			continue
    73  		}
    74  		if len(conErrs) > 0 {
    75  			for id, err := range conErrs {
    76  				report.Errs = append(report.Errs, errors.Wrapf(err, "error killing container %s", id))
    77  			}
    78  			reports = append(reports, &report)
    79  			continue
    80  		}
    81  		reports = append(reports, &report)
    82  	}
    83  	return reports, nil
    84  }
    85  
    86  func (ic *ContainerEngine) PodLogs(ctx context.Context, nameOrID string, options entities.PodLogsOptions) error {
    87  	// Implementation accepts slice
    88  	podName := []string{nameOrID}
    89  	pod, err := getPodsByContext(false, options.Latest, podName, ic.Libpod)
    90  	if err != nil {
    91  		return err
    92  	}
    93  	// Get pod containers
    94  	podCtrs, err := pod[0].AllContainers()
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	ctrNames := []string{}
   100  	// Check if `kubectl pod logs -c ctrname <podname>` alike command is used
   101  	if options.ContainerName != "" {
   102  		ctrFound := false
   103  		for _, ctr := range podCtrs {
   104  			if ctr.ID() == options.ContainerName || ctr.Name() == options.ContainerName {
   105  				ctrNames = append(ctrNames, options.ContainerName)
   106  				ctrFound = true
   107  			}
   108  		}
   109  		if !ctrFound {
   110  			return errors.Wrapf(define.ErrNoSuchCtr, "container %s is not in pod %s", options.ContainerName, nameOrID)
   111  		}
   112  	} else {
   113  		// No container name specified select all containers
   114  		for _, ctr := range podCtrs {
   115  			ctrNames = append(ctrNames, ctr.Name())
   116  		}
   117  	}
   118  
   119  	// PodLogsOptions are similar but contains few extra fields like ctrName
   120  	// So cast other values as is so we can re-use the code
   121  	containerLogsOpts := entities.PodLogsOptionsToContainerLogsOptions(options)
   122  
   123  	return ic.ContainerLogs(ctx, ctrNames, containerLogsOpts)
   124  }
   125  
   126  func (ic *ContainerEngine) PodPause(ctx context.Context, namesOrIds []string, options entities.PodPauseOptions) ([]*entities.PodPauseReport, error) {
   127  	reports := []*entities.PodPauseReport{}
   128  	pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  	for _, p := range pods {
   133  		report := entities.PodPauseReport{Id: p.ID()}
   134  		errs, err := p.Pause(ctx)
   135  		if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
   136  			report.Errs = []error{err}
   137  			continue
   138  		}
   139  		if len(errs) > 0 {
   140  			for id, v := range errs {
   141  				report.Errs = append(report.Errs, errors.Wrapf(v, "error pausing container %s", id))
   142  			}
   143  			reports = append(reports, &report)
   144  			continue
   145  		}
   146  		reports = append(reports, &report)
   147  	}
   148  	return reports, nil
   149  }
   150  
   151  func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, options entities.PodunpauseOptions) ([]*entities.PodUnpauseReport, error) {
   152  	reports := []*entities.PodUnpauseReport{}
   153  	pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  	for _, p := range pods {
   158  		report := entities.PodUnpauseReport{Id: p.ID()}
   159  		errs, err := p.Unpause(ctx)
   160  		if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
   161  			report.Errs = []error{err}
   162  			continue
   163  		}
   164  		if len(errs) > 0 {
   165  			for id, v := range errs {
   166  				report.Errs = append(report.Errs, errors.Wrapf(v, "error unpausing container %s", id))
   167  			}
   168  			reports = append(reports, &report)
   169  			continue
   170  		}
   171  		reports = append(reports, &report)
   172  	}
   173  	return reports, nil
   174  }
   175  
   176  func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, options entities.PodStopOptions) ([]*entities.PodStopReport, error) {
   177  	reports := []*entities.PodStopReport{}
   178  	pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
   179  	if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchPod) {
   180  		return nil, err
   181  	}
   182  	for _, p := range pods {
   183  		report := entities.PodStopReport{Id: p.ID()}
   184  		errs, err := p.StopWithTimeout(ctx, false, options.Timeout)
   185  		if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
   186  			report.Errs = []error{err}
   187  			continue
   188  		}
   189  		if len(errs) > 0 {
   190  			for id, v := range errs {
   191  				report.Errs = append(report.Errs, errors.Wrapf(v, "error stopping container %s", id))
   192  			}
   193  			reports = append(reports, &report)
   194  			continue
   195  		}
   196  		reports = append(reports, &report)
   197  	}
   198  	return reports, nil
   199  }
   200  
   201  func (ic *ContainerEngine) PodRestart(ctx context.Context, namesOrIds []string, options entities.PodRestartOptions) ([]*entities.PodRestartReport, error) {
   202  	reports := []*entities.PodRestartReport{}
   203  	pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
   204  	if err != nil {
   205  		return nil, err
   206  	}
   207  	for _, p := range pods {
   208  		report := entities.PodRestartReport{Id: p.ID()}
   209  		errs, err := p.Restart(ctx)
   210  		if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
   211  			report.Errs = []error{err}
   212  			reports = append(reports, &report)
   213  			continue
   214  		}
   215  		if len(errs) > 0 {
   216  			for id, v := range errs {
   217  				report.Errs = append(report.Errs, errors.Wrapf(v, "error restarting container %s", id))
   218  			}
   219  			reports = append(reports, &report)
   220  			continue
   221  		}
   222  		reports = append(reports, &report)
   223  	}
   224  	return reports, nil
   225  }
   226  
   227  func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, options entities.PodStartOptions) ([]*entities.PodStartReport, error) {
   228  	reports := []*entities.PodStartReport{}
   229  	pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
   230  	if err != nil {
   231  		return nil, err
   232  	}
   233  
   234  	for _, p := range pods {
   235  		report := entities.PodStartReport{Id: p.ID()}
   236  		errs, err := p.Start(ctx)
   237  		if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
   238  			report.Errs = []error{err}
   239  			reports = append(reports, &report)
   240  			continue
   241  		}
   242  		if len(errs) > 0 {
   243  			for id, v := range errs {
   244  				report.Errs = append(report.Errs, errors.Wrapf(v, "error starting container %s", id))
   245  			}
   246  			reports = append(reports, &report)
   247  			continue
   248  		}
   249  		reports = append(reports, &report)
   250  	}
   251  	return reports, nil
   252  }
   253  
   254  func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, options entities.PodRmOptions) ([]*entities.PodRmReport, error) {
   255  	pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
   256  	if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchPod) {
   257  		return nil, err
   258  	}
   259  	reports := make([]*entities.PodRmReport, 0, len(pods))
   260  	for _, p := range pods {
   261  		report := entities.PodRmReport{Id: p.ID()}
   262  		err := ic.Libpod.RemovePod(ctx, p, true, options.Force, options.Timeout)
   263  		if err != nil {
   264  			report.Err = err
   265  		}
   266  		reports = append(reports, &report)
   267  	}
   268  	return reports, nil
   269  }
   270  
   271  func (ic *ContainerEngine) PodPrune(ctx context.Context, options entities.PodPruneOptions) ([]*entities.PodPruneReport, error) {
   272  	return ic.prunePodHelper(ctx)
   273  }
   274  
   275  func (ic *ContainerEngine) prunePodHelper(ctx context.Context) ([]*entities.PodPruneReport, error) {
   276  	response, err := ic.Libpod.PrunePods(ctx)
   277  	if err != nil {
   278  		return nil, err
   279  	}
   280  	reports := make([]*entities.PodPruneReport, 0, len(response))
   281  	for k, v := range response {
   282  		reports = append(reports, &entities.PodPruneReport{
   283  			Err: v,
   284  			Id:  k,
   285  		})
   286  	}
   287  	return reports, nil
   288  }
   289  
   290  func (ic *ContainerEngine) PodCreate(ctx context.Context, specg entities.PodSpec) (*entities.PodCreateReport, error) {
   291  	pod, err := generate.MakePod(&specg, ic.Libpod)
   292  	if err != nil {
   293  		return nil, err
   294  	}
   295  	return &entities.PodCreateReport{Id: pod.ID()}, nil
   296  }
   297  
   298  func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOptions) (*entities.StringSliceReport, error) {
   299  	var (
   300  		pod *libpod.Pod
   301  		err error
   302  	)
   303  
   304  	// Look up the pod.
   305  	if options.Latest {
   306  		pod, err = ic.Libpod.GetLatestPod()
   307  	} else {
   308  		pod, err = ic.Libpod.LookupPod(options.NameOrID)
   309  	}
   310  	if err != nil {
   311  		return nil, errors.Wrap(err, "unable to lookup requested container")
   312  	}
   313  
   314  	// Run Top.
   315  	report := &entities.StringSliceReport{}
   316  	report.Value, err = pod.GetPodPidInformation(options.Descriptors)
   317  	return report, err
   318  }
   319  
   320  func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOptions) ([]*entities.ListPodsReport, error) {
   321  	var (
   322  		err error
   323  		pds = []*libpod.Pod{}
   324  	)
   325  
   326  	filters := make([]libpod.PodFilter, 0, len(options.Filters))
   327  	for k, v := range options.Filters {
   328  		f, err := dfilters.GeneratePodFilterFunc(k, v, ic.Libpod)
   329  		if err != nil {
   330  			return nil, err
   331  		}
   332  		filters = append(filters, f)
   333  	}
   334  	if options.Latest {
   335  		pod, err := ic.Libpod.GetLatestPod()
   336  		if err != nil {
   337  			return nil, err
   338  		}
   339  		pds = append(pds, pod)
   340  	} else {
   341  		pds, err = ic.Libpod.Pods(filters...)
   342  		if err != nil {
   343  			return nil, err
   344  		}
   345  	}
   346  
   347  	reports := make([]*entities.ListPodsReport, 0, len(pds))
   348  	for _, p := range pds {
   349  		var lpcs []*entities.ListPodContainer
   350  		status, err := p.GetPodStatus()
   351  		if err != nil {
   352  			return nil, err
   353  		}
   354  		cons, err := p.AllContainers()
   355  		if err != nil {
   356  			return nil, err
   357  		}
   358  		for _, c := range cons {
   359  			state, err := c.State()
   360  			if err != nil {
   361  				return nil, err
   362  			}
   363  			lpcs = append(lpcs, &entities.ListPodContainer{
   364  				Id:     c.ID(),
   365  				Names:  c.Name(),
   366  				Status: state.String(),
   367  			})
   368  		}
   369  		infraID, err := p.InfraContainerID()
   370  		if err != nil {
   371  			return nil, err
   372  		}
   373  		networks := []string{}
   374  		if len(infraID) > 0 {
   375  			infra, err := p.InfraContainer()
   376  			if err != nil {
   377  				return nil, err
   378  			}
   379  			networks, err = infra.Networks()
   380  			if err != nil {
   381  				return nil, err
   382  			}
   383  		}
   384  		reports = append(reports, &entities.ListPodsReport{
   385  			Cgroup:     p.CgroupParent(),
   386  			Containers: lpcs,
   387  			Created:    p.CreatedTime(),
   388  			Id:         p.ID(),
   389  			InfraId:    infraID,
   390  			Name:       p.Name(),
   391  			Namespace:  p.Namespace(),
   392  			Networks:   networks,
   393  			Status:     status,
   394  			Labels:     p.Labels(),
   395  		})
   396  	}
   397  	return reports, nil
   398  }
   399  
   400  func (ic *ContainerEngine) PodInspect(ctx context.Context, options entities.PodInspectOptions) (*entities.PodInspectReport, error) {
   401  	var (
   402  		pod *libpod.Pod
   403  		err error
   404  	)
   405  	// Look up the pod.
   406  	if options.Latest {
   407  		pod, err = ic.Libpod.GetLatestPod()
   408  	} else {
   409  		pod, err = ic.Libpod.LookupPod(options.NameOrID)
   410  	}
   411  	if err != nil {
   412  		return nil, errors.Wrap(err, "unable to lookup requested container")
   413  	}
   414  	inspect, err := pod.Inspect()
   415  	if err != nil {
   416  		return nil, err
   417  	}
   418  	return &entities.PodInspectReport{InspectPodData: inspect}, nil
   419  }