github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/k8s/container.go (about)

     1  package k8s
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	v1 "k8s.io/api/core/v1"
     8  
     9  	"github.com/tilt-dev/tilt/internal/container"
    10  )
    11  
    12  const ContainerIDPrefix = "docker://"
    13  
    14  // Kubernetes has a bug where the image ref in the container status
    15  // can be wrong (though this does not mean the container is running
    16  // unexpected code)
    17  //
    18  // Repro steps:
    19  // 1) Create an image and give it two different tags (A and B)
    20  // 2) Deploy Pods with both A and B in the pod spec
    21  // 3) The PodStatus will choose A or B for both pods.
    22  //
    23  // More details here:
    24  // https://github.com/kubernetes/kubernetes/issues/51017
    25  //
    26  // For Tilt, it's pretty important that the image tag is correct (for matching
    27  // purposes). To work around this bug, we change the image reference in
    28  // ContainerStatus to match the ContainerSpec.
    29  func FixContainerStatusImages(pod *v1.Pod) {
    30  	refsByContainerName := make(map[string]string)
    31  	for _, c := range pod.Spec.Containers {
    32  		if c.Name != "" {
    33  			refsByContainerName[c.Name] = c.Image
    34  		}
    35  	}
    36  	for i, cs := range pod.Status.ContainerStatuses {
    37  		image, ok := refsByContainerName[cs.Name]
    38  		if !ok {
    39  			continue
    40  		}
    41  
    42  		cs.Image = image
    43  		pod.Status.ContainerStatuses[i] = cs
    44  	}
    45  }
    46  
    47  // FixContainerStatusImagesNoMutation is the same as FixContainerStatusImages but it does not mutate the input.
    48  // It instead makes a deep copy and returns that with the updated status.
    49  // It should be used over FixContainerStatusImages when the source of the pod is shared such as an informer.
    50  func FixContainerStatusImagesNoMutation(pod *v1.Pod) *v1.Pod {
    51  	pod = pod.DeepCopy()
    52  	FixContainerStatusImages(pod)
    53  	return pod
    54  }
    55  
    56  func NormalizeContainerID(id string) (container.ID, error) {
    57  	if id == "" {
    58  		return "", nil
    59  	}
    60  
    61  	components := strings.SplitN(id, "://", 2)
    62  	if len(components) != 2 {
    63  		return "", fmt.Errorf("Malformed container ID: %s", id)
    64  	}
    65  	return container.ID(components[1]), nil
    66  }
    67  
    68  func ContainerSpecOf(pod *v1.Pod, status v1.ContainerStatus) v1.Container {
    69  	for _, spec := range pod.Spec.Containers {
    70  		if spec.Name == status.Name {
    71  			return spec
    72  		}
    73  	}
    74  	return v1.Container{}
    75  }