Change logic behind put post and patch for routes

This commit is contained in:
James Jeffrey
2017-06-30 16:46:03 -07:00
parent ed0b49b706
commit 70eb25c873
4 changed files with 145 additions and 185 deletions

View File

@@ -1,96 +0,0 @@
package server
import (
"context"
"net/http"
"github.com/gin-gonic/gin"
"gitlab-odx.oracle.com/odx/functions/api"
"gitlab-odx.oracle.com/odx/functions/api/models"
"gitlab-odx.oracle.com/odx/functions/api/runner/common"
)
func (s *Server) handleRouteCreate(c *gin.Context) {
ctx := c.MustGet("ctx").(context.Context)
log := common.Logger(ctx)
var wroute models.RouteWrapper
err := c.BindJSON(&wroute)
if err != nil {
log.WithError(err).Debug(models.ErrInvalidJSON)
c.JSON(http.StatusBadRequest, simpleError(models.ErrInvalidJSON))
return
}
if wroute.Route == nil {
log.WithError(err).Debug(models.ErrInvalidJSON)
c.JSON(http.StatusBadRequest, simpleError(models.ErrRoutesMissingNew))
return
}
wroute.Route.AppName = c.MustGet(api.AppName).(string)
wroute.Route.SetDefaults()
if err := wroute.Validate(false); err != nil {
log.WithError(err).Debug(models.ErrRoutesCreate)
c.JSON(http.StatusBadRequest, simpleError(err))
return
}
// err = s.Runner.EnsureImageExists(ctx, &task.Config{
// Image: wroute.Route.Image,
// })
// if err != nil {
// c.JSON(http.StatusBadRequest, simpleError(models.ErrUsableImage))
// return
// }
app, err := s.Datastore.GetApp(ctx, wroute.Route.AppName)
if err != nil && err != models.ErrAppsNotFound {
log.WithError(err).Error(models.ErrAppsGet)
c.JSON(http.StatusInternalServerError, simpleError(models.ErrAppsGet))
return
} else if app == nil {
// Create a new application and add the route to that new application
newapp := &models.App{Name: wroute.Route.AppName}
if err := newapp.Validate(); err != nil {
log.Error(err)
c.JSON(http.StatusInternalServerError, simpleError(err))
return
}
err = s.FireBeforeAppCreate(ctx, newapp)
if err != nil {
log.WithError(err).Error(models.ErrAppsCreate)
c.JSON(http.StatusInternalServerError, simpleError(ErrInternalServerError))
return
}
_, err = s.Datastore.InsertApp(ctx, newapp)
if err != nil {
log.WithError(err).Error(models.ErrRoutesCreate)
c.JSON(http.StatusInternalServerError, simpleError(ErrInternalServerError))
return
}
err = s.FireAfterAppCreate(ctx, newapp)
if err != nil {
log.WithError(err).Error(models.ErrRoutesCreate)
c.JSON(http.StatusInternalServerError, simpleError(ErrInternalServerError))
return
}
}
route, err := s.Datastore.InsertRoute(ctx, wroute.Route)
if err != nil {
handleErrorResponse(c, err)
return
}
s.cacheRefresh(route)
c.JSON(http.StatusOK, routeResponse{"Route successfully created", route})
}

View File

@@ -0,0 +1,132 @@
package server
import (
"context"
"fmt"
"net/http"
"path"
"strings"
"github.com/gin-gonic/gin"
"gitlab-odx.oracle.com/odx/functions/api"
"gitlab-odx.oracle.com/odx/functions/api/models"
"gitlab-odx.oracle.com/odx/functions/api/runner/common"
)
/* handleRouteCreateOrUpdate is used to handle POST PUT and PATCH for routes.
Post will only create route if its not there and create app if its not.
create only
Put will create app if its not there and if route is there update if not it will create new route.
update if exists or create if not exists
Patch will not create app if it does not exist since the route needs to exist as well...
update only
*/
func (s *Server) handleRouteCreateOrUpdate(c *gin.Context) {
ctx := c.MustGet("ctx").(context.Context)
log := common.Logger(ctx)
method := strings.ToLower(c.Request.Method)
switch method {
case "post", "put", "patch":
default:
c.JSON(http.StatusMethodNotAllowed, simpleError(fmt.Errorf(http.StatusText(http.StatusMethodNotAllowed))))
return
}
var wroute models.RouteWrapper
err := c.BindJSON(&wroute)
if err != nil {
log.WithError(err).Debug(models.ErrInvalidJSON)
c.JSON(http.StatusBadRequest, simpleError(models.ErrInvalidJSON))
return
}
if wroute.Route == nil {
log.WithError(err).Debug(models.ErrRoutesMissingNew)
c.JSON(http.StatusBadRequest, simpleError(models.ErrRoutesMissingNew))
return
}
wroute.Route.AppName = c.MustGet(api.AppName).(string)
if method == "put" || method == "patch" {
p := path.Clean(c.MustGet(api.Path).(string))
if wroute.Route.Path != "" && wroute.Route.Path != p {
log.Debug(models.ErrRoutesPathImmutable)
c.JSON(http.StatusBadRequest, simpleError(models.ErrRoutesPathImmutable))
return
}
wroute.Route.Path = p
}
wroute.Route.SetDefaults()
if err = wroute.Validate(method == "post"); err != nil {
log.WithError(err).Debug(models.ErrRoutesCreate)
c.JSON(http.StatusBadRequest, simpleError(err))
return
}
if method == "post" || method == "put" {
app, err := s.Datastore.GetApp(ctx, wroute.Route.AppName)
if err != nil && err != models.ErrAppsNotFound {
log.WithError(err).Error(models.ErrAppsGet)
c.JSON(http.StatusInternalServerError, simpleError(models.ErrAppsGet))
return
} else if app == nil {
// Create a new application and add the route to that new application
newapp := &models.App{Name: wroute.Route.AppName}
if err = newapp.Validate(); err != nil {
log.Error(err)
c.JSON(http.StatusInternalServerError, simpleError(err))
return
}
err = s.FireBeforeAppCreate(ctx, newapp)
if err != nil {
log.WithError(err).Error(models.ErrAppsCreate)
c.JSON(http.StatusInternalServerError, simpleError(ErrInternalServerError))
return
}
_, err = s.Datastore.InsertApp(ctx, newapp)
if err != nil {
log.WithError(err).Error(models.ErrRoutesCreate)
c.JSON(http.StatusInternalServerError, simpleError(ErrInternalServerError))
return
}
err = s.FireAfterAppCreate(ctx, newapp)
if err != nil {
log.WithError(err).Error(models.ErrRoutesCreate)
c.JSON(http.StatusInternalServerError, simpleError(ErrInternalServerError))
return
}
}
}
var route *models.Route
switch method {
case "post":
route, err = s.Datastore.InsertRoute(ctx, wroute.Route)
case "put":
route, err = s.Datastore.UpdateRoute(ctx, wroute.Route)
if err == models.ErrRoutesNotFound {
// try insert then
route, err = s.Datastore.InsertRoute(ctx, wroute.Route)
}
case "patch":
route, err = s.Datastore.UpdateRoute(ctx, wroute.Route)
}
if err != nil {
handleErrorResponse(c, err)
return
}
s.cacheRefresh(route)
c.JSON(http.StatusOK, routeResponse{"Route successfully created", route})
}

View File

@@ -1,77 +0,0 @@
package server
import (
"context"
"net/http"
"path"
"github.com/gin-gonic/gin"
"gitlab-odx.oracle.com/odx/functions/api"
"gitlab-odx.oracle.com/odx/functions/api/models"
"gitlab-odx.oracle.com/odx/functions/api/runner/common"
)
func (s *Server) handleRouteUpdate(c *gin.Context) {
ctx := c.MustGet("ctx").(context.Context)
log := common.Logger(ctx)
var wroute models.RouteWrapper
err := c.BindJSON(&wroute)
if err != nil {
log.WithError(err).Debug(models.ErrInvalidJSON)
c.JSON(http.StatusBadRequest, simpleError(models.ErrInvalidJSON))
return
}
if wroute.Route == nil {
log.Debug(models.ErrRoutesMissingNew)
c.JSON(http.StatusBadRequest, simpleError(models.ErrRoutesMissingNew))
return
}
if wroute.Route.Path != "" {
log.Debug(models.ErrRoutesPathImmutable)
c.JSON(http.StatusBadRequest, simpleError(models.ErrRoutesPathImmutable))
return
}
// fmt.Printf("ROUTE BOUND: %+v", *wroute.Route)
wroute.Route.AppName = c.MustGet(api.AppName).(string)
wroute.Route.Path = path.Clean(c.MustGet(api.Path).(string))
wroute.Route.SetDefaults()
if err := wroute.Validate(true); err != nil {
log.WithError(err).Debug(models.ErrRoutesUpdate)
c.JSON(http.StatusBadRequest, simpleError(err))
return
}
if wroute.Route.Image != "" {
// This was checking that an image exists, but it's too slow of an operation. Checks at runtime now.
// err = s.Runner.EnsureImageExists(ctx, &task.Config{
// Image: wroute.Route.Image,
// })
// if err != nil {
// log.WithError(err).Debug(models.ErrRoutesUpdate)
// c.JSON(http.StatusBadRequest, simpleError(models.ErrUsableImage))
// return
// }
}
route, err := s.Datastore.UpdateRoute(ctx, wroute.Route)
if err == models.ErrRoutesNotFound {
// try insert then
route, err = s.Datastore.InsertRoute(ctx, wroute.Route)
}
if err != nil {
handleErrorResponse(c, err)
return
}
s.cacheRefresh(route)
c.JSON(http.StatusOK, routeResponse{"Route successfully updated", route})
}

View File

@@ -19,30 +19,30 @@ import (
"gitlab-odx.oracle.com/odx/functions/api" "gitlab-odx.oracle.com/odx/functions/api"
"gitlab-odx.oracle.com/odx/functions/api/datastore" "gitlab-odx.oracle.com/odx/functions/api/datastore"
"gitlab-odx.oracle.com/odx/functions/api/id" "gitlab-odx.oracle.com/odx/functions/api/id"
"gitlab-odx.oracle.com/odx/functions/api/logs"
"gitlab-odx.oracle.com/odx/functions/api/models" "gitlab-odx.oracle.com/odx/functions/api/models"
"gitlab-odx.oracle.com/odx/functions/api/mqs" "gitlab-odx.oracle.com/odx/functions/api/mqs"
"gitlab-odx.oracle.com/odx/functions/api/runner" "gitlab-odx.oracle.com/odx/functions/api/runner"
"gitlab-odx.oracle.com/odx/functions/api/runner/common" "gitlab-odx.oracle.com/odx/functions/api/runner/common"
"gitlab-odx.oracle.com/odx/functions/api/server/internal/routecache" "gitlab-odx.oracle.com/odx/functions/api/server/internal/routecache"
"gitlab-odx.oracle.com/odx/functions/api/logs"
) )
const ( const (
EnvLogLevel = "log_level" EnvLogLevel = "log_level"
EnvMQURL = "mq_url" EnvMQURL = "mq_url"
EnvDBURL = "db_url" EnvDBURL = "db_url"
EnvLOGDBURL = "logstore_url" EnvLOGDBURL = "logstore_url"
EnvPort = "port" // be careful, Gin expects this variable to be "port" EnvPort = "port" // be careful, Gin expects this variable to be "port"
EnvAPIURL = "api_url" EnvAPIURL = "api_url"
) )
type Server struct { type Server struct {
Datastore models.Datastore Datastore models.Datastore
Runner *runner.Runner Runner *runner.Runner
Router *gin.Engine Router *gin.Engine
MQ models.MessageQueue MQ models.MessageQueue
Enqueue models.Enqueue Enqueue models.Enqueue
LogDB models.FnLog LogDB models.FnLog
apiURL string apiURL string
@@ -317,9 +317,10 @@ func (s *Server) bindHandlers(ctx context.Context) {
apps := v1.Group("/apps/:app") apps := v1.Group("/apps/:app")
{ {
apps.GET("/routes", s.handleRouteList) apps.GET("/routes", s.handleRouteList)
apps.POST("/routes", s.handleRouteCreate) apps.POST("/routes", s.handleRouteCreateOrUpdate)
apps.GET("/routes/*route", s.handleRouteGet) apps.GET("/routes/*route", s.handleRouteGet)
apps.PATCH("/routes/*route", s.handleRouteUpdate) apps.PATCH("/routes/*route", s.handleRouteCreateOrUpdate)
apps.PUT("/routes/*route", s.handleRouteCreateOrUpdate)
apps.DELETE("/routes/*route", s.handleRouteDelete) apps.DELETE("/routes/*route", s.handleRouteDelete)
apps.GET("/calls/*route", s.handleCallList) apps.GET("/calls/*route", s.handleCallList)
} }
@@ -369,6 +370,6 @@ type fnCallsResponse struct {
} }
type fnCallLogResponse struct { type fnCallLogResponse struct {
Message string `json:"message"` Message string `json:"message"`
Log *models.FnCallLog `json:"log"` Log *models.FnCallLog `json:"log"`
} }