mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 22:17:14 +00:00
Merge pull request #980 from thockin/cloudproviders
Make cloud providers into plugins
This commit is contained in:
commit
25b3da718f
@ -75,23 +75,13 @@ func main() {
|
||||
glog.Fatalf("-etcd_servers flag is required.")
|
||||
}
|
||||
|
||||
var cloud cloudprovider.Interface
|
||||
switch *cloudProvider {
|
||||
case "gce":
|
||||
var err error
|
||||
cloud, err = cloudprovider.NewGCECloud()
|
||||
if err != nil {
|
||||
glog.Fatalf("Couldn't connect to GCE cloud: %#v", err)
|
||||
}
|
||||
case "vagrant":
|
||||
var err error
|
||||
cloud, err = cloudprovider.NewVagrantCloud()
|
||||
if err != nil {
|
||||
glog.Fatalf("Couldn't connect to vagrant cloud: %#v", err)
|
||||
}
|
||||
default:
|
||||
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.Infof("Unknown cloud provider: %s", *cloudProvider)
|
||||
glog.Fatalf("Unknown cloud provider: %s", *cloudProvider)
|
||||
} else {
|
||||
glog.Info("No cloud provider specified.")
|
||||
}
|
||||
|
25
cmd/apiserver/plugins.go
Normal file
25
cmd/apiserver/plugins.go
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2014 Google Inc. 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 main
|
||||
|
||||
// This file exists to force the desired plugin implementations to be linked.
|
||||
// This should probably be part of some configuration fed into the build for a
|
||||
// given binary target.
|
||||
import (
|
||||
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/gce"
|
||||
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/vagrant"
|
||||
)
|
@ -14,11 +14,13 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cloudprovider
|
||||
package fake_cloud
|
||||
|
||||
import (
|
||||
"net"
|
||||
"regexp"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
// FakeCloud is a test-double implementation of Interface, TCPLoadBalancer and Instances. It is useful for testing.
|
||||
@ -28,7 +30,7 @@ type FakeCloud struct {
|
||||
Calls []string
|
||||
IP net.IP
|
||||
Machines []string
|
||||
Zone
|
||||
cloudprovider.Zone
|
||||
}
|
||||
|
||||
func (f *FakeCloud) addCall(desc string) {
|
||||
@ -43,18 +45,18 @@ func (f *FakeCloud) ClearCalls() {
|
||||
// TCPLoadBalancer returns a fake implementation of TCPLoadBalancer.
|
||||
//
|
||||
// Actually it just returns f itself.
|
||||
func (f *FakeCloud) TCPLoadBalancer() (TCPLoadBalancer, bool) {
|
||||
func (f *FakeCloud) TCPLoadBalancer() (cloudprovider.TCPLoadBalancer, bool) {
|
||||
return f, true
|
||||
}
|
||||
|
||||
// Instances returns a fake implementation of Instances.
|
||||
//
|
||||
// Actually it just returns f itself.
|
||||
func (f *FakeCloud) Instances() (Instances, bool) {
|
||||
func (f *FakeCloud) Instances() (cloudprovider.Instances, bool) {
|
||||
return f, true
|
||||
}
|
||||
|
||||
func (f *FakeCloud) Zones() (Zones, bool) {
|
||||
func (f *FakeCloud) Zones() (cloudprovider.Zones, bool) {
|
||||
return f, true
|
||||
}
|
||||
|
||||
@ -104,7 +106,7 @@ func (f *FakeCloud) List(filter string) ([]string, error) {
|
||||
return result, f.Err
|
||||
}
|
||||
|
||||
func (f *FakeCloud) GetZone() (Zone, error) {
|
||||
func (f *FakeCloud) GetZone() (cloudprovider.Zone, error) {
|
||||
f.addCall("get-zone")
|
||||
return f.Zone, f.Err
|
||||
}
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cloudprovider
|
||||
package gce_cloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -28,6 +28,7 @@ import (
|
||||
|
||||
"code.google.com/p/goauth2/compute/serviceaccount"
|
||||
compute "code.google.com/p/google-api-go-client/compute/v1"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
// GCECloud is an implementation of Interface, TCPLoadBalancer and Instances for Google Compute Engine.
|
||||
@ -38,6 +39,10 @@ type GCECloud struct {
|
||||
instanceRE string
|
||||
}
|
||||
|
||||
func init() {
|
||||
cloudprovider.RegisterCloudProvider("gce", func() (cloudprovider.Interface, error) { return newGCECloud() })
|
||||
}
|
||||
|
||||
func getProjectAndZone() (string, string, error) {
|
||||
client := http.Client{}
|
||||
url := "http://metadata/computeMetadata/v1/instance/zone"
|
||||
@ -62,8 +67,8 @@ func getProjectAndZone() (string, string, error) {
|
||||
return parts[1], parts[3], nil
|
||||
}
|
||||
|
||||
// NewGCECloud creates a new instance of GCECloud.
|
||||
func NewGCECloud() (*GCECloud, error) {
|
||||
// newGCECloud creates a new instance of GCECloud.
|
||||
func newGCECloud() (*GCECloud, error) {
|
||||
projectID, zone, err := getProjectAndZone()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -84,17 +89,17 @@ func NewGCECloud() (*GCECloud, error) {
|
||||
}
|
||||
|
||||
// TCPLoadBalancer returns an implementation of TCPLoadBalancer for Google Compute Engine.
|
||||
func (gce *GCECloud) TCPLoadBalancer() (TCPLoadBalancer, bool) {
|
||||
func (gce *GCECloud) TCPLoadBalancer() (cloudprovider.TCPLoadBalancer, bool) {
|
||||
return gce, true
|
||||
}
|
||||
|
||||
// Instances returns an implementation of Instances for Google Compute Engine.
|
||||
func (gce *GCECloud) Instances() (Instances, bool) {
|
||||
func (gce *GCECloud) Instances() (cloudprovider.Instances, bool) {
|
||||
return gce, true
|
||||
}
|
||||
|
||||
// Zones returns an implementation of Zones for Google Compute Engine.
|
||||
func (gce *GCECloud) Zones() (Zones, bool) {
|
||||
func (gce *GCECloud) Zones() (cloudprovider.Zones, bool) {
|
||||
return gce, true
|
||||
}
|
||||
|
||||
@ -237,12 +242,12 @@ func (gce *GCECloud) List(filter string) ([]string, error) {
|
||||
return instances, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) GetZone() (Zone, error) {
|
||||
func (gce *GCECloud) GetZone() (cloudprovider.Zone, error) {
|
||||
region, err := getGceRegion(gce.zone)
|
||||
if err != nil {
|
||||
return Zone{}, err
|
||||
return cloudprovider.Zone{}, err
|
||||
}
|
||||
return Zone{
|
||||
return cloudprovider.Zone{
|
||||
FailureDomain: gce.zone,
|
||||
Region: region,
|
||||
}, nil
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cloudprovider
|
||||
package gce_cloud
|
||||
|
||||
import (
|
||||
"testing"
|
56
pkg/cloudprovider/plugins.go
Normal file
56
pkg/cloudprovider/plugins.go
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 2014 Google Inc. 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 cloudprovider
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// Factory is a function that returns a cloudprovider.Interface.
|
||||
type Factory func() (Interface, error)
|
||||
|
||||
// All registered cloud providers.
|
||||
var providersMutex sync.Mutex
|
||||
var providers = make(map[string]Factory)
|
||||
|
||||
// RegisterCloudProvider registers a cloudprovider.Factory by name. This
|
||||
// is expected to happen during app startup.
|
||||
func RegisterCloudProvider(name string, cloud Factory) {
|
||||
providersMutex.Lock()
|
||||
defer providersMutex.Unlock()
|
||||
_, found := providers[name]
|
||||
if found {
|
||||
glog.Fatalf("Cloud provider %q was registered twice", name)
|
||||
}
|
||||
glog.Infof("Registered cloud provider %q", name)
|
||||
providers[name] = cloud
|
||||
}
|
||||
|
||||
// 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) {
|
||||
providersMutex.Lock()
|
||||
defer providersMutex.Unlock()
|
||||
f, found := providers[name]
|
||||
if !found {
|
||||
return nil, nil
|
||||
}
|
||||
return f()
|
||||
}
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cloudprovider
|
||||
package vagrant_cloud
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@ -24,6 +24,8 @@ import (
|
||||
"net/http"
|
||||
neturl "net/url"
|
||||
"sort"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
// VagrantCloud is an implementation of Interface, TCPLoadBalancer and Instances for developer managed Vagrant cluster
|
||||
@ -34,6 +36,10 @@ type VagrantCloud struct {
|
||||
saltAuth string
|
||||
}
|
||||
|
||||
func init() {
|
||||
cloudprovider.RegisterCloudProvider("vagrant", func() (cloudprovider.Interface, error) { return newVagrantCloud() })
|
||||
}
|
||||
|
||||
// SaltToken is an authorization token required by Salt REST API
|
||||
type SaltToken struct {
|
||||
Token string `json:"token"`
|
||||
@ -61,8 +67,8 @@ type SaltMinionsResponse struct {
|
||||
Minions []SaltMinions `json:"return"`
|
||||
}
|
||||
|
||||
// NewVagrantCloud creates a new instance of VagrantCloud configured to talk to the Salt REST API.
|
||||
func NewVagrantCloud() (*VagrantCloud, error) {
|
||||
// newVagrantCloud creates a new instance of VagrantCloud configured to talk to the Salt REST API.
|
||||
func newVagrantCloud() (*VagrantCloud, error) {
|
||||
return &VagrantCloud{
|
||||
saltURL: "http://127.0.0.1:8000",
|
||||
saltUser: "vagrant",
|
||||
@ -72,17 +78,17 @@ func NewVagrantCloud() (*VagrantCloud, error) {
|
||||
}
|
||||
|
||||
// TCPLoadBalancer returns an implementation of TCPLoadBalancer for Vagrant cloud
|
||||
func (v *VagrantCloud) TCPLoadBalancer() (TCPLoadBalancer, bool) {
|
||||
func (v *VagrantCloud) TCPLoadBalancer() (cloudprovider.TCPLoadBalancer, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Instances returns an implementation of Instances for Vagrant cloud
|
||||
func (v *VagrantCloud) Instances() (Instances, bool) {
|
||||
func (v *VagrantCloud) Instances() (cloudprovider.Instances, bool) {
|
||||
return v, true
|
||||
}
|
||||
|
||||
// Zones returns an implementation of Zones for Vagrant cloud
|
||||
func (v *VagrantCloud) Zones() (Zones, bool) {
|
||||
func (v *VagrantCloud) Zones() (cloudprovider.Zones, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cloudprovider
|
||||
package vagrant_cloud
|
||||
|
||||
import (
|
||||
"net/http"
|
@ -20,12 +20,12 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/fake"
|
||||
)
|
||||
|
||||
func TestCloudList(t *testing.T) {
|
||||
instances := []string{"m1", "m2"}
|
||||
fakeCloud := cloudprovider.FakeCloud{
|
||||
fakeCloud := fake_cloud.FakeCloud{
|
||||
Machines: instances,
|
||||
}
|
||||
registry, err := NewCloudRegistry(&fakeCloud, ".*")
|
||||
@ -45,7 +45,7 @@ func TestCloudList(t *testing.T) {
|
||||
|
||||
func TestCloudContains(t *testing.T) {
|
||||
instances := []string{"m1", "m2"}
|
||||
fakeCloud := cloudprovider.FakeCloud{
|
||||
fakeCloud := fake_cloud.FakeCloud{
|
||||
Machines: instances,
|
||||
}
|
||||
registry, err := NewCloudRegistry(&fakeCloud, ".*")
|
||||
@ -74,7 +74,7 @@ func TestCloudContains(t *testing.T) {
|
||||
|
||||
func TestCloudListRegexp(t *testing.T) {
|
||||
instances := []string{"m1", "m2", "n1", "n2"}
|
||||
fakeCloud := cloudprovider.FakeCloud{
|
||||
fakeCloud := fake_cloud.FakeCloud{
|
||||
Machines: instances,
|
||||
}
|
||||
registry, err := NewCloudRegistry(&fakeCloud, "m[0-9]+")
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/fake"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/minion"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
|
||||
@ -228,7 +228,7 @@ func TestGetPod(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetPodCloud(t *testing.T) {
|
||||
fakeCloud := &cloudprovider.FakeCloud{}
|
||||
fakeCloud := &fake_cloud.FakeCloud{}
|
||||
podRegistry := registrytest.NewPodRegistry(nil)
|
||||
podRegistry.Pod = &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
|
||||
storage := RegistryStorage{
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/fake"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/minion"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
|
||||
@ -30,7 +30,7 @@ import (
|
||||
|
||||
func TestServiceRegistryCreate(t *testing.T) {
|
||||
registry := registrytest.NewServiceRegistry()
|
||||
fakeCloud := &cloudprovider.FakeCloud{}
|
||||
fakeCloud := &fake_cloud.FakeCloud{}
|
||||
machines := []string{"foo", "bar", "baz"}
|
||||
storage := NewRegistryStorage(registry, fakeCloud, minion.NewRegistry(machines))
|
||||
svc := &api.Service{
|
||||
@ -136,7 +136,7 @@ func TestServiceStorageValidatesUpdate(t *testing.T) {
|
||||
|
||||
func TestServiceRegistryExternalService(t *testing.T) {
|
||||
registry := registrytest.NewServiceRegistry()
|
||||
fakeCloud := &cloudprovider.FakeCloud{}
|
||||
fakeCloud := &fake_cloud.FakeCloud{}
|
||||
machines := []string{"foo", "bar", "baz"}
|
||||
storage := NewRegistryStorage(registry, fakeCloud, minion.NewRegistry(machines))
|
||||
svc := &api.Service{
|
||||
@ -160,7 +160,7 @@ func TestServiceRegistryExternalService(t *testing.T) {
|
||||
|
||||
func TestServiceRegistryExternalServiceError(t *testing.T) {
|
||||
registry := registrytest.NewServiceRegistry()
|
||||
fakeCloud := &cloudprovider.FakeCloud{
|
||||
fakeCloud := &fake_cloud.FakeCloud{
|
||||
Err: fmt.Errorf("test error"),
|
||||
}
|
||||
machines := []string{"foo", "bar", "baz"}
|
||||
@ -182,7 +182,7 @@ func TestServiceRegistryExternalServiceError(t *testing.T) {
|
||||
|
||||
func TestServiceRegistryDelete(t *testing.T) {
|
||||
registry := registrytest.NewServiceRegistry()
|
||||
fakeCloud := &cloudprovider.FakeCloud{}
|
||||
fakeCloud := &fake_cloud.FakeCloud{}
|
||||
machines := []string{"foo", "bar", "baz"}
|
||||
storage := NewRegistryStorage(registry, fakeCloud, minion.NewRegistry(machines))
|
||||
svc := api.Service{
|
||||
@ -202,7 +202,7 @@ func TestServiceRegistryDelete(t *testing.T) {
|
||||
|
||||
func TestServiceRegistryDeleteExternal(t *testing.T) {
|
||||
registry := registrytest.NewServiceRegistry()
|
||||
fakeCloud := &cloudprovider.FakeCloud{}
|
||||
fakeCloud := &fake_cloud.FakeCloud{}
|
||||
machines := []string{"foo", "bar", "baz"}
|
||||
storage := NewRegistryStorage(registry, fakeCloud, minion.NewRegistry(machines))
|
||||
svc := api.Service{
|
||||
@ -245,7 +245,7 @@ func TestServiceRegistryMakeLinkVariables(t *testing.T) {
|
||||
|
||||
func TestServiceRegistryGet(t *testing.T) {
|
||||
registry := registrytest.NewServiceRegistry()
|
||||
fakeCloud := &cloudprovider.FakeCloud{}
|
||||
fakeCloud := &fake_cloud.FakeCloud{}
|
||||
machines := []string{"foo", "bar", "baz"}
|
||||
storage := NewRegistryStorage(registry, fakeCloud, minion.NewRegistry(machines))
|
||||
registry.CreateService(api.Service{
|
||||
@ -263,7 +263,7 @@ func TestServiceRegistryGet(t *testing.T) {
|
||||
|
||||
func TestServiceRegistryList(t *testing.T) {
|
||||
registry := registrytest.NewServiceRegistry()
|
||||
fakeCloud := &cloudprovider.FakeCloud{}
|
||||
fakeCloud := &fake_cloud.FakeCloud{}
|
||||
machines := []string{"foo", "bar", "baz"}
|
||||
storage := NewRegistryStorage(registry, fakeCloud, minion.NewRegistry(machines))
|
||||
registry.CreateService(api.Service{
|
||||
|
Loading…
Reference in New Issue
Block a user