Skip to content

Commit 328c9b8

Browse files
committed
all: split builder config into builder & host configs
Our builders are named of the form "GOOS-GOARCH" or "GOOS-GOARCH-suffix". Over time we've grown many builders. This CL doesn't change that. Builders continue to be named and operate as before. Previously the build configuration file (dashboard/builders.go) made each builder type ("linux-amd64-race", etc) define how to create a host running a buildlet of that type, even though many builders had identical host configs. For example, these builders all share the same host type (a Kubernetes container): linux-amd64 linux-amd64-race linux-386 linux-386-387 And these are the same host type (a GCE VM): windows-amd64-gce windows-amd64-race windows-386-gce This CL creates a new concept of a "hostType" which defines how the buildlet is created (Kube, GCE, Reverse, and how), and then each builder itself references a host type. Users never see the hostType. (except perhaps in gomote list output) But they at least never need to care about them. Reverse buildlets now can only be one hostType at a time, which simplifies things. We were no longer using multiple roles per machine once moving to VMs for OS X. gomote continues to operate as it did previously but its underlying protocol changed and clients will need to be updated. As a new feature, gomote now has a new flag to let you reuse a buildlet host connection for different builder rules if they share the same underlying host type. But users can ignore that. This CL is a long-standing TODO (previously attempted and aborted) and will make many things easier and faster, including the linux-arm cross-compilation effort, and keeping pre-warmed buildlets of VM types ready to go. Updates golang/go#17104 Change-Id: Iad8387f48680424a8441e878a2f4762bf79ea4d2 Reviewed-on: https://go-review.googlesource.com/29551 Reviewed-by: Matthew Dempsky <[email protected]>
1 parent 6d82497 commit 328c9b8

File tree

15 files changed

+721
-564
lines changed

15 files changed

+721
-564
lines changed

buildlet/gce.go

+15-12
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,15 @@ type VMOpts struct {
7474

7575
// StartNewVM boots a new VM on GCE and returns a buildlet client
7676
// configured to speak to it.
77-
func StartNewVM(ts oauth2.TokenSource, instName, builderType string, opts VMOpts) (*Client, error) {
77+
func StartNewVM(ts oauth2.TokenSource, instName, hostType string, opts VMOpts) (*Client, error) {
7878
computeService, _ := compute.New(oauth2.NewClient(oauth2.NoContext, ts))
7979

80-
conf, ok := dashboard.Builders[builderType]
80+
hconf, ok := dashboard.Hosts[hostType]
8181
if !ok {
82-
return nil, fmt.Errorf("invalid builder type %q", builderType)
82+
return nil, fmt.Errorf("invalid host type %q", hostType)
83+
}
84+
if !hconf.IsGCE() {
85+
return nil, fmt.Errorf("host type %q is not a GCE host type", hostType)
8386
}
8487

8588
zone := opts.Zone
@@ -96,9 +99,9 @@ func StartNewVM(ts oauth2.TokenSource, instName, builderType string, opts VMOpts
9699
usePreempt := false
97100
Try:
98101
prefix := "https://www.googleapis.com/compute/v1/projects/" + projectID
99-
machType := prefix + "/zones/" + zone + "/machineTypes/" + conf.MachineType()
102+
machType := prefix + "/zones/" + zone + "/machineTypes/" + hconf.MachineType()
100103
diskType := "https://www.googleapis.com/compute/v1/projects/" + projectID + "/zones/" + zone + "/diskTypes/pd-ssd"
101-
if conf.RegularDisk {
104+
if hconf.RegularDisk {
102105
diskType = "" // a spinning disk
103106
}
104107

@@ -126,7 +129,7 @@ Try:
126129
Type: "PERSISTENT",
127130
InitializeParams: &compute.AttachedDiskInitializeParams{
128131
DiskName: instName,
129-
SourceImage: "https://www.googleapis.com/compute/v1/projects/" + projectID + "/global/images/" + conf.VMImage,
132+
SourceImage: "https://www.googleapis.com/compute/v1/projects/" + projectID + "/global/images/" + hconf.VMImage,
130133
DiskType: diskType,
131134
},
132135
},
@@ -159,8 +162,8 @@ Try:
159162
// which the VMs are configured to download at boot and run.
160163
// This lets us/ update the buildlet more easily than
161164
// rebuilding the whole VM image.
162-
addMeta("buildlet-binary-url", conf.BuildletBinaryURL(buildenv.ByProjectID(opts.ProjectID)))
163-
addMeta("builder-type", builderType)
165+
addMeta("buildlet-binary-url", hconf.BuildletBinaryURL(buildenv.ByProjectID(opts.ProjectID)))
166+
addMeta("buildlet-host-type", hostType)
164167
if !opts.TLS.IsZero() {
165168
addMeta("tls-cert", opts.TLS.CertPEM)
166169
addMeta("tls-key", opts.TLS.KeyPEM)
@@ -304,7 +307,7 @@ type VM struct {
304307
Name string
305308
IPPort string
306309
TLS KeyPair
307-
Type string
310+
Type string // buildlet type
308311
}
309312

310313
// ListVMs lists all VMs.
@@ -329,13 +332,13 @@ func ListVMs(ts oauth2.TokenSource, proj, zone string) ([]VM, error) {
329332
meta[it.Key] = *it.Value
330333
}
331334
}
332-
builderType := meta["builder-type"]
333-
if builderType == "" {
335+
hostType := meta["buildlet-host-type"]
336+
if hostType == "" {
334337
continue
335338
}
336339
vm := VM{
337340
Name: inst.Name,
338-
Type: builderType,
341+
Type: hostType,
339342
TLS: KeyPair{
340343
CertPEM: meta["tls-cert"],
341344
KeyPEM: meta["tls-key"],

buildlet/kube.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ type PodOpts struct {
6767

6868
// StartPod creates a new pod on a Kubernetes cluster and returns a buildlet client
6969
// configured to speak to it.
70-
func StartPod(ctx context.Context, kubeClient *kubernetes.Client, podName, builderType string, opts PodOpts) (*Client, error) {
71-
conf, ok := dashboard.Builders[builderType]
70+
func StartPod(ctx context.Context, kubeClient *kubernetes.Client, podName, hostType string, opts PodOpts) (*Client, error) {
71+
conf, ok := dashboard.Hosts[hostType]
7272
if !ok || conf.KubeImage == "" {
73-
return nil, fmt.Errorf("invalid builder type %q", builderType)
73+
return nil, fmt.Errorf("invalid builder type %q", hostType)
7474
}
7575
pod := &api.Pod{
7676
TypeMeta: api.TypeMeta{
@@ -81,7 +81,7 @@ func StartPod(ctx context.Context, kubeClient *kubernetes.Client, podName, build
8181
Name: podName,
8282
Labels: map[string]string{
8383
"name": podName,
84-
"type": builderType,
84+
"type": hostType,
8585
"role": "buildlet",
8686
},
8787
Annotations: map[string]string{},
@@ -132,7 +132,7 @@ func StartPod(ctx context.Context, kubeClient *kubernetes.Client, podName, build
132132
// This lets us/ update the buildlet more easily than
133133
// rebuilding the whole pod image.
134134
addEnv("META_BUILDLET_BINARY_URL", conf.BuildletBinaryURL(buildenv.ByProjectID(opts.ProjectID)))
135-
addEnv("META_BUILDER_TYPE", builderType)
135+
addEnv("META_BUILDLET_HOST_TYPE", hostType)
136136
if !opts.TLS.IsZero() {
137137
addEnv("META_TLS_CERT", opts.TLS.CertPEM)
138138
addEnv("META_TLS_KEY", opts.TLS.KeyPEM)

buildlet/remote.go

+16-8
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,25 @@ func (cc *CoordinatorClient) client() (*http.Client, error) {
5858
return cc.hc, nil
5959
}
6060

61-
// CreateBuildlet creates a new buildlet of the given type on cc.
61+
// CreateBuildlet creates a new buildlet of the given builder type on
62+
// cc.
63+
//
64+
// This takes a builderType (instead of a hostType), but the
65+
// returned buildlet can be used as any builder that has the same
66+
// underlying buildlet type. For instance, a linux-amd64 buildlet can
67+
// act as either linux-amd64 or linux-386-387.
68+
//
6269
// It may expire at any time.
6370
// To release it, call Client.Destroy.
64-
func (cc *CoordinatorClient) CreateBuildlet(buildletType string) (*Client, error) {
71+
func (cc *CoordinatorClient) CreateBuildlet(builderType string) (*Client, error) {
6572
hc, err := cc.client()
6673
if err != nil {
6774
return nil, err
6875
}
6976
ipPort, _ := cc.instance().TLSHostPort() // must succeed if client did
7077
form := url.Values{
71-
"type": {buildletType},
78+
"version": {"20160922"}, // checked by cmd/coordinator/remote.go
79+
"builderType": {builderType},
7280
}
7381
req, _ := http.NewRequest("POST",
7482
"https://"+ipPort+"/buildlet/create",
@@ -100,10 +108,11 @@ func (cc *CoordinatorClient) CreateBuildlet(buildletType string) (*Client, error
100108
}
101109

102110
type RemoteBuildlet struct {
103-
Type string // "openbsd-386"
104-
Name string // "buildlet-adg-openbsd-386-2"
105-
Created time.Time
106-
Expires time.Time
111+
HostType string // "host-linux-kubestd"
112+
BuilderType string // "linux-386-387"
113+
Name string // "buildlet-adg-openbsd-386-2"
114+
Created time.Time
115+
Expires time.Time
107116
}
108117

109118
func (cc *CoordinatorClient) RemoteBuildlets() ([]RemoteBuildlet, error) {
@@ -113,7 +122,6 @@ func (cc *CoordinatorClient) RemoteBuildlets() ([]RemoteBuildlet, error) {
113122
}
114123
ipPort, _ := cc.instance().TLSHostPort() // must succeed if client did
115124
req, _ := http.NewRequest("GET", "https://"+ipPort+"/buildlet/list", nil)
116-
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
117125
req.SetBasicAuth(cc.Auth.Username, cc.Auth.Password)
118126
res, err := hc.Do(req)
119127
if err != nil {

cmd/buildlet/Makefile

+4-4
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,16 @@ buildlet.solaris-amd64: FORCE
5858

5959
dev-buildlet.linux-arm: FORCE
6060
go install golang.org/x/build/cmd/upload
61-
upload --verbose --osarch=$@ --file=go:golang.org/x/build/cmd/buildlet --public dev-go-builder-data/$@
61+
upload --verbose --osarch=$@ --file=go:golang.org/x/build/cmd/buildlet --public dev-go-builder-data/buildlet.linux-arm
6262

6363
dev-buildlet.linux-amd64: FORCE
6464
go install golang.org/x/build/cmd/upload
65-
upload --verbose --osarch=$@ --file=go:golang.org/x/build/cmd/buildlet --public dev-go-builder-data/$@
65+
upload --verbose --osarch=$@ --file=go:golang.org/x/build/cmd/buildlet --public dev-go-builder-data/buildlet.linux-amd64
6666

6767
dev-buildlet.windows-amd64: FORCE
6868
go install golang.org/x/build/cmd/upload
69-
upload --verbose --osarch=$@ --file=go:golang.org/x/build/cmd/buildlet --public dev-go-builder-data/$@
69+
upload --verbose --osarch=$@ --file=go:golang.org/x/build/cmd/buildlet --public dev-go-builder-data/buildlet.windows-amd64
7070

7171
dev-buildlet.plan9-386: FORCE
7272
go install golang.org/x/build/cmd/upload
73-
upload --verbose --osarch=$@ --file=go:golang.org/x/build/cmd/buildlet --public dev-go-builder-data/$@
73+
upload --verbose --osarch=$@ --file=go:golang.org/x/build/cmd/buildlet --public dev-go-builder-data/buildlet.plan9-386

cmd/buildlet/buildlet.go

+16-13
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ func handleWriteTGZ(w http.ResponseWriter, r *http.Request) {
509509
defer res.Body.Close()
510510
if res.StatusCode != http.StatusOK {
511511
log.Printf("writetgz: failed to fetch tgz URL %s: status=%v", urlStr, res.Status)
512-
http.Error(w, fmt.Sprintf("fetching provided url: %s", res.Status), http.StatusInternalServerError)
512+
http.Error(w, fmt.Sprintf("writetgz: fetching provided URL %q: %s", urlStr, res.Status), http.StatusInternalServerError)
513513
return
514514
}
515515
tgz = res.Body
@@ -736,7 +736,14 @@ func handleExec(w http.ResponseWriter, r *http.Request) {
736736
f.Flush()
737737
}
738738

739-
env := append(baseEnv(), r.PostForm["env"]...)
739+
goarch := "amd64" // unless we find otherwise
740+
for _, pair := range r.PostForm["env"] {
741+
if hasPrefixFold(pair, "GOARCH=") {
742+
goarch = pair[len("GOARCH="):]
743+
}
744+
}
745+
746+
env := append(baseEnv(goarch), r.PostForm["env"]...)
740747
env = envutil.Dedup(runtime.GOOS == "windows", env)
741748
env = setPathEnv(env, r.PostForm["path"], *workDir)
742749

@@ -869,21 +876,17 @@ func pathSeparator() string {
869876
}
870877
}
871878

872-
func baseEnv() []string {
879+
func baseEnv(goarch string) []string {
873880
if runtime.GOOS == "windows" {
874-
return windowsBaseEnv()
881+
return windowsBaseEnv(goarch)
875882
}
876883
return os.Environ()
877884
}
878885

879-
func windowsBaseEnv() (e []string) {
886+
func windowsBaseEnv(goarch string) (e []string) {
880887
e = append(e, "GOBUILDEXIT=1") // exit all.bat with completion status
881-
btype, err := metadata.InstanceAttributeValue("builder-type")
882-
if err != nil {
883-
log.Fatalf("Failed to get builder-type: %v", err)
884-
return nil
885-
}
886-
is64 := strings.HasPrefix(btype, "windows-amd64")
888+
889+
is64 := goarch != "386"
887890
for _, pair := range os.Environ() {
888891
const pathEq = "PATH="
889892
if hasPrefixFold(pair, pathEq) {
@@ -1239,9 +1242,9 @@ func makeBSDFilesystemFast() {
12391242
log.Printf("Not on GCE; not remounting root filesystem.")
12401243
return
12411244
}
1242-
btype, err := metadata.InstanceAttributeValue("builder-type")
1245+
btype, err := metadata.InstanceAttributeValue("buildlet-type")
12431246
if _, ok := err.(metadata.NotDefinedError); ok && len(btype) == 0 {
1244-
log.Printf("Not remounting root filesystem due to missing builder-type metadata.")
1247+
log.Printf("Not remounting root filesystem due to missing buildlet-type metadata.")
12451248
return
12461249
}
12471250
if err != nil {

0 commit comments

Comments
 (0)