Skip to content

Commit

Permalink
Modify handleRerun to support both rerunning from the command line an…
Browse files Browse the repository at this point in the history
…d rerunning directly
  • Loading branch information
mirandachrist committed Jun 28, 2019
1 parent 8428606 commit 2f931c6
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 34 deletions.
1 change: 1 addition & 0 deletions prow/cmd/deck/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ go_library(
"//prow/errorutil:go_default_library",
"//prow/flagutil:go_default_library",
"//prow/gcsupload:go_default_library",
"//prow/github:go_default_library",
"//prow/githuboauth:go_default_library",
"//prow/kube:go_default_library",
"//prow/logrusutil:go_default_library",
Expand Down
67 changes: 37 additions & 30 deletions prow/cmd/deck/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import (
"k8s.io/test-infra/prow/config"
"k8s.io/test-infra/prow/deck/jobs"
prowflagutil "k8s.io/test-infra/prow/flagutil"
prowgithub "k8s.io/test-infra/prow/github"
"k8s.io/test-infra/prow/githuboauth"
"k8s.io/test-infra/prow/kube"
"k8s.io/test-infra/prow/logrusutil"
Expand Down Expand Up @@ -1151,20 +1152,34 @@ func handleProwJob(prowJobClient prowv1.ProwJobInterface) http.HandlerFunc {
}

// canTriggerJob determines whether the given user can trigger any job.
func canTriggerJob(user string, cfg config.Getter) bool {
if cfg().Deck.RerunAuthConfig.AllowAnyone {
func canTriggerJob(user string, cfg config.RerunAuthConfig) bool {
if cfg.AllowAnyone {
return true
}
if cfg().Deck.RerunAuthConfig.AuthorizedUsers != nil {
for _, s := range cfg().Deck.RerunAuthConfig.AuthorizedUsers {
if user == s {
return true
}
for _, s := range cfg.AuthorizedUsers {
if prowgithub.NormLogin(user) == prowgithub.NormLogin(s) {
return true
}
}
return false
}

func marshalJob(w http.ResponseWriter, pj prowapi.ProwJob) {
b, err := yaml.Marshal(&pj)
if err != nil {
http.Error(w, fmt.Sprintf("Error marshaling: %v", err), http.StatusInternalServerError)
logrus.WithError(err).Error("Error marshaling job.")
return
}
w.Header().Set("Content-Type", "application/json")
if _, err := w.Write(b); err != nil {
logrus.WithError(err).Error("Error writing log.")
}
}

// handleRerun triggers a rerun of the given job if that features is enabled, it receives a
// POST request, and the user has the necessary permissions. Otherwise, it writes the config
// for a new job but does not trigger it.
func handleRerun(prowJobClient prowv1.ProwJobInterface, createProwJob bool, cfg config.Getter) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("prowjob")
Expand All @@ -1187,41 +1202,33 @@ func handleRerun(prowJobClient prowv1.ProwJobInterface, createProwJob bool, cfg
// On Prow instances that require auth even for viewing Deck this is okayish, because the Prowjob UUID
// is hard to guess
// Ref: https://github.com/kubernetes/test-infra/pull/12827#issuecomment-502850414
if createProwJob {
if r.Method != http.MethodPost {
http.Error(w, "request must be of type POST", http.StatusMethodNotAllowed)
if r.Method == http.MethodPost {
if !createProwJob {
http.Error(w, "Direct rerun feature is not yet enabled", http.StatusMethodNotAllowed)
return
}
githubCookie, err := r.Cookie("github_login")
login, err := r.Cookie("github_login")
if err == http.ErrNoCookie {
http.Redirect(w, r, "/github-login", http.StatusFound)
http.Redirect(w, r, "/github-login?dest=%2F?rerun=work_in_progress", http.StatusFound)
return
} else if err != nil {
http.Error(w, fmt.Sprintf("Error retrieving GitHub cookie: %v", err), http.StatusInternalServerError)
logrus.WithError(err).Errorf("Error retrieving GitHub cookie")
return
}
if canTriggerJob(githubCookie.Value, cfg) {
if _, err := prowJobClient.Create(&newPJ); err != nil {
logrus.WithError(err).Error("Error creating job")
http.Error(w, fmt.Sprintf("Error creating job: %v", err), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/?rerun=success", http.StatusFound)
if !canTriggerJob(login.Value, cfg().Deck.RerunAuthConfig) {
http.Redirect(w, r, "/?rerun=error", http.StatusFound)
return
} else {
http.Redirect(w, r, "/?rerun=denied", http.StatusFound)
}
if _, err := prowJobClient.Create(&newPJ); err != nil {
logrus.WithError(err).Error("Error creating job")
http.Error(w, fmt.Sprintf("Error creating job: %v", err), http.StatusInternalServerError)
return
}
}
b, err := yaml.Marshal(&newPJ)
if err != nil {
http.Error(w, fmt.Sprintf("Error marshaling: %v", err), http.StatusInternalServerError)
logrus.WithError(err).Error("Error marshaling jobs.")
http.Redirect(w, r, "/?rerun=success", http.StatusFound)
return
}
w.Header().Set("Content-Type", "application/json")
if _, err := w.Write(b); err != nil {
logrus.WithError(err).Error("Error writing log.")
}
marshalJob(w, newPJ)
}
}

Expand Down
18 changes: 16 additions & 2 deletions prow/cmd/deck/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ func TestRerun(t *testing.T) {
rerunCreatesJob bool
shouldCreateProwJob bool
httpCode int
httpMethod string
}{
{
name: "Handler returns ProwJob",
Expand All @@ -271,6 +272,7 @@ func TestRerun(t *testing.T) {
rerunCreatesJob: true,
shouldCreateProwJob: true,
httpCode: http.StatusFound,
httpMethod: http.MethodPost,
},
{
name: "User not authorized to create prow job",
Expand All @@ -279,6 +281,7 @@ func TestRerun(t *testing.T) {
rerunCreatesJob: true,
shouldCreateProwJob: false,
httpCode: http.StatusFound,
httpMethod: http.MethodPost,
},
{
name: "RerunCreatesJob set to false, should not create prow job",
Expand All @@ -287,6 +290,7 @@ func TestRerun(t *testing.T) {
rerunCreatesJob: false,
shouldCreateProwJob: false,
httpCode: http.StatusOK,
httpMethod: http.MethodGet,
},
{
name: "Allow anyone set to true, creates job",
Expand All @@ -295,6 +299,16 @@ func TestRerun(t *testing.T) {
rerunCreatesJob: true,
shouldCreateProwJob: true,
httpCode: http.StatusFound,
httpMethod: http.MethodPost,
},
{
name: "Direct rerun disabled, post request",
login: "ugh",
allowAnyone: true,
rerunCreatesJob: false,
shouldCreateProwJob: false,
httpCode: http.StatusMethodNotAllowed,
httpMethod: http.MethodPost,
},
}

Expand Down Expand Up @@ -333,7 +347,7 @@ func TestRerun(t *testing.T) {
}
}
handler := handleRerun(fakeProwJobClient.ProwV1().ProwJobs("prowjobs"), tc.rerunCreatesJob, configGetter)
req, err := http.NewRequest(http.MethodPost, "/rerun?prowjob=wowsuch", nil)
req, err := http.NewRequest(tc.httpMethod, "/rerun?prowjob=wowsuch", nil)
req.AddCookie(&http.Cookie{
Name: "github_login",
Value: tc.login,
Expand All @@ -359,7 +373,7 @@ func TestRerun(t *testing.T) {
t.Errorf("expected to get two prowjobs, got %d", numPJs)
}

} else if !tc.rerunCreatesJob {
} else if !tc.rerunCreatesJob && tc.httpCode == http.StatusOK {
resp := rr.Result()
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
Expand Down
4 changes: 2 additions & 2 deletions prow/cmd/deck/static/prow/prow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -650,12 +650,12 @@ function redraw(fz: FuzzySearch): void {
max = 2 * 3600;
}
drawJobHistogram(totalJob, jobHistogram, now - (12 * 3600), now, max);
if (rerunStatus === "denied") {
if (rerunStatus === "error") {
modal.style.display = "block";
rerunCommand.innerHTML = `You don't have permission to rerun that job. Try asking @cjwagner.`;
} else if (rerunStatus === "success") {
modal.style.display = "block";
rerunCommand.innerHTML = `Job successfully triggered`;
rerunCommand.innerHTML = `Job successfully triggered. Wait 30 seconds and refresh the page for the job to show up`;
} else if (rerunStatus != null) {
modal.style.display = "block";
rerunCommand.innerHTML = `Nice try! The direct rerun feature hasn't been implemented yet, so that button does nothing.`;
Expand Down

0 comments on commit 2f931c6

Please sign in to comment.