Chromium Code Reviews| Index: milo/buildsource/buildbot/builder.go |
| diff --git a/milo/buildsource/buildbot/builder.go b/milo/buildsource/buildbot/builder.go |
| index dc3790656f9d70b6c63cf9685fa4fc929d00f016..0e16887add4c854b42bd9429017b8661b3ce5a6a 100644 |
| --- a/milo/buildsource/buildbot/builder.go |
| +++ b/milo/buildsource/buildbot/builder.go |
| @@ -17,7 +17,6 @@ package buildbot |
| import ( |
| "crypto/sha1" |
| "encoding/base64" |
| - "errors" |
| "fmt" |
| "sort" |
| "strings" |
| @@ -27,8 +26,10 @@ import ( |
| "github.com/luci/gae/service/memcache" |
| "github.com/luci/luci-go/common/clock" |
| + "github.com/luci/luci-go/common/errors" |
| "github.com/luci/luci-go/common/logging" |
| "github.com/luci/luci-go/milo/api/resp" |
| + "github.com/luci/luci-go/milo/common" |
| "golang.org/x/net/context" |
| ) |
| @@ -95,8 +96,8 @@ func getBuildSummary(b *buildbotBuild) *resp.BuildSummary { |
| // getBuilds fetches all of the recent builds from the . Note that |
| // getBuilds() does not perform ACL checks. |
| func getBuilds( |
| - c context.Context, masterName, builderName string, finished bool, limit int, cursor *datastore.Cursor) ( |
| - []*resp.BuildSummary, *datastore.Cursor, error) { |
| + c context.Context, masterName, builderName string, finished bool, limit int, cursor datastore.Cursor) ( |
| + []*resp.BuildSummary, datastore.Cursor, error) { |
| // TODO(hinoka): Builder specific structs. |
| result := []*resp.BuildSummary{} |
| @@ -106,7 +107,7 @@ func getBuilds( |
| q = q.Eq("builder", builderName) |
| q = q.Order("-number") |
| if cursor != nil { |
| - q = q.Start(*cursor) |
| + q = q.Start(cursor) |
| } |
| buildbots, nextCursor, err := runBuildsQuery(c, q, int32(limit)) |
| if err != nil { |
| @@ -122,7 +123,7 @@ func getBuilds( |
| // datastore cursor by creating a mapping of nextCursor -> thisCursor |
| // in memcache. maybeSetGetCursor stores the future mapping, then returns prevCursor |
| // in the mapping for thisCursor -> prevCursor, if available. |
| -func maybeSetGetCursor(c context.Context, thisCursor, nextCursor *datastore.Cursor, limit int) (*datastore.Cursor, bool) { |
| +func maybeSetGetCursor(c context.Context, thisCursor, nextCursor datastore.Cursor, limit int) (datastore.Cursor, bool) { |
| key := func(c datastore.Cursor) string { |
| // Memcache key limit is 250 bytes, hash our cursor to get under this limit. |
| blob := sha1.Sum([]byte(c.String())) |
| @@ -130,12 +131,12 @@ func maybeSetGetCursor(c context.Context, thisCursor, nextCursor *datastore.Curs |
| } |
| // Set the next cursor to this cursor mapping, if available. |
| if nextCursor != nil { |
| - item := memcache.NewItem(c, key(*nextCursor)) |
| + item := memcache.NewItem(c, key(nextCursor)) |
| if thisCursor == nil { |
| // Make sure we know it exists, just empty |
| item.SetValue([]byte{}) |
| } else { |
| - item.SetValue([]byte((*thisCursor).String())) |
| + item.SetValue([]byte(thisCursor.String())) |
| } |
| item.SetExpiration(24 * time.Hour) |
| memcache.Set(c, item) |
| @@ -144,33 +145,17 @@ func maybeSetGetCursor(c context.Context, thisCursor, nextCursor *datastore.Curs |
| if thisCursor == nil { |
| return nil, false |
| } |
| - if item, err := memcache.GetKey(c, key(*thisCursor)); err == nil { |
| + if item, err := memcache.GetKey(c, key(thisCursor)); err == nil { |
| if len(item.Value()) == 0 { |
| return nil, true |
| } |
| if prevCursor, err := datastore.DecodeCursor(c, string(item.Value())); err == nil { |
| - return &prevCursor, true |
| + return prevCursor, true |
| } |
| } |
| return nil, false |
| } |
| -var errMasterNotFound = errors.New( |
| - "Either the request resource was not found or you have insufficient permissions") |
| -var errNotAuth = errors.New("You are not authenticated, try logging in") |
| - |
| -type errBuilderNotFound struct { |
| - master string |
| - builder string |
| - available []string |
| -} |
| - |
| -func (e errBuilderNotFound) Error() string { |
| - avail := strings.Join(e.available, "\n") |
| - return fmt.Sprintf("Cannot find builder %q in master %q.\nAvailable builders: \n%s", |
| - e.builder, e.master, avail) |
| -} |
| - |
| func summarizeSlavePool( |
| baseURL string, slaves []string, slaveMap map[string]*buildbotSlave) *resp.MachinePool { |
| @@ -204,23 +189,13 @@ func summarizeSlavePool( |
| return mp |
| } |
| -// builderImpl is the implementation for getting a milo builder page from buildbot. |
| +// GetBuilder is the implementation for getting a milo builder page from |
| +// buildbot. |
| +// |
| // This gets: |
| -// * Current Builds from querying the master json from the datastore. |
| -// * Recent Builds from a cron job that backfills the recent builds. |
| -func builderImpl( |
| - c context.Context, masterName, builderName string, limit int, cursor string) ( |
| - *resp.Builder, error) { |
| - |
| - var thisCursor *datastore.Cursor |
| - if cursor != "" { |
| - tmpCur, err := datastore.DecodeCursor(c, cursor) |
| - if err != nil { |
| - return nil, fmt.Errorf("bad cursor: %s", err) |
| - } |
| - thisCursor = &tmpCur |
| - } |
| - |
| +// * Current Builds from querying the master json from the datastore. |
| +// * Recent Builds from a cron job that backfills the recent builds. |
| +func GetBuilder(c context.Context, masterName, builderName string, limit int, cursor datastore.Cursor) (*resp.Builder, error) { |
| result := &resp.Builder{ |
| Name: builderName, |
| } |
| @@ -244,7 +219,13 @@ func builderImpl( |
| keys = append(keys, k) |
| } |
| sort.Strings(keys) |
| - return nil, errBuilderNotFound{masterName, builderName, keys} |
| + // TODO(iannucci): add error-info-helper tags to give the error page enough |
| + // information to render link-to-master and link-to-builder. |
| + builders := strings.Join(keys, "\n") |
| + return nil, errors.Reason( |
| + "Cannot find builder %q in master %q.\nAvailable builders: \n%s", |
| + builderName, masterName, builders, |
| + ).Tag(common.CodeParameterError).Err() |
|
Ryan Tseng
2017/07/13 22:00:46
404?
iannucci
2017/07/14 19:00:22
oh yeah
|
| } |
| // Extract pending builds out of the master json. |
| result.PendingBuilds = make([]*resp.BuildSummary, len(p.PendingBuildStates)) |
| @@ -273,20 +254,20 @@ func builderImpl( |
| result.MachinePool = summarizeSlavePool(baseURL+master.Name, p.Slaves, master.Slaves) |
| // This is CPU bound anyways, so there's no need to do this in parallel. |
| - finishedBuilds, nextCursor, err := getBuilds(c, masterName, builderName, true, limit, thisCursor) |
| + finishedBuilds, nextCursor, err := getBuilds(c, masterName, builderName, true, limit, cursor) |
| if err != nil { |
| return nil, err |
| } |
| - if prevCursor, ok := maybeSetGetCursor(c, thisCursor, nextCursor, limit); ok { |
| + if prevCursor, ok := maybeSetGetCursor(c, cursor, nextCursor, limit); ok { |
| if prevCursor == nil { |
| // Magic string to signal display prev without cursor |
| result.PrevCursor = "EMPTY" |
| } else { |
| - result.PrevCursor = (*prevCursor).String() |
| + result.PrevCursor = prevCursor.String() |
| } |
| } |
| if nextCursor != nil { |
| - result.NextCursor = (*nextCursor).String() |
| + result.NextCursor = nextCursor.String() |
| } |
| // Cursor is not needed for current builds. |
| currentBuilds, _, err := getBuilds(c, masterName, builderName, false, 0, nil) |