in cmd/buildlet/buildlet.go [124:265]
func main() {
builderEnv := os.Getenv("GO_BUILDER_ENV")
if builderEnv == "macstadium_vm" {
configureMacStadium()
}
onGCE := metadata.OnGCE()
switch runtime.GOOS {
case "plan9":
if onGCE {
log.SetOutput(&gcePlan9LogWriter{w: os.Stderr})
}
case "linux":
if onGCE && !inKube {
if w, err := os.OpenFile("/dev/console", os.O_WRONLY, 0); err == nil {
log.SetOutput(w)
}
}
case "windows":
if onGCE {
configureSerialLogOutput()
}
}
log.Printf("buildlet starting.")
flag.Parse()
if builderEnv == "android-amd64-emu" {
startAndroidEmulator()
}
// Optimize emphemeral filesystems. Prefer speed over safety,
// since these VMs only last for the duration of one build.
switch runtime.GOOS {
case "openbsd", "freebsd", "netbsd":
makeBSDFilesystemFast()
}
if setOSRlimit != nil {
err := setOSRlimit()
if err != nil {
log.Fatalf("setOSRLimit: %v", err)
}
log.Printf("set OS rlimits.")
}
isReverse := *reverseType != ""
if *listenAddr == "AUTO" && !isReverse {
v := defaultListenAddr()
log.Printf("Will listen on %s", v)
*listenAddr = v
}
if !onGCE && !isReverse && !onEC2() && !strings.HasPrefix(*listenAddr, "localhost:") {
log.Printf("** WARNING *** This server is unsafe and offers no security. Be careful.")
}
if onGCE {
fixMTU()
}
if *workDir == "" && setWorkdirToTmpfs != nil {
setWorkdirToTmpfs()
}
if *workDir == "" {
switch runtime.GOOS {
case "windows":
// We want a short path on Windows, due to
// Windows issues with maximum path lengths.
*workDir = `C:\workdir`
if err := os.MkdirAll(*workDir, 0755); err != nil {
log.Fatalf("error creating workdir: %v", err)
}
default:
wdName := "workdir"
if *reverseType != "" {
wdName += "-" + *reverseType
}
dir := filepath.Join(os.TempDir(), wdName)
removeAllAndMkdir(dir)
*workDir = dir
}
}
os.Setenv("WORKDIR", *workDir) // mostly for demos
if _, err := os.Lstat(*workDir); err != nil {
log.Fatalf("invalid --workdir %q: %v", *workDir, err)
}
// Set up and clean $TMPDIR and $GOCACHE directories.
if runtime.GOOS != "windows" && runtime.GOOS != "plan9" {
processTmpDirEnv = filepath.Join(*workDir, "tmp")
processGoCacheEnv = filepath.Join(*workDir, "gocache")
removeAllAndMkdir(processTmpDirEnv)
removeAllAndMkdir(processGoCacheEnv)
}
http.HandleFunc("/", handleRoot)
http.HandleFunc("/debug/x", handleX)
var password string
if !isReverse {
password = metadataValue(metaKeyPassword)
}
requireAuth := func(handler func(w http.ResponseWriter, r *http.Request)) http.Handler {
return requirePasswordHandler{http.HandlerFunc(handler), password}
}
http.Handle("/debug/goroutines", requireAuth(handleGoroutines))
http.Handle("/writetgz", requireAuth(handleWriteTGZ))
http.Handle("/write", requireAuth(handleWrite))
http.Handle("/exec", requireAuth(handleExec))
http.Handle("/halt", requireAuth(handleHalt))
http.Handle("/tgz", requireAuth(handleGetTGZ))
http.Handle("/removeall", requireAuth(handleRemoveAll))
http.Handle("/workdir", requireAuth(handleWorkDir))
http.Handle("/status", requireAuth(handleStatus))
http.Handle("/ls", requireAuth(handleLs))
http.Handle("/connect-ssh", requireAuth(handleConnectSSH))
http.HandleFunc("/healthz", handleHealthz)
if !isReverse {
listenForCoordinator()
} else {
go func() {
if err := serveReverseHealth(); err != nil {
log.Printf("Error in serveReverseHealth: %v", err)
}
}()
ln, err := dialCoordinator()
if err != nil {
log.Fatalf("Error dialing coordinator: %v", err)
}
srv := &http.Server{}
err = srv.Serve(ln)
log.Printf("http.Serve on reverse connection complete: %v", err)
log.Printf("buildlet reverse mode exiting.")
if *haltEntireOS {
// The coordinator disconnects before doHalt has time to
// execute. handleHalt has a 1s delay.
time.Sleep(5 * time.Second)
}
os.Exit(0)
}
}