k8s.io/kubernetes@v1.29.3/pkg/kubelet/container/runtime.go (about)

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  //go:generate mockgen -source=runtime.go -destination=testing/runtime_mock.go -package=testing Runtime
    18  package container
    19  
    20  import (
    21  	"context"
    22  	"fmt"
    23  	"io"
    24  	"net/url"
    25  	"reflect"
    26  	"strings"
    27  	"time"
    28  
    29  	v1 "k8s.io/api/core/v1"
    30  	"k8s.io/apimachinery/pkg/api/resource"
    31  	"k8s.io/apimachinery/pkg/types"
    32  	"k8s.io/client-go/tools/remotecommand"
    33  	"k8s.io/client-go/util/flowcontrol"
    34  	runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
    35  	"k8s.io/klog/v2"
    36  	"k8s.io/kubernetes/pkg/volume"
    37  )
    38  
    39  // Version interface allow to consume the runtime versions - compare and format to string.
    40  type Version interface {
    41  	// Compare compares two versions of the runtime. On success it returns -1
    42  	// if the version is less than the other, 1 if it is greater than the other,
    43  	// or 0 if they are equal.
    44  	Compare(other string) (int, error)
    45  	// String returns a string that represents the version.
    46  	String() string
    47  }
    48  
    49  // ImageSpec is an internal representation of an image.  Currently, it wraps the
    50  // value of a Container's Image field, but in the future it will include more detailed
    51  // information about the different image types.
    52  type ImageSpec struct {
    53  	// ID of the image.
    54  	Image string
    55  	// Runtime handler used to pull this image
    56  	RuntimeHandler string
    57  	// The annotations for the image.
    58  	// This should be passed to CRI during image pulls and returned when images are listed.
    59  	Annotations []Annotation
    60  }
    61  
    62  // ImageStats contains statistics about all the images currently available.
    63  type ImageStats struct {
    64  	// Total amount of storage consumed by existing images.
    65  	TotalStorageBytes uint64
    66  }
    67  
    68  // Runtime interface defines the interfaces that should be implemented
    69  // by a container runtime.
    70  // Thread safety is required from implementations of this interface.
    71  type Runtime interface {
    72  	// Type returns the type of the container runtime.
    73  	Type() string
    74  
    75  	// Version returns the version information of the container runtime.
    76  	Version(ctx context.Context) (Version, error)
    77  
    78  	// APIVersion returns the cached API version information of the container
    79  	// runtime. Implementation is expected to update this cache periodically.
    80  	// This may be different from the runtime engine's version.
    81  	// TODO(random-liu): We should fold this into Version()
    82  	APIVersion() (Version, error)
    83  	// Status returns the status of the runtime. An error is returned if the Status
    84  	// function itself fails, nil otherwise.
    85  	Status(ctx context.Context) (*RuntimeStatus, error)
    86  	// GetPods returns a list of containers grouped by pods. The boolean parameter
    87  	// specifies whether the runtime returns all containers including those already
    88  	// exited and dead containers (used for garbage collection).
    89  	GetPods(ctx context.Context, all bool) ([]*Pod, error)
    90  	// GarbageCollect removes dead containers using the specified container gc policy
    91  	// If allSourcesReady is not true, it means that kubelet doesn't have the
    92  	// complete list of pods from all available sources (e.g., apiserver, http,
    93  	// file). In this case, garbage collector should refrain itself from aggressive
    94  	// behavior such as removing all containers of unrecognized pods (yet).
    95  	// If evictNonDeletedPods is set to true, containers and sandboxes belonging to pods
    96  	// that are terminated, but not deleted will be evicted.  Otherwise, only deleted pods
    97  	// will be GC'd.
    98  	// TODO: Revisit this method and make it cleaner.
    99  	GarbageCollect(ctx context.Context, gcPolicy GCPolicy, allSourcesReady bool, evictNonDeletedPods bool) error
   100  	// SyncPod syncs the running pod into the desired pod.
   101  	SyncPod(ctx context.Context, pod *v1.Pod, podStatus *PodStatus, pullSecrets []v1.Secret, backOff *flowcontrol.Backoff) PodSyncResult
   102  	// KillPod kills all the containers of a pod. Pod may be nil, running pod must not be.
   103  	// TODO(random-liu): Return PodSyncResult in KillPod.
   104  	// gracePeriodOverride if specified allows the caller to override the pod default grace period.
   105  	// only hard kill paths are allowed to specify a gracePeriodOverride in the kubelet in order to not corrupt user data.
   106  	// it is useful when doing SIGKILL for hard eviction scenarios, or max grace period during soft eviction scenarios.
   107  	KillPod(ctx context.Context, pod *v1.Pod, runningPod Pod, gracePeriodOverride *int64) error
   108  	// GetPodStatus retrieves the status of the pod, including the
   109  	// information of all containers in the pod that are visible in Runtime.
   110  	GetPodStatus(ctx context.Context, uid types.UID, name, namespace string) (*PodStatus, error)
   111  	// TODO(vmarmol): Unify pod and containerID args.
   112  	// GetContainerLogs returns logs of a specific container. By
   113  	// default, it returns a snapshot of the container log. Set 'follow' to true to
   114  	// stream the log. Set 'follow' to false and specify the number of lines (e.g.
   115  	// "100" or "all") to tail the log.
   116  	GetContainerLogs(ctx context.Context, pod *v1.Pod, containerID ContainerID, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) (err error)
   117  	// DeleteContainer deletes a container. If the container is still running, an error is returned.
   118  	DeleteContainer(ctx context.Context, containerID ContainerID) error
   119  	// ImageService provides methods to image-related methods.
   120  	ImageService
   121  	// UpdatePodCIDR sends a new podCIDR to the runtime.
   122  	// This method just proxies a new runtimeConfig with the updated
   123  	// CIDR value down to the runtime shim.
   124  	UpdatePodCIDR(ctx context.Context, podCIDR string) error
   125  	// CheckpointContainer tells the runtime to checkpoint a container
   126  	// and store the resulting archive to the checkpoint directory.
   127  	CheckpointContainer(ctx context.Context, options *runtimeapi.CheckpointContainerRequest) error
   128  	// Generate pod status from the CRI event
   129  	GeneratePodStatus(event *runtimeapi.ContainerEventResponse) (*PodStatus, error)
   130  	// ListMetricDescriptors gets the descriptors for the metrics that will be returned in ListPodSandboxMetrics.
   131  	// This list should be static at startup: either the client and server restart together when
   132  	// adding or removing metrics descriptors, or they should not change.
   133  	// Put differently, if ListPodSandboxMetrics references a name that is not described in the initial
   134  	// ListMetricDescriptors call, then the metric will not be broadcasted.
   135  	ListMetricDescriptors(ctx context.Context) ([]*runtimeapi.MetricDescriptor, error)
   136  	// ListPodSandboxMetrics retrieves the metrics for all pod sandboxes.
   137  	ListPodSandboxMetrics(ctx context.Context) ([]*runtimeapi.PodSandboxMetrics, error)
   138  }
   139  
   140  // StreamingRuntime is the interface implemented by runtimes that handle the serving of the
   141  // streaming calls (exec/attach/port-forward) themselves. In this case, Kubelet should redirect to
   142  // the runtime server.
   143  type StreamingRuntime interface {
   144  	GetExec(ctx context.Context, id ContainerID, cmd []string, stdin, stdout, stderr, tty bool) (*url.URL, error)
   145  	GetAttach(ctx context.Context, id ContainerID, stdin, stdout, stderr, tty bool) (*url.URL, error)
   146  	GetPortForward(ctx context.Context, podName, podNamespace string, podUID types.UID, ports []int32) (*url.URL, error)
   147  }
   148  
   149  // ImageService interfaces allows to work with image service.
   150  type ImageService interface {
   151  	// PullImage pulls an image from the network to local storage using the supplied
   152  	// secrets if necessary. It returns a reference (digest or ID) to the pulled image.
   153  	PullImage(ctx context.Context, image ImageSpec, pullSecrets []v1.Secret, podSandboxConfig *runtimeapi.PodSandboxConfig) (string, error)
   154  	// GetImageRef gets the reference (digest or ID) of the image which has already been in
   155  	// the local storage. It returns ("", nil) if the image isn't in the local storage.
   156  	GetImageRef(ctx context.Context, image ImageSpec) (string, error)
   157  	// ListImages gets all images currently on the machine.
   158  	ListImages(ctx context.Context) ([]Image, error)
   159  	// RemoveImage removes the specified image.
   160  	RemoveImage(ctx context.Context, image ImageSpec) error
   161  	// ImageStats returns Image statistics.
   162  	ImageStats(ctx context.Context) (*ImageStats, error)
   163  	// ImageFsInfo returns a list of file systems for containers/images
   164  	ImageFsInfo(ctx context.Context) (*runtimeapi.ImageFsInfoResponse, error)
   165  }
   166  
   167  // Attacher interface allows to attach a container.
   168  type Attacher interface {
   169  	AttachContainer(ctx context.Context, id ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) (err error)
   170  }
   171  
   172  // CommandRunner interface allows to run command in a container.
   173  type CommandRunner interface {
   174  	// RunInContainer synchronously executes the command in the container, and returns the output.
   175  	// If the command completes with a non-0 exit code, a k8s.io/utils/exec.ExitError will be returned.
   176  	RunInContainer(ctx context.Context, id ContainerID, cmd []string, timeout time.Duration) ([]byte, error)
   177  }
   178  
   179  // Pod is a group of containers.
   180  type Pod struct {
   181  	// The ID of the pod, which can be used to retrieve a particular pod
   182  	// from the pod list returned by GetPods().
   183  	ID types.UID
   184  	// The name and namespace of the pod, which is readable by human.
   185  	Name      string
   186  	Namespace string
   187  	// Creation timestamps of the Pod in nanoseconds.
   188  	CreatedAt uint64
   189  	// List of containers that belongs to this pod. It may contain only
   190  	// running containers, or mixed with dead ones (when GetPods(true)).
   191  	Containers []*Container
   192  	// List of sandboxes associated with this pod. The sandboxes are converted
   193  	// to Container temporarily to avoid substantial changes to other
   194  	// components. This is only populated by kuberuntime.
   195  	// TODO: use the runtimeApi.PodSandbox type directly.
   196  	Sandboxes []*Container
   197  }
   198  
   199  // PodPair contains both runtime#Pod and api#Pod
   200  type PodPair struct {
   201  	// APIPod is the v1.Pod
   202  	APIPod *v1.Pod
   203  	// RunningPod is the pod defined in pkg/kubelet/container/runtime#Pod
   204  	RunningPod *Pod
   205  }
   206  
   207  // ContainerID is a type that identifies a container.
   208  type ContainerID struct {
   209  	// The type of the container runtime. e.g. 'docker'.
   210  	Type string
   211  	// The identification of the container, this is comsumable by
   212  	// the underlying container runtime. (Note that the container
   213  	// runtime interface still takes the whole struct as input).
   214  	ID string
   215  }
   216  
   217  // BuildContainerID returns the ContainerID given type and id.
   218  func BuildContainerID(typ, ID string) ContainerID {
   219  	return ContainerID{Type: typ, ID: ID}
   220  }
   221  
   222  // ParseContainerID is a convenience method for creating a ContainerID from an ID string.
   223  func ParseContainerID(containerID string) ContainerID {
   224  	var id ContainerID
   225  	if err := id.ParseString(containerID); err != nil {
   226  		klog.ErrorS(err, "Parsing containerID failed")
   227  	}
   228  	return id
   229  }
   230  
   231  // ParseString converts given string into ContainerID
   232  func (c *ContainerID) ParseString(data string) error {
   233  	// Trim the quotes and split the type and ID.
   234  	parts := strings.Split(strings.Trim(data, "\""), "://")
   235  	if len(parts) != 2 {
   236  		return fmt.Errorf("invalid container ID: %q", data)
   237  	}
   238  	c.Type, c.ID = parts[0], parts[1]
   239  	return nil
   240  }
   241  
   242  func (c *ContainerID) String() string {
   243  	return fmt.Sprintf("%s://%s", c.Type, c.ID)
   244  }
   245  
   246  // IsEmpty returns whether given ContainerID is empty.
   247  func (c *ContainerID) IsEmpty() bool {
   248  	return *c == ContainerID{}
   249  }
   250  
   251  // MarshalJSON formats a given ContainerID into a byte array.
   252  func (c *ContainerID) MarshalJSON() ([]byte, error) {
   253  	return []byte(fmt.Sprintf("%q", c.String())), nil
   254  }
   255  
   256  // UnmarshalJSON parses ContainerID from a given array of bytes.
   257  func (c *ContainerID) UnmarshalJSON(data []byte) error {
   258  	return c.ParseString(string(data))
   259  }
   260  
   261  // State represents the state of a container
   262  type State string
   263  
   264  const (
   265  	// ContainerStateCreated indicates a container that has been created (e.g. with docker create) but not started.
   266  	ContainerStateCreated State = "created"
   267  	// ContainerStateRunning indicates a currently running container.
   268  	ContainerStateRunning State = "running"
   269  	// ContainerStateExited indicates a container that ran and completed ("stopped" in other contexts, although a created container is technically also "stopped").
   270  	ContainerStateExited State = "exited"
   271  	// ContainerStateUnknown encompasses all the states that we currently don't care about (like restarting, paused, dead).
   272  	ContainerStateUnknown State = "unknown"
   273  )
   274  
   275  // Container provides the runtime information for a container, such as ID, hash,
   276  // state of the container.
   277  type Container struct {
   278  	// The ID of the container, used by the container runtime to identify
   279  	// a container.
   280  	ID ContainerID
   281  	// The name of the container, which should be the same as specified by
   282  	// v1.Container.
   283  	Name string
   284  	// The image name of the container, this also includes the tag of the image,
   285  	// the expected form is "NAME:TAG".
   286  	Image string
   287  	// The id of the image used by the container.
   288  	ImageID string
   289  	// Runtime handler used to pull the image if any.
   290  	ImageRuntimeHandler string
   291  	// Hash of the container, used for comparison. Optional for containers
   292  	// not managed by kubelet.
   293  	Hash uint64
   294  	// Hash of the container over fields with Resources field zero'd out.
   295  	// NOTE: This is needed during alpha and beta so that containers using Resources are
   296  	// not unexpectedly restarted when InPlacePodVerticalScaling feature-gate is toggled.
   297  	//TODO(vinaykul,InPlacePodVerticalScaling): Remove this in GA+1 and make HashWithoutResources to become Hash.
   298  	HashWithoutResources uint64
   299  	// State is the state of the container.
   300  	State State
   301  }
   302  
   303  // PodStatus represents the status of the pod and its containers.
   304  // v1.PodStatus can be derived from examining PodStatus and v1.Pod.
   305  type PodStatus struct {
   306  	// ID of the pod.
   307  	ID types.UID
   308  	// Name of the pod.
   309  	Name string
   310  	// Namespace of the pod.
   311  	Namespace string
   312  	// All IPs assigned to this pod
   313  	IPs []string
   314  	// Status of containers in the pod.
   315  	ContainerStatuses []*Status
   316  	// Status of the pod sandbox.
   317  	// Only for kuberuntime now, other runtime may keep it nil.
   318  	SandboxStatuses []*runtimeapi.PodSandboxStatus
   319  	// Timestamp at which container and pod statuses were recorded
   320  	TimeStamp time.Time
   321  }
   322  
   323  // ContainerResources represents the Resources allocated to the running container.
   324  type ContainerResources struct {
   325  	// CPU capacity reserved for the container
   326  	CPURequest *resource.Quantity
   327  	// CPU limit enforced on the container
   328  	CPULimit *resource.Quantity
   329  	// Memory capaacity reserved for the container
   330  	MemoryRequest *resource.Quantity
   331  	// Memory limit enforced on the container
   332  	MemoryLimit *resource.Quantity
   333  }
   334  
   335  // Status represents the status of a container.
   336  type Status struct {
   337  	// ID of the container.
   338  	ID ContainerID
   339  	// Name of the container.
   340  	Name string
   341  	// Status of the container.
   342  	State State
   343  	// Creation time of the container.
   344  	CreatedAt time.Time
   345  	// Start time of the container.
   346  	StartedAt time.Time
   347  	// Finish time of the container.
   348  	FinishedAt time.Time
   349  	// Exit code of the container.
   350  	ExitCode int
   351  	// Name of the image, this also includes the tag of the image,
   352  	// the expected form is "NAME:TAG".
   353  	Image string
   354  	// ID of the image.
   355  	ImageID string
   356  	// Runtime handler used to pull the image if any.
   357  	ImageRuntimeHandler string
   358  	// Hash of the container, used for comparison.
   359  	Hash uint64
   360  	// Hash of the container over fields with Resources field zero'd out.
   361  	HashWithoutResources uint64
   362  	// Number of times that the container has been restarted.
   363  	RestartCount int
   364  	// A string explains why container is in such a status.
   365  	Reason string
   366  	// Message written by the container before exiting (stored in
   367  	// TerminationMessagePath).
   368  	Message string
   369  	// CPU and memory resources for this container
   370  	Resources *ContainerResources
   371  }
   372  
   373  // FindContainerStatusByName returns container status in the pod status with the given name.
   374  // When there are multiple containers' statuses with the same name, the first match will be returned.
   375  func (podStatus *PodStatus) FindContainerStatusByName(containerName string) *Status {
   376  	for _, containerStatus := range podStatus.ContainerStatuses {
   377  		if containerStatus.Name == containerName {
   378  			return containerStatus
   379  		}
   380  	}
   381  	return nil
   382  }
   383  
   384  // GetRunningContainerStatuses returns container status of all the running containers in a pod
   385  func (podStatus *PodStatus) GetRunningContainerStatuses() []*Status {
   386  	runningContainerStatuses := []*Status{}
   387  	for _, containerStatus := range podStatus.ContainerStatuses {
   388  		if containerStatus.State == ContainerStateRunning {
   389  			runningContainerStatuses = append(runningContainerStatuses, containerStatus)
   390  		}
   391  	}
   392  	return runningContainerStatuses
   393  }
   394  
   395  // Image contains basic information about a container image.
   396  type Image struct {
   397  	// ID of the image.
   398  	ID string
   399  	// Other names by which this image is known.
   400  	RepoTags []string
   401  	// Digests by which this image is known.
   402  	RepoDigests []string
   403  	// The size of the image in bytes.
   404  	Size int64
   405  	// ImageSpec for the image which include annotations.
   406  	Spec ImageSpec
   407  	// Pin for preventing garbage collection
   408  	Pinned bool
   409  }
   410  
   411  // EnvVar represents the environment variable.
   412  type EnvVar struct {
   413  	Name  string
   414  	Value string
   415  }
   416  
   417  // Annotation represents an annotation.
   418  type Annotation struct {
   419  	Name  string
   420  	Value string
   421  }
   422  
   423  // Mount represents a volume mount.
   424  type Mount struct {
   425  	// Name of the volume mount.
   426  	// TODO(yifan): Remove this field, as this is not representing the unique name of the mount,
   427  	// but the volume name only.
   428  	Name string
   429  	// Path of the mount within the container.
   430  	ContainerPath string
   431  	// Path of the mount on the host.
   432  	HostPath string
   433  	// Whether the mount is read-only.
   434  	ReadOnly bool
   435  	// Whether the mount needs SELinux relabeling
   436  	SELinuxRelabel bool
   437  	// Requested propagation mode
   438  	Propagation runtimeapi.MountPropagation
   439  }
   440  
   441  // PortMapping contains information about the port mapping.
   442  type PortMapping struct {
   443  	// Protocol of the port mapping.
   444  	Protocol v1.Protocol
   445  	// The port number within the container.
   446  	ContainerPort int
   447  	// The port number on the host.
   448  	HostPort int
   449  	// The host IP.
   450  	HostIP string
   451  }
   452  
   453  // DeviceInfo contains information about the device.
   454  type DeviceInfo struct {
   455  	// Path on host for mapping
   456  	PathOnHost string
   457  	// Path in Container to map
   458  	PathInContainer string
   459  	// Cgroup permissions
   460  	Permissions string
   461  }
   462  
   463  // CDIDevice contains information about CDI device
   464  type CDIDevice struct {
   465  	// Name is a fully qualified device name
   466  	Name string
   467  }
   468  
   469  // RunContainerOptions specify the options which are necessary for running containers
   470  type RunContainerOptions struct {
   471  	// The environment variables list.
   472  	Envs []EnvVar
   473  	// The mounts for the containers.
   474  	Mounts []Mount
   475  	// The host devices mapped into the containers.
   476  	Devices []DeviceInfo
   477  	// The CDI devices for the container
   478  	CDIDevices []CDIDevice
   479  	// The annotations for the container
   480  	// These annotations are generated by other components (i.e.,
   481  	// not users). Currently, only device plugins populate the annotations.
   482  	Annotations []Annotation
   483  	// If the container has specified the TerminationMessagePath, then
   484  	// this directory will be used to create and mount the log file to
   485  	// container.TerminationMessagePath
   486  	PodContainerDir string
   487  	// The type of container rootfs
   488  	ReadOnly bool
   489  	// hostname for pod containers
   490  	Hostname string
   491  }
   492  
   493  // VolumeInfo contains information about the volume.
   494  type VolumeInfo struct {
   495  	// Mounter is the volume's mounter
   496  	Mounter volume.Mounter
   497  	// BlockVolumeMapper is the Block volume's mapper
   498  	BlockVolumeMapper volume.BlockVolumeMapper
   499  	// SELinuxLabeled indicates whether this volume has had the
   500  	// pod's SELinux label applied to it or not
   501  	SELinuxLabeled bool
   502  	// Whether the volume permission is set to read-only or not
   503  	// This value is passed from volume.spec
   504  	ReadOnly bool
   505  	// Inner volume spec name, which is the PV name if used, otherwise
   506  	// it is the same as the outer volume spec name.
   507  	InnerVolumeSpecName string
   508  }
   509  
   510  // VolumeMap represents the map of volumes.
   511  type VolumeMap map[string]VolumeInfo
   512  
   513  // RuntimeConditionType is the types of required runtime conditions.
   514  type RuntimeConditionType string
   515  
   516  const (
   517  	// RuntimeReady means the runtime is up and ready to accept basic containers.
   518  	RuntimeReady RuntimeConditionType = "RuntimeReady"
   519  	// NetworkReady means the runtime network is up and ready to accept containers which require network.
   520  	NetworkReady RuntimeConditionType = "NetworkReady"
   521  )
   522  
   523  // RuntimeStatus contains the status of the runtime.
   524  type RuntimeStatus struct {
   525  	// Conditions is an array of current observed runtime conditions.
   526  	Conditions []RuntimeCondition
   527  }
   528  
   529  // GetRuntimeCondition gets a specified runtime condition from the runtime status.
   530  func (r *RuntimeStatus) GetRuntimeCondition(t RuntimeConditionType) *RuntimeCondition {
   531  	for i := range r.Conditions {
   532  		c := &r.Conditions[i]
   533  		if c.Type == t {
   534  			return c
   535  		}
   536  	}
   537  	return nil
   538  }
   539  
   540  // String formats the runtime status into human readable string.
   541  func (r *RuntimeStatus) String() string {
   542  	var ss []string
   543  	for _, c := range r.Conditions {
   544  		ss = append(ss, c.String())
   545  	}
   546  	return fmt.Sprintf("Runtime Conditions: %s", strings.Join(ss, ", "))
   547  }
   548  
   549  // RuntimeCondition contains condition information for the runtime.
   550  type RuntimeCondition struct {
   551  	// Type of runtime condition.
   552  	Type RuntimeConditionType
   553  	// Status of the condition, one of true/false.
   554  	Status bool
   555  	// Reason is brief reason for the condition's last transition.
   556  	Reason string
   557  	// Message is human readable message indicating details about last transition.
   558  	Message string
   559  }
   560  
   561  // String formats the runtime condition into human readable string.
   562  func (c *RuntimeCondition) String() string {
   563  	return fmt.Sprintf("%s=%t reason:%s message:%s", c.Type, c.Status, c.Reason, c.Message)
   564  }
   565  
   566  // Pods represents the list of pods
   567  type Pods []*Pod
   568  
   569  // FindPodByID finds and returns a pod in the pod list by UID. It will return an empty pod
   570  // if not found.
   571  func (p Pods) FindPodByID(podUID types.UID) Pod {
   572  	for i := range p {
   573  		if p[i].ID == podUID {
   574  			return *p[i]
   575  		}
   576  	}
   577  	return Pod{}
   578  }
   579  
   580  // FindPodByFullName finds and returns a pod in the pod list by the full name.
   581  // It will return an empty pod if not found.
   582  func (p Pods) FindPodByFullName(podFullName string) Pod {
   583  	for i := range p {
   584  		if BuildPodFullName(p[i].Name, p[i].Namespace) == podFullName {
   585  			return *p[i]
   586  		}
   587  	}
   588  	return Pod{}
   589  }
   590  
   591  // FindPod combines FindPodByID and FindPodByFullName, it finds and returns a pod in the
   592  // pod list either by the full name or the pod ID. It will return an empty pod
   593  // if not found.
   594  func (p Pods) FindPod(podFullName string, podUID types.UID) Pod {
   595  	if len(podFullName) > 0 {
   596  		return p.FindPodByFullName(podFullName)
   597  	}
   598  	return p.FindPodByID(podUID)
   599  }
   600  
   601  // FindContainerByName returns a container in the pod with the given name.
   602  // When there are multiple containers with the same name, the first match will
   603  // be returned.
   604  func (p *Pod) FindContainerByName(containerName string) *Container {
   605  	for _, c := range p.Containers {
   606  		if c.Name == containerName {
   607  			return c
   608  		}
   609  	}
   610  	return nil
   611  }
   612  
   613  // FindContainerByID returns a container in the pod with the given ContainerID.
   614  func (p *Pod) FindContainerByID(id ContainerID) *Container {
   615  	for _, c := range p.Containers {
   616  		if c.ID == id {
   617  			return c
   618  		}
   619  	}
   620  	return nil
   621  }
   622  
   623  // FindSandboxByID returns a sandbox in the pod with the given ContainerID.
   624  func (p *Pod) FindSandboxByID(id ContainerID) *Container {
   625  	for _, c := range p.Sandboxes {
   626  		if c.ID == id {
   627  			return c
   628  		}
   629  	}
   630  	return nil
   631  }
   632  
   633  // ToAPIPod converts Pod to v1.Pod. Note that if a field in v1.Pod has no
   634  // corresponding field in Pod, the field would not be populated.
   635  func (p *Pod) ToAPIPod() *v1.Pod {
   636  	var pod v1.Pod
   637  	pod.UID = p.ID
   638  	pod.Name = p.Name
   639  	pod.Namespace = p.Namespace
   640  
   641  	for _, c := range p.Containers {
   642  		var container v1.Container
   643  		container.Name = c.Name
   644  		container.Image = c.Image
   645  		pod.Spec.Containers = append(pod.Spec.Containers, container)
   646  	}
   647  	return &pod
   648  }
   649  
   650  // IsEmpty returns true if the pod is empty.
   651  func (p *Pod) IsEmpty() bool {
   652  	return reflect.DeepEqual(p, &Pod{})
   653  }
   654  
   655  // GetPodFullName returns a name that uniquely identifies a pod.
   656  func GetPodFullName(pod *v1.Pod) string {
   657  	// Use underscore as the delimiter because it is not allowed in pod name
   658  	// (DNS subdomain format), while allowed in the container name format.
   659  	return pod.Name + "_" + pod.Namespace
   660  }
   661  
   662  // BuildPodFullName builds the pod full name from pod name and namespace.
   663  func BuildPodFullName(name, namespace string) string {
   664  	return name + "_" + namespace
   665  }
   666  
   667  // ParsePodFullName parsed the pod full name.
   668  func ParsePodFullName(podFullName string) (string, string, error) {
   669  	parts := strings.Split(podFullName, "_")
   670  	if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
   671  		return "", "", fmt.Errorf("failed to parse the pod full name %q", podFullName)
   672  	}
   673  	return parts[0], parts[1], nil
   674  }
   675  
   676  // Option is a functional option type for Runtime, useful for
   677  // completely optional settings.
   678  type Option func(Runtime)
   679  
   680  // SortContainerStatusesByCreationTime sorts the container statuses by creation time.
   681  type SortContainerStatusesByCreationTime []*Status
   682  
   683  func (s SortContainerStatusesByCreationTime) Len() int      { return len(s) }
   684  func (s SortContainerStatusesByCreationTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
   685  func (s SortContainerStatusesByCreationTime) Less(i, j int) bool {
   686  	return s[i].CreatedAt.Before(s[j].CreatedAt)
   687  }
   688  
   689  const (
   690  	// MaxPodTerminationMessageLogLength is the maximum bytes any one pod may have written
   691  	// as termination message output across all containers. Containers will be evenly truncated
   692  	// until output is below this limit.
   693  	MaxPodTerminationMessageLogLength = 1024 * 12
   694  	// MaxContainerTerminationMessageLength is the upper bound any one container may write to
   695  	// its termination message path. Contents above this length will be truncated.
   696  	MaxContainerTerminationMessageLength = 1024 * 4
   697  	// MaxContainerTerminationMessageLogLength is the maximum bytes any one container will
   698  	// have written to its termination message when the message is read from the logs.
   699  	MaxContainerTerminationMessageLogLength = 1024 * 2
   700  	// MaxContainerTerminationMessageLogLines is the maximum number of previous lines of
   701  	// log output that the termination message can contain.
   702  	MaxContainerTerminationMessageLogLines = 80
   703  )