diff --git a/args/args.go b/args/args.go new file mode 100644 index 00000000..5941640e --- /dev/null +++ b/args/args.go @@ -0,0 +1,100 @@ +package args + +import ( + "fmt" + "strings" + + "github.com/roboll/helmfile/state" +) + +type argMap struct { + m map[string]string + flags []string +} + +func (a *argMap) SetArg(flag, arg string) { + if _, exists := a.m[flag]; !exists { + a.m[flag] = arg + a.flags = append(a.flags, flag) + } +} + +func newArgMap() *argMap { + return &argMap{m: map[string]string{}} +} + +func GetArgs(args string, state *state.HelmState) []string { + //args := c.String("args") + argsMap := newArgMap() + spaceflagArg := map[string]bool{} + + if len(args) > 0 { + argsVals := strings.Split(args, " ") + prevFlag := "" + for _, arg := range argsVals { + if strings.HasPrefix(arg, "--") { + argVal := strings.SplitN(arg, "=", 2) + if len(argVal) > 1 { + arg := argVal[0] + value := argVal[1] + argsMap.SetArg(arg, value) + } else { + argsMap.SetArg(arg, "") + } + prevFlag = arg + } else { + spaceflagArg[prevFlag] = true + argsMap.m[prevFlag] = arg + } + } + } + + if len(state.HelmDefaults.Args) > 0 { + for _, arg := range state.HelmDefaults.Args { + var flag string + var val string + + argsNum, _ := fmt.Sscanf(arg, "--%s %s", &flag, &val) + if argsNum == 2 { + argsMap.SetArg(flag, arg) + } else { + argVal := strings.SplitN(arg, "=", 2) + argFirst := argVal[0] + if len(argVal) > 1 { + val = argVal[1] + argsMap.SetArg(argFirst, val) + } else { + argsMap.SetArg(argFirst, "") + } + } + } + } + + if state.HelmDefaults.TillerNamespace != "" { + argsMap.SetArg("--tiller-namespace", state.HelmDefaults.TillerNamespace) + } + if state.HelmDefaults.KubeContext != "" { + argsMap.SetArg("--kube-context", state.HelmDefaults.KubeContext) + } + + var argArr []string + + for _, flag := range argsMap.flags { + val := argsMap.m[flag] + + if val != "" { + if spaceflagArg[flag] { + argArr = append(argArr, fmt.Sprintf("%s %s", flag, val)) + } else { + argArr = append(argArr, fmt.Sprintf("%s=%s", flag, val)) + } + + } else { + argArr = append(argArr, fmt.Sprintf("%s", flag)) + } + } + + state.HelmDefaults.Args = argArr + + return state.HelmDefaults.Args +} diff --git a/args/args_test.go b/args/args_test.go new file mode 100644 index 00000000..9655256f --- /dev/null +++ b/args/args_test.go @@ -0,0 +1,34 @@ +package args + +import ( + "fmt" + "strings" + "testing" + + "github.com/roboll/helmfile/state" +) + +func TestGetArgs(t *testing.T) { + args := "--timeout=3600 --set app1.bootstrap=true,app2.bootstrap=false --tiller-namespace ns" + defaultArgs := []string{"--recreate-pods", "--force"} + fmt.Println(defaultArgs) + fmt.Println(len(defaultArgs)) + Helmdefaults := state.HelmSpec{KubeContext: "test", TillerNamespace: "test-namespace", Args: defaultArgs} + testState := &state.HelmState{HelmDefaults: Helmdefaults} + receivedArgs := GetArgs(args, testState) + + expectedOutput := "--timeout=3600 --set app1.bootstrap=true,app2.bootstrap=false --tiller-namespace ns --recreate-pods --force --kube-context=test" + + if compareArgs(expectedOutput, receivedArgs) == false { + t.Errorf("expected %s, got %s", expectedOutput, strings.Join(receivedArgs, " ")) + } +} + +func compareArgs(expectedArgs string, args []string) bool { + + if strings.Compare(strings.Join(args, " "), expectedArgs) != 0 { + return false + } + return true + +} diff --git a/main.go b/main.go index 884d4251..27eebf71 100644 --- a/main.go +++ b/main.go @@ -7,15 +7,16 @@ import ( "os/signal" "path/filepath" "sort" - "strings" "syscall" + "os/exec" + + "github.com/roboll/helmfile/args" "github.com/roboll/helmfile/helmexec" "github.com/roboll/helmfile/state" "github.com/urfave/cli" "go.uber.org/zap" "go.uber.org/zap/zapcore" - "os/exec" ) const ( @@ -104,7 +105,7 @@ func main() { }, Action: func(c *cli.Context) error { return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error { - args := getArgs(c, state) + args := args.GetArgs(c.String("args"), state) if len(args) > 0 { helm.SetExtraArgs(args...) } @@ -137,7 +138,7 @@ func main() { }, Action: func(c *cli.Context) error { return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error { - args := getArgs(c, state) + args := args.GetArgs(c.String("args"), state) if len(args) > 0 { helm.SetExtraArgs(args...) } @@ -181,7 +182,7 @@ func main() { }, Action: func(c *cli.Context) error { return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error { - args := getArgs(c, state) + args := args.GetArgs(c.String("args"), state) if len(args) > 0 { helm.SetExtraArgs(args...) } @@ -224,7 +225,7 @@ func main() { }, Action: func(c *cli.Context) error { return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error { - args := getArgs(c, state) + args := args.GetArgs(c.String("args"), state) if len(args) > 0 { helm.SetExtraArgs(args...) } @@ -268,7 +269,7 @@ func main() { return errs } - args := getArgs(c, state) + args := args.GetArgs(c.String("args"), state) if len(args) > 0 { helm.SetExtraArgs(args...) } @@ -302,7 +303,7 @@ func main() { return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error { workers := c.Int("concurrency") - args := getArgs(c, state) + args := args.GetArgs(c.String("args"), state) if len(args) > 0 { helm.SetExtraArgs(args...) } @@ -332,7 +333,7 @@ func main() { return eachDesiredStateDo(c, func(state *state.HelmState, helm helmexec.Interface) []error { purge := c.Bool("purge") - args := getArgs(c, state) + args := args.GetArgs(c.String("args"), state) if len(args) > 0 { helm.SetExtraArgs(args...) } @@ -369,7 +370,7 @@ func main() { cleanup := c.Bool("cleanup") timeout := c.Int("timeout") - args := getArgs(c, state) + args := args.GetArgs(c.String("args"), state) if len(args) > 0 { helm.SetExtraArgs(args...) } @@ -567,63 +568,3 @@ func clean(st *state.HelmState, errs []error) error { } return nil } - -func getArgs(c *cli.Context, state *state.HelmState) []string { - args := c.String("args") - argsMap := map[string]string{} - - if len(args) > 0 { - argsVals := strings.Split(args, " ") - for _, arg := range argsVals { - argVal := strings.SplitN(arg, "=", 2) - if len(argVal) > 1 { - arg := argVal[0] - value := argVal[1] - argsMap[arg] = value - } else { - arg := argVal[0] - argsMap[arg] = "" - } - } - } - if len(state.HelmDefaults.Args) > 0 { - for _, arg := range state.HelmDefaults.Args { - argVal := strings.SplitN(arg, "=", 2) - arg := argVal[0] - if _, exists := argsMap[arg]; !exists { - if len(argVal) > 1 { - argsMap[arg] = argVal[1] - } else { - argsMap[arg] = "" - } - } - } - } - - if state.HelmDefaults.TillerNamespace != "" { - setDefaultValue(argsMap, "--tiller-namespace", state.HelmDefaults.TillerNamespace) - } - if state.HelmDefaults.KubeContext != "" { - setDefaultValue(argsMap, "--kube-context", state.HelmDefaults.KubeContext) - } - - var argArr []string - - for key, val := range argsMap { - if val != "" { - argArr = append(argArr, fmt.Sprintf("%s=%s", key, val)) - } else { - argArr = append(argArr, fmt.Sprintf("%s", key)) - } - } - - state.HelmDefaults.Args = argArr - - return state.HelmDefaults.Args -} - -func setDefaultValue(argsMap map[string]string, flag string, value string) { - if _, exists := argsMap[flag]; !exists { - argsMap[flag] = value - } -}