From 1057edfa8fcf034f17e78b8ac304ea1a193fc2d2 Mon Sep 17 00:00:00 2001 From: Yongkun Anfernee Gui Date: Thu, 8 Feb 2018 16:58:04 -0800 Subject: [PATCH] Add registry to discover driver in different platforms Different platform has differnet list of supported drivers. The registry contains the correct list of drivers that are supported. In future we could add commands like `minikube list-drivers` --- pkg/minikube/cluster/cluster.go | 57 ++++++------ pkg/minikube/cluster/cluster_darwin.go | 12 ++- pkg/minikube/cluster/cluster_linux.go | 12 ++- pkg/minikube/cluster/cluster_windows.go | 7 +- pkg/minikube/cluster/registry.go | 112 ++++++++++++++++++++++++ pkg/minikube/cluster/registry_test.go | 68 ++++++++++++++ 6 files changed, 233 insertions(+), 35 deletions(-) create mode 100644 pkg/minikube/cluster/registry.go create mode 100644 pkg/minikube/cluster/registry_test.go diff --git a/pkg/minikube/cluster/cluster.go b/pkg/minikube/cluster/cluster.go index 726402ae4..b8eb40095 100644 --- a/pkg/minikube/cluster/cluster.go +++ b/pkg/minikube/cluster/cluster.go @@ -30,7 +30,6 @@ import ( "github.com/docker/machine/drivers/virtualbox" "github.com/docker/machine/libmachine" - "github.com/docker/machine/libmachine/drivers" "github.com/docker/machine/libmachine/engine" "github.com/docker/machine/libmachine/host" "github.com/docker/machine/libmachine/mcnerror" @@ -58,6 +57,8 @@ func init() { flag.Set("logtostderr", "false") // Setting the default client to native gives much better performance. ssh.SetDefaultClient(ssh.Native) + + registry.Register("virtualbox", createVirtualboxHost) } // StartHost starts a host VM. @@ -180,7 +181,7 @@ func engineOptions(config MachineConfig) *engine.Options { return &o } -func createVirtualboxHost(config MachineConfig) drivers.Driver { +func createVirtualboxHost(config MachineConfig) RawDriver { d := virtualbox.NewDriver(cfg.GetMachineName(), constants.GetMinipath()) d.Boot2DockerURL = config.Downloader.GetISOFileURI(config.MinikubeISO) d.Memory = config.Memory @@ -193,20 +194,8 @@ func createVirtualboxHost(config MachineConfig) drivers.Driver { return d } -func createHost(api libmachine.API, config MachineConfig) (*host.Host, error) { - var driver interface{} - - if config.VMDriver != "none" { - if err := config.Downloader.CacheMinikubeISOFromURL(config.MinikubeISO); err != nil { - return nil, errors.Wrap(err, "Error attempting to cache minikube ISO from URL") - } - } - +func preCreateHost(config *MachineConfig) error { switch config.VMDriver { - case "virtualbox": - driver = createVirtualboxHost(config) - case "vmwarefusion": - driver = createVMwareFusionHost(config) case "kvm": if viper.GetBool(cfg.ShowDriverDeprecationNotification) { fmt.Fprintln(os.Stderr, `WARNING: The kvm driver is now deprecated and support for it will be removed in a future release. @@ -214,9 +203,6 @@ func createHost(api libmachine.API, config MachineConfig) (*host.Host, error) { See https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#kvm2-driver for more information. To disable this message, run [minikube config set WantShowDriverDeprecationNotification false]`) } - driver = createKVMHost(config) - case "kvm2": - driver = createKVM2Host(config) case "xhyve": if viper.GetBool(cfg.ShowDriverDeprecationNotification) { fmt.Fprintln(os.Stderr, `WARNING: The xhyve driver is now deprecated and support for it will be removed in a future release. @@ -224,17 +210,34 @@ Please consider switching to the hyperkit driver, which is intended to replace t See https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#hyperkit-driver for more information. To disable this message, run [minikube config set WantShowDriverDeprecationNotification false]`) } - driver = createXhyveHost(config) - case "hyperv": - driver = createHypervHost(config) - case "none": - driver = createNoneHost(config) - case "hyperkit": - driver = createHyperkitHost(config) - default: - glog.Exitf("Unsupported driver: %s\n", config.VMDriver) } + return nil +} + +func createHost(api libmachine.API, config MachineConfig) (*host.Host, error) { + err := preCreateHost(&config) + if err != nil { + return nil, err + } + + driverFunc, err := registry.Driver(config.VMDriver) + if err != nil { + if err == ErrDriverNotFound { + glog.Exitf("Unsupported driver: %s\n", config.VMDriver) + } else { + glog.Exit(err.Error()) + } + } + + if config.VMDriver != "none" { + if err := config.Downloader.CacheMinikubeISOFromURL(config.MinikubeISO); err != nil { + return nil, errors.Wrap(err, "Error attempting to cache minikube ISO from URL") + } + } + + driver := driverFunc(config) + data, err := json.Marshal(driver) if err != nil { return nil, errors.Wrap(err, "Error marshalling json") diff --git a/pkg/minikube/cluster/cluster_darwin.go b/pkg/minikube/cluster/cluster_darwin.go index 336661731..9dbd4f393 100644 --- a/pkg/minikube/cluster/cluster_darwin.go +++ b/pkg/minikube/cluster/cluster_darwin.go @@ -27,7 +27,13 @@ import ( "k8s.io/minikube/pkg/minikube/constants" ) -func createVMwareFusionHost(config MachineConfig) drivers.Driver { +func init() { + registry.Register("vmwarefusion", createVMwareFusionHost) + registry.Register("hyperkit", createHyperkitHost) + registry.Register("xhyve", createXhyveHost) +} + +func createVMwareFusionHost(config MachineConfig) RawDriver { d := vmwarefusion.NewDriver(cfg.GetMachineName(), constants.GetMinipath()).(*vmwarefusion.Driver) d.Boot2DockerURL = config.Downloader.GetISOFileURI(config.MinikubeISO) d.Memory = config.Memory @@ -59,7 +65,7 @@ type xhyveDriver struct { RawDisk bool } -func createHyperkitHost(config MachineConfig) *hyperkit.Driver { +func createHyperkitHost(config MachineConfig) RawDriver { return &hyperkit.Driver{ BaseDriver: &drivers.BaseDriver{ MachineName: cfg.GetMachineName(), @@ -77,7 +83,7 @@ func createHyperkitHost(config MachineConfig) *hyperkit.Driver { } } -func createXhyveHost(config MachineConfig) *xhyveDriver { +func createXhyveHost(config MachineConfig) RawDriver { useVirtio9p := !config.DisableDriverMounts return &xhyveDriver{ BaseDriver: &drivers.BaseDriver{ diff --git a/pkg/minikube/cluster/cluster_linux.go b/pkg/minikube/cluster/cluster_linux.go index fb21521ce..2023c71fe 100644 --- a/pkg/minikube/cluster/cluster_linux.go +++ b/pkg/minikube/cluster/cluster_linux.go @@ -27,6 +27,12 @@ import ( "k8s.io/minikube/pkg/minikube/constants" ) +func init() { + registry.Register("kvm", createKVMHost) + registry.Register("kvm2", createKVM2Host) + registry.Register("none", createNoneHost) +} + type kvmDriver struct { *drivers.BaseDriver @@ -42,7 +48,7 @@ type kvmDriver struct { IOMode string } -func createKVMHost(config MachineConfig) *kvmDriver { +func createKVMHost(config MachineConfig) RawDriver { return &kvmDriver{ BaseDriver: &drivers.BaseDriver{ MachineName: cfg.GetMachineName(), @@ -62,7 +68,7 @@ func createKVMHost(config MachineConfig) *kvmDriver { } } -func createKVM2Host(config MachineConfig) *kvmDriver { +func createKVM2Host(config MachineConfig) RawDriver { return &kvmDriver{ BaseDriver: &drivers.BaseDriver{ MachineName: cfg.GetMachineName(), @@ -90,7 +96,7 @@ func detectVBoxManageCmd() string { return cmd } -func createNoneHost(config MachineConfig) *none.Driver { +func createNoneHost(config MachineConfig) RawDriver { return &none.Driver{ BaseDriver: &drivers.BaseDriver{ MachineName: cfg.GetMachineName(), diff --git a/pkg/minikube/cluster/cluster_windows.go b/pkg/minikube/cluster/cluster_windows.go index a6aa37343..df5307fce 100644 --- a/pkg/minikube/cluster/cluster_windows.go +++ b/pkg/minikube/cluster/cluster_windows.go @@ -23,7 +23,6 @@ import ( "path/filepath" "github.com/docker/machine/drivers/hyperv" - "github.com/docker/machine/libmachine/drivers" "github.com/golang/glog" "github.com/pkg/errors" "golang.org/x/sys/windows/registry" @@ -31,7 +30,11 @@ import ( "k8s.io/minikube/pkg/minikube/constants" ) -func createHypervHost(config MachineConfig) drivers.Driver { +func init() { + registry.Register("hyperkit", createHypervHost) +} + +func createHypervHost(config MachineConfig) RawDriver { d := hyperv.NewDriver(cfg.GetMachineName(), constants.GetMinipath()) d.Boot2DockerURL = config.Downloader.GetISOFileURI(config.MinikubeISO) d.VSwitch = config.HypervVirtualSwitch diff --git a/pkg/minikube/cluster/registry.go b/pkg/minikube/cluster/registry.go new file mode 100644 index 000000000..5793901c6 --- /dev/null +++ b/pkg/minikube/cluster/registry.go @@ -0,0 +1,112 @@ +/* +Copyright 2018 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 cluster + +import ( + "sync" + + "github.com/pkg/errors" +) + +var ( + // ErrDriverNameExist is the error returned when trying to register a driver + // which already exists in registry + ErrDriverNameExist = errors.New("registry: duplicated driver name") + + // ErrDriverNotFound is the error returned when driver of a given name does + // not exist in registry + ErrDriverNotFound = errors.New("registry: driver not found") +) + +// DriverFunc creates a Driver from MachineConfig +type DriverFunc func(MachineConfig) RawDriver + +// RawDriver is the configuration of a driver that you can marshal into json bytes +// and pass to libmachine's NewHost method +type RawDriver interface{} + +// Registry contains all the supported driver types on the host +type Registry interface { + // Register a driver in registry + Register(name string, f DriverFunc) error + + // Driver returns the registered driver from a given name + Driver(name string) (DriverFunc, error) + + DriverLister +} + +// DriverLister lists the name of the supported drivers +type DriverLister interface { + // List lists all the driver types + List() []string +} + +type driverRegistry struct { + drivers map[string]DriverFunc + lock sync.Mutex +} + +func createRegistry() *driverRegistry { + return &driverRegistry{ + drivers: make(map[string]DriverFunc), + } +} + +var ( + registry = createRegistry() +) + +func ListDrivers() []string { + return registry.List() +} + +func (r *driverRegistry) Register(name string, f DriverFunc) error { + r.lock.Lock() + defer r.lock.Unlock() + + if _, ok := r.drivers[name]; ok { + return ErrDriverNameExist + } + + r.drivers[name] = f + return nil +} + +func (r *driverRegistry) List() []string { + r.lock.Lock() + defer r.lock.Unlock() + + result := make([]string, 0, len(r.drivers)) + + for name := range r.drivers { + result = append(result, name) + } + + return result +} + +func (r *driverRegistry) Driver(name string) (DriverFunc, error) { + r.lock.Lock() + defer r.lock.Unlock() + + if driver, ok := r.drivers[name]; ok { + return driver, nil + } + + return nil, ErrDriverNotFound +} diff --git a/pkg/minikube/cluster/registry_test.go b/pkg/minikube/cluster/registry_test.go new file mode 100644 index 000000000..d66efd5f7 --- /dev/null +++ b/pkg/minikube/cluster/registry_test.go @@ -0,0 +1,68 @@ +/* +Copyright 2018 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 cluster + +import ( + "sort" + "testing" +) + +func TestRegistry(t *testing.T) { + dummy := func(_ MachineConfig) RawDriver { + return nil + } + + registry := createRegistry() + + err := registry.Register("foo", dummy) + if err != nil { + t.Fatal("expect nil") + } + + err = registry.Register("foo", dummy) + if err != ErrDriverNameExist { + t.Fatal("expect ErrDriverNameExist") + } + + err = registry.Register("bar", dummy) + if err != nil { + t.Fatal("expect nil") + } + + list := registry.List() + if len(list) != 2 { + t.Fatalf("expect len(list) to be %d; got %d", 2, len(list)) + } + + sort.Strings(list) + if list[0] != "bar" || list[1] != "foo" { + t.Fatalf("expect registry.List return %s; got %s", []string{"bar", "foo"}, list) + } + + driver, err := registry.Driver("foo") + if err != nil { + t.Fatal("expect nil") + } + if driver == nil { + t.Fatal("expect registry.Driver(foo) returns registered driver") + } + + driver, err = registry.Driver("foo2") + if err != ErrDriverNotFound { + t.Fatal("expect ErrDriverNotFound") + } +} -- GitLab