Update godeps

This commit is contained in:
Prashanth Balasubramanian 2016-06-21 11:58:43 -07:00
parent 423433bc5f
commit 701c5a0e30
482 changed files with 86915 additions and 19741 deletions

View file

@ -28,6 +28,8 @@ import (
"strings"
"time"
"gopkg.in/gcfg.v1"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/service"
"k8s.io/kubernetes/pkg/api/unversioned"
@ -47,7 +49,6 @@ import (
container "google.golang.org/api/container/v1"
"google.golang.org/api/googleapi"
"google.golang.org/cloud/compute/metadata"
"gopkg.in/gcfg.v1"
)
const (
@ -84,21 +85,48 @@ type GCECloud struct {
managedZones []string // List of zones we are spanning (for Ubernetes-Lite, primarily when running on master)
networkURL string
nodeTags []string // List of tags to use on firewall rules for load balancers
nodeInstancePrefix string // If non-"", an advisory prefix for all nodes in the cluster
useMetadataServer bool
operationPollRateLimiter flowcontrol.RateLimiter
}
type Config struct {
Global struct {
TokenURL string `gcfg:"token-url"`
TokenBody string `gcfg:"token-body"`
ProjectID string `gcfg:"project-id"`
NetworkName string `gcfg:"network-name"`
NodeTags []string `gcfg:"node-tags"`
Multizone bool `gcfg:"multizone"`
TokenURL string `gcfg:"token-url"`
TokenBody string `gcfg:"token-body"`
ProjectID string `gcfg:"project-id"`
NetworkName string `gcfg:"network-name"`
NodeTags []string `gcfg:"node-tags"`
NodeInstancePrefix string `gcfg:"node-instance-prefix"`
Multizone bool `gcfg:"multizone"`
}
}
// Disks is interface for manipulation with GCE PDs.
type Disks interface {
// AttachDisk attaches given disk to given instance. Current instance
// is used when instanceID is empty string.
AttachDisk(diskName, instanceID string, readOnly bool) error
// DetachDisk detaches given disk to given instance. Current instance
// is used when instanceID is empty string.
DetachDisk(devicePath, instanceID string) error
// DiskIsAttached checks if a disk is attached to the given node.
DiskIsAttached(diskName, instanceID string) (bool, error)
// CreateDisk creates a new PD with given properties. Tags are serialized
// as JSON into Description field.
CreateDisk(name string, zone string, sizeGb int64, tags map[string]string) error
// DeleteDisk deletes PD.
DeleteDisk(diskToDelete string) error
// GetAutoLabelsForPD returns labels to apply to PersistentVolume
// representing this PD, namely failure domain and zone.
GetAutoLabelsForPD(name string) (map[string]string, error)
}
type instRefSlice []*compute.InstanceReference
func (p instRefSlice) Len() int { return len(p) }
@ -234,6 +262,7 @@ func newGCECloud(config io.Reader) (*GCECloud, error) {
tokenSource := google.ComputeTokenSource("")
var nodeTags []string
var nodeInstancePrefix string
if config != nil {
var cfg Config
if err := gcfg.ReadInto(&cfg, config); err != nil {
@ -252,22 +281,23 @@ func newGCECloud(config io.Reader) (*GCECloud, error) {
}
}
if cfg.Global.TokenURL != "" {
tokenSource = newAltTokenSource(cfg.Global.TokenURL, cfg.Global.TokenBody)
tokenSource = NewAltTokenSource(cfg.Global.TokenURL, cfg.Global.TokenBody)
}
nodeTags = cfg.Global.NodeTags
nodeInstancePrefix = cfg.Global.NodeInstancePrefix
if cfg.Global.Multizone {
managedZones = nil // Use all zones in region
}
}
return CreateGCECloud(projectID, region, zone, managedZones, networkURL, nodeTags, tokenSource, true /* useMetadataServer */)
return CreateGCECloud(projectID, region, zone, managedZones, networkURL, nodeTags, nodeInstancePrefix, tokenSource, true /* useMetadataServer */)
}
// Creates a GCECloud object using the specified parameters.
// If no networkUrl is specified, loads networkName via rest call.
// If no tokenSource is specified, uses oauth2.DefaultTokenSource.
// If managedZones is nil / empty all zones in the region will be managed.
func CreateGCECloud(projectID, region, zone string, managedZones []string, networkURL string, nodeTags []string, tokenSource oauth2.TokenSource, useMetadataServer bool) (*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(
@ -322,6 +352,7 @@ func CreateGCECloud(projectID, region, zone string, managedZones []string, netwo
managedZones: managedZones,
networkURL: networkURL,
nodeTags: nodeTags,
nodeInstancePrefix: nodeInstancePrefix,
useMetadataServer: useMetadataServer,
operationPollRateLimiter: operationPollRateLimiter,
}, nil
@ -401,19 +432,33 @@ func (gce *GCECloud) waitForOp(op *compute.Operation, getOperation func(operatio
return getErrorFromOp(op)
}
opStart := time.Now()
opName := op.Name
return wait.Poll(operationPollInterval, operationPollTimeoutDuration, func() (bool, error) {
start := time.Now()
gce.operationPollRateLimiter.Accept()
duration := time.Now().Sub(start)
if duration > 5*time.Second {
glog.Infof("pollOperation: waited %v for %v", duration, opName)
glog.Infof("pollOperation: throttled %v for %v", duration, opName)
}
pollOp, err := getOperation(opName)
if err != nil {
glog.Warningf("GCE poll operation %s failed: pollOp: [%v] err: [%v] getErrorFromOp: [%v]", opName, pollOp, err, getErrorFromOp(pollOp))
}
return opIsDone(pollOp), getErrorFromOp(pollOp)
done := opIsDone(pollOp)
if done {
duration := time.Now().Sub(opStart)
if duration > 1*time.Minute {
// Log the JSON. It's cleaner than the %v structure.
enc, err := pollOp.MarshalJSON()
if err != nil {
glog.Warningf("waitForOperation: long operation (%v): %v (failed to encode to JSON: %v)", duration, pollOp, err)
} else {
glog.Infof("waitForOperation: long operation (%v): %v", duration, string(enc))
}
}
}
return done, getErrorFromOp(pollOp)
})
}
@ -480,7 +525,7 @@ func isHTTPErrorCode(err error, code int) bool {
// Due to an interesting series of design decisions, this handles both creating
// new load balancers and updating existing load balancers, recognizing when
// each is needed.
func (gce *GCECloud) EnsureLoadBalancer(apiService *api.Service, hostNames []string, annotations map[string]string) (*api.LoadBalancerStatus, error) {
func (gce *GCECloud) EnsureLoadBalancer(apiService *api.Service, hostNames []string) (*api.LoadBalancerStatus, error) {
if len(hostNames) == 0 {
return nil, fmt.Errorf("Cannot EnsureLoadBalancer() with no hosts")
}
@ -501,7 +546,7 @@ func (gce *GCECloud) EnsureLoadBalancer(apiService *api.Service, hostNames []str
affinityType := apiService.Spec.SessionAffinity
serviceName := types.NamespacedName{Namespace: apiService.Namespace, Name: apiService.Name}
glog.V(2).Infof("EnsureLoadBalancer(%v, %v, %v, %v, %v, %v, %v)", loadBalancerName, gce.region, loadBalancerIP, portStr, hosts, serviceName, annotations)
glog.V(2).Infof("EnsureLoadBalancer(%v, %v, %v, %v, %v, %v, %v)", loadBalancerName, gce.region, loadBalancerIP, portStr, hosts, serviceName, apiService.Annotations)
// Check if the forwarding rule exists, and if so, what its IP is.
fwdRuleExists, fwdRuleNeedsUpdate, fwdRuleIP, err := gce.forwardingRuleNeedsUpdate(loadBalancerName, gce.region, loadBalancerIP, ports)
@ -611,7 +656,7 @@ func (gce *GCECloud) EnsureLoadBalancer(apiService *api.Service, hostNames []str
// is because the forwarding rule is used as the indicator that the load
// balancer is fully created - it's what getLoadBalancer checks for.
// Check if user specified the allow source range
sourceRanges, err := service.GetLoadBalancerSourceRanges(annotations)
sourceRanges, err := service.GetLoadBalancerSourceRanges(apiService)
if err != nil {
return nil, err
}
@ -938,10 +983,16 @@ func (gce *GCECloud) firewallObject(name, region, desc string, sourceRanges nets
for ix := range ports {
allowedPorts[ix] = strconv.Itoa(int(ports[ix].Port))
}
hostTags, err := gce.computeHostTags(hosts)
if err != nil {
return nil, err
// If the node tags to be used for this cluster have been predefined in the
// provider config, just use them. Otherwise, invoke computeHostTags method to get the tags.
hostTags := gce.nodeTags
if len(hostTags) == 0 {
var err error
if hostTags, err = gce.computeHostTags(hosts); err != nil {
return nil, fmt.Errorf("No node tags supplied and also failed to parse the given lists of hosts for tags. Abort creating firewall rule.")
}
}
firewall := &compute.Firewall{
Name: makeFirewallName(name),
Description: desc,
@ -963,21 +1014,28 @@ func (gce *GCECloud) firewallObject(name, region, desc string, sourceRanges nets
return firewall, nil
}
// If the node tags to be used for this cluster have been predefined in the
// provider config, just use them. Otherwise, grab all tags from all relevant
// instances:
// ComputeHostTags grabs all tags from all instances being added to the pool.
// * The longest tag that is a prefix of the instance name is used
// * If any instance has a prefix tag, all instances must
// * If no instances have a prefix tag, no tags are used
// * If any instance has no matching prefix tag, return error
// Invoking this method to get host tags is risky since it depends on the format
// of the host names in the cluster. Only use it as a fallback if gce.nodeTags
// is unspecified
func (gce *GCECloud) computeHostTags(hosts []*gceInstance) ([]string, error) {
if len(gce.nodeTags) > 0 {
return gce.nodeTags, nil
}
// TODO: We could store the tags in gceInstance, so we could have already fetched it
hostNamesByZone := make(map[string][]string)
hostNamesByZone := make(map[string]map[string]bool) // map of zones -> map of names -> bool (for easy lookup)
nodeInstancePrefix := gce.nodeInstancePrefix
for _, host := range hosts {
hostNamesByZone[host.Zone] = append(hostNamesByZone[host.Zone], host.Name)
if !strings.HasPrefix(host.Name, gce.nodeInstancePrefix) {
glog.Warningf("instance '%s' does not conform to prefix '%s', ignoring filter", host, gce.nodeInstancePrefix)
nodeInstancePrefix = ""
}
z, ok := hostNamesByZone[host.Zone]
if !ok {
z = make(map[string]bool)
hostNamesByZone[host.Zone] = z
}
z[host.Name] = true
}
tags := sets.NewString()
@ -988,11 +1046,14 @@ func (gce *GCECloud) computeHostTags(hosts []*gceInstance) ([]string, error) {
for ; page == 0 || (pageToken != "" && page < maxPages); page++ {
listCall := gce.service.Instances.List(gce.projectID, zone)
// Add the filter for hosts
listCall = listCall.Filter("name eq (" + strings.Join(hostNames, "|") + ")")
if nodeInstancePrefix != "" {
// Add the filter for hosts
listCall = listCall.Filter("name eq " + nodeInstancePrefix + ".*")
}
// Add the fields we want
listCall = listCall.Fields("items(name,tags)")
// TODO(zmerlynn): Internal bug 29524655
// listCall = listCall.Fields("items(name,tags)")
if pageToken != "" {
listCall = listCall.PageToken(pageToken)
@ -1004,6 +1065,10 @@ func (gce *GCECloud) computeHostTags(hosts []*gceInstance) ([]string, error) {
}
pageToken = res.NextPageToken
for _, instance := range res.Items {
if !hostNames[instance.Name] {
continue
}
longest_tag := ""
for _, tag := range instance.Tags.Items {
if strings.HasPrefix(instance.Name, tag) && len(tag) > len(longest_tag) {
@ -1012,8 +1077,8 @@ func (gce *GCECloud) computeHostTags(hosts []*gceInstance) ([]string, error) {
}
if len(longest_tag) > 0 {
tags.Insert(longest_tag)
} else if len(tags) > 0 {
return nil, fmt.Errorf("Some, but not all, instances have prefix tags (%s is missing)", instance.Name)
} else {
return nil, fmt.Errorf("Could not find any tag that is a prefix of instance name for instance %s", instance.Name)
}
}
}
@ -1021,11 +1086,9 @@ func (gce *GCECloud) computeHostTags(hosts []*gceInstance) ([]string, error) {
glog.Errorf("computeHostTags exceeded maxPages=%d for Instances.List: truncating.", maxPages)
}
}
if len(tags) == 0 {
glog.V(2).Info("No instances had tags, creating rule without target tags")
return nil, fmt.Errorf("No instances found")
}
return tags.List(), nil
}
@ -2389,21 +2452,20 @@ type gceDisk struct {
// 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)
remaining := len(names)
nodeInstancePrefix := gce.nodeInstancePrefix
for _, name := range names {
name = canonicalizeInstanceName(name)
if !strings.HasPrefix(name, gce.nodeInstancePrefix) {
glog.Warningf("instance '%s' does not conform to prefix '%s', removing filter", name, gce.nodeInstancePrefix)
nodeInstancePrefix = ""
}
instances[name] = nil
}
for _, zone := range gce.managedZones {
var remaining []string
for name, instance := range instances {
if instance == nil {
remaining = append(remaining, name)
}
}
if len(remaining) == 0 {
if remaining == 0 {
break
}
@ -2412,10 +2474,13 @@ func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error)
for ; page == 0 || (pageToken != "" && page < maxPages); page++ {
listCall := gce.service.Instances.List(gce.projectID, zone)
// Add the filter for hosts
listCall = listCall.Filter("name eq (" + strings.Join(remaining, "|") + ")")
if nodeInstancePrefix != "" {
// Add the filter for hosts
listCall = listCall.Filter("name eq " + nodeInstancePrefix + ".*")
}
listCall = listCall.Fields("items(name,id,disks,machineType)")
// TODO(zmerlynn): Internal bug 29524655
// listCall = listCall.Fields("items(name,id,disks,machineType)")
if pageToken != "" {
listCall.PageToken(pageToken)
}
@ -2427,6 +2492,10 @@ func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error)
pageToken = res.NextPageToken
for _, i := range res.Items {
name := i.Name
if _, ok := instances[name]; !ok {
continue
}
instance := &gceInstance{
Zone: zone,
Name: name,
@ -2435,6 +2504,7 @@ func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error)
Type: lastComponent(i.MachineType),
}
instances[name] = instance
remaining--
}
}
if page >= maxPages {

View file

@ -57,14 +57,14 @@ func init() {
prometheus.MustRegister(getTokenFailCounter)
}
type altTokenSource struct {
type AltTokenSource struct {
oauthClient *http.Client
tokenURL string
tokenBody string
throttle flowcontrol.RateLimiter
}
func (a *altTokenSource) Token() (*oauth2.Token, error) {
func (a *AltTokenSource) Token() (*oauth2.Token, error) {
a.throttle.Accept()
getTokenCounter.Inc()
t, err := a.token()
@ -74,7 +74,7 @@ func (a *altTokenSource) Token() (*oauth2.Token, error) {
return t, err
}
func (a *altTokenSource) token() (*oauth2.Token, error) {
func (a *AltTokenSource) token() (*oauth2.Token, error) {
req, err := http.NewRequest("POST", a.tokenURL, strings.NewReader(a.tokenBody))
if err != nil {
return nil, err
@ -100,9 +100,9 @@ func (a *altTokenSource) token() (*oauth2.Token, error) {
}, nil
}
func newAltTokenSource(tokenURL, tokenBody string) oauth2.TokenSource {
func NewAltTokenSource(tokenURL, tokenBody string) oauth2.TokenSource {
client := oauth2.NewClient(oauth2.NoContext, google.ComputeTokenSource(""))
a := &altTokenSource{
a := &AltTokenSource{
oauthClient: client,
tokenURL: tokenURL,
tokenBody: tokenBody,