From 6add1993c95c741f3745b8763382f96325f83677 Mon Sep 17 00:00:00 2001 From: Federico Simoncelli Date: Wed, 3 Sep 2014 21:12:20 +0000 Subject: [PATCH] Support configurations for cloudproviders Cloud providers may need specific configurations to run properly (e.g. authentication parameters, uri, etc.). This patch adds the simplest implementation for passing configurations to cloudproviders: a new apiserver -cloud_config flag to specify the path to an arbitrary configuration file. Signed-off-by: Federico Simoncelli --- cmd/apiserver/apiserver.go | 45 +++++++++++++++++++++------- pkg/cloudprovider/gce/gce.go | 3 +- pkg/cloudprovider/plugins.go | 14 ++++++--- pkg/cloudprovider/vagrant/vagrant.go | 3 +- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/cmd/apiserver/apiserver.go b/cmd/apiserver/apiserver.go index 32856352052..fd66438f8a7 100644 --- a/cmd/apiserver/apiserver.go +++ b/cmd/apiserver/apiserver.go @@ -22,6 +22,7 @@ import ( "flag" "net" "net/http" + "os" "strconv" "time" @@ -39,6 +40,7 @@ var ( address = flag.String("address", "127.0.0.1", "The address on the local server to listen to. Default 127.0.0.1") apiPrefix = flag.String("api_prefix", "/api/v1beta1", "The prefix for API requests on the server. Default '/api/v1beta1'") cloudProvider = flag.String("cloud_provider", "", "The provider for cloud services. Empty string for no provider.") + cloudConfigFile = flag.String("cloud_config", "", "The path to the cloud provider configuration file. Empty string for no configuration file.") minionRegexp = flag.String("minion_regexp", "", "If non empty, and -cloud_provider is specified, a regular expression for matching minion VMs") minionPort = flag.Uint("minion_port", 10250, "The port at which kubelet will be listening on the minions.") healthCheckMinions = flag.Bool("health_check_minions", true, "If true, health check minions and filter unhealthy ones. [default true]") @@ -63,6 +65,37 @@ func verifyMinionFlags() { } } +func initCloudProvider(name string, configFilePath string) cloudprovider.Interface { + var config *os.File + + if name == "" { + glog.Info("No cloud provider specified.") + return nil + } + + if configFilePath != "" { + var err error + + config, err = os.Open(configFilePath) + if err != nil { + glog.Fatalf("Couldn't open cloud provider configuration %s: %#v", + configFilePath, err) + } + + defer config.Close() + } + + cloud, err := cloudprovider.GetCloudProvider(name, config) + if err != nil { + glog.Fatalf("Couldn't init cloud provider %q: %#v", name, err) + } + if cloud == nil { + glog.Fatalf("Unknown cloud provider: %s", name) + } + + return cloud +} + func main() { flag.Parse() util.InitLogs() @@ -75,17 +108,7 @@ func main() { glog.Fatalf("-etcd_servers flag is required.") } - cloud, err := cloudprovider.GetCloudProvider(*cloudProvider) - if err != nil { - glog.Fatalf("Couldn't init cloud provider %q: %#v", *cloudProvider, err) - } - if cloud == nil { - if len(*cloudProvider) > 0 { - glog.Fatalf("Unknown cloud provider: %s", *cloudProvider) - } else { - glog.Info("No cloud provider specified.") - } - } + cloud := initCloudProvider(*cloudProvider, *cloudConfigFile) podInfoGetter := &client.HTTPPodInfoGetter{ Client: http.DefaultClient, diff --git a/pkg/cloudprovider/gce/gce.go b/pkg/cloudprovider/gce/gce.go index adb8c8d9756..3c503e47c58 100644 --- a/pkg/cloudprovider/gce/gce.go +++ b/pkg/cloudprovider/gce/gce.go @@ -18,6 +18,7 @@ package gce_cloud import ( "fmt" + "io" "io/ioutil" "net" "net/http" @@ -40,7 +41,7 @@ type GCECloud struct { } func init() { - cloudprovider.RegisterCloudProvider("gce", func() (cloudprovider.Interface, error) { return newGCECloud() }) + cloudprovider.RegisterCloudProvider("gce", func(config io.Reader) (cloudprovider.Interface, error) { return newGCECloud() }) } func getProjectAndZone() (string, string, error) { diff --git a/pkg/cloudprovider/plugins.go b/pkg/cloudprovider/plugins.go index cac60f630eb..b15c0be0c88 100644 --- a/pkg/cloudprovider/plugins.go +++ b/pkg/cloudprovider/plugins.go @@ -17,13 +17,17 @@ limitations under the License. package cloudprovider import ( + "io" "sync" "github.com/golang/glog" ) // Factory is a function that returns a cloudprovider.Interface. -type Factory func() (Interface, error) +// The config parameter provides an io.Reader handler to the factory in +// order to load specific configurations. If no configuration is provided +// the parameter is nil. +type Factory func(config io.Reader) (Interface, error) // All registered cloud providers. var providersMutex sync.Mutex @@ -44,13 +48,15 @@ func RegisterCloudProvider(name string, cloud Factory) { // GetCloudProvider creates an instance of the named cloud provider, or nil if // the name is not known. The error return is only used if the named provider -// was known but failed to initialize. -func GetCloudProvider(name string) (Interface, error) { +// was known but failed to initialize. The config parameter specifies the +// io.Reader handler of the configuration file for the cloud provider, or nil +// for no configuation. +func GetCloudProvider(name string, config io.Reader) (Interface, error) { providersMutex.Lock() defer providersMutex.Unlock() f, found := providers[name] if !found { return nil, nil } - return f() + return f(config) } diff --git a/pkg/cloudprovider/vagrant/vagrant.go b/pkg/cloudprovider/vagrant/vagrant.go index 8202ce9651e..f0a0295fe45 100644 --- a/pkg/cloudprovider/vagrant/vagrant.go +++ b/pkg/cloudprovider/vagrant/vagrant.go @@ -20,6 +20,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "io/ioutil" "net" "net/http" @@ -38,7 +39,7 @@ type VagrantCloud struct { } func init() { - cloudprovider.RegisterCloudProvider("vagrant", func() (cloudprovider.Interface, error) { return newVagrantCloud() }) + cloudprovider.RegisterCloudProvider("vagrant", func(config io.Reader) (cloudprovider.Interface, error) { return newVagrantCloud() }) } // SaltToken is an authorization token required by Salt REST API.