diff --git a/docker-compose.yaml b/docker-compose.yaml index c16c0a7..4444152 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,7 +1,7 @@ version: "3.7" services: basic-auth-plugin: - image: "docker.io/openfaas/basic-auth-plugin:0.18.18${ARCH_SUFFIX}" + image: ghcr.io/openfaas/basic-auth:0.20.5 environment: - port=8080 - secret_mount_path=/run/secrets @@ -41,7 +41,7 @@ services: - "127.0.0.1:9090:9090" gateway: - image: "docker.io/openfaas/gateway:0.19.1${ARCH_SUFFIX}" + image: ghcr.io/openfaas/gateway:0.20.5 environment: - basic_auth=true - functions_provider_url=http://faasd-provider:8081/ diff --git a/go.mod b/go.mod index ef434c0..9c5d7f7 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/opencontainers/runc v1.0.0-rc9 // indirect github.com/opencontainers/runtime-spec v1.0.2 github.com/openfaas/faas v0.0.0-20201205125747-9bbb25e3c7c4 - github.com/openfaas/faas-provider v0.15.3 + github.com/openfaas/faas-provider v0.16.2 github.com/pkg/errors v0.9.1 github.com/prometheus/procfs v0.2.0 // indirect github.com/sethvargo/go-password v0.1.3 diff --git a/go.sum b/go.sum index e2a4ccc..8c1a275 100644 --- a/go.sum +++ b/go.sum @@ -181,8 +181,8 @@ github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/ github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/openfaas/faas v0.0.0-20201205125747-9bbb25e3c7c4 h1:JJjthDw7WziZQ7sC5C+M2872mIdud5R+s6Cb0cXyPuA= github.com/openfaas/faas v0.0.0-20201205125747-9bbb25e3c7c4/go.mod h1:E0m2rLup0Vvxg53BKxGgaYAGcZa3Xl+vvL7vSi5yQ14= -github.com/openfaas/faas-provider v0.15.3 h1:tfjuL5F/tdoUr1J65XrUADyoe59x38VzN1w0DvBaTRk= -github.com/openfaas/faas-provider v0.15.3/go.mod h1:fq1JL0mX4rNvVVvRLaLRJ3H6o667sHuyP5p/7SZEe98= +github.com/openfaas/faas-provider v0.16.2 h1:ChpiZh1RM8zFIzvp31OPlKpTbh5Lcm7f91WCFcpW4gA= +github.com/openfaas/faas-provider v0.16.2/go.mod h1:fq1JL0mX4rNvVVvRLaLRJ3H6o667sHuyP5p/7SZEe98= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/pkg/provider/handlers/functions.go b/pkg/provider/handlers/functions.go index dd58fc1..d236dbb 100644 --- a/pkg/provider/handlers/functions.go +++ b/pkg/provider/handlers/functions.go @@ -3,6 +3,7 @@ package handlers import ( "context" "fmt" + "github.com/opencontainers/runtime-spec/specs-go" "log" "strings" @@ -22,6 +23,7 @@ type Function struct { IP string labels map[string]string annotations map[string]string + secrets []string } // ListFunctions returns a map of all functions with running tasks on namespace @@ -71,12 +73,19 @@ func GetFunction(client *containerd.Client, name string) (Function, error) { labels, annotations := buildLabelsAndAnnotations(allLabels) + spec, err := c.Spec(ctx) + if err != nil { + return Function{}, fmt.Errorf("unable to load function spec for reading secrets: %s, error %s", name, err) + } + + secrets := readSecretsFromMounts(spec.Mounts) + fn.name = containerName fn.namespace = faasd.FunctionNamespace fn.image = image.Name() fn.labels = labels fn.annotations = annotations - + fn.secrets = secrets replicas := 0 task, err := c.Task(ctx, nil) if err == nil { @@ -105,6 +114,18 @@ func GetFunction(client *containerd.Client, name string) (Function, error) { return fn, nil } +func readSecretsFromMounts(mounts []specs.Mount) []string { + secrets := []string{} + for _, mnt := range mounts { + x := strings.Split(mnt.Destination, "/var/openfaas/secrets/") + if len(x) > 1 { + secrets = append(secrets, x[1]) + } + + } + return secrets +} + // buildLabelsAndAnnotations returns a separated list with labels first, // followed by annotations by checking each key of ctrLabels for a prefix. func buildLabelsAndAnnotations(ctrLabels map[string]string) (map[string]string, map[string]string) { diff --git a/pkg/provider/handlers/functions_test.go b/pkg/provider/handlers/functions_test.go index bc54c9a..d6458a8 100644 --- a/pkg/provider/handlers/functions_test.go +++ b/pkg/provider/handlers/functions_test.go @@ -2,6 +2,8 @@ package handlers import ( "fmt" + "github.com/opencontainers/runtime-spec/specs-go" + "reflect" "testing" ) @@ -27,3 +29,27 @@ func Test_BuildLabelsAndAnnotationsFromServiceSpec_Annotations(t *testing.T) { t.Errorf("want: '%s' entry in annotation map got: key not found", "current-time") } } + +func Test_SplitMountToSecrets(t *testing.T) { + type test struct { + Name string + Input []specs.Mount + Expected []string + } + tests := []test{ + {Name: "No matching openfaas secrets", Input: []specs.Mount{{Destination: "/foo/"}}, Expected: []string{}}, + {Name: "No Mounts", Input: []specs.Mount{{Destination: "/foo/"}}, Expected: []string{}}, + {Name: "One Mounts IS secret", Input: []specs.Mount{{Destination: "/var/openfaas/secrets/secret1"}}, Expected: []string{"secret1"}}, + {Name: "Multiple Mounts 1 secret", Input: []specs.Mount{{Destination: "/var/openfaas/secrets/secret1"}, {Destination: "/some/other/path"}}, Expected: []string{"secret1"}}, + {Name: "Multiple Mounts all secrets", Input: []specs.Mount{{Destination: "/var/openfaas/secrets/secret1"}, {Destination: "/var/openfaas/secrets/secret2"}}, Expected: []string{"secret1", "secret2"}}, + } + + for _, tc := range tests { + t.Run(tc.Name, func(t *testing.T) { + got := readSecretsFromMounts(tc.Input) + if !reflect.DeepEqual(got, tc.Expected) { + t.Fatalf("expected %s, got %s", tc.Expected, got) + } + }) + } +} diff --git a/pkg/provider/handlers/info.go b/pkg/provider/handlers/info.go index aa1d13f..19a8488 100644 --- a/pkg/provider/handlers/info.go +++ b/pkg/provider/handlers/info.go @@ -22,10 +22,10 @@ func MakeInfoHandler(version, sha string) http.HandlerFunc { defer r.Body.Close() } - infoResponse := types.InfoResponse{ + infoResponse := types.ProviderInfo{ Orchestration: OrchestrationIdentifier, - Provider: ProviderName, - Version: types.ProviderVersion{ + Name: ProviderName, + Version: &types.VersionInfo{ Release: version, SHA: sha, }, diff --git a/pkg/provider/handlers/info_test.go b/pkg/provider/handlers/info_test.go index 0576f85..e7ea471 100644 --- a/pkg/provider/handlers/info_test.go +++ b/pkg/provider/handlers/info_test.go @@ -15,14 +15,14 @@ func Test_InfoHandler(t *testing.T) { r := httptest.NewRequest("GET", "/", nil) handler(w, r) - resp := types.InfoResponse{} + resp := types.ProviderInfo{} err := json.Unmarshal(w.Body.Bytes(), &resp) if err != nil { t.Fatalf("unexpected error unmarshalling the response") } - if resp.Provider != ProviderName { - t.Fatalf("expected provider %q, got %q", ProviderName, resp.Provider) + if resp.Name != ProviderName { + t.Fatalf("expected provider %q, got %q", ProviderName, resp.Name) } if resp.Orchestration != OrchestrationIdentifier { diff --git a/pkg/provider/handlers/read.go b/pkg/provider/handlers/read.go index 1c1a74f..943dbed 100644 --- a/pkg/provider/handlers/read.go +++ b/pkg/provider/handlers/read.go @@ -31,6 +31,7 @@ func MakeReadHandler(client *containerd.Client) func(w http.ResponseWriter, r *h Namespace: fn.namespace, Labels: labels, Annotations: annotations, + Secrets: fn.secrets, }) } diff --git a/pkg/provider/handlers/replicas.go b/pkg/provider/handlers/replicas.go index 934afd4..52e2137 100644 --- a/pkg/provider/handlers/replicas.go +++ b/pkg/provider/handlers/replicas.go @@ -23,6 +23,7 @@ func MakeReplicaReaderHandler(client *containerd.Client) func(w http.ResponseWri Namespace: f.namespace, Labels: &f.labels, Annotations: &f.annotations, + Secrets: f.secrets, } functionBytes, _ := json.Marshal(found) diff --git a/vendor/github.com/openfaas/faas-provider/types/model.go b/vendor/github.com/openfaas/faas-provider/types/model.go index 9e73c21..5a09e3d 100644 --- a/vendor/github.com/openfaas/faas-provider/types/model.go +++ b/vendor/github.com/openfaas/faas-provider/types/model.go @@ -3,92 +3,45 @@ package types // FunctionDeployment represents a request to create or update a Function. type FunctionDeployment struct { - // Service corresponds to a Service + // Service is the name of the function deployment Service string `json:"service"` - // Image corresponds to a Docker image + // Image is a fully-qualified container image Image string `json:"image"` - // Network is specific to Docker Swarm - default overlay network is: func_functions - Network string `json:"network"` + // Namespace for the function, if supported by the faas-provider + Namespace string `json:"namespace,omitempty"` - // EnvProcess corresponds to the fprocess variable for your container watchdog. - EnvProcess string `json:"envProcess"` + // EnvProcess overrides the fprocess environment variable and can be used + // with the watchdog + EnvProcess string `json:"envProcess,omitempty"` - // EnvVars provides overrides for functions. - EnvVars map[string]string `json:"envVars"` + // EnvVars can be provided to set environment variables for the function runtime. + EnvVars map[string]string `json:"envVars,omitempty"` - // RegistryAuth is the registry authentication (optional) - // in the same encoded format as Docker native credentials - // (see ~/.docker/config.json) - RegistryAuth string `json:"registryAuth,omitempty"` - - // Constraints are specific to back-end orchestration platform - Constraints []string `json:"constraints"` + // 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"` + Secrets []string `json:"secrets,omitempty"` // Labels are metadata for functions which may be used by the - // back-end for making scheduling or routing decisions - Labels *map[string]string `json:"labels"` + // faas-provider or the gateway + Labels *map[string]string `json:"labels,omitempty"` // Annotations are metadata for functions which may be used by the - // back-end for management, orchestration, events and build tasks - Annotations *map[string]string `json:"annotations"` + // faas-provider or the gateway + Annotations *map[string]string `json:"annotations,omitempty"` // Limits for function - Limits *FunctionResources `json:"limits"` + Limits *FunctionResources `json:"limits,omitempty"` // Requests of resources requested by function - Requests *FunctionResources `json:"requests"` + Requests *FunctionResources `json:"requests,omitempty"` // ReadOnlyRootFilesystem removes write-access from the root filesystem // mount-point. - ReadOnlyRootFilesystem bool `json:"readOnlyRootFilesystem"` - - // Namespace for the function to be deployed into - Namespace string `json:"namespace,omitempty"` -} - -// FunctionResources Memory and CPU -type FunctionResources struct { - Memory string `json:"memory"` - CPU string `json:"cpu"` -} - -// FunctionStatus exported for system/functions endpoint -type FunctionStatus struct { - - // Name corresponds to a Service - Name string `json:"name"` - - // Image corresponds to a Docker image - Image string `json:"image"` - - // InvocationCount count of invocations - InvocationCount float64 `json:"invocationCount"` - - // Replicas desired within the cluster - Replicas uint64 `json:"replicas"` - - // EnvProcess is the process to pass to the watchdog, if in use - EnvProcess string `json:"envProcess"` - - // AvailableReplicas is the count of replicas ready to receive - // invocations as reported by the backend - AvailableReplicas uint64 `json:"availableReplicas"` - - // Labels are metadata for functions which may be used by the - // backend for making scheduling or routing decisions - Labels *map[string]string `json:"labels"` - - // Annotations are metadata for functions which may be used by the - // backend for management, orchestration, events and build tasks - Annotations *map[string]string `json:"annotations"` - - // Namespace where the function can be accessed - Namespace string `json:"namespace,omitempty"` + ReadOnlyRootFilesystem bool `json:"readOnlyRootFilesystem,omitempty"` } // Secret for underlying orchestrator @@ -97,3 +50,65 @@ type Secret struct { Namespace string `json:"namespace,omitempty"` Value string `json:"value,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 { + + // Name is the name of the function deployment + Name string `json:"name"` + + // 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 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"` + + // ** Status fields *8 + + // InvocationCount count of invocations + InvocationCount float64 `json:"invocationCount,omitempty"` + + // Replicas desired within the cluster + Replicas uint64 `json:"replicas,omitempty"` + + // AvailableReplicas is the count of replicas ready to receive + // invocations as reported by the faas-provider + AvailableReplicas uint64 `json:"availableReplicas,omitempty"` +} diff --git a/vendor/github.com/openfaas/faas-provider/types/requests.go b/vendor/github.com/openfaas/faas-provider/types/requests.go index 1963c79..752893e 100644 --- a/vendor/github.com/openfaas/faas-provider/types/requests.go +++ b/vendor/github.com/openfaas/faas-provider/types/requests.go @@ -9,20 +9,21 @@ type ScaleServiceRequest struct { Replicas uint64 `json:"replicas"` } -// InfoResponse provides information about the underlying provider -type InfoResponse struct { - Provider string `json:"provider"` - Version ProviderVersion `json:"version"` - Orchestration string `json:"orchestration"` -} - -// ProviderVersion provides the commit sha and release version number of the underlying provider -type ProviderVersion struct { - SHA string `json:"sha"` - Release string `json:"release"` -} - // DeleteFunctionRequest delete a deployed function type DeleteFunctionRequest struct { FunctionName string `json:"functionName"` } + +// ProviderInfo provides information about the configured provider +type ProviderInfo struct { + Name string `json:"provider"` + Version *VersionInfo `json:"version"` + Orchestration string `json:"orchestration"` +} + +// VersionInfo provides the commit message, sha and release version number +type VersionInfo struct { + CommitMessage string `json:"commit_message,omitempty"` + SHA string `json:"sha"` + Release string `json:"release"` +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 4a4744d..f95aa83 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -167,7 +167,7 @@ github.com/opencontainers/runc/libcontainer/user github.com/opencontainers/runtime-spec/specs-go # github.com/openfaas/faas v0.0.0-20201205125747-9bbb25e3c7c4 github.com/openfaas/faas/gateway/requests -# github.com/openfaas/faas-provider v0.15.3 +# github.com/openfaas/faas-provider v0.16.2 github.com/openfaas/faas-provider github.com/openfaas/faas-provider/auth github.com/openfaas/faas-provider/httputil