diff --git a/pkg/cloudprovider/cloud.go b/pkg/cloudprovider/cloud.go index 7e516215894..28a91b6a01a 100644 --- a/pkg/cloudprovider/cloud.go +++ b/pkg/cloudprovider/cloud.go @@ -38,4 +38,6 @@ type TCPLoadBalancer interface { type Instances interface { IPAddress(name string) (net.IP, error) + // Lists instances that match 'filter' which is a regular expression which must match the entire instance name + List(filter string) ([]string, error) } diff --git a/pkg/cloudprovider/fake_cloud.go b/pkg/cloudprovider/fake_cloud.go index e2b06f3aef6..b77438fe594 100644 --- a/pkg/cloudprovider/fake_cloud.go +++ b/pkg/cloudprovider/fake_cloud.go @@ -18,13 +18,15 @@ package cloudprovider import ( "net" + "regexp" ) type FakeCloud struct { - Exists bool - Err error - Calls []string - IP net.IP + Exists bool + Err error + Calls []string + IP net.IP + Machines []string } func (f *FakeCloud) addCall(desc string) { @@ -66,3 +68,14 @@ func (f *FakeCloud) IPAddress(instance string) (net.IP, error) { f.addCall("ip-address") return f.IP, f.Err } + +func (f *FakeCloud) List(filter string) ([]string, error) { + f.addCall("list") + result := []string{} + for _, machine := range f.Machines { + if match, _ := regexp.MatchString(filter, machine); match { + result = append(result, machine) + } + } + return result, f.Err +} diff --git a/pkg/cloudprovider/gce.go b/pkg/cloudprovider/gce.go index 1b1667737d0..83dee9ab431 100644 --- a/pkg/cloudprovider/gce.go +++ b/pkg/cloudprovider/gce.go @@ -30,9 +30,10 @@ import ( ) type GCECloud struct { - service *compute.Service - projectID string - zone string + service *compute.Service + projectID string + zone string + instanceRE string } func getProjectAndZone() (string, string, error) { @@ -179,3 +180,19 @@ func (gce *GCECloud) IPAddress(instance string) (net.IP, error) { } return ip, nil } + +func (gce *GCECloud) List(filter string) ([]string, error) { + listCall := gce.service.Instances.List(gce.projectID, gce.zone) + if len(filter) > 0 { + listCall = listCall.Filter("name eq " + filter) + } + res, err := listCall.Do() + if err != nil { + return nil, err + } + var instances []string + for _, instance := range res.Items { + instances = append(instances, instance.Name) + } + return instances, nil +} diff --git a/pkg/registry/cloud_minion_registry.go b/pkg/registry/cloud_minion_registry.go new file mode 100644 index 00000000000..3a158fabc6d --- /dev/null +++ b/pkg/registry/cloud_minion_registry.go @@ -0,0 +1,65 @@ +/* +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 registry + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider" +) + +type CloudMinionRegistry struct { + cloud cloudprovider.Interface + matchRE string +} + +func MakeCloudMinionRegistry(cloud cloudprovider.Interface, matchRE string) (*CloudMinionRegistry, error) { + return &CloudMinionRegistry{ + cloud: cloud, + matchRE: matchRE, + }, nil +} + +func (c *CloudMinionRegistry) List() ([]string, error) { + instances, ok := c.cloud.Instances() + if !ok { + return nil, fmt.Errorf("cloud doesn't support instances") + } + + return instances.List(c.matchRE) +} + +func (c *CloudMinionRegistry) Insert(minion string) error { + return fmt.Errorf("unsupported") +} + +func (c *CloudMinionRegistry) Delete(minion string) error { + return fmt.Errorf("unsupported") +} + +func (c *CloudMinionRegistry) Contains(minion string) (bool, error) { + instances, err := c.List() + if err != nil { + return false, err + } + for _, name := range instances { + if name == minion { + return true, nil + } + } + return false, nil +} diff --git a/pkg/registry/cloud_minion_registry_test.go b/pkg/registry/cloud_minion_registry_test.go new file mode 100644 index 00000000000..80ea49075ce --- /dev/null +++ b/pkg/registry/cloud_minion_registry_test.go @@ -0,0 +1,76 @@ +/* +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 registry + +import ( + "reflect" + "testing" + + "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider" +) + +func TestCloudList(t *testing.T) { + instances := []string{"m1", "m2"} + fakeCloud := cloudprovider.FakeCloud{ + Machines: instances, + } + registry, err := MakeCloudMinionRegistry(&fakeCloud, ".*") + expectNoError(t, err) + + list, err := registry.List() + expectNoError(t, err) + if !reflect.DeepEqual(list, instances) { + t.Errorf("Unexpected inequality: %#v, %#v", list, instances) + } +} + +func TestCloudContains(t *testing.T) { + instances := []string{"m1", "m2"} + fakeCloud := cloudprovider.FakeCloud{ + Machines: instances, + } + registry, err := MakeCloudMinionRegistry(&fakeCloud, ".*") + expectNoError(t, err) + + contains, err := registry.Contains("m1") + expectNoError(t, err) + if !contains { + t.Errorf("Unexpected !contains") + } + + contains, err = registry.Contains("m100") + expectNoError(t, err) + if contains { + t.Errorf("Unexpected contains") + } +} + +func TestCloudListRegexp(t *testing.T) { + instances := []string{"m1", "m2", "n1", "n2"} + fakeCloud := cloudprovider.FakeCloud{ + Machines: instances, + } + registry, err := MakeCloudMinionRegistry(&fakeCloud, "m[0-9]+") + expectNoError(t, err) + + list, err := registry.List() + expectNoError(t, err) + expectedList := []string{"m1", "m2"} + if !reflect.DeepEqual(list, expectedList) { + t.Errorf("Unexpected inequality: %#v, %#v", list, expectedList) + } +}