...

Source file src/k8s.io/kubernetes/pkg/kubelet/container/runtime.go

Documentation: k8s.io/kubernetes/pkg/kubelet/container

     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  	// GetImageSize returns the size of the image
   166  	GetImageSize(ctx context.Context, image ImageSpec) (uint64, error)
   167  }
   168  
   169  // Attacher interface allows to attach a container.
   170  type Attacher interface {
   171  	AttachContainer(ctx context.Context, id ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) (err error)
   172  }
   173  
   174  // CommandRunner interface allows to run command in a container.
   175  type CommandRunner interface {
   176  	// RunInContainer synchronously executes the command in the container, and returns the output.
   177  	// If the command completes with a non-0 exit code, a k8s.io/utils/exec.ExitError will be returned.
   178  	RunInContainer(ctx context.Context, id ContainerID, cmd []string, timeout time.Duration) ([]byte, error)
   179  }
   180  
   181  // Pod is a group of containers.
   182  type Pod struct {
   183  	// The ID of the pod, which can be used to retrieve a particular pod
   184  	// from the pod list returned by GetPods().
   185  	ID types.UID
   186  	// The name and namespace of the pod, which is readable by human.
   187  	Name      string
   188  	Namespace string
   189  	// Creation timestamps of the Pod in nanoseconds.
   190  	CreatedAt uint64
   191  	// List of containers that belongs to this pod. It may contain only
   192  	// running containers, or mixed with dead ones (when GetPods(true)).
   193  	Containers []*Container
   194  	// List of sandboxes associated with this pod. The sandboxes are converted
   195  	// to Container temporarily to avoid substantial changes to other
   196  	// components. This is only populated by kuberuntime.
   197  	// TODO: use the runtimeApi.PodSandbox type directly.
   198  	Sandboxes []*Container
   199  }
   200  
   201  // PodPair contains both runtime#Pod and api#Pod
   202  type PodPair struct {
   203  	// APIPod is the v1.Pod
   204  	APIPod *v1.Pod
   205  	// RunningPod is the pod defined in pkg/kubelet/container/runtime#Pod
   206  	RunningPod *Pod
   207  }
   208  
   209  // ContainerID is a type that identifies a container.
   210  type ContainerID struct {
   211  	// The type of the container runtime. e.g. 'docker'.
   212  	Type string
   213  	// The identification of the container, this is comsumable by
   214  	// the underlying container runtime. (Note that the container
   215  	// runtime interface still takes the whole struct as input).
   216  	ID string
   217  }
   218  
   219  // BuildContainerID returns the ContainerID given type and id.
   220  func BuildContainerID(typ, ID string) ContainerID {
   221  	return ContainerID{Type: typ, ID: ID}
   222  }
   223  
   224  // ParseContainerID is a convenience method for creating a ContainerID from an ID string.
   225  func ParseContainerID(containerID string) ContainerID {
   226  	var id ContainerID
   227  	if err := id.ParseString(containerID); err != nil {
   228  		klog.ErrorS(err, "Parsing containerID failed")
   229  	}
   230  	return id
   231  }
   232  
   233  // ParseString converts given string into ContainerID
   234  func (c *ContainerID) ParseString(data string) error {
   235  	// Trim the quotes and split the type and ID.
   236  	parts := strings.Split(strings.Trim(data, "\""), "://")
   237  	if len(parts) != 2 {
   238  		return fmt.Errorf("invalid container ID: %q", data)
   239  	}
   240  	c.Type, c.ID = parts[0], parts[1]
   241  	return nil
   242  }
   243  
   244  func (c *ContainerID) String() string {
   245  	return fmt.Sprintf("%s://%s", c.Type, c.ID)
   246  }
   247  
   248  // IsEmpty returns whether given ContainerID is empty.
   249  func (c *ContainerID) IsEmpty() bool {
   250  	return *c == ContainerID{}
   251  }
   252  
   253  // MarshalJSON formats a given ContainerID into a byte array.
   254  func (c *ContainerID) MarshalJSON() ([]byte, error) {
   255  	return []byte(fmt.Sprintf("%q", c.String())), nil
   256  }
   257  
   258  // UnmarshalJSON parses ContainerID from a given array of bytes.
   259  func (c *ContainerID) UnmarshalJSON(data []byte) error {
   260  	return c.ParseString(string(data))
   261  }
   262  
   263  // State represents the state of a container
   264  type State string
   265  
   266  const (
   267  	// ContainerStateCreated indicates a container that has been created (e.g. with docker create) but not started.
   268  	ContainerStateCreated State = "created"
   269  	// ContainerStateRunning indicates a currently running container.
   270  	ContainerStateRunning State = "running"
   271  	// ContainerStateExited indicates a container that ran and completed ("stopped" in other contexts, although a created container is technically also "stopped").
   272  	ContainerStateExited State = "exited"
   273  	// ContainerStateUnknown encompasses all the states that we currently don't care about (like restarting, paused, dead).
   274  	ContainerStateUnknown State = "unknown"
   275  )
   276  
   277  // Container provides the runtime information for a container, such as ID, hash,
   278  // state of the container.
   279  type Container struct {
   280  	// The ID of the container, used by the container runtime to identify
   281  	// a container.
   282  	ID ContainerID
   283  	// The name of the container, which should be the same as specified by
   284  	// v1.Container.
   285  	Name string
   286  	// The image name of the container, this also includes the tag of the image,
   287  	// the expected form is "NAME:TAG".
   288  	Image string
   289  	// The id of the image used by the container.
   290  	ImageID string
   291  	// The digested reference of the image used by the container.
   292  	ImageRef string
   293  	// Runtime handler used to pull the image if any.
   294  	ImageRuntimeHandler string
   295  	// Hash of the container, used for comparison. Optional for containers
   296  	// not managed by kubelet.
   297  	Hash uint64
   298  	// Hash of the container over fields with Resources field zero'd out.
   299  	// NOTE: This is needed during alpha and beta so that containers using Resources are
   300  	// not unexpectedly restarted when InPlacePodVerticalScaling feature-gate is toggled.
   301  	//TODO(vinaykul,InPlacePodVerticalScaling): Remove this in GA+1 and make HashWithoutResources to become Hash.
   302  	HashWithoutResources uint64
   303  	// State is the state of the container.
   304  	State State
   305  }
   306  
   307  // PodStatus represents the status of the pod and its containers.
   308  // v1.PodStatus can be derived from examining PodStatus and v1.Pod.
   309  type PodStatus struct {
   310  	// ID of the pod.
   311  	ID types.UID
   312  	// Name of the pod.
   313  	Name string
   314  	// Namespace of the pod.
   315  	Namespace string
   316  	// All IPs assigned to this pod
   317  	IPs []string
   318  	// Status of containers in the pod.
   319  	ContainerStatuses []*Status
   320  	// Status of the pod sandbox.
   321  	// Only for kuberuntime now, other runtime may keep it nil.
   322  	SandboxStatuses []*runtimeapi.PodSandboxStatus
   323  	// Timestamp at which container and pod statuses were recorded
   324  	TimeStamp time.Time
   325  }
   326  
   327  // ContainerResources represents the Resources allocated to the running container.
   328  type ContainerResources struct {
   329  	// CPU capacity reserved for the container
   330  	CPURequest *resource.Quantity
   331  	// CPU limit enforced on the container
   332  	CPULimit *resource.Quantity
   333  	// Memory capaacity reserved for the container
   334  	MemoryRequest *resource.Quantity
   335  	// Memory limit enforced on the container
   336  	MemoryLimit *resource.Quantity
   337  }
   338  
   339  // Status represents the status of a container.
   340  //
   341  // Status does not contain VolumeMap because CRI API is unaware of volume names.
   342  type Status struct {
   343  	// ID of the container.
   344  	ID ContainerID
   345  	// Name of the container.
   346  	Name string
   347  	// Status of the container.
   348  	State State
   349  	// Creation time of the container.
   350  	CreatedAt time.Time
   351  	// Start time of the container.
   352  	StartedAt time.Time
   353  	// Finish time of the container.
   354  	FinishedAt time.Time
   355  	// Exit code of the container.
   356  	ExitCode int
   357  	// Name of the image, this also includes the tag of the image,
   358  	// the expected form is "NAME:TAG".
   359  	Image string
   360  	// ID of the image.
   361  	ImageID string
   362  	// The digested reference of the image used by the container.
   363  	ImageRef string
   364  	// Runtime handler used to pull the image if any.
   365  	ImageRuntimeHandler string
   366  	// Hash of the container, used for comparison.
   367  	Hash uint64
   368  	// Hash of the container over fields with Resources field zero'd out.
   369  	HashWithoutResources uint64
   370  	// Number of times that the container has been restarted.
   371  	RestartCount int
   372  	// A string explains why container is in such a status.
   373  	Reason string
   374  	// Message written by the container before exiting (stored in
   375  	// TerminationMessagePath).
   376  	Message string
   377  	// CPU and memory resources for this container
   378  	Resources *ContainerResources
   379  }
   380  
   381  // FindContainerStatusByName returns container status in the pod status with the given name.
   382  // When there are multiple containers' statuses with the same name, the first match will be returned.
   383  func (podStatus *PodStatus) FindContainerStatusByName(containerName string) *Status {
   384  	for _, containerStatus := range podStatus.ContainerStatuses {
   385  		if containerStatus.Name == containerName {
   386  			return containerStatus
   387  		}
   388  	}
   389  	return nil
   390  }
   391  
   392  // GetRunningContainerStatuses returns container status of all the running containers in a pod
   393  func (podStatus *PodStatus) GetRunningContainerStatuses() []*Status {
   394  	runningContainerStatuses := []*Status{}
   395  	for _, containerStatus := range podStatus.ContainerStatuses {
   396  		if containerStatus.State == ContainerStateRunning {
   397  			runningContainerStatuses = append(runningContainerStatuses, containerStatus)
   398  		}
   399  	}
   400  	return runningContainerStatuses
   401  }
   402  
   403  // Image contains basic information about a container image.
   404  type Image struct {
   405  	// ID of the image.
   406  	ID string
   407  	// Other names by which this image is known.
   408  	RepoTags []string
   409  	// Digests by which this image is known.
   410  	RepoDigests []string
   411  	// The size of the image in bytes.
   412  	Size int64
   413  	// ImageSpec for the image which include annotations.
   414  	Spec ImageSpec
   415  	// Pin for preventing garbage collection
   416  	Pinned bool
   417  }
   418  
   419  // EnvVar represents the environment variable.
   420  type EnvVar struct {
   421  	Name  string
   422  	Value string
   423  }
   424  
   425  // Annotation represents an annotation.
   426  type Annotation struct {
   427  	Name  string
   428  	Value string
   429  }
   430  
   431  // Mount represents a volume mount.
   432  type Mount struct {
   433  	// Name of the volume mount.
   434  	// TODO(yifan): Remove this field, as this is not representing the unique name of the mount,
   435  	// but the volume name only.
   436  	Name string
   437  	// Path of the mount within the container.
   438  	ContainerPath string
   439  	// Path of the mount on the host.
   440  	HostPath string
   441  	// Whether the mount is read-only.
   442  	ReadOnly bool
   443  	// Whether the mount is recursive read-only.
   444  	// Must not be true if ReadOnly is false.
   445  	RecursiveReadOnly bool
   446  	// Whether the mount needs SELinux relabeling
   447  	SELinuxRelabel bool
   448  	// Requested propagation mode
   449  	Propagation runtimeapi.MountPropagation
   450  }
   451  
   452  // PortMapping contains information about the port mapping.
   453  type PortMapping struct {
   454  	// Protocol of the port mapping.
   455  	Protocol v1.Protocol
   456  	// The port number within the container.
   457  	ContainerPort int
   458  	// The port number on the host.
   459  	HostPort int
   460  	// The host IP.
   461  	HostIP string
   462  }
   463  
   464  // DeviceInfo contains information about the device.
   465  type DeviceInfo struct {
   466  	// Path on host for mapping
   467  	PathOnHost string
   468  	// Path in Container to map
   469  	PathInContainer string
   470  	// Cgroup permissions
   471  	Permissions string
   472  }
   473  
   474  // CDIDevice contains information about CDI device
   475  type CDIDevice struct {
   476  	// Name is a fully qualified device name
   477  	Name string
   478  }
   479  
   480  // RunContainerOptions specify the options which are necessary for running containers
   481  type RunContainerOptions struct {
   482  	// The environment variables list.
   483  	Envs []EnvVar
   484  	// The mounts for the containers.
   485  	Mounts []Mount
   486  	// The host devices mapped into the containers.
   487  	Devices []DeviceInfo
   488  	// The CDI devices for the container
   489  	CDIDevices []CDIDevice
   490  	// The annotations for the container
   491  	// These annotations are generated by other components (i.e.,
   492  	// not users). Currently, only device plugins populate the annotations.
   493  	Annotations []Annotation
   494  	// If the container has specified the TerminationMessagePath, then
   495  	// this directory will be used to create and mount the log file to
   496  	// container.TerminationMessagePath
   497  	PodContainerDir string
   498  	// The type of container rootfs
   499  	ReadOnly bool
   500  	// hostname for pod containers
   501  	Hostname string
   502  }
   503  
   504  // VolumeInfo contains information about the volume.
   505  type VolumeInfo struct {
   506  	// Mounter is the volume's mounter
   507  	Mounter volume.Mounter
   508  	// BlockVolumeMapper is the Block volume's mapper
   509  	BlockVolumeMapper volume.BlockVolumeMapper
   510  	// SELinuxLabeled indicates whether this volume has had the
   511  	// pod's SELinux label applied to it or not
   512  	SELinuxLabeled bool
   513  	// Whether the volume permission is set to read-only or not
   514  	// This value is passed from volume.spec
   515  	ReadOnly bool
   516  	// Inner volume spec name, which is the PV name if used, otherwise
   517  	// it is the same as the outer volume spec name.
   518  	InnerVolumeSpecName string
   519  }
   520  
   521  // VolumeMap represents the map of volumes.
   522  type VolumeMap map[string]VolumeInfo
   523  
   524  // RuntimeConditionType is the types of required runtime conditions.
   525  type RuntimeConditionType string
   526  
   527  const (
   528  	// RuntimeReady means the runtime is up and ready to accept basic containers.
   529  	RuntimeReady RuntimeConditionType = "RuntimeReady"
   530  	// NetworkReady means the runtime network is up and ready to accept containers which require network.
   531  	NetworkReady RuntimeConditionType = "NetworkReady"
   532  )
   533  
   534  // RuntimeStatus contains the status of the runtime.
   535  type RuntimeStatus struct {
   536  	// Conditions is an array of current observed runtime conditions.
   537  	Conditions []RuntimeCondition
   538  	// Handlers is an array of current available handlers
   539  	Handlers []RuntimeHandler
   540  }
   541  
   542  // GetRuntimeCondition gets a specified runtime condition from the runtime status.
   543  func (r *RuntimeStatus) GetRuntimeCondition(t RuntimeConditionType) *RuntimeCondition {
   544  	for i := range r.Conditions {
   545  		c := &r.Conditions[i]
   546  		if c.Type == t {
   547  			return c
   548  		}
   549  	}
   550  	return nil
   551  }
   552  
   553  // String formats the runtime status into human readable string.
   554  func (r *RuntimeStatus) String() string {
   555  	var ss []string
   556  	var sh []string
   557  	for _, c := range r.Conditions {
   558  		ss = append(ss, c.String())
   559  	}
   560  	for _, h := range r.Handlers {
   561  		sh = append(sh, h.String())
   562  	}
   563  	return fmt.Sprintf("Runtime Conditions: %s; Handlers: %s", strings.Join(ss, ", "), strings.Join(sh, ", "))
   564  }
   565  
   566  // RuntimeHandler contains condition information for the runtime handler.
   567  type RuntimeHandler struct {
   568  	// Name is the handler name.
   569  	Name string
   570  	// SupportsRecursiveReadOnlyMounts is true if the handler has support for
   571  	// recursive read-only mounts.
   572  	SupportsRecursiveReadOnlyMounts bool
   573  	// SupportsUserNamespaces is true if the handler has support for
   574  	// user namespaces.
   575  	SupportsUserNamespaces bool
   576  }
   577  
   578  // String formats the runtime handler into human readable string.
   579  func (h *RuntimeHandler) String() string {
   580  	return fmt.Sprintf("Name=%s SupportsRecursiveReadOnlyMounts: %v SupportsUserNamespaces: %v",
   581  		h.Name, h.SupportsRecursiveReadOnlyMounts, h.SupportsUserNamespaces)
   582  }
   583  
   584  // RuntimeCondition contains condition information for the runtime.
   585  type RuntimeCondition struct {
   586  	// Type of runtime condition.
   587  	Type RuntimeConditionType
   588  	// Status of the condition, one of true/false.
   589  	Status bool
   590  	// Reason is brief reason for the condition's last transition.
   591  	Reason string
   592  	// Message is human readable message indicating details about last transition.
   593  	Message string
   594  }
   595  
   596  // String formats the runtime condition into human readable string.
   597  func (c *RuntimeCondition) String() string {
   598  	return fmt.Sprintf("%s=%t reason:%s message:%s", c.Type, c.Status, c.Reason, c.Message)
   599  }
   600  
   601  // Pods represents the list of pods
   602  type Pods []*Pod
   603  
   604  // FindPodByID finds and returns a pod in the pod list by UID. It will return an empty pod
   605  // if not found.
   606  func (p Pods) FindPodByID(podUID types.UID) Pod {
   607  	for i := range p {
   608  		if p[i].ID == podUID {
   609  			return *p[i]
   610  		}
   611  	}
   612  	return Pod{}
   613  }
   614  
   615  // FindPodByFullName finds and returns a pod in the pod list by the full name.
   616  // It will return an empty pod if not found.
   617  func (p Pods) FindPodByFullName(podFullName string) Pod {
   618  	for i := range p {
   619  		if BuildPodFullName(p[i].Name, p[i].Namespace) == podFullName {
   620  			return *p[i]
   621  		}
   622  	}
   623  	return Pod{}
   624  }
   625  
   626  // FindPod combines FindPodByID and FindPodByFullName, it finds and returns a pod in the
   627  // pod list either by the full name or the pod ID. It will return an empty pod
   628  // if not found.
   629  func (p Pods) FindPod(podFullName string, podUID types.UID) Pod {
   630  	if len(podFullName) > 0 {
   631  		return p.FindPodByFullName(podFullName)
   632  	}
   633  	return p.FindPodByID(podUID)
   634  }
   635  
   636  // FindContainerByName returns a container in the pod with the given name.
   637  // When there are multiple containers with the same name, the first match will
   638  // be returned.
   639  func (p *Pod) FindContainerByName(containerName string) *Container {
   640  	for _, c := range p.Containers {
   641  		if c.Name == containerName {
   642  			return c
   643  		}
   644  	}
   645  	return nil
   646  }
   647  
   648  // FindContainerByID returns a container in the pod with the given ContainerID.
   649  func (p *Pod) FindContainerByID(id ContainerID) *Container {
   650  	for _, c := range p.Containers {
   651  		if c.ID == id {
   652  			return c
   653  		}
   654  	}
   655  	return nil
   656  }
   657  
   658  // FindSandboxByID returns a sandbox in the pod with the given ContainerID.
   659  func (p *Pod) FindSandboxByID(id ContainerID) *Container {
   660  	for _, c := range p.Sandboxes {
   661  		if c.ID == id {
   662  			return c
   663  		}
   664  	}
   665  	return nil
   666  }
   667  
   668  // ToAPIPod converts Pod to v1.Pod. Note that if a field in v1.Pod has no
   669  // corresponding field in Pod, the field would not be populated.
   670  func (p *Pod) ToAPIPod() *v1.Pod {
   671  	var pod v1.Pod
   672  	pod.UID = p.ID
   673  	pod.Name = p.Name
   674  	pod.Namespace = p.Namespace
   675  
   676  	for _, c := range p.Containers {
   677  		var container v1.Container
   678  		container.Name = c.Name
   679  		container.Image = c.Image
   680  		pod.Spec.Containers = append(pod.Spec.Containers, container)
   681  	}
   682  	return &pod
   683  }
   684  
   685  // IsEmpty returns true if the pod is empty.
   686  func (p *Pod) IsEmpty() bool {
   687  	return reflect.DeepEqual(p, &Pod{})
   688  }
   689  
   690  // GetPodFullName returns a name that uniquely identifies a pod.
   691  func GetPodFullName(pod *v1.Pod) string {
   692  	// Use underscore as the delimiter because it is not allowed in pod name
   693  	// (DNS subdomain format), while allowed in the container name format.
   694  	return pod.Name + "_" + pod.Namespace
   695  }
   696  
   697  // BuildPodFullName builds the pod full name from pod name and namespace.
   698  func BuildPodFullName(name, namespace string) string {
   699  	return name + "_" + namespace
   700  }
   701  
   702  // ParsePodFullName parsed the pod full name.
   703  func ParsePodFullName(podFullName string) (string, string, error) {
   704  	parts := strings.Split(podFullName, "_")
   705  	if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
   706  		return "", "", fmt.Errorf("failed to parse the pod full name %q", podFullName)
   707  	}
   708  	return parts[0], parts[1], nil
   709  }
   710  
   711  // Option is a functional option type for Runtime, useful for
   712  // completely optional settings.
   713  type Option func(Runtime)
   714  
   715  // SortContainerStatusesByCreationTime sorts the container statuses by creation time.
   716  type SortContainerStatusesByCreationTime []*Status
   717  
   718  func (s SortContainerStatusesByCreationTime) Len() int      { return len(s) }
   719  func (s SortContainerStatusesByCreationTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
   720  func (s SortContainerStatusesByCreationTime) Less(i, j int) bool {
   721  	return s[i].CreatedAt.Before(s[j].CreatedAt)
   722  }
   723  
   724  const (
   725  	// MaxPodTerminationMessageLogLength is the maximum bytes any one pod may have written
   726  	// as termination message output across all containers. Containers will be evenly truncated
   727  	// until output is below this limit.
   728  	MaxPodTerminationMessageLogLength = 1024 * 12
   729  	// MaxContainerTerminationMessageLength is the upper bound any one container may write to
   730  	// its termination message path. Contents above this length will be truncated.
   731  	MaxContainerTerminationMessageLength = 1024 * 4
   732  	// MaxContainerTerminationMessageLogLength is the maximum bytes any one container will
   733  	// have written to its termination message when the message is read from the logs.
   734  	MaxContainerTerminationMessageLogLength = 1024 * 2
   735  	// MaxContainerTerminationMessageLogLines is the maximum number of previous lines of
   736  	// log output that the termination message can contain.
   737  	MaxContainerTerminationMessageLogLines = 80
   738  )
   739  

View as plain text