diff --git a/contrib/HACK.md b/contrib/HACK.md new file mode 100644 index 00000000..b525a29e --- /dev/null +++ b/contrib/HACK.md @@ -0,0 +1,11 @@ +## Hack on the UI for the API Gateway + +To hack on the UI without rebuilding the gateway mount the assets in a bind-mount like this: + +``` +$ docker network create func_functions --driver=overlay --attachable=true +$ docker run -v `pwd`/gateway/assets:/root/assets -v "/var/run/docker.sock:/var/run/docker.sock" \ +-p 8080:8080 --network=func_functions -ti alexellis2/faas-gateway:latest-dev +``` + +Then edit `docker-compose.yml` to use an external network and do a `./deploy_stack.sh`. diff --git a/docker-compose.yml b/docker-compose.yml index 4bce97c8..bbe6de3d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,13 +7,13 @@ services: - "/var/run/docker.sock:/var/run/docker.sock" ports: - 8080:8080 - image: alexellis2/faas-gateway:latest + image: alexellis2/faas-gateway:latest-dev networks: - functions deploy: placement: constraints: [node.role == manager] - + prometheus: image: quay.io/prometheus/prometheus:latest volumes: diff --git a/gateway/assets/newfunction.html b/gateway/assets/newfunction.html index d8d30b76..d0d6e856 100644 --- a/gateway/assets/newfunction.html +++ b/gateway/assets/newfunction.html @@ -20,6 +20,12 @@ +
+ + + + +
diff --git a/gateway/assets/script/bootstrap.js b/gateway/assets/script/bootstrap.js index 154b336b..ef44240d 100644 --- a/gateway/assets/script/bootstrap.js +++ b/gateway/assets/script/bootstrap.js @@ -98,6 +98,22 @@ app.controller("home", ['$scope', '$log', '$http', '$location', '$timeout', '$md }; $scope.createFunc = function() { + var options = { + url: "/system/functions", + data: $scope.item, + method: "POST", + headers: { "Content-Type": "application/json"}, + responseType: "json" + }; + + $http(options) + .then(function(response) { + $scope.invocationResponse = response.data; + $scope.invocationStatus = response.status; + }).catch(function(error1) { + $scope.invocationResponse = error1; + $scope.invocationStatus = null; + }); console.log($scope.item); $scope.closeDialog(); }; @@ -109,28 +125,3 @@ app.controller("home", ['$scope', '$log', '$http', '$location', '$timeout', '$md fetch(); }]); - - -// '' + -// ' '+ -// ''+ -// '
'+ -// ''+ -// ''+ -// ''+ -// ''+ -// ''+ -// ''+ -// ''+ -// ''+ -// '
'+ -// '
' + -// ' ' + -// ' ' + -// ' Close Dialog' + -// ' ' + -// ' ' + -// ' Create' + -// ' ' + -// ' ' + -// '
' \ No newline at end of file diff --git a/gateway/handlers/functionshandler.go b/gateway/handlers/functionshandler.go index 675eeb76..428cf28f 100644 --- a/gateway/handlers/functionshandler.go +++ b/gateway/handlers/functionshandler.go @@ -6,6 +6,8 @@ import ( "fmt" "net/http" + "io/ioutil" + "github.com/alexellis/faas/gateway/metrics" "github.com/alexellis/faas/gateway/requests" "github.com/docker/docker/api/types" @@ -59,3 +61,22 @@ func MakeFunctionReader(metricsOptions metrics.MetricOptions, c *client.Client) w.Write(functionBytes) } } + +// MakeNewFunctionHandler creates a new function (service) inside the swarm network. +func MakeNewFunctionHandler(metricsOptions metrics.MetricOptions, c *client.Client) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + + body, _ := ioutil.ReadAll(r.Body) + defer r.Body.Close() + + request := requests.CreateFunctionRequest{} + err := json.Unmarshal(body, &request) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + fmt.Println(request) + w.WriteHeader(http.StatusNotImplemented) + } +} diff --git a/gateway/requests/requests.go b/gateway/requests/requests.go index d0cf4512..1b1e24c5 100644 --- a/gateway/requests/requests.go +++ b/gateway/requests/requests.go @@ -1,5 +1,13 @@ package requests +// CreateFunctionRequest create a function in the swarm. +type CreateFunctionRequest struct { + Service string `json:"service"` + FProcess string `json:"fprocess"` + Image string `json:"image"` + Network string `json:"network"` +} + type AlexaSessionApplication struct { ApplicationId string `json:"applicationId"` } diff --git a/gateway/server.go b/gateway/server.go index 5dc96d7c..8f389dd0 100644 --- a/gateway/server.go +++ b/gateway/server.go @@ -7,7 +7,7 @@ import ( "time" "github.com/Sirupsen/logrus" - faashandlers "github.com/alexellis/faas/gateway/handlers" + faasHandlers "github.com/alexellis/faas/gateway/handlers" "github.com/alexellis/faas/gateway/metrics" "github.com/docker/docker/client" "github.com/gorilla/mux" @@ -35,14 +35,15 @@ func main() { r := mux.NewRouter() // r.StrictSlash(false) - functionHandler := faashandlers.MakeProxy(metricsOptions, true, dockerClient, &logger) + functionHandler := faasHandlers.MakeProxy(metricsOptions, true, dockerClient, &logger) r.HandleFunc("/function/{name:[a-zA-Z_0-9]+}", functionHandler) r.HandleFunc("/function/{name:[a-zA-Z_0-9]+}/", functionHandler) - r.HandleFunc("/system/alert", faashandlers.MakeAlertHandler(dockerClient)) - r.HandleFunc("/system/functions", faashandlers.MakeFunctionReader(metricsOptions, dockerClient)).Methods("GET") + r.HandleFunc("/system/alert", faasHandlers.MakeAlertHandler(dockerClient)) + r.HandleFunc("/system/functions", faasHandlers.MakeFunctionReader(metricsOptions, dockerClient)).Methods("GET") + r.HandleFunc("/system/functions", faasHandlers.MakeNewFunctionHandler(metricsOptions, dockerClient)).Methods("POST") - r.HandleFunc("/", faashandlers.MakeProxy(metricsOptions, false, dockerClient, &logger)).Methods("POST") + r.HandleFunc("/", faasHandlers.MakeProxy(metricsOptions, false, dockerClient, &logger)).Methods("POST") metricsHandler := metrics.PrometheusHandler() r.Handle("/metrics", metricsHandler) diff --git a/gateway/tests/integration/createfunction_test.go b/gateway/tests/integration/createfunction_test.go new file mode 100644 index 00000000..ff317f59 --- /dev/null +++ b/gateway/tests/integration/createfunction_test.go @@ -0,0 +1,34 @@ +package inttests + +import ( + "net/http" + "testing" +) + +func TestCreate_ValidJson(t *testing.T) { + reqBody := `{}` + _, code, err := fireRequest("http://localhost:8080/system/functions", http.MethodPost, reqBody) + + if err != nil { + t.Log(err) + t.Fail() + } + + if code != http.StatusOK { + t.Errorf("Got HTTP code: %d, want %d\n", code, http.StatusBadRequest) + } +} + +func TestCreateBadFunctionNotJson(t *testing.T) { + reqBody := `not json` + _, code, err := fireRequest("http://localhost:8080/system/functions", http.MethodPost, reqBody) + + if err != nil { + t.Log(err) + t.Fail() + } + + if code != http.StatusBadRequest { + t.Errorf("Got HTTP code: %d, want %d\n", code, http.StatusBadRequest) + } +} diff --git a/gateway/tests/integration/routes_test.go b/gateway/tests/integration/routes_test.go index 9560f6bc..8d3f9936 100644 --- a/gateway/tests/integration/routes_test.go +++ b/gateway/tests/integration/routes_test.go @@ -25,7 +25,7 @@ func fireRequestWithHeader(url string, method string, reqBody string, xheader st log.Fatal(err) } - req.Header.Set("User-Agent", "spacecount-tutorial") + req.Header.Set("User-Agent", "go-integration") if len(xheader) != 0 { req.Header.Set("X-Function", xheader) }