| 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 "sort" | 12 "sort" |
| 13 "time" | 13 "time" |
| 14 | 14 |
| 15 "github.com/luci/gae/service/datastore" | 15 "github.com/luci/gae/service/datastore" |
| 16 » log "github.com/luci/luci-go/common/logging" | 16 » "github.com/luci/luci-go/common/logging" |
| 17 "github.com/luci/luci-go/milo/api/resp" | 17 "github.com/luci/luci-go/milo/api/resp" |
| 18 "github.com/luci/luci-go/milo/appengine/settings" |
| 18 | 19 |
| 19 "golang.org/x/net/context" | 20 "golang.org/x/net/context" |
| 20 ) | 21 ) |
| 21 | 22 |
| 22 func decodeMasterEntry( | 23 func decodeMasterEntry( |
| 23 c context.Context, entry *buildbotMasterEntry, master *buildbotMaster) e
rror { | 24 c context.Context, entry *buildbotMasterEntry, master *buildbotMaster) e
rror { |
| 24 | 25 |
| 25 reader, err := gzip.NewReader(bytes.NewReader(entry.Data)) | 26 reader, err := gzip.NewReader(bytes.NewReader(entry.Data)) |
| 26 if err != nil { | 27 if err != nil { |
| 27 return err | 28 return err |
| 28 } | 29 } |
| 29 defer reader.Close() | 30 defer reader.Close() |
| 30 if err = json.NewDecoder(reader).Decode(master); err != nil { | 31 if err = json.NewDecoder(reader).Decode(master); err != nil { |
| 31 return err | 32 return err |
| 32 } | 33 } |
| 33 return nil | 34 return nil |
| 34 } | 35 } |
| 35 | 36 |
| 36 // getMasterJSON fetches the latest known buildbot master data and returns | 37 // getMasterJSON fetches the latest known buildbot master data and returns |
| 37 // the buildbotMaster struct (if found), whether or not it is internal, | 38 // the buildbotMaster struct (if found), whether or not it is internal, |
| 38 // the last modified time, and an error if not found. | 39 // the last modified time, and an error if not found. |
| 39 func getMasterJSON(c context.Context, name string) ( | 40 func getMasterJSON(c context.Context, name string) ( |
| 40 master *buildbotMaster, internal bool, t time.Time, err error) { | 41 master *buildbotMaster, internal bool, t time.Time, err error) { |
| 41 master = &buildbotMaster{} | 42 master = &buildbotMaster{} |
| 42 entry := buildbotMasterEntry{Name: name} | 43 entry := buildbotMasterEntry{Name: name} |
| 43 ds := datastore.Get(c) | 44 ds := datastore.Get(c) |
| 44 err = ds.Get(&entry) | 45 err = ds.Get(&entry) |
| 45 if err != nil { | 46 if err != nil { |
| 46 » » log.WithError(err).Errorf( | 47 » » logging.WithError(err).Errorf( |
| 47 c, "Encountered error while fetching entry for %s:\n%s",
name, err) | 48 c, "Encountered error while fetching entry for %s:\n%s",
name, err) |
| 48 return | 49 return |
| 49 } | 50 } |
| 50 internal = entry.Internal | 51 internal = entry.Internal |
| 51 t = entry.Modified | 52 t = entry.Modified |
| 52 err = decodeMasterEntry(c, &entry, master) | 53 err = decodeMasterEntry(c, &entry, master) |
| 53 return | 54 return |
| 54 } | 55 } |
| 55 | 56 |
| 56 // GetAllBuilders returns a resp.Module object containing all known masters | 57 // GetAllBuilders returns a resp.Module object containing all known masters |
| 57 // and builders. | 58 // and builders. |
| 58 func GetAllBuilders(c context.Context) (*resp.Module, error) { | 59 func GetAllBuilders(c context.Context) (*resp.Module, error) { |
| 59 result := &resp.Module{Name: "Buildbot"} | 60 result := &resp.Module{Name: "Buildbot"} |
| 60 // Fetch all Master entries from datastore | 61 // Fetch all Master entries from datastore |
| 61 ds := datastore.Get(c) | 62 ds := datastore.Get(c) |
| 62 q := datastore.NewQuery("buildbotMasterEntry") | 63 q := datastore.NewQuery("buildbotMasterEntry") |
| 63 // TODO(hinoka): Support internal queries. | |
| 64 q = q.Eq("Internal", false) | |
| 65 // TODO(hinoka): Maybe don't look past like a month or so? | 64 // TODO(hinoka): Maybe don't look past like a month or so? |
| 66 entries := []*buildbotMasterEntry{} | 65 entries := []*buildbotMasterEntry{} |
| 67 err := ds.GetAll(q, &entries) | 66 err := ds.GetAll(q, &entries) |
| 68 if err != nil { | 67 if err != nil { |
| 69 return nil, err | 68 return nil, err |
| 70 } | 69 } |
| 71 | 70 |
| 72 // Add each builder from each master entry into the result. | 71 // Add each builder from each master entry into the result. |
| 73 // TODO(hinoka): FanInOut this? | 72 // TODO(hinoka): FanInOut this? |
| 74 for _, entry := range entries { | 73 for _, entry := range entries { |
| 74 if entry.Internal { |
| 75 // Bypass the master if it's an internal master and the
user is not |
| 76 // part of the buildbot-private project. |
| 77 allowed, err := settings.IsAllowedInternal(c) |
| 78 if err != nil { |
| 79 logging.WithError(err).Errorf(c, "Could not proc
ess master %s", entry.Name) |
| 80 return nil, err |
| 81 } |
| 82 if !allowed { |
| 83 continue |
| 84 } |
| 85 } |
| 75 master := &buildbotMaster{} | 86 master := &buildbotMaster{} |
| 76 err = decodeMasterEntry(c, entry, master) | 87 err = decodeMasterEntry(c, entry, master) |
| 77 if err != nil { | 88 if err != nil { |
| 78 » » » log.WithError(err).Errorf(c, "Could not decode %s", entr
y.Name) | 89 » » » logging.WithError(err).Errorf(c, "Could not decode %s",
entry.Name) |
| 79 continue | 90 continue |
| 80 } | 91 } |
| 81 ml := resp.MasterListing{Name: entry.Name} | 92 ml := resp.MasterListing{Name: entry.Name} |
| 82 // TODO(hinoka): Sort | |
| 83 // Sort the builder listing. | 93 // Sort the builder listing. |
| 84 sb := make([]string, 0, len(master.Builders)) | 94 sb := make([]string, 0, len(master.Builders)) |
| 85 for bn := range master.Builders { | 95 for bn := range master.Builders { |
| 86 sb = append(sb, bn) | 96 sb = append(sb, bn) |
| 87 } | 97 } |
| 88 sort.Strings(sb) | 98 sort.Strings(sb) |
| 89 for _, bn := range sb { | 99 for _, bn := range sb { |
| 90 ml.Builders = append(ml.Builders, resp.Link{ | 100 ml.Builders = append(ml.Builders, resp.Link{ |
| 91 Label: bn, | 101 Label: bn, |
| 92 // Go templates escapes this for us, and also | 102 // Go templates escapes this for us, and also |
| 93 // slashes are not allowed in builder names. | 103 // slashes are not allowed in builder names. |
| 94 URL: fmt.Sprintf("/buildbot/%s/%s", entry.Name,
bn), | 104 URL: fmt.Sprintf("/buildbot/%s/%s", entry.Name,
bn), |
| 95 }) | 105 }) |
| 96 } | 106 } |
| 97 result.Masters = append(result.Masters, ml) | 107 result.Masters = append(result.Masters, ml) |
| 98 } | 108 } |
| 99 return result, nil | 109 return result, nil |
| 100 } | 110 } |
| OLD | NEW |