From 0154bd279ddc558dfcd6355d49ca7af3b088744a Mon Sep 17 00:00:00 2001 From: FengyunPan Date: Mon, 10 Jul 2017 20:43:07 +0800 Subject: [PATCH] Rackspace for cloud-controller-manager This implements the NodeAddressesByProviderID and InstanceTypeByProviderID methods used by the cloud-controller-manager to the RackSpace provider. The instance type returned is the flavor name, for consistency InstanceType has been implemented too returning the same value. This is part of #47257 cc @wlan0 --- .../providers/rackspace/rackspace.go | 69 ++++++++++++++++++- .../providers/rackspace/rackspace_test.go | 43 ++++++++++++ 2 files changed, 109 insertions(+), 3 deletions(-) diff --git a/pkg/cloudprovider/providers/rackspace/rackspace.go b/pkg/cloudprovider/providers/rackspace/rackspace.go index 32aaea0587d..0e04d9407c4 100644 --- a/pkg/cloudprovider/providers/rackspace/rackspace.go +++ b/pkg/cloudprovider/providers/rackspace/rackspace.go @@ -398,7 +398,25 @@ func (i *Instances) NodeAddresses(nodeName types.NodeName) ([]v1.NodeAddress, er // This method will not be called from the node that is requesting this ID. i.e. metadata service // and other local methods cannot be used here func (i *Instances) NodeAddressesByProviderID(providerID string) ([]v1.NodeAddress, error) { - return []v1.NodeAddress{}, errors.New("unimplemented") + instanceID, err := instanceIDFromProviderID(providerID) + + if err != nil { + return []v1.NodeAddress{}, err + } + + server, err := servers.Get(i.compute, instanceID).Extract() + + if err != nil { + return []v1.NodeAddress{}, err + } + + addresses, err := i.NodeAddresses(mapServerToNodeName(server)) + + if err != nil { + return []v1.NodeAddress{}, err + } + + return addresses, nil } // mapNodeNameToServerName maps from a k8s NodeName to a rackspace Server Name @@ -431,14 +449,59 @@ func (i *Instances) InstanceID(nodeName types.NodeName) (string, error) { // InstanceType returns the type of the specified instance. func (i *Instances) InstanceType(name types.NodeName) (string, error) { - return "", nil + serverName := mapNodeNameToServerName(name) + + srv, err := getServerByName(i.compute, serverName) + if err != nil { + return "", err + } + + return srvInstanceType(srv) +} + +func srvInstanceType(srv *osservers.Server) (string, error) { + val, ok := srv.Flavor["name"] + + if !ok { + return "", fmt.Errorf("flavor name not present in server info") + } + + flavor, ok := val.(string) + + if !ok { + return "", fmt.Errorf("flavor name is not a string") + } + + return flavor, nil +} + +func instanceIDFromProviderID(providerID string) (instanceID string, err error) { + var providerIDRegexp = regexp.MustCompile(`^rackspace://([^/]+)$`) + matches := providerIDRegexp.FindStringSubmatch(providerID) + if len(matches) != 2 { + return "", fmt.Errorf("ProviderID \"%s\" didn't match expected format \"rackspace://InstanceID\"", providerID) + } + + return matches[1], nil } // InstanceTypeByProviderID returns the cloudprovider instance type of the node with the specified unique providerID // This method will not be called from the node that is requesting this ID. i.e. metadata service // and other local methods cannot be used here func (i *Instances) InstanceTypeByProviderID(providerID string) (string, error) { - return "", errors.New("unimplemented") + instanceID, err := instanceIDFromProviderID(providerID) + + if err != nil { + return "", err + } + + server, err := servers.Get(i.compute, instanceID).Extract() + + if err != nil { + return "", err + } + + return srvInstanceType(server) } func (i *Instances) AddSSHKeyToAllInstances(user string, keyData []byte) error { diff --git a/pkg/cloudprovider/providers/rackspace/rackspace_test.go b/pkg/cloudprovider/providers/rackspace/rackspace_test.go index 66101bcd4a2..92a42619611 100644 --- a/pkg/cloudprovider/providers/rackspace/rackspace_test.go +++ b/pkg/cloudprovider/providers/rackspace/rackspace_test.go @@ -162,3 +162,46 @@ func TestZones(t *testing.T) { t.Fatalf("GetZone() returned wrong region (%s)", zone.Region) } } + +func TestInstanceIDFromProviderID(t *testing.T) { + testCases := []struct { + providerID string + instanceID string + fail bool + }{ + { + providerID: ProviderName + "://7b9cf879-7146-417c-abfd-cb4272f0c935", + instanceID: "7b9cf879-7146-417c-abfd-cb4272f0c935", + fail: false, + }, + { + providerID: "7b9cf879-7146-417c-abfd-cb4272f0c935", + instanceID: "", + fail: true, + }, + { + providerID: "other-provider://7b9cf879-7146-417c-abfd-cb4272f0c935", + instanceID: "", + fail: true, + }, + { + providerID: "", + instanceID: "", + fail: true, + }, + } + + for _, test := range testCases { + instanceID, err := instanceIDFromProviderID(test.providerID) + if (err != nil) != test.fail { + t.Errorf("%s yielded `err != nil` as %t. expected %t", test.providerID, (err != nil), test.fail) + } + + if test.fail { + continue + } + if instanceID != test.instanceID { + t.Errorf("%s yielded %s. expected %s", test.providerID, instanceID, test.instanceID) + } + } +}