Files
fn-serverless/api/datastore/internal/datastoreutil/validator.go
Reed Allman 00c29b8bf3 datastore no longer implements logstore (#1013)
* datastore no longer implements logstore

the underlying implementation of our sql store implements both the datastore
and the logstore interface, however going forward we are likely to encounter
datastore implementers that would mock out the logstore interface and not use
its methods - signalling a poor interface. this remedies that, now they are 2
completely separate things, which our sqlstore happens to implement both of.

related to some recent changes around wrapping, this keeps the imposed metrics
and validation wrapping of a servers logstore and datastore, just moving it
into New instead of in the opts - this is so that a user can have the
underlying datastore in order to set the logstore to it, since wrapping it in
a validator/metrics would render it no longer a logstore implementer (i.e.
validate datastore doesn't implement the logstore interface), we need to do
this after setting the logstore to the datastore if one wasn't provided
explicitly.

* splits logstore and datastore metrics & validation logic
* `make test` should be `make full-test` always. got rid of that so that
nobody else has to wait for CI to blow up on them after the tests pass locally
ever again.

* fix new tests
2018-06-04 00:08:16 -07:00

139 lines
3.6 KiB
Go

package datastoreutil
import (
"context"
"github.com/jmoiron/sqlx"
"github.com/fnproject/fn/api/models"
)
// NewValidator returns a models.Datastore which validates certain arguments before delegating to ds.
func NewValidator(ds models.Datastore) models.Datastore {
return &validator{ds}
}
type validator struct {
models.Datastore
}
func (v *validator) GetAppID(ctx context.Context, appName string) (string, error) {
if appName == "" {
return "", models.ErrAppsMissingName
}
return v.Datastore.GetAppID(ctx, appName)
}
func (v *validator) GetAppByID(ctx context.Context, appID string) (*models.App, error) {
if appID == "" {
return nil, models.ErrDatastoreEmptyAppID
}
return v.Datastore.GetAppByID(ctx, appID)
}
func (v *validator) GetApps(ctx context.Context, appFilter *models.AppFilter) ([]*models.App, error) {
return v.Datastore.GetApps(ctx, appFilter)
}
// app and app.Name will never be nil/empty.
func (v *validator) InsertApp(ctx context.Context, app *models.App) (*models.App, error) {
if app == nil {
return nil, models.ErrDatastoreEmptyApp
}
app.SetDefaults()
if err := app.Validate(); err != nil {
return nil, err
}
return v.Datastore.InsertApp(ctx, app)
}
// app and app.Name will never be nil/empty.
func (v *validator) UpdateApp(ctx context.Context, app *models.App) (*models.App, error) {
if app == nil {
return nil, models.ErrDatastoreEmptyApp
}
if app.ID == "" {
return nil, models.ErrDatastoreEmptyAppID
}
return v.Datastore.UpdateApp(ctx, app)
}
// name will never be empty.
func (v *validator) RemoveApp(ctx context.Context, appID string) error {
if appID == "" {
return models.ErrDatastoreEmptyAppID
}
return v.Datastore.RemoveApp(ctx, appID)
}
// appName and routePath will never be empty.
func (v *validator) GetRoute(ctx context.Context, appID, routePath string) (*models.Route, error) {
if appID == "" {
return nil, models.ErrDatastoreEmptyAppID
}
if routePath == "" {
return nil, models.ErrRoutesMissingPath
}
return v.Datastore.GetRoute(ctx, appID, routePath)
}
// appName will never be empty
func (v *validator) GetRoutesByApp(ctx context.Context, appID string, routeFilter *models.RouteFilter) (routes []*models.Route, err error) {
if appID == "" {
return nil, models.ErrDatastoreEmptyAppID
}
return v.Datastore.GetRoutesByApp(ctx, appID, routeFilter)
}
// route will never be nil and route's AppName and Path will never be empty.
func (v *validator) InsertRoute(ctx context.Context, route *models.Route) (*models.Route, error) {
if route == nil {
return nil, models.ErrDatastoreEmptyRoute
}
route.SetDefaults()
if err := route.Validate(); err != nil {
return nil, err
}
return v.Datastore.InsertRoute(ctx, route)
}
// route will never be nil and route's AppName and Path will never be empty.
func (v *validator) UpdateRoute(ctx context.Context, newroute *models.Route) (*models.Route, error) {
if newroute == nil {
return nil, models.ErrDatastoreEmptyRoute
}
if newroute.AppID == "" {
return nil, models.ErrRoutesMissingAppID
}
if newroute.Path == "" {
return nil, models.ErrRoutesMissingPath
}
return v.Datastore.UpdateRoute(ctx, newroute)
}
// appName and routePath will never be empty.
func (v *validator) RemoveRoute(ctx context.Context, appID string, routePath string) error {
if appID == "" {
return models.ErrDatastoreEmptyAppID
}
if routePath == "" {
return models.ErrRoutesMissingPath
}
return v.Datastore.RemoveRoute(ctx, appID, routePath)
}
// GetDatabase returns the underlying sqlx database implementation
func (v *validator) GetDatabase() *sqlx.DB {
return v.Datastore.GetDatabase()
}