Merge pull request #6300 from cjcullen/tokens

Add an alternative TokenSource to the GCE CloudProvider.
This commit is contained in:
Alex Robinson 2015-04-01 18:02:40 -07:00
commit 9949936b5c
5 changed files with 124 additions and 16 deletions

View File

@ -300,6 +300,16 @@ grains:
cbr-cidr: ${MASTER_IP_RANGE} cbr-cidr: ${MASTER_IP_RANGE}
cloud: gce cloud: gce
EOF EOF
if ! [[ -z "${PROJECT_ID:-}" ]] && ! [[ -z "${TOKEN_URL:-}" ]]; then
cat <<EOF >/etc/gce.conf
[global]
token-url = ${TOKEN_URL}
project-id = ${PROJECT_ID}
EOF
cat <<EOF >>/etc/salt/minion.d/grains.conf
cloud_config: /etc/gce.conf
EOF
fi
} }
function salt-node-role() { function salt-node-role() {

View File

@ -9,7 +9,12 @@
{% if grains.cloud is defined -%} {% if grains.cloud is defined -%}
{% set cloud_provider = "--cloud_provider=" + grains.cloud -%} {% 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 cloud_config = "--cloud_config=/etc/aws.conf" -%}
{% endif -%} {% endif -%}
@ -26,7 +31,6 @@
{% set publicAddressOverride = "--public_address_override=" + grains.publicAddressOverride -%} {% set publicAddressOverride = "--public_address_override=" + grains.publicAddressOverride -%}
{% endif -%} {% endif -%}
{% if grains.etcd_servers is defined -%} {% if grains.etcd_servers is defined -%}
{% set etcd_servers = "--etcd_servers=http://" + grains.etcd_servers + ":4001" -%} {% set etcd_servers = "--etcd_servers=http://" + grains.etcd_servers + ":4001" -%}
{% elif grains.cloud == 'gce' -%} {% elif grains.cloud == 'gce' -%}

View File

@ -19,7 +19,12 @@
{% if grains.cloud is defined -%} {% if grains.cloud is defined -%}
{% set cloud_provider = "--cloud_provider=" + grains.cloud -%} {% 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 cloud_config = "--cloud_config=/etc/aws.conf" -%}
{% set machines = "--machines=" + ','.join(salt['mine.get']('roles:kubernetes-pool', 'network.ip_addrs', expr_form='grain').keys()) -%} {% set machines = "--machines=" + ','.join(salt['mine.get']('roles:kubernetes-pool', 'network.ip_addrs', expr_form='grain').keys()) -%}

View File

@ -33,6 +33,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider" "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
"code.google.com/p/gcfg"
compute "code.google.com/p/google-api-go-client/compute/v1" compute "code.google.com/p/google-api-go-client/compute/v1"
container "code.google.com/p/google-api-go-client/container/v1beta1" container "code.google.com/p/google-api-go-client/container/v1beta1"
"github.com/golang/glog" "github.com/golang/glog"
@ -55,8 +56,15 @@ type GCECloud struct {
metadataAccess func(string) (string, error) metadataAccess func(string) (string, error)
} }
type Config struct {
Global struct {
TokenURL string `gcfg:"token-url"`
ProjectID string `gcfg:"project-id"`
}
}
func init() { 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) { func getMetadata(url string) (string, error) {
@ -103,7 +111,7 @@ func getInstanceID() (string, error) {
} }
// newGCECloud creates a new instance of GCECloud. // newGCECloud creates a new instance of GCECloud.
func newGCECloud() (*GCECloud, error) { func newGCECloud(config io.Reader) (*GCECloud, error) {
projectID, zone, err := getProjectAndZone() projectID, zone, err := getProjectAndZone()
if err != nil { if err != nil {
return nil, err return nil, err
@ -115,7 +123,18 @@ func newGCECloud() (*GCECloud, error) {
if err != nil { if err != nil {
return nil, err 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) svc, err := compute.New(client)
if err != nil { if err != nil {
return nil, err return nil, err
@ -337,6 +356,18 @@ func (gce *GCECloud) getInstanceByName(name string) (*compute.Instance, error) {
// NodeAddresses is an implementation of Instances.NodeAddresses. // NodeAddresses is an implementation of Instances.NodeAddresses.
func (gce *GCECloud) NodeAddresses(instance string) ([]api.NodeAddress, error) { 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) inst, err := gce.getInstanceByName(instance)
if err != nil { if err != nil {
return nil, err return nil, err
@ -345,16 +376,7 @@ func (gce *GCECloud) NodeAddresses(instance string) ([]api.NodeAddress, error) {
if ip == nil { if ip == nil {
return nil, fmt.Errorf("invalid network IP: %s", inst.NetworkInterfaces[0].AccessConfigs[0].NatIP) return nil, fmt.Errorf("invalid network IP: %s", inst.NetworkInterfaces[0].AccessConfigs[0].NatIP)
} }
return &api.NodeAddress{Type: api.NodeLegacyHostIP, Address: ip.String()}, nil
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
} }
// ExternalID returns the cloud provider ID of the specified instance. // ExternalID returns the cloud provider ID of the specified instance.

View File

@ -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)
}