blob: 18d0d2c97d6450d3504dd47c5478b7a5e957e30e [file] [log] [blame]
Brad Fitzpatrick874c0832015-01-16 12:59:14 -08001// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Brad Fitzpatrick874c0832015-01-16 12:59:14 -08005package main
6
7import (
Brad Fitzpatrickf1b4be02019-03-27 17:09:27 +00008 "encoding/json"
Brad Fitzpatrick874c0832015-01-16 12:59:14 -08009 "flag"
10 "fmt"
Brad Fitzpatrickf1b4be02019-03-27 17:09:27 +000011 "log"
12 "net/http"
Brad Fitzpatrick874c0832015-01-16 12:59:14 -080013 "os"
14 "sort"
Brad Fitzpatrickb35ba9f2015-01-19 20:53:34 -080015 "strings"
Brad Fitzpatrick6191a532019-11-19 18:23:13 +000016 "time"
Brad Fitzpatrick874c0832015-01-16 12:59:14 -080017
Brad Fitzpatricke4d08a52016-09-15 18:22:09 -040018 "golang.org/x/build/buildlet"
Brad Fitzpatrick6191a532019-11-19 18:23:13 +000019 "golang.org/x/build/types"
Brad Fitzpatrick874c0832015-01-16 12:59:14 -080020)
21
Brad Fitzpatrickf1b4be02019-03-27 17:09:27 +000022type builderType struct {
23 Name string
24 IsReverse bool
25 ExpectNum int
26}
27
28func builders() (bt []builderType) {
29 type builderInfo struct {
30 HostType string
Brad Fitzpatrick45156e82015-02-05 13:37:19 -080031 }
Brad Fitzpatrickf1b4be02019-03-27 17:09:27 +000032 type hostInfo struct {
33 IsReverse bool
34 ExpectNum int
35 ContainerImage string
36 VMImage string
37 }
38 // resj is the response JSON from the builders.
39 var resj struct {
40 Builders map[string]builderInfo
41 Hosts map[string]hostInfo
42 }
43 res, err := http.Get("https://farmer.golang.org/builders?mode=json")
44 if err != nil {
45 log.Fatal(err)
46 }
47 defer res.Body.Close()
48 if res.StatusCode != 200 {
49 log.Fatalf("fetching builder types: %s", res.Status)
50 }
51 if err := json.NewDecoder(res.Body).Decode(&resj); err != nil {
52 log.Fatalf("decoding builder types: %v", err)
53 }
54 for b, bi := range resj.Builders {
55 if strings.HasPrefix(b, "misc-compile") {
56 continue
57 }
58 hi, ok := resj.Hosts[bi.HostType]
59 if !ok {
60 continue
61 }
62 if !hi.IsReverse && hi.ContainerImage == "" && hi.VMImage == "" {
63 continue
64 }
65 bt = append(bt, builderType{
66 Name: b,
67 IsReverse: hi.IsReverse,
68 ExpectNum: hi.ExpectNum,
69 })
70 }
71 sort.Slice(bt, func(i, j int) bool {
72 return bt[i].Name < bt[j].Name
73 })
Brad Fitzpatrick45156e82015-02-05 13:37:19 -080074 return
75}
76
Brad Fitzpatrick874c0832015-01-16 12:59:14 -080077func create(args []string) error {
78 fs := flag.NewFlagSet("create", flag.ContinueOnError)
Brad Fitzpatrick45156e82015-02-05 13:37:19 -080079
Brad Fitzpatrick874c0832015-01-16 12:59:14 -080080 fs.Usage = func() {
Andrew Gerrandbf8575d2015-05-08 13:34:07 +100081 fmt.Fprintln(os.Stderr, "create usage: gomote create [create-opts] <type>")
Brad Fitzpatrick874c0832015-01-16 12:59:14 -080082 fs.PrintDefaults()
Andrew Gerrandbf8575d2015-05-08 13:34:07 +100083 fmt.Fprintln(os.Stderr, "\nValid types:")
Brad Fitzpatrickf1b4be02019-03-27 17:09:27 +000084 for _, bt := range builders() {
85 var warn string
86 if bt.IsReverse {
87 if bt.ExpectNum > 0 {
88 warn = fmt.Sprintf(" [limited capacity: %d machines]", bt.ExpectNum)
89 } else {
90 warn = " [limited capacity]"
91 }
92 }
93 fmt.Fprintf(os.Stderr, " * %s%s\n", bt.Name, warn)
Brad Fitzpatrick45156e82015-02-05 13:37:19 -080094 }
Brad Fitzpatrick874c0832015-01-16 12:59:14 -080095 os.Exit(1)
96 }
Brad Fitzpatrick6191a532019-11-19 18:23:13 +000097 var status bool
98 fs.BoolVar(&status, "status", true, "print regular status updates while waiting")
99
Brad Fitzpatrick6a12af62015-07-19 10:26:22 -0700100 // TODO(bradfitz): restore this option, and send it to the coordinator:
101 // For now, comment it out so it's not misleading.
102 // var timeout time.Duration
103 // fs.DurationVar(&timeout, "timeout", 60*time.Minute, "how long the VM will live before being deleted.")
Brad Fitzpatrick874c0832015-01-16 12:59:14 -0800104
105 fs.Parse(args)
106 if fs.NArg() != 1 {
107 fs.Usage()
108 }
109 builderType := fs.Arg(0)
Brad Fitzpatrick874c0832015-01-16 12:59:14 -0800110
Brad Fitzpatrick6191a532019-11-19 18:23:13 +0000111 t := time.Now()
Brad Fitzpatricke4d08a52016-09-15 18:22:09 -0400112 cc, err := buildlet.NewCoordinatorClientFromFlags()
113 if err != nil {
114 return fmt.Errorf("failed to create coordinator client: %v", err)
115 }
Brad Fitzpatrick6191a532019-11-19 18:23:13 +0000116 client, err := cc.CreateBuildletWithStatus(builderType, func(st types.BuildletWaitStatus) {
117 if status {
Brad Fitzpatricka24f9652019-12-04 03:45:10 +0000118 if st.Message != "" {
119 fmt.Fprintf(os.Stderr, "# %s\n", st.Message)
120 return
121 }
Brad Fitzpatrick6191a532019-11-19 18:23:13 +0000122 fmt.Fprintf(os.Stderr, "# still creating %s after %v; %d requests ahead of you\n", builderType, time.Since(t).Round(time.Second), st.Ahead)
123 }
124 })
Brad Fitzpatrick6a12af62015-07-19 10:26:22 -0700125 if err != nil {
126 return fmt.Errorf("failed to create buildlet: %v", err)
Andrew Gerrand51edd242015-03-05 15:56:40 +1100127 }
Brad Fitzpatrick6a12af62015-07-19 10:26:22 -0700128 fmt.Println(client.RemoteName())
Brad Fitzpatrick874c0832015-01-16 12:59:14 -0800129 return nil
130}