Skip to content

Commit

Permalink
Allow configuration of invoke URL pattern via environment variables
Browse files Browse the repository at this point in the history
  • Loading branch information
Richard Connon committed Feb 11, 2019
1 parent 6c43ac0 commit 6690cb8
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 22 deletions.
28 changes: 15 additions & 13 deletions api/server/fn_annotator.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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)

}
29 changes: 20 additions & 9 deletions api/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -1159,17 +1171,16 @@ 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)
lbTriggerGroup.Any("/:app_name/*trigger_source", s.handleHTTPTriggerCall)
}

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)
}
}

Expand Down

0 comments on commit 6690cb8

Please sign in to comment.