Skip to content

Commit

Permalink
Tools 2752 conf support (#34)
Browse files Browse the repository at this point in the history
* feat: TOOLS-2752 support astools.conf and astools.yaml
  • Loading branch information
Jesse S authored Feb 6, 2024
1 parent cfa5d8c commit 78f7f0c
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 72 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/mac-artifact.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ jobs:
working-directory: ${{ steps.working-dir.outputs.value }}
run: |
sudo make install
asconfig --version 2>&1 | grep "asconfig"
asconfig --version 2>&1 | grep "Aerospike Config"
- uses: actions/upload-artifact@v3
with:
name: ${{ steps.system-info.outputs.platform }}-${{ runner.arch }}-${{ runner.os }}-${{ steps.system-info.outputs.release }}-asconfig
Expand Down
13 changes: 6 additions & 7 deletions cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/aerospike/aerospike-management-lib/asconfig"
"github.com/aerospike/aerospike-management-lib/info"
"github.com/aerospike/asconfig/conf"
"github.com/aerospike/tools-common-go/client"
"github.com/aerospike/tools-common-go/config"
"github.com/aerospike/tools-common-go/flags"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -50,9 +50,7 @@ func newGenerateCmd() *cobra.Command {

logger.Debugf("Generating config from Aerospike node")

asCommonConfig := client.NewDefaultAerospikeHostConfig()

flags.SetAerospikeConf(asCommonConfig, asCommonFlags)
asCommonConfig := aerospikeFlags.NewAerospikeConfig()

asPolicy, err := asCommonConfig.NewClientPolicy()
if err != nil {
Expand Down Expand Up @@ -143,9 +141,10 @@ func newGenerateCmd() *cobra.Command {
}

res.Version = VERSION
res.Flags().AddFlagSet(
flags.SetAerospikeFlags(asCommonFlags, flags.DefaultWrapHelpString),
)
asFlagSet := aerospikeFlags.NewFlagSet(flags.DefaultWrapHelpString)
res.Flags().AddFlagSet(asFlagSet)
config.BindPFlags(asFlagSet, "cluster")

res.Flags().StringP("output", "o", os.Stdout.Name(), flags.DefaultWrapHelpString("File path to write output to"))
res.Flags().StringP("format", "F", "conf", flags.DefaultWrapHelpString("The format of the destination file(s). Valid options are: yaml, yml, and conf."))

Expand Down
38 changes: 23 additions & 15 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"strings"

"github.com/aerospike/asconfig/log"
"github.com/aerospike/tools-common-go/config"
"github.com/aerospike/tools-common-go/flags"

"github.com/aerospike/asconfig/schema"

Expand All @@ -17,27 +19,34 @@ import (
"github.com/spf13/cobra"
)

// Replaced at compile time
var (
VERSION = "development"
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = newRootCmd()

var (
VERSION = "development" // Replaced at compile time
errInvalidLogLevel = fmt.Errorf("Invalid log-level flag")
aerospikeFlags = flags.NewDefaultAerospikeFlags()
cfFileFlags = flags.NewConfFileFlags()
)

// newRootCmd is the root command constructor. It is useful for producing copies of rootCmd for testing.
func newRootCmd() *cobra.Command {
res := &cobra.Command{
rootCmd := &cobra.Command{
Use: "asconfig",
Short: "Manage Aerospike configuration",
Long: "Asconfig is used to manage Aerospike configuration.",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
var multiErr error

cfgFile, err := config.InitConfig(cfFileFlags.File, cfFileFlags.Instance, cmd.Flags())
if err != nil {
multiErr = errors.Join(multiErr, err)
}

if cfgFile != "" {
logger.Infof("Using config file: %s", cfgFile)
}

lvl, err := cmd.Flags().GetString("log-level")
if err != nil {
multiErr = fmt.Errorf("%w, %w", multiErr, err)
Expand All @@ -54,24 +63,23 @@ func newRootCmd() *cobra.Command {
},
}

res.Version = VERSION
res.SetVersionTemplate("asconfig\n{{printf \"Version %s\" .Version}}\n")
rootCmd.Version = VERSION

logLevelUsage := fmt.Sprintf("Set the logging detail level. Valid levels are: %v", log.GetLogLevels())
res.PersistentFlags().StringP("log-level", "l", "info", logLevelUsage)
res.PersistentFlags().BoolP("version", "V", false, "Version for asconfig.")
res.PersistentFlags().BoolP("help", "u", false, "Display help information")
rootCmd.PersistentFlags().StringP("log-level", "l", "info", logLevelUsage)
rootCmd.PersistentFlags().AddFlagSet(cfFileFlags.NewFlagSet(flags.DefaultWrapHelpString))
flags.SetupRoot(rootCmd, "Aerospike Config")

res.SilenceErrors = true
res.SilenceUsage = true
rootCmd.SilenceErrors = true
rootCmd.SilenceUsage = true

res.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error {
rootCmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error {
logger.Error(err)
cmd.Println(cmd.UsageString())
return errors.Join(err, ErrSilent)
})

return res
return rootCmd
}

// Execute adds all child commands to the root command and sets flags appropriately.
Expand Down
186 changes: 155 additions & 31 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,169 @@ package cmd

import (
"errors"
"os"
"testing"

"github.com/aerospike/tools-common-go/config"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/stretchr/testify/suite"
)

type preTestRoot struct {
flags []string
arguments []string
expectedErrors []error
func TestPersistentPreRunRootFlags(t *testing.T) {
var testCases = []struct {
flags []string
arguments []string
expectedErrors []error
}{
{
flags: []string{"-l", "info"},
arguments: []string{},
expectedErrors: []error{nil},
},
{
flags: []string{"-l", "panic"},
arguments: []string{},
expectedErrors: []error{nil},
},
{
flags: []string{"--log-level", "bad_level"},
arguments: []string{},
expectedErrors: []error{
errInvalidLogLevel,
},
},
}
cmd := newRootCmd()

for _, tc := range testCases {
t.Run(tc.flags[0], func(t *testing.T) {
cmd.ParseFlags(tc.flags)
err := cmd.PersistentPreRunE(cmd, tc.arguments)
for _, expectedErr := range tc.expectedErrors {
if !errors.Is(err, expectedErr) {
t.Errorf("%v\n actual err: %v\n is not expected err: %v", tc.flags, err, expectedErr)
}
}
})
}
}

var preTestsRoot = []preTestRoot{
{
flags: []string{"-l", "info"},
arguments: []string{},
expectedErrors: []error{nil},
},
{
flags: []string{"-l", "panic"},
arguments: []string{},
expectedErrors: []error{nil},
},
{
flags: []string{"--log-level", "bad_level"},
arguments: []string{},
expectedErrors: []error{
errInvalidLogLevel,
},
},
const tomlConfigTxt = `
[group1]
str1 = "localhost:3000"
int1 = 3000
bool1 = true
[group2]
str2 = "localhost:4000"
int2 = 4000
bool2 = false
`

const yamlConfigTxt = `
group1:
str1: "localhost:3000"
int1: 3000
bool1: true
group2:
str2: "localhost:4000"
int2: 4000
bool2: false
`

type RootTest struct {
suite.Suite
}

func TestPersistentPreRunRoot(t *testing.T) {
cmd := newRootCmd()
func (suite *RootTest) TestPersistentPreRunRootInitConfig() {
testCases := []struct {
configFile string
configFileTxt string
}{
{
configFile: "test.conf",
configFileTxt: tomlConfigTxt,
},
{
configFile: "test.yaml",
configFileTxt: yamlConfigTxt,
},
}

for _, test := range preTestsRoot {
cmd.ParseFlags(test.flags)
err := cmd.PersistentPreRunE(cmd, test.arguments)
for _, expectedErr := range test.expectedErrors {
if !errors.Is(err, expectedErr) {
t.Errorf("%v\n actual err: %v\n is not expected err: %v", test.flags, err, expectedErr)
}
createCmd := func() (*cobra.Command, *pflag.FlagSet, *pflag.FlagSet) {
rootCmd := newRootCmd()
subCmd := &cobra.Command{
Use: "sub",
Run: func(cmd *cobra.Command, args []string) {},
}
flagSet1 := &pflag.FlagSet{}
flagSet2 := &pflag.FlagSet{}

rootCmd.AddCommand(subCmd)
flagSet1.String("str1", "str1", "string flag")
flagSet1.Int("int1", 0, "int flag")
flagSet1.Bool("bool1", false, "bool flag")
flagSet2.String("str2", "str2", "string flag")
flagSet2.Int("int2", 0, "int flag")
flagSet2.Bool("bool2", false, "bool flag")
config.BindPFlags(flagSet1, "group1")
config.BindPFlags(flagSet2, "group2")
subCmd.PersistentFlags().AddFlagSet(flagSet1)
subCmd.PersistentFlags().AddFlagSet(flagSet2)

return rootCmd, flagSet1, flagSet2
}

for _, tc := range testCases {
suite.T().Run(tc.configFile, func(t *testing.T) {
config.Reset()

rootCmd, flagSet1, flagSet2 := createCmd()

err := os.WriteFile(tc.configFile, []byte(tc.configFileTxt), 0600)
if err != nil {
t.Fatalf("unable to write %s: %v", tc.configFile, err)
}

defer os.Remove(tc.configFile)

rootCmd.SetArgs([]string{"sub", "--config-file", tc.configFile})
err = rootCmd.Execute()

if err != nil {
suite.FailNow("unexpected error", err)
}

str1, err := flagSet1.GetString("str1")
suite.NoError(err)
suite.Equal("localhost:3000", str1)

int1, err := flagSet1.GetInt("int1")
suite.NoError(err)
suite.Equal(3000, int1)

bool1, err := flagSet1.GetBool("bool1")
suite.NoError(err)
suite.Equal(true, bool1)

str2, err := flagSet2.GetString("str2")
suite.NoError(err)
suite.Equal("localhost:4000", str2)

int2, err := flagSet2.GetInt("int2")
suite.NoError(err)
suite.Equal(4000, int2)

bool2, err := flagSet2.GetBool("bool2")
suite.NoError(err)
suite.Equal(false, bool2)

})
}
}

func TestRunTestSuite(t *testing.T) {
suite.Run(t, new(RootTest))
}
22 changes: 20 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,53 @@ go 1.20
require (
github.com/aerospike/aerospike-client-go/v6 v6.14.1
github.com/aerospike/aerospike-management-lib v1.2.1-0.20240131023930-e7454a7e0866
github.com/aerospike/tools-common-go v0.0.0-20240126183151-d9f720a5507f
github.com/aerospike/tools-common-go v0.0.0-20240202003831-d9386330f03a
github.com/bombsimon/logrusr/v4 v4.1.0
github.com/docker/docker v24.0.7+incompatible
github.com/go-logr/logr v1.4.1
github.com/opencontainers/image-spec v1.0.2
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/viper v1.18.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/yuin/gopher-lua v1.1.1 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/sync v0.6.0 // indirect
Expand All @@ -44,4 +61,5 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect
google.golang.org/grpc v1.60.1 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
Loading

0 comments on commit 78f7f0c

Please sign in to comment.