github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/pkg/domain/infra/abi/pods.go (about)

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