| OLD | NEW |
| 1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 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 swarming | 5 package swarming |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "net/http" | 8 "net/http" |
| 9 "os" | 9 "os" |
| 10 | 10 |
| 11 "google.golang.org/api/googleapi" | 11 "google.golang.org/api/googleapi" |
| 12 | 12 |
| 13 "github.com/julienschmidt/httprouter" | 13 "github.com/julienschmidt/httprouter" |
| 14 "golang.org/x/net/context" | 14 "golang.org/x/net/context" |
| 15 | 15 |
| 16 "github.com/luci/luci-go/milo/appengine/settings" | 16 "github.com/luci/luci-go/milo/appengine/settings" |
| 17 "github.com/luci/luci-go/milo/common/miloerror" | 17 "github.com/luci/luci-go/milo/common/miloerror" |
| 18 "github.com/luci/luci-go/server/templates" | 18 "github.com/luci/luci-go/server/templates" |
| 19 ) | 19 ) |
| 20 | 20 |
| 21 func getServer(r *http.Request) string { | 21 const ( |
| 22 » defaultSwarmingServer = "chromium-swarm.appspot.com" |
| 23 » defaultSwarmingDevServer = "chromium-swarm-dev.appspot.com" |
| 24 ) |
| 25 |
| 26 func getSwarmingHost(r *http.Request) string { |
| 22 server := r.FormValue("server") | 27 server := r.FormValue("server") |
| 23 // TODO(hinoka): configure this mapping in luci-config | |
| 24 switch server { | 28 switch server { |
| 25 case "": | 29 case "": |
| 26 » » return "chromium-swarm.appspot.com" | 30 » » return defaultSwarmingServer |
| 27 case "dev": | 31 case "dev": |
| 28 » » return "chromium-swarm-dev.appspot.com" | 32 » » return defaultSwarmingDevServer |
| 29 default: | 33 default: |
| 30 return server | 34 return server |
| 31 } | 35 } |
| 32 } | 36 } |
| 33 | 37 |
| 38 func getSwarmingService(c context.Context, host string) (swarmingService, error)
{ |
| 39 switch host { |
| 40 // TODO(hinoka): configure this mapping in luci-config |
| 41 case defaultSwarmingServer, defaultSwarmingDevServer, |
| 42 "cast-swarming.appspot.com": |
| 43 return newProdService(c, host) |
| 44 |
| 45 default: |
| 46 return nil, &miloerror.Error{ |
| 47 Message: "unregistered Swarming host", |
| 48 Code: http.StatusNotFound, |
| 49 } |
| 50 } |
| 51 } |
| 52 |
| 34 // Log is for fetching logs from swarming. | 53 // Log is for fetching logs from swarming. |
| 35 type Log struct{} | 54 type Log struct{} |
| 36 | 55 |
| 37 // Build is for deciphering recipe builds from swarming based off of logs. | 56 // Build is for deciphering recipe builds from swarming based off of logs. |
| 38 type Build struct{} | 57 type Build struct{} |
| 39 | 58 |
| 40 // GetTemplateName for Log returns the template name for log pages. | 59 // GetTemplateName for Log returns the template name for log pages. |
| 41 func (l Log) GetTemplateName(t settings.Theme) string { | 60 func (l Log) GetTemplateName(t settings.Theme) string { |
| 42 return "log.html" | 61 return "log.html" |
| 43 } | 62 } |
| 44 | 63 |
| 45 // Render writes the build log to the given response writer. | 64 // Render writes the build log to the given response writer. |
| 46 func (l Log) Render(c context.Context, r *http.Request, p httprouter.Params) (*t
emplates.Args, error) { | 65 func (l Log) Render(c context.Context, r *http.Request, p httprouter.Params) (*t
emplates.Args, error) { |
| 47 id := p.ByName("id") | 66 id := p.ByName("id") |
| 48 if id == "" { | 67 if id == "" { |
| 49 return nil, &miloerror.Error{ | 68 return nil, &miloerror.Error{ |
| 50 Message: "No id", | 69 Message: "No id", |
| 51 Code: http.StatusBadRequest, | 70 Code: http.StatusBadRequest, |
| 52 } | 71 } |
| 53 } | 72 } |
| 54 logname := p.ByName("logname") | 73 logname := p.ByName("logname") |
| 55 if logname == "" { | 74 if logname == "" { |
| 56 return nil, &miloerror.Error{ | 75 return nil, &miloerror.Error{ |
| 57 Message: "No log name", | 76 Message: "No log name", |
| 58 Code: http.StatusBadRequest, | 77 Code: http.StatusBadRequest, |
| 59 } | 78 } |
| 60 } | 79 } |
| 61 | 80 |
| 62 » log, closed, err := swarmingBuildLogImpl(c, getServer(r), id, logname) | 81 » sf, err := getSwarmingService(c, getSwarmingHost(r)) |
| 63 if err != nil { | 82 if err != nil { |
| 64 return nil, convertErr(err) | 83 return nil, convertErr(err) |
| 65 } | 84 } |
| 85 |
| 86 log, closed, err := swarmingBuildLogImpl(c, sf, id, logname) |
| 87 if err != nil { |
| 88 return nil, convertErr(err) |
| 89 } |
| 66 | 90 |
| 67 args := &templates.Args{ | 91 args := &templates.Args{ |
| 68 "Log": log, | 92 "Log": log, |
| 69 "Closed": closed, | 93 "Closed": closed, |
| 70 } | 94 } |
| 71 return args, nil | 95 return args, nil |
| 72 } | 96 } |
| 73 | 97 |
| 74 // GetTemplateName for Build returns the template name for build pages. | 98 // GetTemplateName for Build returns the template name for build pages. |
| 75 func (b Build) GetTemplateName(t settings.Theme) string { | 99 func (b Build) GetTemplateName(t settings.Theme) string { |
| 76 return "build.html" | 100 return "build.html" |
| 77 } | 101 } |
| 78 | 102 |
| 79 // Render renders both the build page and the log. | 103 // Render renders both the build page and the log. |
| 80 func (b Build) Render(c context.Context, r *http.Request, p httprouter.Params) (
*templates.Args, error) { | 104 func (b Build) Render(c context.Context, r *http.Request, p httprouter.Params) (
*templates.Args, error) { |
| 81 // Get the swarming ID | 105 // Get the swarming ID |
| 82 id := p.ByName("id") | 106 id := p.ByName("id") |
| 83 if id == "" { | 107 if id == "" { |
| 84 return nil, &miloerror.Error{ | 108 return nil, &miloerror.Error{ |
| 85 Message: "No id", | 109 Message: "No id", |
| 86 Code: http.StatusBadRequest, | 110 Code: http.StatusBadRequest, |
| 87 } | 111 } |
| 88 } | 112 } |
| 89 | 113 |
| 90 » result, err := swarmingBuildImpl(c, r.URL.String(), getServer(r), id) | 114 » sf, err := getSwarmingService(c, getSwarmingHost(r)) |
| 91 if err != nil { | 115 if err != nil { |
| 92 return nil, convertErr(err) | 116 return nil, convertErr(err) |
| 93 } | 117 } |
| 118 |
| 119 result, err := swarmingBuildImpl(c, sf, r.URL.String(), id) |
| 120 if err != nil { |
| 121 return nil, convertErr(err) |
| 122 } |
| 94 | 123 |
| 95 // Render into the template | 124 // Render into the template |
| 96 args := &templates.Args{ | 125 args := &templates.Args{ |
| 97 "Build": result, | 126 "Build": result, |
| 98 } | 127 } |
| 99 return args, nil | 128 return args, nil |
| 100 } | 129 } |
| 101 | 130 |
| 102 func convertErr(err error) error { | 131 func convertErr(err error) error { |
| 103 if isAPINotFound(err) || os.IsNotExist(err) { | 132 if isAPINotFound(err) || os.IsNotExist(err) { |
| 104 return &miloerror.Error{ | 133 return &miloerror.Error{ |
| 105 Message: err.Error(), | 134 Message: err.Error(), |
| 106 Code: http.StatusNotFound, | 135 Code: http.StatusNotFound, |
| 107 } | 136 } |
| 108 } | 137 } |
| 109 return err | 138 return err |
| 110 } | 139 } |
| 111 | 140 |
| 112 // isAPINotFound returns true if err is a HTTP 404 API response. | 141 // isAPINotFound returns true if err is a HTTP 404 API response. |
| 113 func isAPINotFound(err error) bool { | 142 func isAPINotFound(err error) bool { |
| 114 if apiErr, ok := err.(*googleapi.Error); ok && apiErr.Code == http.Statu
sNotFound { | 143 if apiErr, ok := err.(*googleapi.Error); ok && apiErr.Code == http.Statu
sNotFound { |
| 115 return true | 144 return true |
| 116 } | 145 } |
| 117 | 146 |
| 118 return false | 147 return false |
| 119 } | 148 } |
| OLD | NEW |