Add annotation to trigger on create if endpoints are enabled (#1177)

* Add annotations for creation of triggers and fns along with the test for them fixes #1178

* Log errors and still return created resource for annotation failures
This commit is contained in:
James Jeffrey
2018-08-21 02:26:36 -07:00
committed by Tom Coupland
parent 24f41c29b2
commit d336035678
4 changed files with 101 additions and 21 deletions

View File

@@ -3,12 +3,14 @@ package server
import (
"net/http"
"github.com/fnproject/fn/api/common"
"github.com/fnproject/fn/api/models"
"github.com/gin-gonic/gin"
)
func (s *Server) handleFnCreate(c *gin.Context) {
ctx := c.Request.Context()
log := common.Logger(ctx)
fn := &models.Fn{}
err := c.BindJSON(fn)
@@ -24,7 +26,22 @@ func (s *Server) handleFnCreate(c *gin.Context) {
fnCreated, err := s.datastore.InsertFn(ctx, fn)
if err != nil {
handleErrorResponse(c, err)
return
}
c.JSON(http.StatusOK, fnCreated)
app, err := s.datastore.GetAppByID(ctx, fnCreated.AppID)
if err != nil {
log.Debugln("Failed to lookup app.")
c.JSON(http.StatusOK, fnCreated)
return
}
fnAnnotated, err := s.fnAnnotator.AnnotateFn(c, app, fnCreated)
if err != nil {
log.Debugln("Failed to annotate fn")
c.JSON(http.StatusOK, fnCreated)
return
}
c.JSON(http.StatusOK, fnAnnotated)
}

View File

@@ -361,29 +361,52 @@ func TestFnGet(t *testing.T) {
func TestFnInvokeEndpointAnnotations(t *testing.T) {
a := &models.App{ID: "app_id", Name: "myapp"}
fn := &models.Fn{ID: "fnid", AppID: a.ID, Name: "fnname"}
fn := &models.Fn{AppID: a.ID, Name: "fnname", Image: "fnproject/image"}
commonDS := datastore.NewMockInit([]*models.App{a}, []*models.Fn{fn})
commonDS := datastore.NewMockInit([]*models.App{a})
srv := testServer(commonDS, &mqs.Mock{}, logs.NewMock(), nil, ServerTypeAPI)
_, rec := routerRequest(t, srv.Router, "GET", "/v2/fns/fnid", bytes.NewBuffer([]byte("")))
if rec.Code != http.StatusOK {
t.Fatalf("expected code %d != 200", rec.Code)
body, err := json.Marshal(fn)
if err != nil {
t.Fatalf("Failed to marshal json to create fn %s", err)
}
var fnGet models.Fn
err := json.NewDecoder(rec.Body).Decode(&fnGet)
_, createFN := routerRequest(t, srv.Router, "POST", "/v2/fns", bytes.NewReader(body))
if createFN.Code != http.StatusOK {
t.Fatalf("expected code %d != 200 %s", createFN.Code, createFN.Body.String())
}
var fnCreate models.Fn
err = json.NewDecoder(createFN.Body).Decode(&fnCreate)
if err != nil {
t.Fatalf("Invalid json from server %s", err)
}
const fnEndpoint = "fnproject.io/fn/invokeEndpoint"
v, err := fnGet.Annotations.GetString(fnEndpoint)
v, err := fnCreate.Annotations.GetString(fnEndpoint)
if err != nil {
t.Errorf("failed to get fn %s", err)
}
if v != "http://127.0.0.1:8080/invoke/"+fnCreate.ID {
t.Errorf("unexpected fn val %s", v)
}
_, rec := routerRequest(t, srv.Router, "GET", "/v2/fns/"+fnCreate.ID, bytes.NewBuffer([]byte("")))
if rec.Code != http.StatusOK {
t.Fatalf("expected code %d != 200", rec.Code)
}
var fnGet models.Fn
err = json.NewDecoder(rec.Body).Decode(&fnGet)
if err != nil {
t.Fatalf("Invalid json from server %s", err)
}
v, err = fnGet.Annotations.GetString(fnEndpoint)
if err != nil {
t.Fatalf("failed to get fn %s", err)
}
if v != "http://127.0.0.1:8080/invoke/fnid" {
if v != "http://127.0.0.1:8080/invoke/"+fnCreate.ID {
t.Errorf("unexpected fn val %s", v)
}
@@ -404,7 +427,7 @@ func TestFnInvokeEndpointAnnotations(t *testing.T) {
}
v, err = resp.Items[0].Annotations.GetString(fnEndpoint)
if v != "http://127.0.0.1:8080/invoke/fnid" {
if v != "http://127.0.0.1:8080/invoke/"+fnCreate.ID {
t.Errorf("unexpected fn val %s", v)
}
}

View File

@@ -1,8 +1,10 @@
package server
import (
"fmt"
"net/http"
"github.com/fnproject/fn/api/common"
"github.com/fnproject/fn/api/models"
"github.com/gin-gonic/gin"
)
@@ -10,6 +12,7 @@ import (
func (s *Server) handleTriggerCreate(c *gin.Context) {
ctx := c.Request.Context()
trigger := &models.Trigger{}
log := common.Logger(ctx)
err := c.BindJSON(trigger)
if err != nil {
@@ -27,5 +30,19 @@ func (s *Server) handleTriggerCreate(c *gin.Context) {
return
}
c.JSON(http.StatusOK, triggerCreated)
app, err := s.datastore.GetAppByID(ctx, triggerCreated.AppID)
if err != nil {
log.Debugln(fmt.Errorf("unexpected error - trigger app not available: %s", err))
c.JSON(http.StatusOK, triggerCreated)
return
}
triggerAnnotated, err := s.triggerAnnotator.AnnotateTrigger(c, app, triggerCreated)
if err != nil {
log.Debugln("Failed to annotate trigger on cration")
c.JSON(http.StatusOK, triggerCreated)
return
}
c.JSON(http.StatusOK, triggerAnnotated)
}

View File

@@ -315,24 +315,47 @@ func TestHTTPTriggerEndpointAnnotations(t *testing.T) {
a := &models.App{ID: "appid", Name: "myapp"}
fn := &models.Fn{ID: "fnid", AppID: a.ID}
fn.SetDefaults()
trig := &models.Trigger{ID: "triggerid", FnID: fn.ID, AppID: a.ID, Type: "http", Source: "/myt"}
commonDS := datastore.NewMockInit([]*models.App{a}, []*models.Fn{fn}, []*models.Trigger{trig})
trig := &models.Trigger{Name: "thetrigger", FnID: fn.ID, AppID: a.ID, Type: "http", Source: "/myt"}
commonDS := datastore.NewMockInit([]*models.App{a}, []*models.Fn{fn})
triggerBody, err := json.Marshal(trig)
if err != nil {
t.Fatalf("Failed to marshal triggerbody: %s", err)
}
srv := testServer(commonDS, &mqs.Mock{}, logs.NewMock(), nil, ServerTypeAPI)
_, rec := routerRequest(t, srv.Router, "GET", "/v2/triggers/triggerid", bytes.NewBuffer([]byte("")))
_, createTrigger := routerRequest(t, srv.Router, "POST", BaseRoute, bytes.NewReader(triggerBody))
if createTrigger.Code != http.StatusOK {
t.Fatalf("expected code %d != 200 %s", createTrigger.Code, createTrigger.Body.String())
}
var triggerCreate models.Trigger
err = json.NewDecoder(createTrigger.Body).Decode(&triggerCreate)
if err != nil {
t.Fatalf("Invalid json from server on trigger create: %s", err)
}
const triggerEndpoint = "fnproject.io/trigger/httpEndpoint"
v, err := triggerCreate.Annotations.GetString(triggerEndpoint)
if err != nil {
t.Fatalf("failed to get trigger %s", err)
}
if v != "http://127.0.0.1:8080/t/myapp/myt" {
t.Errorf("unexpected trigger val %s", v)
}
_, rec := routerRequest(t, srv.Router, "GET", "/v2/triggers/"+triggerCreate.ID, bytes.NewBuffer([]byte("")))
if rec.Code != http.StatusOK {
t.Fatalf("expected code %d != 200", rec.Code)
}
var triggerGet models.Trigger
err := json.NewDecoder(rec.Body).Decode(&triggerGet)
err = json.NewDecoder(rec.Body).Decode(&triggerGet)
if err != nil {
t.Fatalf("Invalid json from server %s", err)
}
const triggerEndpoint = "fnproject.io/trigger/httpEndpoint"
v, err := triggerGet.Annotations.GetString(triggerEndpoint)
v, err = triggerGet.Annotations.GetString(triggerEndpoint)
if err != nil {
t.Fatalf("failed to get trigger %s", err)
}