func (p *kubeBuildletPool) GetBuildlet(ctx context.Context, typ, rev string, el eventTimeLogger) (*buildlet.Client, error) { conf, ok := dashboard.Builders[typ] if !ok || conf.KubeImage == "" { return nil, fmt.Errorf("kubepool: invalid builder type %q", typ) } if kubeErr != nil { return nil, kubeErr } if kubeClient == nil { panic("expect non-nil kubeClient") } deleteIn := podDeleteTimeout if strings.HasPrefix(rev, "user-") { // Created by gomote (see remote.go), so don't kill it in 45 minutes. // remote.go handles timeouts itself. deleteIn = 0 rev = strings.TrimPrefix(rev, "user-") } // name is the cluster-wide unique name of the kubernetes pod. Max length // is not documented, but it's kept <= 61 bytes, in line with GCE revPrefix := rev if len(revPrefix) > 8 { revPrefix = rev[:8] } podName := "buildlet-" + typ + "-" + revPrefix + "-rn" + randHex(6) var needDelete bool el.logEventTime("creating_kube_pod", podName) log.Printf("Creating Kubernetes pod %q for %s at %s", podName, typ, rev) bc, err := buildlet.StartPod(ctx, kubeClient, podName, typ, buildlet.PodOpts{ ImageRegistry: registryPrefix, Description: fmt.Sprintf("Go Builder for %s at %s", typ, rev), DeleteIn: deleteIn, OnPodCreated: func() { el.logEventTime("pod_created") p.setPodUsed(podName, true) needDelete = true }, OnGotPodInfo: func() { el.logEventTime("got_pod_info", "waiting_for_buildlet...") }, }) if err != nil { el.logEventTime("kube_buildlet_create_failure", fmt.Sprintf("%s: %v", podName, err)) if needDelete { log.Printf("Deleting failed pod %q", podName) kubeClient.DeletePod(ctx, podName) p.setPodUsed(podName, false) } return nil, err } bc.SetDescription("Kube Pod: " + podName) // The build's context will be canceled when the build completes (successfully // or not), or if the buildlet becomes unavailable. In any case, delete the pod // running the buildlet. go func() { <-ctx.Done() log.Printf("Deleting pod %q after build context cancel received ", podName) // Giving DeletePod a new context here as the build ctx has been canceled kubeClient.DeletePod(context.Background(), podName) p.setPodUsed(podName, false) }() return bc, nil }
func (p *kubeBuildletPool) GetBuildlet(ctx context.Context, typ, rev string, el eventTimeLogger) (*buildlet.Client, error) { conf, ok := dashboard.Builders[typ] if !ok || conf.KubeImage == "" { return nil, fmt.Errorf("kubepool: invalid builder type %q", typ) } if kubeErr != nil { return nil, kubeErr } if kubeClient == nil { panic("expect non-nil kubeClient") } deleteIn := podDeleteTimeout if strings.HasPrefix(rev, "user-") { // Created by gomote (see remote.go), so don't kill it in 45 minutes. // remote.go handles timeouts itself. deleteIn = 0 rev = strings.TrimPrefix(rev, "user-") } // name is the cluster-wide unique name of the kubernetes pod. Max length // is not documented, but it's kept <= 61 bytes, in line with GCE revPrefix := rev if len(revPrefix) > 8 { revPrefix = rev[:8] } podName := "buildlet-" + typ + "-" + revPrefix + "-rn" + randHex(6) var needDelete bool el.logEventTime("creating_kube_pod", podName) log.Printf("Creating Kubernetes pod %q for %s at %s", podName, typ, rev) bc, err := buildlet.StartPod(ctx, kubeClient, podName, typ, buildlet.PodOpts{ ImageRegistry: registryPrefix, Description: fmt.Sprintf("Go Builder for %s at %s", typ, rev), DeleteIn: deleteIn, OnPodRequested: func() { el.logEventTime("pod_create_requested", podName) log.Printf("Pod %q starting", podName) }, OnPodCreated: func() { el.logEventTime("pod_created") needDelete = true // redundant with OnPodRequested one, but fine. }, OnGotPodInfo: func() { el.logEventTime("got_pod_info", "waiting_for_buildlet...") }, }) if err != nil { el.logEventTime("kube_buildlet_create_failure", fmt.Sprintf("%s: %v", podName, err)) log.Printf("Failed to create kube pod for %s, %s: %v", typ, rev, err) if needDelete { //TODO(evanbrown): delete pod } //p.setInstanceUsed(instName, false) return nil, err } bc.SetDescription("Kube Pod: " + podName) return bc, nil }