| /* |
| Used by the Leasing Server to send emails. |
| */ |
| |
| package main |
| |
| import ( |
| "fmt" |
| "strings" |
| |
| "go.skia.org/infra/go/email" |
| "go.skia.org/infra/go/httputils" |
| "go.skia.org/infra/go/sklog" |
| ) |
| |
| const ( |
| LEASING_EMAIL_DISPLAY_NAME = "Leasing Server" |
| |
| GMAIL_CACHED_TOKEN = "leasing_gmail_cached_token" |
| |
| CONNECTION_INSTRUCTIONS_PAGE = "https://skia.org/dev/testing/swarmingbots#connecting-to-swarming-bots" |
| ) |
| |
| var ( |
| gmail *email.GMail |
| |
| httpClient = httputils.NewTimeoutClient() |
| ) |
| |
| func MailInit(emailClientId, emailClientSecret, tokenFile string) error { |
| var err error |
| gmail, err = email.NewGMail(emailClientId, emailClientSecret, tokenFile) |
| if err != nil { |
| return fmt.Errorf("Could not initialize gmail object: %s", err) |
| } |
| |
| return nil |
| } |
| |
| func getRecipients(taskOwner string) []string { |
| // Figure out the list of recipients. |
| recipients := []string{taskOwner} |
| trooper, err := GetTrooperEmail(httpClient) |
| if err != nil { |
| sklog.Errorf("Could not get trooper email: %s", err) |
| return recipients |
| } |
| // Make sure rmistry@ is included on all emails for now. |
| recipients = append(recipients, "rmistry@google.com") |
| return append(recipients, trooper) |
| } |
| |
| func SendStartEmail(ownerEmail, swarmingServer, swarmingId, swarmingBot, TaskIdForIsolates string, setupDebugger bool) error { |
| sectionAboutIsolates := "" |
| if TaskIdForIsolates != "" { |
| sectionAboutIsolatesTemplate := ` |
| Isolates downloaded from the <a href="%s">specified task</a> will be available on the bot.<br/> |
| See the stdout of your <a href="%s">leasing task</a> for location of the artifacts and the command to run.<br/><br/> |
| ` |
| sectionAboutIsolates = fmt.Sprintf(sectionAboutIsolatesTemplate, GetSwarmingTaskLink(swarmingServer, TaskIdForIsolates), GetSwarmingTaskLink(swarmingServer, swarmingId)) |
| } |
| sectionAboutDebugger := "" |
| if setupDebugger { |
| sectionAboutDebuggerTemplate := ` |
| Add to your .ssh/config the section from <a href="https://docs.google.com/document/d/1zTR1YtrIFBo-fRWgbUgvJNVJ-s_4_sNjTrHIoX2vulo/edit#heading=h.mf3a1j4xx7fx">here</a>.<br/> |
| To use the device's debugger on your machine, setup port forwarding in a terminal with:<br/> |
| ssh -v -N -L 8888:localhost:8888 chrome-bot@%s.r1.sk<br/> |
| Then connect to http://localhost:8888 from your browser.<br/><br/> |
| ` |
| sectionAboutDebugger = fmt.Sprintf(sectionAboutDebuggerTemplate, swarmingBot) |
| } |
| |
| subject := getSubject(ownerEmail, swarmingBot, swarmingId) |
| taskLink := GetSwarmingTaskLink(swarmingServer, swarmingId) |
| bodyTemplate := ` |
| Your <a href="%s">leasing task</a> has been picked up by the swarming bot <a href="%s">%s</a>. |
| <br/><br/> |
| %s |
| %s |
| Please see <a href="%s">this page</a> for instructions on how to connect to the bot. |
| <br/> |
| Contact the CC'ed trooper if you have any questions. |
| <br/><br/> |
| You can expire or extend the lease time <a href="%s">here</a>. |
| <br/> |
| Another email will be sent 15 mins before the lease end time. |
| <br/><br/> |
| Thanks! |
| ` |
| body := fmt.Sprintf(bodyTemplate, taskLink, GetSwarmingBotLink(swarmingServer, swarmingBot), swarmingBot, sectionAboutDebugger, sectionAboutIsolates, CONNECTION_INSTRUCTIONS_PAGE, fmt.Sprintf("%s%s", PROD_URI, MY_LEASES_URI)) |
| markup, err := getSwarmingLinkMarkup(taskLink) |
| if err != nil { |
| return fmt.Errorf("Failed to get view action markup: %s", err) |
| } |
| if err := gmail.SendWithMarkup(LEASING_EMAIL_DISPLAY_NAME, getRecipients(ownerEmail), subject, body, markup); err != nil { |
| return fmt.Errorf("Could not send start email: %s", err) |
| } |
| return nil |
| } |
| |
| func SendWarningEmail(ownerEmail, swarmingServer, swarmingId, swarmingBot string) error { |
| subject := getSubject(ownerEmail, swarmingBot, swarmingId) |
| taskLink := GetSwarmingTaskLink(swarmingServer, swarmingId) |
| bodyTemplate := ` |
| Your <a href="%s">leasing task</a> has less than 15 mins remaining. |
| <br/><br/> |
| You can expire or extend the lease time <a href="%s">here</a>. |
| <br/><br/> |
| Thanks! |
| ` |
| body := fmt.Sprintf(bodyTemplate, taskLink, fmt.Sprintf("%s%s", PROD_URI, MY_LEASES_URI)) |
| markup, err := getSwarmingLinkMarkup(taskLink) |
| if err != nil { |
| return fmt.Errorf("Failed to get view action markup: %s", err) |
| } |
| if err := gmail.SendWithMarkup(LEASING_EMAIL_DISPLAY_NAME, getRecipients(ownerEmail), subject, body, markup); err != nil { |
| return fmt.Errorf("Could not send warning email: %s", err) |
| } |
| return nil |
| } |
| |
| func SendFailureEmail(ownerEmail, swarmingServer, swarmingId, swarmingBot, swarmingTaskState string) error { |
| subject := getSubject(ownerEmail, swarmingBot, swarmingId) |
| taskLink := GetSwarmingTaskLink(swarmingServer, swarmingId) |
| bodyTemplate := ` |
| Your <a href="%s">leasing task</a> unexpectedly ended with the state: %s. |
| <br/><br/> |
| You can reschedule another leasing task <a href="%s">here</a>. |
| <br/> |
| Contact the CC'ed trooper if you have any questions. |
| <br/><br/> |
| Thanks! |
| ` |
| body := fmt.Sprintf(bodyTemplate, taskLink, swarmingTaskState, PROD_URI) |
| markup, err := getSwarmingLinkMarkup(taskLink) |
| if err != nil { |
| return fmt.Errorf("Failed to get view action markup: %s", err) |
| } |
| if err := gmail.SendWithMarkup(LEASING_EMAIL_DISPLAY_NAME, getRecipients(ownerEmail), subject, body, markup); err != nil { |
| return fmt.Errorf("Could not send failure email: %s", err) |
| } |
| return nil |
| } |
| |
| func SendExtensionEmail(ownerEmail, swarmingServer, swarmingId, swarmingBot string, durationHrs int) error { |
| subject := getSubject(ownerEmail, swarmingBot, swarmingId) |
| taskLink := GetSwarmingTaskLink(swarmingServer, swarmingId) |
| bodyTemplate := ` |
| Your <a href="%s">leasing task</a> has been extended by %dhr. |
| <br/><br/> |
| If needed, you can reschedule more leasing tasks <a href="%s">here</a>. |
| <br/><br/> |
| Thanks! |
| ` |
| body := fmt.Sprintf(bodyTemplate, taskLink, durationHrs, PROD_URI) |
| markup, err := getSwarmingLinkMarkup(taskLink) |
| if err != nil { |
| return fmt.Errorf("Failed to get view action markup: %s", err) |
| } |
| if err := gmail.SendWithMarkup(LEASING_EMAIL_DISPLAY_NAME, getRecipients(ownerEmail), subject, body, markup); err != nil { |
| return fmt.Errorf("Could not send completion email: %s", err) |
| } |
| return nil |
| } |
| |
| func SendCompletionEmail(ownerEmail, swarmingServer, swarmingId, swarmingBot string) error { |
| subject := getSubject(ownerEmail, swarmingBot, swarmingId) |
| taskLink := GetSwarmingTaskLink(swarmingServer, swarmingId) |
| bodyTemplate := ` |
| Your <a href="%s">leasing task</a> has completed. |
| <br/><br/> |
| If needed, you can reschedule more leasing tasks <a href="%s">here</a>. |
| <br/><br/> |
| Thanks! |
| ` |
| body := fmt.Sprintf(bodyTemplate, taskLink, PROD_URI) |
| markup, err := getSwarmingLinkMarkup(taskLink) |
| if err != nil { |
| return fmt.Errorf("Failed to get view action markup: %s", err) |
| } |
| if err := gmail.SendWithMarkup(LEASING_EMAIL_DISPLAY_NAME, getRecipients(ownerEmail), subject, body, markup); err != nil { |
| return fmt.Errorf("Could not send completion email: %s", err) |
| } |
| return nil |
| } |
| |
| func getSubject(ownerEmail, swarmingBot, swarmingId string) string { |
| subjectTemplate := "%s's leasing task for %s update (id:%s)" |
| return fmt.Sprintf(subjectTemplate, getUsernameFromEmail(ownerEmail), swarmingBot, swarmingId) |
| |
| } |
| |
| func getSwarmingLinkMarkup(taskLink string) (string, error) { |
| return email.GetViewActionMarkup(taskLink, "View Logs", "Direct link to the swarming task logs") |
| } |
| |
| func getUsernameFromEmail(e string) string { |
| return strings.Split(e, "@")[0] |
| } |