From 5e6e67ba597f8798ec4ec4f62c8bc02fe3a8888c Mon Sep 17 00:00:00 2001 From: CJ Cullen Date: Tue, 31 Mar 2015 09:41:27 -0700 Subject: [PATCH] Add an alternative TokenSource to the GCE CloudProvider. --- cluster/gce/configure-vm.sh | 10 +++ cluster/saltbase/salt/kube-apiserver/default | 8 ++- .../salt/kube-controller-manager/default | 7 +- pkg/cloudprovider/gce/gce.go | 48 +++++++++---- pkg/cloudprovider/gce/token_source.go | 67 +++++++++++++++++++ 5 files changed, 124 insertions(+), 16 deletions(-) create mode 100644 pkg/cloudprovider/gce/token_source.go diff --git a/cluster/gce/configure-vm.sh b/cluster/gce/configure-vm.sh index 92325024a9c..fe5bd92cb5a 100644 --- a/cluster/gce/configure-vm.sh +++ b/cluster/gce/configure-vm.sh @@ -300,6 +300,16 @@ grains: cbr-cidr: ${MASTER_IP_RANGE} cloud: gce EOF + if ! [[ -z "${PROJECT_ID:-}" ]] && ! [[ -z "${TOKEN_URL:-}" ]]; then + cat </etc/gce.conf +[global] +token-url = ${TOKEN_URL} +project-id = ${PROJECT_ID} +EOF + cat <>/etc/salt/minion.d/grains.conf + cloud_config: /etc/gce.conf +EOF + fi } function salt-node-role() { diff --git a/cluster/saltbase/salt/kube-apiserver/default b/cluster/saltbase/salt/kube-apiserver/default index fa030595e38..982c65f4d7e 100644 --- a/cluster/saltbase/salt/kube-apiserver/default +++ b/cluster/saltbase/salt/kube-apiserver/default @@ -9,7 +9,12 @@ {% if grains.cloud is defined -%} {% set cloud_provider = "--cloud_provider=" + grains.cloud -%} -{% if grains.cloud == 'aws' -%} +{% if grains.cloud == 'gce' -%} + {% if grains.cloud_config is defined -%} + {% set cloud_config = "--cloud_config=" + grains.cloud_config -%} + {% endif -%} + +{% elif grains.cloud == 'aws' -%} {% set cloud_config = "--cloud_config=/etc/aws.conf" -%} {% endif -%} @@ -26,7 +31,6 @@ {% set publicAddressOverride = "--public_address_override=" + grains.publicAddressOverride -%} {% endif -%} - {% if grains.etcd_servers is defined -%} {% set etcd_servers = "--etcd_servers=http://" + grains.etcd_servers + ":4001" -%} {% elif grains.cloud == 'gce' -%} diff --git a/cluster/saltbase/salt/kube-controller-manager/default b/cluster/saltbase/salt/kube-controller-manager/default index f0925055c80..c10a3976ac8 100644 --- a/cluster/saltbase/salt/kube-controller-manager/default +++ b/cluster/saltbase/salt/kube-controller-manager/default @@ -19,7 +19,12 @@ {% if grains.cloud is defined -%} {% set cloud_provider = "--cloud_provider=" + grains.cloud -%} -{% if grains.cloud == 'aws' -%} +{% if grains.cloud == 'gce' -%} + {% if grains.cloud_config is defined -%} + {% set cloud_config = "--cloud_config=" + grains.cloud_config -%} + {% endif -%} + +{% elif grains.cloud == 'aws' -%} {% set cloud_config = "--cloud_config=/etc/aws.conf" -%} {% set machines = "--machines=" + ','.join(salt['mine.get']('roles:kubernetes-pool', 'network.ip_addrs', expr_form='grain').keys()) -%} diff --git a/pkg/cloudprovider/gce/gce.go b/pkg/cloudprovider/gce/gce.go index 9f0c040f83a..745c8df8998 100644 --- a/pkg/cloudprovider/gce/gce.go +++ b/pkg/cloudprovider/gce/gce.go @@ -33,6 +33,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider" + "code.google.com/p/gcfg" compute "code.google.com/p/google-api-go-client/compute/v1" container "code.google.com/p/google-api-go-client/container/v1beta1" "github.com/golang/glog" @@ -55,8 +56,15 @@ type GCECloud struct { metadataAccess func(string) (string, error) } +type Config struct { + Global struct { + TokenURL string `gcfg:"token-url"` + ProjectID string `gcfg:"project-id"` + } +} + func init() { - cloudprovider.RegisterCloudProvider("gce", func(config io.Reader) (cloudprovider.Interface, error) { return newGCECloud() }) + cloudprovider.RegisterCloudProvider("gce", func(config io.Reader) (cloudprovider.Interface, error) { return newGCECloud(config) }) } func getMetadata(url string) (string, error) { @@ -103,7 +111,7 @@ func getInstanceID() (string, error) { } // newGCECloud creates a new instance of GCECloud. -func newGCECloud() (*GCECloud, error) { +func newGCECloud(config io.Reader) (*GCECloud, error) { projectID, zone, err := getProjectAndZone() if err != nil { return nil, err @@ -115,7 +123,18 @@ func newGCECloud() (*GCECloud, error) { if err != nil { return nil, err } - client := oauth2.NewClient(oauth2.NoContext, google.ComputeTokenSource("")) + tokenSource := google.ComputeTokenSource("") + if config != nil { + var cfg Config + if err := gcfg.ReadInto(&cfg, config); err != nil { + return nil, err + } + if cfg.Global.ProjectID != "" && cfg.Global.TokenURL != "" { + projectID = cfg.Global.ProjectID + tokenSource = newAltTokenSource(cfg.Global.TokenURL) + } + } + client := oauth2.NewClient(oauth2.NoContext, tokenSource) svc, err := compute.New(client) if err != nil { return nil, err @@ -337,6 +356,18 @@ func (gce *GCECloud) getInstanceByName(name string) (*compute.Instance, error) { // NodeAddresses is an implementation of Instances.NodeAddresses. func (gce *GCECloud) NodeAddresses(instance string) ([]api.NodeAddress, error) { + externalIP, err := gce.metadataAccess(EXTERNAL_IP_METADATA_URL) + if err != nil { + return nil, err + } + nodeAddresses := []api.NodeAddress{{Type: api.NodeExternalIP, Address: externalIP}} + if legacyHostAddress, err := gce.getLegacyHostAddress(instance); err == nil { + nodeAddresses = append(nodeAddresses, *legacyHostAddress) + } + return nodeAddresses, nil +} + +func (gce *GCECloud) getLegacyHostAddress(instance string) (*api.NodeAddress, error) { inst, err := gce.getInstanceByName(instance) if err != nil { return nil, err @@ -345,16 +376,7 @@ func (gce *GCECloud) NodeAddresses(instance string) ([]api.NodeAddress, error) { if ip == nil { return nil, fmt.Errorf("invalid network IP: %s", inst.NetworkInterfaces[0].AccessConfigs[0].NatIP) } - - externalIP, err := gce.metadataAccess(EXTERNAL_IP_METADATA_URL) - if err != nil { - return nil, err - } - - return []api.NodeAddress{ - {Type: api.NodeExternalIP, Address: externalIP}, - {Type: api.NodeLegacyHostIP, Address: ip.String()}, - }, nil + return &api.NodeAddress{Type: api.NodeLegacyHostIP, Address: ip.String()}, nil } // ExternalID returns the cloud provider ID of the specified instance. diff --git a/pkg/cloudprovider/gce/token_source.go b/pkg/cloudprovider/gce/token_source.go new file mode 100644 index 00000000000..b9ee3e81eb2 --- /dev/null +++ b/pkg/cloudprovider/gce/token_source.go @@ -0,0 +1,67 @@ +/* +Copyright 2015 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 gce_cloud + +import ( + "encoding/json" + "net/http" + "time" + + "code.google.com/p/google-api-go-client/googleapi" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" +) + +type altTokenSource struct { + oauthClient *http.Client + tokenURL string +} + +func (a *altTokenSource) Token() (*oauth2.Token, error) { + req, err := http.NewRequest("GET", a.tokenURL, nil) + if err != nil { + return nil, err + } + res, err := a.oauthClient.Do(req) + if err != nil { + return nil, err + } + defer res.Body.Close() + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + var tok struct { + AccessToken string `json:"accessToken"` + ExpiryTimeSeconds int64 `json:"expiryTimeSeconds,string"` + } + if err := json.NewDecoder(res.Body).Decode(&tok); err != nil { + return nil, err + } + return &oauth2.Token{ + AccessToken: tok.AccessToken, + Expiry: time.Unix(tok.ExpiryTimeSeconds, 0), + }, nil +} + +func newAltTokenSource(tokenURL string) oauth2.TokenSource { + client := oauth2.NewClient(oauth2.NoContext, google.ComputeTokenSource("")) + a := &altTokenSource{ + oauthClient: client, + tokenURL: tokenURL, + } + return oauth2.ReuseTokenSource(nil, a) +}