github.com/abayer/test-infra@v0.0.5/mungegithub/mungers/e2e/resolved.go (about)

     1  /*
     2  Copyright 2016 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 e2e
    18  
    19  import (
    20  	"encoding/json"
    21  	"net/http"
    22  	"strconv"
    23  	"sync"
    24  
    25  	cache "k8s.io/test-infra/mungegithub/mungers/flakesync"
    26  
    27  	"github.com/golang/glog"
    28  )
    29  
    30  type resolutionKey struct {
    31  	job    cache.Job
    32  	number cache.Number
    33  }
    34  
    35  // ResolutionTracker provides a place for build cops to say "I've resolved this
    36  // problem" so the merge queue can continue merging.
    37  type ResolutionTracker struct {
    38  	resolved map[resolutionKey]bool
    39  	lock     sync.RWMutex
    40  }
    41  
    42  // NewResolutionTracker constructs an empty resolution tracker. It's the
    43  // caller's responsibility to hook up Get/SetHTTP.
    44  func NewResolutionTracker() *ResolutionTracker {
    45  	return &ResolutionTracker{
    46  		resolved: map[resolutionKey]bool{},
    47  	}
    48  }
    49  
    50  // Resolved returns true if the given build has been manually marked as resolved.
    51  func (r *ResolutionTracker) Resolved(j cache.Job, n cache.Number) bool {
    52  	r.lock.RLock()
    53  	defer r.lock.RUnlock()
    54  	return r.resolved[resolutionKey{j, n}]
    55  }
    56  
    57  func getReqKey(req *http.Request) (key resolutionKey, err error) {
    58  	key.job = cache.Job(req.URL.Query().Get("job"))
    59  	var n int
    60  	n, err = strconv.Atoi(req.URL.Query().Get("number"))
    61  	key.number = cache.Number(n)
    62  	return key, err
    63  }
    64  
    65  func (r *ResolutionTracker) serve(data interface{}, status int, res http.ResponseWriter) {
    66  	res.Header().Set("Content-type", "application/json")
    67  	res.WriteHeader(status)
    68  	if err := json.NewEncoder(res).Encode(data); err != nil {
    69  		glog.Errorf("Couldn't write %#v: %v", data, err)
    70  	}
    71  }
    72  
    73  // ListHTTP returns a list of overrides that have been entered.
    74  func (r *ResolutionTracker) ListHTTP(res http.ResponseWriter, req *http.Request) {
    75  	r.lock.RLock()
    76  	defer r.lock.RUnlock()
    77  	type Entry struct {
    78  		Job      cache.Job
    79  		Number   cache.Number
    80  		Resolved bool
    81  	}
    82  	var list []Entry
    83  	for key, resolved := range r.resolved {
    84  		if !resolved {
    85  			continue
    86  		}
    87  		list = append(list, Entry{
    88  			Job:      key.job,
    89  			Number:   key.number,
    90  			Resolved: true,
    91  		})
    92  	}
    93  	r.serve(struct{ ManualResolutions []Entry }{list}, http.StatusOK, res)
    94  }
    95  
    96  // GetHTTP accepts "job" and "number" query parameters and returns a json blob
    97  // indicating whether the specified build has been marked as resolved.
    98  func (r *ResolutionTracker) GetHTTP(res http.ResponseWriter, req *http.Request) {
    99  	key, err := getReqKey(req)
   100  	if err != nil {
   101  		r.serve(struct{ Error string }{err.Error()}, http.StatusNotAcceptable, res)
   102  		return
   103  	}
   104  	r.lock.RLock()
   105  	defer r.lock.RUnlock()
   106  	r.serveKeyLocked(key, res)
   107  }
   108  
   109  // SetHTTP accepts "job", "number", and "resolved" query parameters. "resolved"
   110  // counts as "true" if not explicitly set to "false". Returns a json blob
   111  // indicating whether the specified build has been marked as resolved.
   112  func (r *ResolutionTracker) SetHTTP(res http.ResponseWriter, req *http.Request) {
   113  	key, err := getReqKey(req)
   114  	if err != nil {
   115  		r.serve(struct{ Error string }{err.Error()}, http.StatusNotAcceptable, res)
   116  		return
   117  	}
   118  	r.lock.Lock()
   119  	defer r.lock.Unlock()
   120  	r.resolved[key] = req.URL.Query().Get("resolved") != "false"
   121  	glog.Infof("Marking manually resolved: %v %v: %v", key.job, key.number, r.resolved[key])
   122  	r.serveKeyLocked(key, res)
   123  }
   124  
   125  func (r *ResolutionTracker) serveKeyLocked(key resolutionKey, res http.ResponseWriter) {
   126  	r.serve(struct {
   127  		Job      string
   128  		Number   int
   129  		Resolved bool
   130  	}{
   131  		string(key.job),
   132  		int(key.number),
   133  		r.resolved[key],
   134  	}, http.StatusOK, res)
   135  }