diff --git a/cmd/minikube/cmd/config/config.go b/cmd/minikube/cmd/config/config.go new file mode 100644 index 000000000000..3f129f32af3b --- /dev/null +++ b/cmd/minikube/cmd/config/config.go @@ -0,0 +1,146 @@ +/* +Copyright 2016 The Kubernetes Authors 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://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 config + +import ( + "encoding/json" + "io" + + "os" + + "github.com/golang/glog" + "github.com/spf13/cobra" + "k8s.io/minikube/pkg/minikube/constants" +) + +type configFile interface { + io.ReadWriter +} + +type setFn func(string, string) error +type MinikubeConfig map[string]interface{} + +type Setting struct { + name string + set func(MinikubeConfig, string, string) error + validations []setFn + callbacks []setFn +} + +// These are all the settings that are configurable +// and their validation and callback fn run on Set +var settings []Setting = []Setting{ + { + name: "vm-driver", + set: SetString, + validations: []setFn{IsValidDriver}, + callbacks: []setFn{RequiresRestartMsg}, + }, + { + name: "cpus", + set: SetInt, + validations: []setFn{IsPositive}, + callbacks: []setFn{RequiresRestartMsg}, + }, + { + name: "disk-size", + set: SetString, + validations: []setFn{IsValidDiskSize}, + callbacks: []setFn{RequiresRestartMsg}, + }, + { + name: "host-only-cidr", + set: SetString, + validations: []setFn{IsValidCIDR}, + }, + { + name: "memory", + set: SetInt, + validations: []setFn{IsPositive}, + callbacks: []setFn{RequiresRestartMsg}, + }, + { + name: "show-libmachine-logs", + set: SetBool, + }, + { + name: "log_dir", + set: SetString, + validations: []setFn{IsValidPath}, + }, + { + name: "kubernetes-version", + set: SetString, + }, +} + +var ConfigCmd = &cobra.Command{ + Use: "config SUBCOMMAND [flags]", + Short: "Modify minikube config", + Long: `config modifies minikube config files using subcommands like "minikube config set vm-driver kvm"`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +// Reads in the JSON minikube config +func ReadConfig() MinikubeConfig { + f, err := os.Open(constants.ConfigFile) + if err != nil { + if os.IsNotExist(err) { + return make(map[string]interface{}) + } + glog.Errorf("Could not open file %s: %s", constants.ConfigFile, err) + } + var m MinikubeConfig + m, err = decode(f) + if err != nil { + glog.Errorf("Could not decode config %s: %s", constants.ConfigFile, err) + } + + return m +} + +// Writes a minikube config to the JSON file +func WriteConfig(m MinikubeConfig) { + f, err := os.Create(constants.ConfigFile) + if err != nil { + glog.Errorf("Could not open file %s: %s", constants.ConfigFile, err) + } + defer f.Close() + err = encode(f, m) + if err != nil { + glog.Errorf("Error encoding config %s: %s", constants.ConfigFile, err) + } +} + +func decode(r io.Reader) (MinikubeConfig, error) { + var data MinikubeConfig + err := json.NewDecoder(r).Decode(&data) + return data, err +} + +func encode(w io.Writer, m MinikubeConfig) error { + b, err := json.MarshalIndent(m, "", " ") + if err != nil { + return err + } + + _, err = w.Write(b) + + return err +} diff --git a/cmd/minikube/cmd/config/config_test.go b/cmd/minikube/cmd/config/config_test.go new file mode 100644 index 000000000000..9d13279aad8e --- /dev/null +++ b/cmd/minikube/cmd/config/config_test.go @@ -0,0 +1,83 @@ +/* +Copyright 2016 The Kubernetes Authors 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://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 config + +import ( + "bytes" + "reflect" + "testing" +) + +type configTestCase struct { + data string + config map[string]interface{} +} + +var configTestCases = []configTestCase{ + { + data: `{ + "memory": 2 +}`, + config: map[string]interface{}{ + "memory": 2, + }, + }, + { + data: `{ + "ReminderWaitPeriodInHours": 99, + "cpus": 4, + "disk-size": "20g", + "log_dir": "/etc/hosts", + "show-libmachine-logs": true, + "v": 5, + "vm-driver": "kvm" +}`, + config: map[string]interface{}{ + "vm-driver": "kvm", + "cpus": 4, + "disk-size": "20g", + "v": 5, + "show-libmachine-logs": true, + "log_dir": "/etc/hosts", + "ReminderWaitPeriodInHours": 99, + }, + }, +} + +func TestReadConfig(t *testing.T) { + for _, tt := range configTestCases { + r := bytes.NewBufferString(tt.data) + config, err := decode(r) + if reflect.DeepEqual(config, tt.config) || err != nil { + t.Errorf("Did not read config correctly,\n\n wanted %+v, \n\n got %+v", tt.config, config) + } + } +} + +func TestWriteConfig(t *testing.T) { + var b bytes.Buffer + for _, tt := range configTestCases { + err := encode(&b, tt.config) + if err != nil { + t.Errorf("Error encoding: %s", err) + } + if b.String() != tt.data { + t.Errorf("Did not write config correctly, \n\n expected:\n %+v \n\n actual:\n %+v", tt.data, b.String()) + } + b.Reset() + } +} diff --git a/cmd/minikube/cmd/config/get.go b/cmd/minikube/cmd/config/get.go new file mode 100644 index 000000000000..7a6d4cb32b9c --- /dev/null +++ b/cmd/minikube/cmd/config/get.go @@ -0,0 +1,49 @@ +/* +Copyright 2016 The Kubernetes Authors 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://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 config + +import ( + "fmt" + "github.com/spf13/cobra" + "os" +) + +var configGetCmd = &cobra.Command{ + Use: "get PROPERTY_NAME", + Short: "Gets the value of PROPERTY_NAME from the minikube config file", + Long: "Returns the value of PROPERTY_NAME from the minikube config file. Can be overwritten at runtime by flags or environmental variables.", + Run: func(cmd *cobra.Command, args []string) { + if len(args) != 1 { + fmt.Fprintln(os.Stderr, "usage: minikube config get PROPERTY_NAME") + os.Exit(1) + } + + val := get(args[0]) + if val != "" { + fmt.Fprintln(os.Stdout, val) + } + }, +} + +func init() { + ConfigCmd.AddCommand(configGetCmd) +} + +func get(name string) string { + m := ReadConfig() + return fmt.Sprintf("%v", m[name]) +} diff --git a/cmd/minikube/cmd/config/set.go b/cmd/minikube/cmd/config/set.go new file mode 100644 index 000000000000..7e5a8e2ae582 --- /dev/null +++ b/cmd/minikube/cmd/config/set.go @@ -0,0 +1,75 @@ +/* +Copyright 2016 The Kubernetes Authors 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://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 config + +import ( + "fmt" + "github.com/spf13/cobra" + "os" +) + +var configSetCmd = &cobra.Command{ + Use: "set PROPERTY_NAME PROPERTY_VALUE", + Short: "Sets an individual value in a minikube config file", + Long: `Sets the PROPERTY_NAME config value to PROPERTY_VALUE + These values can be overwritten by flags or environment variables at runtime.`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) != 2 { + fmt.Fprintln(os.Stderr, "usage: minikube config set PROPERTY_NAME PROPERTY_VALUE") + os.Exit(1) + } + err := set(args[0], args[1]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + }, +} + +func init() { + ConfigCmd.AddCommand(configSetCmd) +} + +func set(name string, value string) error { + s, err := findSetting(name) + if err != nil { + return err + } + // Validate the new value + err = run(name, value, s.validations) + if err != nil { + return err + } + + // Set the value + config := ReadConfig() + err = s.set(config, name, value) + if err != nil { + return err + } + + // Run any callbacks for this property + err = run(name, value, s.callbacks) + if err != nil { + return err + } + + // Write the value + WriteConfig(config) + + return nil +} diff --git a/cmd/minikube/cmd/config/set_test.go b/cmd/minikube/cmd/config/set_test.go new file mode 100644 index 000000000000..a2c35ecc59e7 --- /dev/null +++ b/cmd/minikube/cmd/config/set_test.go @@ -0,0 +1,26 @@ +/* +Copyright 2016 The Kubernetes Authors 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://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 config + +import "testing" + +func TestNotFound(t *testing.T) { + err := set("nonexistant", "10") + if err == nil { + t.Fatalf("Set did not return error for unknown property") + } +} diff --git a/cmd/minikube/cmd/config/unset.go b/cmd/minikube/cmd/config/unset.go new file mode 100644 index 000000000000..a4dd74541e54 --- /dev/null +++ b/cmd/minikube/cmd/config/unset.go @@ -0,0 +1,47 @@ +/* +Copyright 2016 The Kubernetes Authors 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://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 config + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +var configUnsetCmd = &cobra.Command{ + Use: "unset PROPERTY_NAME", + Short: "unsets an individual value in a minikube config file", + Long: "unsets PROPERTY_NAME from the minikube config file. Can be overwritten by flags or environmental variables", + Run: func(cmd *cobra.Command, args []string) { + if len(args) != 1 { + fmt.Fprintf(os.Stdout, "usage: minikube config unset PROPERTY_NAME") + os.Exit(1) + } + unset(args[0]) + }, +} + +func init() { + ConfigCmd.AddCommand(configUnsetCmd) +} + +func unset(name string) { + m := ReadConfig() + delete(m, name) + WriteConfig(m) +} diff --git a/cmd/minikube/cmd/config/util.go b/cmd/minikube/cmd/config/util.go new file mode 100644 index 000000000000..4728abaa71b2 --- /dev/null +++ b/cmd/minikube/cmd/config/util.go @@ -0,0 +1,72 @@ +/* +Copyright 2016 The Kubernetes Authors 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://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 config + +import ( + "fmt" + "strconv" +) + +// Runs all the validation or callback functions and collects errors +func run(name string, value string, fns []setFn) error { + var errors []error + for _, fn := range fns { + err := fn(name, value) + if err != nil { + errors = append(errors, err) + } + } + if len(errors) > 0 { + return fmt.Errorf("%v", errors) + } else { + return nil + } +} + +func findSetting(name string) (Setting, error) { + for _, s := range settings { + if name == s.name { + return s, nil + } + } + return Setting{}, fmt.Errorf("Property name %s not found", name) +} + +// Set Functions + +func SetString(m MinikubeConfig, name string, val string) error { + m[name] = val + return nil +} + +func SetInt(m MinikubeConfig, name string, val string) error { + i, err := strconv.Atoi(val) + if err != nil { + return err + } + m[name] = i + return nil +} + +func SetBool(m MinikubeConfig, name string, val string) error { + b, err := strconv.ParseBool(val) + if err != nil { + return err + } + m[name] = b + return nil +} diff --git a/cmd/minikube/cmd/config/util_test.go b/cmd/minikube/cmd/config/util_test.go new file mode 100644 index 000000000000..e85142a223cc --- /dev/null +++ b/cmd/minikube/cmd/config/util_test.go @@ -0,0 +1,77 @@ +/* +Copyright 2016 The Kubernetes Authors 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://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 config + +import "testing" + +var minikubeConfig = MinikubeConfig{ + "vm-driver": "kvm", + "cpus": 12, + "show-libmachine-logs": true, +} + +func TestFindSettingNotFound(t *testing.T) { + s, err := findSetting("nonexistant") + if err == nil { + t.Fatalf("Shouldn't have found setting, but did. [%+v]", s) + } +} + +func TestFindSetting(t *testing.T) { + s, err := findSetting("vm-driver") + if err != nil { + t.Fatalf("Couldn't find setting, vm-driver: %s", err) + } + if s.name != "vm-driver" { + t.Fatalf("Found wrong setting, expected vm-driver, got %s", s.name) + } +} + +func TestSetString(t *testing.T) { + err := SetString(minikubeConfig, "vm-driver", "virtualbox") + if err != nil { + t.Fatalf("Couldnt set string: %s", err) + } +} + +func TestSetInt(t *testing.T) { + err := SetInt(minikubeConfig, "cpus", "22") + if err != nil { + t.Fatalf("Couldn't set int in config: %s", err) + } + val, ok := minikubeConfig["cpus"].(int) + if !ok { + t.Fatalf("Type not set to int") + } + if val != 22 { + t.Fatalf("SetInt set wrong value") + } +} + +func TestSetBool(t *testing.T) { + err := SetBool(minikubeConfig, "show-libmachine-logs", "true") + if err != nil { + t.Fatalf("Couldn't set bool in config: %s", err) + } + val, ok := minikubeConfig["show-libmachine-logs"].(bool) + if !ok { + t.Fatalf("Type not set to bool") + } + if !val { + t.Fatalf("SetBool set wrong value") + } +} diff --git a/cmd/minikube/cmd/config/validations.go b/cmd/minikube/cmd/config/validations.go new file mode 100644 index 000000000000..ca64a94698de --- /dev/null +++ b/cmd/minikube/cmd/config/validations.go @@ -0,0 +1,76 @@ +/* +Copyright 2016 The Kubernetes Authors 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://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 config + +import ( + "fmt" + "net" + "os" + "strconv" + + units "github.com/docker/go-units" + "k8s.io/minikube/pkg/minikube/constants" +) + +func IsValidDriver(string, driver string) error { + for _, d := range constants.SupportedVMDrivers { + if driver == d { + return nil + } + } + return fmt.Errorf("Driver %s is not supported", driver) +} + +func RequiresRestartMsg(string, string) error { + fmt.Fprintln(os.Stdout, "These changes will take effect upon a restart") + return nil +} + +func IsValidDiskSize(name string, disksize string) error { + _, err := units.FromHumanSize(disksize) + if err != nil { + return fmt.Errorf("Not valid disk size: %v", err) + } + return nil +} + +func IsPositive(name string, val string) error { + i, err := strconv.Atoi(val) + if err != nil { + return fmt.Errorf("%s:%v", name, err) + } + if i <= 0 { + return fmt.Errorf("%s must be > 0", name) + } + return nil +} + +func IsValidCIDR(name string, cidr string) error { + _, _, err := net.ParseCIDR(cidr) + if err != nil { + return fmt.Errorf("Error parsing CIDR: %v", err) + } + return nil +} + +func IsValidPath(name string, path string) error { + _, err := os.Stat(path) + if err != nil { + return fmt.Errorf("%s path is not valid: %v", name, err) + } + return nil +} diff --git a/cmd/minikube/cmd/config/validations_test.go b/cmd/minikube/cmd/config/validations_test.go new file mode 100644 index 000000000000..da5f12444c35 --- /dev/null +++ b/cmd/minikube/cmd/config/validations_test.go @@ -0,0 +1,96 @@ +/* +Copyright 2016 The Kubernetes Authors 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://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 config + +import "testing" + +type validationTest struct { + value string + shouldErr bool +} + +func runValidations(t *testing.T, tests []validationTest, name string, f func(string, string) error) { + for _, tt := range tests { + err := f(name, tt.value) + if err != nil && !tt.shouldErr { + t.Errorf("%s: %v", tt.value, err) + } + if err == nil && tt.shouldErr { + t.Errorf("%s: %v", tt.value, err) + } + } +} + +func TestDriver(t *testing.T) { + + var tests = []validationTest{ + { + value: "vkasdhfasjdf", + shouldErr: true, + }, + { + value: "", + shouldErr: true, + }, + } + + runValidations(t, tests, "vm-driver", IsValidDriver) + +} + +func TestValidCIDR(t *testing.T) { + var tests = []validationTest{ + { + value: "0.0.0.0/0", + shouldErr: false, + }, + { + value: "1.1.1.1/32", + shouldErr: false, + }, + { + value: "192.168.0.0/16", + shouldErr: false, + }, + { + value: "255.255.255.255/1", + shouldErr: false, + }, + { + value: "8.8.8.8/33", + shouldErr: true, + }, + { + value: "12.1", + shouldErr: true, + }, + { + value: "1", + shouldErr: true, + }, + { + value: "a string!", + shouldErr: true, + }, + { + value: "192.168.1.1/8/", + shouldErr: true, + }, + } + + runValidations(t, tests, "cidr", IsValidCIDR) +} diff --git a/cmd/minikube/cmd/root.go b/cmd/minikube/cmd/root.go index 827010bb6f65..d973fbcc0d76 100644 --- a/cmd/minikube/cmd/root.go +++ b/cmd/minikube/cmd/root.go @@ -26,6 +26,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" + configCmd "k8s.io/minikube/cmd/minikube/cmd/config" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/notify" @@ -108,6 +109,7 @@ func setFlagsUsingViper() { func init() { RootCmd.PersistentFlags().Bool(showLibmachineLogs, false, "Whether or not to show logs from libmachine.") + RootCmd.AddCommand(configCmd.ConfigCmd) pflag.CommandLine.AddGoFlagSet(goflag.CommandLine) viper.BindPFlags(RootCmd.PersistentFlags()) cobra.OnInitialize(initConfig) @@ -115,9 +117,9 @@ func init() { // initConfig reads in config file and ENV variables if set. func initConfig() { - configPath := constants.MakeMiniPath("config") - viper.SetConfigName("config") - viper.AddConfigPath(configPath) + configPath := constants.ConfigFile + viper.SetConfigFile(configPath) + viper.SetConfigType("json") err := viper.ReadInConfig() if err != nil { glog.Warningf("Error reading config file at %s: %s", configPath, err) diff --git a/cmd/minikube/cmd/root_test.go b/cmd/minikube/cmd/root_test.go index ea9d612775d5..554da0a0b048 100644 --- a/cmd/minikube/cmd/root_test.go +++ b/cmd/minikube/cmd/root_test.go @@ -29,11 +29,11 @@ import ( "k8s.io/minikube/pkg/minikube/tests" ) -var yamlExampleConfig = []byte(`v: 999 -alsologtostderr: true -log_dir: "/etc/hosts" -log-flush-frequency: "3s" -`) +var jsonExampleConfig = []byte(`{ + "v": "100", + "alsologtostderr": "true", + "log_dir": "/etc/hosts", +}`) type configTest struct { Name string @@ -50,7 +50,7 @@ var configTests = []configTest{ }, { Name: "v", - ConfigValue: "999", + ConfigValue: `{ "v":"999" }`, ExpectedValue: "999", }, { @@ -72,7 +72,7 @@ var configTests = []configTest{ { Name: "v", FlagValue: "3", - ConfigValue: "222", + ConfigValue: `{ "v": "222" }`, EnvValue: "888", ExpectedValue: "3", }, @@ -80,15 +80,9 @@ var configTests = []configTest{ { Name: "v", EnvValue: "2", - ConfigValue: "999", + ConfigValue: `{ "v": "999" }`, ExpectedValue: "2", }, - // Config should not override flags not on whitelist - { - Name: "log-flush-frequency", - ConfigValue: "6s", - ExpectedValue: "5s", - }, // Env should not override flags not on whitelist { Name: "log_backtrace_at", @@ -118,17 +112,17 @@ func TestPreRunDirectories(t *testing.T) { } } -func initTestConfig(config string) { - viper.SetConfigType("yml") +func initTestConfig(config string) error { + viper.SetConfigType("json") r := bytes.NewReader([]byte(config)) - viper.ReadConfig(r) + return viper.ReadConfig(r) } func TestViperConfig(t *testing.T) { defer viper.Reset() - initTestConfig("v: 999") - if viper.GetString("v") != "999" { - t.Fatalf("Viper did not read test config file") + err := initTestConfig(`{ "v": "999" }`) + if viper.GetString("v") != "999" || err != nil { + t.Fatalf("Viper did not read test config file: %v", err) } } @@ -136,7 +130,7 @@ func getEnvVarName(name string) string { return constants.MinikubeEnvPrefix + "_" + strings.ToUpper(name) } -func setValues(tt configTest) { +func setValues(t *testing.T, tt configTest) { if tt.FlagValue != "" { pflag.Set(tt.Name, tt.FlagValue) } @@ -144,7 +138,10 @@ func setValues(tt configTest) { os.Setenv(getEnvVarName(tt.Name), tt.EnvValue) } if tt.ConfigValue != "" { - initTestConfig(tt.Name + ": " + tt.ConfigValue) + err := initTestConfig(tt.ConfigValue) + if err != nil { + t.Fatalf("Config %s not read correctly: %v", tt.ConfigValue, err) + } } } @@ -160,7 +157,7 @@ func unsetValues(tt configTest) { func TestViperAndFlags(t *testing.T) { for _, tt := range configTests { - setValues(tt) + setValues(t, tt) setupViper() var actual = pflag.Lookup(tt.Name).Value.String() if actual != tt.ExpectedValue { diff --git a/docs/minikube.md b/docs/minikube.md index 64ab797560a3..af37f7277e36 100644 --- a/docs/minikube.md +++ b/docs/minikube.md @@ -22,6 +22,7 @@ Minikube is a CLI tool that provisions and manages single-node Kubernetes cluste ``` ### SEE ALSO +* [minikube config](minikube_config.md) - Modify minikube config * [minikube dashboard](minikube_dashboard.md) - Opens/displays the kubernetes dashboard URL for your local cluster * [minikube delete](minikube_delete.md) - Deletes a local kubernetes cluster. * [minikube docker-env](minikube_docker-env.md) - sets up docker env variables; similar to '$(docker-machine env)' diff --git a/docs/minikube_config.md b/docs/minikube_config.md new file mode 100644 index 000000000000..7609986495f5 --- /dev/null +++ b/docs/minikube_config.md @@ -0,0 +1,33 @@ +## minikube config + +Modify minikube config + +### Synopsis + + +config modifies minikube config files using subcommands like "minikube config set vm-driver kvm" + +``` +minikube config SUBCOMMAND [flags] +``` + +### Options inherited from parent commands + +``` + --alsologtostderr[=false]: log to standard error as well as files + --log-flush-frequency=5s: Maximum number of seconds between log flushes + --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace + --log_dir="": If non-empty, write log files in this directory + --logtostderr[=false]: log to standard error instead of files + --show-libmachine-logs[=false]: Whether or not to show logs from libmachine. + --stderrthreshold=2: logs at or above this threshold go to stderr + --v=0: log level for V logs + --vmodule=: comma-separated list of pattern=N settings for file-filtered logging +``` + +### SEE ALSO +* [minikube](minikube.md) - Minikube is a tool for managing local Kubernetes clusters. +* [minikube config get](minikube_config_get.md) - Gets the value of PROPERTY_NAME from the minikube config file +* [minikube config set](minikube_config_set.md) - Sets an individual value in a minikube config file +* [minikube config unset](minikube_config_unset.md) - unsets an individual value in a minikube config file + diff --git a/docs/minikube_config_get.md b/docs/minikube_config_get.md new file mode 100644 index 000000000000..9ea9d1f484c9 --- /dev/null +++ b/docs/minikube_config_get.md @@ -0,0 +1,30 @@ +## minikube config get + +Gets the value of PROPERTY_NAME from the minikube config file + +### Synopsis + + +Returns the value of PROPERTY_NAME from the minikube config file. Can be overwritten at runtime by flags or environmental variables. + +``` +minikube config get PROPERTY_NAME +``` + +### Options inherited from parent commands + +``` + --alsologtostderr[=false]: log to standard error as well as files + --log-flush-frequency=5s: Maximum number of seconds between log flushes + --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace + --log_dir="": If non-empty, write log files in this directory + --logtostderr[=false]: log to standard error instead of files + --show-libmachine-logs[=false]: Whether or not to show logs from libmachine. + --stderrthreshold=2: logs at or above this threshold go to stderr + --v=0: log level for V logs + --vmodule=: comma-separated list of pattern=N settings for file-filtered logging +``` + +### SEE ALSO +* [minikube config](minikube_config.md) - Modify minikube config + diff --git a/docs/minikube_config_set.md b/docs/minikube_config_set.md new file mode 100644 index 000000000000..d52d0ea19e62 --- /dev/null +++ b/docs/minikube_config_set.md @@ -0,0 +1,31 @@ +## minikube config set + +Sets an individual value in a minikube config file + +### Synopsis + + +Sets the PROPERTY_NAME config value to PROPERTY_VALUE + These values can be overwritten by flags or environment variables at runtime. + +``` +minikube config set PROPERTY_NAME PROPERTY_VALUE +``` + +### Options inherited from parent commands + +``` + --alsologtostderr[=false]: log to standard error as well as files + --log-flush-frequency=5s: Maximum number of seconds between log flushes + --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace + --log_dir="": If non-empty, write log files in this directory + --logtostderr[=false]: log to standard error instead of files + --show-libmachine-logs[=false]: Whether or not to show logs from libmachine. + --stderrthreshold=2: logs at or above this threshold go to stderr + --v=0: log level for V logs + --vmodule=: comma-separated list of pattern=N settings for file-filtered logging +``` + +### SEE ALSO +* [minikube config](minikube_config.md) - Modify minikube config + diff --git a/docs/minikube_config_unset.md b/docs/minikube_config_unset.md new file mode 100644 index 000000000000..1399a1ef6c08 --- /dev/null +++ b/docs/minikube_config_unset.md @@ -0,0 +1,30 @@ +## minikube config unset + +unsets an individual value in a minikube config file + +### Synopsis + + +unsets PROPERTY_NAME from the minikube config file. Can be overwritten by flags or environmental variables + +``` +minikube config unset PROPERTY_NAME +``` + +### Options inherited from parent commands + +``` + --alsologtostderr[=false]: log to standard error as well as files + --log-flush-frequency=5s: Maximum number of seconds between log flushes + --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace + --log_dir="": If non-empty, write log files in this directory + --logtostderr[=false]: log to standard error instead of files + --show-libmachine-logs[=false]: Whether or not to show logs from libmachine. + --stderrthreshold=2: logs at or above this threshold go to stderr + --v=0: log level for V logs + --vmodule=: comma-separated list of pattern=N settings for file-filtered logging +``` + +### SEE ALSO +* [minikube config](minikube_config.md) - Modify minikube config + diff --git a/pkg/minikube/constants/constants.go b/pkg/minikube/constants/constants.go index 8f6de995fb22..36579326d843 100644 --- a/pkg/minikube/constants/constants.go +++ b/pkg/minikube/constants/constants.go @@ -72,6 +72,7 @@ const ( ) var ConfigFilePath = MakeMiniPath("config") +var ConfigFile = MakeMiniPath("config", "config.json") var LocalkubeDownloadURLPrefix = "https://storage.googleapis.com/minikube/k8sReleases/" var LocalkubeLinuxFilename = "localkube-linux-amd64" diff --git a/test/integration/commands_test.go b/test/integration/commands_test.go new file mode 100644 index 000000000000..516443a330e7 --- /dev/null +++ b/test/integration/commands_test.go @@ -0,0 +1,50 @@ +// +build integration + +/* +Copyright 2016 The Kubernetes Authors 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://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 integration + +import ( + "testing" + + "k8s.io/minikube/test/integration/util" +) + +func TestConfigCommand(t *testing.T) { + runner := util.MinikubeRunner{ + Args: *args, + BinaryPath: *binaryPath, + T: t} + runner.RunCommand("config set show-libmachine-logs true", false) + get := runner.RunCommand("config get show-libmachine-logs", false) + if get != "true" { + t.Fatalf("Config command returned invalid valid: %s", get) + } +} + +func TestConfigUnset(t *testing.T) { + runner := util.MinikubeRunner{ + Args: *args, + BinaryPath: *binaryPath, + T: t} + runner.RunCommand("config set disk-size 20g", false) + runner.RunCommand("config unset disk-size", false) + get := runner.RunCommand("config get disk-size", false) + if get == "20g" { + t.Fatalf("Config unset command did not unset properly") + } +}