188 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
package libpod
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/containers/common/pkg/util"
 | 
						|
	"github.com/containers/podman/v4/libpod/define"
 | 
						|
)
 | 
						|
 | 
						|
// Contains the public Runtime API for pods
 | 
						|
 | 
						|
// A PodCreateOption is a functional option which alters the Pod created by
 | 
						|
// NewPod
 | 
						|
type PodCreateOption func(*Pod) error
 | 
						|
 | 
						|
// PodFilter is a function to determine whether a pod is included in command
 | 
						|
// output. Pods to be outputted are tested using the function. A true return
 | 
						|
// will include the pod, a false return will exclude it.
 | 
						|
type PodFilter func(*Pod) bool
 | 
						|
 | 
						|
// RemovePod removes a pod
 | 
						|
// If removeCtrs is specified, containers will be removed
 | 
						|
// Otherwise, a pod that is not empty will return an error and not be removed
 | 
						|
// If force is specified with removeCtrs, all containers will be stopped before
 | 
						|
// being removed
 | 
						|
// Otherwise, the pod will not be removed if any containers are running
 | 
						|
func (r *Runtime) RemovePod(ctx context.Context, p *Pod, removeCtrs, force bool, timeout *uint) error {
 | 
						|
	if !r.valid {
 | 
						|
		return define.ErrRuntimeStopped
 | 
						|
	}
 | 
						|
 | 
						|
	if !p.valid {
 | 
						|
		if ok, _ := r.state.HasPod(p.ID()); !ok {
 | 
						|
			// Pod probably already removed
 | 
						|
			// Or was never in the runtime to begin with
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	p.lock.Lock()
 | 
						|
	defer p.lock.Unlock()
 | 
						|
 | 
						|
	return r.removePod(ctx, p, removeCtrs, force, timeout)
 | 
						|
}
 | 
						|
 | 
						|
// GetPod retrieves a pod by its ID
 | 
						|
func (r *Runtime) GetPod(id string) (*Pod, error) {
 | 
						|
	if !r.valid {
 | 
						|
		return nil, define.ErrRuntimeStopped
 | 
						|
	}
 | 
						|
 | 
						|
	return r.state.Pod(id)
 | 
						|
}
 | 
						|
 | 
						|
// HasPod checks to see if a pod with the given ID exists
 | 
						|
func (r *Runtime) HasPod(id string) (bool, error) {
 | 
						|
	if !r.valid {
 | 
						|
		return false, define.ErrRuntimeStopped
 | 
						|
	}
 | 
						|
 | 
						|
	return r.state.HasPod(id)
 | 
						|
}
 | 
						|
 | 
						|
// LookupPod retrieves a pod by its name or a partial ID
 | 
						|
// If a partial ID is not unique, an error will be returned
 | 
						|
func (r *Runtime) LookupPod(idOrName string) (*Pod, error) {
 | 
						|
	if !r.valid {
 | 
						|
		return nil, define.ErrRuntimeStopped
 | 
						|
	}
 | 
						|
 | 
						|
	return r.state.LookupPod(idOrName)
 | 
						|
}
 | 
						|
 | 
						|
// Pods 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 (r *Runtime) Pods(filters ...PodFilter) ([]*Pod, error) {
 | 
						|
	pods, err := r.GetAllPods()
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	podsFiltered := make([]*Pod, 0, len(pods))
 | 
						|
	for _, pod := range pods {
 | 
						|
		include := true
 | 
						|
		for _, filter := range filters {
 | 
						|
			include = include && filter(pod)
 | 
						|
		}
 | 
						|
 | 
						|
		if include {
 | 
						|
			podsFiltered = append(podsFiltered, pod)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return podsFiltered, nil
 | 
						|
}
 | 
						|
 | 
						|
// GetAllPods retrieves all pods
 | 
						|
func (r *Runtime) GetAllPods() ([]*Pod, error) {
 | 
						|
	if !r.valid {
 | 
						|
		return nil, define.ErrRuntimeStopped
 | 
						|
	}
 | 
						|
 | 
						|
	return r.state.AllPods()
 | 
						|
}
 | 
						|
 | 
						|
// GetLatestPod returns a pod object of the latest created pod.
 | 
						|
func (r *Runtime) GetLatestPod() (*Pod, error) {
 | 
						|
	lastCreatedIndex := -1
 | 
						|
	var lastCreatedTime time.Time
 | 
						|
	pods, err := r.GetAllPods()
 | 
						|
	if err != nil {
 | 
						|
		return nil, fmt.Errorf("unable to get all pods: %w", err)
 | 
						|
	}
 | 
						|
	if len(pods) == 0 {
 | 
						|
		return nil, define.ErrNoSuchPod
 | 
						|
	}
 | 
						|
	for podIndex, pod := range pods {
 | 
						|
		createdTime := pod.config.CreatedTime
 | 
						|
		if createdTime.After(lastCreatedTime) {
 | 
						|
			lastCreatedTime = createdTime
 | 
						|
			lastCreatedIndex = podIndex
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return pods[lastCreatedIndex], nil
 | 
						|
}
 | 
						|
 | 
						|
// GetRunningPods returns an array of running pods
 | 
						|
func (r *Runtime) GetRunningPods() ([]*Pod, error) {
 | 
						|
	var (
 | 
						|
		pods        []string
 | 
						|
		runningPods []*Pod
 | 
						|
	)
 | 
						|
	if !r.valid {
 | 
						|
		return nil, define.ErrRuntimeStopped
 | 
						|
	}
 | 
						|
	containers, err := r.GetRunningContainers()
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	// Assemble running pods
 | 
						|
	for _, c := range containers {
 | 
						|
		if !util.StringInSlice(c.PodID(), pods) {
 | 
						|
			pods = append(pods, c.PodID())
 | 
						|
			pod, err := r.GetPod(c.PodID())
 | 
						|
			if err != nil {
 | 
						|
				if errors.Is(err, define.ErrPodRemoved) || errors.Is(err, define.ErrNoSuchPod) {
 | 
						|
					continue
 | 
						|
				}
 | 
						|
				return nil, err
 | 
						|
			}
 | 
						|
			runningPods = append(runningPods, pod)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return runningPods, nil
 | 
						|
}
 | 
						|
 | 
						|
// PrunePods removes unused pods and their containers from local storage.
 | 
						|
func (r *Runtime) PrunePods(ctx context.Context) (map[string]error, error) {
 | 
						|
	response := make(map[string]error)
 | 
						|
	states := []string{define.PodStateStopped, define.PodStateExited}
 | 
						|
	filterFunc := func(p *Pod) bool {
 | 
						|
		state, _ := p.GetPodStatus()
 | 
						|
		for _, status := range states {
 | 
						|
			if state == status {
 | 
						|
				return true
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	pods, err := r.Pods(filterFunc)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	if len(pods) < 1 {
 | 
						|
		return response, nil
 | 
						|
	}
 | 
						|
	for _, pod := range pods {
 | 
						|
		var timeout *uint
 | 
						|
		err := r.removePod(context.TODO(), pod, true, false, timeout)
 | 
						|
		response[pod.ID()] = err
 | 
						|
	}
 | 
						|
	return response, nil
 | 
						|
}
 |