diff --git a/api/datastore/bolt/bolt.go b/api/datastore/bolt/bolt.go index df171339d..d6e35d8ce 100644 --- a/api/datastore/bolt/bolt.go +++ b/api/datastore/bolt/bolt.go @@ -7,6 +7,8 @@ import ( "path/filepath" "time" + "context" + "github.com/Sirupsen/logrus" "github.com/boltdb/bolt" "github.com/iron-io/functions/api/models" @@ -72,7 +74,7 @@ func New(url *url.URL) (models.Datastore, error) { return ds, nil } -func (ds *BoltDatastore) InsertApp(app *models.App) (*models.App, error) { +func (ds *BoltDatastore) InsertApp(ctx context.Context, app *models.App) (*models.App, error) { if app == nil { return nil, models.ErrDatastoreEmptyApp } @@ -111,7 +113,7 @@ func (ds *BoltDatastore) InsertApp(app *models.App) (*models.App, error) { return app, err } -func (ds *BoltDatastore) UpdateApp(newapp *models.App) (*models.App, error) { +func (ds *BoltDatastore) UpdateApp(ctx context.Context, newapp *models.App) (*models.App, error) { if newapp == nil { return nil, models.ErrDatastoreEmptyApp } @@ -166,7 +168,7 @@ func (ds *BoltDatastore) UpdateApp(newapp *models.App) (*models.App, error) { return app, err } -func (ds *BoltDatastore) RemoveApp(appName string) error { +func (ds *BoltDatastore) RemoveApp(ctx context.Context, appName string) error { if appName == "" { return models.ErrDatastoreEmptyAppName } @@ -187,7 +189,7 @@ func (ds *BoltDatastore) RemoveApp(appName string) error { return err } -func (ds *BoltDatastore) GetApps(filter *models.AppFilter) ([]*models.App, error) { +func (ds *BoltDatastore) GetApps(ctx context.Context, filter *models.AppFilter) ([]*models.App, error) { res := []*models.App{} err := ds.db.View(func(tx *bolt.Tx) error { b := tx.Bucket(ds.appsBucket) @@ -211,7 +213,7 @@ func (ds *BoltDatastore) GetApps(filter *models.AppFilter) ([]*models.App, error return res, nil } -func (ds *BoltDatastore) GetApp(name string) (*models.App, error) { +func (ds *BoltDatastore) GetApp(ctx context.Context, name string) (*models.App, error) { if name == "" { return nil, models.ErrDatastoreEmptyAppName } @@ -250,7 +252,7 @@ func (ds *BoltDatastore) getRouteBucketForApp(tx *bolt.Tx, appName string) (*bol return b, nil } -func (ds *BoltDatastore) InsertRoute(route *models.Route) (*models.Route, error) { +func (ds *BoltDatastore) InsertRoute(ctx context.Context, route *models.Route) (*models.Route, error) { if route == nil { return nil, models.ErrDatastoreEmptyApp } @@ -293,7 +295,7 @@ func (ds *BoltDatastore) InsertRoute(route *models.Route) (*models.Route, error) return route, nil } -func (ds *BoltDatastore) UpdateRoute(newroute *models.Route) (*models.Route, error) { +func (ds *BoltDatastore) UpdateRoute(ctx context.Context, newroute *models.Route) (*models.Route, error) { if newroute == nil { return nil, models.ErrDatastoreEmptyRoute } @@ -369,7 +371,7 @@ func (ds *BoltDatastore) UpdateRoute(newroute *models.Route) (*models.Route, err return route, nil } -func (ds *BoltDatastore) RemoveRoute(appName, routePath string) error { +func (ds *BoltDatastore) RemoveRoute(ctx context.Context, appName, routePath string) error { if appName == "" { return models.ErrDatastoreEmptyAppName } @@ -396,7 +398,7 @@ func (ds *BoltDatastore) RemoveRoute(appName, routePath string) error { return nil } -func (ds *BoltDatastore) GetRoute(appName, routePath string) (*models.Route, error) { +func (ds *BoltDatastore) GetRoute(ctx context.Context, appName, routePath string) (*models.Route, error) { if appName == "" { return nil, models.ErrDatastoreEmptyAppName } @@ -421,7 +423,7 @@ func (ds *BoltDatastore) GetRoute(appName, routePath string) (*models.Route, err return route, err } -func (ds *BoltDatastore) GetRoutesByApp(appName string, filter *models.RouteFilter) ([]*models.Route, error) { +func (ds *BoltDatastore) GetRoutesByApp(ctx context.Context, appName string, filter *models.RouteFilter) ([]*models.Route, error) { res := []*models.Route{} err := ds.db.View(func(tx *bolt.Tx) error { b, err := ds.getRouteBucketForApp(tx, appName) @@ -455,7 +457,7 @@ func (ds *BoltDatastore) GetRoutesByApp(appName string, filter *models.RouteFilt return res, nil } -func (ds *BoltDatastore) GetRoutes(filter *models.RouteFilter) ([]*models.Route, error) { +func (ds *BoltDatastore) GetRoutes(ctx context.Context, filter *models.RouteFilter) ([]*models.Route, error) { res := []*models.Route{} err := ds.db.View(func(tx *bolt.Tx) error { i := 0 @@ -492,7 +494,7 @@ func (ds *BoltDatastore) GetRoutes(filter *models.RouteFilter) ([]*models.Route, return res, nil } -func (ds *BoltDatastore) Put(key, value []byte) error { +func (ds *BoltDatastore) Put(ctx context.Context, key, value []byte) error { ds.db.Update(func(tx *bolt.Tx) error { b := tx.Bucket(ds.extrasBucket) // todo: maybe namespace by app? err := b.Put(key, value) @@ -501,7 +503,7 @@ func (ds *BoltDatastore) Put(key, value []byte) error { return nil } -func (ds *BoltDatastore) Get(key []byte) ([]byte, error) { +func (ds *BoltDatastore) Get(ctx context.Context, key []byte) ([]byte, error) { var ret []byte ds.db.View(func(tx *bolt.Tx) error { b := tx.Bucket(ds.extrasBucket) diff --git a/api/datastore/bolt_test.go b/api/datastore/bolt_test.go index 9afcd51f9..52737ab9a 100644 --- a/api/datastore/bolt_test.go +++ b/api/datastore/bolt_test.go @@ -2,6 +2,7 @@ package datastore import ( "bytes" + "context" "log" "os" "testing" @@ -26,6 +27,8 @@ const tmpBolt = "/tmp/func_test_bolt.db" func TestBolt(t *testing.T) { buf := setLogBuffer() + ctx := context.Background() + os.Remove(tmpBolt) ds, err := New("bolt://" + tmpBolt) if err != nil { @@ -43,31 +46,31 @@ func TestBolt(t *testing.T) { } // Testing insert app - _, err = ds.InsertApp(nil) + _, err = ds.InsertApp(ctx, nil) if err != models.ErrDatastoreEmptyApp { t.Log(buf.String()) t.Fatalf("Test InsertApp(nil): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyApp, err) } - _, err = ds.InsertApp(&models.App{}) + _, err = ds.InsertApp(ctx, &models.App{}) if err != models.ErrDatastoreEmptyAppName { t.Log(buf.String()) t.Fatalf("Test InsertApp(nil): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyAppName, err) } - _, err = ds.InsertApp(testApp) + _, err = ds.InsertApp(ctx, testApp) if err != nil { t.Log(buf.String()) t.Fatalf("Test InsertApp: error when Bolt was storing new app: %s", err) } - _, err = ds.InsertApp(testApp) + _, err = ds.InsertApp(ctx, testApp) if err != models.ErrAppsAlreadyExists { t.Log(buf.String()) t.Fatalf("Test InsertApp duplicated: expected error `%v`, but it was `%v`", models.ErrAppsAlreadyExists, err) } - _, err = ds.UpdateApp(&models.App{ + _, err = ds.UpdateApp(ctx, &models.App{ Name: testApp.Name, Config: map[string]string{ "TEST": "1", @@ -79,13 +82,13 @@ func TestBolt(t *testing.T) { } // Testing get app - _, err = ds.GetApp("") + _, err = ds.GetApp(ctx, "") if err != models.ErrDatastoreEmptyAppName { t.Log(buf.String()) t.Fatalf("Test GetApp: expected error to be %v, but it was %s", models.ErrDatastoreEmptyAppName, err) } - app, err := ds.GetApp(testApp.Name) + app, err := ds.GetApp(ctx, testApp.Name) if err != nil { t.Log(buf.String()) t.Fatalf("Test GetApp: error: %s", err) @@ -96,7 +99,7 @@ func TestBolt(t *testing.T) { } // Testing list apps - apps, err := ds.GetApps(&models.AppFilter{}) + apps, err := ds.GetApps(ctx, &models.AppFilter{}) if err != nil { t.Log(buf.String()) t.Fatalf("Test GetApps: unexpected error %v", err) @@ -110,18 +113,18 @@ func TestBolt(t *testing.T) { } // Testing app delete - err = ds.RemoveApp("") + err = ds.RemoveApp(ctx, "") if err != models.ErrDatastoreEmptyAppName { t.Log(buf.String()) t.Fatalf("Test RemoveApp: expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyAppName, err) } - err = ds.RemoveApp(testApp.Name) + err = ds.RemoveApp(ctx, testApp.Name) if err != nil { t.Log(buf.String()) t.Fatalf("Test RemoveApp: error: %s", err) } - app, err = ds.GetApp(testApp.Name) + app, err = ds.GetApp(ctx, testApp.Name) if err != nil { t.Log(buf.String()) t.Fatalf("Test GetApp: error: %s", err) @@ -132,7 +135,7 @@ func TestBolt(t *testing.T) { } // Test update inexistent app - _, err = ds.UpdateApp(&models.App{ + _, err = ds.UpdateApp(ctx, &models.App{ Name: testApp.Name, Config: map[string]string{ "TEST": "1", @@ -144,47 +147,47 @@ func TestBolt(t *testing.T) { } // Insert app again to test routes - ds.InsertApp(testApp) + ds.InsertApp(ctx, testApp) // Testing insert route - _, err = ds.InsertRoute(nil) + _, err = ds.InsertRoute(ctx, nil) if err == models.ErrDatastoreEmptyRoute { t.Log(buf.String()) t.Fatalf("Test InsertRoute(nil): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyRoute, err) } - _, err = ds.InsertRoute(testRoute) + _, err = ds.InsertRoute(ctx, testRoute) if err != nil { t.Log(buf.String()) t.Fatalf("Test InsertRoute: error when Bolt was storing new route: %s", err) } - _, err = ds.InsertRoute(testRoute) + _, err = ds.InsertRoute(ctx, testRoute) if err != models.ErrRoutesAlreadyExists { t.Log(buf.String()) t.Fatalf("Test InsertRoute duplicated: expected error to be `%v`, but it was `%v`", models.ErrRoutesAlreadyExists, err) } - _, err = ds.UpdateRoute(testRoute) + _, err = ds.UpdateRoute(ctx, testRoute) if err != nil { t.Log(buf.String()) t.Fatalf("Test UpdateRoute: unexpected error: %v", err) } // Testing get - _, err = ds.GetRoute("a", "") + _, err = ds.GetRoute(ctx, "a", "") if err != models.ErrDatastoreEmptyRoutePath { t.Log(buf.String()) t.Fatalf("Test GetRoute(empty route path): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyRoutePath, err) } - _, err = ds.GetRoute("", "a") + _, err = ds.GetRoute(ctx, "", "a") if err != models.ErrDatastoreEmptyAppName { t.Log(buf.String()) t.Fatalf("Test GetRoute(empty app name): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyAppName, err) } - route, err := ds.GetRoute(testApp.Name, testRoute.Path) + route, err := ds.GetRoute(ctx, testApp.Name, testRoute.Path) if err != nil { t.Log(buf.String()) t.Fatalf("Test GetRoute: unexpected error %v", err) @@ -195,7 +198,7 @@ func TestBolt(t *testing.T) { } // Testing list routes - routes, err := ds.GetRoutesByApp(testApp.Name, &models.RouteFilter{}) + routes, err := ds.GetRoutesByApp(ctx, testApp.Name, &models.RouteFilter{}) if err != nil { t.Log(buf.String()) t.Fatalf("Test GetRoutes: unexpected error %v", err) @@ -209,7 +212,7 @@ func TestBolt(t *testing.T) { } // Testing list routes - routes, err = ds.GetRoutes(&models.RouteFilter{Image: testRoute.Image}) + routes, err = ds.GetRoutes(ctx, &models.RouteFilter{Image: testRoute.Image}) if err != nil { t.Log(buf.String()) t.Fatalf("Test GetRoutes: error: %s", err) @@ -223,25 +226,25 @@ func TestBolt(t *testing.T) { } // Testing app delete - err = ds.RemoveRoute("", "") + err = ds.RemoveRoute(ctx, "", "") if err != models.ErrDatastoreEmptyAppName { t.Log(buf.String()) t.Fatalf("Test RemoveRoute(empty app name): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyAppName, err) } - err = ds.RemoveRoute("a", "") + err = ds.RemoveRoute(ctx, "a", "") if err != models.ErrDatastoreEmptyRoutePath { t.Log(buf.String()) t.Fatalf("Test RemoveRoute(empty route path): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyRoutePath, err) } - err = ds.RemoveRoute(testRoute.AppName, testRoute.Path) + err = ds.RemoveRoute(ctx, testRoute.AppName, testRoute.Path) if err != nil { t.Log(buf.String()) t.Fatalf("Test RemoveApp: unexpected error: %v", err) } - _, err = ds.UpdateRoute(&models.Route{ + _, err = ds.UpdateRoute(ctx, &models.Route{ AppName: testRoute.AppName, Path: testRoute.Path, Image: "test", @@ -251,7 +254,7 @@ func TestBolt(t *testing.T) { t.Fatalf("Test UpdateRoute inexistent: expected error to be `%v`, but it was `%v`", models.ErrRoutesNotFound, err) } - route, err = ds.GetRoute(testRoute.AppName, testRoute.Path) + route, err = ds.GetRoute(ctx, testRoute.AppName, testRoute.Path) if err != nil { t.Log(buf.String()) t.Fatalf("Test GetRoute: error: %s", err) diff --git a/api/datastore/mock.go b/api/datastore/mock.go index 197244852..d5dccd768 100644 --- a/api/datastore/mock.go +++ b/api/datastore/mock.go @@ -1,100 +1,141 @@ package datastore -import "github.com/iron-io/functions/api/models" +import ( + "github.com/iron-io/functions/api/models" + + "context" +) type Mock struct { - FakeApp *models.App - FakeApps []*models.App - FakeRoute *models.Route - FakeRoutes []*models.Route + Apps []*models.App + Routes []*models.Route } -func (m *Mock) GetApp(appName string) (*models.App, error) { - app := m.FakeApp - if app == nil && m.FakeApps != nil { - for _, a := range m.FakeApps { - if a.Name == appName { - app = a - } +func NewMock(apps []*models.App, routes []*models.Route) *Mock { + if apps == nil { + apps = []*models.App{} + } + if routes == nil { + routes = []*models.Route{} + } + return &Mock{apps, routes} +} + +func (m *Mock) GetApp(ctx context.Context, appName string) (app *models.App, err error) { + for _, a := range m.Apps { + if a.Name == appName { + return a, nil } } + return nil, models.ErrAppsNotFound +} + +func (m *Mock) GetApps(ctx context.Context, appFilter *models.AppFilter) ([]*models.App, error) { + return m.Apps, nil +} + +func (m *Mock) InsertApp(ctx context.Context, app *models.App) (*models.App, error) { + if a, _ := m.GetApp(ctx, app.Name); a != nil { + return nil, models.ErrAppsAlreadyExists + } + m.Apps = append(m.Apps, app) return app, nil } -func (m *Mock) GetApps(appFilter *models.AppFilter) ([]*models.App, error) { - // TODO: improve this mock method - return m.FakeApps, nil -} - -func (m *Mock) InsertApp(app *models.App) (*models.App, error) { - // TODO: improve this mock method - return m.FakeApp, nil -} - -func (m *Mock) UpdateApp(app *models.App) (*models.App, error) { - // TODO: improve this mock method - return m.FakeApp, nil -} - -func (m *Mock) RemoveApp(appName string) error { - // TODO: improve this mock method - return nil -} - -func (m *Mock) GetRoute(appName, routePath string) (*models.Route, error) { - route := m.FakeRoute - if route == nil && m.FakeRoutes != nil { - for _, r := range m.FakeRoutes { - if r.AppName == appName && r.Path == routePath { - route = r - } +func (m *Mock) UpdateApp(ctx context.Context, app *models.App) (*models.App, error) { + a, err := m.GetApp(ctx, app.Name) + if err != nil { + return nil, err + } + if app.Config != nil { + if a.Config == nil { + a.Config = map[string]string{} + } + for k, v := range app.Config { + a.Config[k] = v } } + return a, nil +} +func (m *Mock) RemoveApp(ctx context.Context, appName string) error { + for i, a := range m.Apps { + if a.Name == appName { + m.Apps = append(m.Apps[:i], m.Apps[i+1:]...) + return nil + } + } + return models.ErrAppsNotFound +} + +func (m *Mock) GetRoute(ctx context.Context, appName, routePath string) (*models.Route, error) { + for _, r := range m.Routes { + if r.AppName == appName && r.Path == routePath { + return r, nil + } + } + return nil, models.ErrRoutesNotFound +} + +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) + } + } + return +} + +func (m *Mock) GetRoutesByApp(ctx context.Context, appName string, routeFilter *models.RouteFilter) (routes []*models.Route, err error) { + for _, r := range m.Routes { + if r.AppName == appName && (routeFilter.Path == "" || r.Path == routeFilter.Path) && (routeFilter.AppName == "" || r.AppName == routeFilter.AppName) { + routes = append(routes, r) + } + } + return +} + +func (m *Mock) InsertRoute(ctx context.Context, route *models.Route) (*models.Route, error) { + if r, _ := m.GetRoute(ctx, route.AppName, route.Path); r != nil { + return nil, models.ErrAppsAlreadyExists + } + m.Routes = append(m.Routes, route) return route, nil } -func (m *Mock) GetRoutes(routeFilter *models.RouteFilter) ([]*models.Route, error) { - // TODO: improve this mock method - return m.FakeRoutes, nil -} - -func (m *Mock) GetRoutesByApp(appName string, routeFilter *models.RouteFilter) ([]*models.Route, error) { - var routes []*models.Route - route := m.FakeRoute - if route == nil && m.FakeRoutes != nil { - for _, r := range m.FakeRoutes { - if r.AppName == appName && (routeFilter.Path == "" || r.Path == routeFilter.Path) && (routeFilter.AppName == "" || r.AppName == routeFilter.AppName) { - routes = append(routes, r) - } +func (m *Mock) UpdateRoute(ctx context.Context, route *models.Route) (*models.Route, error) { + r, err := m.GetRoute(ctx, route.AppName, route.Path) + if err != nil { + return nil, err + } + if route.Config != nil { + if route.Config == nil { + r.Config = map[string]string{} + } + for k, v := range route.Config { + r.Config[k] = v } } - - return routes, nil + return r, nil } -func (m *Mock) InsertRoute(route *models.Route) (*models.Route, error) { - // TODO: improve this mock method - return m.FakeRoute, nil +func (m *Mock) RemoveRoute(ctx context.Context, appName, routePath string) error { + for i, r := range m.Routes { + if r.AppName == appName && r.Path == routePath { + m.Routes = append(m.Routes[:i], m.Routes[i+1:]...) + return nil + } + } + return models.ErrRoutesNotFound } -func (m *Mock) UpdateRoute(route *models.Route) (*models.Route, error) { - // TODO: improve this mock method - return m.FakeRoute, nil -} - -func (m *Mock) RemoveRoute(appName, routePath string) error { +func (m *Mock) Put(ctx context.Context, key, value []byte) error { // TODO: improve this mock method return nil } -func (m *Mock) Put(key, value []byte) error { - // TODO: improve this mock method - return nil -} - -func (m *Mock) Get(key []byte) ([]byte, error) { +func (m *Mock) Get(ctx context.Context, key []byte) ([]byte, error) { // TODO: improve this mock method return []byte{}, nil } diff --git a/api/datastore/postgres/postgres.go b/api/datastore/postgres/postgres.go index 373169f3a..e9a6e3b1c 100644 --- a/api/datastore/postgres/postgres.go +++ b/api/datastore/postgres/postgres.go @@ -6,6 +6,8 @@ import ( "fmt" "net/url" + "context" + "github.com/Sirupsen/logrus" "github.com/iron-io/functions/api/models" "github.com/lib/pq" @@ -76,7 +78,7 @@ func New(url *url.URL) (models.Datastore, error) { return pg, nil } -func (ds *PostgresDatastore) InsertApp(app *models.App) (*models.App, error) { +func (ds *PostgresDatastore) InsertApp(ctx context.Context, app *models.App) (*models.App, error) { var cbyte []byte var err error @@ -111,7 +113,7 @@ func (ds *PostgresDatastore) InsertApp(app *models.App) (*models.App, error) { return app, nil } -func (ds *PostgresDatastore) UpdateApp(app *models.App) (*models.App, error) { +func (ds *PostgresDatastore) UpdateApp(ctx context.Context, app *models.App) (*models.App, error) { if app == nil { return nil, models.ErrAppsNotFound } @@ -147,7 +149,7 @@ func (ds *PostgresDatastore) UpdateApp(app *models.App) (*models.App, error) { return app, nil } -func (ds *PostgresDatastore) RemoveApp(appName string) error { +func (ds *PostgresDatastore) RemoveApp(ctx context.Context, appName string) error { if appName == "" { return models.ErrDatastoreEmptyAppName } @@ -164,7 +166,7 @@ func (ds *PostgresDatastore) RemoveApp(appName string) error { return nil } -func (ds *PostgresDatastore) GetApp(name string) (*models.App, error) { +func (ds *PostgresDatastore) GetApp(ctx context.Context, name string) (*models.App, error) { if name == "" { return nil, models.ErrDatastoreEmptyAppName } @@ -208,7 +210,7 @@ func scanApp(scanner rowScanner, app *models.App) error { return err } -func (ds *PostgresDatastore) GetApps(filter *models.AppFilter) ([]*models.App, error) { +func (ds *PostgresDatastore) GetApps(ctx context.Context, filter *models.AppFilter) ([]*models.App, error) { res := []*models.App{} rows, err := ds.db.Query(` @@ -239,7 +241,7 @@ func (ds *PostgresDatastore) GetApps(filter *models.AppFilter) ([]*models.App, e return res, nil } -func (ds *PostgresDatastore) InsertRoute(route *models.Route) (*models.Route, error) { +func (ds *PostgresDatastore) InsertRoute(ctx context.Context, route *models.Route) (*models.Route, error) { if route == nil { return nil, models.ErrDatastoreEmptyRoute } @@ -282,7 +284,7 @@ func (ds *PostgresDatastore) InsertRoute(route *models.Route) (*models.Route, er return route, nil } -func (ds *PostgresDatastore) UpdateRoute(route *models.Route) (*models.Route, error) { +func (ds *PostgresDatastore) UpdateRoute(ctx context.Context, route *models.Route) (*models.Route, error) { if route == nil { return nil, models.ErrDatastoreEmptyRoute } @@ -328,7 +330,7 @@ func (ds *PostgresDatastore) UpdateRoute(route *models.Route) (*models.Route, er return route, nil } -func (ds *PostgresDatastore) RemoveRoute(appName, routePath string) error { +func (ds *PostgresDatastore) RemoveRoute(ctx context.Context, appName, routePath string) error { if appName == "" { return models.ErrDatastoreEmptyAppName } @@ -381,7 +383,7 @@ func scanRoute(scanner rowScanner, route *models.Route) error { return err } -func (ds *PostgresDatastore) GetRoute(appName, routePath string) (*models.Route, error) { +func (ds *PostgresDatastore) GetRoute(ctx context.Context, appName, routePath string) (*models.Route, error) { if appName == "" { return nil, models.ErrDatastoreEmptyAppName } @@ -403,7 +405,7 @@ func (ds *PostgresDatastore) GetRoute(appName, routePath string) (*models.Route, return &route, nil } -func (ds *PostgresDatastore) GetRoutes(filter *models.RouteFilter) ([]*models.Route, error) { +func (ds *PostgresDatastore) GetRoutes(ctx context.Context, filter *models.RouteFilter) ([]*models.Route, error) { res := []*models.Route{} filterQuery := buildFilterQuery(filter) rows, err := ds.db.Query(fmt.Sprintf("%s %s", routeSelector, filterQuery)) @@ -428,7 +430,7 @@ func (ds *PostgresDatastore) GetRoutes(filter *models.RouteFilter) ([]*models.Ro return res, nil } -func (ds *PostgresDatastore) GetRoutesByApp(appName string, filter *models.RouteFilter) ([]*models.Route, error) { +func (ds *PostgresDatastore) GetRoutesByApp(ctx context.Context, appName string, filter *models.RouteFilter) ([]*models.Route, error) { res := []*models.Route{} filter.AppName = appName filterQuery := buildFilterQuery(filter) @@ -481,7 +483,7 @@ func buildFilterQuery(filter *models.RouteFilter) string { return filterQuery } -func (ds *PostgresDatastore) Put(key, value []byte) error { +func (ds *PostgresDatastore) Put(ctx context.Context, key, value []byte) error { _, err := ds.db.Exec(` INSERT INTO extras ( key, @@ -499,7 +501,7 @@ func (ds *PostgresDatastore) Put(key, value []byte) error { return nil } -func (ds *PostgresDatastore) Get(key []byte) ([]byte, error) { +func (ds *PostgresDatastore) Get(ctx context.Context, key []byte) ([]byte, error) { row := ds.db.QueryRow("SELECT value FROM extras WHERE key=$1", key) var value []byte diff --git a/api/datastore/postgres_test.go b/api/datastore/postgres_test.go index 806fd14e8..436864b9a 100644 --- a/api/datastore/postgres_test.go +++ b/api/datastore/postgres_test.go @@ -1,6 +1,7 @@ package datastore import ( + "context" "database/sql" "fmt" "os/exec" @@ -41,6 +42,8 @@ func TestPostgres(t *testing.T) { defer close() buf := setLogBuffer() + ctx := context.Background() + ds, err := New(tmpPostgres) if err != nil { t.Fatalf("Error when creating datastore: %v", err) @@ -57,31 +60,31 @@ func TestPostgres(t *testing.T) { } // Testing insert app - _, err = ds.InsertApp(nil) + _, err = ds.InsertApp(ctx, nil) if err != models.ErrDatastoreEmptyApp { t.Log(buf.String()) t.Fatalf("Test InsertApp(nil): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyApp, err) } - _, err = ds.InsertApp(&models.App{}) + _, err = ds.InsertApp(ctx, &models.App{}) if err != models.ErrDatastoreEmptyAppName { t.Log(buf.String()) t.Fatalf("Test InsertApp(nil): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyAppName, err) } - _, err = ds.InsertApp(testApp) + _, err = ds.InsertApp(ctx, testApp) if err != nil { t.Log(buf.String()) t.Fatalf("Test InsertApp: error when storing new app: %s", err) } - _, err = ds.InsertApp(testApp) + _, err = ds.InsertApp(ctx, testApp) if err != models.ErrAppsAlreadyExists { t.Log(buf.String()) t.Fatalf("Test InsertApp duplicated: expected error `%v`, but it was `%v`", models.ErrAppsAlreadyExists, err) } - _, err = ds.UpdateApp(&models.App{ + _, err = ds.UpdateApp(ctx, &models.App{ Name: testApp.Name, Config: map[string]string{ "TEST": "1", @@ -93,13 +96,13 @@ func TestPostgres(t *testing.T) { } // Testing get app - _, err = ds.GetApp("") + _, err = ds.GetApp(ctx, "") if err != models.ErrDatastoreEmptyAppName { t.Log(buf.String()) t.Fatalf("Test GetApp: expected error to be %v, but it was %s", models.ErrDatastoreEmptyAppName, err) } - app, err := ds.GetApp(testApp.Name) + app, err := ds.GetApp(ctx, testApp.Name) if err != nil { t.Log(buf.String()) t.Fatalf("Test GetApp: error: %s", err) @@ -110,7 +113,7 @@ func TestPostgres(t *testing.T) { } // Testing list apps - apps, err := ds.GetApps(&models.AppFilter{}) + apps, err := ds.GetApps(ctx, &models.AppFilter{}) if err != nil { t.Log(buf.String()) t.Fatalf("Test GetApps: unexpected error %v", err) @@ -124,18 +127,18 @@ func TestPostgres(t *testing.T) { } // Testing app delete - err = ds.RemoveApp("") + err = ds.RemoveApp(ctx, "") if err != models.ErrDatastoreEmptyAppName { t.Log(buf.String()) t.Fatalf("Test RemoveApp: expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyAppName, err) } - err = ds.RemoveApp(testApp.Name) + err = ds.RemoveApp(ctx, testApp.Name) if err != nil { t.Log(buf.String()) t.Fatalf("Test RemoveApp: error: %s", err) } - app, err = ds.GetApp(testApp.Name) + app, err = ds.GetApp(ctx, testApp.Name) if err != models.ErrAppsNotFound { t.Log(buf.String()) t.Fatalf("Test GetApp(removed): expected error `%v`, but it was `%v`", models.ErrAppsNotFound, err) @@ -146,7 +149,7 @@ func TestPostgres(t *testing.T) { } // Test update inexistent app - _, err = ds.UpdateApp(&models.App{ + _, err = ds.UpdateApp(ctx, &models.App{ Name: testApp.Name, Config: map[string]string{ "TEST": "1", @@ -158,47 +161,47 @@ func TestPostgres(t *testing.T) { } // Insert app again to test routes - ds.InsertApp(testApp) + ds.InsertApp(ctx, testApp) // Testing insert route - _, err = ds.InsertRoute(nil) + _, err = ds.InsertRoute(ctx, nil) if err != models.ErrDatastoreEmptyRoute { t.Log(buf.String()) t.Fatalf("Test InsertRoute(nil): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyRoute, err) } - _, err = ds.InsertRoute(testRoute) + _, err = ds.InsertRoute(ctx, testRoute) if err != nil { t.Log(buf.String()) t.Fatalf("Test InsertRoute: error when storing new route: %s", err) } - _, err = ds.InsertRoute(testRoute) + _, err = ds.InsertRoute(ctx, testRoute) if err != models.ErrRoutesAlreadyExists { t.Log(buf.String()) t.Fatalf("Test InsertRoute duplicated: expected error to be `%v`, but it was `%v`", models.ErrRoutesAlreadyExists, err) } - _, err = ds.UpdateRoute(testRoute) + _, err = ds.UpdateRoute(ctx, testRoute) if err != nil { t.Log(buf.String()) t.Fatalf("Test UpdateRoute: unexpected error: %v", err) } // Testing get - _, err = ds.GetRoute("a", "") + _, err = ds.GetRoute(ctx, "a", "") if err != models.ErrDatastoreEmptyRoutePath { t.Log(buf.String()) t.Fatalf("Test GetRoute(empty route path): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyRoutePath, err) } - _, err = ds.GetRoute("", "a") + _, err = ds.GetRoute(ctx, "", "a") if err != models.ErrDatastoreEmptyAppName { t.Log(buf.String()) t.Fatalf("Test GetRoute(empty app name): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyAppName, err) } - route, err := ds.GetRoute(testApp.Name, testRoute.Path) + route, err := ds.GetRoute(ctx, testApp.Name, testRoute.Path) if err != nil { t.Log(buf.String()) t.Fatalf("Test GetRoute: unexpected error %v", err) @@ -209,7 +212,7 @@ func TestPostgres(t *testing.T) { } // Testing list routes - routes, err := ds.GetRoutesByApp(testApp.Name, &models.RouteFilter{}) + routes, err := ds.GetRoutesByApp(ctx, testApp.Name, &models.RouteFilter{}) if err != nil { t.Log(buf.String()) t.Fatalf("Test GetRoutes: unexpected error %v", err) @@ -223,7 +226,7 @@ func TestPostgres(t *testing.T) { } // Testing list routes - routes, err = ds.GetRoutes(&models.RouteFilter{Image: testRoute.Image}) + routes, err = ds.GetRoutes(ctx, &models.RouteFilter{Image: testRoute.Image}) if err != nil { t.Log(buf.String()) t.Fatalf("Test GetRoutes: error: %s", err) @@ -237,25 +240,25 @@ func TestPostgres(t *testing.T) { } // Testing app delete - err = ds.RemoveRoute("", "") + err = ds.RemoveRoute(ctx, "", "") if err != models.ErrDatastoreEmptyAppName { t.Log(buf.String()) t.Fatalf("Test RemoveRoute(empty app name): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyAppName, err) } - err = ds.RemoveRoute("a", "") + err = ds.RemoveRoute(ctx, "a", "") if err != models.ErrDatastoreEmptyRoutePath { t.Log(buf.String()) t.Fatalf("Test RemoveRoute(empty route path): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyRoutePath, err) } - err = ds.RemoveRoute(testRoute.AppName, testRoute.Path) + err = ds.RemoveRoute(ctx, testRoute.AppName, testRoute.Path) if err != nil { t.Log(buf.String()) t.Fatalf("Test RemoveApp: unexpected error: %v", err) } - _, err = ds.UpdateRoute(&models.Route{ + _, err = ds.UpdateRoute(ctx, &models.Route{ AppName: testRoute.AppName, Path: testRoute.Path, Image: "test", @@ -265,7 +268,7 @@ func TestPostgres(t *testing.T) { t.Fatalf("Test UpdateRoute inexistent: expected error to be `%v`, but it was `%v`", models.ErrRoutesNotFound, err) } - route, err = ds.GetRoute(testRoute.AppName, testRoute.Path) + route, err = ds.GetRoute(ctx, testRoute.AppName, testRoute.Path) if err != models.ErrRoutesNotFound { t.Log(buf.String()) t.Fatalf("Test GetRoute: expected error `%v`, but it was `%v`", models.ErrRoutesNotFound, err) diff --git a/api/models/datastore.go b/api/models/datastore.go index d73cfcf7e..ca17b0996 100644 --- a/api/models/datastore.go +++ b/api/models/datastore.go @@ -1,25 +1,28 @@ package models -import "errors" +import ( + "context" + "errors" +) type Datastore interface { - GetApp(appName string) (*App, error) - GetApps(*AppFilter) ([]*App, error) - InsertApp(app *App) (*App, error) - UpdateApp(app *App) (*App, error) - RemoveApp(appName string) error + GetApp(ctx context.Context, appName string) (*App, error) + GetApps(ctx context.Context, filter *AppFilter) ([]*App, error) + InsertApp(ctx context.Context, app *App) (*App, error) + UpdateApp(ctx context.Context, app *App) (*App, error) + RemoveApp(ctx context.Context, appName string) error - GetRoute(appName, routePath string) (*Route, error) - GetRoutes(*RouteFilter) (routes []*Route, err error) - GetRoutesByApp(string, *RouteFilter) (routes []*Route, err error) - InsertRoute(route *Route) (*Route, error) - UpdateRoute(route *Route) (*Route, error) - RemoveRoute(appName, routePath string) error + GetRoute(ctx context.Context, appName, routePath string) (*Route, error) + GetRoutes(ctx context.Context, filter *RouteFilter) (routes []*Route, err error) + GetRoutesByApp(ctx context.Context, appName string, filter *RouteFilter) (routes []*Route, err error) + InsertRoute(ctx context.Context, route *Route) (*Route, error) + UpdateRoute(ctx context.Context, route *Route) (*Route, error) + RemoveRoute(ctx context.Context, appName, routePath string) error // The following provide a generic key value store for arbitrary data, can be used by extensions to store extra data // todo: should we namespace these by app? Then when an app is deleted, it can delete any of this extra data too. - Put([]byte, []byte) error - Get([]byte) ([]byte, error) + Put(context.Context, []byte, []byte) error + Get(context.Context, []byte) ([]byte, error) } var ( diff --git a/api/mqs/mock.go b/api/mqs/mock.go index 55d5c257c..eadae7f4f 100644 --- a/api/mqs/mock.go +++ b/api/mqs/mock.go @@ -7,10 +7,10 @@ import ( ) type Mock struct { - FakeApp *models.App - FakeApps []*models.App - FakeRoute *models.Route - FakeRoutes []*models.Route + FakeApp *models.App + Apps []*models.App + FakeRoute *models.Route + Routes []*models.Route } func (mock *Mock) Push(context.Context, *models.Task) (*models.Task, error) { diff --git a/api/server/apps_create.go b/api/server/apps_create.go index e71c7809c..6d5eee8e0 100644 --- a/api/server/apps_create.go +++ b/api/server/apps_create.go @@ -41,7 +41,7 @@ func (s *Server) handleAppCreate(c *gin.Context) { return } - _, err = Api.Datastore.InsertApp(wapp.App) + _, err = Api.Datastore.InsertApp(ctx, wapp.App) if err != nil { log.WithError(err).Errorln(models.ErrAppsCreate) c.JSON(http.StatusInternalServerError, simpleError(models.ErrAppsCreate)) diff --git a/api/server/apps_delete.go b/api/server/apps_delete.go index 9f591fc8d..b7190f307 100644 --- a/api/server/apps_delete.go +++ b/api/server/apps_delete.go @@ -15,7 +15,7 @@ func handleAppDelete(c *gin.Context) { appName := c.Param("app") - routes, err := Api.Datastore.GetRoutesByApp(appName, &models.RouteFilter{}) + routes, err := Api.Datastore.GetRoutesByApp(ctx, appName, &models.RouteFilter{}) if err != nil { log.WithError(err).Debug(models.ErrAppsRemoving) c.JSON(http.StatusInternalServerError, simpleError(models.ErrAppsRemoving)) @@ -28,7 +28,7 @@ func handleAppDelete(c *gin.Context) { return } - if err := Api.Datastore.RemoveApp(appName); err != nil { + if err := Api.Datastore.RemoveApp(ctx, appName); err != nil { log.WithError(err).Debug(models.ErrAppsRemoving) c.JSON(http.StatusInternalServerError, simpleError(models.ErrAppsRemoving)) return diff --git a/api/server/apps_get.go b/api/server/apps_get.go index 95ff231ed..054e8d631 100644 --- a/api/server/apps_get.go +++ b/api/server/apps_get.go @@ -14,15 +14,13 @@ func handleAppGet(c *gin.Context) { log := common.Logger(ctx) appName := c.Param("app") - app, err := Api.Datastore.GetApp(appName) + app, err := Api.Datastore.GetApp(ctx, appName) - if err != nil { + if err != nil && err != models.ErrAppsNotFound { log.WithError(err).Error(models.ErrAppsGet) c.JSON(http.StatusInternalServerError, simpleError(models.ErrAppsGet)) return - } - - if app == nil { + } else if app == nil { log.WithError(err).Error(models.ErrAppsNotFound) c.JSON(http.StatusNotFound, simpleError(models.ErrAppsNotFound)) return diff --git a/api/server/apps_list.go b/api/server/apps_list.go index 881c25c49..e8e65ee2a 100644 --- a/api/server/apps_list.go +++ b/api/server/apps_list.go @@ -15,7 +15,7 @@ func handleAppList(c *gin.Context) { filter := &models.AppFilter{} - apps, err := Api.Datastore.GetApps(filter) + apps, err := Api.Datastore.GetApps(ctx, filter) if err != nil { log.WithError(err).Debug(models.ErrAppsList) c.JSON(http.StatusInternalServerError, simpleError(models.ErrAppsList)) diff --git a/api/server/apps_test.go b/api/server/apps_test.go index 689b13523..e4f7b3fa0 100644 --- a/api/server/apps_test.go +++ b/api/server/apps_test.go @@ -85,17 +85,22 @@ func TestAppDelete(t *testing.T) { tasks := mockTasksConduit() defer close(tasks) - router := testRouter(&datastore.Mock{}, &mqs.Mock{}, testRunner(t), tasks) - for i, test := range []struct { + ds models.Datastore path string body string expectedCode int expectedError error }{ - {"/v1/apps", "", http.StatusNotFound, nil}, - {"/v1/apps/myapp", "", http.StatusOK, nil}, + {&datastore.Mock{}, "/v1/apps", "", http.StatusNotFound, nil}, + {&datastore.Mock{ + Apps: []*models.App{{ + Name: "myapp", + }}, + }, "/v1/apps/myapp", "", http.StatusOK, nil}, } { + router := testRouter(test.ds, &mqs.Mock{}, testRunner(t), tasks) + _, rec := routerRequest(t, router, "DELETE", test.path, nil) if rec.Code != test.expectedCode { @@ -203,9 +208,9 @@ func TestAppUpdate(t *testing.T) { // success {&datastore.Mock{ - FakeApp: &models.App{ + Apps: []*models.App{{ Name: "myapp", - }, + }}, }, "/v1/apps/myapp", `{ "app": { "config": { "test": "1" } } }`, http.StatusOK, nil}, } { router := testRouter(test.mock, &mqs.Mock{}, testRunner(t), tasks) diff --git a/api/server/apps_update.go b/api/server/apps_update.go index 6863a79c7..c7def80ed 100644 --- a/api/server/apps_update.go +++ b/api/server/apps_update.go @@ -28,7 +28,8 @@ func handleAppUpdate(c *gin.Context) { return } - app, err := Api.Datastore.UpdateApp(wapp.App) + wapp.App.Name = c.Param("app") + app, err := Api.Datastore.UpdateApp(ctx, wapp.App) if err != nil { log.WithError(err).Debug(models.ErrAppsUpdate) c.JSON(http.StatusInternalServerError, simpleError(models.ErrAppsUpdate)) diff --git a/api/server/routes_create.go b/api/server/routes_create.go index b1ae16f18..e0e5fca95 100644 --- a/api/server/routes_create.go +++ b/api/server/routes_create.go @@ -49,14 +49,12 @@ func (s *Server) handleRouteCreate(c *gin.Context) { return } - app, err := Api.Datastore.GetApp(wroute.Route.AppName) - if err != nil { + app, err := Api.Datastore.GetApp(ctx, wroute.Route.AppName) + if err != nil && err != models.ErrAppsNotFound { log.WithError(err).Error(models.ErrAppsGet) c.JSON(http.StatusInternalServerError, simpleError(models.ErrAppsGet)) return - } - - if app == nil { + } else if app == nil { // Create a new application and add the route to that new application newapp := &models.App{Name: wroute.Route.AppName} if err := newapp.Validate(); err != nil { @@ -65,7 +63,7 @@ func (s *Server) handleRouteCreate(c *gin.Context) { return } - app, err = Api.Datastore.InsertApp(newapp) + app, err = Api.Datastore.InsertApp(ctx, newapp) if err != nil { log.WithError(err).Error(models.ErrAppsCreate) c.JSON(http.StatusInternalServerError, simpleError(models.ErrAppsCreate)) @@ -73,7 +71,7 @@ func (s *Server) handleRouteCreate(c *gin.Context) { } } - _, err = Api.Datastore.InsertRoute(wroute.Route) + _, err = Api.Datastore.InsertRoute(ctx, wroute.Route) if err != nil { log.WithError(err).Error(models.ErrRoutesCreate) c.JSON(http.StatusInternalServerError, simpleError(models.ErrRoutesCreate)) diff --git a/api/server/routes_delete.go b/api/server/routes_delete.go index 08e026819..660b97c35 100644 --- a/api/server/routes_delete.go +++ b/api/server/routes_delete.go @@ -17,14 +17,14 @@ func (s *Server) handleRouteDelete(c *gin.Context) { appName := c.Param("app") routePath := path.Clean(c.Param("route")) - route, err := Api.Datastore.GetRoute(appName, routePath) + route, err := Api.Datastore.GetRoute(ctx, appName, routePath) if err != nil || route == nil { log.Error(models.ErrRoutesNotFound) c.JSON(http.StatusNotFound, simpleError(models.ErrRoutesNotFound)) return } - if err := Api.Datastore.RemoveRoute(appName, routePath); err != nil { + if err := Api.Datastore.RemoveRoute(ctx, appName, routePath); err != nil { log.WithError(err).Debug(models.ErrRoutesRemoving) c.JSON(http.StatusInternalServerError, simpleError(models.ErrRoutesRemoving)) return diff --git a/api/server/routes_get.go b/api/server/routes_get.go index 6f98df291..c43fcfbfb 100644 --- a/api/server/routes_get.go +++ b/api/server/routes_get.go @@ -18,15 +18,13 @@ func handleRouteGet(c *gin.Context) { appName := c.Param("app") routePath := path.Clean(c.Param("route")) - route, err := Api.Datastore.GetRoute(appName, routePath) - if err != nil { + route, err := Api.Datastore.GetRoute(ctx, appName, routePath) + if err != nil && err != models.ErrRoutesNotFound { + log.WithError(err).Error(models.ErrRoutesGet) c.JSON(http.StatusInternalServerError, simpleError(models.ErrRoutesGet)) return - } - - if route == nil { - log.Error(models.ErrRoutesNotFound) + } else if route == nil { c.JSON(http.StatusNotFound, simpleError(models.ErrRoutesNotFound)) return } diff --git a/api/server/routes_list.go b/api/server/routes_list.go index 72baee4f1..f0dc415c4 100644 --- a/api/server/routes_list.go +++ b/api/server/routes_list.go @@ -23,9 +23,9 @@ func handleRouteList(c *gin.Context) { var routes []*models.Route var err error if app := c.Param("app"); app != "" { - routes, err = Api.Datastore.GetRoutesByApp(app, filter) + routes, err = Api.Datastore.GetRoutesByApp(ctx, app, filter) } else { - routes, err = Api.Datastore.GetRoutes(filter) + routes, err = Api.Datastore.GetRoutes(ctx, filter) } if err != nil { diff --git a/api/server/routes_test.go b/api/server/routes_test.go index ad02235db..83f5fa3c9 100644 --- a/api/server/routes_test.go +++ b/api/server/routes_test.go @@ -64,22 +64,22 @@ func TestRouteDelete(t *testing.T) { tasks := mockTasksConduit() defer close(tasks) - router := testRouter(&datastore.Mock{ - FakeRoutes: []*models.Route{ - &models.Route{AppName: "a", Path: "/myroute"}, - }, - }, &mqs.Mock{}, testRunner(t), tasks) - for i, test := range []struct { + ds models.Datastore path string body string expectedCode int expectedError error }{ - {"/v1/apps/a/routes", "", http.StatusTemporaryRedirect, nil}, - {"/v1/apps/a/routes/myroute", "", http.StatusOK, nil}, - {"/v1/apps/a/routes/missing", "", http.StatusNotFound, nil}, + {&datastore.Mock{}, "/v1/apps/a/routes", "", http.StatusTemporaryRedirect, nil}, + {&datastore.Mock{}, "/v1/apps/a/routes/missing", "", http.StatusNotFound, nil}, + {&datastore.Mock{ + Routes: []*models.Route{ + {Path: "/myroute", AppName: "a"}, + }, + }, "/v1/apps/a/routes/myroute", "", http.StatusOK, nil}, } { + router := testRouter(test.ds, &mqs.Mock{}, testRunner(t), tasks) _, rec := routerRequest(t, router, "DELETE", test.path, nil) if rec.Code != test.expectedCode { @@ -175,22 +175,31 @@ func TestRouteUpdate(t *testing.T) { tasks := mockTasksConduit() defer close(tasks) - router := testRouter(&datastore.Mock{}, &mqs.Mock{}, testRunner(t), tasks) - for i, test := range []struct { + ds models.Datastore path string body string expectedCode int expectedError error }{ // errors - {"/v1/apps/a/routes/myroute/do", ``, http.StatusBadRequest, models.ErrInvalidJSON}, - {"/v1/apps/a/routes/myroute/do", `{}`, http.StatusBadRequest, models.ErrRoutesMissingNew}, + {&datastore.Mock{}, "/v1/apps/a/routes/myroute/do", ``, http.StatusBadRequest, models.ErrInvalidJSON}, + {&datastore.Mock{}, "/v1/apps/a/routes/myroute/do", `{}`, http.StatusBadRequest, models.ErrRoutesMissingNew}, // success - {"/v1/apps/a/routes/myroute/do", `{ "route": { "image": "iron/hello", "path": "/myroute" } }`, http.StatusOK, nil}, + {&datastore.Mock{ + Routes: []*models.Route{ + { + AppName: "a", + Path: "/myroute/do", + }, + }, + }, "/v1/apps/a/routes/myroute/do", `{ "route": { "image": "iron/hello", "path": "/myroute" } }`, http.StatusOK, nil}, } { + router := testRouter(test.ds, &mqs.Mock{}, testRunner(t), tasks) + body := bytes.NewBuffer([]byte(test.body)) + _, rec := routerRequest(t, router, "PUT", test.path, body) if rec.Code != test.expectedCode { diff --git a/api/server/routes_update.go b/api/server/routes_update.go index 0c016799b..35a2b8c87 100644 --- a/api/server/routes_update.go +++ b/api/server/routes_update.go @@ -43,7 +43,7 @@ func handleRouteUpdate(c *gin.Context) { } } - _, err = Api.Datastore.UpdateRoute(wroute.Route) + _, err = Api.Datastore.UpdateRoute(ctx, wroute.Route) if err != nil { log.WithError(err).Debug(models.ErrRoutesUpdate) c.JSON(http.StatusInternalServerError, simpleError(models.ErrRoutesUpdate)) diff --git a/api/server/runner.go b/api/server/runner.go index 3f2b600ff..0707c68b4 100644 --- a/api/server/runner.go +++ b/api/server/runner.go @@ -81,7 +81,7 @@ func (s *Server) handleRequest(c *gin.Context, enqueue models.Enqueue) { path = c.Request.URL.Path } - app, err := Api.Datastore.GetApp(appName) + app, err := Api.Datastore.GetApp(ctx, appName) if err != nil || app == nil { log.WithError(err).Error(models.ErrAppsNotFound) c.JSON(http.StatusNotFound, simpleError(models.ErrAppsNotFound)) @@ -96,7 +96,7 @@ func (s *Server) handleRequest(c *gin.Context, enqueue models.Enqueue) { } log.WithFields(logrus.Fields{"app": appName, "path": path}).Debug("Finding route on datastore") - routes, err := s.loadroutes(models.RouteFilter{AppName: appName, Path: path}) + routes, err := s.loadroutes(ctx, models.RouteFilter{AppName: appName, Path: path}) if err != nil { log.WithError(err).Error(models.ErrRoutesList) c.JSON(http.StatusInternalServerError, simpleError(models.ErrRoutesList)) @@ -122,11 +122,11 @@ func (s *Server) handleRequest(c *gin.Context, enqueue models.Enqueue) { c.JSON(http.StatusNotFound, simpleError(models.ErrRunnerRouteNotFound)) } -func (s *Server) loadroutes(filter models.RouteFilter) ([]*models.Route, error) { +func (s *Server) loadroutes(ctx context.Context, filter models.RouteFilter) ([]*models.Route, error) { resp, err := s.singleflight.do( filter, func() (interface{}, error) { - return Api.Datastore.GetRoutesByApp(filter.AppName, &filter) + return Api.Datastore.GetRoutesByApp(ctx, filter.AppName, &filter) }, ) return resp.([]*models.Route), err diff --git a/api/server/runner_async_test.go b/api/server/runner_async_test.go index c578eaef2..65ff1bad2 100644 --- a/api/server/runner_async_test.go +++ b/api/server/runner_async_test.go @@ -35,10 +35,10 @@ func TestRouteRunnerAsyncExecution(t *testing.T) { t.Skip() tasks := mockTasksConduit() ds := &datastore.Mock{ - FakeApps: []*models.App{ + Apps: []*models.App{ {Name: "myapp", Config: map[string]string{"app": "true"}}, }, - FakeRoutes: []*models.Route{ + Routes: []*models.Route{ {Type: "async", Path: "/myroute", AppName: "myapp", Image: "iron/hello", Config: map[string]string{"test": "true"}}, {Type: "async", Path: "/myerror", AppName: "myapp", Image: "iron/error", Config: map[string]string{"test": "true"}}, {Type: "async", Path: "/myroute/:param", AppName: "myapp", Image: "iron/hello", Config: map[string]string{"test": "true"}}, diff --git a/api/server/runner_test.go b/api/server/runner_test.go index 7cdd48031..1878716aa 100644 --- a/api/server/runner_test.go +++ b/api/server/runner_test.go @@ -26,7 +26,7 @@ func TestRouteRunnerGet(t *testing.T) { tasks := mockTasksConduit() router := testRouter(&datastore.Mock{ - FakeApps: []*models.App{ + Apps: []*models.App{ {Name: "myapp", Config: models.Config{}}, }, }, &mqs.Mock{}, testRunner(t), tasks) @@ -66,7 +66,7 @@ func TestRouteRunnerPost(t *testing.T) { tasks := mockTasksConduit() router := testRouter(&datastore.Mock{ - FakeApps: []*models.App{ + Apps: []*models.App{ {Name: "myapp", Config: models.Config{}}, }, }, &mqs.Mock{}, testRunner(t), tasks) @@ -113,10 +113,10 @@ func TestRouteRunnerExecution(t *testing.T) { go runner.StartWorkers(ctx, testRunner(t), tasks) router := testRouter(&datastore.Mock{ - FakeApps: []*models.App{ + Apps: []*models.App{ {Name: "myapp", Config: models.Config{}}, }, - FakeRoutes: []*models.Route{ + Routes: []*models.Route{ {Path: "/myroute", AppName: "myapp", Image: "iron/hello", Headers: map[string][]string{"X-Function": {"Test"}}}, {Path: "/myerror", AppName: "myapp", Image: "iron/error", Headers: map[string][]string{"X-Function": {"Test"}}}, }, diff --git a/api/server/server.go b/api/server/server.go index f5180b380..22e3ee4ec 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -56,20 +56,20 @@ func New(ctx context.Context, ds models.Datastore, mq models.MessageQueue, r *ru c.Set("ctx", ctx) c.Next() }) - Api.primeCache() + Api.primeCache(ctx) return Api } -func (s *Server) primeCache() { +func (s *Server) primeCache(ctx context.Context) { logrus.Info("priming cache with known routes") - apps, err := s.Datastore.GetApps(nil) + apps, err := s.Datastore.GetApps(ctx, nil) if err != nil { logrus.WithError(err).Error("cannot prime cache - could not load application list") return } for _, app := range apps { - routes, err := s.Datastore.GetRoutesByApp(app.Name, &models.RouteFilter{AppName: app.Name}) + routes, err := s.Datastore.GetRoutesByApp(ctx, app.Name, &models.RouteFilter{AppName: app.Name}) if err != nil { logrus.WithError(err).WithField("appName", app.Name).Error("cannot prime cache - could not load routes") continue