github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/store/liveupdates/containers.go (about) 1 package liveupdates 2 3 import ( 4 "fmt" 5 6 v1 "k8s.io/api/core/v1" 7 8 "github.com/tilt-dev/tilt/internal/container" 9 "github.com/tilt-dev/tilt/internal/controllers/apis/liveupdate" 10 "github.com/tilt-dev/tilt/internal/k8s" 11 "github.com/tilt-dev/tilt/internal/store/k8sconv" 12 "github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1" 13 ) 14 15 // If all containers running the given image are ready, returns info for them. 16 // (If this image is running on multiple pods, return an error.) 17 func RunningContainersForOnePod( 18 selector *v1alpha1.LiveUpdateKubernetesSelector, 19 resource *k8sconv.KubernetesResource, 20 imageMap *v1alpha1.ImageMap, 21 ) ([]Container, error) { 22 if selector == nil || resource == nil { 23 return nil, nil 24 } 25 26 activePods := []v1alpha1.Pod{} 27 for _, p := range resource.FilteredPods { 28 // Ignore completed pods. 29 if p.Phase == string(v1.PodSucceeded) || p.Phase == string(v1.PodFailed) { 30 continue 31 } 32 activePods = append(activePods, p) 33 } 34 35 if len(activePods) == 0 { 36 return nil, nil 37 } 38 if len(activePods) > 1 { 39 return nil, fmt.Errorf("can only get container info for a single pod; image target %s has %d pods", selector.Image, len(resource.FilteredPods)) 40 } 41 42 pod := activePods[0] 43 var containers []Container 44 for _, c := range pod.Containers { 45 if !liveupdate.KubernetesSelectorMatchesContainer(c, selector, imageMap) { 46 continue 47 } 48 if c.ID == "" || c.Name == "" || c.State.Running == nil { 49 // If we're missing any relevant info for this container, OR if the 50 // container isn't running, we can't update it in place. 51 // (Since we'll need to fully rebuild this image, we shouldn't bother 52 // in-place updating ANY containers on this pod -- they'll all 53 // be recreated when we image build. So don't return ANY Containers.) 54 return nil, nil 55 } 56 containers = append(containers, Container{ 57 PodID: k8s.PodID(pod.Name), 58 ContainerID: container.ID(c.ID), 59 ContainerName: container.Name(c.Name), 60 Namespace: k8s.Namespace(pod.Namespace), 61 }) 62 } 63 64 return containers, nil 65 } 66 67 func RunningContainersForDC(dcs *v1alpha1.DockerComposeService) []Container { 68 if dcs == nil || dcs.Status.ContainerID == "" { 69 return nil 70 } 71 return []Container{ 72 Container{ContainerID: container.ID(dcs.Status.ContainerID)}, 73 } 74 } 75 76 // Information describing a single running & ready container 77 type Container struct { 78 PodID k8s.PodID 79 ContainerID container.ID 80 ContainerName container.Name 81 Namespace k8s.Namespace 82 } 83 84 func (c Container) Empty() bool { 85 return c == Container{} 86 } 87 88 func (c Container) DisplayName() string { 89 if c.PodID == "" { 90 if c.ContainerName == "" { 91 return c.ContainerID.ShortStr() 92 } 93 return c.ContainerName.String() 94 } 95 96 return fmt.Sprintf("%s/%s", c.PodID, c.ContainerName) 97 }