mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Merge branch 'mask-errors' into 'master'
mask errors in api response, log real error See merge request !108
This commit is contained in:
@@ -420,7 +420,7 @@ func (ds *sqlStore) RemoveRoute(ctx context.Context, appName, routePath string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return models.ErrRoutesRemoving
|
return models.ErrRoutesNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -1,46 +1,15 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Apps []*App
|
type Apps []*App
|
||||||
type Tasks []*Task
|
type Tasks []*Task
|
||||||
type FnCalls []*FnCall
|
type FnCalls []*FnCall
|
||||||
|
|
||||||
var (
|
|
||||||
ErrAppsAlreadyExists = errors.New("App already exists")
|
|
||||||
ErrAppsCreate = errors.New("Could not create app")
|
|
||||||
ErrAppsGet = errors.New("Could not get app from datastore")
|
|
||||||
ErrAppsList = errors.New("Could not list apps from datastore")
|
|
||||||
ErrAppsMissingNew = errors.New("Missing new application")
|
|
||||||
ErrAppsNameImmutable = errors.New("Could not update app - name is immutable")
|
|
||||||
ErrAppsNotFound = errors.New("App not found")
|
|
||||||
ErrAppsNothingToUpdate = errors.New("Nothing to update")
|
|
||||||
ErrAppsRemoving = errors.New("Could not remove app from datastore")
|
|
||||||
ErrAppsUpdate = errors.New("Could not update app")
|
|
||||||
ErrDeleteAppsWithRoutes = errors.New("Cannot remove apps with routes")
|
|
||||||
ErrUsableImage = errors.New("Image not found")
|
|
||||||
ErrTaskInvalidAppAndRoute = errors.New("Unable to get call for given app and route")
|
|
||||||
)
|
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Routes Routes `json:"routes,omitempty"`
|
Routes Routes `json:"routes,omitempty"`
|
||||||
Config `json:"config"`
|
Config `json:"config"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
maxAppName = 30
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrAppsValidationMissingName = errors.New("Missing app name")
|
|
||||||
ErrAppsValidationTooLongName = fmt.Errorf("App name must be %v characters or less", maxAppName)
|
|
||||||
ErrAppsValidationInvalidName = errors.New("Invalid app name")
|
|
||||||
)
|
|
||||||
|
|
||||||
func (a *App) Validate() error {
|
func (a *App) Validate() error {
|
||||||
if a.Name == "" {
|
if a.Name == "" {
|
||||||
return ErrAppsValidationMissingName
|
return ErrAppsValidationMissingName
|
||||||
|
|||||||
@@ -1,27 +1,12 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "github.com/go-openapi/errors"
|
|
||||||
|
|
||||||
type AppWrapper struct {
|
type AppWrapper struct {
|
||||||
App *App `json:"app"`
|
App *App `json:"app"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AppWrapper) Validate() error {
|
func (m *AppWrapper) Validate() error { return m.validateApp() }
|
||||||
var res []error
|
|
||||||
|
|
||||||
if err := m.validateApp(); err != nil {
|
|
||||||
// prop
|
|
||||||
res = append(res, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(res) > 0 {
|
|
||||||
return errors.CompositeValidationError(res...)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *AppWrapper) validateApp() error {
|
func (m *AppWrapper) validateApp() error {
|
||||||
|
|
||||||
if m.App != nil {
|
if m.App != nil {
|
||||||
if err := m.App.Validate(); err != nil {
|
if err := m.App.Validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ package models
|
|||||||
|
|
||||||
import "github.com/go-openapi/strfmt"
|
import "github.com/go-openapi/strfmt"
|
||||||
|
|
||||||
// This file was generated by the swagger tool.
|
|
||||||
// Editing this file might prove futile when you re-run the swagger generate command
|
|
||||||
|
|
||||||
/*Complete complete
|
/*Complete complete
|
||||||
|
|
||||||
swagger:model Complete
|
swagger:model Complete
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
)
|
)
|
||||||
@@ -47,8 +46,7 @@ type Datastore interface {
|
|||||||
|
|
||||||
// InsertRoute inserts a route. Returns ErrDatastoreEmptyRoute when route is nil, and ErrDatastoreEmptyAppName
|
// InsertRoute inserts a route. Returns ErrDatastoreEmptyRoute when route is nil, and ErrDatastoreEmptyAppName
|
||||||
// or ErrDatastoreEmptyRoutePath for empty AppName or Path.
|
// or ErrDatastoreEmptyRoutePath for empty AppName or Path.
|
||||||
// Returns ErrRoutesAlreadyExists if the exact route.Path already exists, or ErrRoutesCreate if a conflicting
|
// Returns ErrRoutesAlreadyExists if the exact route.Path already exists
|
||||||
// route already exists.
|
|
||||||
InsertRoute(ctx context.Context, route *Route) (*Route, error)
|
InsertRoute(ctx context.Context, route *Route) (*Route, error)
|
||||||
|
|
||||||
// UpdateRoute updates route's Config and Header fields. Returns ErrDatastoreEmptyRoute when route is nil, and
|
// UpdateRoute updates route's Config and Header fields. Returns ErrDatastoreEmptyRoute when route is nil, and
|
||||||
@@ -70,12 +68,3 @@ type Datastore interface {
|
|||||||
// GetDatabase returns the underlying sqlx database implementation
|
// GetDatabase returns the underlying sqlx database implementation
|
||||||
GetDatabase() *sqlx.DB
|
GetDatabase() *sqlx.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
ErrDatastoreEmptyAppName = errors.New("Missing app name")
|
|
||||||
ErrDatastoreEmptyRoutePath = errors.New("Missing route name")
|
|
||||||
ErrDatastoreEmptyApp = errors.New("Missing app")
|
|
||||||
ErrDatastoreEmptyRoute = errors.New("Missing route")
|
|
||||||
ErrDatastoreEmptyKey = errors.New("Missing key")
|
|
||||||
ErrDatastoreEmptyTaskID = errors.New("Missing task ID")
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,7 +1,182 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO we can put constants all in this file too
|
||||||
|
const (
|
||||||
|
maxAppName = 30
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidJSON = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Invalid JSON"),
|
||||||
|
}
|
||||||
|
ErrRunnerTimeout = err{
|
||||||
|
code: http.StatusGatewayTimeout,
|
||||||
|
error: errors.New("Timed out"),
|
||||||
|
}
|
||||||
|
ErrRunnerRouteNotFound = err{
|
||||||
|
code: http.StatusNotFound,
|
||||||
|
error: errors.New("Route not found on that application"),
|
||||||
|
}
|
||||||
|
ErrAppsValidationMissingName = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing app name"),
|
||||||
|
}
|
||||||
|
ErrAppsValidationTooLongName = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: fmt.Errorf("App name must be %v characters or less", maxAppName),
|
||||||
|
}
|
||||||
|
ErrAppsValidationInvalidName = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Invalid app name"),
|
||||||
|
}
|
||||||
|
ErrAppsAlreadyExists = err{
|
||||||
|
code: http.StatusConflict,
|
||||||
|
error: errors.New("App already exists"),
|
||||||
|
}
|
||||||
|
ErrAppsMissingNew = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing new application"),
|
||||||
|
}
|
||||||
|
ErrAppsNameImmutable = err{
|
||||||
|
code: http.StatusConflict,
|
||||||
|
error: errors.New("Could not update app - name is immutable"),
|
||||||
|
}
|
||||||
|
ErrAppsNotFound = err{
|
||||||
|
code: http.StatusNotFound,
|
||||||
|
error: errors.New("App not found"),
|
||||||
|
}
|
||||||
|
ErrDeleteAppsWithRoutes = err{
|
||||||
|
code: http.StatusConflict,
|
||||||
|
error: errors.New("Cannot remove apps with routes"),
|
||||||
|
}
|
||||||
|
ErrDatastoreEmptyAppName = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing app name"),
|
||||||
|
}
|
||||||
|
ErrDatastoreEmptyRoutePath = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing route name"),
|
||||||
|
}
|
||||||
|
ErrDatastoreEmptyApp = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing app"),
|
||||||
|
}
|
||||||
|
ErrDatastoreEmptyRoute = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing route"),
|
||||||
|
}
|
||||||
|
ErrDatastoreEmptyKey = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing key"),
|
||||||
|
}
|
||||||
|
ErrDatastoreEmptyTaskID = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing task ID"),
|
||||||
|
}
|
||||||
|
ErrInvalidPayload = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Invalid payload"),
|
||||||
|
}
|
||||||
|
ErrRoutesAlreadyExists = err{
|
||||||
|
code: http.StatusConflict,
|
||||||
|
error: errors.New("Route already exists"),
|
||||||
|
}
|
||||||
|
ErrRoutesMissingNew = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing new route"),
|
||||||
|
}
|
||||||
|
ErrRoutesNotFound = err{
|
||||||
|
code: http.StatusNotFound,
|
||||||
|
error: errors.New("Route not found"),
|
||||||
|
}
|
||||||
|
ErrRoutesPathImmutable = err{
|
||||||
|
code: http.StatusConflict,
|
||||||
|
error: errors.New("Could not update route - path is immutable"),
|
||||||
|
}
|
||||||
|
ErrRoutesValidationFoundDynamicURL = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Dynamic URL is not allowed"),
|
||||||
|
}
|
||||||
|
ErrRoutesValidationInvalidPath = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Invalid Path format"),
|
||||||
|
}
|
||||||
|
ErrRoutesValidationInvalidType = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Invalid route Type"),
|
||||||
|
}
|
||||||
|
ErrRoutesValidationInvalidFormat = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Invalid route Format"),
|
||||||
|
}
|
||||||
|
ErrRoutesValidationMissingAppName = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing route AppName"),
|
||||||
|
}
|
||||||
|
ErrRoutesValidationMissingImage = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing route Image"),
|
||||||
|
}
|
||||||
|
ErrRoutesValidationMissingName = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing route Name"),
|
||||||
|
}
|
||||||
|
ErrRoutesValidationMissingPath = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing route Path"),
|
||||||
|
}
|
||||||
|
ErrRoutesValidationMissingType = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Missing route Type"),
|
||||||
|
}
|
||||||
|
ErrRoutesValidationPathMalformed = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Path malformed"),
|
||||||
|
}
|
||||||
|
ErrRoutesValidationNegativeTimeout = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Negative timeout"),
|
||||||
|
}
|
||||||
|
ErrRoutesValidationNegativeIdleTimeout = err{
|
||||||
|
code: http.StatusBadRequest,
|
||||||
|
error: errors.New("Negative idle timeout"),
|
||||||
|
}
|
||||||
|
ErrNoSpecialHandlerFound = err{
|
||||||
|
code: http.StatusNotFound,
|
||||||
|
error: errors.New("Path not found"),
|
||||||
|
}
|
||||||
|
ErrCallNotFound = err{
|
||||||
|
code: http.StatusNotFound,
|
||||||
|
error: errors.New("Call not found"),
|
||||||
|
}
|
||||||
|
ErrCallLogNotFound = err{
|
||||||
|
code: http.StatusNotFound,
|
||||||
|
error: errors.New("Call log not found"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// any error that implements this interface will return an API response
|
||||||
|
// with the provided status code and error message body
|
||||||
|
type APIError interface {
|
||||||
|
Code() int
|
||||||
|
error
|
||||||
|
}
|
||||||
|
|
||||||
|
type err struct {
|
||||||
|
code int
|
||||||
|
error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e err) Code() int { return e.code }
|
||||||
|
|
||||||
|
// uniform error output
|
||||||
type Error struct {
|
type Error struct {
|
||||||
Error *ErrorBody `json:"error,omitempty"`
|
Error *ErrorBody `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
@@ -9,7 +184,3 @@ type Error struct {
|
|||||||
func (m *Error) Validate() error {
|
func (m *Error) Validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
ErrInvalidJSON = errors.New("Invalid JSON")
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
// This file was generated by the swagger tool.
|
|
||||||
// Editing this file might prove futile when you re-run the swagger generate command
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
strfmt "github.com/go-openapi/strfmt"
|
strfmt "github.com/go-openapi/strfmt"
|
||||||
"github.com/go-openapi/swag"
|
"github.com/go-openapi/swag"
|
||||||
|
|
||||||
"github.com/go-openapi/errors"
|
|
||||||
"github.com/go-openapi/validate"
|
"github.com/go-openapi/validate"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -67,19 +63,7 @@ type IDStatus struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates this Id status
|
// Validate validates this Id status
|
||||||
func (m *IDStatus) Validate(formats strfmt.Registry) error {
|
func (m *IDStatus) Validate(formats strfmt.Registry) error { return m.validateStatus(formats) }
|
||||||
var res []error
|
|
||||||
|
|
||||||
if err := m.validateStatus(formats); err != nil {
|
|
||||||
// prop
|
|
||||||
res = append(res, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(res) > 0 {
|
|
||||||
return errors.CompositeValidationError(res...)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var idStatusTypeStatusPropEnum []interface{}
|
var idStatusTypeStatusPropEnum []interface{}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
// This file was generated by the swagger tool.
|
|
||||||
// Editing this file might prove futile when you re-run the swagger generate command
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
strfmt "github.com/go-openapi/strfmt"
|
strfmt "github.com/go-openapi/strfmt"
|
||||||
|
|
||||||
"github.com/go-openapi/errors"
|
|
||||||
"github.com/go-openapi/validate"
|
"github.com/go-openapi/validate"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -43,15 +39,6 @@ func (m Reason) validateReasonEnum(path, location string, value Reason) error {
|
|||||||
|
|
||||||
// Validate validates this reason
|
// Validate validates this reason
|
||||||
func (m Reason) Validate(formats strfmt.Registry) error {
|
func (m Reason) Validate(formats strfmt.Registry) error {
|
||||||
var res []error
|
|
||||||
|
|
||||||
// value enum
|
// value enum
|
||||||
if err := m.validateReasonEnum("", "body", m); err != nil {
|
return m.validateReasonEnum("", "body", m)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(res) > 0 {
|
|
||||||
return errors.CompositeValidationError(res...)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
apiErrors "github.com/go-openapi/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -15,19 +12,6 @@ const (
|
|||||||
htfnScaleDownTimeout = 30 // seconds
|
htfnScaleDownTimeout = 30 // seconds
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
ErrInvalidPayload = errors.New("Invalid payload")
|
|
||||||
ErrRoutesAlreadyExists = errors.New("Route already exists")
|
|
||||||
ErrRoutesCreate = errors.New("Could not create route")
|
|
||||||
ErrRoutesGet = errors.New("Could not get route from datastore")
|
|
||||||
ErrRoutesList = errors.New("Could not list routes from datastore")
|
|
||||||
ErrRoutesMissingNew = errors.New("Missing new route")
|
|
||||||
ErrRoutesNotFound = errors.New("Route not found")
|
|
||||||
ErrRoutesPathImmutable = errors.New("Could not update route - path is immutable")
|
|
||||||
ErrRoutesRemoving = errors.New("Could not remove route from datastore")
|
|
||||||
ErrRoutesUpdate = errors.New("Could not update route")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Routes []*Route
|
type Routes []*Route
|
||||||
|
|
||||||
type Route struct {
|
type Route struct {
|
||||||
@@ -43,21 +27,6 @@ type Route struct {
|
|||||||
Config `json:"config"`
|
Config `json:"config"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
ErrRoutesValidationFoundDynamicURL = errors.New("Dynamic URL is not allowed")
|
|
||||||
ErrRoutesValidationInvalidPath = errors.New("Invalid Path format")
|
|
||||||
ErrRoutesValidationInvalidType = errors.New("Invalid route Type")
|
|
||||||
ErrRoutesValidationInvalidFormat = errors.New("Invalid route Format")
|
|
||||||
ErrRoutesValidationMissingAppName = errors.New("Missing route AppName")
|
|
||||||
ErrRoutesValidationMissingImage = errors.New("Missing route Image")
|
|
||||||
ErrRoutesValidationMissingName = errors.New("Missing route Name")
|
|
||||||
ErrRoutesValidationMissingPath = errors.New("Missing route Path")
|
|
||||||
ErrRoutesValidationMissingType = errors.New("Missing route Type")
|
|
||||||
ErrRoutesValidationPathMalformed = errors.New("Path malformed")
|
|
||||||
ErrRoutesValidationNegativeTimeout = errors.New("Negative timeout")
|
|
||||||
ErrRoutesValidationNegativeIdleTimeout = errors.New("Negative idle timeout")
|
|
||||||
)
|
|
||||||
|
|
||||||
// SetDefaults sets zeroed field to defaults.
|
// SetDefaults sets zeroed field to defaults.
|
||||||
func (r *Route) SetDefaults() {
|
func (r *Route) SetDefaults() {
|
||||||
if r.Memory == 0 {
|
if r.Memory == 0 {
|
||||||
@@ -90,60 +59,55 @@ func (r *Route) SetDefaults() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates field values, skipping zeroed fields if skipZero is true.
|
// Validate validates field values, skipping zeroed fields if skipZero is true.
|
||||||
|
// it returns the first error, if any.
|
||||||
func (r *Route) Validate(skipZero bool) error {
|
func (r *Route) Validate(skipZero bool) error {
|
||||||
var res []error
|
|
||||||
|
|
||||||
if !skipZero {
|
if !skipZero {
|
||||||
if r.AppName == "" {
|
if r.AppName == "" {
|
||||||
res = append(res, ErrRoutesValidationMissingAppName)
|
return ErrRoutesValidationMissingAppName
|
||||||
}
|
|
||||||
|
|
||||||
if r.Image == "" {
|
|
||||||
res = append(res, ErrRoutesValidationMissingImage)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Path == "" {
|
if r.Path == "" {
|
||||||
res = append(res, ErrRoutesValidationMissingPath)
|
return ErrRoutesValidationMissingPath
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Image == "" {
|
||||||
|
return ErrRoutesValidationMissingImage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !skipZero || r.Path != "" {
|
if !skipZero || r.Path != "" {
|
||||||
u, err := url.Parse(r.Path)
|
u, err := url.Parse(r.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res = append(res, ErrRoutesValidationPathMalformed)
|
return ErrRoutesValidationPathMalformed
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(u.Path, ":") {
|
if strings.Contains(u.Path, ":") {
|
||||||
res = append(res, ErrRoutesValidationFoundDynamicURL)
|
return ErrRoutesValidationFoundDynamicURL
|
||||||
}
|
}
|
||||||
|
|
||||||
if !path.IsAbs(u.Path) {
|
if !path.IsAbs(u.Path) {
|
||||||
res = append(res, ErrRoutesValidationInvalidPath)
|
return ErrRoutesValidationInvalidPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !skipZero || r.Type != "" {
|
if !skipZero || r.Type != "" {
|
||||||
if r.Type != TypeAsync && r.Type != TypeSync {
|
if r.Type != TypeAsync && r.Type != TypeSync {
|
||||||
res = append(res, ErrRoutesValidationInvalidType)
|
return ErrRoutesValidationInvalidType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !skipZero || r.Format != "" {
|
if !skipZero || r.Format != "" {
|
||||||
if r.Format != FormatDefault && r.Format != FormatHTTP {
|
if r.Format != FormatDefault && r.Format != FormatHTTP {
|
||||||
res = append(res, ErrRoutesValidationInvalidFormat)
|
return ErrRoutesValidationInvalidFormat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Timeout < 0 {
|
if r.Timeout < 0 {
|
||||||
res = append(res, ErrRoutesValidationNegativeTimeout)
|
return ErrRoutesValidationNegativeTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.IdleTimeout < 0 {
|
if r.IdleTimeout < 0 {
|
||||||
res = append(res, ErrRoutesValidationNegativeIdleTimeout)
|
return ErrRoutesValidationNegativeIdleTimeout
|
||||||
}
|
|
||||||
|
|
||||||
if len(res) > 0 {
|
|
||||||
return apiErrors.CompositeValidationError(res...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -1,23 +1,10 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "github.com/go-openapi/errors"
|
|
||||||
|
|
||||||
type RouteWrapper struct {
|
type RouteWrapper struct {
|
||||||
Route *Route `json:"route"`
|
Route *Route `json:"route"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *RouteWrapper) Validate(skipZero bool) error {
|
func (m *RouteWrapper) Validate(skipZero bool) error { return m.validateRoute(skipZero) }
|
||||||
var res []error
|
|
||||||
|
|
||||||
if err := m.validateRoute(skipZero); err != nil {
|
|
||||||
res = append(res, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(res) > 0 {
|
|
||||||
return errors.CompositeValidationError(res...)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *RouteWrapper) validateRoute(skipZero bool) error {
|
func (m *RouteWrapper) validateRoute(skipZero bool) error {
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrRunnerRouteNotFound = errors.New("Route not found on that application")
|
|
||||||
ErrRunnerInvalidPayload = errors.New("Invalid payload")
|
|
||||||
ErrRunnerRunRoute = errors.New("Couldn't run this route in the job server")
|
|
||||||
ErrRunnerAPICantConnect = errors.New("Couldn`t connect to the job server API")
|
|
||||||
ErrRunnerAPICreateJob = errors.New("Could not create a job in job server")
|
|
||||||
ErrRunnerInvalidResponse = errors.New("Invalid response")
|
|
||||||
ErrRunnerTimeout = errors.New("Timed out")
|
|
||||||
)
|
|
||||||
@@ -2,9 +2,6 @@ package models
|
|||||||
|
|
||||||
import "github.com/go-openapi/strfmt"
|
import "github.com/go-openapi/strfmt"
|
||||||
|
|
||||||
// This file was generated by the swagger tool.
|
|
||||||
// Editing this file might prove futile when you re-run the swagger generate command
|
|
||||||
|
|
||||||
/*Start start
|
/*Start start
|
||||||
|
|
||||||
swagger:model Start
|
swagger:model Start
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
// This file was generated by the swagger tool.
|
|
||||||
// Editing this file might prove futile when you re-run the swagger generate command
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
apierrors "errors"
|
|
||||||
|
|
||||||
strfmt "github.com/go-openapi/strfmt"
|
strfmt "github.com/go-openapi/strfmt"
|
||||||
|
|
||||||
"github.com/go-openapi/errors"
|
|
||||||
"github.com/go-openapi/validate"
|
"github.com/go-openapi/validate"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,12 +23,6 @@ const (
|
|||||||
FormatHTTP = "http"
|
FormatHTTP = "http"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
ErrCallNotFound = apierrors.New("Call not found")
|
|
||||||
ErrCallLogNotFound = apierrors.New("Call log not found")
|
|
||||||
ErrCallLogRemoving = apierrors.New("Could not remove call log")
|
|
||||||
)
|
|
||||||
|
|
||||||
type FnCall struct {
|
type FnCall struct {
|
||||||
IDStatus
|
IDStatus
|
||||||
CompletedAt strfmt.DateTime `json:"completed_at,omitempty"`
|
CompletedAt strfmt.DateTime `json:"completed_at,omitempty"`
|
||||||
@@ -167,25 +155,18 @@ type Task struct {
|
|||||||
|
|
||||||
// Validate validates this task
|
// Validate validates this task
|
||||||
func (m *Task) Validate(formats strfmt.Registry) error {
|
func (m *Task) Validate(formats strfmt.Registry) error {
|
||||||
var res []error
|
|
||||||
|
|
||||||
// NewTask validations will get generated automatically
|
|
||||||
|
|
||||||
if err := m.IDStatus.Validate(formats); err != nil {
|
if err := m.IDStatus.Validate(formats); err != nil {
|
||||||
res = append(res, err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.validateEnvVars(formats); err != nil {
|
if err := m.validateEnvVars(formats); err != nil {
|
||||||
res = append(res, err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.validateReason(formats); err != nil {
|
if err := m.validateReason(formats); err != nil {
|
||||||
res = append(res, err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(res) > 0 {
|
|
||||||
return errors.CompositeValidationError(res...)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -418,6 +418,10 @@ func (drv *DockerDriver) run(ctx context.Context, container string, task drivers
|
|||||||
|
|
||||||
err = drv.startTask(ctx, container)
|
err = drv.startTask(ctx, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == context.DeadlineExceeded {
|
||||||
|
// if there's just a timeout making the docker calls, rewrite it as such
|
||||||
|
return &runResult{start: start, status: drivers.StatusTimeout}, nil
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,38 +5,32 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gitlab-odx.oracle.com/odx/functions/api/models"
|
"gitlab-odx.oracle.com/odx/functions/api/models"
|
||||||
"gitlab-odx.oracle.com/odx/functions/api/runner/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) handleAppCreate(c *gin.Context) {
|
func (s *Server) handleAppCreate(c *gin.Context) {
|
||||||
ctx := c.MustGet("mctx").(MiddlewareContext)
|
ctx := c.MustGet("mctx").(MiddlewareContext)
|
||||||
log := common.Logger(ctx)
|
|
||||||
|
|
||||||
var wapp models.AppWrapper
|
var wapp models.AppWrapper
|
||||||
|
|
||||||
err := c.BindJSON(&wapp)
|
err := c.BindJSON(&wapp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Debug(models.ErrInvalidJSON)
|
handleErrorResponse(c, models.ErrInvalidJSON)
|
||||||
c.JSON(http.StatusBadRequest, simpleError(models.ErrInvalidJSON))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if wapp.App == nil {
|
if wapp.App == nil {
|
||||||
log.Debug(models.ErrAppsMissingNew)
|
handleErrorResponse(c, models.ErrAppsMissingNew)
|
||||||
c.JSON(http.StatusBadRequest, simpleError(models.ErrAppsMissingNew))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := wapp.Validate(); err != nil {
|
if err := wapp.Validate(); err != nil {
|
||||||
log.Error(err)
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusInternalServerError, simpleError(err))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.FireBeforeAppCreate(ctx, wapp.App)
|
err = s.FireBeforeAppCreate(ctx, wapp.App)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error(models.ErrAppsCreate)
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusInternalServerError, simpleError(err))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,8 +42,7 @@ func (s *Server) handleAppCreate(c *gin.Context) {
|
|||||||
|
|
||||||
err = s.FireAfterAppCreate(ctx, wapp.App)
|
err = s.FireAfterAppCreate(ctx, wapp.App)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error(models.ErrAppsCreate)
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusInternalServerError, simpleError(err))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,21 +17,20 @@ func (s *Server) handleAppDelete(c *gin.Context) {
|
|||||||
|
|
||||||
routes, err := s.Datastore.GetRoutesByApp(ctx, app.Name, &models.RouteFilter{})
|
routes, err := s.Datastore.GetRoutesByApp(ctx, app.Name, &models.RouteFilter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error(models.ErrAppsRemoving)
|
log.WithError(err).Error("error getting route in app delete")
|
||||||
c.JSON(http.StatusInternalServerError, simpleError(ErrInternalServerError))
|
handleErrorResponse(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//TODO allow this? #528
|
//TODO allow this? #528
|
||||||
if len(routes) > 0 {
|
if len(routes) > 0 {
|
||||||
log.WithError(err).Debug(models.ErrDeleteAppsWithRoutes)
|
handleErrorResponse(c, models.ErrDeleteAppsWithRoutes)
|
||||||
c.JSON(http.StatusBadRequest, simpleError(models.ErrDeleteAppsWithRoutes))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.FireBeforeAppDelete(ctx, app)
|
err = s.FireBeforeAppDelete(ctx, app)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error(models.ErrAppsRemoving)
|
log.WithError(err).Error("error firing before app delete")
|
||||||
c.JSON(http.StatusInternalServerError, simpleError(ErrInternalServerError))
|
handleErrorResponse(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,8 +48,8 @@ func (s *Server) handleAppDelete(c *gin.Context) {
|
|||||||
|
|
||||||
err = s.FireAfterAppDelete(ctx, app)
|
err = s.FireAfterAppDelete(ctx, app)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error(models.ErrAppsRemoving)
|
log.WithError(err).Error("error firing after app delete")
|
||||||
c.JSON(http.StatusInternalServerError, simpleError(ErrInternalServerError))
|
handleErrorResponse(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,10 +39,10 @@ func TestAppCreate(t *testing.T) {
|
|||||||
{datastore.NewMock(), logs.NewMock(), "/v1/apps", ``, http.StatusBadRequest, models.ErrInvalidJSON},
|
{datastore.NewMock(), logs.NewMock(), "/v1/apps", ``, http.StatusBadRequest, models.ErrInvalidJSON},
|
||||||
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{}`, http.StatusBadRequest, models.ErrAppsMissingNew},
|
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{}`, http.StatusBadRequest, models.ErrAppsMissingNew},
|
||||||
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{ "name": "Test" }`, http.StatusBadRequest, models.ErrAppsMissingNew},
|
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{ "name": "Test" }`, http.StatusBadRequest, models.ErrAppsMissingNew},
|
||||||
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{ "app": { "name": "" } }`, http.StatusInternalServerError, models.ErrAppsValidationMissingName},
|
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{ "app": { "name": "" } }`, http.StatusBadRequest, models.ErrAppsValidationMissingName},
|
||||||
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{ "app": { "name": "1234567890123456789012345678901" } }`, http.StatusInternalServerError, models.ErrAppsValidationTooLongName},
|
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{ "app": { "name": "1234567890123456789012345678901" } }`, http.StatusBadRequest, models.ErrAppsValidationTooLongName},
|
||||||
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{ "app": { "name": "&&%@!#$#@$" } }`, http.StatusInternalServerError, models.ErrAppsValidationInvalidName},
|
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{ "app": { "name": "&&%@!#$#@$" } }`, http.StatusBadRequest, models.ErrAppsValidationInvalidName},
|
||||||
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{ "app": { "name": "&&%@!#$#@$" } }`, http.StatusInternalServerError, models.ErrAppsValidationInvalidName},
|
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{ "app": { "name": "&&%@!#$#@$" } }`, http.StatusBadRequest, models.ErrAppsValidationInvalidName},
|
||||||
|
|
||||||
// success
|
// success
|
||||||
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{ "app": { "name": "teste" } }`, http.StatusOK, nil},
|
{datastore.NewMock(), logs.NewMock(), "/v1/apps", `{ "app": { "name": "teste" } }`, http.StatusOK, nil},
|
||||||
@@ -215,7 +215,7 @@ func TestAppUpdate(t *testing.T) {
|
|||||||
[]*models.App{{
|
[]*models.App{{
|
||||||
Name: "myapp",
|
Name: "myapp",
|
||||||
}}, nil, nil, nil,
|
}}, nil, nil, nil,
|
||||||
), logs.NewMock(), "/v1/apps/myapp", `{ "app": { "name": "othername" } }`, http.StatusBadRequest, nil},
|
), logs.NewMock(), "/v1/apps/myapp", `{ "app": { "name": "othername" } }`, http.StatusConflict, nil},
|
||||||
} {
|
} {
|
||||||
rnr, cancel := testRunner(t)
|
rnr, cancel := testRunner(t)
|
||||||
srv := testServer(test.mock, &mqs.Mock{}, test.logDB, rnr)
|
srv := testServer(test.mock, &mqs.Mock{}, test.logDB, rnr)
|
||||||
|
|||||||
@@ -6,31 +6,26 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gitlab-odx.oracle.com/odx/functions/api"
|
"gitlab-odx.oracle.com/odx/functions/api"
|
||||||
"gitlab-odx.oracle.com/odx/functions/api/models"
|
"gitlab-odx.oracle.com/odx/functions/api/models"
|
||||||
"gitlab-odx.oracle.com/odx/functions/api/runner/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) handleAppUpdate(c *gin.Context) {
|
func (s *Server) handleAppUpdate(c *gin.Context) {
|
||||||
ctx := c.MustGet("mctx").(MiddlewareContext)
|
ctx := c.MustGet("mctx").(MiddlewareContext)
|
||||||
log := common.Logger(ctx)
|
|
||||||
|
|
||||||
wapp := models.AppWrapper{}
|
wapp := models.AppWrapper{}
|
||||||
|
|
||||||
err := c.BindJSON(&wapp)
|
err := c.BindJSON(&wapp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Debug(models.ErrInvalidJSON)
|
handleErrorResponse(c, models.ErrInvalidJSON)
|
||||||
c.JSON(http.StatusBadRequest, simpleError(models.ErrInvalidJSON))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if wapp.App == nil {
|
if wapp.App == nil {
|
||||||
log.Debug(models.ErrAppsMissingNew)
|
handleErrorResponse(c, models.ErrAppsMissingNew)
|
||||||
c.JSON(http.StatusBadRequest, simpleError(models.ErrAppsMissingNew))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if wapp.App.Name != "" {
|
if wapp.App.Name != "" {
|
||||||
log.Debug(models.ErrAppsNameImmutable)
|
handleErrorResponse(c, models.ErrAppsNameImmutable)
|
||||||
c.JSON(http.StatusBadRequest, simpleError(models.ErrAppsNameImmutable))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,8 +33,7 @@ func (s *Server) handleAppUpdate(c *gin.Context) {
|
|||||||
|
|
||||||
err = s.FireAfterAppUpdate(ctx, wapp.App)
|
err = s.FireAfterAppUpdate(ctx, wapp.App)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error(models.ErrAppsUpdate)
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusInternalServerError, simpleError(ErrInternalServerError))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,8 +45,7 @@ func (s *Server) handleAppUpdate(c *gin.Context) {
|
|||||||
|
|
||||||
err = s.FireAfterAppUpdate(ctx, wapp.App)
|
err = s.FireAfterAppUpdate(ctx, wapp.App)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error(models.ErrAppsUpdate)
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusInternalServerError, simpleError(ErrInternalServerError))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,24 +14,24 @@ func (s *Server) handleCallList(c *gin.Context) {
|
|||||||
|
|
||||||
appName, ok := c.MustGet(api.AppName).(string)
|
appName, ok := c.MustGet(api.AppName).(string)
|
||||||
if ok && appName == "" {
|
if ok && appName == "" {
|
||||||
c.JSON(http.StatusBadRequest, models.ErrRoutesValidationMissingAppName)
|
handleErrorResponse(c, models.ErrRoutesValidationMissingAppName)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := s.Datastore.GetApp(c, appName)
|
_, err := s.Datastore.GetApp(c, appName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusNotFound, models.ErrAppsNotFound)
|
handleErrorResponse(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
appRoute, ok := c.MustGet(api.Path).(string)
|
appRoute, ok := c.MustGet(api.Path).(string)
|
||||||
if ok && appRoute == "" {
|
if ok && appRoute == "" {
|
||||||
c.JSON(http.StatusBadRequest, models.ErrRoutesValidationMissingPath)
|
handleErrorResponse(c, models.ErrRoutesValidationMissingPath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = s.Datastore.GetRoute(c, appName, appRoute)
|
_, err = s.Datastore.GetRoute(c, appName, appRoute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusNotFound, models.ErrRoutesNotFound)
|
handleErrorResponse(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,35 +3,31 @@ package server
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"runtime/debug"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gitlab-odx.oracle.com/odx/functions/api/models"
|
"gitlab-odx.oracle.com/odx/functions/api/models"
|
||||||
"gitlab-odx.oracle.com/odx/functions/api/runner/common"
|
"gitlab-odx.oracle.com/odx/functions/api/runner/common"
|
||||||
"net/http"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrInternalServerError = errors.New("Something unexpected happened on the server")
|
var ErrInternalServerError = errors.New("internal server error")
|
||||||
|
|
||||||
func simpleError(err error) *models.Error {
|
func simpleError(err error) *models.Error {
|
||||||
return &models.Error{Error: &models.ErrorBody{Message: err.Error()}}
|
return &models.Error{Error: &models.ErrorBody{Message: err.Error()}}
|
||||||
}
|
}
|
||||||
|
|
||||||
var errStatusCode = map[error]int{
|
|
||||||
models.ErrAppsNotFound: http.StatusNotFound,
|
|
||||||
models.ErrAppsAlreadyExists: http.StatusConflict,
|
|
||||||
models.ErrRoutesNotFound: http.StatusNotFound,
|
|
||||||
models.ErrRoutesAlreadyExists: http.StatusConflict,
|
|
||||||
models.ErrCallNotFound: http.StatusNotFound,
|
|
||||||
models.ErrCallLogNotFound: http.StatusNotFound,
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleErrorResponse(c *gin.Context, err error) {
|
func handleErrorResponse(c *gin.Context, err error) {
|
||||||
ctx := c.MustGet("ctx").(context.Context)
|
ctx := c.MustGet("ctx").(context.Context)
|
||||||
log := common.Logger(ctx)
|
log := common.Logger(ctx)
|
||||||
log.Error(err)
|
|
||||||
|
|
||||||
if code, ok := errStatusCode[err]; ok {
|
if aerr, ok := err.(models.APIError); ok {
|
||||||
c.JSON(code, simpleError(err))
|
log.WithFields(logrus.Fields{"code": aerr.Code()}).WithError(err).Error("api error")
|
||||||
} else {
|
c.JSON(aerr.Code(), simpleError(err))
|
||||||
c.JSON(http.StatusInternalServerError, simpleError(err))
|
} else if err != nil {
|
||||||
|
// get a stack trace so we can trace this error
|
||||||
|
log.WithError(err).WithFields(logrus.Fields{"stack": string(debug.Stack())}).Error("internal server error")
|
||||||
|
c.JSON(http.StatusInternalServerError, simpleError(ErrInternalServerError))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,11 +45,13 @@ func (s *Server) apiAppHandlerWrapperFunc(apiHandler ApiAppHandler) gin.HandlerF
|
|||||||
appName := c.Param(api.CApp)
|
appName := c.Param(api.CApp)
|
||||||
app, err := s.Datastore.GetApp(c.Request.Context(), appName)
|
app, err := s.Datastore.GetApp(c.Request.Context(), appName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
handleErrorResponse(c, err)
|
||||||
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if app == nil {
|
if app == nil {
|
||||||
c.AbortWithStatus(http.StatusNotFound)
|
handleErrorResponse(c, models.ErrAppsNotFound)
|
||||||
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gitlab-odx.oracle.com/odx/functions/api"
|
"gitlab-odx.oracle.com/odx/functions/api"
|
||||||
"gitlab-odx.oracle.com/odx/functions/api/models"
|
"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.
|
/* handleRouteCreateOrUpdate is used to handle POST PUT and PATCH for routes.
|
||||||
@@ -25,23 +24,20 @@ import (
|
|||||||
*/
|
*/
|
||||||
func (s *Server) handleRouteCreateOrUpdate(c *gin.Context) {
|
func (s *Server) handleRouteCreateOrUpdate(c *gin.Context) {
|
||||||
ctx := c.MustGet("mctx").(MiddlewareContext)
|
ctx := c.MustGet("mctx").(MiddlewareContext)
|
||||||
log := common.Logger(ctx)
|
|
||||||
method := strings.ToUpper(c.Request.Method)
|
method := strings.ToUpper(c.Request.Method)
|
||||||
|
|
||||||
var wroute models.RouteWrapper
|
var wroute models.RouteWrapper
|
||||||
|
|
||||||
err, resperr := s.bindAndValidate(ctx, c, method, &wroute)
|
err := s.bindAndValidate(ctx, c, method, &wroute)
|
||||||
if err != nil || resperr != nil {
|
if err != nil {
|
||||||
log.WithError(err).Debug(resperr)
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusBadRequest, simpleError(resperr))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the app if it does not exist.
|
// Create the app if it does not exist.
|
||||||
err, resperr = s.ensureApp(ctx, &wroute, method)
|
err = s.ensureApp(ctx, &wroute, method)
|
||||||
if err != nil || resperr != nil {
|
if err != nil {
|
||||||
log.WithError(err).Debug(resperr)
|
handleErrorResponse(c, err)
|
||||||
handleErrorResponse(c, resperr)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,53 +53,51 @@ func (s *Server) handleRouteCreateOrUpdate(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ensureApp will only execute if it is on post or put. Patch is not allowed to create apps.
|
// ensureApp will only execute if it is on post or put. Patch is not allowed to create apps.
|
||||||
func (s *Server) ensureApp(ctx MiddlewareContext, wroute *models.RouteWrapper, method string) (error, error) {
|
func (s *Server) ensureApp(ctx MiddlewareContext, wroute *models.RouteWrapper, method string) error {
|
||||||
if !(method == http.MethodPost || method == http.MethodPut) {
|
if !(method == http.MethodPost || method == http.MethodPut) {
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
var app *models.App
|
app, err := s.Datastore.GetApp(ctx, wroute.Route.AppName)
|
||||||
var err error
|
|
||||||
app, err = s.Datastore.GetApp(ctx, wroute.Route.AppName)
|
|
||||||
if err != nil && err != models.ErrAppsNotFound {
|
if err != nil && err != models.ErrAppsNotFound {
|
||||||
return err, models.ErrAppsGet
|
return err
|
||||||
} else if app == nil {
|
} else if app == nil {
|
||||||
// Create a new application
|
// Create a new application
|
||||||
newapp := &models.App{Name: wroute.Route.AppName}
|
newapp := &models.App{Name: wroute.Route.AppName}
|
||||||
if err = newapp.Validate(); err != nil {
|
if err = newapp.Validate(); err != nil {
|
||||||
return err, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.FireBeforeAppCreate(ctx, newapp)
|
err = s.FireBeforeAppCreate(ctx, newapp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, models.ErrAppsCreate
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = s.Datastore.InsertApp(ctx, newapp)
|
_, err = s.Datastore.InsertApp(ctx, newapp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, models.ErrAppsCreate
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.FireAfterAppCreate(ctx, newapp)
|
err = s.FireAfterAppCreate(ctx, newapp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, models.ErrAppsCreate
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bindAndValidate binds the RouteWrapper to the json from the request and validates that it is correct.
|
/* bindAndValidate binds the RouteWrapper to the json from the request and validates that it is correct.
|
||||||
If it is a put or patch it makes sure that the path in the url matches the provideed one in the body.
|
If it is a put or patch it makes sure that the path in the url matches the provideed one in the body.
|
||||||
Defaults are set and if patch skipZero is true for validating the RouteWrapper
|
Defaults are set and if patch skipZero is true for validating the RouteWrapper
|
||||||
*/
|
*/
|
||||||
func (s *Server) bindAndValidate(ctx context.Context, c *gin.Context, method string, wroute *models.RouteWrapper) (error, error) {
|
func (s *Server) bindAndValidate(ctx context.Context, c *gin.Context, method string, wroute *models.RouteWrapper) error {
|
||||||
err := c.BindJSON(wroute)
|
err := c.BindJSON(wroute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, models.ErrInvalidJSON
|
return models.ErrInvalidJSON
|
||||||
}
|
}
|
||||||
|
|
||||||
if wroute.Route == nil {
|
if wroute.Route == nil {
|
||||||
return err, models.ErrRoutesMissingNew
|
return models.ErrRoutesMissingNew
|
||||||
}
|
}
|
||||||
wroute.Route.AppName = c.MustGet(api.AppName).(string)
|
wroute.Route.AppName = c.MustGet(api.AppName).(string)
|
||||||
|
|
||||||
@@ -111,17 +105,14 @@ func (s *Server) bindAndValidate(ctx context.Context, c *gin.Context, method str
|
|||||||
p := path.Clean(c.MustGet(api.Path).(string))
|
p := path.Clean(c.MustGet(api.Path).(string))
|
||||||
|
|
||||||
if wroute.Route.Path != "" && wroute.Route.Path != p {
|
if wroute.Route.Path != "" && wroute.Route.Path != p {
|
||||||
return models.ErrRoutesPathImmutable, models.ErrRoutesPathImmutable
|
return models.ErrRoutesPathImmutable
|
||||||
}
|
}
|
||||||
wroute.Route.Path = p
|
wroute.Route.Path = p
|
||||||
}
|
}
|
||||||
|
|
||||||
wroute.Route.SetDefaults()
|
wroute.Route.SetDefaults()
|
||||||
|
|
||||||
if err = wroute.Validate(method == http.MethodPatch); err != nil {
|
return wroute.Validate(method == http.MethodPatch)
|
||||||
return models.ErrRoutesCreate, err
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateOrInsertRoute will either update or insert the route respective the method.
|
// updateOrInsertRoute will either update or insert the route respective the method.
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ func TestRouteCreate(t *testing.T) {
|
|||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPost, "/v1/apps/a/routes", `{ "route": { "path": "/myroute" } }`, http.StatusBadRequest, models.ErrRoutesValidationMissingImage},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPost, "/v1/apps/a/routes", `{ "route": { "path": "/myroute" } }`, http.StatusBadRequest, models.ErrRoutesValidationMissingImage},
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPost, "/v1/apps/a/routes", `{ "route": { "image": "funcy/hello" } }`, http.StatusBadRequest, models.ErrRoutesValidationMissingPath},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPost, "/v1/apps/a/routes", `{ "route": { "image": "funcy/hello" } }`, http.StatusBadRequest, models.ErrRoutesValidationMissingPath},
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPost, "/v1/apps/a/routes", `{ "route": { "image": "funcy/hello", "path": "myroute" } }`, http.StatusBadRequest, models.ErrRoutesValidationInvalidPath},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPost, "/v1/apps/a/routes", `{ "route": { "image": "funcy/hello", "path": "myroute" } }`, http.StatusBadRequest, models.ErrRoutesValidationInvalidPath},
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPost, "/v1/apps/$/routes", `{ "route": { "image": "funcy/hello", "path": "/myroute" } }`, http.StatusInternalServerError, models.ErrAppsValidationInvalidName},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPost, "/v1/apps/$/routes", `{ "route": { "image": "funcy/hello", "path": "/myroute" } }`, http.StatusBadRequest, models.ErrAppsValidationInvalidName},
|
||||||
{datastore.NewMockInit(nil,
|
{datastore.NewMockInit(nil,
|
||||||
[]*models.Route{
|
[]*models.Route{
|
||||||
{
|
{
|
||||||
@@ -84,16 +84,16 @@ func TestRoutePut(t *testing.T) {
|
|||||||
buf := setLogBuffer()
|
buf := setLogBuffer()
|
||||||
|
|
||||||
for i, test := range []routeTestCase{
|
for i, test := range []routeTestCase{
|
||||||
// errors
|
// errors (NOTE: this route doesn't exist yet)
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ }`, http.StatusBadRequest, models.ErrRoutesMissingNew},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ }`, http.StatusBadRequest, models.ErrRoutesMissingNew},
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "path": "/myroute" }`, http.StatusBadRequest, models.ErrRoutesMissingNew},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "path": "/myroute" }`, http.StatusBadRequest, models.ErrRoutesMissingNew},
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { } }`, http.StatusBadRequest, models.ErrRoutesValidationMissingImage},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { } }`, http.StatusBadRequest, models.ErrRoutesValidationMissingImage},
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { "path": "/myroute" } }`, http.StatusBadRequest, models.ErrRoutesValidationMissingImage},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { "path": "/myroute" } }`, http.StatusBadRequest, models.ErrRoutesValidationMissingImage},
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { "image": "funcy/hello", "path": "myroute" } }`, http.StatusBadRequest, models.ErrRoutesPathImmutable},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { "image": "funcy/hello", "path": "myroute" } }`, http.StatusConflict, models.ErrRoutesPathImmutable},
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { "image": "funcy/hello", "path": "diffRoute" } }`, http.StatusBadRequest, models.ErrRoutesPathImmutable},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { "image": "funcy/hello", "path": "diffRoute" } }`, http.StatusConflict, models.ErrRoutesPathImmutable},
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/$/routes/myroute", `{ "route": { "image": "funcy/hello", "path": "/myroute" } }`, http.StatusInternalServerError, models.ErrAppsValidationInvalidName},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/$/routes/myroute", `{ "route": { "image": "funcy/hello", "path": "/myroute" } }`, http.StatusBadRequest, models.ErrAppsValidationInvalidName},
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { "type": "invalid-type" } }`, http.StatusBadRequest, models.ErrRoutesValidationInvalidType},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { "image": "funcy/hello", "path": "/myroute", "type": "invalid-type" } }`, http.StatusBadRequest, models.ErrRoutesValidationInvalidType},
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { "format": "invalid-format" } }`, http.StatusBadRequest, models.ErrRoutesValidationInvalidFormat},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { "image": "funcy/hello", "path": "/myroute", "format": "invalid-format" } }`, http.StatusBadRequest, models.ErrRoutesValidationInvalidFormat},
|
||||||
|
|
||||||
// success
|
// success
|
||||||
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { "image": "funcy/hello", "path": "/myroute" } }`, http.StatusOK, nil},
|
{datastore.NewMock(), logs.NewMock(), http.MethodPut, "/v1/apps/a/routes/myroute", `{ "route": { "image": "funcy/hello", "path": "/myroute" } }`, http.StatusOK, nil},
|
||||||
@@ -259,7 +259,7 @@ func TestRouteUpdate(t *testing.T) {
|
|||||||
Path: "/myroute/do",
|
Path: "/myroute/do",
|
||||||
},
|
},
|
||||||
}, nil, nil,
|
}, nil, nil,
|
||||||
), logs.NewMock(), http.MethodPatch, "/v1/apps/a/routes/myroute/do", `{ "route": { "path": "/otherpath" } }`, http.StatusBadRequest, models.ErrRoutesPathImmutable},
|
), logs.NewMock(), http.MethodPatch, "/v1/apps/a/routes/myroute/do", `{ "route": { "path": "/otherpath" } }`, http.StatusConflict, models.ErrRoutesPathImmutable},
|
||||||
} {
|
} {
|
||||||
test.run(t, i, buf)
|
test.run(t, i, buf)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package server
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -30,7 +29,6 @@ type runnerResponse struct {
|
|||||||
|
|
||||||
func (s *Server) handleSpecial(c *gin.Context) {
|
func (s *Server) handleSpecial(c *gin.Context) {
|
||||||
ctx := c.MustGet("ctx").(context.Context)
|
ctx := c.MustGet("ctx").(context.Context)
|
||||||
log := common.Logger(ctx)
|
|
||||||
|
|
||||||
ctx = context.WithValue(ctx, api.AppName, "")
|
ctx = context.WithValue(ctx, api.AppName, "")
|
||||||
c.Set(api.AppName, "")
|
c.Set(api.AppName, "")
|
||||||
@@ -38,21 +36,15 @@ func (s *Server) handleSpecial(c *gin.Context) {
|
|||||||
c.Set(api.Path, c.Request.URL.Path)
|
c.Set(api.Path, c.Request.URL.Path)
|
||||||
|
|
||||||
ctx, err := s.UseSpecialHandlers(ctx, c.Request, c.Writer)
|
ctx, err := s.UseSpecialHandlers(ctx, c.Request, c.Writer)
|
||||||
if err == ErrNoSpecialHandlerFound {
|
if err != nil {
|
||||||
log.WithError(err).Errorln("Not special handler found")
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusNotFound, http.StatusText(http.StatusNotFound))
|
|
||||||
return
|
|
||||||
} else if err != nil {
|
|
||||||
log.WithError(err).Errorln("Error using special handler!")
|
|
||||||
c.JSON(http.StatusInternalServerError, simpleError(errors.New("Failed to run function")))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Set("ctx", ctx)
|
c.Set("ctx", ctx)
|
||||||
c.Set(api.AppName, ctx.Value(api.AppName).(string))
|
c.Set(api.AppName, ctx.Value(api.AppName).(string))
|
||||||
if c.MustGet(api.AppName).(string) == "" {
|
if c.MustGet(api.AppName).(string) == "" {
|
||||||
log.WithError(err).Errorln("Specialhandler returned empty app name")
|
handleErrorResponse(c, models.ErrRunnerRouteNotFound)
|
||||||
c.JSON(http.StatusBadRequest, simpleError(models.ErrRunnerRouteNotFound))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,23 +102,23 @@ func (s *Server) handleRequest(c *gin.Context, enqueue models.Enqueue) {
|
|||||||
path := reqRoute.Path
|
path := reqRoute.Path
|
||||||
|
|
||||||
app, err := s.Datastore.GetApp(ctx, appName)
|
app, err := s.Datastore.GetApp(ctx, appName)
|
||||||
if err != nil || app == nil {
|
if err != nil {
|
||||||
log.WithError(err).Error(models.ErrAppsNotFound)
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusNotFound, simpleError(models.ErrAppsNotFound))
|
return
|
||||||
|
} else if app == nil {
|
||||||
|
handleErrorResponse(c, models.ErrAppsNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.WithFields(logrus.Fields{"app": appName, "path": path}).Debug("Finding route on datastore")
|
log.WithFields(logrus.Fields{"app": appName, "path": path}).Debug("Finding route on datastore")
|
||||||
routes, err := s.loadroutes(ctx, models.RouteFilter{AppName: appName, Path: path})
|
routes, err := s.loadroutes(ctx, models.RouteFilter{AppName: appName, Path: path})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error(models.ErrRoutesList)
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusInternalServerError, simpleError(models.ErrRoutesList))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(routes) == 0 {
|
if len(routes) == 0 {
|
||||||
log.WithError(err).Error(models.ErrRunnerRouteNotFound)
|
handleErrorResponse(c, models.ErrRunnerRouteNotFound)
|
||||||
c.JSON(http.StatusNotFound, simpleError(models.ErrRunnerRouteNotFound))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,8 +131,7 @@ func (s *Server) handleRequest(c *gin.Context, enqueue models.Enqueue) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Error(models.ErrRunnerRouteNotFound)
|
handleErrorResponse(c, models.ErrRunnerRouteNotFound)
|
||||||
c.JSON(http.StatusNotFound, simpleError(models.ErrRunnerRouteNotFound))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) loadroutes(ctx context.Context, filter models.RouteFilter) ([]*models.Route, error) {
|
func (s *Server) loadroutes(ctx context.Context, filter models.RouteFilter) ([]*models.Route, error) {
|
||||||
@@ -241,8 +232,7 @@ func (s *Server) serve(ctx context.Context, c *gin.Context, appName string, rout
|
|||||||
// Read payload
|
// Read payload
|
||||||
pl, err := ioutil.ReadAll(cfg.Stdin)
|
pl, err := ioutil.ReadAll(cfg.Stdin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error(models.ErrInvalidPayload)
|
handleErrorResponse(c, models.ErrInvalidPayload)
|
||||||
c.JSON(http.StatusBadRequest, simpleError(models.ErrInvalidPayload))
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// Create Task
|
// Create Task
|
||||||
|
|||||||
@@ -205,28 +205,24 @@ func (s *Server) handleTaskRequest(c *gin.Context) {
|
|||||||
case "GET":
|
case "GET":
|
||||||
task, err := s.MQ.Reserve(ctx)
|
task, err := s.MQ.Reserve(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error()
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusInternalServerError, simpleError(models.ErrRoutesList))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusAccepted, task)
|
c.JSON(http.StatusAccepted, task)
|
||||||
case "DELETE":
|
case "DELETE":
|
||||||
body, err := ioutil.ReadAll(c.Request.Body)
|
body, err := ioutil.ReadAll(c.Request.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error()
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusInternalServerError, err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var task models.Task
|
var task models.Task
|
||||||
if err = json.Unmarshal(body, &task); err != nil {
|
if err = json.Unmarshal(body, &task); err != nil {
|
||||||
logrus.WithError(err).Error()
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusInternalServerError, err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.MQ.Delete(ctx, &task); err != nil {
|
if err := s.MQ.Delete(ctx, &task); err != nil {
|
||||||
logrus.WithError(err).Error()
|
handleErrorResponse(c, err)
|
||||||
c.JSON(http.StatusInternalServerError, err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusAccepted, task)
|
c.JSON(http.StatusAccepted, task)
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ func TestFullStack(t *testing.T) {
|
|||||||
{"execute myroute", "POST", "/r/myapp/myroute", `{ "name": "Teste" }`, http.StatusOK, 2},
|
{"execute myroute", "POST", "/r/myapp/myroute", `{ "name": "Teste" }`, http.StatusOK, 2},
|
||||||
{"execute myroute2", "POST", "/r/myapp/myroute2", `{ "name": "Teste" }`, http.StatusInternalServerError, 2},
|
{"execute myroute2", "POST", "/r/myapp/myroute2", `{ "name": "Teste" }`, http.StatusInternalServerError, 2},
|
||||||
{"delete myroute", "DELETE", "/v1/apps/myapp/routes/myroute", ``, http.StatusOK, 1},
|
{"delete myroute", "DELETE", "/v1/apps/myapp/routes/myroute", ``, http.StatusOK, 1},
|
||||||
{"delete app (fail)", "DELETE", "/v1/apps/myapp", ``, http.StatusBadRequest, 1},
|
{"delete app (fail)", "DELETE", "/v1/apps/myapp", ``, http.StatusConflict, 1},
|
||||||
{"delete myroute2", "DELETE", "/v1/apps/myapp/routes/myroute2", ``, http.StatusOK, 0},
|
{"delete myroute2", "DELETE", "/v1/apps/myapp/routes/myroute2", ``, http.StatusOK, 0},
|
||||||
{"delete app (success)", "DELETE", "/v1/apps/myapp", ``, http.StatusOK, 0},
|
{"delete app (success)", "DELETE", "/v1/apps/myapp", ``, http.StatusOK, 0},
|
||||||
{"get deleted app", "GET", "/v1/apps/myapp", ``, http.StatusNotFound, 0},
|
{"get deleted app", "GET", "/v1/apps/myapp", ``, http.StatusNotFound, 0},
|
||||||
|
|||||||
@@ -2,11 +2,10 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
|
||||||
|
|
||||||
var ErrNoSpecialHandlerFound = errors.New("Path not found")
|
"gitlab-odx.oracle.com/odx/functions/api/models"
|
||||||
|
)
|
||||||
|
|
||||||
type SpecialHandler interface {
|
type SpecialHandler interface {
|
||||||
Handle(c HandlerContext) error
|
Handle(c HandlerContext) error
|
||||||
@@ -56,7 +55,7 @@ func (s *Server) AddSpecialHandler(handler SpecialHandler) {
|
|||||||
// UseSpecialHandlers execute all special handlers
|
// UseSpecialHandlers execute all special handlers
|
||||||
func (s *Server) UseSpecialHandlers(ctx context.Context, req *http.Request, resp http.ResponseWriter) (context.Context, error) {
|
func (s *Server) UseSpecialHandlers(ctx context.Context, req *http.Request, resp http.ResponseWriter) (context.Context, error) {
|
||||||
if len(s.specialHandlers) == 0 {
|
if len(s.specialHandlers) == 0 {
|
||||||
return ctx, ErrNoSpecialHandlerFound
|
return ctx, models.ErrNoSpecialHandlerFound
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &SpecialHandlerContext{
|
c := &SpecialHandlerContext{
|
||||||
|
|||||||
Reference in New Issue
Block a user