camweb: send deploy handler logs to GCLogging as well

When logging to Google Cloud Logging, make sure the deploy handler logs
are written there too.

We tag them with the from:camli-gce-launcher label.

Change-Id: I4dab010009f98efd2aeba7c57dc4ab3ca6a566b3
This commit is contained in:
mpl 2015-11-13 19:39:29 +01:00
parent a2aee25cfb
commit 621388f0bf
3 changed files with 92 additions and 59 deletions

View File

@ -132,6 +132,8 @@ type Deployer struct {
// SHA-1 and SHA-256 fingerprints of the HTTPS certificate created during setupHTTPS, if any. // SHA-1 and SHA-256 fingerprints of the HTTPS certificate created during setupHTTPS, if any.
// Keyed by hash name: "SHA-1", and "SHA-256". // Keyed by hash name: "SHA-1", and "SHA-256".
certFingerprints map[string]string certFingerprints map[string]string
*log.Logger // Cannot be nil.
} }
// Get returns the Instance corresponding to the Project, Zone, and Name defined in the // Get returns the Instance corresponding to the Project, Zone, and Name defined in the
@ -305,7 +307,7 @@ func (d *Deployer) Create(ctx *context.Context) (*compute.Instance, error) {
} }
if Verbose { if Verbose {
ij, _ := json.MarshalIndent(inst, "", " ") ij, _ := json.MarshalIndent(inst, "", " ")
log.Printf("Instance: %s", ij) d.Printf("Instance: %s", ij)
} }
if err = <-fwc; err != nil { if err = <-fwc; err != nil {
@ -410,7 +412,7 @@ func (d *Deployer) createInstance(computeService *compute.Service, ctx *context.
} }
if Verbose { if Verbose {
log.Print("Creating instance...") d.Print("Creating instance...")
} }
op, err := computeService.Instances.Insert(d.Conf.Project, d.Conf.Zone, instance).Do() op, err := computeService.Instances.Insert(d.Conf.Project, d.Conf.Zone, instance).Do()
if err != nil { if err != nil {
@ -418,7 +420,7 @@ func (d *Deployer) createInstance(computeService *compute.Service, ctx *context.
} }
opName := op.Name opName := op.Name
if Verbose { if Verbose {
log.Printf("Created. Waiting on operation %v", opName) d.Printf("Created. Waiting on operation %v", opName)
} }
OpLoop: OpLoop:
for { for {
@ -433,18 +435,18 @@ OpLoop:
switch op.Status { switch op.Status {
case "PENDING", "RUNNING": case "PENDING", "RUNNING":
if Verbose { if Verbose {
log.Printf("Waiting on operation %v", opName) d.Printf("Waiting on operation %v", opName)
} }
continue continue
case "DONE": case "DONE":
if op.Error != nil { if op.Error != nil {
for _, operr := range op.Error.Errors { for _, operr := range op.Error.Errors {
log.Printf("Error: %+v", operr) d.Printf("Error: %+v", operr)
} }
return fmt.Errorf("failed to start.") return fmt.Errorf("failed to start.")
} }
if Verbose { if Verbose {
log.Printf("Success. %+v", op) d.Printf("Success. %+v", op)
} }
break OpLoop break OpLoop
default: default:
@ -512,7 +514,7 @@ func (d *Deployer) setBuckets(storageService *storage.Service, ctx *context.Cont
} }
if len(needBucket) > 0 { if len(needBucket) > 0 {
if Verbose { if Verbose {
log.Printf("Need to create buckets: %v", needBucket) d.Printf("Need to create buckets: %v", needBucket)
} }
var waitBucket sync.WaitGroup var waitBucket sync.WaitGroup
var bucketErr error var bucketErr error
@ -525,7 +527,7 @@ func (d *Deployer) setBuckets(storageService *storage.Service, ctx *context.Cont
go func() { go func() {
defer waitBucket.Done() defer waitBucket.Done()
if Verbose { if Verbose {
log.Printf("Creating bucket %s", name) d.Printf("Creating bucket %s", name)
} }
b, err := storageService.Buckets.Insert(d.Conf.Project, &storage.Bucket{ b, err := storageService.Buckets.Insert(d.Conf.Project, &storage.Bucket{
Id: name, Id: name,
@ -536,7 +538,7 @@ func (d *Deployer) setBuckets(storageService *storage.Service, ctx *context.Cont
return return
} }
if Verbose { if Verbose {
log.Printf("Created bucket %s: %+v", name, b) d.Printf("Created bucket %s: %+v", name, b)
} }
}() }()
} }
@ -587,7 +589,7 @@ func (d *Deployer) setFirewall(ctx *context.Context, computeService *compute.Ser
} }
if Verbose { if Verbose {
log.Printf("Need to create rules: %v", needRules) d.Printf("Need to create rules: %v", needRules)
} }
var wg syncutil.Group var wg syncutil.Group
for name, rule := range needRules { for name, rule := range needRules {
@ -597,14 +599,14 @@ func (d *Deployer) setFirewall(ctx *context.Context, computeService *compute.Ser
name, rule := name, rule name, rule := name, rule
wg.Go(func() error { wg.Go(func() error {
if Verbose { if Verbose {
log.Printf("Creating rule %s", name) d.Printf("Creating rule %s", name)
} }
r, err := computeService.Firewalls.Insert(d.Conf.Project, &rule).Do() r, err := computeService.Firewalls.Insert(d.Conf.Project, &rule).Do()
if err != nil { if err != nil {
return fmt.Errorf("error creating rule %s: %v", name, err) return fmt.Errorf("error creating rule %s: %v", name, err)
} }
if Verbose { if Verbose {
log.Printf("Created rule %s: %+v", name, r) d.Printf("Created rule %s: %+v", name, r)
} }
return nil return nil
}) })
@ -624,7 +626,7 @@ func (d *Deployer) setupHTTPS(storageService *storage.Service) error {
} }
d.certFingerprints = sigs d.certFingerprints = sigs
if Verbose { if Verbose {
log.Printf("Reusing existing certificate with fingerprint %v", sigs["SHA-256"]) d.Printf("Reusing existing certificate with fingerprint %v", sigs["SHA-256"])
} }
return nil return nil
} }
@ -646,7 +648,7 @@ func (d *Deployer) setupHTTPS(storageService *storage.Service) error {
} else { } else {
if Verbose { if Verbose {
log.Printf("Generating self-signed certificate for %v ...", d.Conf.Hostname) d.Printf("Generating self-signed certificate for %v ...", d.Conf.Hostname)
} }
certBytes, keyBytes, err := httputil.GenSelfTLS(d.Conf.Hostname) certBytes, keyBytes, err := httputil.GenSelfTLS(d.Conf.Hostname)
if err != nil { if err != nil {
@ -658,14 +660,14 @@ func (d *Deployer) setupHTTPS(storageService *storage.Service) error {
} }
d.certFingerprints = sigs d.certFingerprints = sigs
if Verbose { if Verbose {
log.Printf("Wrote certificate with SHA-256 fingerprint %s", sigs["SHA-256"]) d.Printf("Wrote certificate with SHA-256 fingerprint %s", sigs["SHA-256"])
} }
cert = ioutil.NopCloser(bytes.NewReader(certBytes)) cert = ioutil.NopCloser(bytes.NewReader(certBytes))
key = ioutil.NopCloser(bytes.NewReader(keyBytes)) key = ioutil.NopCloser(bytes.NewReader(keyBytes))
} }
if Verbose { if Verbose {
log.Print("Uploading certificate and key...") d.Print("Uploading certificate and key...")
} }
_, err = storageService.Objects.Insert(d.Conf.bucketBase(), _, err = storageService.Objects.Insert(d.Conf.bucketBase(),
&storage.Object{Name: path.Join(configDir, certFilename)}).Media(cert).Do() &storage.Object{Name: path.Join(configDir, certFilename)}).Media(cert).Do()

View File

@ -121,7 +121,7 @@ type DeployHandler struct {
zones map[string][]string zones map[string][]string
regions []string regions []string
*log.Logger logger *log.Logger // should not be nil.
} }
// Config is the set of parameters to initialize the DeployHandler. // Config is the set of parameters to initialize the DeployHandler.
@ -217,14 +217,14 @@ func NewDeployHandler(host, prefix string) (http.Handler, error) {
h.serveRoot(w, r) h.serveRoot(w, r)
}) })
h.mux = mux h.mux = mux
h.Logger = log.New(os.Stderr, "", log.LstdFlags) h.SetLogger(log.New(os.Stderr, "GCE DEPLOYER: ", log.LstdFlags))
h.zones = backupZones h.zones = backupZones
// TODO(mpl): use time.AfterFunc and avoid having a goroutine running all the time almost // TODO(mpl): use time.AfterFunc and avoid having a goroutine running all the time almost
// doing nothing. // doing nothing.
refreshZonesFn := func() { refreshZonesFn := func() {
for { for {
if err := h.refreshZones(); err != nil { if err := h.refreshZones(); err != nil {
h.Printf("error while refreshing zones: %v", err) h.logger.Printf("error while refreshing zones: %v", err)
} }
time.Sleep(24 * time.Hour) time.Sleep(24 * time.Hour)
} }
@ -282,7 +282,7 @@ func (h *DeployHandler) refreshZones() error {
if err != nil { if err != nil {
if err == errNoRefresh { if err == errNoRefresh {
h.zones = backupZones h.zones = backupZones
h.Printf("Cannot refresh zones because %v. Using hard-coded ones instead.") h.logger.Printf("Cannot refresh zones because %v. Using hard-coded ones instead.")
return nil return nil
} }
return err return err
@ -336,19 +336,19 @@ func (h *DeployHandler) serveRoot(w http.ResponseWriter, r *http.Request) {
ZoneValues: h.zoneValues(), ZoneValues: h.zoneValues(),
MachineValues: machineValues, MachineValues: machineValues,
}); err != nil { }); err != nil {
h.Print(err) h.logger.Print(err)
} }
} }
func (h *DeployHandler) serveSetup(w http.ResponseWriter, r *http.Request) { func (h *DeployHandler) serveSetup(w http.ResponseWriter, r *http.Request) {
if r.FormValue("mode") != "setupproject" { if r.FormValue("mode") != "setupproject" {
httputil.ServeError(w, r, errors.New("bad form")) h.serveError(w, r, errors.New("bad form"))
return return
} }
ck, err := r.Cookie("user") ck, err := r.Cookie("user")
if err != nil { if err != nil {
h.serveFormError(w, errors.New("Cookie expired, or CSRF attempt. Please reload and retry.")) h.serveFormError(w, errors.New("Cookie expired, or CSRF attempt. Please reload and retry."))
h.Printf("Cookie expired, or CSRF attempt on form.") h.logger.Printf("Cookie expired, or CSRF attempt on form.")
return return
} }
@ -360,7 +360,7 @@ func (h *DeployHandler) serveSetup(w http.ResponseWriter, r *http.Request) {
br, err := h.storeInstanceConf(instConf) br, err := h.storeInstanceConf(instConf)
if err != nil { if err != nil {
httputil.ServeError(w, r, fmt.Errorf("could not store instance configuration: %v", err)) h.serveError(w, r, fmt.Errorf("could not store instance configuration: %v", err))
return return
} }
@ -377,43 +377,44 @@ func (h *DeployHandler) serveCallback(w http.ResponseWriter, r *http.Request) {
http.Error(w, http.Error(w,
fmt.Sprintf("Cookie expired, or CSRF attempt. Restart from %s%s%s", h.scheme, h.host, h.prefix), fmt.Sprintf("Cookie expired, or CSRF attempt. Restart from %s%s%s", h.scheme, h.host, h.prefix),
http.StatusBadRequest) http.StatusBadRequest)
h.Printf("Cookie expired, or CSRF attempt on callback.") h.logger.Printf("Cookie expired, or CSRF attempt on callback.")
return return
} }
code := r.FormValue("code") code := r.FormValue("code")
if code == "" { if code == "" {
httputil.ServeError(w, r, errors.New("No oauth code parameter in callback URL")) h.serveError(w, r, errors.New("No oauth code parameter in callback URL"))
return return
} }
h.Printf("successful authentication: %v", r.URL.RawQuery) h.logger.Printf("successful authentication: %v", r.URL.RawQuery)
br, tk, err := fromState(r) br, tk, err := fromState(r)
if err != nil { if err != nil {
httputil.ServeError(w, r, err) h.serveError(w, r, err)
return return
} }
if !xsrftoken.Valid(tk, h.xsrfKey, ck.Value, br.String()) { if !xsrftoken.Valid(tk, h.xsrfKey, ck.Value, br.String()) {
httputil.ServeError(w, r, fmt.Errorf("Invalid xsrf token: %q", tk)) h.serveError(w, r, fmt.Errorf("Invalid xsrf token: %q", tk))
return return
} }
oAuthConf := h.oAuthConfig() oAuthConf := h.oAuthConfig()
tok, err := oAuthConf.Exchange(oauth2.NoContext, code) tok, err := oAuthConf.Exchange(oauth2.NoContext, code)
if err != nil { if err != nil {
httputil.ServeError(w, r, fmt.Errorf("could not obtain a token: %v", err)) h.serveError(w, r, fmt.Errorf("could not obtain a token: %v", err))
return return
} }
h.Printf("successful authorization with token: %v", tok) h.logger.Printf("successful authorization with token: %v", tok)
instConf, err := h.instanceConf(br) instConf, err := h.instanceConf(br)
if err != nil { if err != nil {
httputil.ServeError(w, r, err) h.serveError(w, r, err)
return return
} }
depl := &Deployer{ depl := &Deployer{
Client: oAuthConf.Client(oauth2.NoContext, tok), Client: oAuthConf.Client(oauth2.NoContext, tok),
Conf: instConf, Conf: instConf,
Logger: h.logger,
} }
if found := h.serveOldInstance(w, br, depl); found { if found := h.serveOldInstance(w, br, depl); found {
@ -423,7 +424,7 @@ func (h *DeployHandler) serveCallback(w http.ResponseWriter, r *http.Request) {
if err := h.recordState(br, &creationState{ if err := h.recordState(br, &creationState{
InstConf: br, InstConf: br,
}); err != nil { }); err != nil {
httputil.ServeError(w, r, err) h.serveError(w, r, err)
return return
} }
@ -433,7 +434,7 @@ func (h *DeployHandler) serveCallback(w http.ResponseWriter, r *http.Request) {
InstConf: br, InstConf: br,
} }
if err != nil { if err != nil {
h.Printf("could not create instance: %v", err) h.logger.Printf("could not create instance: %v", err)
switch e := err.(type) { switch e := err.(type) {
case instanceExistsError: case instanceExistsError:
state.Err = fmt.Sprintf("%v %v", e, helpDeleteInstance) state.Err = fmt.Sprintf("%v %v", e, helpDeleteInstance)
@ -449,7 +450,7 @@ func (h *DeployHandler) serveCallback(w http.ResponseWriter, r *http.Request) {
state.CertFingerprintSHA256 = depl.certFingerprints["SHA-256"] state.CertFingerprintSHA256 = depl.certFingerprints["SHA-256"]
} }
if err := h.recordState(br, state); err != nil { if err := h.recordState(br, state); err != nil {
h.Printf("Could not record creation state for %v: %v", br, err) h.logger.Printf("Could not record creation state for %v: %v", br, err)
h.recordStateErrMu.Lock() h.recordStateErrMu.Lock()
defer h.recordStateErrMu.Unlock() defer h.recordStateErrMu.Unlock()
h.recordStateErr[br.String()] = err h.recordStateErr[br.String()] = err
@ -472,9 +473,9 @@ func (h *DeployHandler) serveOldInstance(w http.ResponseWriter, br blob.Ref, dep
} }
} }
if err != nil { if err != nil {
h.Printf("Instance (%v, %v, %v) already exists, but error getting its certificate: %v", h.logger.Printf("Instance (%v, %v, %v) already exists, but error getting its certificate: %v",
depl.Conf.Project, depl.Conf.Name, depl.Conf.Zone, err) depl.Conf.Project, depl.Conf.Name, depl.Conf.Zone, err)
h.serveError(w, h.serveErrorPage(w,
fmt.Errorf("Instance already running at %v. You need to manually delete the old one before creating a new one.", addr(inst)), fmt.Errorf("Instance already running at %v. You need to manually delete the old one before creating a new one.", addr(inst)),
helpDeleteInstance, helpDeleteInstance,
) )
@ -487,15 +488,15 @@ func (h *DeployHandler) serveOldInstance(w http.ResponseWriter, br blob.Ref, dep
} }
} }
if password != depl.Conf.Password { if password != depl.Conf.Password {
h.Printf("Instance (%v, %v, %v) already exists, but with different password: %v", h.logger.Printf("Instance (%v, %v, %v) already exists, but with different password: %v",
depl.Conf.Project, depl.Conf.Name, depl.Conf.Zone, password) depl.Conf.Project, depl.Conf.Name, depl.Conf.Zone, password)
h.serveError(w, h.serveErrorPage(w,
fmt.Errorf("Instance already running at %v. You need to manually delete the old one before creating a new one.", addr(inst)), fmt.Errorf("Instance already running at %v. You need to manually delete the old one before creating a new one.", addr(inst)),
helpDeleteInstance, helpDeleteInstance,
) )
return true return true
} }
h.Printf("Reusing existing instance for (%v, %v, %v)", depl.Conf.Project, depl.Conf.Name, depl.Conf.Zone) h.logger.Printf("Reusing existing instance for (%v, %v, %v)", depl.Conf.Project, depl.Conf.Name, depl.Conf.Zone)
if err := h.recordState(br, &creationState{ if err := h.recordState(br, &creationState{
InstConf: br, InstConf: br,
@ -504,8 +505,8 @@ func (h *DeployHandler) serveOldInstance(w http.ResponseWriter, br blob.Ref, dep
CertFingerprintSHA256: sigs["SHA-256"], CertFingerprintSHA256: sigs["SHA-256"],
Exists: true, Exists: true,
}); err != nil { }); err != nil {
h.Printf("Could not record creation state for %v: %v", br, err) h.logger.Printf("Could not record creation state for %v: %v", br, err)
h.serveError(w, fmt.Errorf("An error occurred while recording the state of your instance. %v", fileIssue(br.String()))) h.serveErrorPage(w, fmt.Errorf("An error occurred while recording the state of your instance. %v", fileIssue(br.String())))
return true return true
} }
h.serveProgress(w, br) h.serveProgress(w, br)
@ -519,7 +520,7 @@ func (h *DeployHandler) serveFormError(w http.ResponseWriter, err error, hints .
for _, v := range hints { for _, v := range hints {
topHints = append(topHints, v) topHints = append(topHints, v)
} }
h.Print(err) h.logger.Print(err)
h.tplMu.RLock() h.tplMu.RLock()
defer h.tplMu.RUnlock() defer h.tplMu.RUnlock()
if tplErr := h.tpl.ExecuteTemplate(w, "withform", &TemplateData{ if tplErr := h.tpl.ExecuteTemplate(w, "withform", &TemplateData{
@ -531,7 +532,7 @@ func (h *DeployHandler) serveFormError(w http.ResponseWriter, err error, hints .
ZoneValues: h.zoneValues(), ZoneValues: h.zoneValues(),
MachineValues: machineValues, MachineValues: machineValues,
}); tplErr != nil { }); tplErr != nil {
h.Printf("Could not serve form error %q because: %v", err, tplErr) h.logger.Printf("Could not serve form error %q because: %v", err, tplErr)
} }
} }
@ -544,7 +545,7 @@ func fileIssue(br string) string {
// serves an error page. If it isn't finished yet, it replies with "running". // serves an error page. If it isn't finished yet, it replies with "running".
func (h *DeployHandler) serveInstanceState(w http.ResponseWriter, r *http.Request) { func (h *DeployHandler) serveInstanceState(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" { if r.Method != "GET" {
httputil.ServeError(w, r, fmt.Errorf("Wrong method: %v", r.Method)) h.serveError(w, r, fmt.Errorf("Wrong method: %v", r.Method))
return return
} }
br := r.URL.Query().Get("instancekey") br := r.URL.Query().Get("instancekey")
@ -555,20 +556,20 @@ func (h *DeployHandler) serveInstanceState(w http.ResponseWriter, r *http.Reques
} }
var state creationState var state creationState
if err := json.Unmarshal([]byte(stateValue), &state); err != nil { if err := json.Unmarshal([]byte(stateValue), &state); err != nil {
httputil.ServeError(w, r, fmt.Errorf("could not json decode instance state: %v", err)) h.serveError(w, r, fmt.Errorf("could not json decode instance state: %v", err))
return return
} }
if state.Err != "" { if state.Err != "" {
// No need to log that error here since we're already doing it in serveCallback // No need to log that error here since we're already doing it in serveCallback
// TODO(mpl): fix overescaping of double quotes. // TODO(mpl): fix overescaping of double quotes.
h.serveError(w, fmt.Errorf("An error occurred while creating your instance: %q. ", state.Err)) h.serveErrorPage(w, fmt.Errorf("An error occurred while creating your instance: %q. ", state.Err))
return return
} }
if state.Success || state.Exists { if state.Success || state.Exists {
conf, err := h.instanceConf(state.InstConf) conf, err := h.instanceConf(state.InstConf)
if err != nil { if err != nil {
h.Printf("Could not get parameters for success message: %v", err) h.logger.Printf("Could not get parameters for success message: %v", err)
h.serveError(w, fmt.Errorf("Your instance was created and should soon be up at https://%s but there might have been a problem in the creation process. %v", state.Err, fileIssue(br))) h.serveErrorPage(w, fmt.Errorf("Your instance was created and should soon be up at https://%s but there might have been a problem in the creation process. %v", state.Err, fileIssue(br)))
return return
} }
h.serveSuccess(w, &TemplateData{ h.serveSuccess(w, &TemplateData{
@ -589,7 +590,7 @@ func (h *DeployHandler) serveInstanceState(w http.ResponseWriter, r *http.Reques
defer h.recordStateErrMu.RUnlock() defer h.recordStateErrMu.RUnlock()
if _, ok := h.recordStateErr[br]; ok { if _, ok := h.recordStateErr[br]; ok {
// No need to log that error here since we're already doing it in serveCallback // No need to log that error here since we're already doing it in serveCallback
h.serveError(w, fmt.Errorf("An error occurred while recording the state of your instance. %v", fileIssue(br))) h.serveErrorPage(w, fmt.Errorf("An error occurred while recording the state of your instance. %v", fileIssue(br)))
return return
} }
fmt.Fprintf(w, "running") fmt.Fprintf(w, "running")
@ -606,16 +607,16 @@ func (h *DeployHandler) serveProgress(w http.ResponseWriter, instanceKey blob.Re
InstanceKey: instanceKey.String(), InstanceKey: instanceKey.String(),
PiggyGIF: h.piggyGIF, PiggyGIF: h.piggyGIF,
}); err != nil { }); err != nil {
h.Printf("Could not serve progress: %v", err) h.logger.Printf("Could not serve progress: %v", err)
} }
} }
func (h *DeployHandler) serveError(w http.ResponseWriter, err error, hints ...string) { func (h *DeployHandler) serveErrorPage(w http.ResponseWriter, err error, hints ...string) {
var topHints []string var topHints []string
for _, v := range hints { for _, v := range hints {
topHints = append(topHints, v) topHints = append(topHints, v)
} }
h.Print(err) h.logger.Print(err)
h.tplMu.RLock() h.tplMu.RLock()
defer h.tplMu.RUnlock() defer h.tplMu.RUnlock()
if tplErr := h.tpl.ExecuteTemplate(w, "noform", &TemplateData{ if tplErr := h.tpl.ExecuteTemplate(w, "noform", &TemplateData{
@ -623,7 +624,7 @@ func (h *DeployHandler) serveError(w http.ResponseWriter, err error, hints ...st
Err: err, Err: err,
Hints: topHints, Hints: topHints,
}); tplErr != nil { }); tplErr != nil {
h.Printf("Could not serve error %q because: %v", err, tplErr) h.logger.Printf("Could not serve error %q because: %v", err, tplErr)
} }
} }
@ -631,7 +632,7 @@ func (h *DeployHandler) serveSuccess(w http.ResponseWriter, data *TemplateData)
h.tplMu.RLock() h.tplMu.RLock()
defer h.tplMu.RUnlock() defer h.tplMu.RUnlock()
if err := h.tpl.ExecuteTemplate(w, "noform", data); err != nil { if err := h.tpl.ExecuteTemplate(w, "noform", data); err != nil {
h.Printf("Could not serve success: %v", err) h.logger.Printf("Could not serve success: %v", err)
} }
} }
@ -692,8 +693,15 @@ func (h *DeployHandler) randomZone(region string) string {
return region + zones[rand.Intn(len(zones))] return region + zones[rand.Intn(len(zones))]
} }
func (h *DeployHandler) SetLogger(logger *log.Logger) { func (h *DeployHandler) SetLogger(lg *log.Logger) {
h.Logger = logger h.logger = lg
}
func (h *DeployHandler) serveError(w http.ResponseWriter, r *http.Request, err error) {
if h.logger != nil {
h.logger.Printf("%v", err)
}
httputil.ServeError(w, r, err)
} }
func (h *DeployHandler) oAuthConfig() *oauth2.Config { func (h *DeployHandler) oAuthConfig() *oauth2.Config {

View File

@ -397,9 +397,17 @@ func gceDeployHandlerConfig() (*gce.Config, error) {
// If a launcher isn't enabled, gceDeployHandler returns nil. If another error occurs, // If a launcher isn't enabled, gceDeployHandler returns nil. If another error occurs,
// log.Fatal is called. // log.Fatal is called.
func gceDeployHandler(prefix string) http.Handler { func gceDeployHandler(prefix string) http.Handler {
hostPort, err := netutil.HostPort("https://" + *httpsAddr) var hostPort string
if err != nil { var err error
if inProd {
hostPort = "camlistore.org:443" hostPort = "camlistore.org:443"
} else {
hostPort, err = netutil.HostPort("https://" + *httpsAddr)
if err != nil {
// The deploy handler unfortunately needs to know its own host because of the oauth2 callback
log.Print("Starting without a GCE deploy handler because we need -https host:port")
return nil
}
} }
config, err := gceDeployHandlerConfig() config, err := gceDeployHandlerConfig()
if config == nil { if config == nil {
@ -626,9 +634,11 @@ func main() {
mux.Handle(bbhpattern, buildbotHandler) mux.Handle(bbhpattern, buildbotHandler)
} }
var gceLauncher *gce.DeployHandler
if *httpsAddr != "" { if *httpsAddr != "" {
if launcher := gceDeployHandler("/launch/"); launcher != nil { if launcher := gceDeployHandler("/launch/"); launcher != nil {
mux.Handle("/launch/", launcher) mux.Handle("/launch/", launcher)
gceLauncher = launcher.(*gce.DeployHandler)
} }
} }
@ -675,6 +685,19 @@ func main() {
log.Fatalf("Failed to ping Google Cloud Logging: %v", err) log.Fatalf("Failed to ping Google Cloud Logging: %v", err)
} }
handler = NewLoggingHandler(handler, gceLogger{logc}) handler = NewLoggingHandler(handler, gceLogger{logc})
if gceLauncher != nil {
ctx := cloud.NewContext(projID, hc)
logc, err := logging.NewClient(ctx, projID, *gceLogName)
if err != nil {
log.Fatal(err)
}
logc.CommonLabels = map[string]string{
"from": "camli-gce-launcher",
}
logger := logc.Logger(logging.Default)
logger.SetPrefix("launcher: ")
gceLauncher.SetLogger(logger)
}
} }
errc := make(chan error) errc := make(chan error)