Files
faas-cli/commands/store_deploy.go
Alex Ellis (OpenFaaS Ltd) 10815dfbdb Fix issue with overrides for env-vars in store
The store deploy command was passing multiple environment
variables to the deployment endpoint, instead of implementing
the intended precedence.

Tested with a local faasd instance. This is important for
when people test with things like the sleep function from the
openfaas function store.

Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
2022-10-11 09:34:38 +01:00

153 lines
5.4 KiB
Go

// Copyright (c) OpenFaaS Author(s) 2018. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
package commands
import (
"context"
"fmt"
"os"
"github.com/openfaas/faas-cli/proxy"
"github.com/spf13/cobra"
)
func init() {
// Setup flags that are used by multiple commands (variables defined in faas.go)
storeDeployCmd.Flags().StringVarP(&gateway, "gateway", "g", defaultGateway, "Gateway URL starting with http(s)://")
storeDeployCmd.Flags().StringVar(&network, "network", "", "Name of the network")
storeDeployCmd.Flags().StringVar(&functionName, "name", "", "Name of the deployed function (overriding name from the store)")
storeDeployCmd.Flags().StringVarP(&functionNamespace, "namespace", "n", "", "Namespace of the function")
// Setup flags that are used only by deploy command (variables defined above)
storeDeployCmd.Flags().StringArrayVarP(&storeDeployFlags.envvarOpts, "env", "e", []string{}, "Adds one or more environment variables to the defined ones by store (ENVVAR=VALUE)")
storeDeployCmd.Flags().StringArrayVarP(&storeDeployFlags.labelOpts, "label", "l", []string{}, "Set one or more label (LABEL=VALUE)")
storeDeployCmd.Flags().BoolVar(&storeDeployFlags.replace, "replace", false, "Replace any existing function")
storeDeployCmd.Flags().BoolVar(&storeDeployFlags.update, "update", true, "Update existing functions")
storeDeployCmd.Flags().StringArrayVar(&storeDeployFlags.constraints, "constraint", []string{}, "Apply a constraint to the function")
storeDeployCmd.Flags().StringArrayVar(&storeDeployFlags.secrets, "secret", []string{}, "Give the function access to a secure secret")
storeDeployCmd.Flags().StringArrayVarP(&storeDeployFlags.annotationOpts, "annotation", "", []string{}, "Set one or more annotation (ANNOTATION=VALUE)")
storeDeployCmd.Flags().BoolVar(&tlsInsecure, "tls-no-verify", false, "Disable TLS validation")
storeDeployCmd.Flags().StringVarP(&token, "token", "k", "", "Pass a JWT token to use instead of basic auth")
storeDeployCmd.Flags().DurationVar(&timeoutOverride, "timeout", commandTimeout, "Timeout for any HTTP calls made to the OpenFaaS API.")
// Set bash-completion.
_ = storeDeployCmd.Flags().SetAnnotation("handler", cobra.BashCompSubdirsInDir, []string{})
storeCmd.AddCommand(storeDeployCmd)
}
var storeDeployCmd = &cobra.Command{
Use: `deploy (FUNCTION_NAME|FUNCTION_TITLE)
[--name FUNCTION_NAME]
[--gateway GATEWAY_URL]
[--network NETWORK_NAME]
[--env ENVVAR=VALUE ...]
[--label LABEL=VALUE ...]
[--annotation ANNOTATION=VALUE ...]
[--replace=false]
[--update=true]
[--constraint PLACEMENT_CONSTRAINT ...]
[--secret "SECRET_NAME"]
[--url STORE_URL]
[--tls-no-verify=false]`,
Short: "Deploy OpenFaaS functions from a store",
Long: `Same as faas-cli deploy except that function is pre-loaded with arguments from the store`,
Example: ` faas-cli store deploy figlet
faas-cli store deploy figlet \
--gateway=http://127.0.0.1:8080 \
--env=MYVAR=myval`,
RunE: runStoreDeploy,
PreRunE: preRunEStoreDeploy,
}
func preRunEStoreDeploy(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("please provide the function name")
}
return nil
}
func runStoreDeploy(cmd *cobra.Command, args []string) error {
targetPlatform := getTargetPlatform(platformValue)
storeItems, err := storeList(storeAddress)
if err != nil {
return err
}
platformFunctions := filterStoreList(storeItems, targetPlatform)
requestedStoreFn := args[0]
item := storeFindFunction(requestedStoreFn, platformFunctions)
if item == nil {
return fmt.Errorf("function '%s' not found for platform '%s'", requestedStoreFn, targetPlatform)
}
flagEnvs, err := parseMap(storeDeployFlags.envvarOpts, "env")
if err != nil {
return err
}
// Add the store environment variables to the provided ones from cmd
mergedEnvs := mergeMap(item.Environment, flagEnvs)
envs := []string{}
for k, v := range mergedEnvs {
env := fmt.Sprintf("%s=%s", k, v)
storeDeployFlags.envvarOpts = append(envs, env)
}
storeDeployFlags.envvarOpts = envs
// Add the store labels to the provided ones from cmd
if item.Labels != nil {
for k, v := range item.Labels {
label := fmt.Sprintf("%s=%s", k, v)
storeDeployFlags.labelOpts = append(storeDeployFlags.labelOpts, label)
}
}
if item.Annotations != nil {
for k, v := range item.Annotations {
annotation := fmt.Sprintf("%s=%s", k, v)
storeDeployFlags.annotationOpts = append(storeDeployFlags.annotationOpts, annotation)
}
}
// Use the network from manifest if not changed by user
if !cmd.Flag("network").Changed {
network = item.Network
}
itemName := item.Name
if functionName != "" {
itemName = functionName
}
imageName := item.GetImageName(targetPlatform)
gateway = getGatewayURL(gateway, defaultGateway, "", os.Getenv(openFaaSURLEnvironment))
cliAuth, err := proxy.NewCLIAuth(token, gateway)
if err != nil {
return err
}
transport := GetDefaultCLITransport(tlsInsecure, &timeoutOverride)
proxyClient, err := proxy.NewClient(cliAuth, gateway, transport, &timeoutOverride)
if err != nil {
return err
}
statusCode, err := deployImage(context.Background(), proxyClient, imageName, item.Fprocess, itemName, "", storeDeployFlags,
tlsInsecure, item.ReadOnlyRootFilesystem, token, functionNamespace)
if badStatusCode(statusCode) {
failedStatusCode := map[string]int{itemName: statusCode}
err := deployFailed(failedStatusCode)
return err
}
return err
}