Skip to content

Commit

Permalink
Config with env (#1072)
Browse files Browse the repository at this point in the history
* config easegress-server with env

* update doc

* add more test
  • Loading branch information
suchen-sci committed Aug 31, 2023
1 parent 5382955 commit 642d6b7
Show file tree
Hide file tree
Showing 4 changed files with 229 additions and 1 deletion.
46 changes: 46 additions & 0 deletions doc/cookbook/multi-node-cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [Deploy an Easegress Cluster Step by Step](#deploy-an-easegress-cluster-step-by-step)
- [Add New Member](#add-new-member)
- [YAML Configuration (optional)](#yaml-configuration-optional)
- [Flags and Environment Variables](#flags-and-environment-variables)
- [Configuration tips (optional)](#configuration-tips-optional)
- [References](#references)

Expand Down Expand Up @@ -187,6 +188,51 @@ cluster:
- http:https://$HOST1:2380
```

## Flags and Environment Variables

In addition to deploying the easegress-server using command-line flags or a YAML file, you can also utilize environment variables. Below are all the available environment variables along with their corresponding flags.

```
EASEGRESS_NAME: --name
EASEGRESS_LABELS: --labels
EASEGRESS_CONFIG_FILE: --config-file
EASEGRESS_FORCE_NEW_CLUSTER: --force-new-cluster
EASEGRESS_SIGNAL_UPGRADE: --signal-upgrade
EASEGRESS_USE_STANDALONE_ETCD: --use-standalone-etcd
EASEGRESS_CLUSTER_NAME: --cluster-name
EASEGRESS_CLUSTER_ROLE: --cluster-role
EASEGRESS_CLUSTER_REQUEST_TIMEOUT: --cluster-request-timeout
EASEGRESS_LISTEN_CLIENT_URLS: --listen-client-urls
EASEGRESS_LISTEN_PEER_URLS: --listen-peer-urls
EASEGRESS_ADVERTISE_CLIENT_URLS: --advertise-client-urls
EASEGRESS_INITIAL_ADVERTISE_PEER_URLS: --initial-advertise-peer-urls
EASEGRESS_INITIAL_CLUSTER: --initial-cluster
EASEGRESS_STATE_FLAG: --state-flag
EASEGRESS_PRIMARY_LISTEN_PEER_URLS: --primary-listen-peer-urls
EASEGRESS_MAX_CALL_SEND_MSG_SIZE: --max-call-send-msg-size
EASEGRESS_API_ADDR: --api-addr
EASEGRESS_TLS: --tls
EASEGRESS_CERT_FILE: --cert-file
EASEGRESS_KEY_FILE: --key-file
EASEGRESS_DEBUG: --debug
EASEGRESS_DISABLE_ACCESS: --disable-access
EASEGRESS_OBJECTS_DUMP_INTERVAL: --objects-dump-interval
EASEGRESS_INITIAL_OBJECT_CONFIG_FILES: --initial-object-config-files
EASEGRESS_HOME_DIR: --home-dir
EASEGRESS_DATA_DIR: --data-dir
EASEGRESS_WAL_DIR: --wal-dir
EASEGRESS_LOG_DIR: --log-dir
EASEGRESS_MEMBER_DIR: --member-dir
EASEGRESS_CPU_PROFILE_FILE: --cpu-profile-file
EASEGRESS_MEMORY_PROFILE_FILE: --memory-profile-file
EASEGRESS_STATUS_UPDATE_MAX_BATCH_SIZE: --status-update-max-batch-size
```

## Configuration tips (optional)

*What is a good size for the cluster?*
Expand Down
52 changes: 52 additions & 0 deletions pkg/option/env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2017, MegaEase
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package option

import (
"fmt"
"os"
"strings"

"github.com/spf13/pflag"
)

// SetFlagsFromEnv sets flags from environment variables.
func SetFlagsFromEnv(prefix string, fs *pflag.FlagSet) error {
var err error
fs.VisitAll(func(f *pflag.Flag) {
if err2 := setFlagFromEnv(fs, prefix, f.Name); err2 != nil {
err = err2
}
})
return err
}

func flagToEnv(prefix, name string) string {
return prefix + "_" + strings.ToUpper(strings.ReplaceAll(name, "-", "_"))
}

func setFlagFromEnv(fs *pflag.FlagSet, prefix, flagName string) error {
key := flagToEnv(prefix, flagName)
val := os.Getenv(key)
if val != "" {
if err := fs.Set(flagName, val); err != nil {
return fmt.Errorf("invalid value %q for %s: %v", val, key, err)
}
}
return nil
}
126 changes: 126 additions & 0 deletions pkg/option/env_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2017, MegaEase
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package option

import (
"os"
"strings"
"testing"

"github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
)

func resetEnv() func() {
envs := os.Environ()
return func() {
os.Clearenv()
for _, env := range envs {
kv := strings.SplitN(env, "=", 2)
os.Setenv(kv[0], kv[1])
}
}
}

func TestSetFlagsFromEnv(t *testing.T) {
assert := assert.New(t)

reset := resetEnv()
defer reset()
os.Setenv("EASEGRESS_TEST_STRING", "test")
os.Setenv("EASEGRESS_TEST_BOOL", "true")
os.Setenv("EASEGRESS_TEST_ARRAY", "a,b,c")
os.Setenv("EASEGRESS_TEST_INT", "1")

var stringFlag string
var boolFlag bool
var arrayFlag []string
var intFlag int
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
flags.StringVar(&stringFlag, "test-string", "", "test string flag")
flags.BoolVar(&boolFlag, "test-bool", false, "test bool flag")
flags.StringSliceVar(&arrayFlag, "test-array", []string{}, "test array flag")
flags.IntVar(&intFlag, "test-int", 0, "test int flag")

err := SetFlagsFromEnv("EASEGRESS", flags)
assert.NoError(err)
assert.Equal("test", stringFlag)
assert.Equal(true, boolFlag)
assert.Equal([]string{"a", "b", "c"}, arrayFlag)
assert.Equal(1, intFlag)
}

func TestSetFlagsFromEnvFail(t *testing.T) {
assert := assert.New(t)

reset := resetEnv()
defer reset()
os.Setenv("EASEGRESS_TEST_BOOL", "123")

var boolFlag bool
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
flags.BoolVar(&boolFlag, "test-bool", false, "test bool flag")

err := SetFlagsFromEnv("EASEGRESS", flags)
assert.Error(err)

os.Setenv("EASEGRESS_VERSION", "not-a-bool")
// options from env
opt := New()
err = opt.Parse()
assert.Error(err)
}

func TestOptionFromEnv(t *testing.T) {
assert := assert.New(t)

reset := resetEnv()
defer reset()
os.Setenv("EASEGRESS_NAME", "test-option-from-env")
os.Setenv("EASEGRESS_HOME_DIR", "./test-home-dir")
os.Setenv("EASEGRESS_LOG_DIR", "./test-log-dir")
os.Setenv("EASEGRESS_NAME", "test-option-from-env")
os.Setenv("EASEGRESS_LISTEN_CLIENT_URLS", "http:https://localhost:2379,http:https://localhost:10080")

{
// options from env
opt := New()
err := opt.Parse()
assert.NoError(err)
assert.Equal("test-option-from-env", opt.Name)
assert.Equal("./test-home-dir", opt.HomeDir)
assert.Equal("./test-log-dir", opt.LogDir)
assert.Equal([]string{"http:https://localhost:2379", "http:https://localhost:10080"}, opt.Cluster.ListenClientURLs)
}

{
args := os.Args
defer func() {
os.Args = args
}()
os.Args = []string{"easegress-server", "--name=test-option-from-args", "--home-dir=./test-home-dir-from-args", "--log-dir=./test-log-dir-from-args"}
// options from env and args
opt := New()
err := opt.Parse()
assert.NoError(err)
assert.Equal("test-option-from-args", opt.Name)
assert.Equal("./test-home-dir-from-args", opt.HomeDir)
assert.Equal("./test-log-dir-from-args", opt.LogDir)
assert.Equal([]string{"http:https://localhost:2379", "http:https://localhost:10080"}, opt.Cluster.ListenClientURLs)
}
}
6 changes: 5 additions & 1 deletion pkg/option/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,11 @@ func (opt *Options) renameLegacyClusterRoles() {
// Parse parses all arguments, when the user wants to display version information or view help,
// we do not execute subsequent logic and return directly.
func (opt *Options) Parse() error {
err := opt.flags.Parse(os.Args[1:])
err := SetFlagsFromEnv("EASEGRESS", opt.flags)
if err != nil {
return err
}
err = opt.flags.Parse(os.Args[1:])
if err != nil {
return err
}
Expand Down

0 comments on commit 642d6b7

Please sign in to comment.