cmd/gomote: remove the old create-VMs-directly model; always use coordinator
Fixes golang/go#11711
Change-Id: I1c05de286393a610b74595f57487ebd341b6e599
Reviewed-on: https://go-review.googlesource.com/12393
Reviewed-by: Andrew Gerrand <adg@golang.org>
diff --git a/cmd/gomote/auth.go b/cmd/gomote/auth.go
index e7df09b..bc421d9 100644
--- a/cmd/gomote/auth.go
+++ b/cmd/gomote/auth.go
@@ -11,11 +11,6 @@
"path/filepath"
"runtime"
"strings"
-
- "golang.org/x/build/auth"
- "golang.org/x/build/buildlet"
- "golang.org/x/oauth2"
- "google.golang.org/api/compute/v1"
)
func username() string {
@@ -42,41 +37,6 @@
return filepath.Join(homeDir(), ".config", "gomote")
}
-func projTokenSource() oauth2.TokenSource {
- ts, err := auth.ProjectTokenSource(*proj, compute.ComputeScope)
- if err != nil {
- log.Fatalf("Failed to get OAuth2 token source for project %s: %v", *proj, err)
- }
- return ts
-}
-
-func userKeyPair() buildlet.KeyPair {
- keyDir := configDir()
- crtFile := filepath.Join(keyDir, "gomote.crt")
- keyFile := filepath.Join(keyDir, "gomote.key")
- _, crtErr := os.Stat(crtFile)
- _, keyErr := os.Stat(keyFile)
- if crtErr == nil && keyErr == nil {
- return buildlet.KeyPair{
- CertPEM: slurpString(crtFile),
- KeyPEM: slurpString(keyFile),
- }
- }
- check := func(what string, err error) {
- if err != nil {
- log.Printf("%s: %v", what, err)
- }
- }
- check("making key dir", os.MkdirAll(keyDir, 0700))
- kp, err := buildlet.NewKeyPair()
- if err != nil {
- log.Fatalf("Error generating new key pair: %v", err)
- }
- check("writing cert file: ", ioutil.WriteFile(crtFile, []byte(kp.CertPEM), 0600))
- check("writing key file: ", ioutil.WriteFile(keyFile, []byte(kp.KeyPEM), 0600))
- return kp
-}
-
func slurpString(f string) string {
slurp, err := ioutil.ReadFile(f)
if err != nil {
@@ -91,8 +51,8 @@
}
keyDir := configDir()
baseFile := "user-" + *user + ".token"
- if *dev {
- baseFile = "dev-" + baseFile
+ if *staging {
+ baseFile = "staging-" + baseFile
}
tokenFile := filepath.Join(keyDir, baseFile)
slurp, err := ioutil.ReadFile(tokenFile)
diff --git a/cmd/gomote/create.go b/cmd/gomote/create.go
index e30980f..08badf2 100644
--- a/cmd/gomote/create.go
+++ b/cmd/gomote/create.go
@@ -7,13 +7,10 @@
import (
"flag"
"fmt"
- "log"
"os"
"sort"
"strings"
- "time"
- "golang.org/x/build/buildlet"
"golang.org/x/build/dashboard"
)
@@ -37,8 +34,10 @@
}
os.Exit(1)
}
- var timeout time.Duration
- fs.DurationVar(&timeout, "timeout", 60*time.Minute, "how long the VM will live before being deleted.")
+ // TODO(bradfitz): restore this option, and send it to the coordinator:
+ // For now, comment it out so it's not misleading.
+ // var timeout time.Duration
+ // fs.DurationVar(&timeout, "timeout", 60*time.Minute, "how long the VM will live before being deleted.")
fs.Parse(args)
if fs.NArg() != 1 {
@@ -63,36 +62,11 @@
}
}
- if *user == "" {
- instPrefix := fmt.Sprintf("mote-%s-", username())
- instName, err := nextName(instPrefix + builderType)
- if err != nil {
- return err
- }
- client, err := buildlet.StartNewVM(projTokenSource(), instName, builderType, buildlet.VMOpts{
- Zone: *zone,
- ProjectID: *proj,
- TLS: userKeyPair(),
- DeleteIn: timeout,
- Description: fmt.Sprintf("gomote buildlet for %s", username()),
- OnInstanceRequested: func() {
- log.Printf("Sent create request. Waiting for operation.")
- },
- OnInstanceCreated: func() {
- log.Printf("Instance created.")
- },
- })
- if err != nil {
- return fmt.Errorf("failed to create VM: %v", err)
- }
- fmt.Printf("%s\t%s\n", strings.TrimPrefix(instName, instPrefix), client.URL())
- } else {
- cc := coordinatorClient()
- client, err := cc.CreateBuildlet(builderType)
- if err != nil {
- return fmt.Errorf("failed to create buildlet: %v", err)
- }
- fmt.Println(client.RemoteName())
+ cc := coordinatorClient()
+ client, err := cc.CreateBuildlet(builderType)
+ if err != nil {
+ return fmt.Errorf("failed to create buildlet: %v", err)
}
+ fmt.Println(client.RemoteName())
return nil
}
diff --git a/cmd/gomote/destroy.go b/cmd/gomote/destroy.go
index 49f1e63..aed8818 100644
--- a/cmd/gomote/destroy.go
+++ b/cmd/gomote/destroy.go
@@ -27,9 +27,5 @@
if err != nil {
return err
}
- if *user == "" {
- return bc.DestroyVM(projTokenSource(), *proj, *zone, fmt.Sprintf("mote-%s-%s", username(), name))
- } else {
- return bc.Destroy()
- }
+ return bc.Destroy()
}
diff --git a/cmd/gomote/gomote.go b/cmd/gomote/gomote.go
index 2e6c5d7..00d1c7d 100644
--- a/cmd/gomote/gomote.go
+++ b/cmd/gomote/gomote.go
@@ -31,14 +31,9 @@
)
var (
- user = flag.String("user", username(), "gomote server username; if set to the empty string, only GCE VMs can be created, without using the coordinator.")
+ user = flag.String("user", username(), "gomote server username. You must have the token for user-$USER. The error message will say where to put it.")
- proj = flag.String("project", "symbolic-datum-552", "GCE project owning builders")
- zone = flag.String("zone", "us-central1-a", "GCE zone")
-
- // Mostly dev options:
- dev = flag.Bool("dev", false, "if true, the default project becomes the default staging project")
- buildletBucket = flag.String("buildletbucket", "", "Optional alternate GCS bucket for the buildlet binaries.")
+ staging = flag.Bool("staging", false, "if true, use the staging build coordinator and buildlets")
)
type command struct {
@@ -84,7 +79,7 @@
func coordinatorClient() *buildlet.CoordinatorClient {
inst := build.ProdCoordinator
- if *dev {
+ if *staging {
inst = build.StagingCoordinator
}
return &buildlet.CoordinatorClient{
@@ -115,13 +110,9 @@
registerCommands()
flag.Usage = usage
flag.Parse()
- if *dev {
- *proj = "go-dashboard-dev"
+ if *staging {
dashboard.BuildletBucket = "dev-go-builder-data"
}
- if v := *buildletBucket; v != "" {
- dashboard.BuildletBucket = v
- }
args := flag.Args()
if len(args) == 0 {
usage()
diff --git a/cmd/gomote/list.go b/cmd/gomote/list.go
index 06d3159..ab7ffaa 100644
--- a/cmd/gomote/list.go
+++ b/cmd/gomote/list.go
@@ -28,62 +28,51 @@
fs.Usage()
}
- if *user == "" {
- prefix := fmt.Sprintf("mote-%s-", username())
- vms, err := buildlet.ListVMs(projTokenSource(), *proj, *zone)
- if err != nil {
- return fmt.Errorf("failed to list VMs: %v", err)
- }
- for _, vm := range vms {
- if !strings.HasPrefix(vm.Name, prefix) {
- continue
+ cc := coordinatorClient()
+ rbs, err := cc.RemoteBuildlets()
+ if err != nil {
+ log.Fatal(err)
+ }
+ for _, rb := range rbs {
+ fmt.Printf("%s\t%s\texpires in %v\n", rb.Name, rb.Type, rb.Expires.Sub(time.Now()))
+ }
+
+ return nil
+}
+
+func clientAndConf(name string) (bc *buildlet.Client, conf dashboard.BuildConfig, err error) {
+ cc := coordinatorClient()
+
+ rbs, err := cc.RemoteBuildlets()
+ if err != nil {
+ return
+ }
+ var ok bool
+ for _, rb := range rbs {
+ if rb.Name == name {
+ conf, ok = namedConfig(rb.Type)
+ if !ok {
+ err = fmt.Errorf("builder %q exists, but unknown type %q", name, rb.Type)
+ return
}
- fmt.Printf("%s\thttps://%s\n", strings.TrimPrefix(vm.Name, prefix), strings.TrimSuffix(vm.IPPort, ":443"))
- }
- } else {
- cc := coordinatorClient()
- rbs, err := cc.RemoteBuildlets()
- if err != nil {
- log.Fatal(err)
- }
- for _, rb := range rbs {
- fmt.Printf("%s\t%s\texpires in %v\n", rb.Name, rb.Type, rb.Expires.Sub(time.Now()))
+ break
}
}
- return nil
+ if !ok {
+ err = fmt.Errorf("unknown builder %q", name)
+ return
+ }
+
+ bc, err = namedClient(name)
+ return
}
func namedClient(name string) (*buildlet.Client, error) {
if strings.Contains(name, ":") {
return buildlet.NewClient(name, buildlet.NoKeyPair), nil
}
- if *user != "" {
- cc := coordinatorClient()
- return cc.NamedBuildlet(name)
- }
- // TODO(bradfitz): cache the list on disk and avoid the API call?
- vms, err := buildlet.ListVMs(projTokenSource(), *proj, *zone)
- if err != nil {
- return nil, fmt.Errorf("error listing VMs while looking up %q: %v", name, err)
- }
- wantName := fmt.Sprintf("mote-%s-%s", username(), name)
- var matches []buildlet.VM
- for _, vm := range vms {
- if vm.Name == wantName {
- return buildlet.NewClient(vm.IPPort, vm.TLS), nil
- }
- if strings.HasPrefix(vm.Name, wantName) {
- matches = append(matches, vm)
- }
- }
- if len(matches) == 1 {
- vm := matches[0]
- return buildlet.NewClient(vm.IPPort, vm.TLS), nil
- }
- if len(matches) > 1 {
- return nil, fmt.Errorf("prefix %q is ambiguous", wantName)
- }
- return nil, fmt.Errorf("buildlet %q not running", name)
+ cc := coordinatorClient()
+ return cc.NamedBuildlet(name)
}
// namedConfig returns the builder configuration that matches the given mote
@@ -97,29 +86,3 @@
}
return dashboard.Builders[match], match != ""
}
-
-// nextName returns the next available numbered name or the given buildlet base
-// name. For example, if the provided prefix is "linux-amd64" and there's
-// already an instance named "linux-amd64", nextName will return
-// "linux-amd64-1".
-func nextName(prefix string) (string, error) {
- vms, err := buildlet.ListVMs(projTokenSource(), *proj, *zone)
- if err != nil {
- return "", fmt.Errorf("error listing VMs: %v", err)
- }
- matches := map[string]bool{}
- for _, vm := range vms {
- if strings.HasPrefix(vm.Name, prefix) {
- matches[vm.Name] = true
- }
- }
- if len(matches) == 0 || !matches[prefix] {
- return prefix, nil
- }
- for i := 1; ; i++ {
- next := fmt.Sprintf("%v-%v", prefix, i)
- if !matches[next] {
- return next, nil
- }
- }
-}
diff --git a/cmd/gomote/put.go b/cmd/gomote/put.go
index 3fef2dc..fb6f7ac 100644
--- a/cmd/gomote/put.go
+++ b/cmd/gomote/put.go
@@ -99,18 +99,14 @@
fs.Usage()
}
name := fs.Arg(0)
- conf, ok := namedConfig(name)
- if !ok {
- return fmt.Errorf("unknown builder %q", name)
+ bc, conf, err := clientAndConf(name)
+ if err != nil {
+ return err
}
if conf.Go14URL == "" {
fmt.Printf("No Go14URL field defined for %q; ignoring. (may be baked into image)\n", name)
return nil
}
- bc, err := namedClient(name)
- if err != nil {
- return err
- }
return bc.PutTarFromURL(conf.Go14URL, "go1.4")
}
diff --git a/cmd/gomote/run.go b/cmd/gomote/run.go
index 9421b82..a14f0bc 100644
--- a/cmd/gomote/run.go
+++ b/cmd/gomote/run.go
@@ -40,34 +40,8 @@
name, cmd := fs.Arg(0), fs.Arg(1)
var conf dashboard.BuildConfig
- if *user == "" {
- var ok bool
- conf, ok = namedConfig(name)
- if !ok {
- return fmt.Errorf("unknown builder type %q", name)
- }
- } else {
- cc := coordinatorClient()
- rbs, err := cc.RemoteBuildlets()
- if err != nil {
- return err
- }
- var ok bool
- for _, rb := range rbs {
- if rb.Name == name {
- conf, ok = namedConfig(rb.Type)
- if !ok {
- return fmt.Errorf("builder %q exists, but unknown type %q", name, rb.Type)
- }
- break
- }
- }
- if !ok {
- return fmt.Errorf("unknown builder %q", name)
- }
- }
- bc, err := namedClient(name)
+ bc, conf, err := clientAndConf(name)
if err != nil {
return err
}