Commit 9949936b authored by Alex Robinson's avatar Alex Robinson

Merge pull request #6300 from cjcullen/tokens

Add an alternative TokenSource to the GCE CloudProvider.
parents 3a724b26 5e6e67ba
...@@ -300,6 +300,16 @@ grains: ...@@ -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() {
......
...@@ -9,7 +9,12 @@ ...@@ -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 @@ ...@@ -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' -%}
......
...@@ -19,7 +19,12 @@ ...@@ -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()) -%}
......
...@@ -33,6 +33,7 @@ import ( ...@@ -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 { ...@@ -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) { ...@@ -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) { ...@@ -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,24 +356,27 @@ func (gce *GCECloud) getInstanceByName(name string) (*compute.Instance, error) { ...@@ -337,24 +356,27 @@ 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) {
inst, err := gce.getInstanceByName(instance) externalIP, err := gce.metadataAccess(EXTERNAL_IP_METADATA_URL)
if err != nil { if err != nil {
return nil, err return nil, err
} }
ip := net.ParseIP(inst.NetworkInterfaces[0].AccessConfigs[0].NatIP) nodeAddresses := []api.NodeAddress{{Type: api.NodeExternalIP, Address: externalIP}}
if ip == nil { if legacyHostAddress, err := gce.getLegacyHostAddress(instance); err == nil {
return nil, fmt.Errorf("invalid network IP: %s", inst.NetworkInterfaces[0].AccessConfigs[0].NatIP) nodeAddresses = append(nodeAddresses, *legacyHostAddress)
} }
return nodeAddresses, nil
}
externalIP, err := gce.metadataAccess(EXTERNAL_IP_METADATA_URL) func (gce *GCECloud) getLegacyHostAddress(instance string) (*api.NodeAddress, error) {
inst, err := gce.getInstanceByName(instance)
if err != nil { if err != nil {
return nil, err return nil, err
} }
ip := net.ParseIP(inst.NetworkInterfaces[0].AccessConfigs[0].NatIP)
return []api.NodeAddress{ if ip == nil {
{Type: api.NodeExternalIP, Address: externalIP}, return nil, fmt.Errorf("invalid network IP: %s", inst.NetworkInterfaces[0].AccessConfigs[0].NatIP)
{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. // ExternalID returns the cloud provider ID of the specified instance.
......
/*
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)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment