github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/client.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package unversioned
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"net"
    23  	"net/url"
    24  	"strings"
    25  
    26  	"github.com/emicklei/go-restful/swagger"
    27  
    28  	"k8s.io/kubernetes/pkg/api"
    29  	"k8s.io/kubernetes/pkg/api/unversioned"
    30  	"k8s.io/kubernetes/pkg/version"
    31  )
    32  
    33  // Interface holds the methods for clients of Kubernetes,
    34  // an interface to allow mock testing.
    35  type Interface interface {
    36  	PodsNamespacer
    37  	PodTemplatesNamespacer
    38  	ReplicationControllersNamespacer
    39  	ServicesNamespacer
    40  	EndpointsNamespacer
    41  	VersionInterface
    42  	NodesInterface
    43  	EventNamespacer
    44  	LimitRangesNamespacer
    45  	ResourceQuotasNamespacer
    46  	ServiceAccountsNamespacer
    47  	SecretsNamespacer
    48  	NamespacesInterface
    49  	PersistentVolumesInterface
    50  	PersistentVolumeClaimsNamespacer
    51  	ComponentStatusesInterface
    52  	SwaggerSchemaInterface
    53  	Extensions() ExtensionsInterface
    54  	Discovery() DiscoveryInterface
    55  }
    56  
    57  func (c *Client) ReplicationControllers(namespace string) ReplicationControllerInterface {
    58  	return newReplicationControllers(c, namespace)
    59  }
    60  
    61  func (c *Client) Nodes() NodeInterface {
    62  	return newNodes(c)
    63  }
    64  
    65  func (c *Client) Events(namespace string) EventInterface {
    66  	return newEvents(c, namespace)
    67  }
    68  
    69  func (c *Client) Endpoints(namespace string) EndpointsInterface {
    70  	return newEndpoints(c, namespace)
    71  }
    72  
    73  func (c *Client) Pods(namespace string) PodInterface {
    74  	return newPods(c, namespace)
    75  }
    76  
    77  func (c *Client) PodTemplates(namespace string) PodTemplateInterface {
    78  	return newPodTemplates(c, namespace)
    79  }
    80  
    81  func (c *Client) Services(namespace string) ServiceInterface {
    82  	return newServices(c, namespace)
    83  }
    84  func (c *Client) LimitRanges(namespace string) LimitRangeInterface {
    85  	return newLimitRanges(c, namespace)
    86  }
    87  
    88  func (c *Client) ResourceQuotas(namespace string) ResourceQuotaInterface {
    89  	return newResourceQuotas(c, namespace)
    90  }
    91  
    92  func (c *Client) ServiceAccounts(namespace string) ServiceAccountsInterface {
    93  	return newServiceAccounts(c, namespace)
    94  }
    95  
    96  func (c *Client) Secrets(namespace string) SecretsInterface {
    97  	return newSecrets(c, namespace)
    98  }
    99  
   100  func (c *Client) Namespaces() NamespaceInterface {
   101  	return newNamespaces(c)
   102  }
   103  
   104  func (c *Client) PersistentVolumes() PersistentVolumeInterface {
   105  	return newPersistentVolumes(c)
   106  }
   107  
   108  func (c *Client) PersistentVolumeClaims(namespace string) PersistentVolumeClaimInterface {
   109  	return newPersistentVolumeClaims(c, namespace)
   110  }
   111  
   112  func (c *Client) ComponentStatuses() ComponentStatusInterface {
   113  	return newComponentStatuses(c)
   114  }
   115  
   116  // VersionInterface has a method to retrieve the server version.
   117  type VersionInterface interface {
   118  	ServerVersion() (*version.Info, error)
   119  	ServerAPIVersions() (*unversioned.APIVersions, error)
   120  }
   121  
   122  // APIStatus is exposed by errors that can be converted to an api.Status object
   123  // for finer grained details.
   124  type APIStatus interface {
   125  	Status() unversioned.Status
   126  }
   127  
   128  // Client is the implementation of a Kubernetes client.
   129  type Client struct {
   130  	*RESTClient
   131  	*ExtensionsClient
   132  	// TODO: remove this when we re-structure pkg/client.
   133  	*DiscoveryClient
   134  }
   135  
   136  // ServerVersion retrieves and parses the server's version.
   137  func (c *Client) ServerVersion() (*version.Info, error) {
   138  	body, err := c.Get().AbsPath("/version").Do().Raw()
   139  	if err != nil {
   140  		return nil, err
   141  	}
   142  	var info version.Info
   143  	err = json.Unmarshal(body, &info)
   144  	if err != nil {
   145  		return nil, fmt.Errorf("got '%s': %v", string(body), err)
   146  	}
   147  	return &info, nil
   148  }
   149  
   150  // ServerAPIVersions retrieves and parses the list of API versions the server supports.
   151  func (c *Client) ServerAPIVersions() (*unversioned.APIVersions, error) {
   152  	body, err := c.Get().AbsPath("/api").Do().Raw()
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  	var v unversioned.APIVersions
   157  	err = json.Unmarshal(body, &v)
   158  	if err != nil {
   159  		return nil, fmt.Errorf("got '%s': %v", string(body), err)
   160  	}
   161  	return &v, nil
   162  }
   163  
   164  type ComponentValidatorInterface interface {
   165  	ValidateComponents() (*api.ComponentStatusList, error)
   166  }
   167  
   168  // ValidateComponents retrieves and parses the master's self-monitored cluster state.
   169  // TODO: This should hit the versioned endpoint when that is implemented.
   170  func (c *Client) ValidateComponents() (*api.ComponentStatusList, error) {
   171  	body, err := c.Get().AbsPath("/validate").DoRaw()
   172  	if err != nil {
   173  		return nil, err
   174  	}
   175  
   176  	statuses := []api.ComponentStatus{}
   177  	if err := json.Unmarshal(body, &statuses); err != nil {
   178  		return nil, fmt.Errorf("got '%s': %v", string(body), err)
   179  	}
   180  	return &api.ComponentStatusList{Items: statuses}, nil
   181  }
   182  
   183  // SwaggerSchemaInterface has a method to retrieve the swagger schema. Used in
   184  // client.Interface
   185  type SwaggerSchemaInterface interface {
   186  	SwaggerSchema(groupVersion string) (*swagger.ApiDeclaration, error)
   187  }
   188  
   189  // SwaggerSchema retrieves and parses the swagger API schema the server supports.
   190  func (c *Client) SwaggerSchema(groupVersion string) (*swagger.ApiDeclaration, error) {
   191  	if groupVersion == "" {
   192  		return nil, fmt.Errorf("groupVersion cannot be empty")
   193  	}
   194  
   195  	groupList, err := c.Discovery().ServerGroups()
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  	groupVersions := ExtractGroupVersions(groupList)
   200  	// This check also takes care the case that kubectl is newer than the running endpoint
   201  	if stringDoesntExistIn(groupVersion, groupVersions) {
   202  		return nil, fmt.Errorf("API version: %s is not supported by the server. Use one of: %v", groupVersion, groupVersions)
   203  	}
   204  	var path string
   205  	if groupVersion == "v1" {
   206  		path = "/swaggerapi/api/" + groupVersion
   207  	} else {
   208  		path = "/swaggerapi/apis/" + groupVersion
   209  	}
   210  
   211  	body, err := c.Get().AbsPath(path).Do().Raw()
   212  	if err != nil {
   213  		return nil, err
   214  	}
   215  	var schema swagger.ApiDeclaration
   216  	err = json.Unmarshal(body, &schema)
   217  	if err != nil {
   218  		return nil, fmt.Errorf("got '%s': %v", string(body), err)
   219  	}
   220  	return &schema, nil
   221  }
   222  
   223  func stringDoesntExistIn(str string, slice []string) bool {
   224  	for _, s := range slice {
   225  		if s == str {
   226  			return false
   227  		}
   228  	}
   229  	return true
   230  }
   231  
   232  // IsTimeout tests if this is a timeout error in the underlying transport.
   233  // This is unbelievably ugly.
   234  // See: http://stackoverflow.com/questions/23494950/specifically-check-for-timeout-error for details
   235  func IsTimeout(err error) bool {
   236  	if err == nil {
   237  		return false
   238  	}
   239  	switch err := err.(type) {
   240  	case *url.Error:
   241  		if err, ok := err.Err.(net.Error); ok {
   242  			return err.Timeout()
   243  		}
   244  	case net.Error:
   245  		return err.Timeout()
   246  	}
   247  
   248  	if strings.Contains(err.Error(), "use of closed network connection") {
   249  		return true
   250  	}
   251  	return false
   252  }
   253  
   254  func (c *Client) Extensions() ExtensionsInterface {
   255  	return c.ExtensionsClient
   256  }
   257  
   258  func (c *Client) Discovery() DiscoveryInterface {
   259  	return c.DiscoveryClient
   260  }