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 }