Skip to content

Commit

Permalink
[m3query] Allow for optional override config file. (#1934)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelnikolov authored and arnikola committed Sep 11, 2019
1 parent 6d22d4d commit db4dc03
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 16 deletions.
10 changes: 5 additions & 5 deletions src/cmd/services/m3coordinator/main/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ import (
"os"

"github.com/m3db/m3/src/query/server"
xconfig "github.com/m3db/m3/src/x/config"
"github.com/m3db/m3/src/x/etcd"
)

var (
configFile = flag.String("f", "", "configuration file")
)
var configFiles xconfig.FlagStringSlice

func main() {
flag.Var(&configFiles, "f", "configuration file(s)")
flag.Parse()

if len(*configFile) == 0 {
if len(configFiles) == 0 || len(configFiles[0]) == 0 {
flag.Usage()
os.Exit(1)
}
Expand All @@ -45,6 +45,6 @@ func main() {
etcd.SetGlobals()

server.Run(server.RunOptions{
ConfigFile: *configFile,
ConfigFiles: configFiles,
})
}
10 changes: 5 additions & 5 deletions src/cmd/services/m3query/main/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ import (
"os"

"github.com/m3db/m3/src/query/server"
xconfig "github.com/m3db/m3/src/x/config"
"github.com/m3db/m3/src/x/etcd"
)

var (
configFile = flag.String("f", "", "configuration file")
)
var configFiles xconfig.FlagStringSlice

func main() {
flag.Var(&configFiles, "f", "configuration file(s)")
flag.Parse()

if len(*configFile) == 0 {
if len(configFiles) == 0 || len(configFiles[0]) == 0 {
flag.Usage()
os.Exit(1)
}
Expand All @@ -45,6 +45,6 @@ func main() {
etcd.SetGlobals()

server.Run(server.RunOptions{
ConfigFile: *configFile,
ConfigFiles: configFiles,
})
}
12 changes: 6 additions & 6 deletions src/query/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ type cleanupFn func() error
// RunOptions provides options for running the server
// with backwards compatibility if only solely adding fields.
type RunOptions struct {
// ConfigFile is the config file to use.
ConfigFile string
// ConfigFiles is the array of config files to use. All files of the array get merged together.
ConfigFiles []string

// Config is an alternate way to provide configuration and will be used
// instead of parsing ConfigFile if ConfigFile is not specified.
Expand Down Expand Up @@ -127,12 +127,12 @@ func Run(runOpts RunOptions) {
rand.Seed(time.Now().UnixNano())

var cfg config.Configuration
if runOpts.ConfigFile != "" {
if err := xconfig.LoadFile(&cfg, runOpts.ConfigFile, xconfig.Options{}); err != nil {
fmt.Fprintf(os.Stderr, "unable to load %s: %v", runOpts.ConfigFile, err)
if len(runOpts.ConfigFiles) > 0 {
if err := xconfig.LoadFiles(&cfg, runOpts.ConfigFiles, xconfig.Options{}); err != nil {
fmt.Fprintf(os.Stderr, "unable to load %s: %v", runOpts.ConfigFiles, err)
os.Exit(1)
}
fmt.Fprintf(os.Stdout, "using %s config file: %v", serviceName, runOpts.ConfigFile)
fmt.Fprintf(os.Stdout, "using %s config files: %v", serviceName, runOpts.ConfigFiles)
} else {
cfg = runOpts.Config
}
Expand Down
12 changes: 12 additions & 0 deletions src/x/config/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
package config_test

import (
"flag"
"fmt"
"log"

Expand All @@ -40,3 +41,14 @@ func ExampleLoadFile() {
fmt.Printf("listenAddress: %s\n", cfg.ListenAddress)
// Output: listenAddress: 0.0.0.0:8392
}

// The FlagStringSlice allows for multiple values when used as a flag variable.
func ExampleFlagStringSlice() {
var configFiles config.FlagStringSlice
fs := flag.NewFlagSet("config", flag.PanicOnError)
fs.Var(&configFiles, "f", "config files")
fs.Parse([]string{"-f", "file1.yaml", "-f", "file2.yaml", "-f", "file3.yaml"})
fmt.Println("Config files:", configFiles)
// Output:
// Config files: [file1.yaml file2.yaml file3.yaml]
}
51 changes: 51 additions & 0 deletions src/x/config/flag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2019 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package config

import (
"flag"
"fmt"
)

var _ flag.Value = &FlagStringSlice{}

// FlagStringSlice represents a slice of strings. When used as a flag variable,
// it allows for multiple string values. For example, it can be used like this:
// var configFiles FlagStringSlice
// flag.Var(&configFiles, "f", "configuration file(s)")
// Then it can be invoked like this:
// ./app -f file1.yaml -f file2.yaml -f valueN.yaml
// Finally, when the flags are parsed, the variable contains all the values.
type FlagStringSlice []string

// String() returns a string implmentation of the slice.
func (i *FlagStringSlice) String() string {
if i == nil {
return ""
}
return fmt.Sprintf("%v", ([]string)(*i))
}

// Set appends a string value to the slice.
func (i *FlagStringSlice) Set(value string) error {
*i = append(*i, value)
return nil
}
91 changes: 91 additions & 0 deletions src/x/config/flag_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright (c) 2019 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package config_test

import (
"flag"
"testing"

"github.com/m3db/m3/src/x/config"

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

func TestFlagArray(t *testing.T) {
tests := []struct {
args []string
name string
want string
}{
{
name: "single value",
args: []string{"-f", "./some/file/path/here.yaml"},
want: "[./some/file/path/here.yaml]",
},
{
name: "single empty value",
args: []string{"-f", ""},
want: "[]",
},
{
name: "two value",
args: []string{"-f", "file1.yaml", "-f", "file2.yaml"},
want: "[file1.yaml file2.yaml]",
},
{
name: "two value one of which empty",
args: []string{"-f", "", "-f", "file2.yaml"},
want: "[ file2.yaml]",
},
{
name: "three values",
args: []string{"-f", "file1.yaml", "-f", "file2.yaml", "-f", "file3.yaml"},
want: "[file1.yaml file2.yaml file3.yaml]",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var values config.FlagStringSlice
fs := flag.NewFlagSet(tt.name, flag.PanicOnError)
fs.Var(&values, "f", "config files")
err := fs.Parse(tt.args)
assert.NoError(t, err, "error parsing flags")
assert.Equal(t, tt.want, values.String(), "unexpected output")
})
}
}

func TestFlagStringSliceNilFlag(t *testing.T) {
var s *config.FlagStringSlice
assert.Equal(t, "", s.String(), "nil string slice representation")
}

func TestFlagStringSliceWithOtherFlags(t *testing.T) {
var values config.FlagStringSlice
var x string
fs := flag.NewFlagSet("app", flag.PanicOnError)
fs.StringVar(&x, "x", "", "some random var")
fs.Var(&values, "f", "config files")
fs.Parse([]string{"-f", "file1.yaml", "-x", "file2.yaml", "-f", "file3.yaml"})
assert.Equal(t, "[file1.yaml file3.yaml]", values.String(), "flag string slice representation")
assert.Equal(t, "file2.yaml", x, "x value")
}

0 comments on commit db4dc03

Please sign in to comment.