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 }