Merge pull request #157 from keel-hq/feature/http-approvals
Feature/http approvalsfeature/updated_gcr_pubsub_chan
commit
638ef933c8
|
@ -5,9 +5,15 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/keel-hq/keel/cache"
|
||||
"github.com/keel-hq/keel/types"
|
||||
)
|
||||
|
||||
type approveRequest struct {
|
||||
Identifier string `json:"identifier"`
|
||||
Voter string `json:"voter"`
|
||||
}
|
||||
|
||||
func (s *TriggerServer) approvalsHandler(resp http.ResponseWriter, req *http.Request) {
|
||||
// unknown lists all
|
||||
approvals, err := s.approvalsManager.List()
|
||||
|
@ -31,6 +37,46 @@ func (s *TriggerServer) approvalsHandler(resp http.ResponseWriter, req *http.Req
|
|||
resp.Write(bts)
|
||||
}
|
||||
|
||||
func (s *TriggerServer) approvalApproveHandler(resp http.ResponseWriter, req *http.Request) {
|
||||
|
||||
var ar approveRequest
|
||||
dec := json.NewDecoder(req.Body)
|
||||
defer req.Body.Close()
|
||||
|
||||
err := dec.Decode(&ar)
|
||||
if err != nil {
|
||||
fmt.Fprintf(resp, "%s", err)
|
||||
resp.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if ar.Identifier == "" {
|
||||
http.Error(resp, "identifier not supplied", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
approval, err := s.approvalsManager.Approve(ar.Identifier, ar.Voter)
|
||||
if err != nil {
|
||||
if err == cache.ErrNotFound {
|
||||
http.Error(resp, fmt.Sprintf("approval '%s' not found", ar.Identifier), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(resp, "%s", err)
|
||||
resp.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
bts, err := json.Marshal(&approval)
|
||||
if err != nil {
|
||||
fmt.Fprintf(resp, "%s", err)
|
||||
resp.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
resp.Write(bts)
|
||||
}
|
||||
|
||||
func (s *TriggerServer) approvalDeleteHandler(resp http.ResponseWriter, req *http.Request) {
|
||||
identifier := getID(req)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
@ -109,5 +110,202 @@ func TestDeleteApproval(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Errorf("expected approval to be deleted")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestApprove(t *testing.T) {
|
||||
fp := &fakeProvider{}
|
||||
mem := memory.NewMemoryCache(100*time.Second, 100*time.Second, 10*time.Second)
|
||||
am := approvals.New(mem, codecs.DefaultSerializer())
|
||||
providers := provider.New([]provider.Provider{fp}, am)
|
||||
srv := NewTriggerServer(&Opts{Providers: providers, ApprovalManager: am})
|
||||
srv.registerRoutes(srv.router)
|
||||
|
||||
err := am.Create(&types.Approval{
|
||||
Identifier: "12345",
|
||||
VotesRequired: 5,
|
||||
NewVersion: "2.0.0",
|
||||
CurrentVersion: "1.0.0",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create approval: %s", err)
|
||||
}
|
||||
|
||||
// listing
|
||||
req, err := http.NewRequest("POST", "/v1/approvals", bytes.NewBufferString(`{"identifier":"12345", "voter": "foo"}`))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create req: %s", err)
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
srv.router.ServeHTTP(rec, req)
|
||||
if rec.Code != 200 {
|
||||
t.Errorf("unexpected status code: %d", rec.Code)
|
||||
|
||||
t.Log(rec.Body.String())
|
||||
}
|
||||
|
||||
approved, err := am.Get("12345")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get approval: %s", err)
|
||||
}
|
||||
|
||||
if approved.VotesReceived != 1 {
|
||||
t.Errorf("expected to find one voter")
|
||||
}
|
||||
|
||||
if approved.Voters[0] != "foo" {
|
||||
t.Errorf("unexpected voter: %s", approved.Voters[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestApproveNotFound(t *testing.T) {
|
||||
fp := &fakeProvider{}
|
||||
mem := memory.NewMemoryCache(100*time.Second, 100*time.Second, 10*time.Second)
|
||||
am := approvals.New(mem, codecs.DefaultSerializer())
|
||||
providers := provider.New([]provider.Provider{fp}, am)
|
||||
srv := NewTriggerServer(&Opts{Providers: providers, ApprovalManager: am})
|
||||
srv.registerRoutes(srv.router)
|
||||
|
||||
// listing
|
||||
req, err := http.NewRequest("POST", "/v1/approvals", bytes.NewBufferString(`{"identifier":"12345", "voter": "foo"}`))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create req: %s", err)
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
srv.router.ServeHTTP(rec, req)
|
||||
if rec.Code != 404 {
|
||||
t.Errorf("unexpected status code: %d", rec.Code)
|
||||
|
||||
t.Log(rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestApproveGarbageRequest(t *testing.T) {
|
||||
fp := &fakeProvider{}
|
||||
mem := memory.NewMemoryCache(100*time.Second, 100*time.Second, 10*time.Second)
|
||||
am := approvals.New(mem, codecs.DefaultSerializer())
|
||||
providers := provider.New([]provider.Provider{fp}, am)
|
||||
srv := NewTriggerServer(&Opts{Providers: providers, ApprovalManager: am})
|
||||
srv.registerRoutes(srv.router)
|
||||
|
||||
// listing
|
||||
req, err := http.NewRequest("POST", "/v1/approvals", bytes.NewBufferString(`{"foo":"bar"}`))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create req: %s", err)
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
srv.router.ServeHTTP(rec, req)
|
||||
if rec.Code != 400 {
|
||||
t.Errorf("unexpected status code: %d", rec.Code)
|
||||
|
||||
t.Log(rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSameVoter(t *testing.T) {
|
||||
fp := &fakeProvider{}
|
||||
mem := memory.NewMemoryCache(100*time.Second, 100*time.Second, 10*time.Second)
|
||||
am := approvals.New(mem, codecs.DefaultSerializer())
|
||||
providers := provider.New([]provider.Provider{fp}, am)
|
||||
srv := NewTriggerServer(&Opts{Providers: providers, ApprovalManager: am})
|
||||
srv.registerRoutes(srv.router)
|
||||
|
||||
err := am.Create(&types.Approval{
|
||||
Identifier: "12345",
|
||||
VotesRequired: 5,
|
||||
NewVersion: "2.0.0",
|
||||
CurrentVersion: "1.0.0",
|
||||
VotesReceived: 1,
|
||||
Voters: []string{"foo"},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create approval: %s", err)
|
||||
}
|
||||
|
||||
// listing
|
||||
req, err := http.NewRequest("POST", "/v1/approvals", bytes.NewBufferString(`{"identifier":"12345", "voter": "foo"}`))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create req: %s", err)
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
srv.router.ServeHTTP(rec, req)
|
||||
if rec.Code != 200 {
|
||||
t.Errorf("unexpected status code: %d", rec.Code)
|
||||
|
||||
t.Log(rec.Body.String())
|
||||
}
|
||||
|
||||
approved, err := am.Get("12345")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get approval: %s", err)
|
||||
}
|
||||
|
||||
if approved.VotesReceived != 1 {
|
||||
t.Errorf("expected to find one voter")
|
||||
}
|
||||
|
||||
if approved.Voters[0] != "foo" {
|
||||
t.Errorf("unexpected voter: %s", approved.Voters[0])
|
||||
}
|
||||
}
|
||||
func TestDifferentVoter(t *testing.T) {
|
||||
fp := &fakeProvider{}
|
||||
mem := memory.NewMemoryCache(100*time.Second, 100*time.Second, 10*time.Second)
|
||||
am := approvals.New(mem, codecs.DefaultSerializer())
|
||||
providers := provider.New([]provider.Provider{fp}, am)
|
||||
srv := NewTriggerServer(&Opts{Providers: providers, ApprovalManager: am})
|
||||
srv.registerRoutes(srv.router)
|
||||
|
||||
err := am.Create(&types.Approval{
|
||||
Identifier: "12345",
|
||||
VotesRequired: 5,
|
||||
NewVersion: "2.0.0",
|
||||
CurrentVersion: "1.0.0",
|
||||
VotesReceived: 1,
|
||||
Voters: []string{"bar"},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create approval: %s", err)
|
||||
}
|
||||
|
||||
// listing
|
||||
req, err := http.NewRequest("POST", "/v1/approvals", bytes.NewBufferString(`{"identifier":"12345", "voter": "foo"}`))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create req: %s", err)
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
srv.router.ServeHTTP(rec, req)
|
||||
if rec.Code != 200 {
|
||||
t.Errorf("unexpected status code: %d", rec.Code)
|
||||
|
||||
t.Log(rec.Body.String())
|
||||
}
|
||||
|
||||
approved, err := am.Get("12345")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get approval: %s", err)
|
||||
}
|
||||
|
||||
if approved.VotesReceived != 2 {
|
||||
t.Errorf("expected to find 2 voters")
|
||||
}
|
||||
|
||||
if approved.Voters[0] != "bar" {
|
||||
t.Errorf("unexpected voter: %s", approved.Voters[0])
|
||||
}
|
||||
if approved.Voters[1] != "foo" {
|
||||
t.Errorf("unexpected voter: %s", approved.Voters[0])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,6 +85,8 @@ func (s *TriggerServer) registerRoutes(mux *mux.Router) {
|
|||
|
||||
// approvals
|
||||
mux.HandleFunc("/v1/approvals", s.approvalsHandler).Methods("GET", "OPTIONS")
|
||||
// approving
|
||||
mux.HandleFunc("/v1/approvals", s.approvalApproveHandler).Methods("POST", "OPTIONS")
|
||||
mux.HandleFunc("/v1/approvals/{id}", s.approvalDeleteHandler).Methods("DELETE", "OPTIONS")
|
||||
|
||||
// native webhooks handler
|
||||
|
|
Loading…
Reference in New Issue