mirror of
https://github.com/openfaas/faasd.git
synced 2025-06-19 12:36:38 +00:00
Add support for namespace mutations
Adds support for: Get, Create, Update, Delete Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
committed by
Alex Ellis
parent
c83b649301
commit
57baf34f5a
10
Makefile
10
Makefile
@ -20,11 +20,15 @@ local:
|
|||||||
test:
|
test:
|
||||||
CGO_ENABLED=0 GOOS=linux go test -mod=vendor -ldflags $(LDFLAGS) ./...
|
CGO_ENABLED=0 GOOS=linux go test -mod=vendor -ldflags $(LDFLAGS) ./...
|
||||||
|
|
||||||
|
.PHONY: dist-local
|
||||||
|
dist-local:
|
||||||
|
CGO_ENABLED=0 GOOS=linux go build -mod=vendor -ldflags $(LDFLAGS) -o bin/faasd
|
||||||
|
|
||||||
.PHONY: dist
|
.PHONY: dist
|
||||||
dist:
|
dist:
|
||||||
CGO_ENABLED=0 GOOS=linux go build -mod=vendor -ldflags $(LDFLAGS) -a -installsuffix cgo -o bin/faasd
|
CGO_ENABLED=0 GOOS=linux go build -mod=vendor -ldflags $(LDFLAGS) -o bin/faasd
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -mod=vendor -ldflags $(LDFLAGS) -a -installsuffix cgo -o bin/faasd-armhf
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -mod=vendor -ldflags $(LDFLAGS) -o bin/faasd-armhf
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -mod=vendor -ldflags $(LDFLAGS) -a -installsuffix cgo -o bin/faasd-arm64
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -mod=vendor -ldflags $(LDFLAGS) -o bin/faasd-arm64
|
||||||
|
|
||||||
.PHONY: hashgen
|
.PHONY: hashgen
|
||||||
hashgen:
|
hashgen:
|
||||||
|
@ -97,7 +97,7 @@ func runInstall(_ *cobra.Command, _ []string) error {
|
|||||||
sudo journalctl -u faasd --lines 100 -f
|
sudo journalctl -u faasd --lines 100 -f
|
||||||
|
|
||||||
Login with:
|
Login with:
|
||||||
sudo cat /var/lib/faasd/secrets/basic-auth-password | faas-cli login -s`)
|
sudo -E cat /var/lib/faasd/secrets/basic-auth-password | faas-cli login -s`)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -93,18 +93,19 @@ func makeProviderCmd() *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bootstrapHandlers := types.FaaSHandlers{
|
bootstrapHandlers := types.FaaSHandlers{
|
||||||
FunctionProxy: proxy.NewHandlerFunc(*config, invokeResolver),
|
FunctionProxy: proxy.NewHandlerFunc(*config, invokeResolver),
|
||||||
DeleteFunction: handlers.MakeDeleteHandler(client, cni),
|
DeleteFunction: handlers.MakeDeleteHandler(client, cni),
|
||||||
DeployFunction: handlers.MakeDeployHandler(client, cni, baseUserSecretsPath, alwaysPull),
|
DeployFunction: handlers.MakeDeployHandler(client, cni, baseUserSecretsPath, alwaysPull),
|
||||||
FunctionLister: handlers.MakeReadHandler(client),
|
FunctionLister: handlers.MakeReadHandler(client),
|
||||||
FunctionStatus: handlers.MakeReplicaReaderHandler(client),
|
FunctionStatus: handlers.MakeReplicaReaderHandler(client),
|
||||||
ScaleFunction: handlers.MakeReplicaUpdateHandler(client, cni),
|
ScaleFunction: handlers.MakeReplicaUpdateHandler(client, cni),
|
||||||
UpdateFunction: handlers.MakeUpdateHandler(client, cni, baseUserSecretsPath, alwaysPull),
|
UpdateFunction: handlers.MakeUpdateHandler(client, cni, baseUserSecretsPath, alwaysPull),
|
||||||
Health: func(w http.ResponseWriter, r *http.Request) {},
|
Health: func(w http.ResponseWriter, r *http.Request) {},
|
||||||
Info: handlers.MakeInfoHandler(Version, GitCommit),
|
Info: handlers.MakeInfoHandler(Version, GitCommit),
|
||||||
ListNamespaces: handlers.MakeNamespacesLister(client),
|
ListNamespaces: handlers.MakeNamespacesLister(client),
|
||||||
Secrets: handlers.MakeSecretHandler(client.NamespaceService(), baseUserSecretsPath),
|
Secrets: handlers.MakeSecretHandler(client.NamespaceService(), baseUserSecretsPath),
|
||||||
Logs: logs.NewLogHandlerFunc(faasdlogs.New(), config.ReadTimeout),
|
Logs: logs.NewLogHandlerFunc(faasdlogs.New(), config.ReadTimeout),
|
||||||
|
MutateNamespace: handlers.MakeMutateNamespace(client),
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Listening on: 0.0.0.0:%d\n", *config.TCPPort)
|
log.Printf("Listening on: 0.0.0.0:%d\n", *config.TCPPort)
|
||||||
|
@ -257,7 +257,7 @@ sudo faasd install
|
|||||||
2020/02/17 17:38:06 Writing to: "/var/lib/faasd/secrets/basic-auth-password"
|
2020/02/17 17:38:06 Writing to: "/var/lib/faasd/secrets/basic-auth-password"
|
||||||
2020/02/17 17:38:06 Writing to: "/var/lib/faasd/secrets/basic-auth-user"
|
2020/02/17 17:38:06 Writing to: "/var/lib/faasd/secrets/basic-auth-user"
|
||||||
Login with:
|
Login with:
|
||||||
sudo cat /var/lib/faasd/secrets/basic-auth-password | faas-cli login -s
|
sudo -E cat /var/lib/faasd/secrets/basic-auth-password | faas-cli login -s
|
||||||
```
|
```
|
||||||
|
|
||||||
You can now log in either from this machine or a remote machine using the OpenFaaS UI, or CLI.
|
You can now log in either from this machine or a remote machine using the OpenFaaS UI, or CLI.
|
||||||
|
8
go.mod
8
go.mod
@ -17,7 +17,7 @@ require (
|
|||||||
github.com/morikuni/aec v1.0.0
|
github.com/morikuni/aec v1.0.0
|
||||||
github.com/opencontainers/runtime-spec v1.1.0-rc.3
|
github.com/opencontainers/runtime-spec v1.1.0-rc.3
|
||||||
github.com/openfaas/faas-provider v0.24.0
|
github.com/openfaas/faas-provider v0.24.0
|
||||||
github.com/openfaas/faas/gateway v0.0.0-20230628073303-c0d710c97ff7
|
github.com/openfaas/faas/gateway v0.0.0-20230707085301-9e6f814f6fd8
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/sethvargo/go-password v0.2.0
|
github.com/sethvargo/go-password v0.2.0
|
||||||
github.com/spf13/cobra v1.7.0
|
github.com/spf13/cobra v1.7.0
|
||||||
@ -81,10 +81,10 @@ require (
|
|||||||
github.com/opencontainers/image-spec v1.1.0-rc3 // indirect
|
github.com/opencontainers/image-spec v1.1.0-rc3 // indirect
|
||||||
github.com/opencontainers/runc v1.1.5 // indirect
|
github.com/opencontainers/runc v1.1.5 // indirect
|
||||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||||
github.com/openfaas/nats-queue-worker v0.0.0-20230117214128-3615ccb286cc // indirect
|
github.com/openfaas/nats-queue-worker v0.0.0-20230303171817-9dfe6fa61387 // indirect
|
||||||
github.com/otiai10/copy v1.12.0 // indirect
|
github.com/otiai10/copy v1.12.0 // indirect
|
||||||
github.com/prometheus/client_golang v1.16.0 // indirect
|
github.com/prometheus/client_golang v1.16.0 // indirect
|
||||||
github.com/prometheus/client_model v0.3.0 // indirect
|
github.com/prometheus/client_model v0.4.0 // indirect
|
||||||
github.com/prometheus/common v0.42.0 // indirect
|
github.com/prometheus/common v0.42.0 // indirect
|
||||||
github.com/prometheus/procfs v0.10.1 // indirect
|
github.com/prometheus/procfs v0.10.1 // indirect
|
||||||
github.com/rivo/uniseg v0.2.0 // indirect
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
@ -100,7 +100,7 @@ require (
|
|||||||
golang.org/x/crypto v0.10.0 // indirect
|
golang.org/x/crypto v0.10.0 // indirect
|
||||||
golang.org/x/mod v0.12.0 // indirect
|
golang.org/x/mod v0.12.0 // indirect
|
||||||
golang.org/x/net v0.10.0 // indirect
|
golang.org/x/net v0.10.0 // indirect
|
||||||
golang.org/x/sync v0.2.0 // indirect
|
golang.org/x/sync v0.3.0 // indirect
|
||||||
golang.org/x/text v0.10.0 // indirect
|
golang.org/x/text v0.10.0 // indirect
|
||||||
golang.org/x/tools v0.8.0 // indirect
|
golang.org/x/tools v0.8.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
|
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
|
||||||
|
8
go.sum
8
go.sum
@ -250,8 +250,12 @@ github.com/openfaas/faas/gateway v0.0.0-20230317100158-e44448c5dca2 h1:mSQlNX+et
|
|||||||
github.com/openfaas/faas/gateway v0.0.0-20230317100158-e44448c5dca2/go.mod h1:iQNG+Up27CXDLHgIr9mcifTzaPD2mYOFTZW8MHxib7M=
|
github.com/openfaas/faas/gateway v0.0.0-20230317100158-e44448c5dca2/go.mod h1:iQNG+Up27CXDLHgIr9mcifTzaPD2mYOFTZW8MHxib7M=
|
||||||
github.com/openfaas/faas/gateway v0.0.0-20230628073303-c0d710c97ff7 h1:L93R55OfxBjoWVR5bCWn1HHbVzyiNTL+hgWloS/hNrg=
|
github.com/openfaas/faas/gateway v0.0.0-20230628073303-c0d710c97ff7 h1:L93R55OfxBjoWVR5bCWn1HHbVzyiNTL+hgWloS/hNrg=
|
||||||
github.com/openfaas/faas/gateway v0.0.0-20230628073303-c0d710c97ff7/go.mod h1:REnxOe821v2IRlQEvj1Gjt5w1Xdshx8IT5/UF1MlEQc=
|
github.com/openfaas/faas/gateway v0.0.0-20230628073303-c0d710c97ff7/go.mod h1:REnxOe821v2IRlQEvj1Gjt5w1Xdshx8IT5/UF1MlEQc=
|
||||||
|
github.com/openfaas/faas/gateway v0.0.0-20230707085301-9e6f814f6fd8 h1:KJyo/Em7/Pzb61cGu0U8l3/6dBQAK/lMEZCK9can8WU=
|
||||||
|
github.com/openfaas/faas/gateway v0.0.0-20230707085301-9e6f814f6fd8/go.mod h1:dr/Cno1dEuFB7+OD8fzq+CApKMY9Gdbho4zJKl0nVzI=
|
||||||
github.com/openfaas/nats-queue-worker v0.0.0-20230117214128-3615ccb286cc h1:qMcVTwdbRAqZtQrYS9rvUxnbQY6nmqf7CIsjp7A+cOo=
|
github.com/openfaas/nats-queue-worker v0.0.0-20230117214128-3615ccb286cc h1:qMcVTwdbRAqZtQrYS9rvUxnbQY6nmqf7CIsjp7A+cOo=
|
||||||
github.com/openfaas/nats-queue-worker v0.0.0-20230117214128-3615ccb286cc/go.mod h1:s86POyW6C8S4CALFRhO8ax5sR2uaQUJQ0HaQGvbTpTc=
|
github.com/openfaas/nats-queue-worker v0.0.0-20230117214128-3615ccb286cc/go.mod h1:s86POyW6C8S4CALFRhO8ax5sR2uaQUJQ0HaQGvbTpTc=
|
||||||
|
github.com/openfaas/nats-queue-worker v0.0.0-20230303171817-9dfe6fa61387 h1:D4xbdy309Wdyhlm6PgJqUV/aR77VQQG8UTF+q0ay71c=
|
||||||
|
github.com/openfaas/nats-queue-worker v0.0.0-20230303171817-9dfe6fa61387/go.mod h1:s86POyW6C8S4CALFRhO8ax5sR2uaQUJQ0HaQGvbTpTc=
|
||||||
github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY=
|
github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY=
|
||||||
github.com/otiai10/copy v1.12.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww=
|
github.com/otiai10/copy v1.12.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
@ -266,6 +270,8 @@ github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lF
|
|||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
||||||
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||||
|
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
|
||||||
|
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
|
||||||
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
|
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
|
||||||
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
|
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
|
||||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
@ -387,6 +393,8 @@ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
|||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
@ -24,7 +24,7 @@ func (i *InvokeResolver) Resolve(functionName string) (url.URL, error) {
|
|||||||
actualFunctionName := functionName
|
actualFunctionName := functionName
|
||||||
log.Printf("Resolve: %q\n", actualFunctionName)
|
log.Printf("Resolve: %q\n", actualFunctionName)
|
||||||
|
|
||||||
namespace := getNamespace(functionName, faasd.DefaultFunctionNamespace)
|
namespace := getNamespaceOrDefault(functionName, faasd.DefaultFunctionNamespace)
|
||||||
|
|
||||||
if strings.Contains(functionName, ".") {
|
if strings.Contains(functionName, ".") {
|
||||||
actualFunctionName = strings.TrimSuffix(functionName, "."+namespace)
|
actualFunctionName = strings.TrimSuffix(functionName, "."+namespace)
|
||||||
@ -47,7 +47,7 @@ func (i *InvokeResolver) Resolve(functionName string) (url.URL, error) {
|
|||||||
return *urlRes, nil
|
return *urlRes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNamespace(name, defaultNamespace string) string {
|
func getNamespaceOrDefault(name, defaultNamespace string) string {
|
||||||
namespace := defaultNamespace
|
namespace := defaultNamespace
|
||||||
if strings.Contains(name, ".") {
|
if strings.Contains(name, ".") {
|
||||||
namespace = name[strings.LastIndexAny(name, ".")+1:]
|
namespace = name[strings.LastIndexAny(name, ".")+1:]
|
||||||
|
285
pkg/provider/handlers/mutate_namespaces.go
Normal file
285
pkg/provider/handlers/mutate_namespaces.go
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/openfaas/faas-provider/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MakeMutateNamespace(client *containerd.Client) func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Body != nil {
|
||||||
|
defer r.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodPost:
|
||||||
|
createNamespace(client, w, r)
|
||||||
|
case http.MethodGet:
|
||||||
|
getNamespace(client, w, r)
|
||||||
|
case http.MethodDelete:
|
||||||
|
deleteNamespace(client, w, r)
|
||||||
|
case http.MethodPut:
|
||||||
|
updateNamespace(client, w, r)
|
||||||
|
|
||||||
|
default:
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateNamespace(client *containerd.Client, w http.ResponseWriter, r *http.Request) {
|
||||||
|
req, err := parseNamespaceRequest(r)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), err.(*HttpError).Status)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
namespaceExists, err := namespaceExists(r.Context(), client, req.Name)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !namespaceExists {
|
||||||
|
http.Error(w, fmt.Sprintf("namespace %s not found", req.Name), http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
originalLabels, err := client.NamespaceService().Labels(r.Context(), req.Name)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasOpenFaaSLabel(originalLabels) {
|
||||||
|
http.Error(w, fmt.Sprintf("namespace %s is not an openfaas namespace", req.Name), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var exclusions []string
|
||||||
|
|
||||||
|
// build exclusions
|
||||||
|
for key, _ := range originalLabels {
|
||||||
|
if _, ok := req.Labels[key]; !ok {
|
||||||
|
exclusions = append(exclusions, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call SetLabel with empty string if label is to be removed
|
||||||
|
for _, key := range exclusions {
|
||||||
|
if err := client.NamespaceService().SetLabel(r.Context(), req.Name, key, ""); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now add the new labels
|
||||||
|
for key, value := range req.Labels {
|
||||||
|
if err := client.NamespaceService().SetLabel(r.Context(), req.Name, key, value); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteNamespace(client *containerd.Client, w http.ResponseWriter, r *http.Request) {
|
||||||
|
req, err := parseNamespaceRequest(r)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), err.(*HttpError).Status)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := client.NamespaceService().Delete(r.Context(), req.Name); err != nil {
|
||||||
|
if strings.Contains(err.Error(), "not found") {
|
||||||
|
http.Error(w, fmt.Sprintf("namespace %s not found", req.Name), http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
}
|
||||||
|
|
||||||
|
func namespaceExists(ctx context.Context, client *containerd.Client, name string) (bool, error) {
|
||||||
|
ns, err := client.NamespaceService().List(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for _, namespace := range ns {
|
||||||
|
if namespace == name {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNamespace(client *containerd.Client, w http.ResponseWriter, r *http.Request) {
|
||||||
|
req, err := parseNamespaceRequest(r)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), err.(*HttpError).Status)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
namespaceExists, err := namespaceExists(r.Context(), client, req.Name)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !namespaceExists {
|
||||||
|
http.Error(w, fmt.Sprintf("namespace %s not found", req.Name), http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
labels, err := client.NamespaceService().Labels(r.Context(), req.Name)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasOpenFaaSLabel(labels) {
|
||||||
|
http.Error(w, fmt.Sprintf("namespace %s not found", req.Name), http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res := types.FunctionNamespace{
|
||||||
|
Name: req.Name,
|
||||||
|
Labels: labels,
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
if err := json.NewEncoder(w).Encode(res); err != nil {
|
||||||
|
log.Printf("Get Namespace error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createNamespace(client *containerd.Client, w http.ResponseWriter, r *http.Request) {
|
||||||
|
req, err := parseNamespaceRequest(r)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), err.(*HttpError).Status)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if namespace exists, and it has the openfaas label
|
||||||
|
namespaces, err := client.NamespaceService().List(r.Context())
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for _, namespace := range namespaces {
|
||||||
|
if namespace == req.Name {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if found {
|
||||||
|
http.Error(w, fmt.Sprintf("namespace %s already exists", req.Name), http.StatusConflict)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := client.NamespaceService().Create(r.Context(), req.Name, req.Labels); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getNamespace returns a namespace object or an error
|
||||||
|
func parseNamespaceRequest(r *http.Request) (types.FunctionNamespace, error) {
|
||||||
|
var req types.FunctionNamespace
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
namespaceInPath := vars["name"]
|
||||||
|
|
||||||
|
if r.Method == http.MethodGet {
|
||||||
|
if namespaceInPath == "" {
|
||||||
|
return req, &HttpError{
|
||||||
|
Err: fmt.Errorf("namespace not specified in URL"),
|
||||||
|
Status: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.FunctionNamespace{
|
||||||
|
Name: namespaceInPath,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
body, _ := io.ReadAll(r.Body)
|
||||||
|
|
||||||
|
if err := json.Unmarshal(body, &req); err != nil {
|
||||||
|
return req, &HttpError{
|
||||||
|
Err: fmt.Errorf("error parsing request body: %s", err.Error()),
|
||||||
|
Status: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
if namespaceInPath == "" {
|
||||||
|
return req, &HttpError{
|
||||||
|
Err: fmt.Errorf("namespace not specified in URL"),
|
||||||
|
Status: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if req.Name != namespaceInPath {
|
||||||
|
return req, &HttpError{
|
||||||
|
Err: fmt.Errorf("namespace in request body does not match namespace in URL"),
|
||||||
|
Status: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Name == "" {
|
||||||
|
return req, &HttpError{
|
||||||
|
Err: fmt.Errorf("namespace not specified in request body"),
|
||||||
|
Status: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok := hasOpenFaaSLabel(req.Labels); !ok {
|
||||||
|
return req, &HttpError{
|
||||||
|
Err: fmt.Errorf("request does not have openfaas=1 label"),
|
||||||
|
Status: http.StatusBadRequest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasOpenFaaSLabel(labels map[string]string) bool {
|
||||||
|
if v, ok := labels["openfaas"]; ok && v == "1" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type HttpError struct {
|
||||||
|
Err error
|
||||||
|
Status int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *HttpError) Error() string {
|
||||||
|
return e.Err.Error()
|
||||||
|
}
|
23
vendor/github.com/openfaas/faas/gateway/LICENSE
generated
vendored
23
vendor/github.com/openfaas/faas/gateway/LICENSE
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2016-2018 Alex Ellis
|
|
||||||
Copyright (c) 2018 OpenFaaS Author(s)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
|
|
29
vendor/github.com/openfaas/faas/gateway/requests/forward_request.go
generated
vendored
29
vendor/github.com/openfaas/faas/gateway/requests/forward_request.go
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
package requests
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
import "net/url"
|
|
||||||
|
|
||||||
// ForwardRequest for proxying incoming requests
|
|
||||||
type ForwardRequest struct {
|
|
||||||
RawPath string
|
|
||||||
RawQuery string
|
|
||||||
Method string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewForwardRequest create a ForwardRequest
|
|
||||||
func NewForwardRequest(method string, url url.URL) ForwardRequest {
|
|
||||||
return ForwardRequest{
|
|
||||||
Method: method,
|
|
||||||
RawQuery: url.RawQuery,
|
|
||||||
RawPath: url.Path,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToURL create formatted URL
|
|
||||||
func (f *ForwardRequest) ToURL(addr string, watchdogPort int) string {
|
|
||||||
if len(f.RawQuery) > 0 {
|
|
||||||
return fmt.Sprintf("http://%s:%d%s?%s", addr, watchdogPort, f.RawPath, f.RawQuery)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("http://%s:%d%s", addr, watchdogPort, f.RawPath)
|
|
||||||
|
|
||||||
}
|
|
23
vendor/github.com/openfaas/faas/gateway/requests/prometheus.go
generated
vendored
23
vendor/github.com/openfaas/faas/gateway/requests/prometheus.go
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
// Copyright (c) Alex Ellis 2017. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
package requests
|
|
||||||
|
|
||||||
// PrometheusInnerAlertLabel PrometheusInnerAlertLabel
|
|
||||||
type PrometheusInnerAlertLabel struct {
|
|
||||||
AlertName string `json:"alertname"`
|
|
||||||
FunctionName string `json:"function_name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrometheusInnerAlert PrometheusInnerAlert
|
|
||||||
type PrometheusInnerAlert struct {
|
|
||||||
Status string `json:"status"`
|
|
||||||
Labels PrometheusInnerAlertLabel `json:"labels"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrometheusAlert as produced by AlertManager
|
|
||||||
type PrometheusAlert struct {
|
|
||||||
Status string `json:"status"`
|
|
||||||
Receiver string `json:"receiver"`
|
|
||||||
Alerts []PrometheusInnerAlert `json:"alerts"`
|
|
||||||
}
|
|
11
vendor/github.com/openfaas/faas/gateway/requests/requests.go
generated
vendored
11
vendor/github.com/openfaas/faas/gateway/requests/requests.go
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
// Copyright (c) Alex Ellis 2017. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
// Package requests package provides a client SDK or library for
|
|
||||||
// the OpenFaaS gateway REST API
|
|
||||||
package requests
|
|
||||||
|
|
||||||
// DeleteFunctionRequest delete a deployed function
|
|
||||||
type DeleteFunctionRequest struct {
|
|
||||||
FunctionName string `json:"functionName"`
|
|
||||||
}
|
|
1586
vendor/github.com/prometheus/client_model/go/metrics.pb.go
generated
vendored
1586
vendor/github.com/prometheus/client_model/go/metrics.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
10
vendor/golang.org/x/sync/errgroup/errgroup.go
generated
vendored
10
vendor/golang.org/x/sync/errgroup/errgroup.go
generated
vendored
@ -20,7 +20,7 @@ type token struct{}
|
|||||||
// A zero Group is valid, has no limit on the number of active goroutines,
|
// A zero Group is valid, has no limit on the number of active goroutines,
|
||||||
// and does not cancel on error.
|
// and does not cancel on error.
|
||||||
type Group struct {
|
type Group struct {
|
||||||
cancel func()
|
cancel func(error)
|
||||||
|
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ func (g *Group) done() {
|
|||||||
// returns a non-nil error or the first time Wait returns, whichever occurs
|
// returns a non-nil error or the first time Wait returns, whichever occurs
|
||||||
// first.
|
// first.
|
||||||
func WithContext(ctx context.Context) (*Group, context.Context) {
|
func WithContext(ctx context.Context) (*Group, context.Context) {
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := withCancelCause(ctx)
|
||||||
return &Group{cancel: cancel}, ctx
|
return &Group{cancel: cancel}, ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ func WithContext(ctx context.Context) (*Group, context.Context) {
|
|||||||
func (g *Group) Wait() error {
|
func (g *Group) Wait() error {
|
||||||
g.wg.Wait()
|
g.wg.Wait()
|
||||||
if g.cancel != nil {
|
if g.cancel != nil {
|
||||||
g.cancel()
|
g.cancel(g.err)
|
||||||
}
|
}
|
||||||
return g.err
|
return g.err
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ func (g *Group) Go(f func() error) {
|
|||||||
g.errOnce.Do(func() {
|
g.errOnce.Do(func() {
|
||||||
g.err = err
|
g.err = err
|
||||||
if g.cancel != nil {
|
if g.cancel != nil {
|
||||||
g.cancel()
|
g.cancel(g.err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ func (g *Group) TryGo(f func() error) bool {
|
|||||||
g.errOnce.Do(func() {
|
g.errOnce.Do(func() {
|
||||||
g.err = err
|
g.err = err
|
||||||
if g.cancel != nil {
|
if g.cancel != nil {
|
||||||
g.cancel()
|
g.cancel(g.err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
14
vendor/golang.org/x/sync/errgroup/go120.go
generated
vendored
Normal file
14
vendor/golang.org/x/sync/errgroup/go120.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build go1.20
|
||||||
|
// +build go1.20
|
||||||
|
|
||||||
|
package errgroup
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
func withCancelCause(parent context.Context) (context.Context, func(error)) {
|
||||||
|
return context.WithCancelCause(parent)
|
||||||
|
}
|
15
vendor/golang.org/x/sync/errgroup/pre_go120.go
generated
vendored
Normal file
15
vendor/golang.org/x/sync/errgroup/pre_go120.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !go1.20
|
||||||
|
// +build !go1.20
|
||||||
|
|
||||||
|
package errgroup
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
func withCancelCause(parent context.Context) (context.Context, func(error)) {
|
||||||
|
ctx, cancel := context.WithCancel(parent)
|
||||||
|
return ctx, func(error) { cancel() }
|
||||||
|
}
|
15
vendor/modules.txt
generated
vendored
15
vendor/modules.txt
generated
vendored
@ -339,10 +339,9 @@ github.com/openfaas/faas-provider/httputil
|
|||||||
github.com/openfaas/faas-provider/logs
|
github.com/openfaas/faas-provider/logs
|
||||||
github.com/openfaas/faas-provider/proxy
|
github.com/openfaas/faas-provider/proxy
|
||||||
github.com/openfaas/faas-provider/types
|
github.com/openfaas/faas-provider/types
|
||||||
# github.com/openfaas/faas/gateway v0.0.0-20230628073303-c0d710c97ff7
|
# github.com/openfaas/faas/gateway v0.0.0-20230707085301-9e6f814f6fd8
|
||||||
## explicit; go 1.19
|
## explicit; go 1.20
|
||||||
github.com/openfaas/faas/gateway/requests
|
# github.com/openfaas/nats-queue-worker v0.0.0-20230303171817-9dfe6fa61387
|
||||||
# github.com/openfaas/nats-queue-worker v0.0.0-20230117214128-3615ccb286cc
|
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
# github.com/otiai10/copy v1.12.0
|
# github.com/otiai10/copy v1.12.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
@ -355,8 +354,8 @@ github.com/prometheus/client_golang/prometheus
|
|||||||
github.com/prometheus/client_golang/prometheus/internal
|
github.com/prometheus/client_golang/prometheus/internal
|
||||||
github.com/prometheus/client_golang/prometheus/promauto
|
github.com/prometheus/client_golang/prometheus/promauto
|
||||||
github.com/prometheus/client_golang/prometheus/promhttp
|
github.com/prometheus/client_golang/prometheus/promhttp
|
||||||
# github.com/prometheus/client_model v0.3.0
|
# github.com/prometheus/client_model v0.4.0
|
||||||
## explicit; go 1.9
|
## explicit; go 1.18
|
||||||
github.com/prometheus/client_model/go
|
github.com/prometheus/client_model/go
|
||||||
# github.com/prometheus/common v0.42.0
|
# github.com/prometheus/common v0.42.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
@ -439,8 +438,8 @@ golang.org/x/net/http2/hpack
|
|||||||
golang.org/x/net/idna
|
golang.org/x/net/idna
|
||||||
golang.org/x/net/internal/timeseries
|
golang.org/x/net/internal/timeseries
|
||||||
golang.org/x/net/trace
|
golang.org/x/net/trace
|
||||||
# golang.org/x/sync v0.2.0
|
# golang.org/x/sync v0.3.0
|
||||||
## explicit
|
## explicit; go 1.17
|
||||||
golang.org/x/sync/errgroup
|
golang.org/x/sync/errgroup
|
||||||
golang.org/x/sync/semaphore
|
golang.org/x/sync/semaphore
|
||||||
# golang.org/x/sys v0.10.0
|
# golang.org/x/sys v0.10.0
|
||||||
|
Reference in New Issue
Block a user