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