mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Copies the log endpoints up to the V2 endpoints, in a similar way to the call endpoints. The main change is to when logs are inserted into S3. The signature of the function has been changed to take the whole call object, rather than just the app and call id's. This allows the function to switch between calls for Routes and those for Fns. Obviously this switching can be removed when v1 is removed. In the sql implementation it inserts with both appID and fnID, this allows the two get's to work, and the down grade of the migration. When the v1 logs are removed, the appId can be dropped. The log fetch test and error messages have been changed to be FnID specific.
261 lines
7.3 KiB
Go
261 lines
7.3 KiB
Go
package models
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
)
|
|
|
|
// TODO we can put constants all in this file too
|
|
const (
|
|
maxAppName = 30
|
|
maxFnName = 30
|
|
MaxTriggerName = 30
|
|
)
|
|
|
|
var (
|
|
ErrInvalidJSON = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Invalid JSON"),
|
|
}
|
|
ErrClientCancel = err{
|
|
// The special custom error code to close connection without any response
|
|
code: 444,
|
|
error: errors.New("Client cancelled context"),
|
|
}
|
|
ErrCallTimeout = err{
|
|
code: http.StatusGatewayTimeout,
|
|
error: errors.New("Timed out"),
|
|
}
|
|
ErrCallTimeoutServerBusy = err{
|
|
code: http.StatusServiceUnavailable,
|
|
error: errors.New("Timed out - server too busy"),
|
|
}
|
|
|
|
ErrUnsupportedMediaType = err{
|
|
code: http.StatusUnsupportedMediaType,
|
|
error: errors.New("Content Type not supported")}
|
|
|
|
ErrMissingID = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing ID")}
|
|
|
|
ErrMissingAppID = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing App ID")}
|
|
ErrMissingFnID = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing Fn ID")}
|
|
ErrMissingName = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing Name")}
|
|
|
|
ErrCreatedAtProvided = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Trigger Created At Provided for Create")}
|
|
ErrUpdatedAtProvided = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Trigger ID Provided for Create")}
|
|
|
|
ErrDatastoreEmptyApp = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing app"),
|
|
}
|
|
ErrDatastoreEmptyCallID = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing call ID"),
|
|
}
|
|
ErrDatastoreEmptyFn = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing Fn"),
|
|
}
|
|
ErrDatastoreEmptyFnID = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing Fn ID"),
|
|
}
|
|
ErrInvalidPayload = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Invalid payload"),
|
|
}
|
|
ErrDatastoreEmptyRoute = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing route"),
|
|
}
|
|
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"),
|
|
}
|
|
ErrRoutesMissingAppID = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing route AppName"),
|
|
}
|
|
ErrRoutesMissingImage = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing route Image"),
|
|
}
|
|
ErrRoutesInvalidImage = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Invalid route Image"),
|
|
}
|
|
ErrRoutesMissingName = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing route Name"),
|
|
}
|
|
ErrRoutesMissingPath = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Missing route Path"),
|
|
}
|
|
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),
|
|
}
|
|
ErrInvalidMemory = 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"),
|
|
}
|
|
ErrInvalidCPUs = err{
|
|
code: http.StatusBadRequest,
|
|
error: fmt.Errorf("Cpus is invalid. Value should be either between [%.3f and %.3f] or [%dm and %dm] milliCPU units",
|
|
float64(MinMilliCPUs)/1000.0, float64(MaxMilliCPUs)/1000.0, MinMilliCPUs, MaxMilliCPUs),
|
|
}
|
|
ErrCallLogNotFound = err{
|
|
code: http.StatusNotFound,
|
|
error: errors.New("Call log not found"),
|
|
}
|
|
ErrInvokeNotSupported = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Invoking routes /r/ is not supported on nodes configured as type API"),
|
|
}
|
|
ErrAPINotSupported = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Invoking api /v1/ requests is not supported on nodes configured as type Runner"),
|
|
}
|
|
ErrPathNotFound = err{
|
|
code: http.StatusNotFound,
|
|
error: errors.New("Path not found"),
|
|
}
|
|
ErrFunctionResponseTooBig = err{
|
|
code: http.StatusBadGateway,
|
|
error: fmt.Errorf("function response too large"),
|
|
}
|
|
ErrRequestContentTooBig = err{
|
|
code: http.StatusRequestEntityTooLarge,
|
|
error: fmt.Errorf("Request content too large"),
|
|
}
|
|
ErrInvalidAnnotationKey = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Invalid annotation key, annotation keys must be non-empty ascii strings excluding whitespace"),
|
|
}
|
|
ErrInvalidAnnotationKeyLength = err{
|
|
code: http.StatusBadRequest,
|
|
error: fmt.Errorf("Invalid annotation key length, annotation keys may not be larger than %d bytes", maxAnnotationKeyBytes),
|
|
}
|
|
ErrInvalidAnnotationValue = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Invalid annotation value, annotation values may only be non-empty strings, numbers, objects, or arrays"),
|
|
}
|
|
ErrInvalidAnnotationValueLength = err{
|
|
code: http.StatusBadRequest,
|
|
error: fmt.Errorf("Invalid annotation value length, annotation values may not be larger than %d bytes when serialized as JSON", maxAnnotationValueBytes),
|
|
}
|
|
ErrTooManyAnnotationKeys = err{
|
|
code: http.StatusBadRequest,
|
|
error: fmt.Errorf("Invalid annotation change, new key(s) exceed maximum permitted number of annotations keys (%d)", maxAnnotationsKeys),
|
|
}
|
|
|
|
ErrAsyncUnsupported = err{
|
|
code: http.StatusBadRequest,
|
|
error: errors.New("Async functions are not supported on this server"),
|
|
}
|
|
)
|
|
|
|
// 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} }
|
|
|
|
func IsAPIError(e error) bool {
|
|
_, ok := e.(APIError)
|
|
return ok
|
|
}
|
|
|
|
func GetAPIErrorCode(e error) int {
|
|
err, ok := e.(APIError)
|
|
if ok {
|
|
return err.Code()
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// ErrorWrapper uniform error output (v1) only
|
|
type ErrorWrapper struct {
|
|
Error *Error `json:"error,omitempty"`
|
|
}
|
|
|
|
func (m *ErrorWrapper) Validate() error {
|
|
return nil
|
|
}
|