github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/cmd/deck/abort_test.go (about) 1 /* 2 Copyright 2022 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "context" 21 "fmt" 22 "net/http" 23 "net/http/httptest" 24 "testing" 25 "time" 26 27 "github.com/gorilla/sessions" 28 "github.com/sirupsen/logrus" 29 "golang.org/x/oauth2" 30 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 31 prowapi "sigs.k8s.io/prow/pkg/apis/prowjobs/v1" 32 "sigs.k8s.io/prow/pkg/client/clientset/versioned/fake" 33 "sigs.k8s.io/prow/pkg/github/fakegithub" 34 "sigs.k8s.io/prow/pkg/githuboauth" 35 "sigs.k8s.io/prow/pkg/plugins" 36 ) 37 38 // TestAbort that an aborted job has an updated status and 39 // that permissions were granted appropriately 40 func TestAbort(t *testing.T) { 41 testCases := []struct { 42 name string 43 login string 44 authorized []string 45 allowAnyone bool 46 jobState prowapi.ProwJobState 47 httpCode int 48 httpMethod string 49 }{ 50 { 51 name: "Abort on triggered state", 52 login: "authorized", 53 authorized: []string{"authorized", "alsoauthorized"}, 54 allowAnyone: false, 55 jobState: prowapi.TriggeredState, 56 httpCode: http.StatusOK, 57 httpMethod: http.MethodPost, 58 }, 59 { 60 name: "Abort on pending state", 61 login: "authorized", 62 authorized: []string{"authorized", "alsoauthorized"}, 63 allowAnyone: false, 64 jobState: prowapi.PendingState, 65 httpCode: http.StatusOK, 66 httpMethod: http.MethodPost, 67 }, 68 { 69 name: "Attempt to abort on success state", 70 login: "authorized", 71 authorized: []string{"authorized", "alsoauthorized"}, 72 allowAnyone: false, 73 jobState: prowapi.SuccessState, 74 httpCode: http.StatusBadRequest, 75 httpMethod: http.MethodPost, 76 }, 77 { 78 name: "Attempt to abort on aborted state", 79 login: "authorized", 80 authorized: []string{"authorized", "alsoauthorized"}, 81 allowAnyone: false, 82 jobState: prowapi.AbortedState, 83 httpCode: http.StatusBadRequest, 84 httpMethod: http.MethodPost, 85 }, 86 { 87 name: "User not authorized to abort job", 88 login: "random-dude", 89 authorized: []string{"authorized", "alsoauthorized"}, 90 allowAnyone: false, 91 jobState: prowapi.PendingState, 92 httpCode: http.StatusUnauthorized, 93 httpMethod: http.MethodPost, 94 }, 95 { 96 name: "Allow anyone set to true, abort job", 97 login: "ugh", 98 authorized: []string{"authorized", "alsoauthorized"}, 99 allowAnyone: true, 100 jobState: prowapi.PendingState, 101 httpCode: http.StatusOK, 102 httpMethod: http.MethodPost, 103 }, 104 { 105 name: "User permitted to abort on specific job", 106 login: "authorized", 107 authorized: []string{}, 108 allowAnyone: false, 109 jobState: prowapi.PendingState, 110 httpCode: http.StatusOK, 111 httpMethod: http.MethodPost, 112 }, 113 { 114 name: "User on permitted team", 115 login: "sig-lead", 116 authorized: []string{}, 117 allowAnyone: false, 118 jobState: prowapi.PendingState, 119 httpCode: http.StatusOK, 120 httpMethod: http.MethodPost, 121 }, 122 } 123 124 for _, tc := range testCases { 125 t.Run(tc.name, func(t *testing.T) { 126 fakeProwJobClient := fake.NewSimpleClientset(&prowapi.ProwJob{ 127 ObjectMeta: metav1.ObjectMeta{ 128 Name: "wowsuch", 129 Namespace: "prowjobs", 130 }, 131 Spec: prowapi.ProwJobSpec{ 132 Job: "whoa", 133 Type: prowapi.PresubmitJob, 134 Refs: &prowapi.Refs{ 135 Org: "org", 136 Repo: "repo", 137 Pulls: []prowapi.Pull{ 138 { 139 Number: 1, 140 Author: tc.login, 141 }, 142 }, 143 }, 144 RerunAuthConfig: &prowapi.RerunAuthConfig{ 145 AllowAnyone: false, 146 GitHubUsers: []string{"authorized", "alsoauthorized"}, 147 GitHubTeamIDs: []int{42}, 148 }, 149 }, 150 Status: prowapi.ProwJobStatus{ 151 State: tc.jobState, 152 }, 153 }) 154 authCfgGetter := func(refs *prowapi.ProwJobSpec) *prowapi.RerunAuthConfig { 155 return &prowapi.RerunAuthConfig{ 156 AllowAnyone: tc.allowAnyone, 157 GitHubUsers: tc.authorized, 158 } 159 } 160 161 req, err := http.NewRequest(tc.httpMethod, "/abort?prowjob=wowsuch", nil) 162 if err != nil { 163 t.Fatalf("Error making request: %v", err) 164 } 165 req.AddCookie(&http.Cookie{ 166 Name: "github_login", 167 Value: tc.login, 168 Path: "/", 169 Expires: time.Now().Add(time.Hour * 24 * 30), 170 Secure: true, 171 }) 172 mockCookieStore := sessions.NewCookieStore([]byte("secret-key")) 173 session, err := sessions.GetRegistry(req).Get(mockCookieStore, "access-token-session") 174 if err != nil { 175 t.Fatalf("Error making access token session: %v", err) 176 } 177 session.Values["access-token"] = &oauth2.Token{AccessToken: "validtoken"} 178 179 rr := httptest.NewRecorder() 180 mockConfig := &githuboauth.Config{ 181 CookieStore: mockCookieStore, 182 } 183 goa := githuboauth.NewAgent(mockConfig, &logrus.Entry{}) 184 ghc := &fakeAuthenticatedUserIdentifier{login: tc.login} 185 rc := fakegithub.NewFakeClient() 186 rc.OrgMembers = map[string][]string{"org": {"org-member"}} 187 pca := plugins.NewFakeConfigAgent() 188 handler := handleAbort(fakeProwJobClient.ProwV1().ProwJobs("prowjobs"), authCfgGetter, goa, ghc, rc, &pca, logrus.WithField("handler", "/abort")) 189 handler.ServeHTTP(rr, req) 190 if rr.Code != tc.httpCode { 191 t.Fatalf("Bad error code: %d", rr.Code) 192 } 193 194 if tc.httpCode == http.StatusOK { 195 pj, err := fakeProwJobClient.ProwV1().ProwJobs("prowjobs").Get(context.TODO(), "wowsuch", metav1.GetOptions{}) 196 if err != nil { 197 t.Fatalf("Job not found: %v", err) 198 } 199 if pj.Status.State != prowapi.AbortedState { 200 t.Errorf("Wrong state, expected \"%v\", got \"%v\"", prowapi.AbortedState, pj.Status.State) 201 } 202 if pj.Complete() { 203 t.Errorf("Did not expect to be complete, expected \"%v\", got \"%v\"", !pj.Complete(), pj.Complete()) 204 } 205 expectedDescription := fmt.Sprintf("%v successfully aborted wowsuch.", tc.login) 206 if tc.allowAnyone { 207 expectedDescription = "Successfully aborted wowsuch." 208 } 209 if pj.Status.Description != expectedDescription { 210 t.Errorf("Wrong description, expected \"%v\", got \"%v\"", expectedDescription, pj.Status.Description) 211 } 212 } 213 }) 214 } 215 }