// HandleBuildPodDeletion sets the status of a build to error if the build pod has been deleted func (bc *BuildPodDeleteController) HandleBuildPodDeletion(pod *kapi.Pod) error { glog.V(4).Infof("Handling deletion of build pod %s/%s", pod.Namespace, pod.Name) obj, exists, err := bc.BuildStore.Get(buildKey(pod)) if err != nil { glog.V(4).Infof("Error getting build for pod %s/%s", pod.Namespace, pod.Name) return err } if !exists || obj == nil { glog.V(5).Infof("No Build found for deleted pod %s/%s", pod.Namespace, pod.Name) return nil } build := obj.(*buildapi.Build) if buildutil.IsBuildComplete(build) { glog.V(4).Infof("Pod was deleted but Build %s/%s is already completed, so no need to update it.", build.Namespace, build.Name) return nil } nextStatus := buildapi.BuildStatusError if build.Status != nextStatus { glog.V(4).Infof("Updating build %s/%s status %s -> %s", build.Namespace, build.Name, build.Status, nextStatus) build.Status = nextStatus build.Message = "The Pod for this Build was deleted before the Build completed." now := util.Now() build.CompletionTimestamp = &now if err := bc.BuildUpdater.Update(build.Namespace, build); err != nil { return fmt.Errorf("Failed to update Build %s/%s: %v", build.Namespace, build.Name, err) } } return nil }
// HandlePod updates the state of the build based on the pod state func (bc *BuildPodController) HandlePod(pod *kapi.Pod) error { obj, exists, err := bc.BuildStore.Get(buildKey(pod)) if err != nil { glog.V(4).Infof("Error getting Build for pod %s/%s: %v", pod.Namespace, pod.Name, err) return err } if !exists || obj == nil { glog.V(5).Infof("No Build found for pod %s/%s", pod.Namespace, pod.Name) return nil } build := obj.(*buildapi.Build) // A cancelling event was triggered for the build, delete its pod and update build status. if build.Cancelled { glog.V(4).Infof("Cancelling Build %s/%s.", build.Namespace, build.Name) if err := bc.CancelBuild(build, pod); err != nil { return fmt.Errorf("failed to cancel Build %s/%s: %v, will retry", build.Namespace, build.Name, err) } return nil } nextStatus := build.Status switch pod.Status.Phase { case kapi.PodRunning: // The pod's still running nextStatus = buildapi.BuildStatusRunning case kapi.PodSucceeded, kapi.PodFailed: // Check the exit codes of all the containers in the pod nextStatus = buildapi.BuildStatusComplete for _, info := range pod.Status.ContainerStatuses { if info.State.Termination != nil && info.State.Termination.ExitCode != 0 { nextStatus = buildapi.BuildStatusFailed break } } } if build.Status != nextStatus { glog.V(4).Infof("Updating Build %s/%s status %s -> %s", build.Namespace, build.Name, build.Status, nextStatus) build.Status = nextStatus if buildutil.IsBuildComplete(build) { now := util.Now() build.CompletionTimestamp = &now } if build.Status == buildapi.BuildStatusRunning { now := util.Now() build.StartTimestamp = &now } if err := bc.BuildUpdater.Update(build.Namespace, build); err != nil { return fmt.Errorf("failed to update Build %s/%s: %v", build.Namespace, build.Name, err) } glog.V(4).Infof("Build %s/%s status was updated %s -> %s", build.Namespace, build.Name, build.Status, nextStatus) } return nil }
// List lists all Pods associated with a Build. func (lw *buildPodDeleteLW) List() (runtime.Object, error) { glog.V(5).Info("Checking for deleted build pods") buildList, err := lw.Client.Builds(kapi.NamespaceAll).List(labels.Everything(), fields.Everything()) if err != nil { glog.V(4).Infof("Failed to find any builds due to error %v", err) return nil, err } for _, build := range buildList.Items { glog.V(5).Infof("Found build %s/%s", build.Namespace, build.Name) if buildutil.IsBuildComplete(&build) { glog.V(5).Infof("Ignoring build %s/%s because it is complete", build.Namespace, build.Name) continue } pod, err := lw.KubeClient.Pods(build.Namespace).Get(buildutil.GetBuildPodName(&build)) if err != nil && !kerrors.IsNotFound(err) { glog.V(4).Infof("Error getting pod for build %s/%s: %v", build.Namespace, build.Name, err) return nil, err } if (err != nil && kerrors.IsNotFound(err)) || pod.Labels[buildapi.BuildLabel] != build.Name { pod = nil } if pod == nil { deletedPod := &kapi.Pod{ ObjectMeta: kapi.ObjectMeta{ Name: buildutil.GetBuildPodName(&build), Namespace: build.Namespace, }, } glog.V(4).Infof("No build pod found for build %s/%s, sending delete event for build pod", build.Namespace, build.Name) err := lw.store.Delete(deletedPod) if err != nil { glog.V(4).Infof("Error queuing delete event: %v", err) } } else { glog.V(5).Infof("Found build pod %s/%s for build %s", pod.Namespace, pod.Name, build.Name) } } return &kapi.PodList{}, nil }