mirror of
https://github.com/openfaas/faas.git
synced 2025-06-09 16:56:47 +00:00
Export new metrics for OpenFaaS Pro scaling
* Add service target metric * Add service min replicas metric * Add scale type metric These combined allow new auto-scaling modes and parameters for OpenFaaS Pro customers. Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
parent
34735d61d0
commit
d85d5e7239
@ -1,6 +1,6 @@
|
|||||||
FROM --platform=${BUILDPLATFORM:-linux/amd64} teamserverless/license-check:0.3.9 as license-check
|
FROM --platform=${BUILDPLATFORM:-linux/amd64} teamserverless/license-check:0.3.9 as license-check
|
||||||
|
|
||||||
FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.15 as build
|
FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.17 as build
|
||||||
|
|
||||||
ENV GO111MODULE=on
|
ENV GO111MODULE=on
|
||||||
ENV CGO_ENABLED=0
|
ENV CGO_ENABLED=0
|
||||||
@ -24,7 +24,6 @@ COPY go.sum go.sum
|
|||||||
COPY handlers handlers
|
COPY handlers handlers
|
||||||
COPY metrics metrics
|
COPY metrics metrics
|
||||||
COPY requests requests
|
COPY requests requests
|
||||||
COPY tests tests
|
|
||||||
|
|
||||||
COPY types types
|
COPY types types
|
||||||
COPY plugin plugin
|
COPY plugin plugin
|
||||||
|
@ -5,9 +5,7 @@ go 1.16
|
|||||||
require (
|
require (
|
||||||
github.com/docker/distribution v2.7.1+incompatible
|
github.com/docker/distribution v2.7.1+incompatible
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/nats-io/nats-server/v2 v2.3.2 // indirect
|
github.com/openfaas/faas-provider v0.18.7
|
||||||
github.com/nats-io/nats-streaming-server v0.22.0 // indirect
|
|
||||||
github.com/openfaas/faas-provider v0.18.6
|
|
||||||
github.com/openfaas/nats-queue-worker v0.0.0-20210726161954-ada9a31504c9
|
github.com/openfaas/nats-queue-worker v0.0.0-20210726161954-ada9a31504c9
|
||||||
github.com/prometheus/client_golang v1.9.0
|
github.com/prometheus/client_golang v1.9.0
|
||||||
github.com/prometheus/client_model v0.2.0
|
github.com/prometheus/client_model v0.2.0
|
||||||
|
@ -71,7 +71,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
|||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||||
@ -93,7 +92,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
|
|||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
|
||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
@ -105,8 +103,8 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
|||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
@ -141,7 +139,6 @@ github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa
|
|||||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
|
|
||||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||||
@ -176,12 +173,9 @@ github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY
|
|||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
|
|
||||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||||
@ -245,10 +239,9 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
|||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
github.com/openfaas/faas v0.0.0-20200422113858-a7c6c3920078/go.mod h1:E0m2rLup0Vvxg53BKxGgaYAGcZa3Xl+vvL7vSi5yQ14=
|
|
||||||
github.com/openfaas/faas-provider v0.18.6 h1:wypzvPKZqta8t4rx3W6Dm14ommBCc+rQ4DKDiBdGB7M=
|
|
||||||
github.com/openfaas/faas-provider v0.18.6/go.mod h1:fq1JL0mX4rNvVVvRLaLRJ3H6o667sHuyP5p/7SZEe98=
|
github.com/openfaas/faas-provider v0.18.6/go.mod h1:fq1JL0mX4rNvVVvRLaLRJ3H6o667sHuyP5p/7SZEe98=
|
||||||
github.com/openfaas/nats-queue-worker v0.0.0-20210726161233-3fa550b705fe/go.mod h1:njdij5dt/fm8EMrpUFiAW5u6tg7higDN+Xi+LXclDas=
|
github.com/openfaas/faas-provider v0.18.7 h1:Oq3N7KrlAkAZ23N5gzZfdA9F62vpUFk3ZkQpQuHeRBU=
|
||||||
|
github.com/openfaas/faas-provider v0.18.7/go.mod h1:S217qfIaMrv+XKJxgbhBzJzCfyFvoIF+BvYdDo6XIDQ=
|
||||||
github.com/openfaas/nats-queue-worker v0.0.0-20210726161954-ada9a31504c9 h1:dpG1UcgTesGfLetgT3ns1cAhP8XMDZqxnxTW1MlnwSc=
|
github.com/openfaas/nats-queue-worker v0.0.0-20210726161954-ada9a31504c9 h1:dpG1UcgTesGfLetgT3ns1cAhP8XMDZqxnxTW1MlnwSc=
|
||||||
github.com/openfaas/nats-queue-worker v0.0.0-20210726161954-ada9a31504c9/go.mod h1:ajlN2z+D8JPBq3kWNv4WLT6mtKPqlgeE3dYEx39d1tk=
|
github.com/openfaas/nats-queue-worker v0.0.0-20210726161954-ada9a31504c9/go.mod h1:ajlN2z+D8JPBq3kWNv4WLT6mtKPqlgeE3dYEx39d1tk=
|
||||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||||
@ -261,7 +254,6 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh
|
|||||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
|
|
||||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||||
@ -378,7 +370,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
|||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -495,7 +486,6 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ
|
|||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||||
@ -503,7 +493,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
|||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
const NameExpression = "-a-zA-Z_0-9."
|
const NameExpression = "-a-zA-Z_0-9."
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
if len(version.GitCommitMessage) == 0 {
|
if len(version.GitCommitMessage) == 0 {
|
||||||
version.GitCommitMessage = "See GitHub for latest changes"
|
version.GitCommitMessage = "See GitHub for latest changes"
|
||||||
}
|
}
|
||||||
@ -125,7 +126,7 @@ func main() {
|
|||||||
faasHandlers.DeployFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer, serviceAuthInjector)
|
faasHandlers.DeployFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer, serviceAuthInjector)
|
||||||
faasHandlers.DeleteFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer, serviceAuthInjector)
|
faasHandlers.DeleteFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer, serviceAuthInjector)
|
||||||
faasHandlers.UpdateFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer, serviceAuthInjector)
|
faasHandlers.UpdateFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer, serviceAuthInjector)
|
||||||
faasHandlers.QueryFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer, serviceAuthInjector)
|
faasHandlers.FunctionStatus = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer, serviceAuthInjector)
|
||||||
|
|
||||||
faasHandlers.InfoHandler = handlers.MakeInfoHandler(handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer, serviceAuthInjector))
|
faasHandlers.InfoHandler = handlers.MakeInfoHandler(handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer, serviceAuthInjector))
|
||||||
faasHandlers.SecretHandler = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer, serviceAuthInjector)
|
faasHandlers.SecretHandler = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer, serviceAuthInjector)
|
||||||
@ -198,8 +199,8 @@ func main() {
|
|||||||
decorateExternalAuth(faasHandlers.ListFunctions, config.UpstreamTimeout, config.AuthProxyURL, config.AuthProxyPassBody)
|
decorateExternalAuth(faasHandlers.ListFunctions, config.UpstreamTimeout, config.AuthProxyURL, config.AuthProxyPassBody)
|
||||||
faasHandlers.ScaleFunction =
|
faasHandlers.ScaleFunction =
|
||||||
decorateExternalAuth(faasHandlers.ScaleFunction, config.UpstreamTimeout, config.AuthProxyURL, config.AuthProxyPassBody)
|
decorateExternalAuth(faasHandlers.ScaleFunction, config.UpstreamTimeout, config.AuthProxyURL, config.AuthProxyPassBody)
|
||||||
faasHandlers.QueryFunction =
|
faasHandlers.FunctionStatus =
|
||||||
decorateExternalAuth(faasHandlers.QueryFunction, config.UpstreamTimeout, config.AuthProxyURL, config.AuthProxyPassBody)
|
decorateExternalAuth(faasHandlers.FunctionStatus, config.UpstreamTimeout, config.AuthProxyURL, config.AuthProxyPassBody)
|
||||||
faasHandlers.InfoHandler =
|
faasHandlers.InfoHandler =
|
||||||
decorateExternalAuth(faasHandlers.InfoHandler, config.UpstreamTimeout, config.AuthProxyURL, config.AuthProxyPassBody)
|
decorateExternalAuth(faasHandlers.InfoHandler, config.UpstreamTimeout, config.AuthProxyURL, config.AuthProxyPassBody)
|
||||||
faasHandlers.AsyncReport =
|
faasHandlers.AsyncReport =
|
||||||
@ -222,7 +223,7 @@ func main() {
|
|||||||
r.HandleFunc("/system/info", faasHandlers.InfoHandler).Methods(http.MethodGet)
|
r.HandleFunc("/system/info", faasHandlers.InfoHandler).Methods(http.MethodGet)
|
||||||
r.HandleFunc("/system/alert", faasHandlers.Alert).Methods(http.MethodPost)
|
r.HandleFunc("/system/alert", faasHandlers.Alert).Methods(http.MethodPost)
|
||||||
|
|
||||||
r.HandleFunc("/system/function/{name:["+NameExpression+"]+}", faasHandlers.QueryFunction).Methods(http.MethodGet)
|
r.HandleFunc("/system/function/{name:["+NameExpression+"]+}", faasHandlers.FunctionStatus).Methods(http.MethodGet)
|
||||||
r.HandleFunc("/system/functions", faasHandlers.ListFunctions).Methods(http.MethodGet)
|
r.HandleFunc("/system/functions", faasHandlers.ListFunctions).Methods(http.MethodGet)
|
||||||
r.HandleFunc("/system/functions", faasHandlers.DeployFunction).Methods(http.MethodPost)
|
r.HandleFunc("/system/functions", faasHandlers.DeployFunction).Methods(http.MethodPost)
|
||||||
r.HandleFunc("/system/functions", faasHandlers.DeleteFunction).Methods(http.MethodDelete)
|
r.HandleFunc("/system/functions", faasHandlers.DeleteFunction).Methods(http.MethodDelete)
|
||||||
|
@ -35,9 +35,7 @@ func AddMetricsHandler(handler http.HandlerFunc, prometheusQuery PrometheusQuery
|
|||||||
recorder.Code,
|
recorder.Code,
|
||||||
string(upstreamBody))
|
string(upstreamBody))
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
http.Error(w, "Unexpected status code retriving functions from backend", http.StatusInternalServerError)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
w.Write([]byte(fmt.Sprintf("List functions responded with code %d", recorder.Code)))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,28 +46,33 @@ func AddMetricsHandler(handler http.HandlerFunc, prometheusQuery PrometheusQuery
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Metrics upstream error: %s", err)
|
log.Printf("Metrics upstream error: %s", err)
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
http.Error(w, "Error parsing metrics from upstream provider/backend", http.StatusInternalServerError)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
w.Write([]byte("Error parsing metrics from upstream provider/backend."))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expr := url.QueryEscape(`sum(gateway_function_invocation_total{function_name=~".*", code=~".*"}) by (function_name, code)`)
|
// Ensure values are empty first.
|
||||||
// expr := "sum(gateway_function_invocation_total%7Bfunction_name%3D~%22.*%22%2C+code%3D~%22.*%22%7D)+by+(function_name%2C+code)"
|
for i := range functions {
|
||||||
results, fetchErr := prometheusQuery.Fetch(expr)
|
functions[i].InvocationCount = 0
|
||||||
if fetchErr != nil {
|
|
||||||
log.Printf("Error querying Prometheus API: %s\n", fetchErr.Error())
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(upstreamBody)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(functions) > 0 {
|
||||||
|
|
||||||
|
ns := functions[0].Namespace
|
||||||
|
q := fmt.Sprintf(`sum(gateway_function_invocation_total{function_name=~".*.%s"}) by (function_name)`, ns)
|
||||||
|
// Restrict query results to only function names matching namespace suffix.
|
||||||
|
|
||||||
|
results, err := prometheusQuery.Fetch(url.QueryEscape(q))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error querying Prometheus: %s\n", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
mixIn(&functions, results)
|
mixIn(&functions, results)
|
||||||
|
}
|
||||||
|
|
||||||
bytesOut, marshalErr := json.Marshal(functions)
|
bytesOut, err := json.Marshal(functions)
|
||||||
if marshalErr != nil {
|
if err != nil {
|
||||||
log.Println(marshalErr)
|
log.Printf("Error serializing functions: %s", err)
|
||||||
|
http.Error(w, "error writing response after adding metrics", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,25 +88,19 @@ func mixIn(functions *[]types.FunctionStatus, metrics *VectorQueryResponse) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure values are empty first.
|
|
||||||
for i := range *functions {
|
|
||||||
(*functions)[i].InvocationCount = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, function := range *functions {
|
for i, function := range *functions {
|
||||||
for _, v := range metrics.Data.Result {
|
for _, v := range metrics.Data.Result {
|
||||||
|
|
||||||
if v.Metric.FunctionName == fmt.Sprintf("%s.%s", function.Name, function.Namespace) {
|
if v.Metric.FunctionName == fmt.Sprintf("%s.%s", function.Name, function.Namespace) {
|
||||||
metricValue := v.Value[1]
|
metricValue := v.Value[1]
|
||||||
switch metricValue.(type) {
|
switch value := metricValue.(type) {
|
||||||
case string:
|
case string:
|
||||||
f, strconvErr := strconv.ParseFloat(metricValue.(string), 64)
|
f, err := strconv.ParseFloat(value, 64)
|
||||||
if strconvErr != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to convert value for metric: %s\n", strconvErr)
|
log.Printf("add_metrics: unable to convert value %q for metric: %s", value, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
(*functions)[i].InvocationCount += f
|
(*functions)[i].InvocationCount += f
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ func Test_FunctionsHandler_ReturnsJSONAndOneFunction(t *testing.T) {
|
|||||||
func makeFunctionsHandler() http.HandlerFunc {
|
func makeFunctionsHandler() http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
functions := []types.FunctionStatus{
|
functions := []types.FunctionStatus{
|
||||||
types.FunctionStatus{
|
{
|
||||||
Name: "func_echoit",
|
Name: "func_echoit",
|
||||||
Replicas: 0,
|
Replicas: 0,
|
||||||
Namespace: "openfaas-fn",
|
Namespace: "openfaas-fn",
|
||||||
|
@ -12,12 +12,14 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/openfaas/faas-provider/auth"
|
"github.com/openfaas/faas-provider/auth"
|
||||||
types "github.com/openfaas/faas-provider/types"
|
types "github.com/openfaas/faas-provider/types"
|
||||||
|
"github.com/openfaas/faas/gateway/scaling"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -46,6 +48,7 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
|
|||||||
e.metricOptions.GatewayFunctionsHistogram.Describe(ch)
|
e.metricOptions.GatewayFunctionsHistogram.Describe(ch)
|
||||||
e.metricOptions.ServiceReplicasGauge.Describe(ch)
|
e.metricOptions.ServiceReplicasGauge.Describe(ch)
|
||||||
e.metricOptions.GatewayFunctionInvocationStarted.Describe(ch)
|
e.metricOptions.GatewayFunctionInvocationStarted.Describe(ch)
|
||||||
|
e.metricOptions.ServiceTargetLoadGauge.Describe(ch)
|
||||||
|
|
||||||
e.metricOptions.ServiceMetrics.Counter.Describe(ch)
|
e.metricOptions.ServiceMetrics.Counter.Describe(ch)
|
||||||
e.metricOptions.ServiceMetrics.Histogram.Describe(ch)
|
e.metricOptions.ServiceMetrics.Histogram.Describe(ch)
|
||||||
@ -59,6 +62,8 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
|
|||||||
e.metricOptions.GatewayFunctionInvocationStarted.Collect(ch)
|
e.metricOptions.GatewayFunctionInvocationStarted.Collect(ch)
|
||||||
|
|
||||||
e.metricOptions.ServiceReplicasGauge.Reset()
|
e.metricOptions.ServiceReplicasGauge.Reset()
|
||||||
|
e.metricOptions.ServiceTargetLoadGauge.Reset()
|
||||||
|
|
||||||
for _, service := range e.services {
|
for _, service := range e.services {
|
||||||
var serviceName string
|
var serviceName string
|
||||||
if len(service.Namespace) > 0 {
|
if len(service.Namespace) > 0 {
|
||||||
@ -66,12 +71,54 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
|
|||||||
} else {
|
} else {
|
||||||
serviceName = service.Name
|
serviceName = service.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set current replica count
|
||||||
e.metricOptions.ServiceReplicasGauge.
|
e.metricOptions.ServiceReplicasGauge.
|
||||||
WithLabelValues(serviceName).
|
WithLabelValues(serviceName).
|
||||||
Set(float64(service.Replicas))
|
Set(float64(service.Replicas))
|
||||||
|
|
||||||
|
// Set minimum replicas
|
||||||
|
minReplicas := scaling.DefaultMinReplicas
|
||||||
|
if service.Labels != nil {
|
||||||
|
a := *service.Labels
|
||||||
|
if v, ok := a[scaling.MinScaleLabel]; ok && len(v) > 0 {
|
||||||
|
val, _ := strconv.Atoi(v)
|
||||||
|
minReplicas = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e.metricOptions.ServiceMinReplicasGauge.
|
||||||
|
WithLabelValues(serviceName).
|
||||||
|
Set(float64(minReplicas))
|
||||||
|
|
||||||
|
// Set scale type
|
||||||
|
scaleType := scaling.DefaultTypeScale
|
||||||
|
if service.Labels != nil {
|
||||||
|
a := *service.Labels
|
||||||
|
if v, ok := a[scaling.ScaleTypeLabel]; ok && len(v) > 0 {
|
||||||
|
scaleType = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set target load
|
||||||
|
targetScale := scaling.DefaultTargetLoad
|
||||||
|
if service.Labels != nil {
|
||||||
|
a := *service.Labels
|
||||||
|
if v, ok := a[scaling.TargetLoadLabel]; ok && len(v) > 0 {
|
||||||
|
val, _ := strconv.Atoi(v)
|
||||||
|
targetScale = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e.metricOptions.ServiceTargetLoadGauge.
|
||||||
|
WithLabelValues(serviceName, scaleType).
|
||||||
|
Set(float64(targetScale))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e.metricOptions.ServiceReplicasGauge.Collect(ch)
|
e.metricOptions.ServiceReplicasGauge.Collect(ch)
|
||||||
|
e.metricOptions.ServiceMinReplicasGauge.Collect(ch)
|
||||||
|
e.metricOptions.ServiceTargetLoadGauge.Collect(ch)
|
||||||
|
|
||||||
e.metricOptions.ServiceMetrics.Counter.Collect(ch)
|
e.metricOptions.ServiceMetrics.Counter.Collect(ch)
|
||||||
e.metricOptions.ServiceMetrics.Histogram.Collect(ch)
|
e.metricOptions.ServiceMetrics.Histogram.Collect(ch)
|
||||||
|
@ -44,21 +44,21 @@ func Test_Describe_DescribesThePrometheusMetrics(t *testing.T) {
|
|||||||
expectedGatewayFunctionInvocationDesc := `Desc{fqName: "gateway_function_invocation_total", help: "Function metrics", constLabels: {}, variableLabels: [function_name code]}`
|
expectedGatewayFunctionInvocationDesc := `Desc{fqName: "gateway_function_invocation_total", help: "Function metrics", constLabels: {}, variableLabels: [function_name code]}`
|
||||||
actualGatewayFunctionInvocationDesc := d.String()
|
actualGatewayFunctionInvocationDesc := d.String()
|
||||||
if expectedGatewayFunctionInvocationDesc != actualGatewayFunctionInvocationDesc {
|
if expectedGatewayFunctionInvocationDesc != actualGatewayFunctionInvocationDesc {
|
||||||
t.Errorf("Want %s, got: %s", expectedGatewayFunctionInvocationDesc, actualGatewayFunctionInvocationDesc)
|
t.Errorf("Want\n%s\ngot\n%s", expectedGatewayFunctionInvocationDesc, actualGatewayFunctionInvocationDesc)
|
||||||
}
|
}
|
||||||
|
|
||||||
d = <-ch
|
d = <-ch
|
||||||
expectedGatewayFunctionsHistogramDesc := `Desc{fqName: "gateway_functions_seconds", help: "Function time taken", constLabels: {}, variableLabels: [function_name]}`
|
expectedGatewayFunctionsHistogramDesc := `Desc{fqName: "gateway_functions_seconds", help: "Function time taken", constLabels: {}, variableLabels: [function_name]}`
|
||||||
actualGatewayFunctionsHistogramDesc := d.String()
|
actualGatewayFunctionsHistogramDesc := d.String()
|
||||||
if expectedGatewayFunctionsHistogramDesc != actualGatewayFunctionsHistogramDesc {
|
if expectedGatewayFunctionsHistogramDesc != actualGatewayFunctionsHistogramDesc {
|
||||||
t.Errorf("Want %s, got: %s", expectedGatewayFunctionsHistogramDesc, actualGatewayFunctionsHistogramDesc)
|
t.Errorf("Want\n%s\ngot\n%s", expectedGatewayFunctionsHistogramDesc, actualGatewayFunctionsHistogramDesc)
|
||||||
}
|
}
|
||||||
|
|
||||||
d = <-ch
|
d = <-ch
|
||||||
expectedServiceReplicasGaugeDesc := `Desc{fqName: "gateway_service_count", help: "Service replicas", constLabels: {}, variableLabels: [function_name]}`
|
expectedServiceReplicasGaugeDesc := `Desc{fqName: "gateway_service_count", help: "Current count of replicas for function", constLabels: {}, variableLabels: [function_name]}`
|
||||||
actualServiceReplicasGaugeDesc := d.String()
|
actualServiceReplicasGaugeDesc := d.String()
|
||||||
if expectedServiceReplicasGaugeDesc != actualServiceReplicasGaugeDesc {
|
if expectedServiceReplicasGaugeDesc != actualServiceReplicasGaugeDesc {
|
||||||
t.Errorf("Want %s, got: %s", expectedServiceReplicasGaugeDesc, actualServiceReplicasGaugeDesc)
|
t.Errorf("Want\n%s\ngot\n%s", expectedServiceReplicasGaugeDesc, actualServiceReplicasGaugeDesc)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,11 @@ type MetricOptions struct {
|
|||||||
GatewayFunctionInvocation *prometheus.CounterVec
|
GatewayFunctionInvocation *prometheus.CounterVec
|
||||||
GatewayFunctionsHistogram *prometheus.HistogramVec
|
GatewayFunctionsHistogram *prometheus.HistogramVec
|
||||||
GatewayFunctionInvocationStarted *prometheus.CounterVec
|
GatewayFunctionInvocationStarted *prometheus.CounterVec
|
||||||
|
|
||||||
ServiceReplicasGauge *prometheus.GaugeVec
|
ServiceReplicasGauge *prometheus.GaugeVec
|
||||||
|
ServiceMinReplicasGauge *prometheus.GaugeVec
|
||||||
|
ServiceTargetLoadGauge *prometheus.GaugeVec
|
||||||
|
|
||||||
ServiceMetrics *ServiceMetricOptions
|
ServiceMetrics *ServiceMetricOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,11 +66,29 @@ func BuildMetricsOptions() MetricOptions {
|
|||||||
prometheus.GaugeOpts{
|
prometheus.GaugeOpts{
|
||||||
Namespace: "gateway",
|
Namespace: "gateway",
|
||||||
Name: "service_count",
|
Name: "service_count",
|
||||||
Help: "Service replicas",
|
Help: "Current count of replicas for function",
|
||||||
},
|
},
|
||||||
[]string{"function_name"},
|
[]string{"function_name"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
serviceMinReplicas := prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Namespace: "gateway",
|
||||||
|
Name: "service_min",
|
||||||
|
Help: "Minium replicas for function",
|
||||||
|
},
|
||||||
|
[]string{"function_name"},
|
||||||
|
)
|
||||||
|
|
||||||
|
serviceTargetLoad := prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Namespace: "gateway",
|
||||||
|
Name: "service_target_load",
|
||||||
|
Help: "Target load for function",
|
||||||
|
},
|
||||||
|
[]string{"function_name", "scaling_type"},
|
||||||
|
)
|
||||||
|
|
||||||
// For automatic monitoring and alerting (RED method)
|
// For automatic monitoring and alerting (RED method)
|
||||||
histogram := prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
histogram := prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||||
Subsystem: "http",
|
Subsystem: "http",
|
||||||
@ -104,6 +126,8 @@ func BuildMetricsOptions() MetricOptions {
|
|||||||
GatewayFunctionsHistogram: gatewayFunctionsHistogram,
|
GatewayFunctionsHistogram: gatewayFunctionsHistogram,
|
||||||
GatewayFunctionInvocation: gatewayFunctionInvocation,
|
GatewayFunctionInvocation: gatewayFunctionInvocation,
|
||||||
ServiceReplicasGauge: serviceReplicas,
|
ServiceReplicasGauge: serviceReplicas,
|
||||||
|
ServiceMinReplicasGauge: serviceMinReplicas,
|
||||||
|
ServiceTargetLoadGauge: serviceTargetLoad,
|
||||||
ServiceMetrics: serviceMetricOptions,
|
ServiceMetrics: serviceMetricOptions,
|
||||||
GatewayFunctionInvocationStarted: gatewayFunctionInvocationStarted,
|
GatewayFunctionInvocationStarted: gatewayFunctionInvocationStarted,
|
||||||
}
|
}
|
||||||
|
@ -100,12 +100,15 @@ func (s ExternalServiceQuery) GetReplicas(serviceName, serviceNamespace string)
|
|||||||
scalingFactor := uint64(scaling.DefaultScalingFactor)
|
scalingFactor := uint64(scaling.DefaultScalingFactor)
|
||||||
availableReplicas := function.AvailableReplicas
|
availableReplicas := function.AvailableReplicas
|
||||||
|
|
||||||
|
targetLoad := uint64(scaling.DefaultTargetLoad)
|
||||||
|
|
||||||
if function.Labels != nil {
|
if function.Labels != nil {
|
||||||
labels := *function.Labels
|
labels := *function.Labels
|
||||||
|
|
||||||
minReplicas = extractLabelValue(labels[scaling.MinScaleLabel], minReplicas)
|
minReplicas = extractLabelValue(labels[scaling.MinScaleLabel], minReplicas)
|
||||||
maxReplicas = extractLabelValue(labels[scaling.MaxScaleLabel], maxReplicas)
|
maxReplicas = extractLabelValue(labels[scaling.MaxScaleLabel], maxReplicas)
|
||||||
extractedScalingFactor := extractLabelValue(labels[scaling.ScalingFactorLabel], scalingFactor)
|
extractedScalingFactor := extractLabelValue(labels[scaling.ScalingFactorLabel], scalingFactor)
|
||||||
|
targetLoad = extractLabelValue(labels[scaling.TargetLoadLabel], targetLoad)
|
||||||
|
|
||||||
if extractedScalingFactor >= 0 && extractedScalingFactor <= 100 {
|
if extractedScalingFactor >= 0 && extractedScalingFactor <= 100 {
|
||||||
scalingFactor = extractedScalingFactor
|
scalingFactor = extractedScalingFactor
|
||||||
@ -113,6 +116,7 @@ func (s ExternalServiceQuery) GetReplicas(serviceName, serviceNamespace string)
|
|||||||
log.Printf("Bad Scaling Factor: %d, is not in range of [0 - 100]. Will fallback to %d", extractedScalingFactor, scalingFactor)
|
log.Printf("Bad Scaling Factor: %d, is not in range of [0 - 100]. Will fallback to %d", extractedScalingFactor, scalingFactor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("GetReplicas [%s.%s] took: %fs", serviceName, serviceNamespace, time.Since(start).Seconds())
|
log.Printf("GetReplicas [%s.%s] took: %fs", serviceName, serviceNamespace, time.Since(start).Seconds())
|
||||||
|
|
||||||
return scaling.ServiceQueryResponse{
|
return scaling.ServiceQueryResponse{
|
||||||
@ -122,6 +126,7 @@ func (s ExternalServiceQuery) GetReplicas(serviceName, serviceNamespace string)
|
|||||||
ScalingFactor: scalingFactor,
|
ScalingFactor: scalingFactor,
|
||||||
AvailableReplicas: availableReplicas,
|
AvailableReplicas: availableReplicas,
|
||||||
Annotations: function.Annotations,
|
Annotations: function.Annotations,
|
||||||
|
TargetLoad: targetLoad,
|
||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ func TestGetReplicasExistentFn(t *testing.T) {
|
|||||||
MinReplicas: uint64(scaling.DefaultMinReplicas),
|
MinReplicas: uint64(scaling.DefaultMinReplicas),
|
||||||
ScalingFactor: uint64(scaling.DefaultScalingFactor),
|
ScalingFactor: uint64(scaling.DefaultScalingFactor),
|
||||||
AvailableReplicas: 0,
|
AvailableReplicas: 0,
|
||||||
|
TargetLoad: 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
var injector middleware.AuthInjector
|
var injector middleware.AuthInjector
|
||||||
@ -89,7 +90,7 @@ func TestGetReplicasExistentFn(t *testing.T) {
|
|||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
if svcQryResp != expectedSvcQryResp {
|
if svcQryResp != expectedSvcQryResp {
|
||||||
t.Logf("Unexpected return values - wanted %+v, got: %+v ", expectedSvcQryResp, svcQryResp)
|
t.Logf("Unexpected return values - wanted\n%+v\ngot\n%+v ", expectedSvcQryResp, svcQryResp)
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,11 @@ const (
|
|||||||
// DefaultScalingFactor is the defining proportion for the scaling increments.
|
// DefaultScalingFactor is the defining proportion for the scaling increments.
|
||||||
DefaultScalingFactor = 20
|
DefaultScalingFactor = 20
|
||||||
|
|
||||||
|
// DefaultTargetLoad
|
||||||
|
DefaultTargetLoad = 10
|
||||||
|
|
||||||
|
DefaultTypeScale = "rps"
|
||||||
|
|
||||||
// MinScaleLabel label indicating min scale for a function
|
// MinScaleLabel label indicating min scale for a function
|
||||||
MinScaleLabel = "com.openfaas.scale.min"
|
MinScaleLabel = "com.openfaas.scale.min"
|
||||||
|
|
||||||
@ -18,4 +23,10 @@ const (
|
|||||||
|
|
||||||
// ScalingFactorLabel label indicates the scaling factor for a function
|
// ScalingFactorLabel label indicates the scaling factor for a function
|
||||||
ScalingFactorLabel = "com.openfaas.scale.factor"
|
ScalingFactorLabel = "com.openfaas.scale.factor"
|
||||||
|
|
||||||
|
// TargetLoadLabel see also DefaultTargetScale
|
||||||
|
TargetLoadLabel = "com.openfaas.scale.target"
|
||||||
|
|
||||||
|
// ScaleTypeLabel see also DefaultScaleType
|
||||||
|
ScaleTypeLabel = "com.openfaas.scale.type"
|
||||||
)
|
)
|
||||||
|
@ -17,4 +17,5 @@ type ServiceQueryResponse struct {
|
|||||||
ScalingFactor uint64
|
ScalingFactor uint64
|
||||||
AvailableReplicas uint64
|
AvailableReplicas uint64
|
||||||
Annotations *map[string]string
|
Annotations *map[string]string
|
||||||
|
TargetLoad uint64
|
||||||
}
|
}
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
# Integration testing
|
|
||||||
|
|
||||||
These tests should be run against the sample stack included in the repository root.
|
|
||||||
|
|
||||||
## Deploy the stack
|
|
||||||
```
|
|
||||||
./deploy_stack.sh
|
|
||||||
faas-cli deploy -f ./stack.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
## Remove the stack
|
|
||||||
1. Delete all OpenFaaS deployed functions
|
|
||||||
```
|
|
||||||
faas-cli remove
|
|
||||||
docker stack rm func
|
|
||||||
```
|
|
@ -1,88 +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 inttests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
types "github.com/openfaas/faas-provider/types"
|
|
||||||
requests "github.com/openfaas/faas/gateway/requests"
|
|
||||||
)
|
|
||||||
|
|
||||||
func createFunction(request types.FunctionDeployment) (string, int, error) {
|
|
||||||
marshalled, _ := json.Marshal(request)
|
|
||||||
return fireRequest("http://localhost:8080/system/functions", http.MethodPost, string(marshalled))
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteFunction(name string) (string, int, error) {
|
|
||||||
marshalled, _ := json.Marshal(requests.DeleteFunctionRequest{FunctionName: name})
|
|
||||||
return fireRequest("http://localhost:8080/system/functions", http.MethodDelete, string(marshalled))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreate_ValidRequest(t *testing.T) {
|
|
||||||
request := types.FunctionDeployment{
|
|
||||||
Service: "test_resizer",
|
|
||||||
Image: "functions/resizer",
|
|
||||||
EnvProcess: "",
|
|
||||||
}
|
|
||||||
|
|
||||||
_, code, err := createFunction(request)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Log(err)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedErrorCode := http.StatusAccepted
|
|
||||||
if code != expectedErrorCode {
|
|
||||||
t.Errorf("Got HTTP code: %d, want %d\n", code, expectedErrorCode)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteFunction("test_resizer")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreate_InvalidImage(t *testing.T) {
|
|
||||||
request := types.FunctionDeployment{
|
|
||||||
Service: "test_resizer",
|
|
||||||
Image: "a b c",
|
|
||||||
EnvProcess: "",
|
|
||||||
}
|
|
||||||
|
|
||||||
body, code, err := createFunction(request)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Log(err)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedErrorCode := http.StatusBadRequest
|
|
||||||
if code != expectedErrorCode {
|
|
||||||
t.Errorf("Got HTTP code: %d, want %d\n", code, expectedErrorCode)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedErrorSlice := "is not a valid repository/tag"
|
|
||||||
if !strings.Contains(body, expectedErrorSlice) {
|
|
||||||
t.Errorf("Error message %s does not contain: %s\n", body, expectedErrorSlice)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreate_InvalidJson(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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +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 inttests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDelete_EmptyFunctionGivenFails(t *testing.T) {
|
|
||||||
reqBody := `{"functionName":""}`
|
|
||||||
_, code, err := fireRequest("http://localhost:8080/system/functions", http.MethodDelete, 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDelete_NonExistingFunctionGives404(t *testing.T) {
|
|
||||||
reqBody := `{"functionName":"does_not_exist"}`
|
|
||||||
_, code, err := fireRequest("http://localhost:8080/system/functions", http.MethodDelete, reqBody)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Log(err)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if code != http.StatusNotFound {
|
|
||||||
t.Errorf("Got HTTP code: %d, want %d\n", code, http.StatusNotFound)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
package inttests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/openfaas/faas/gateway/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_InfoEndpoint_Returns_200(t *testing.T) {
|
|
||||||
_, code, err := fireRequest("http://localhost:8080/system/info", http.MethodGet, "")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Log(err)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
wantCode := http.StatusOK
|
|
||||||
if code != wantCode {
|
|
||||||
t.Errorf("status code, want: %d, got: %d", wantCode, code)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_InfoEndpoint_Returns_Gateway_Version_SHA_And_Message(t *testing.T) {
|
|
||||||
body, _, err := fireRequest("http://localhost:8080/system/info", http.MethodGet, "")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Log(err)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
gatewayInfo := &types.GatewayInfo{}
|
|
||||||
err = json.Unmarshal([]byte(body), gatewayInfo)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Could not unmarshal gateway info, response body:%s, error:%s", body, err.Error())
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(gatewayInfo.Version.SHA) != 40 {
|
|
||||||
t.Errorf("length of SHA incorrect, want: %d, got: %d. Json body was %s", 40, len(gatewayInfo.Version.SHA), body)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(gatewayInfo.Version.CommitMessage) == 0 {
|
|
||||||
t.Errorf("length of commit message should be greater than 0. Json body was %s", body)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_InfoEndpoint_Returns_Arch(t *testing.T) {
|
|
||||||
body, _, err := fireRequest("http://localhost:8080/system/info", http.MethodGet, "")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Log(err)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
gatewayInfo := &types.GatewayInfo{}
|
|
||||||
err = json.Unmarshal([]byte(body), gatewayInfo)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Could not unmarshal gateway info, response body:%s, error:%s", body, err.Error())
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(gatewayInfo.Arch) == 0 {
|
|
||||||
t.Errorf("value of arch should be non-empty")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,125 +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 inttests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Before running these tests do a Docker stack deploy.
|
|
||||||
|
|
||||||
func fireRequest(url string, method string, reqBody string) (string, int, error) {
|
|
||||||
headers := make(map[string]string)
|
|
||||||
return fireRequestWithHeaders(url, method, reqBody, headers)
|
|
||||||
}
|
|
||||||
|
|
||||||
func fireRequestWithHeaders(url string, method string, reqBody string, headers map[string]string) (string, int, error) {
|
|
||||||
httpClient := http.Client{
|
|
||||||
Timeout: time.Second * 2, // Maximum of 2 secs
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest(method, url, bytes.NewBufferString(reqBody))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("User-Agent", "go-integration")
|
|
||||||
for kk, vv := range headers {
|
|
||||||
req.Header.Set(kk, vv)
|
|
||||||
}
|
|
||||||
|
|
||||||
res, getErr := httpClient.Do(req)
|
|
||||||
if getErr != nil {
|
|
||||||
log.Fatal(getErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
body, readErr := ioutil.ReadAll(res.Body)
|
|
||||||
defer req.Body.Close()
|
|
||||||
if readErr != nil {
|
|
||||||
log.Fatal(readErr)
|
|
||||||
}
|
|
||||||
return string(body), res.StatusCode, readErr
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGet_Rejected(t *testing.T) {
|
|
||||||
var reqBody string
|
|
||||||
unsupportedMethod := http.MethodHead
|
|
||||||
_, code, err := fireRequest("http://localhost:8080/function/echoit", unsupportedMethod, reqBody)
|
|
||||||
want := http.StatusMethodNotAllowed
|
|
||||||
if code != want {
|
|
||||||
t.Logf("Failed got: %d, wanted: %d", code, want)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Log(err)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEchoIt_Post_Route_Handler_ForwardsClientHeaders(t *testing.T) {
|
|
||||||
reqBody := "test message"
|
|
||||||
headers := make(map[string]string, 0)
|
|
||||||
headers["X-Api-Key"] = "123"
|
|
||||||
|
|
||||||
body, code, err := fireRequestWithHeaders("http://localhost:8080/function/echoit", http.MethodPost, reqBody, headers)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Log(err)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if code != http.StatusOK {
|
|
||||||
t.Logf("Failed, code: %d, body:%s", code, body)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if body != reqBody {
|
|
||||||
t.Log("Expected body returned")
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEchoIt_Post_Route_Handler(t *testing.T) {
|
|
||||||
reqBody := "test message"
|
|
||||||
body, code, err := fireRequest("http://localhost:8080/function/echoit", http.MethodPost, reqBody)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Log(err)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if code != http.StatusOK {
|
|
||||||
t.Log("Failed")
|
|
||||||
}
|
|
||||||
if body != reqBody {
|
|
||||||
t.Log("Expected body returned")
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test suppressed due to X-Header deprecation.
|
|
||||||
// func TestEchoIt_Post_X_Header_Routing_Handler(t *testing.T) {
|
|
||||||
// reqBody := "test message"
|
|
||||||
// headers := make(map[string]string, 0)
|
|
||||||
// headers["X-Function"] = "func_echoit"
|
|
||||||
|
|
||||||
// body, code, err := fireRequestWithHeaders("http://localhost:8080/", http.MethodPost, reqBody, headers)
|
|
||||||
|
|
||||||
// if err != nil {
|
|
||||||
// t.Log(err)
|
|
||||||
// t.Fail()
|
|
||||||
// }
|
|
||||||
// if code != http.StatusOK {
|
|
||||||
// t.Logf("statusCode - want: %d, got: %d", http.StatusOK, code)
|
|
||||||
// }
|
|
||||||
// if body != reqBody {
|
|
||||||
// t.Logf("Expected body from echo function to be equal to input, but was: %s", body)
|
|
||||||
// t.Fail()
|
|
||||||
// }
|
|
||||||
// }
|
|
@ -4,18 +4,24 @@ import "net/http"
|
|||||||
|
|
||||||
// HandlerSet can be initialized with handlers for binding to mux
|
// HandlerSet can be initialized with handlers for binding to mux
|
||||||
type HandlerSet struct {
|
type HandlerSet struct {
|
||||||
// Proxy invokes functions upstream
|
// Proxy invokes a function
|
||||||
Proxy http.HandlerFunc
|
Proxy http.HandlerFunc
|
||||||
|
|
||||||
|
// DeployFunction deploys a new function that isn't already deployed
|
||||||
DeployFunction http.HandlerFunc
|
DeployFunction http.HandlerFunc
|
||||||
|
|
||||||
|
// DeleteFunction deletes a function that is already deployed
|
||||||
DeleteFunction http.HandlerFunc
|
DeleteFunction http.HandlerFunc
|
||||||
|
|
||||||
|
// ListFunctions lists all deployed functions in a namespace
|
||||||
ListFunctions http.HandlerFunc
|
ListFunctions http.HandlerFunc
|
||||||
Alert http.HandlerFunc
|
Alert http.HandlerFunc
|
||||||
|
|
||||||
|
// UpdateFunction updates an existing function
|
||||||
UpdateFunction http.HandlerFunc
|
UpdateFunction http.HandlerFunc
|
||||||
|
|
||||||
// QueryFunction queries the metdata for a function
|
// FunctionStatus returns the status of an already deployed function
|
||||||
QueryFunction http.HandlerFunc
|
FunctionStatus http.HandlerFunc
|
||||||
|
|
||||||
// QueuedProxy queue work and return synchronous response
|
// QueuedProxy queue work and return synchronous response
|
||||||
QueuedProxy http.HandlerFunc
|
QueuedProxy http.HandlerFunc
|
||||||
|
51
gateway/vendor/github.com/openfaas/faas-provider/types/function_deployment.go
generated
vendored
Normal file
51
gateway/vendor/github.com/openfaas/faas-provider/types/function_deployment.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
// FunctionDeployment represents a request to create or update a Function.
|
||||||
|
type FunctionDeployment struct {
|
||||||
|
|
||||||
|
// Service is the name of the function deployment
|
||||||
|
Service string `json:"service"`
|
||||||
|
|
||||||
|
// Image is a fully-qualified container image
|
||||||
|
Image string `json:"image"`
|
||||||
|
|
||||||
|
// Namespace for the function, if supported by the faas-provider
|
||||||
|
Namespace string `json:"namespace,omitempty"`
|
||||||
|
|
||||||
|
// EnvProcess overrides the fprocess environment variable and can be used
|
||||||
|
// with the watchdog
|
||||||
|
EnvProcess string `json:"envProcess,omitempty"`
|
||||||
|
|
||||||
|
// EnvVars can be provided to set environment variables for the function runtime.
|
||||||
|
EnvVars map[string]string `json:"envVars,omitempty"`
|
||||||
|
|
||||||
|
// Constraints are specific to the faas-provider.
|
||||||
|
Constraints []string `json:"constraints,omitempty"`
|
||||||
|
|
||||||
|
// Secrets list of secrets to be made available to function
|
||||||
|
Secrets []string `json:"secrets,omitempty"`
|
||||||
|
|
||||||
|
// Labels are metadata for functions which may be used by the
|
||||||
|
// faas-provider or the gateway
|
||||||
|
Labels *map[string]string `json:"labels,omitempty"`
|
||||||
|
|
||||||
|
// Annotations are metadata for functions which may be used by the
|
||||||
|
// faas-provider or the gateway
|
||||||
|
Annotations *map[string]string `json:"annotations,omitempty"`
|
||||||
|
|
||||||
|
// Limits for function
|
||||||
|
Limits *FunctionResources `json:"limits,omitempty"`
|
||||||
|
|
||||||
|
// Requests of resources requested by function
|
||||||
|
Requests *FunctionResources `json:"requests,omitempty"`
|
||||||
|
|
||||||
|
// ReadOnlyRootFilesystem removes write-access from the root filesystem
|
||||||
|
// mount-point.
|
||||||
|
ReadOnlyRootFilesystem bool `json:"readOnlyRootFilesystem,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FunctionResources Memory and CPU
|
||||||
|
type FunctionResources struct {
|
||||||
|
Memory string `json:"memory,omitempty"`
|
||||||
|
CPU string `json:"cpu,omitempty"`
|
||||||
|
}
|
@ -2,72 +2,6 @@ package types
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
// Secret for underlying orchestrator
|
|
||||||
type Secret struct {
|
|
||||||
// Name of the secret
|
|
||||||
Name string `json:"name"`
|
|
||||||
|
|
||||||
// Namespace if applicable for the secret
|
|
||||||
Namespace string `json:"namespace,omitempty"`
|
|
||||||
|
|
||||||
// Value is a string representing the string's value
|
|
||||||
Value string `json:"value,omitempty"`
|
|
||||||
|
|
||||||
// RawValue can be used to provide binary data when
|
|
||||||
// Value is not set
|
|
||||||
RawValue []byte `json:"rawValue,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FunctionDeployment represents a request to create or update a Function.
|
|
||||||
type FunctionDeployment struct {
|
|
||||||
|
|
||||||
// Service is the name of the function deployment
|
|
||||||
Service string `json:"service"`
|
|
||||||
|
|
||||||
// Image is a fully-qualified container image
|
|
||||||
Image string `json:"image"`
|
|
||||||
|
|
||||||
// Namespace for the function, if supported by the faas-provider
|
|
||||||
Namespace string `json:"namespace,omitempty"`
|
|
||||||
|
|
||||||
// EnvProcess overrides the fprocess environment variable and can be used
|
|
||||||
// with the watchdog
|
|
||||||
EnvProcess string `json:"envProcess,omitempty"`
|
|
||||||
|
|
||||||
// EnvVars can be provided to set environment variables for the function runtime.
|
|
||||||
EnvVars map[string]string `json:"envVars,omitempty"`
|
|
||||||
|
|
||||||
// Constraints are specific to the faas-provider.
|
|
||||||
Constraints []string `json:"constraints,omitempty"`
|
|
||||||
|
|
||||||
// Secrets list of secrets to be made available to function
|
|
||||||
Secrets []string `json:"secrets,omitempty"`
|
|
||||||
|
|
||||||
// Labels are metadata for functions which may be used by the
|
|
||||||
// faas-provider or the gateway
|
|
||||||
Labels *map[string]string `json:"labels,omitempty"`
|
|
||||||
|
|
||||||
// Annotations are metadata for functions which may be used by the
|
|
||||||
// faas-provider or the gateway
|
|
||||||
Annotations *map[string]string `json:"annotations,omitempty"`
|
|
||||||
|
|
||||||
// Limits for function
|
|
||||||
Limits *FunctionResources `json:"limits,omitempty"`
|
|
||||||
|
|
||||||
// Requests of resources requested by function
|
|
||||||
Requests *FunctionResources `json:"requests,omitempty"`
|
|
||||||
|
|
||||||
// ReadOnlyRootFilesystem removes write-access from the root filesystem
|
|
||||||
// mount-point.
|
|
||||||
ReadOnlyRootFilesystem bool `json:"readOnlyRootFilesystem,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FunctionResources Memory and CPU
|
|
||||||
type FunctionResources struct {
|
|
||||||
Memory string `json:"memory,omitempty"`
|
|
||||||
CPU string `json:"cpu,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FunctionStatus exported for system/functions endpoint
|
// FunctionStatus exported for system/functions endpoint
|
||||||
type FunctionStatus struct {
|
type FunctionStatus struct {
|
||||||
|
|
||||||
@ -128,4 +62,24 @@ type FunctionStatus struct {
|
|||||||
// CreatedAt is the time read back from the faas backend's
|
// CreatedAt is the time read back from the faas backend's
|
||||||
// data store for when the function or its container was created.
|
// data store for when the function or its container was created.
|
||||||
CreatedAt time.Time `json:"createdAt,omitempty"`
|
CreatedAt time.Time `json:"createdAt,omitempty"`
|
||||||
|
|
||||||
|
// Utilisation represents CPU and RAM used by all of the
|
||||||
|
// functions' replicas. Divide by AvailableReplicas for an
|
||||||
|
// average value per replica.
|
||||||
|
Utilisation FunctionUtilisation `json:"usage,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FunctionUtilisation represents CPU and RAM used by all of the
|
||||||
|
// functions' replicas.
|
||||||
|
//
|
||||||
|
// CPU is measured in seconds consumed since the last measurement
|
||||||
|
// RAM is measured in total bytes consumed
|
||||||
|
//
|
||||||
|
type FunctionUtilisation struct {
|
||||||
|
// CPU is the increase in CPU usage since the last measurement
|
||||||
|
// equivalent to Kubernetes' concept of millicores.
|
||||||
|
CPU float64 `json:"cpu,omitempty"`
|
||||||
|
|
||||||
|
//TotalMemoryBytes is the total memory usage in bytes.
|
||||||
|
TotalMemoryBytes float64 `json:"totalMemoryBytes,omitempty"`
|
||||||
}
|
}
|
17
gateway/vendor/github.com/openfaas/faas-provider/types/secret.go
generated
vendored
Normal file
17
gateway/vendor/github.com/openfaas/faas-provider/types/secret.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
// Secret for underlying orchestrator
|
||||||
|
type Secret struct {
|
||||||
|
// Name of the secret
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Namespace if applicable for the secret
|
||||||
|
Namespace string `json:"namespace,omitempty"`
|
||||||
|
|
||||||
|
// Value is a string representing the string's value
|
||||||
|
Value string `json:"value,omitempty"`
|
||||||
|
|
||||||
|
// RawValue can be used to provide binary data when
|
||||||
|
// Value is not set
|
||||||
|
RawValue []byte `json:"rawValue,omitempty"`
|
||||||
|
}
|
6
gateway/vendor/modules.txt
vendored
6
gateway/vendor/modules.txt
vendored
@ -20,10 +20,6 @@ github.com/golang/protobuf/ptypes/timestamp
|
|||||||
github.com/gorilla/mux
|
github.com/gorilla/mux
|
||||||
# github.com/matttproud/golang_protobuf_extensions v1.0.1
|
# github.com/matttproud/golang_protobuf_extensions v1.0.1
|
||||||
github.com/matttproud/golang_protobuf_extensions/pbutil
|
github.com/matttproud/golang_protobuf_extensions/pbutil
|
||||||
# github.com/nats-io/nats-server/v2 v2.3.2
|
|
||||||
## explicit
|
|
||||||
# github.com/nats-io/nats-streaming-server v0.22.0
|
|
||||||
## explicit
|
|
||||||
# github.com/nats-io/nats.go v1.11.1-0.20210623165838-4b75fc59ae30
|
# github.com/nats-io/nats.go v1.11.1-0.20210623165838-4b75fc59ae30
|
||||||
github.com/nats-io/nats.go
|
github.com/nats-io/nats.go
|
||||||
github.com/nats-io/nats.go/encoders/builtin
|
github.com/nats-io/nats.go/encoders/builtin
|
||||||
@ -35,7 +31,7 @@ github.com/nats-io/nuid
|
|||||||
# github.com/nats-io/stan.go v0.9.0
|
# github.com/nats-io/stan.go v0.9.0
|
||||||
github.com/nats-io/stan.go
|
github.com/nats-io/stan.go
|
||||||
github.com/nats-io/stan.go/pb
|
github.com/nats-io/stan.go/pb
|
||||||
# github.com/openfaas/faas-provider v0.18.6
|
# github.com/openfaas/faas-provider v0.18.7
|
||||||
## explicit
|
## explicit
|
||||||
github.com/openfaas/faas-provider/auth
|
github.com/openfaas/faas-provider/auth
|
||||||
github.com/openfaas/faas-provider/types
|
github.com/openfaas/faas-provider/types
|
||||||
|
Loading…
x
Reference in New Issue
Block a user