Implement providerID node functions for gce
*Add splitProviderID helper function *Add getInstanceFromProjectInZoneByName function *Implement gce InstanceTypeByProviderID *Implement gce NodeAddressesByProviderID
This commit is contained in:
		| @@ -17,7 +17,6 @@ limitations under the License. | ||||
| package gce | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"strconv" | ||||
| @@ -62,7 +61,27 @@ func (gce *GCECloud) NodeAddresses(_ types.NodeName) ([]v1.NodeAddress, error) { | ||||
| // 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 (gce *GCECloud) NodeAddressesByProviderID(providerID string) ([]v1.NodeAddress, error) { | ||||
| 	return []v1.NodeAddress{}, errors.New("unimplemented") | ||||
| 	project, zone, name, err := splitProviderID(providerID) | ||||
| 	if err != nil { | ||||
| 		return []v1.NodeAddress{}, err | ||||
| 	} | ||||
|  | ||||
| 	instance, err := gce.service.Instances.Get(project, zone, canonicalizeInstanceName(name)).Do() | ||||
| 	if err != nil { | ||||
| 		return []v1.NodeAddress{}, fmt.Errorf("error while querying for providerID %q: %v", providerID, err) | ||||
| 	} | ||||
|  | ||||
| 	if len(instance.NetworkInterfaces) < 1 { | ||||
| 		return []v1.NodeAddress{}, fmt.Errorf("could not find network interfaces for providerID %q", providerID) | ||||
| 	} | ||||
| 	networkInterface := instance.NetworkInterfaces[0] | ||||
|  | ||||
| 	nodeAddresses := []v1.NodeAddress{{Type: v1.NodeInternalIP, Address: networkInterface.NetworkIP}} | ||||
| 	for _, config := range networkInterface.AccessConfigs { | ||||
| 		nodeAddresses = append(nodeAddresses, v1.NodeAddress{Type: v1.NodeExternalIP, Address: config.NatIP}) | ||||
| 	} | ||||
|  | ||||
| 	return nodeAddresses, nil | ||||
| } | ||||
|  | ||||
| // InstanceTypeByProviderID returns the cloudprovider instance type of the node | ||||
| @@ -70,7 +89,15 @@ func (gce *GCECloud) NodeAddressesByProviderID(providerID string) ([]v1.NodeAddr | ||||
| // node that is requesting this ID. i.e. metadata service and other local | ||||
| // methods cannot be used here | ||||
| func (gce *GCECloud) InstanceTypeByProviderID(providerID string) (string, error) { | ||||
| 	return "", errors.New("unimplemented") | ||||
| 	project, zone, name, err := splitProviderID(providerID) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	instance, err := gce.getInstanceFromProjectInZoneByName(project, zone, name) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return instance.Type, nil | ||||
| } | ||||
|  | ||||
| // ExternalID returns the cloud provider ID of the node with the specified NodeName (deprecated). | ||||
| @@ -339,30 +366,38 @@ func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error) | ||||
| func (gce *GCECloud) getInstanceByName(name string) (*gceInstance, error) { | ||||
| 	// Avoid changing behaviour when not managing multiple zones | ||||
| 	for _, zone := range gce.managedZones { | ||||
| 		name = canonicalizeInstanceName(name) | ||||
| 		mc := newInstancesMetricContext("get", zone) | ||||
| 		res, err := gce.service.Instances.Get(gce.projectID, zone, name).Do() | ||||
| 		mc.Observe(err) | ||||
| 		instance, err := gce.getInstanceFromProjectInZoneByName(gce.projectID, zone, name) | ||||
| 		if err != nil { | ||||
| 			glog.Errorf("getInstanceByName: failed to get instance %s; err: %v", name, err) | ||||
|  | ||||
| 			if isHTTPErrorCode(err, http.StatusNotFound) { | ||||
| 				continue | ||||
| 			} | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return &gceInstance{ | ||||
| 			Zone:  lastComponent(res.Zone), | ||||
| 			Name:  res.Name, | ||||
| 			ID:    res.Id, | ||||
| 			Disks: res.Disks, | ||||
| 			Type:  lastComponent(res.MachineType), | ||||
| 		}, nil | ||||
| 		return instance, nil | ||||
| 	} | ||||
|  | ||||
| 	return nil, cloudprovider.InstanceNotFound | ||||
| } | ||||
|  | ||||
| func (gce *GCECloud) getInstanceFromProjectInZoneByName(project, zone, name string) (*gceInstance, error) { | ||||
| 	name = canonicalizeInstanceName(name) | ||||
| 	mc := newInstancesMetricContext("get", zone) | ||||
| 	res, err := gce.service.Instances.Get(project, zone, name).Do() | ||||
| 	mc.Observe(err) | ||||
| 	if err != nil { | ||||
| 		glog.Errorf("getInstanceFromProjectInZoneByName: failed to get instance %s; err: %v", name, err) | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &gceInstance{ | ||||
| 		Zone:  lastComponent(res.Zone), | ||||
| 		Name:  res.Name, | ||||
| 		ID:    res.Id, | ||||
| 		Disks: res.Disks, | ||||
| 		Type:  lastComponent(res.MachineType), | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func getInstanceIDViaMetadata() (string, error) { | ||||
| 	result, err := metadata.Get("instance/hostname") | ||||
| 	if err != nil { | ||||
|   | ||||
| @@ -158,3 +158,93 @@ func TestCreateFirewallFails(t *testing.T) { | ||||
| 		t.Errorf("error expected when creating firewall without any tags found") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestSplitProviderID(t *testing.T) { | ||||
| 	providers := []struct { | ||||
| 		providerID string | ||||
|  | ||||
| 		project  string | ||||
| 		zone     string | ||||
| 		instance string | ||||
|  | ||||
| 		fail bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			providerID: ProviderName + "://project-example-164317/us-central1-f/kubernetes-node-fhx1", | ||||
| 			project:    "project-example-164317", | ||||
| 			zone:       "us-central1-f", | ||||
| 			instance:   "kubernetes-node-fhx1", | ||||
| 			fail:       false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			providerID: ProviderName + "://project-example.164317/us-central1-f/kubernetes-node-fhx1", | ||||
| 			project:    "project-example.164317", | ||||
| 			zone:       "us-central1-f", | ||||
| 			instance:   "kubernetes-node-fhx1", | ||||
| 			fail:       false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			providerID: ProviderName + "://project-example-164317/us-central1-fkubernetes-node-fhx1", | ||||
| 			project:    "", | ||||
| 			zone:       "", | ||||
| 			instance:   "", | ||||
| 			fail:       true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			providerID: ProviderName + ":/project-example-164317/us-central1-f/kubernetes-node-fhx1", | ||||
| 			project:    "", | ||||
| 			zone:       "", | ||||
| 			instance:   "", | ||||
| 			fail:       true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			providerID: "aws://project-example-164317/us-central1-f/kubernetes-node-fhx1", | ||||
| 			project:    "", | ||||
| 			zone:       "", | ||||
| 			instance:   "", | ||||
| 			fail:       true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			providerID: ProviderName + "://project-example-164317/us-central1-f/kubernetes-node-fhx1/", | ||||
| 			project:    "", | ||||
| 			zone:       "", | ||||
| 			instance:   "", | ||||
| 			fail:       true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			providerID: ProviderName + "://project-example.164317//kubernetes-node-fhx1", | ||||
| 			project:    "", | ||||
| 			zone:       "", | ||||
| 			instance:   "", | ||||
| 			fail:       true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			providerID: ProviderName + "://project-example.164317/kubernetes-node-fhx1", | ||||
| 			project:    "", | ||||
| 			zone:       "", | ||||
| 			instance:   "", | ||||
| 			fail:       true, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range providers { | ||||
| 		project, zone, instance, err := splitProviderID(test.providerID) | ||||
| 		if (err != nil) != test.fail { | ||||
| 			t.Errorf("Expected to failt=%t, with pattern %v", test.fail, test) | ||||
| 		} | ||||
|  | ||||
| 		if test.fail { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if project != test.project { | ||||
| 			t.Errorf("Expected %v, but got %v", test.project, project) | ||||
| 		} | ||||
| 		if zone != test.zone { | ||||
| 			t.Errorf("Expected %v, but got %v", test.zone, zone) | ||||
| 		} | ||||
| 		if instance != test.instance { | ||||
| 			t.Errorf("Expected %v, but got %v", test.instance, instance) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -17,7 +17,9 @@ limitations under the License. | ||||
| package gce | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
|  | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| @@ -35,6 +37,8 @@ type gceInstance struct { | ||||
| 	Type  string | ||||
| } | ||||
|  | ||||
| var providerIdRE = regexp.MustCompile(`^` + ProviderName + `://([^/]+)/([^/]+)/([^/]+)$`) | ||||
|  | ||||
| func getProjectAndZone() (string, string, error) { | ||||
| 	result, err := metadata.Get("instance/zone") | ||||
| 	if err != nil { | ||||
| @@ -100,3 +104,14 @@ func isHTTPErrorCode(err error, code int) bool { | ||||
| 	apiErr, ok := err.(*googleapi.Error) | ||||
| 	return ok && apiErr.Code == code | ||||
| } | ||||
|  | ||||
| // splitProviderID splits a provider's id into core components. | ||||
| // A providerID is build out of '${ProviderName}://${project-id}/${zone}/${instance-name}' | ||||
| // See cloudprovider.GetInstanceProviderID. | ||||
| func splitProviderID(providerID string) (project, zone, instance string, err error) { | ||||
| 	matches := providerIdRE.FindStringSubmatch(providerID) | ||||
| 	if len(matches) != 4 { | ||||
| 		return "", "", "", errors.New("error splitting providerID") | ||||
| 	} | ||||
| 	return matches[1], matches[2], matches[3], nil | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 realfake
					realfake