diff --git a/pkg/cloudprovider/providers/gce/BUILD b/pkg/cloudprovider/providers/gce/BUILD index 85f22652a9..90fcfbe074 100644 --- a/pkg/cloudprovider/providers/gce/BUILD +++ b/pkg/cloudprovider/providers/gce/BUILD @@ -46,6 +46,7 @@ go_library( "//vendor:golang.org/x/net/context", "//vendor:golang.org/x/oauth2", "//vendor:golang.org/x/oauth2/google", + "//vendor:google.golang.org/api/compute/v0.alpha", "//vendor:google.golang.org/api/compute/v1", "//vendor:google.golang.org/api/container/v1", "//vendor:google.golang.org/api/gensupport", diff --git a/pkg/cloudprovider/providers/gce/gce.go b/pkg/cloudprovider/providers/gce/gce.go index 2a6a418612..cd8ec9c72a 100644 --- a/pkg/cloudprovider/providers/gce/gce.go +++ b/pkg/cloudprovider/providers/gce/gce.go @@ -36,6 +36,7 @@ import ( "github.com/golang/glog" "golang.org/x/oauth2" "golang.org/x/oauth2/google" + computealpha "google.golang.org/api/compute/v0.alpha" compute "google.golang.org/api/compute/v1" container "google.golang.org/api/container/v1" "google.golang.org/api/gensupport" @@ -77,6 +78,7 @@ const ( // GCECloud is an implementation of Interface, LoadBalancer and Instances for Google Compute Engine. type GCECloud struct { service *compute.Service + serviceAlpha *computealpha.Service containerService *container.Service projectID string region string @@ -211,43 +213,29 @@ func newGCECloud(config io.Reader) (*GCECloud, error) { func CreateGCECloud(projectID, region, zone string, managedZones []string, networkURL string, nodeTags []string, nodeInstancePrefix string, tokenSource oauth2.TokenSource, useMetadataServer bool) (*GCECloud, error) { - if tokenSource == nil { - var err error - tokenSource, err = google.DefaultTokenSource( - oauth2.NoContext, - compute.CloudPlatformScope, - compute.ComputeScope) - glog.Infof("Using DefaultTokenSource %#v", tokenSource) - if err != nil { - return nil, err - } - } else { - glog.Infof("Using existing Token Source %#v", tokenSource) - } - - if err := wait.PollImmediate(5*time.Second, 30*time.Second, func() (bool, error) { - if _, err := tokenSource.Token(); err != nil { - glog.Errorf("error fetching initial token: %v", err) - return false, nil - } - return true, nil - }); err != nil { - return nil, err - } - - client := oauth2.NewClient(oauth2.NoContext, tokenSource) - svc, err := compute.New(client) + client, err := newOauthClient(tokenSource) if err != nil { return nil, err } - containerSvc, err := container.New(client) + service, err := compute.New(client) + if err != nil { + return nil, err + } + + client, err = newOauthClient(tokenSource) + serviceAlpha, err := computealpha.New(client) + if err != nil { + return nil, err + } + + containerService, err := container.New(client) if err != nil { return nil, err } if networkURL == "" { - networkName, err := getNetworkNameViaAPICall(svc, projectID) + networkName, err := getNetworkNameViaAPICall(service, projectID) if err != nil { return nil, err } @@ -255,7 +243,7 @@ func CreateGCECloud(projectID, region, zone string, managedZones []string, netwo } if len(managedZones) == 0 { - managedZones, err = getZonesForRegion(svc, projectID, region) + managedZones, err = getZonesForRegion(service, projectID, region) if err != nil { return nil, err } @@ -267,8 +255,9 @@ func CreateGCECloud(projectID, region, zone string, managedZones []string, netwo operationPollRateLimiter := flowcontrol.NewTokenBucketRateLimiter(10, 100) // 10 qps, 100 bucket size. return &GCECloud{ - service: svc, - containerService: containerSvc, + service: service, + serviceAlpha: serviceAlpha, + containerService: containerService, projectID: projectID, region: region, localZone: zone, @@ -378,3 +367,31 @@ func getZonesForRegion(svc *compute.Service, projectID, region string) ([]string } return zones, nil } + +func newOauthClient(tokenSource oauth2.TokenSource) (*http.Client, error) { + if tokenSource == nil { + var err error + tokenSource, err = google.DefaultTokenSource( + oauth2.NoContext, + compute.CloudPlatformScope, + compute.ComputeScope) + glog.Infof("Using DefaultTokenSource %#v", tokenSource) + if err != nil { + return nil, err + } + } else { + glog.Infof("Using existing Token Source %#v", tokenSource) + } + + if err := wait.PollImmediate(5*time.Second, 30*time.Second, func() (bool, error) { + if _, err := tokenSource.Token(); err != nil { + glog.Errorf("error fetching initial token: %v", err) + return false, nil + } + return true, nil + }); err != nil { + return nil, err + } + + return oauth2.NewClient(oauth2.NoContext, tokenSource), nil +} diff --git a/pkg/cloudprovider/providers/gce/gce_instances.go b/pkg/cloudprovider/providers/gce/gce_instances.go index 8f71a7c7e5..c6c87199bc 100644 --- a/pkg/cloudprovider/providers/gce/gce_instances.go +++ b/pkg/cloudprovider/providers/gce/gce_instances.go @@ -26,6 +26,7 @@ import ( "cloud.google.com/go/compute/metadata" "github.com/golang/glog" + computealpha "google.golang.org/api/compute/v0.alpha" compute "google.golang.org/api/compute/v1" "k8s.io/apimachinery/pkg/types" @@ -51,6 +52,20 @@ func (gce *GCECloud) NodeAddresses(_ types.NodeName) ([]v1.NodeAddress, error) { }, nil } +// 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") +} + +// 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 (gce *GCECloud) InstanceTypeByProviderID(providerID string) (string, error) { + return "", errors.New("unimplemented") +} + // ExternalID returns the cloud provider ID of the node with the specified NodeName (deprecated). func (gce *GCECloud) ExternalID(nodeName types.NodeName) (string, error) { instanceName := mapNodeNameToInstanceName(nodeName) @@ -202,6 +217,31 @@ func (gce *GCECloud) CurrentNodeName(hostname string) (types.NodeName, error) { return types.NodeName(hostname), nil } +// PodCIDRs returns a list of CIDR ranges that are assigned to the +// `node` for allocation to pods. Returns a list of the form +// "/". +func (gce *GCECloud) PodCIDRs(nodeName types.NodeName) (cidrs []string, err error) { + var instance *gceInstance + instance, err = gce.getInstanceByName(mapNodeNameToInstanceName(nodeName)) + if err != nil { + return + } + + var res *computealpha.Instance + res, err = gce.serviceAlpha.Instances.Get( + gce.projectID, instance.Zone, instance.Name).Do() + if err != nil { + return + } + + for _, networkInterface := range res.NetworkInterfaces { + for _, aliasIpRange := range networkInterface.AliasIpRanges { + cidrs = append(cidrs, aliasIpRange.IpCidrRange) + } + } + return +} + // Gets the named instances, returning cloudprovider.InstanceNotFound if any instance is not found func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error) { instances := make(map[string]*gceInstance) @@ -351,17 +391,3 @@ func (gce *GCECloud) isCurrentInstance(instanceID string) bool { return currentInstanceID == canonicalizeInstanceName(instanceID) } - -// NodeAddressesByProviderID returns the node addresses of an instances 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 (gce *GCECloud) NodeAddressesByProviderID(providerID string) ([]v1.NodeAddress, error) { - return []v1.NodeAddress{}, errors.New("unimplemented") -} - -// 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 (gce *GCECloud) InstanceTypeByProviderID(providerID string) (string, error) { - return "", errors.New("unimplemented") -}