From 01d5a81389e52408c09f13af8ab79bb0594ef081 Mon Sep 17 00:00:00 2001 From: Pedro Nasser Date: Thu, 24 Nov 2016 03:46:42 -0200 Subject: [PATCH] Add appfilter and tests (#337) add appfilter and tests --- api/datastore/bolt/bolt.go | 25 ++++++++++++++++++++--- api/datastore/bolt_test.go | 9 +++++++++ api/datastore/mock.go | 4 +--- api/datastore/postgres/postgres.go | 32 +++++++++++++++++++++++------- api/datastore/postgres_test.go | 9 +++++++++ api/models/app.go | 1 + api/models/datastore.go | 6 ------ 7 files changed, 67 insertions(+), 19 deletions(-) diff --git a/api/datastore/bolt/bolt.go b/api/datastore/bolt/bolt.go index d6e35d8ce..03abafc99 100644 --- a/api/datastore/bolt/bolt.go +++ b/api/datastore/bolt/bolt.go @@ -12,6 +12,8 @@ import ( "github.com/Sirupsen/logrus" "github.com/boltdb/bolt" "github.com/iron-io/functions/api/models" + "regexp" + "strings" ) type BoltDatastore struct { @@ -199,7 +201,9 @@ func (ds *BoltDatastore) GetApps(ctx context.Context, filter *models.AppFilter) if err != nil { return err } - res = append(res, app) + if applyAppFilter(app, filter) { + res = append(res, app) + } return nil }) if err2 != nil { @@ -444,7 +448,7 @@ func (ds *BoltDatastore) GetRoutesByApp(ctx context.Context, appName string, fil if err != nil { return err } - if models.ApplyRouteFilter(&route, filter) { + if applyRouteFilter(&route, filter) { i++ res = append(res, &route) } @@ -480,7 +484,7 @@ func (ds *BoltDatastore) GetRoutes(ctx context.Context, filter *models.RouteFilt if err != nil { return err } - if models.ApplyRouteFilter(&route, filter) { + if applyRouteFilter(&route, filter) { i++ res = append(res, &route) } @@ -512,3 +516,18 @@ func (ds *BoltDatastore) Get(ctx context.Context, key []byte) ([]byte, error) { }) return ret, nil } + +func applyAppFilter(app *models.App, filter *models.AppFilter) bool { + if filter.Name != "" { + nameLike, err := regexp.MatchString(strings.Replace(filter.Name, "%", ".*", -1), app.Name) + return err == nil && nameLike + } + + return true +} + +func applyRouteFilter(route *models.Route, filter *models.RouteFilter) bool { + return (filter.Path == "" || route.Path == filter.Path) && + (filter.AppName == "" || route.AppName == filter.AppName) && + (filter.Image == "" || route.Image == filter.Image) +} diff --git a/api/datastore/bolt_test.go b/api/datastore/bolt_test.go index 52737ab9a..c5f443317 100644 --- a/api/datastore/bolt_test.go +++ b/api/datastore/bolt_test.go @@ -225,6 +225,15 @@ func TestBolt(t *testing.T) { t.Fatalf("Test GetRoutes: expected `app.Name` to be `%s` but it was `%s`", testRoute.Path, routes[0].Path) } + apps, err = ds.GetApps(ctx, &models.AppFilter{Name: "Tes%"}) + if err != nil { + t.Log(buf.String()) + t.Fatalf("Test GetApps(filter): unexpected error %v", err) + } + if len(apps) == 0 { + t.Fatal("Test GetApps(filter): expected result count to be greater than 0") + } + // Testing app delete err = ds.RemoveRoute(ctx, "", "") if err != models.ErrDatastoreEmptyAppName { diff --git a/api/datastore/mock.go b/api/datastore/mock.go index d5dccd768..bc86abda1 100644 --- a/api/datastore/mock.go +++ b/api/datastore/mock.go @@ -80,9 +80,7 @@ func (m *Mock) GetRoute(ctx context.Context, appName, routePath string) (*models func (m *Mock) GetRoutes(ctx context.Context, routeFilter *models.RouteFilter) (routes []*models.Route, err error) { for _, r := range m.Routes { - if models.ApplyRouteFilter(r, routeFilter) { - routes = append(routes, r) - } + routes = append(routes, r) } return } diff --git a/api/datastore/postgres/postgres.go b/api/datastore/postgres/postgres.go index e9a6e3b1c..010003e0e 100644 --- a/api/datastore/postgres/postgres.go +++ b/api/datastore/postgres/postgres.go @@ -213,10 +213,9 @@ func scanApp(scanner rowScanner, app *models.App) error { func (ds *PostgresDatastore) GetApps(ctx context.Context, filter *models.AppFilter) ([]*models.App, error) { res := []*models.App{} - rows, err := ds.db.Query(` - SELECT DISTINCT * - FROM apps`, - ) + filterQuery := buildFilterAppQuery(filter) + rows, err := ds.db.Query(fmt.Sprintf("SELECT DISTINCT * FROM apps %s", filterQuery)) + if err != nil { return nil, err } @@ -407,7 +406,7 @@ func (ds *PostgresDatastore) GetRoute(ctx context.Context, appName, routePath st func (ds *PostgresDatastore) GetRoutes(ctx context.Context, filter *models.RouteFilter) ([]*models.Route, error) { res := []*models.Route{} - filterQuery := buildFilterQuery(filter) + filterQuery := buildFilterRouteQuery(filter) rows, err := ds.db.Query(fmt.Sprintf("%s %s", routeSelector, filterQuery)) // todo: check for no rows so we don't respond with a sql 500 err if err != nil { @@ -433,7 +432,7 @@ func (ds *PostgresDatastore) GetRoutes(ctx context.Context, filter *models.Route func (ds *PostgresDatastore) GetRoutesByApp(ctx context.Context, appName string, filter *models.RouteFilter) ([]*models.Route, error) { res := []*models.Route{} filter.AppName = appName - filterQuery := buildFilterQuery(filter) + filterQuery := buildFilterRouteQuery(filter) rows, err := ds.db.Query(fmt.Sprintf("%s %s", routeSelector, filterQuery)) // todo: check for no rows so we don't respond with a sql 500 err if err != nil { @@ -456,7 +455,26 @@ func (ds *PostgresDatastore) GetRoutesByApp(ctx context.Context, appName string, return res, nil } -func buildFilterQuery(filter *models.RouteFilter) string { +func buildFilterAppQuery(filter *models.AppFilter) string { + filterQuery := "" + + filterQueries := []string{} + if filter.Name != "" { + filterQueries = append(filterQueries, fmt.Sprintf("name LIKE '%s'", filter.Name)) + } + + for i, field := range filterQueries { + if i == 0 { + filterQuery = fmt.Sprintf("WHERE %s ", field) + } else { + filterQuery = fmt.Sprintf("%s AND %s", filterQuery, field) + } + } + + return filterQuery +} + +func buildFilterRouteQuery(filter *models.RouteFilter) string { filterQuery := "" filterQueries := []string{} diff --git a/api/datastore/postgres_test.go b/api/datastore/postgres_test.go index 436864b9a..9a07ac5d0 100644 --- a/api/datastore/postgres_test.go +++ b/api/datastore/postgres_test.go @@ -126,6 +126,15 @@ func TestPostgres(t *testing.T) { t.Fatalf("Test GetApps: expected `app.Name` to be `%s` but it was `%s`", app.Name, testApp.Name) } + apps, err = ds.GetApps(ctx, &models.AppFilter{Name: "Tes%"}) + if err != nil { + t.Log(buf.String()) + t.Fatalf("Test GetApps(filter): unexpected error %v", err) + } + if len(apps) == 0 { + t.Fatal("Test GetApps(filter): expected result count to be greater than 0") + } + // Testing app delete err = ds.RemoveApp(ctx, "") if err != models.ErrDatastoreEmptyAppName { diff --git a/api/models/app.go b/api/models/app.go index b0fe70709..25c552c1b 100644 --- a/api/models/app.go +++ b/api/models/app.go @@ -53,4 +53,5 @@ func (a *App) Validate() error { } type AppFilter struct { + Name string } diff --git a/api/models/datastore.go b/api/models/datastore.go index ca17b0996..9aee718c1 100644 --- a/api/models/datastore.go +++ b/api/models/datastore.go @@ -31,9 +31,3 @@ var ( ErrDatastoreEmptyApp = errors.New("Missing app") ErrDatastoreEmptyRoute = errors.New("Missing route") ) - -func ApplyRouteFilter(route *Route, filter *RouteFilter) bool { - return (filter.Path == "" || route.Path == filter.Path) && - (filter.AppName == "" || route.AppName == filter.AppName) && - (filter.Image == "" || route.Image == filter.Image) -}