cmd/ejobs: check if provided binary is built for linux/amd64 platform

Change-Id: I31ca5c33fdd8a7ca4a13cac8979a31ef60c29b50
Reviewed-on: https://go-review.googlesource.com/c/pkgsite-metrics/+/505735
Reviewed-by: Jonathan Amsterdam <jba@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
diff --git a/cmd/ejobs/main.go b/cmd/ejobs/main.go
index 2e7c7ab..47c3d68 100644
--- a/cmd/ejobs/main.go
+++ b/cmd/ejobs/main.go
@@ -9,6 +9,7 @@
 	"bytes"
 	"context"
 	"crypto/md5"
+	"debug/buildinfo"
 	"encoding/json"
 	"errors"
 	"flag"
@@ -43,7 +44,7 @@
 	{"cancel", "JOBID...",
 		"cancel the jobs", doCancel},
 	{"start", "BINARY [MIN_IMPORTERS]",
-		"start a job", doStart},
+		"start a job for a linux/amd64 binary", doStart},
 }
 
 type command struct {
@@ -67,7 +68,7 @@
 
 	flag.Parse()
 	if err := run(context.Background()); err != nil {
-		fmt.Fprintf(os.Stderr, "%v\n", err)
+		fmt.Fprintf(os.Stderr, "%v\n\n", err)
 		flag.Usage()
 		os.Exit(2)
 	}
@@ -186,6 +187,8 @@
 		return err
 	} else if fi.IsDir() {
 		return fmt.Errorf("%s is a directory, not a file", binaryFile)
+	} else if err := checkIsLinuxAmd64(binaryFile); err != nil {
+		return err
 	}
 
 	// Copy binary to GCS if it's not already there.
@@ -210,6 +213,36 @@
 	return nil
 }
 
+// checkIsLinuxAmd64 checks if binaryFile is a linux/amd64 Go
+// binary. If not, returns an error with appropriate message.
+// Otherwise, returns nil.
+func checkIsLinuxAmd64(binaryFile string) error {
+	bin, err := os.Open(binaryFile)
+	if err != nil {
+		return err
+	}
+	defer bin.Close()
+
+	bi, err := buildinfo.Read(bin)
+	if err != nil {
+		return err
+	}
+
+	var goos, goarch string
+	for _, setting := range bi.Settings {
+		if setting.Key == "GOOS" {
+			goos = setting.Value
+		} else if setting.Key == "GOARCH" {
+			goarch = setting.Value
+		}
+	}
+
+	if goos != "linux" || goarch != "amd64" {
+		return fmt.Errorf("binary not built for linux/amd64: GOOS=%s GOARCH=%s", goos, goarch)
+	}
+	return nil
+}
+
 // uploadAnalysisBinary copies binaryFile to the GCS location used for
 // analysis binaries.
 // As an optimization, it skips the upload if the file is already on GCS