From 942119bbf1c9d58563832d08f7996f970beb58c0 Mon Sep 17 00:00:00 2001 From: "Alex Ellis (VMware)" Date: Mon, 12 Mar 2018 16:36:23 +0000 Subject: [PATCH] Move from localhost to 127.0.0.1 as a default for IPv6 clashes, add env-var OPENFAAS_URL as override for gateway URL for Kubernetes users Signed-off-by: Alex Ellis (VMware) --- MANUAL_CLI.md | 2 +- README.md | 39 +++++++++++++--- commands/config_priority_test.go | 78 ++++++++++++++++++++++++++++++++ commands/config_priorty.go | 30 ++++++++++++ commands/deploy.go | 21 +-------- commands/deploy_test.go | 59 ------------------------ commands/faas.go | 2 +- commands/invoke.go | 2 +- commands/list.go | 5 +- commands/login.go | 6 ++- commands/remove.go | 3 +- commands/store_deploy.go | 2 +- deploy_samples.sh | 6 +-- sample/hmac.yml | 2 +- stack.yml | 4 +- stack/stack_test.go | 4 +- 16 files changed, 163 insertions(+), 102 deletions(-) create mode 100644 commands/config_priority_test.go create mode 100644 commands/config_priorty.go diff --git a/MANUAL_CLI.md b/MANUAL_CLI.md index a0ac6527..2079574e 100644 --- a/MANUAL_CLI.md +++ b/MANUAL_CLI.md @@ -51,7 +51,7 @@ $ faas-cli deploy \ 200 OK -URL: http://localhost:8080/function/node_info +URL: http://127.0.0.1:8080/function/node_info ``` > This tool can be used to deploy any Docker image as a FaaS function, as long as it includes the watchdog binary as the `CMD` or `ENTRYPOINT` of the image. diff --git a/README.md b/README.md index 37404810..eb387732 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,18 @@ The main commands supported by the CLI are: * `faas-cli logout` - removes basic auth credentials for a given gateway * `faas-cli store` - allows browsing and deploying OpenFaaS store functions +The default gateway URL of `127.0.0.1:8080` can be overriden in three places including an environmental variable. + +* 1st priority `--gateway` flag +* 2nd priority `--yaml` / `-f` flag or `stack.yml` if in current directory +* 3rd priority `OPENFAAS_URL` environmental variable + +For Kubernetes users you may want to set this in your `.bash_rc` file: + +``` +export OPENFAAS_URL=127.0.0.1:31112 +``` + Advanced commands: * `faas-cli template pull` - pull in templates from a remote GitHub repository [Detailed Documentation](guide/TEMPLATE.md) @@ -141,6 +153,9 @@ Specify `lang: Dockerfile` if you want the faas-cli to execute a build or `skip_ * If you are using a stack file add the `skip_build: true` attribute * Use one of the [samples as a basis](https://github.com/openfaas/faas/tree/master/sample-functions) +Read the blog post/tutorial: [Turn Any CLI into a Function with OpenFaaS](https://blog.alexellis.io/cli-functions-with-openfaas/) + + ### Use a YAML stack file A YAML stack file groups functions together and also saves on typing. @@ -152,7 +167,7 @@ Here is an example file using the `stack.yml` file included in the repository. ```yaml provider: name: faas - gateway: http://localhost:8080 + gateway: http://127.0.0.1:8080 functions: url-ping: @@ -187,9 +202,21 @@ Now you can use the following command to deploy your function(s): $ faas-cli deploy -f ./stack.yml ``` -#### Managing secrets +#### Secure secret management -You can deploy secrets and configuration via environmental variables in-line or via external files. +Secrets can be used with OpenFaaS when using Docker Swarm or Kubernetes, this means your data is encrypted at rest and is less likely to be leaked during logging / stack traces than with environmental variables. + +```yaml + secrets: + - secret-name-1 + - secret-name-2 +``` + +Secrets should be defined in the cluster ahead of time using `docker secret create` or `kubectl`. + +#### Managing environment/configuration + +You can deploy non-encrypted secrets and configuration via environmental variables set either in-line or via external (environment) files. > Note: external files take priority over in-line environmental variables. This allows you to specify a default and then have overrides within an external file. @@ -289,12 +316,12 @@ You can initiate a HTTP POST via `curl`: * if you want to pass input from STDIN then use `--data-binary @-` ``` -$ curl -d '{"hello": "world"}' http://localhost:8080/function/nodejs-echo +$ curl -d '{"hello": "world"}' http://127.0.0.1:8080/function/nodejs-echo { nodeVersion: 'v6.9.1', input: '{"hello": "world"}' } -$ curl --data-binary @README.md http://localhost:8080/function/nodejs-echo +$ curl --data-binary @README.md http://127.0.0.1:8080/function/nodejs-echo -$ uname -a | curl http://localhost:8080/function/nodejs-echo--data-binary @- +$ uname -a | curl http://127.0.0.1:8080/function/nodejs-echo--data-binary @- ``` > For further instructions on the manual CLI flags (without using a YAML file) read [manual_cli.md](https://github.com/openfaas/faas-cli/blob/master/MANUAL_CLI.md) diff --git a/commands/config_priority_test.go b/commands/config_priority_test.go new file mode 100644 index 00000000..5d355af0 --- /dev/null +++ b/commands/config_priority_test.go @@ -0,0 +1,78 @@ +// 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 commands + +import ( + "testing" +) + +// Test_getGatewayURL tests for priority of URL for gateway over several sources +func Test_getGatewayURL(t *testing.T) { + defaultValue := "http://127.0.0.1:8080" + testCases := []struct { + name string + defaultURL string + + yamlURL string + argumentURL string + environmentURL string + expectedURL string + }{ + { + name: "Nothing provided", + defaultURL: defaultValue, + yamlURL: "", + argumentURL: "", + expectedURL: "http://127.0.0.1:8080", + }, + { + name: "Only YAML provided", + defaultURL: defaultValue, + yamlURL: "http://remote1:8080", + argumentURL: "", + expectedURL: "http://remote1:8080", + }, + { + name: "Only argument override", + defaultURL: defaultValue, + yamlURL: "", + argumentURL: "http://remote2:8080", + expectedURL: "http://remote2:8080", + }, + { + name: "Prioritize argument over YAML when argument is not default", + defaultURL: defaultValue, + yamlURL: "http://remote-yml:8080", + argumentURL: "http://remote-arg:8080", + expectedURL: "http://remote-arg:8080", + }, + { + name: "When argument is default use YAML", + defaultURL: defaultValue, + yamlURL: "http://remote-yml:8080", + argumentURL: defaultValue, + expectedURL: "http://remote-yml:8080", + }, + { + name: "YAML provided (with defaults) and env-var override", + defaultURL: defaultValue, + yamlURL: defaultValue, + environmentURL: "http://remote2:8080", + argumentURL: "", + expectedURL: "http://remote2:8080", + }, + } + + fails := 0 + for _, testCase := range testCases { + url := getGatewayURL(testCase.argumentURL, testCase.defaultURL, testCase.yamlURL, testCase.environmentURL) + if url != testCase.expectedURL { + t.Logf("gatewayURL %s\nwant: %s, got: %s", testCase.name, testCase.expectedURL, url) + fails++ + } + } + if fails > 0 { + t.Fail() + } +} diff --git a/commands/config_priorty.go b/commands/config_priorty.go new file mode 100644 index 00000000..28cfa820 --- /dev/null +++ b/commands/config_priorty.go @@ -0,0 +1,30 @@ +// 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 commands + +import ( + "fmt" + "strings" +) + +func getGatewayURL(argumentURL, defaultURL, yamlURL, environmentURL string) string { + var gatewayURL string + + if len(argumentURL) > 0 && argumentURL != defaultURL { + gatewayURL = argumentURL + } else if len(yamlURL) > 0 && yamlURL != defaultURL { + gatewayURL = yamlURL + } else if len(environmentURL) > 0 { + gatewayURL = environmentURL + } else { + gatewayURL = defaultURL + } + + gatewayURL = strings.ToLower(strings.TrimRight(gatewayURL, "/")) + if !strings.HasPrefix(gatewayURL, "http") { + gatewayURL = fmt.Sprintf("http://%s", gatewayURL) + } + + return gatewayURL +} diff --git a/commands/deploy.go b/commands/deploy.go index 3342d3d1..c1200bbe 100644 --- a/commands/deploy.go +++ b/commands/deploy.go @@ -119,7 +119,7 @@ func runDeployCommand(args []string, image string, fprocess string, functionName return err } - parsedServices.Provider.GatewayURL = getGatewayURL(gateway, defaultGateway, parsedServices.Provider.GatewayURL) + parsedServices.Provider.GatewayURL = getGatewayURL(gateway, defaultGateway, parsedServices.Provider.GatewayURL, os.Getenv("OPENFAAS_URL")) // Override network if passed if len(network) > 0 && network != defaultNetwork { @@ -303,25 +303,6 @@ func mergeMap(i map[string]string, j map[string]string) map[string]string { return merged } -func getGatewayURL(argumentURL string, defaultURL string, yamlURL string) string { - var gatewayURL string - - if len(argumentURL) > 0 && argumentURL != defaultURL { - gatewayURL = argumentURL - } else if len(yamlURL) > 0 { - gatewayURL = yamlURL - } else { - gatewayURL = defaultURL - } - - gatewayURL = strings.ToLower(strings.TrimRight(gatewayURL, "/")) - if !strings.HasPrefix(gatewayURL, "http") { - gatewayURL = fmt.Sprintf("http://%s", gatewayURL) - } - - return gatewayURL -} - func compileEnvironment(envvarOpts []string, yamlEnvironment map[string]string, fileEnvironment map[string]string) (map[string]string, error) { envvarArguments, err := parseMap(envvarOpts, "env") if err != nil { diff --git a/commands/deploy_test.go b/commands/deploy_test.go index 98e4ff2d..69d71fb7 100644 --- a/commands/deploy_test.go +++ b/commands/deploy_test.go @@ -11,65 +11,6 @@ import ( "github.com/openfaas/faas-cli/test" ) -func Test_getGatewayURL(t *testing.T) { - defaultValue := "http://localhost:8080" - testCases := []struct { - name string - defaultURL string - yamlURL string - argumentURL string - expectedURL string - }{ - { - name: "Nothing provided", - defaultURL: defaultValue, - yamlURL: "", - argumentURL: "", - expectedURL: "http://localhost:8080", - }, - { - name: "Only YAML provided", - defaultURL: defaultValue, - yamlURL: "http://remote1:8080", - argumentURL: "", - expectedURL: "http://remote1:8080", - }, - { - name: "Only argument override", - defaultURL: defaultValue, - yamlURL: "", - argumentURL: "http://remote2:8080", - expectedURL: "http://remote2:8080", - }, - { - name: "Prioritize argument over YAML when argument is not default", - defaultURL: defaultValue, - yamlURL: "http://remote-yml:8080", - argumentURL: "http://remote-arg:8080", - expectedURL: "http://remote-arg:8080", - }, - { - name: "When argument is default use YAML", - defaultURL: defaultValue, - yamlURL: "http://remote-yml:8080", - argumentURL: defaultValue, - expectedURL: "http://remote-yml:8080", - }, - } - - fails := 0 - for _, testCase := range testCases { - url := getGatewayURL(testCase.argumentURL, testCase.defaultURL, testCase.yamlURL) - if url != testCase.expectedURL { - t.Logf("gatewayURL %s\nwant: %s, got: %s", testCase.name, testCase.expectedURL, url) - fails++ - } - } - if fails > 0 { - t.Fail() - } -} - func Test_deploy(t *testing.T) { s := test.MockHttpServer(t, []test.Request{ { diff --git a/commands/faas.go b/commands/faas.go index 82638819..ea6ffe8d 100644 --- a/commands/faas.go +++ b/commands/faas.go @@ -13,7 +13,7 @@ import ( ) const ( - defaultGateway = "http://localhost:8080" + defaultGateway = "http://127.0.0.1:8080" defaultNetwork = "func_functions" defaultYAML = "stack.yml" ) diff --git a/commands/invoke.go b/commands/invoke.go index db6b3c39..b3415cba 100644 --- a/commands/invoke.go +++ b/commands/invoke.go @@ -70,7 +70,7 @@ func runInvoke(cmd *cobra.Command, args []string) error { } } - gatewayAddress := getGatewayURL(gateway, defaultGateway, yamlGateway) + gatewayAddress := getGatewayURL(gateway, defaultGateway, yamlGateway, os.Getenv("OPENFAAS_URL")) stat, _ := os.Stdin.Stat() if (stat.Mode() & os.ModeCharDevice) != 0 { diff --git a/commands/list.go b/commands/list.go index b31c627c..ce0a0f40 100644 --- a/commands/list.go +++ b/commands/list.go @@ -5,6 +5,7 @@ package commands import ( "fmt" + "os" "github.com/openfaas/faas-cli/proxy" "github.com/openfaas/faas-cli/stack" @@ -30,7 +31,7 @@ var listCmd = &cobra.Command{ Short: "List OpenFaaS functions", Long: `Lists OpenFaaS functions either on a local or remote gateway`, Example: ` faas-cli list - faas-cli list --gateway https://localhost:8080 --verbose`, + faas-cli list --gateway https://127.0.0.1:8080 --verbose`, RunE: runList, } @@ -50,7 +51,7 @@ func runList(cmd *cobra.Command, args []string) error { } } - gatewayAddress = getGatewayURL(gateway, defaultGateway, yamlGateway) + gatewayAddress = getGatewayURL(gateway, defaultGateway, yamlGateway, os.Getenv("OPENFAAS_URL")) functions, err := proxy.ListFunctions(gatewayAddress) if err != nil { diff --git a/commands/login.go b/commands/login.go index 31d26de7..c188e7a5 100644 --- a/commands/login.go +++ b/commands/login.go @@ -35,7 +35,7 @@ var loginCmd = &cobra.Command{ Use: `login [--username USERNAME] [--password PASSWORD] [--gateway GATEWAY_URL]`, Short: "Log in to OpenFaaS gateway", Long: "Log in to OpenFaaS gateway.\nIf no gateway is specified, the default local one will be used.", - Example: ` faas-cli login -u user -p password --gateway http://localhost:8080 + Example: ` faas-cli login -u user -p password --gateway http://127.0.0.1:8080 cat ~/faas_pass.txt | faas-cli login -u user --password-stdin --gateway https://openfaas.mydomain.com`, RunE: runLogin, } @@ -76,7 +76,9 @@ func runLogin(cmd *cobra.Command, args []string) error { } fmt.Println("Calling the OpenFaaS server to validate the credentials...") - gateway = getGatewayURL(gateway, "", "") + + gateway = getGatewayURL(gateway, "", "", os.Getenv("OPENFAAS_URL")) + if err := validateLogin(gateway, username, password); err != nil { return err } diff --git a/commands/remove.go b/commands/remove.go index 52d69056..1321970e 100644 --- a/commands/remove.go +++ b/commands/remove.go @@ -5,6 +5,7 @@ package commands import ( "fmt" + "os" "github.com/openfaas/faas-cli/proxy" "github.com/openfaas/faas-cli/stack" @@ -52,7 +53,7 @@ func runDelete(cmd *cobra.Command, args []string) error { } } - gatewayAddress = getGatewayURL(gateway, defaultGateway, yamlGateway) + gatewayAddress = getGatewayURL(gateway, defaultGateway, yamlGateway, os.Getenv("OPENFAAS_URL")) if len(services.Functions) > 0 { if len(services.Provider.Network) == 0 { diff --git a/commands/store_deploy.go b/commands/store_deploy.go index 92bf92fb..ef6c8906 100644 --- a/commands/store_deploy.go +++ b/commands/store_deploy.go @@ -43,7 +43,7 @@ var storeDeployCmd = &cobra.Command{ 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://localhost:8080 \ + --gateway=http://127.0.0.1:8080 \ --env=MYVAR=myval`, RunE: runStoreDeploy, } diff --git a/deploy_samples.sh b/deploy_samples.sh index 4adf84c1..2cb263fa 100755 --- a/deploy_samples.sh +++ b/deploy_samples.sh @@ -8,13 +8,13 @@ sleep 5 curl -SL https://raw.githubusercontent.com/openfaas/faas/master/sample-functions/ResizeImageMagick/gordon.png > gordon.png echo "Testing nodejs-echo" -curl -sd "This was the input string." http://localhost:8080/function/nodejs-echo +curl -sd "This was the input string." http://127.0.0.1:8080/function/nodejs-echo echo echo "Testing url-ping" -curl -sd "https://shop.pimoroni.com" http://localhost:8080/function/url-ping +curl -sd "https://shop.pimoroni.com" http://127.0.0.1:8080/function/url-ping echo echo "Testing shrink-image" -curl -d "" http://localhost:8080/function/shrink-image --data-binary @gordon.png > small_gordon.png +curl -d "" http://127.0.0.1:8080/function/shrink-image --data-binary @gordon.png > small_gordon.png echo diff --git a/sample/hmac.yml b/sample/hmac.yml index 1a6bfb1f..bc607b85 100644 --- a/sample/hmac.yml +++ b/sample/hmac.yml @@ -1,6 +1,6 @@ provider: name: faas - gateway: http://localhost:8080 + gateway: http://127.0.0.1:8080 functions: hmac: diff --git a/stack.yml b/stack.yml index 7c44f111..e7adb13f 100644 --- a/stack.yml +++ b/stack.yml @@ -1,6 +1,6 @@ provider: name: faas - gateway: http://localhost:8080 # can be a remote server + gateway: http://127.0.0.1:8080 # can be a remote server network: "func_functions" # this is optional and defaults to func_functions functions: @@ -31,7 +31,7 @@ functions: requests: memory: 30m - # curl localhost:8080/function/shrink-image --data-binary @big.png > smaller.png + # curl 127.0.0.1:8080/function/shrink-image --data-binary @big.png > smaller.png shrink-image: lang: dockerfile handler: ./sample/imagemagick diff --git a/stack/stack_test.go b/stack/stack_test.go index b0494669..da4d3948 100644 --- a/stack/stack_test.go +++ b/stack/stack_test.go @@ -12,7 +12,7 @@ import ( const TestData_1 string = `provider: name: faas - gateway: http://localhost:8080 + gateway: http://127.0.0.1:8080 network: "func_functions" functions: @@ -45,7 +45,7 @@ functions: const TestData_2 string = `provider: name: faas - gateway: http://localhost:8080 + gateway: http://127.0.0.1:8080 network: "func_functions" `