| OLD | NEW |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package buildbot | 5 package buildbot |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | 8 "bytes" |
| 9 "compress/gzip" | 9 "compress/gzip" |
| 10 "encoding/json" | 10 "encoding/json" |
| 11 "fmt" | 11 "fmt" |
| 12 "net/http" |
| 12 "sort" | 13 "sort" |
| 13 "time" | 14 "time" |
| 14 | 15 |
| 15 "github.com/luci/gae/service/datastore" | 16 "github.com/luci/gae/service/datastore" |
| 16 "github.com/luci/luci-go/common/logging" | 17 "github.com/luci/luci-go/common/logging" |
| 17 "github.com/luci/luci-go/milo/api/resp" | 18 "github.com/luci/luci-go/milo/api/resp" |
| 18 "github.com/luci/luci-go/milo/appengine/settings" | 19 "github.com/luci/luci-go/milo/appengine/settings" |
| 20 "github.com/luci/luci-go/milo/common/miloerror" |
| 19 | 21 |
| 20 "golang.org/x/net/context" | 22 "golang.org/x/net/context" |
| 21 ) | 23 ) |
| 22 | 24 |
| 23 func decodeMasterEntry( | 25 func decodeMasterEntry( |
| 24 c context.Context, entry *buildbotMasterEntry, master *buildbotMaster) e
rror { | 26 c context.Context, entry *buildbotMasterEntry, master *buildbotMaster) e
rror { |
| 25 | 27 |
| 26 reader, err := gzip.NewReader(bytes.NewReader(entry.Data)) | 28 reader, err := gzip.NewReader(bytes.NewReader(entry.Data)) |
| 27 if err != nil { | 29 if err != nil { |
| 28 return err | 30 return err |
| 29 } | 31 } |
| 30 defer reader.Close() | 32 defer reader.Close() |
| 31 if err = json.NewDecoder(reader).Decode(master); err != nil { | 33 if err = json.NewDecoder(reader).Decode(master); err != nil { |
| 32 return err | 34 return err |
| 33 } | 35 } |
| 34 return nil | 36 return nil |
| 35 } | 37 } |
| 36 | 38 |
| 39 var errMasterNotFound = miloerror.Error{ |
| 40 Message: "Master not found", |
| 41 Code: http.StatusNotFound, |
| 42 } |
| 43 |
| 44 // getMasterEntry feches the named master and does an ACL check on the |
| 45 // current user. |
| 46 func getMasterEntry(c context.Context, name string) (*buildbotMasterEntry, error
) { |
| 47 entry := buildbotMasterEntry{Name: name} |
| 48 ds := datastore.Get(c) |
| 49 err := ds.Get(&entry) |
| 50 switch { |
| 51 case err == datastore.ErrNoSuchEntity: |
| 52 return nil, errMasterNotFound |
| 53 case err != nil: |
| 54 logging.WithError(err).Errorf( |
| 55 c, "Encountered error while fetching entry for %s:\n%s",
name, err) |
| 56 return nil, err |
| 57 } |
| 58 |
| 59 // Do the ACL check if the entry is internal. |
| 60 if entry.Internal { |
| 61 allowed, err := settings.IsAllowedInternal(c) |
| 62 if err != nil { |
| 63 return nil, err |
| 64 } |
| 65 if !allowed { |
| 66 return nil, errMasterNotFound |
| 67 } |
| 68 } |
| 69 |
| 70 return &entry, nil |
| 71 } |
| 72 |
| 37 // getMasterJSON fetches the latest known buildbot master data and returns | 73 // getMasterJSON fetches the latest known buildbot master data and returns |
| 38 // the buildbotMaster struct (if found), whether or not it is internal, | 74 // the buildbotMaster struct (if found), whether or not it is internal, |
| 39 // the last modified time, and an error if not found. | 75 // the last modified time, and an error if not found. |
| 40 func getMasterJSON(c context.Context, name string) ( | 76 func getMasterJSON(c context.Context, name string) ( |
| 41 » master *buildbotMaster, internal bool, t time.Time, err error) { | 77 » master *buildbotMaster, t time.Time, err error) { |
| 42 master = &buildbotMaster{} | 78 master = &buildbotMaster{} |
| 43 » entry := buildbotMasterEntry{Name: name} | 79 » entry, err := getMasterEntry(c, name) |
| 44 » ds := datastore.Get(c) | |
| 45 » err = ds.Get(&entry) | |
| 46 if err != nil { | 80 if err != nil { |
| 47 logging.WithError(err).Errorf( | |
| 48 c, "Encountered error while fetching entry for %s:\n%s",
name, err) | |
| 49 return | 81 return |
| 50 } | 82 } |
| 51 internal = entry.Internal | |
| 52 t = entry.Modified | 83 t = entry.Modified |
| 53 » err = decodeMasterEntry(c, &entry, master) | 84 » err = decodeMasterEntry(c, entry, master) |
| 54 return | 85 return |
| 55 } | 86 } |
| 56 | 87 |
| 57 // GetAllBuilders returns a resp.Module object containing all known masters | 88 // GetAllBuilders returns a resp.Module object containing all known masters |
| 58 // and builders. | 89 // and builders. |
| 59 func GetAllBuilders(c context.Context) (*resp.Module, error) { | 90 func GetAllBuilders(c context.Context) (*resp.Module, error) { |
| 60 result := &resp.Module{Name: "Buildbot"} | 91 result := &resp.Module{Name: "Buildbot"} |
| 61 // Fetch all Master entries from datastore | 92 // Fetch all Master entries from datastore |
| 62 ds := datastore.Get(c) | 93 ds := datastore.Get(c) |
| 63 q := datastore.NewQuery("buildbotMasterEntry") | 94 q := datastore.NewQuery("buildbotMasterEntry") |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 Label: bn, | 132 Label: bn, |
| 102 // Go templates escapes this for us, and also | 133 // Go templates escapes this for us, and also |
| 103 // slashes are not allowed in builder names. | 134 // slashes are not allowed in builder names. |
| 104 URL: fmt.Sprintf("/buildbot/%s/%s", entry.Name,
bn), | 135 URL: fmt.Sprintf("/buildbot/%s/%s", entry.Name,
bn), |
| 105 }) | 136 }) |
| 106 } | 137 } |
| 107 result.Masters = append(result.Masters, ml) | 138 result.Masters = append(result.Masters, ml) |
| 108 } | 139 } |
| 109 return result, nil | 140 return result, nil |
| 110 } | 141 } |
| OLD | NEW |