mirror of
https://github.com/openfaas/faas.git
synced 2025-06-25 00:03:24 +00:00
Add feature for invoking namespaced functions
When coupled with the latest version of faas-netes, the gateway can now invoke, query and deploy functions into alternative namespaces. Tested e2e by creating a namespace "fn" and deploying, then invoking a function deployed there and in the default namespace. Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
committed by
Alex Ellis
parent
0a90125aba
commit
238ce1be23
@ -5,8 +5,10 @@ package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -27,6 +29,28 @@ func TestSingleHostBaseURLResolver(t *testing.T) {
|
||||
|
||||
const watchdogPort = 8080
|
||||
|
||||
func TestFunctionAsHostBaseURLResolver_WithNamespaceOverride(t *testing.T) {
|
||||
|
||||
suffix := "openfaas-fn.local.cluster.svc."
|
||||
namespace := "openfaas-fn"
|
||||
newNS := "production-fn"
|
||||
|
||||
r := FunctionAsHostBaseURLResolver{FunctionSuffix: suffix, FunctionNamespace: namespace}
|
||||
|
||||
req, _ := http.NewRequest(http.MethodGet, "http://localhost/function/hello."+newNS, nil)
|
||||
|
||||
resolved := r.Resolve(req)
|
||||
|
||||
newSuffix := strings.Replace(suffix, namespace, newNS, -1)
|
||||
|
||||
want := fmt.Sprintf("http://hello.%s:%d", newSuffix, watchdogPort)
|
||||
log.Println(want)
|
||||
if resolved != want {
|
||||
t.Logf("r.Resolve failed, want: %s got: %s", want, resolved)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestFunctionAsHostBaseURLResolver_WithSuffix(t *testing.T) {
|
||||
suffix := "openfaas-fn.local.cluster.svc."
|
||||
r := FunctionAsHostBaseURLResolver{FunctionSuffix: suffix}
|
||||
@ -35,7 +59,7 @@ func TestFunctionAsHostBaseURLResolver_WithSuffix(t *testing.T) {
|
||||
|
||||
resolved := r.Resolve(req)
|
||||
want := fmt.Sprintf("http://hello.%s:%d", suffix, watchdogPort)
|
||||
|
||||
log.Println(want)
|
||||
if resolved != want {
|
||||
t.Logf("r.Resolve failed, want: %s got: %s", want, resolved)
|
||||
t.Fail()
|
||||
|
@ -179,7 +179,8 @@ func (s SingleHostBaseURLResolver) Resolve(r *http.Request) string {
|
||||
|
||||
// FunctionAsHostBaseURLResolver resolves URLs using a function from the URL as a host
|
||||
type FunctionAsHostBaseURLResolver struct {
|
||||
FunctionSuffix string
|
||||
FunctionSuffix string
|
||||
FunctionNamespace string
|
||||
}
|
||||
|
||||
// Resolve the base URL for a request
|
||||
@ -188,8 +189,13 @@ func (f FunctionAsHostBaseURLResolver) Resolve(r *http.Request) string {
|
||||
|
||||
const watchdogPort = 8080
|
||||
var suffix string
|
||||
|
||||
if len(f.FunctionSuffix) > 0 {
|
||||
suffix = "." + f.FunctionSuffix
|
||||
if index := strings.LastIndex(svcName, "."); index > -1 && len(svcName) > index+1 {
|
||||
suffix = strings.Replace(f.FunctionSuffix, f.FunctionNamespace, "", -1)
|
||||
} else {
|
||||
suffix = "." + f.FunctionSuffix
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf("http://%s%s:%d", svcName, suffix, watchdogPort)
|
||||
|
@ -135,6 +135,11 @@ func Test_getServiceName(t *testing.T) {
|
||||
url: "/function/testFunc",
|
||||
serviceName: "testFunc",
|
||||
},
|
||||
{
|
||||
name: "includes namespace",
|
||||
url: "/function/test1.fn",
|
||||
serviceName: "test1.fn",
|
||||
},
|
||||
{
|
||||
name: "can handle request with trailing slash",
|
||||
url: "/function/testFunc/",
|
||||
|
@ -32,6 +32,30 @@ func Test_Transform_RemovesFunctionPrefixWithSingleParam(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Transform_RemovesFunctionPrefixWithDotInName(t *testing.T) {
|
||||
|
||||
req, _ := http.NewRequest(http.MethodGet, "/function/figlet.fn", nil)
|
||||
transformer := FunctionPrefixTrimmingURLPathTransformer{}
|
||||
want := ""
|
||||
got := transformer.Transform(req)
|
||||
|
||||
if want != got {
|
||||
t.Errorf("want: %s, got: %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Transform_RemovesFunctionPrefixWithDotInNameAndPath(t *testing.T) {
|
||||
|
||||
req, _ := http.NewRequest(http.MethodGet, "/function/figlet.fn/employees", nil)
|
||||
transformer := FunctionPrefixTrimmingURLPathTransformer{}
|
||||
want := "/employees"
|
||||
got := transformer.Transform(req)
|
||||
|
||||
if want != got {
|
||||
t.Errorf("want: %s, got: %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Transform_RemovesFunctionPrefixWithParams(t *testing.T) {
|
||||
|
||||
req, _ := http.NewRequest(http.MethodGet, "/function/figlet/employees/100", nil)
|
||||
|
@ -66,7 +66,7 @@ func getServiceName(urlValue string) string {
|
||||
forward := "/function/"
|
||||
if strings.HasPrefix(urlValue, forward) {
|
||||
// With a path like `/function/xyz/rest/of/path?q=a`, the service
|
||||
// name we wish to locate is just the `xyz` portion. With a postive
|
||||
// name we wish to locate is just the `xyz` portion. With a positive
|
||||
// match on the regex below, it will return a three-element slice.
|
||||
// The item at index `0` is the same as `urlValue`, at `1`
|
||||
// will be the service name we need, and at `2` the rest of the path.
|
||||
|
Reference in New Issue
Block a user