Unverified Commit 4b57951f authored by Derek Nola's avatar Derek Nola Committed by GitHub

Fix to allow etcd-snapshot to use config file with flags that are only used with…

Fix to allow etcd-snapshot to use config file with flags that are only used with k3s server. (#4464) * Enabled skipping of unknown flags from config in parser * Added new unit test, expanded existing Signed-off-by: 's avatarDerek Nola <derek.nola@suse.com>
parent 5ab6d21a
package configfilearg
import (
"github.com/rancher/k3s/pkg/cli/cmds"
"github.com/rancher/k3s/pkg/version"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
var defaultParser = &Parser{
After: []string{"server", "agent", "etcd-snapshot:1"},
FlagNames: []string{"--config", "-c"},
EnvName: version.ProgramUpper + "_CONFIG_FILE",
DefaultConfig: "/etc/rancher/" + version.Program + "/config.yaml",
ValidFlags: map[string][]cli.Flag{"server": cmds.ServerFlags, "etcd-snapshot": cmds.EtcdSnapshotFlags},
}
func MustParse(args []string) []string {
parser := &Parser{
After: []string{"server", "agent", "etcd-snapshot:1"},
FlagNames: []string{"--config", "-c"},
EnvName: version.ProgramUpper + "_CONFIG_FILE",
DefaultConfig: "/etc/rancher/" + version.Program + "/config.yaml",
}
result, err := parser.Parse(args)
result, err := defaultParser.Parse(args)
if err != nil {
logrus.Fatal(err)
}
......
package configfilearg
import (
"reflect"
"testing"
)
func Test_UnitMustParse(t *testing.T) {
tests := []struct {
name string
args []string
config string
want []string
}{
{
name: "Basic server",
args: []string{"k3s", "server"},
want: []string{"k3s", "server"},
},
{
name: "Server with known flags",
args: []string{"k3s", "server", "-t 12345", "--write-kubeconfig-mode 644"},
want: []string{"k3s", "server", "-t 12345", "--write-kubeconfig-mode 644"},
},
{
name: "Server with known flags and config with known and unknown flags",
args: []string{"k3s", "server", "--write-kubeconfig-mode 644"},
config: "./testdata/defaultdata.yaml",
want: []string{"k3s", "server", "--token=12345", "--node-label=DEAFBEEF",
"--etcd-s3=true", "--etcd-s3-bucket=my-backup", "--write-kubeconfig-mode 644"},
},
{
name: "Basic etcd-snapshot",
args: []string{"k3s", "etcd-snapshot", "save"},
want: []string{"k3s", "etcd-snapshot", "save"},
},
{
name: "Etcd-snapshot with known flags",
args: []string{"k3s", "etcd-snapshot", "save", "--s3=true"},
want: []string{"k3s", "etcd-snapshot", "save", "--s3=true"},
},
{
name: "Etcd-snapshot with config with known and unknown flags",
args: []string{"k3s", "etcd-snapshot", "save"},
config: "./testdata/defaultdata.yaml",
want: []string{"k3s", "etcd-snapshot", "save", "--etcd-s3=true", "--etcd-s3-bucket=my-backup"},
},
{
name: "Agent with known flags",
args: []string{"k3s", "agent", "--token=12345"},
want: []string{"k3s", "agent", "--token=12345"},
},
{
name: "Agent with config with known and unknown flags, flags are not skipped",
args: []string{"k3s", "agent"},
config: "./testdata/defaultdata.yaml",
want: []string{"k3s", "agent", "--token=12345", "--node-label=DEAFBEEF",
"--etcd-s3=true", "--etcd-s3-bucket=my-backup", "--notaflag=true"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defaultParser.DefaultConfig = tt.config
if got := MustParse(tt.args); !reflect.DeepEqual(got, tt.want) {
t.Errorf("MustParse() = %+v\nWant = %+v", got, tt.want)
}
})
}
}
......@@ -13,6 +13,8 @@ import (
"github.com/rancher/k3s/pkg/agent/util"
"github.com/rancher/wrangler/pkg/data/convert"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"gopkg.in/yaml.v2"
)
......@@ -21,6 +23,7 @@ type Parser struct {
FlagNames []string
EnvName string
DefaultConfig string
ValidFlags map[string][]cli.Flag
}
// Parse will parse an os.Args style slice looking for Parser.FlagNames after Parse.After.
......@@ -44,12 +47,55 @@ func (p *Parser) Parse(args []string) ([]string, error) {
} else if err != nil {
return nil, err
}
if len(args) > 1 {
values, err = p.stripInvalidFlags(args[1], values)
if err != nil {
return nil, err
}
}
return append(prefix, append(values, suffix...)...), nil
}
return args, nil
}
func (p *Parser) stripInvalidFlags(command string, args []string) ([]string, error) {
var result []string
var cmdFlags []cli.Flag
for k, v := range p.ValidFlags {
if k == command {
cmdFlags = v
}
}
if len(cmdFlags) == 0 {
return args, nil
}
validFlags := make(map[string]bool, len(cmdFlags))
for _, f := range cmdFlags {
//split flags with aliases into 2 entries
for _, s := range strings.Split(f.GetName(), ",") {
validFlags[s] = true
}
}
re, err := regexp.Compile("^-+(.+)=")
if err != nil {
return args, err
}
for _, arg := range args {
mArg := arg
if match := re.FindAllStringSubmatch(arg, -1); match != nil {
mArg = match[0][1]
}
if validFlags[mArg] {
result = append(result, arg)
} else {
logrus.Warnf("Unknown flag %s found in config.yaml, skipping\n", arg)
}
}
return result, nil
}
func (p *Parser) FindString(args []string, target string) (string, error) {
configFile, isSet := p.findConfigFileFlag(args)
if configFile != "" {
......@@ -102,7 +148,7 @@ func (p *Parser) findStart(args []string) ([]string, []string, bool) {
if len(p.After) == 0 {
return []string{}, args, true
}
afterTemp := append([]string{}, p.After...)
afterIndex := make(map[string]int)
re, err := regexp.Compile(`(.+):(\d+)`)
if err != nil {
......@@ -110,9 +156,9 @@ func (p *Parser) findStart(args []string) ([]string, []string, bool) {
}
// After keywords ending with ":<NUM>" can set + NUM of arguments as the split point.
// used for matching on subcommmands
for i, arg := range p.After {
for i, arg := range afterTemp {
if match := re.FindAllStringSubmatch(arg, -1); match != nil {
p.After[i] = match[0][1]
afterTemp[i] = match[0][1]
afterIndex[match[0][1]], err = strconv.Atoi(match[0][2])
if err != nil {
return args, nil, false
......@@ -121,7 +167,7 @@ func (p *Parser) findStart(args []string) ([]string, []string, bool) {
}
for i, val := range args {
for _, test := range p.After {
for _, test := range afterTemp {
if val == test {
if skip := afterIndex[test]; skip != 0 {
if len(args) <= i+skip || strings.HasPrefix(args[i+skip], "-") {
......
......@@ -77,6 +77,13 @@ func Test_UnitParser_findStart(t *testing.T) {
found: true,
},
{
name: "another command and subcommand with flags",
args: []string{"etcd-snapshot", "save", "--s3"},
prefix: []string{"etcd-snapshot", "save"},
suffix: []string{"--s3"},
found: true,
},
{
name: "command and too many subcommands",
args: []string{"etcd-snapshot", "list", "delete", "foo", "bar"},
prefix: []string{"etcd-snapshot", "list"},
......
token: 12345
node-label: DEAFBEEF
etcd-s3: true
etcd-s3-bucket: my-backup
notaflag : true
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment