Allow configuration of CLI config via env variables

**What**
- Support configuration the faas-cli configuration directory path via
  the `OPENFAAS_CONFIG` env variable. When this value is set, the path
  will be overridden. When empty, we will also check the CI flag, which
  defaults the location to the current working directory. When neither
  `OPENFAAS_CONFIG` or `CI` are set, then the default location is in
  the current HOME folder.
- Various tests have been updated to use this new env variable instead
  of modifying the global variables. Also, the variables are now
  constants to prevent this kind of modiication in general.

Signed-off-by: Lucas Roesler <roesler.lucas@gmail.com>
This commit is contained in:
Lucas Roesler
2020-11-08 12:38:13 +01:00
committed by Alex Ellis
parent 6914d950c9
commit d8c8e342c2
3 changed files with 225 additions and 49 deletions

View File

@@ -378,6 +378,8 @@ The [scripts/export-sealed-secret-pubcert.sh](https://github.com/openfaas-incuba
* `OPENFAAS_TEMPLATE_URL` - to set the default URL to pull templates from
* `OPENFAAS_PREFIX` - for use with `faas-cli new` - this can act in place of `--prefix`
* `OPENFAAS_URL` - to override the default gateway URL
* `OPENFAAS_CONFIG` - to override the location of the configuration folder, which contains auth configuration.
* `CI` - to override the location of the configuration folder, when true, the configuration folder is `.openfaas` in the current working directory. This value is ignored if `OPENFAAS_CONFIG` is set.
### FaaS-CLI Developers / Contributors

View File

@@ -18,7 +18,20 @@ import (
"gopkg.in/yaml.v2"
)
var (
//AuthType auth type
type AuthType string
const (
//BasicAuthType basic authentication type
BasicAuthType = "basic"
//Oauth2AuthType oauth2 authentication type
Oauth2AuthType = "oauth2"
// ConfigLocationEnv is the name of he env variable used
// to configure the location of the faas-cli config folder.
// When not set, DefaultDir location is used.
ConfigLocationEnv string = "OPENFAAS_CONFIG"
DefaultDir string = "~/.openfaas"
DefaultFile string = "config.yml"
DefaultPermissions os.FileMode = 0700
@@ -31,16 +44,6 @@ var (
DefaultCIPermissions os.FileMode = 0744
)
//AuthType auth type
type AuthType string
const (
//BasicAuthType basic authentication type
BasicAuthType = "basic"
//Oauth2AuthType oauth2 authentication type
Oauth2AuthType = "oauth2"
)
// ConfigFile for OpenFaaS CLI exclusively.
type ConfigFile struct {
AuthConfigs []AuthConfig `yaml:"auths"`
@@ -66,6 +69,28 @@ func New(filePath string) (*ConfigFile, error) {
return conf, nil
}
// ConfigDir returns the path to the faas-cli config directory.
// When
// 1. CI = "true" and OPENFAAS_CONFIG="", then it will return `.openfaas`, which is located in the current working directory.
// 2. CI = "true" and OPENFAAS_CONFIG="<path>", then it will return the path value in OPENFAAS_CONFIG
// 3. CI = "" and OPENFAAS_CONFIG="", then it will return the default location ~/.openfaas
func ConfigDir() string {
override := os.Getenv(ConfigLocationEnv)
ci := isRunningInCI()
switch {
// case (1) from docs string
case ci && override == "":
return DefaultCIDir
// case (2) from the doc string
case override != "":
// case (3) from the doc string
return override
default:
return DefaultDir
}
}
// isRunningInCI checks the ENV var CI and returns true if it's set to true or 1
func isRunningInCI() bool {
if env, ok := os.LookupEnv("CI"); ok {
@@ -79,10 +104,9 @@ func isRunningInCI() bool {
// EnsureFile creates the root dir and config file
func EnsureFile() (string, error) {
permission := DefaultPermissions
dir := DefaultDir
dir := ConfigDir()
if isRunningInCI() {
permission = DefaultCIPermissions
dir = DefaultCIDir
}
dirPath, err := homedir.Expand(dir)
if err != nil {
@@ -107,10 +131,7 @@ func EnsureFile() (string, error) {
// FileExists returns true if the config file is located at the default path
func fileExists() bool {
dir := DefaultDir
if isRunningInCI() {
dir = DefaultCIDir
}
dir := ConfigDir()
dirPath, err := homedir.Expand(dir)
if err != nil {
return false

View File

@@ -13,9 +13,16 @@ import (
)
func Test_LookupAuthConfig_WithNoConfigFile(t *testing.T) {
DefaultDir, _ = ioutil.TempDir("", "faas-cli-file-test")
DefaultFile = "test1.yml"
_, err := LookupAuthConfig("http://openfaas.test1")
configDir, err := ioutil.TempDir("", "faas-cli-file-test")
if err != nil {
t.Fatalf("can not create test config directory: %s", err)
}
defer os.RemoveAll(configDir)
os.Setenv(ConfigLocationEnv, configDir)
defer os.Unsetenv(ConfigLocationEnv)
_, err = LookupAuthConfig("http://openfaas.test1")
if err == nil {
t.Errorf("Error was not returned")
}
@@ -27,15 +34,25 @@ func Test_LookupAuthConfig_WithNoConfigFile(t *testing.T) {
}
func Test_LookupAuthConfig_GatewayWithNoConfig(t *testing.T) {
DefaultDir, _ = ioutil.TempDir("", "faas-cli-file-test")
DefaultFile = "test2.yml"
configDir, err := ioutil.TempDir("", "faas-cli-file-test")
if err != nil {
t.Fatalf("can not create test config directory: %s", err)
}
defer os.RemoveAll(configDir)
os.Setenv(ConfigLocationEnv, configDir)
defer os.Unsetenv(ConfigLocationEnv)
u := "admin"
p := "some pass"
gatewayURL := strings.TrimRight("http://openfaas.test/", "/")
token := EncodeAuth(u, p)
UpdateAuthConfig(gatewayURL, token, BasicAuthType)
err = UpdateAuthConfig(gatewayURL, token, BasicAuthType)
if err != nil {
t.Fatalf("unexpected error when updating auth config: %s", err)
}
_, err := LookupAuthConfig("http://openfaas.com")
_, err = LookupAuthConfig("http://openfaas.com")
if err == nil {
t.Errorf("Error was not returned")
}
@@ -47,13 +64,23 @@ func Test_LookupAuthConfig_GatewayWithNoConfig(t *testing.T) {
}
func Test_UpdateAuthConfig_Insert(t *testing.T) {
DefaultDir, _ = ioutil.TempDir("", "faas-cli-file-test")
DefaultFile = "test2.yml"
configDir, err := ioutil.TempDir("", "faas-cli-file-test")
if err != nil {
t.Fatalf("can not create test config directory: %s", err)
}
defer os.RemoveAll(configDir)
os.Setenv(ConfigLocationEnv, configDir)
defer os.Unsetenv(ConfigLocationEnv)
u := "admin"
p := "some pass"
gatewayURL := strings.TrimRight("http://openfaas.test/", "/")
token := EncodeAuth(u, p)
UpdateAuthConfig(gatewayURL, token, BasicAuthType)
err = UpdateAuthConfig(gatewayURL, token, BasicAuthType)
if err != nil {
t.Fatalf("unexpected error when updating auth config: %s", err)
}
authConfig, err := LookupAuthConfig(gatewayURL)
if err != nil {
@@ -73,13 +100,23 @@ func Test_UpdateAuthConfig_Insert(t *testing.T) {
}
func Test_UpdateAuthConfig_Update(t *testing.T) {
DefaultDir, _ = ioutil.TempDir("", "faas-cli-file-test")
DefaultFile = "test3.yml"
configDir, err := ioutil.TempDir("", "faas-cli-file-test")
if err != nil {
t.Fatalf("can not create test config directory: %s", err)
}
defer os.RemoveAll(configDir)
os.Setenv(ConfigLocationEnv, configDir)
defer os.Unsetenv(ConfigLocationEnv)
u := "admin"
p := "pass"
gatewayURL := strings.TrimRight("http://openfaas.test/", "/")
token := EncodeAuth(u, p)
UpdateAuthConfig(gatewayURL, token, BasicAuthType)
err = UpdateAuthConfig(gatewayURL, token, BasicAuthType)
if err != nil {
t.Fatalf("unexpected error when updating auth config: %s", err)
}
authConfig, err := LookupAuthConfig(gatewayURL)
if err != nil {
@@ -97,7 +134,10 @@ func Test_UpdateAuthConfig_Update(t *testing.T) {
u = "admin2"
p = "pass2"
token = EncodeAuth(u, p)
UpdateAuthConfig(gatewayURL, token, BasicAuthType)
err = UpdateAuthConfig(gatewayURL, token, BasicAuthType)
if err != nil {
t.Fatalf("unexpected error when updating auth config: %s", err)
}
authConfig, err = LookupAuthConfig(gatewayURL)
if err != nil {
@@ -148,13 +188,21 @@ func Test_New_NoFile(t *testing.T) {
}
func Test_EnsureFile(t *testing.T) {
DefaultDir, _ = ioutil.TempDir("", "faas-cli-file-test")
DefaultFile = "test6.yml"
configDir, err := ioutil.TempDir("", "faas-cli-file-test")
if err != nil {
t.Fatalf("can not create test config directory: %s", err)
}
defer os.RemoveAll(configDir)
os.Setenv(ConfigLocationEnv, configDir)
defer os.Unsetenv(ConfigLocationEnv)
cfg, err := EnsureFile()
if err != nil {
t.Error(err.Error())
}
if _, err := os.Stat(cfg); os.IsNotExist(err) {
_, err = os.Stat(cfg)
if os.IsNotExist(err) {
t.Errorf("expected config at %s", cfg)
}
}
@@ -174,19 +222,31 @@ func Test_DecodeAuth(t *testing.T) {
}
func Test_RemoveAuthConfig(t *testing.T) {
DefaultDir, _ = ioutil.TempDir("", "faas-cli-file-test")
DefaultFile = "test7.yml"
configDir, err := ioutil.TempDir("", "faas-cli-file-test")
if err != nil {
t.Fatalf("can not create test config directory: %s", err)
}
defer os.RemoveAll(configDir)
os.Setenv(ConfigLocationEnv, configDir)
defer os.Unsetenv(ConfigLocationEnv)
u := "admin"
p := "pass"
token := EncodeAuth(u, p)
gatewayURL := strings.TrimRight("http://openfaas.test/", "/")
UpdateAuthConfig(gatewayURL, token, BasicAuthType)
err = UpdateAuthConfig(gatewayURL, token, BasicAuthType)
if err != nil {
t.Fatalf("unexpected error when updating auth config: %s", err)
}
gatewayURL2 := strings.TrimRight("http://openfaas.test2/", "/")
UpdateAuthConfig(gatewayURL2, token, BasicAuthType)
err = UpdateAuthConfig(gatewayURL2, token, BasicAuthType)
if err != nil {
t.Fatalf("unexpected error when updating auth config: %s", err)
}
err := RemoveAuthConfig(gatewayURL)
err = RemoveAuthConfig(gatewayURL)
if err != nil {
t.Errorf("got error %s", err.Error())
}
@@ -202,9 +262,16 @@ func Test_RemoveAuthConfig(t *testing.T) {
}
func Test_RemoveAuthConfig_WithNoConfigFile(t *testing.T) {
DefaultDir, _ = ioutil.TempDir("", "faas-cli-file-test")
DefaultFile = "test8.yml"
err := RemoveAuthConfig("http://openfaas.test1")
configDir, err := ioutil.TempDir("", "faas-cli-file-test")
if err != nil {
t.Fatalf("can not create test config directory: %s", err)
}
defer os.RemoveAll(configDir)
os.Setenv(ConfigLocationEnv, configDir)
defer os.Unsetenv(ConfigLocationEnv)
err = RemoveAuthConfig("http://openfaas.test1")
if err == nil {
t.Errorf("Error was not returned")
}
@@ -216,16 +283,25 @@ func Test_RemoveAuthConfig_WithNoConfigFile(t *testing.T) {
}
func Test_RemoveAuthConfig_WithUnknownGateway(t *testing.T) {
DefaultDir, _ = ioutil.TempDir("", "faas-cli-file-test")
DefaultFile = "test9.yml"
configDir, err := ioutil.TempDir("", "faas-cli-file-test")
if err != nil {
t.Fatalf("can not create test config directory: %s", err)
}
defer os.RemoveAll(configDir)
os.Setenv(ConfigLocationEnv, configDir)
defer os.Unsetenv(ConfigLocationEnv)
u := "admin"
p := "pass"
token := EncodeAuth(u, p)
gatewayURL := strings.TrimRight("http://openfaas.test/", "/")
UpdateAuthConfig(gatewayURL, token, BasicAuthType)
err = UpdateAuthConfig(gatewayURL, token, BasicAuthType)
if err != nil {
t.Fatalf("unexpected error when updating auth config: %s", err)
}
err := RemoveAuthConfig("http://openfaas.test1")
err = RemoveAuthConfig("http://openfaas.test1")
if err == nil {
t.Errorf("Error was not returned")
}
@@ -237,11 +313,21 @@ func Test_RemoveAuthConfig_WithUnknownGateway(t *testing.T) {
}
func Test_UpdateAuthConfig_Oauth2Insert(t *testing.T) {
DefaultDir, _ = ioutil.TempDir("", "faas-cli-file-test")
DefaultFile = "test2.yml"
configDir, err := ioutil.TempDir("", "faas-cli-file-test")
if err != nil {
t.Fatalf("can not create test config directory: %s", err)
}
defer os.RemoveAll(configDir)
os.Setenv(ConfigLocationEnv, configDir)
defer os.Unsetenv(ConfigLocationEnv)
token := "somebase64encodedstring"
gatewayURL := strings.TrimRight("http://openfaas.test/", "/")
UpdateAuthConfig(gatewayURL, token, Oauth2AuthType)
err = UpdateAuthConfig(gatewayURL, token, Oauth2AuthType)
if err != nil {
t.Fatalf("unexpected error when updating auth config: %s", err)
}
authConfig, err := LookupAuthConfig(gatewayURL)
if err != nil {
@@ -253,3 +339,70 @@ func Test_UpdateAuthConfig_Oauth2Insert(t *testing.T) {
t.Errorf("got token %s, expected %s", authConfig.Token, token)
}
}
func Test_ConfigDir(t *testing.T) {
cases := []struct {
name string
env map[string]string
expectedPath string
}{
{
name: "override value is returned",
env: map[string]string{
"OPENFAAS_CONFIG": "/tmp/foo",
},
expectedPath: "/tmp/foo",
},
{
name: "override value is returned, when CI is set but false",
env: map[string]string{
"OPENFAAS_CONFIG": "/tmp/foo",
"CI": "false",
},
expectedPath: "/tmp/foo",
},
{
name: "override value is returned even when CI is set",
env: map[string]string{
"OPENFAAS_CONFIG": "/tmp/foo",
"CI": "true",
},
expectedPath: "/tmp/foo",
},
{
name: "when CI is true, return the default CI directory",
env: map[string]string{
"CI": "true",
},
expectedPath: DefaultCIDir,
},
{
name: "when CI is false, return the default directory",
env: map[string]string{
"CI": "false",
},
expectedPath: DefaultDir,
},
{
name: "when no other env variables are set, the default path is returned",
expectedPath: DefaultDir,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
for name, value := range tc.env {
os.Setenv(name, value)
defer os.Unsetenv(name)
}
path := ConfigDir()
if path != tc.expectedPath {
t.Fatalf("expected config path '%s', got '%s'", tc.expectedPath, path)
}
})
}
}