Files
fn-serverless/api/models/error.go
Reed Allman 2ebc9c7480 hybrid mergy (#581)
* so it begins

* add clarification to /dequeue, change response to list to future proof

* Specify that runner endpoints are also under /v1

* Add a flag to choose operation mode (node type).

This is specified using the `FN_NODE_TYPE` environment variable. The
default is the existing behaviour, where the server supports all
operations (full API plus asynchronous and synchronous runners).

The additional modes are:
* API - the full API is available, but no functions are executed by the
  node. Async calls are placed into a message queue, and synchronous
  calls are not supported (invoking them results in an API error).
* Runner - only the invocation/route API is present. Asynchronous and
  synchronous invocation requests are supported, but asynchronous
  requests are placed onto the message queue, so might be handled by
  another runner.

* Add agent type and checks on Submit

* Sketch of a factored out data access abstraction for api/runner agents

* Fix tests, adding node/agent types to constructors

* Add tests for full, API, and runner server modes.

* Added atomic UpdateCall to datastore

* adds in server side endpoints

* Made ServerNodeType public because tests use it

* Made ServerNodeType public because tests use it

* fix test build

* add hybrid runner client

pretty simple go api client that covers surface area needed for hybrid,
returning structs from models that the agent can use directly. not exactly
sure where to put this, so put it in `/clients/hybrid` but maybe we should
make `/api/runner/client` or something and shove it in there. want to get
integration tests set up and use the real endpoints next and then wrap this up
in the DataAccessLayer stuff.

* gracefully handles errors from fn
* handles backoff & retry on 500s
* will add to existing spans for debuggo action

* minor fixes

* meh
2017-12-11 10:43:19 -08:00

205 lines
5.3 KiB
Go

package models
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"),
}
ErrCallTimeout = err{
code: http.StatusGatewayTimeout,
error: errors.New("Timed out"),
}
ErrCallTimeoutServerBusy = err{
code: http.StatusServiceUnavailable,
error: errors.New("Timed out - server too busy"),
}
ErrAppsMissingName = err{
code: http.StatusBadRequest,
error: errors.New("Missing app name"),
}
ErrAppsTooLongName = err{
code: http.StatusBadRequest,
error: fmt.Errorf("App name must be %v characters or less", maxAppName),
}
ErrAppsInvalidName = 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 - 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"),
}
ErrDatastoreEmptyCallID = err{
code: http.StatusBadRequest,
error: errors.New("Missing call ID"),
}
ErrDatastoreCannotUpdateCall = err{
code: http.StatusConflict,
error: errors.New("Call to be updated is different from expected"),
}
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 - path is immutable"),
}
ErrFoundDynamicURL = err{
code: http.StatusBadRequest,
error: errors.New("Dynamic URL is not allowed"),
}
ErrRoutesInvalidPath = err{
code: http.StatusBadRequest,
error: errors.New("Invalid route path format"),
}
ErrRoutesInvalidType = err{
code: http.StatusBadRequest,
error: errors.New("Invalid route Type"),
}
ErrRoutesInvalidFormat = err{
code: http.StatusBadRequest,
error: errors.New("Invalid route Format"),
}
ErrRoutesMissingAppName = err{
code: http.StatusBadRequest,
error: errors.New("Missing route AppName"),
}
ErrRoutesMissingImage = err{
code: http.StatusBadRequest,
error: errors.New("Missing route Image"),
}
ErrRoutesMissingName = err{
code: http.StatusBadRequest,
error: errors.New("Missing route Name"),
}
ErrRoutesMissingPath = err{
code: http.StatusBadRequest,
error: errors.New("Missing route Path"),
}
ErrRoutesMissingType = err{
code: http.StatusBadRequest,
error: errors.New("Missing route Type"),
}
ErrPathMalformed = err{
code: http.StatusBadRequest,
error: errors.New("Path malformed"),
}
ErrInvalidToTime = err{
code: http.StatusBadRequest,
error: errors.New("to_time is not an epoch time"),
}
ErrInvalidFromTime = err{
code: http.StatusBadRequest,
error: errors.New("from_time is not an epoch time"),
}
ErrRoutesInvalidTimeout = err{
code: http.StatusBadRequest,
error: fmt.Errorf("timeout value is out of range. Sync should be between 0 and %d, async should be between 0 and %d", MaxSyncTimeout, MaxAsyncTimeout),
}
ErrRoutesInvalidIdleTimeout = err{
code: http.StatusBadRequest,
error: fmt.Errorf("idle_timeout value is out of range. It should be between 0 and %d", MaxIdleTimeout),
}
ErrRoutesInvalidMemory = err{
code: http.StatusBadRequest,
error: fmt.Errorf("memory value is out of range. It should be between 0 and %d", RouteMaxMemory),
}
ErrCallNotFound = err{
code: http.StatusNotFound,
error: errors.New("Call not found"),
}
ErrCallLogNotFound = err{
code: http.StatusNotFound,
error: errors.New("Call log not found"),
}
ErrSyncCallNotSupported = err{
code: http.StatusBadRequest,
error: errors.New("Invoking routes of type sync is not supported on nodes configured as type API"),
}
)
// APIError 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 }
func NewAPIError(code int, e error) APIError { return err{code, e} }
// Error uniform error output
type Error struct {
Error *ErrorBody `json:"error,omitempty"`
}
func (m *Error) Validate() error {
return nil
}