diff --git a/api/server/fn_annotator.go b/api/server/fn_annotator.go index 479e3278f5..d4076f15f7 100644 --- a/api/server/fn_annotator.go +++ b/api/server/fn_annotator.go @@ -8,22 +8,24 @@ import ( "github.com/gin-gonic/gin" ) -//FnAnnotator Is used to inject trigger context (such as request URLs) into outbound trigger resources +//FnAnnotator Is used to inject fn context (such as request URLs) into outbound fn resources type FnAnnotator interface { // Annotates a trigger on read AnnotateFn(ctx *gin.Context, a *models.App, fn *models.Fn) (*models.Fn, error) } -type requestBasedFnAnnotator struct{} +type requestBasedFnAnnotator struct { + group, template string +} -func annotateFnWithBaseURL(baseURL string, app *models.App, fn *models.Fn) (*models.Fn, error) { +func annotateFnWithBaseURL(baseURL, group, template string, app *models.App, fn *models.Fn) (*models.Fn, error) { baseURL = strings.TrimSuffix(baseURL, "/") - src := strings.TrimPrefix(fn.ID, "/") - triggerPath := fmt.Sprintf("%s/invoke/%s", baseURL, src) + path := strings.Replace(template, ":fn_id", fn.ID, -1) + invokePath := fmt.Sprintf("%s%s%s", baseURL, group, path) newT := fn.Clone() - newAnnotations, err := newT.Annotations.With(models.FnInvokeEndpointAnnotation, triggerPath) + newAnnotations, err := newT.Annotations.With(models.FnInvokeEndpointAnnotation, invokePath) if err != nil { return nil, err } @@ -39,25 +41,25 @@ func (tp *requestBasedFnAnnotator) AnnotateFn(ctx *gin.Context, app *models.App, scheme = "https" } - return annotateFnWithBaseURL(fmt.Sprintf("%s://%s", scheme, ctx.Request.Host), app, t) + return annotateFnWithBaseURL(fmt.Sprintf("%s://%s", scheme, ctx.Request.Host), tp.group, tp.template, app, t) } //NewRequestBasedFnAnnotator creates a FnAnnotator that inspects the incoming request host and port, and uses this to generate fn invoke endpoint URLs based on those -func NewRequestBasedFnAnnotator() FnAnnotator { - return &requestBasedFnAnnotator{} +func NewRequestBasedFnAnnotator(group, template string) FnAnnotator { + return &requestBasedFnAnnotator{group: group, template: template} } type staticURLFnAnnotator struct { - baseURL string + baseURL, group, template string } //NewStaticURLFnAnnotator annotates triggers bases on a given, specified URL base - e.g. "https://my.domain" ---> "https://my.domain/t/app/source" -func NewStaticURLFnAnnotator(baseURL string) FnAnnotator { +func NewStaticURLFnAnnotator(baseURL, group, template string) FnAnnotator { - return &staticURLFnAnnotator{baseURL: baseURL} + return &staticURLFnAnnotator{baseURL: baseURL, group: group, template: template} } func (s *staticURLFnAnnotator) AnnotateFn(ctx *gin.Context, app *models.App, trigger *models.Fn) (*models.Fn, error) { - return annotateFnWithBaseURL(s.baseURL, app, trigger) + return annotateFnWithBaseURL(s.baseURL, s.group, s.template, app, trigger) } diff --git a/api/server/fn_annotator_test.go b/api/server/fn_annotator_test.go index 9ee01fb62a..e643e383d1 100644 --- a/api/server/fn_annotator_test.go +++ b/api/server/fn_annotator_test.go @@ -25,7 +25,7 @@ func TestAnnotateFnDefaultProvider(t *testing.T) { } // defaults the fn endpoint to the base URL if it's not already set - tep := NewRequestBasedFnAnnotator() + tep := NewRequestBasedFnAnnotator(DefaultInvokeGroup, DefaultInvokeTemplate) c, _ := gin.CreateTestContext(httptest.NewRecorder()) c.Request = httptest.NewRequest("GET", "/v2/foo/bar", bytes2.NewBuffer([]byte{})) @@ -67,7 +67,7 @@ func TestHttpsFn(t *testing.T) { } // defaults the Fn endpoint to the base URL if it's not already set - tep := NewRequestBasedFnAnnotator() + tep := NewRequestBasedFnAnnotator(DefaultInvokeGroup, DefaultInvokeTemplate) c, _ := gin.CreateTestContext(httptest.NewRecorder()) c.Request = httptest.NewRequest("GET", "/v2/foo/bar", bytes2.NewBuffer([]byte{})) @@ -97,7 +97,7 @@ func TestHttpsFn(t *testing.T) { } func TestStaticUrlFnAnnotator(t *testing.T) { - a := NewStaticURLFnAnnotator("http://foo.bar.com/somewhere") + a := NewStaticURLFnAnnotator("http://foo.bar.com/somewhere", DefaultInvokeGroup, DefaultInvokeTemplate) app := &models.App{ ID: "app_id", diff --git a/api/server/server.go b/api/server/server.go index 175fd359d0..05d9220912 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -119,6 +119,18 @@ const ( // EnvMaxRequestSize sets the limit in bytes for any API request's length. EnvMaxRequestSize = "FN_MAX_REQUEST_SIZE" + // EnvInvokeGroup sets the API group for the invoke endpoint + EnvInvokeGroup = "FN_INVOKE_GROUP" + + // EnvInvokeTemplate sets the API path for the invoke endpoing + EnvInvokeTemplate = "FN_INVOKE_PATH" + + // DefaultInvokeGroup is "/invoke" + DefaultInvokeGroup = "/invoke" + + // DefaultInvokeTemplate is "/:fn_id" + DefaultInvokeTemplate = "/:fn_id" + // DefaultLogFormat is text DefaultLogFormat = "text" @@ -266,14 +278,16 @@ func NewFromEnv(ctx context.Context, opts ...Option) *Server { opts = append(opts, LimitRequestBody(int64(getEnvInt(EnvMaxRequestSize, 0)))) + invokeGroup := getEnv(EnvInvokeGroup, DefaultInvokeGroup) + invokeTemplate := getEnv(EnvInvokeTemplate, DefaultInvokeTemplate) publicLBURL := getEnv(EnvPublicLoadBalancerURL, "") if publicLBURL != "" { logrus.Infof("using LB Base URL: '%s'", publicLBURL) opts = append(opts, WithTriggerAnnotator(NewStaticURLTriggerAnnotator(publicLBURL))) - opts = append(opts, WithFnAnnotator(NewStaticURLFnAnnotator(publicLBURL))) + opts = append(opts, WithFnAnnotator(NewStaticURLFnAnnotator(publicLBURL, invokeGroup, invokeTemplate))) } else { opts = append(opts, WithTriggerAnnotator(NewRequestBasedTriggerAnnotator())) - opts = append(opts, WithFnAnnotator(NewRequestBasedFnAnnotator())) + opts = append(opts, WithFnAnnotator(NewRequestBasedFnAnnotator(invokeGroup, invokeTemplate))) } // Agent handling depends on node type and several other options so it must be the last processed option. @@ -1105,9 +1119,7 @@ func (s *Server) bindHandlers(ctx context.Context) { profilerSetup(admin, "/debug") // Pure runners don't have any route, they have grpc - switch s.nodeType { - - case ServerTypeFull, ServerTypeAPI: + if s.nodeType == ServerTypeFull || s.nodeType == ServerTypeAPI { cleanv2 := engine.Group("/v2") v2 := cleanv2.Group("") v2.Use(s.apiMiddlewareWrapper()) @@ -1159,8 +1171,7 @@ func (s *Server) bindHandlers(ctx context.Context) { } } - switch s.nodeType { - case ServerTypeFull, ServerTypeLB, ServerTypeRunner: + if s.nodeType == ServerTypeFull || s.nodeType == ServerTypeLB || s.nodeType == ServerTypeRunner { if !s.noHTTTPTriggerEndpoint { lbTriggerGroup := engine.Group("/t") lbTriggerGroup.Any("/:app_name", s.handleHTTPTriggerCall) @@ -1168,8 +1179,8 @@ func (s *Server) bindHandlers(ctx context.Context) { } if !s.noFnInvokeEndpoint { - lbFnInvokeGroup := engine.Group("/invoke") - lbFnInvokeGroup.POST("/:fn_id", s.handleFnInvokeCall) + lbFnInvokeGroup := engine.Group(getEnv(EnvInvokeGroup, DefaultInvokeGroup)) + lbFnInvokeGroup.POST(getEnv(EnvInvokeTemplate, DefaultInvokeTemplate), s.handleFnInvokeCall) } } diff --git a/api/server/server_test.go b/api/server/server_test.go index 8446cdf748..ab3aab4385 100644 --- a/api/server/server_test.go +++ b/api/server/server_test.go @@ -27,7 +27,7 @@ func testServer(ds models.Datastore, mq models.MessageQueue, logDB models.LogSto WithAgent(rnr), WithType(nodeType), WithTriggerAnnotator(NewRequestBasedTriggerAnnotator()), - WithFnAnnotator(NewRequestBasedFnAnnotator()), + WithFnAnnotator(NewRequestBasedFnAnnotator(DefaultInvokeGroup, DefaultInvokeTemplate)), )...) } diff --git a/test/fn-system-tests/system_test.go b/test/fn-system-tests/system_test.go index ea01781a9a..3e19c528ac 100644 --- a/test/fn-system-tests/system_test.go +++ b/test/fn-system-tests/system_test.go @@ -232,7 +232,7 @@ func SetUpAPINode(ctx context.Context) (*server.Server, error) { opts = append(opts, server.WithLogURL("")) opts = append(opts, server.WithLogstoreFromDatastore()) opts = append(opts, server.WithTriggerAnnotator(server.NewStaticURLTriggerAnnotator(LBAddress))) - opts = append(opts, server.WithFnAnnotator(server.NewStaticURLFnAnnotator(LBAddress))) + opts = append(opts, server.WithFnAnnotator(server.NewStaticURLFnAnnotator(LBAddress, server.DefaultInvokeGroup, server.DefaultInvokeTemplate))) opts = append(opts, server.EnableShutdownEndpoint(ctx, func() {})) // TODO: do it properly return server.New(ctx, opts...), nil }