-
Notifications
You must be signed in to change notification settings - Fork 405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HTTP Triggers hookup #1086
HTTP Triggers hookup #1086
Conversation
api/datastore/sql/sql.go
Outdated
@@ -445,15 +511,17 @@ func (ds *SQLStore) GetAppByID(ctx context.Context, appID string) (*models.App, | |||
|
|||
// GetApps retrieves an array of apps according to a specific filter. | |||
func (ds *SQLStore) GetApps(ctx context.Context, filter *models.AppFilter) ([]*models.App, error) { | |||
res := []*models.App{} | |||
var res []*models.App |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for json we were at least in v1 returning an empty list. a nil list will be nil in json. we should probably have a package level var to skip the alloc, but that's the rationale if we're keeping that behavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah good point !
I just auto-refactoerd there.
We should check in DS tests here.
api/datastore/sql/sql.go
Outdated
} | ||
|
||
func (ds *SQLStore) GetFns(ctx context.Context, filter *models.FnFilter) ([]*models.Fn, error) { | ||
var res []*models.Fn // for json empty list |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
res := []*models.Fn{}
for json empty list ;)
api/datastore/sql/sql.go
Outdated
@@ -667,6 +881,48 @@ func (ds *SQLStore) GetRoutesByApp(ctx context.Context, appID string, filter *mo | |||
return res, nil | |||
} | |||
|
|||
func (ds *SQLStore) GetFnByID(ctx context.Context, fnID string) (*models.Fn, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
open ended question: it may be wise to require an app id as well as an fn id here to avoid security bugs where a user may be able to access another user's function which they shouldn't have access to by supplying the correct id. this would become an issue from some auth middleware, presumably, but would manifest as an issue at this level (because at auth time you wouldn't know the function doesn't exist on a certain other app until you look it up).
for example:
- Bob has an app
poodles
, with function id4242
. - Julie has an app
corgis
with a few functions on it. - Bob is Julie's sworn nemesis (ok, maybe not relevant).
- Julie calls the api at
/v2/apps/corgis/fns/4242
, is authenticated against thecorgis
app correctly, and grabs Bob's function4242
out of the db. Julie then sheathes Bob's beautiful poodle Fifi in the thick of Nordic winter (and maybe adopts it so that this is more of a rescue than a tale of malevolence?).
in any event, I have seen this before! maybe, we'd like to guard against it differently, but it's an issue at some level no less and the cost of adding app id to each of these endpoints is relatively minimal, as its already given in the API and we'd just be passing it down -- maybe, there are better ways though.
edit: apps are referenced by id in this scenario and poodles and corgis should be ids, but it detracts from the story so much I've left this tale of poodles and corgis here - use your imagination to replace the strings with made up ids, the issue is unchanged in this scenario :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My view is that access control is orthogonal to the API structure - makes more sense (in my per-haps 90s oriented API design mentality) to solve authz on a resource-level properly rather than relying on API to help you here .
Of course - getting the access control right (when you need access to the resource to assert on policy) is a harder problem that I leave as an excercise to the implementor of that feature.
All of this is consolidating at the Data store level right now which is good as it's sound w.r.t most ACL decisions but bad as it adds more complexity there.
I /think/ you can plausibly implement a reasonably power Authz policy based on the data store abstraction by making decision after the subordinate call is complete but before the interceptor returns - this is what I've seen in the past (i.e. you can't make an ACL on a object till you've loaded it)
api/models/datastore.go
Outdated
@@ -59,8 +56,44 @@ type Datastore interface { | |||
// ErrDatastoreEmptyRoutePath when routePath is empty. Returns ErrRoutesNotFound when no route exists. | |||
RemoveRoute(ctx context.Context, appID, routePath string) error | |||
|
|||
// GetDatabase returns the underlying sqlx database implementation | |||
GetDatabase() *sqlx.DB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the extension stuff (and in particular https://github.com/fnproject/ext-auth) was using this. i'm no fan either, but it may be better to wage that battle another time (up to you)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm good point - I think I chose to keep this broken in the very short term.
One option might be to return the root data source from the stack via this interface and then let the extensions up-cast to something that gives them the DB
api/server/server.go
Outdated
{ | ||
v2.GET("/apps", s.handleAppList) | ||
v2.POST("/apps", s.handleAppCreate) | ||
v2.GET("/apps/:appId", s.handleAppGet) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in the process of linting... would appreciate doing appID
/ fnID
/ etc. while you're in here (lint will yell), though I can do a sweep afterwards for a low low price for you my friend merchant voice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep
api/server/runner.go
Outdated
// Requires the following in the context: | ||
// * "app" | ||
// * "source" | ||
func (s *Server) handleTriggerHttpFunctionCall2(c *gin.Context) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps I missed it or it's still WIP (apologies), I don't see another handler that will allow invoking a function for any trigger type w/ cloud event data, only a handler for http triggers (which will mostly be serviced by an lb and can use the former, but we probably should have for convenience as well for 'getting started'). just didn't see anything and pointing this out in case, sure that something is in the works i'm just not sure of what :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, still WIP , haven't looked at cloud event endpoint - imagine that that would be a different URL
know it's WIP but left a few hopefully helpful comments, sorry if it's just something you hadn't gotten to yet and i'm just nagging, forgive me i was curious |
e4e4eed
to
76b60e8
Compare
Have rebased down, some of this stuff went in on the triggers merge - so might need fixing frlz on master |
Just doing another PR to fix the original feedback here, |
CLA BotThank you for your submission! It appears that the following authors have not signed our Contributor License Agreement:
Please do so now by visiting http://www.oracle.com/technetwork/community/oca-486395.html Once complete, let us know in our community Slack and we’ll send you an Fn T-shirt. We are working on modernizing the CLA process into a digital signature but it isn’t quite ready yet. Thank you for being a part of the Fn Community! |
586e74e
to
fb4eb1c
Compare
CLA BotAll committers have signed the CLA. |
api/server/runner_httptrigger.go
Outdated
return err | ||
} | ||
|
||
// TODO TRIGGERWIP Not sure I want this evil magic in my life here - shoud remove |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we need to just do this content type detection as a middleware for all endpoints on the incoming request and outgoing response if we're going to do it at all. the CRUD api needs it too, it just assumes json and doesn't error on content type or anything. anyway, feel free to remove, but i think some of the examples and maybe tests rely on this behavior for better or for worse so it may not be worth it (we can hide it). it's better than defaulting to json :)
70c44b8
to
ddec183
Compare
ddec183
to
18ee3a3
Compare
api/models/call.go
Outdated
@@ -149,6 +149,12 @@ type Call struct { | |||
|
|||
// App this call belongs to. | |||
AppID string `json:"app_id" db:"app_id"` | |||
|
|||
// App this call belongs to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
api/models/call.go
Outdated
// App this call belongs to. | ||
TriggerID string `json:"trigger_id" db:"trigger_id"` | ||
|
||
// App this call belongs to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed (and actually started populating these, which I'd missed)
@@ -71,46 +77,63 @@ func ValidTriggerType(a string) bool { | |||
} | |||
|
|||
var ( | |||
//ErrTriggerIDProvided indicates that a trigger ID was specified when it shouldn't have been |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ouch, this looks painful!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
golang/lint#263
It's the style guide
expectedError error | ||
}{ | ||
{"/t/app/route", "", http.StatusNotFound, models.ErrAppsNotFound}, | ||
{"/t/myapp/route", "", http.StatusNotFound, models.ErrTriggerNotFound}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No success test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep -about 30 of them further down the file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM quite a big change it would be nice to have @hhexo to review it. I am going to add him as reviewer
@@ -183,22 +200,18 @@ func (da *directDataAccess) Finish(ctx context.Context, mCall *models.Call, stde | |||
if async { | |||
// XXX (reed): delete MQ message, eventually | |||
// YYY (hhexo): yes, once we have the queued/running/finished mechanics | |||
// return da.mq.Delete(ctx, mCall) | |||
// return cda.mq.Delete(ctx, mCall) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this no-op if puzzle me. I think the idea here is to highlight the todo but shall we comment the entire 'if' ? The compiler will be grateful to us for saving some work :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
meh-the compiler will do that for free
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM thanks, this is a good step in carving out most of the hybrid stuff. i think we should aim to get the data access stuff out of the agent eventually, but this may be easier to do later.
This doesn't add invoke yet - and that will necessarily pay down some of the refactoring debt created here but I wanted to get black-box testing and functionality in place for HTTP triggers before we started the larger invoke refactor.
This also adds "unique by appId, source, type" to triggers and tests.
A lot of the changes are an initial refactor of the data store interfaces with a view to removing:
None of these are completely payed down yet so it's a bit entangled at the moment - Many of these things can wash out of invoke.