diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 54c29b8f56..161924ea78 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -22,12 +22,14 @@ import ( "strings" "github.com/docker/machine/libmachine" + "github.com/docker/machine/libmachine/host" "github.com/golang/glog" "github.com/spf13/cobra" cfg "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/kubeconfig" + "k8s.io/minikube/pkg/util" ) var ( @@ -52,8 +54,12 @@ func runStart(cmd *cobra.Command, args []string) { MinikubeISO: minikubeISO, } - host, err := cluster.StartHost(api, config) - + var host *host.Host + start := func() (err error) { + host, err = cluster.StartHost(api, config) + return err + } + err := util.Retry(3, start) if err != nil { glog.Errorln("Error starting host: ", err) os.Exit(1) diff --git a/pkg/util/utils.go b/pkg/util/utils.go index f888c53e3d..268c92daf3 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -61,3 +61,13 @@ func CanReadFile(path string) bool { return true } + +func Retry(attempts int, callback func() error) (err error) { + for i := 0; i < attempts; i++ { + err = callback() + if err == nil { + return nil + } + } + return err +} diff --git a/pkg/util/utils_test.go b/pkg/util/utils_test.go new file mode 100644 index 0000000000..f32802a0ae --- /dev/null +++ b/pkg/util/utils_test.go @@ -0,0 +1,61 @@ +/* +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 util + +import ( + "fmt" + "testing" +) + +// Returns a function that will return n errors, then return successfully forever. +func errorGenerator(n int) func() error { + errors := 0 + return func() (err error) { + if errors < n { + errors += 1 + return fmt.Errorf("Error!") + } + return nil + } +} + +func TestErrorGenerator(t *testing.T) { + errors := 3 + f := errorGenerator(errors) + for i := 0; i < errors-1; i++ { + if err := f(); err == nil { + t.Fatalf("Error should have been thrown at iteration %v", i) + } + } + if err := f(); err == nil { + t.Fatalf("Error should not have been thrown this call!") + } +} + +func TestRetry(t *testing.T) { + + f := errorGenerator(4) + if err := Retry(5, f); err != nil { + t.Fatalf("Error should not have been raised by retry.") + } + + f = errorGenerator(5) + if err := Retry(4, f); err == nil { + t.Fatalf("Error should have been raised by retry.") + } + +}