Add usage metrics for describe command
Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
committed by
Alex Ellis
parent
d94600d2d2
commit
b1c09c0243
@@ -115,6 +115,9 @@ func runDescribe(cmd *cobra.Command, args []string) error {
|
||||
Labels: function.Labels,
|
||||
Annotations: function.Annotations,
|
||||
}
|
||||
if function.Usage != nil {
|
||||
funcDesc.Usage = function.Usage
|
||||
}
|
||||
|
||||
printFunctionDescription(funcDesc)
|
||||
|
||||
@@ -148,6 +151,17 @@ func printFunctionDescription(funcDesc schema.FunctionDescription) {
|
||||
fmt.Fprintln(w, "Async URL:\t "+funcDesc.AsyncURL)
|
||||
printMap(w, "Labels", *funcDesc.Labels)
|
||||
printMap(w, "Annotations", *funcDesc.Annotations)
|
||||
if funcDesc.Usage != nil {
|
||||
fmt.Println()
|
||||
|
||||
fmt.Fprintf(w, "RAM:\t %.2f MB\n", (funcDesc.Usage.TotalMemoryBytes / 1024 / 1024))
|
||||
cpu := funcDesc.Usage.CPU
|
||||
if cpu < 0 {
|
||||
cpu = 1
|
||||
}
|
||||
fmt.Fprintf(w, "CPU:\t %.0f Mi\n", (cpu))
|
||||
|
||||
}
|
||||
|
||||
w.Flush()
|
||||
}
|
||||
|
||||
2
go.mod
2
go.mod
@@ -16,7 +16,7 @@ require (
|
||||
github.com/gotestyourself/gotestyourself v1.4.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/morikuni/aec v1.0.0
|
||||
github.com/openfaas/faas-provider v0.18.5
|
||||
github.com/openfaas/faas-provider v0.18.9
|
||||
github.com/openfaas/faas/gateway v0.0.0-20210311210633-a6dbb4cd0285
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/ryanuber/go-glob v1.0.0
|
||||
|
||||
5
go.sum
5
go.sum
@@ -246,10 +246,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/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/openfaas/faas-provider v0.17.3 h1:LN76lrXUKAx27o5X8l+daKWEzsdiW2E99jMOlI1SO5Q=
|
||||
github.com/openfaas/faas-provider v0.17.3/go.mod h1:fq1JL0mX4rNvVVvRLaLRJ3H6o667sHuyP5p/7SZEe98=
|
||||
github.com/openfaas/faas-provider v0.18.5 h1:y7CCkbh0dW9aWpRisXbjgG9MTZVrdiDKLNt7qqo8M5c=
|
||||
github.com/openfaas/faas-provider v0.18.5/go.mod h1:fq1JL0mX4rNvVVvRLaLRJ3H6o667sHuyP5p/7SZEe98=
|
||||
github.com/openfaas/faas-provider v0.18.9 h1:nHPlq9PYLGLuyhuXfASlBPOvXiZC/fJqHOr6m+0Fn1s=
|
||||
github.com/openfaas/faas-provider v0.18.9/go.mod h1:S217qfIaMrv+XKJxgbhBzJzCfyFvoIF+BvYdDo6XIDQ=
|
||||
github.com/openfaas/faas/gateway v0.0.0-20210311210633-a6dbb4cd0285 h1:oLrTwALS1EyjvG5AXZQM43CDZPNXoIcjDpeAK3UG/yM=
|
||||
github.com/openfaas/faas/gateway v0.0.0-20210311210633-a6dbb4cd0285/go.mod h1:ZZUyq1Ghd3zvhKvSWfXelAsvbUxWP1TqWtvapP4701Q=
|
||||
github.com/openfaas/nats-queue-worker v0.0.0-20200512211843-8e9eefd5a320/go.mod h1:BfT8MB890hbhbtPid+X/oU0HAznGFS581NiG2hkr8Rc=
|
||||
|
||||
@@ -54,6 +54,26 @@ func NewClient(auth ClientAuth, gatewayURL string, transport http.RoundTripper,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) newRequestByURL(method string, uri *url.URL, body io.Reader) (*http.Request, error) {
|
||||
|
||||
req, err := http.NewRequest(method, uri.String(), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if body != nil {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
if c.UserAgent != "" {
|
||||
req.Header.Set("User-Agent", c.UserAgent)
|
||||
}
|
||||
|
||||
c.ClientAuth.Set(req)
|
||||
|
||||
return req, err
|
||||
}
|
||||
|
||||
//newRequest create a new HTTP request with authentication
|
||||
func (c *Client) newRequest(method, path string, body io.Reader) (*http.Request, error) {
|
||||
u, err := url.Parse(path)
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path"
|
||||
|
||||
types "github.com/openfaas/faas-provider/types"
|
||||
)
|
||||
@@ -20,23 +21,26 @@ func (c *Client) GetFunctionInfo(ctx context.Context, functionName string, names
|
||||
err error
|
||||
)
|
||||
|
||||
functionPath := fmt.Sprintf("%s/%s", functionPath, functionName)
|
||||
u := c.GatewayURL
|
||||
v := u.Query()
|
||||
if len(namespace) > 0 {
|
||||
functionPath, err = addQueryParams(functionPath, map[string]string{namespaceKey: namespace})
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
v.Set("namespace", namespace)
|
||||
}
|
||||
|
||||
getRequest, err := c.newRequest(http.MethodGet, functionPath, nil)
|
||||
// Request CPU/RAM usage if available
|
||||
v.Set("usage", "1")
|
||||
|
||||
u.Path = path.Join(functionPath, functionName)
|
||||
u.RawQuery = v.Encode()
|
||||
|
||||
req, err := c.newRequestByURL(http.MethodGet, u, nil)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("cannot connect to OpenFaaS on URL: %s", c.GatewayURL.String())
|
||||
return result, fmt.Errorf("cannot create URL: %s, error: %w", u.String(), err)
|
||||
}
|
||||
|
||||
res, err := c.doRequest(ctx, getRequest)
|
||||
res, err := c.doRequest(ctx, req)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("cannot connect to OpenFaaS on URL: %s", c.GatewayURL.String())
|
||||
|
||||
return result, fmt.Errorf("cannot connect to URL: %s, error: %w", c.GatewayURL.String(), err)
|
||||
}
|
||||
|
||||
if res.Body != nil {
|
||||
@@ -50,14 +54,15 @@ func (c *Client) GetFunctionInfo(ctx context.Context, functionName string, names
|
||||
return result, fmt.Errorf("cannot read result from OpenFaaS on URL: %s", c.GatewayURL.String())
|
||||
}
|
||||
|
||||
jsonErr := json.Unmarshal(bytesOut, &result)
|
||||
if jsonErr != nil {
|
||||
return result, fmt.Errorf("cannot parse result from OpenFaaS on URL: %s\n%s", c.GatewayURL.String(), jsonErr.Error())
|
||||
if err := json.Unmarshal(bytesOut, &result); err != nil {
|
||||
return result, fmt.Errorf("cannot parse result from OpenFaaS on URL: %s\n%w",
|
||||
c.GatewayURL.String(), err)
|
||||
}
|
||||
|
||||
case http.StatusUnauthorized:
|
||||
return result, fmt.Errorf("unauthorized access, run \"faas-cli login\" to setup authentication for this server")
|
||||
case http.StatusNotFound:
|
||||
return result, fmt.Errorf("No such function: %s", functionName)
|
||||
return result, fmt.Errorf("no such function: %s", functionName)
|
||||
default:
|
||||
bytesOut, err := ioutil.ReadAll(res.Body)
|
||||
if err == nil {
|
||||
|
||||
@@ -77,7 +77,7 @@ func Test_GetFunctionInfo_NotFound(t *testing.T) {
|
||||
t.Fatalf("Error was not returned")
|
||||
}
|
||||
|
||||
expectedErrMsg := fmt.Sprintf("No such function: %s", functionName)
|
||||
expectedErrMsg := fmt.Sprintf("no such function: %s", functionName)
|
||||
if err.Error() != expectedErrMsg {
|
||||
t.Fatalf("Want: %s, Got: %s", expectedErrMsg, err.Error())
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package proxy
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"path"
|
||||
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@@ -17,24 +18,23 @@ import (
|
||||
// ListFunctions list deployed functions
|
||||
func (c *Client) ListFunctions(ctx context.Context, namespace string) ([]types.FunctionStatus, error) {
|
||||
var (
|
||||
results []types.FunctionStatus
|
||||
listEndpoint string
|
||||
err error
|
||||
results []types.FunctionStatus
|
||||
err error
|
||||
)
|
||||
|
||||
c.AddCheckRedirect(func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
})
|
||||
|
||||
listEndpoint = systemPath
|
||||
u := c.GatewayURL
|
||||
u.Path = path.Join(systemPath)
|
||||
v := u.Query()
|
||||
if len(namespace) > 0 {
|
||||
listEndpoint, err = addQueryParams(listEndpoint, map[string]string{namespaceKey: namespace})
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
v.Set("namespace", namespace)
|
||||
}
|
||||
u.RawQuery = v.Encode()
|
||||
|
||||
getRequest, err := c.newRequest(http.MethodGet, listEndpoint, nil)
|
||||
getRequest, err := c.newRequestByURL(http.MethodGet, u, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot connect to OpenFaaS on URL: %s", c.GatewayURL.String())
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
package schema
|
||||
|
||||
import "github.com/openfaas/faas-provider/types"
|
||||
|
||||
//FunctionDescription information related to a function
|
||||
type FunctionDescription struct {
|
||||
Name string
|
||||
@@ -16,4 +18,5 @@ type FunctionDescription struct {
|
||||
AsyncURL string
|
||||
Labels *map[string]string
|
||||
Annotations *map[string]string
|
||||
Usage *types.FunctionUsage
|
||||
}
|
||||
|
||||
51
vendor/github.com/openfaas/faas-provider/types/function_deployment.go
generated
vendored
Normal file
51
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"
|
||||
|
||||
// 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
|
||||
type FunctionStatus struct {
|
||||
|
||||
@@ -128,4 +62,24 @@ type FunctionStatus struct {
|
||||
// CreatedAt is the time read back from the faas backend's
|
||||
// data store for when the function or its container was created.
|
||||
CreatedAt time.Time `json:"createdAt,omitempty"`
|
||||
|
||||
// Usage represents CPU and RAM used by all of the
|
||||
// functions' replicas. Divide by AvailableReplicas for an
|
||||
// average value per replica.
|
||||
Usage *FunctionUsage `json:"usage,omitempty"`
|
||||
}
|
||||
|
||||
// FunctionUsage 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 FunctionUsage 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"`
|
||||
}
|
||||
42
vendor/github.com/openfaas/faas-provider/types/queue.go
generated
vendored
Normal file
42
vendor/github.com/openfaas/faas-provider/types/queue.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// Request for asynchronous processing
|
||||
type QueueRequest struct {
|
||||
// Header from HTTP request
|
||||
Header http.Header
|
||||
|
||||
// Host from HTTP request
|
||||
Host string
|
||||
|
||||
// Body from HTTP request to use for invocation
|
||||
Body []byte
|
||||
|
||||
// Method from HTTP request
|
||||
Method string
|
||||
|
||||
// Path from HTTP request
|
||||
Path string
|
||||
|
||||
// QueryString from HTTP request
|
||||
QueryString string
|
||||
|
||||
// Function name to invoke
|
||||
Function string
|
||||
|
||||
// QueueName to publish the request to, leave blank
|
||||
// for default.
|
||||
QueueName string
|
||||
|
||||
// Used by queue worker to submit a result
|
||||
CallbackURL *url.URL `json:"CallbackUrl"`
|
||||
}
|
||||
|
||||
// RequestQueuer can public a request to be executed asynchronously
|
||||
type RequestQueuer interface {
|
||||
Queue(req *QueueRequest) error
|
||||
}
|
||||
17
vendor/github.com/openfaas/faas-provider/types/secret.go
generated
vendored
Normal file
17
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"`
|
||||
}
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -36,7 +36,7 @@ github.com/mitchellh/go-homedir
|
||||
# github.com/morikuni/aec v1.0.0
|
||||
## explicit
|
||||
github.com/morikuni/aec
|
||||
# github.com/openfaas/faas-provider v0.18.5
|
||||
# github.com/openfaas/faas-provider v0.18.9
|
||||
## explicit
|
||||
github.com/openfaas/faas-provider/httputil
|
||||
github.com/openfaas/faas-provider/logs
|
||||
|
||||
Reference in New Issue
Block a user