Skip to content

Commit

Permalink
Merge pull request kubernetes#16082 from caesarxuchao/discover-1.0-se…
Browse files Browse the repository at this point in the history
…rver-new

Auto commit by PR queue bot
  • Loading branch information
k8s-merge-robot committed Oct 30, 2015
2 parents 88008de + 69932ae commit a86d878
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 46 deletions.
70 changes: 70 additions & 0 deletions pkg/client/unversioned/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,76 @@ func TestGetServerVersion(t *testing.T) {
}
}

func TestGetServerGroupsWithV1Server(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
var obj interface{}
switch req.URL.Path {
case "/api":
obj = &unversioned.APIVersions{
Versions: []string{
"v1",
},
}
default:
w.WriteHeader(http.StatusNotFound)
return
}
output, err := json.Marshal(obj)
if err != nil {
t.Errorf("unexpected encoding error: %v", err)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(output)
}))
client := NewOrDie(&Config{Host: server.URL})
// ServerGroups should not return an error even if server returns error at /api and /apis
apiGroupList, err := client.Discovery().ServerGroups()
if err != nil {
t.Errorf("unexpected error: %v", err)
}
groupVersions := ExtractGroupVersions(apiGroupList)
if !reflect.DeepEqual(groupVersions, []string{"v1"}) {
t.Errorf("expected: %q, got: %q", []string{"v1"}, groupVersions)
}
}

func TestGetServerResourcesWithV1Server(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
var obj interface{}
switch req.URL.Path {
case "/api":
obj = &unversioned.APIVersions{
Versions: []string{
"v1",
},
}
default:
w.WriteHeader(http.StatusNotFound)
return
}
output, err := json.Marshal(obj)
if err != nil {
t.Errorf("unexpected encoding error: %v", err)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(output)
}))
client := NewOrDie(&Config{Host: server.URL})
// ServerResources should not return an error even if server returns error at /api/v1.
resourceMap, err := client.Discovery().ServerResources()
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if _, found := resourceMap["v1"]; !found {
t.Errorf("missing v1 in resource map")
}

}

func TestGetServerResources(t *testing.T) {
stable := unversioned.APIResourceList{
GroupVersion: "v1",
Expand Down
75 changes: 29 additions & 46 deletions pkg/client/unversioned/discovery_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@ limitations under the License.
package unversioned

import (
"encoding/json"
"fmt"
"net/http"
"net/url"

"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/unversioned"
)

Expand Down Expand Up @@ -50,8 +49,7 @@ type ServerResourcesInterface interface {
// DiscoveryClient implements the functions that dicovery server-supported API groups,
// versions and resources.
type DiscoveryClient struct {
httpClient HTTPClient
baseURL url.URL
*RESTClient
}

// Convert unversioned.APIVersions to unversioned.APIGroup. APIVersions is used by legacy v1, so
Expand All @@ -71,42 +69,29 @@ func apiVersionsToAPIGroup(apiVersions *unversioned.APIVersions) (apiGroup unver
return
}

func (d *DiscoveryClient) get(url string) (resp *http.Response, err error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
return d.httpClient.Do(req)
}

// ServerGroups returns the supported groups, with information like supported versions and the
// preferred version.
func (d *DiscoveryClient) ServerGroups() (apiGroupList *unversioned.APIGroupList, err error) {
// Get the groupVersions exposed at /api
url := d.baseURL
url.Path = "/api"
resp, err := d.get(url.String())
if err != nil {
return nil, err
v := &unversioned.APIVersions{}
err = d.Get().AbsPath("/api").Do().Into(v)
apiGroup := unversioned.APIGroup{}
if err == nil {
apiGroup = apiVersionsToAPIGroup(v)
}
var v unversioned.APIVersions
defer resp.Body.Close()
err = json.NewDecoder(resp.Body).Decode(&v)
if err != nil {
return nil, fmt.Errorf("unexpected error: %v", err)
if err != nil && !errors.IsNotFound(err) && !errors.IsForbidden(err) {
return nil, err
}
apiGroup := apiVersionsToAPIGroup(&v)

// Get the groupVersions exposed at /apis
url.Path = "/apis"
resp2, err := d.get(url.String())
if err != nil {
apiGroupList = &unversioned.APIGroupList{}
err = d.Get().AbsPath("/apis").Do().Into(apiGroupList)
if err != nil && !errors.IsNotFound(err) && !errors.IsForbidden(err) {
return nil, err
}
defer resp2.Body.Close()
apiGroupList = &unversioned.APIGroupList{}
if err = json.NewDecoder(resp2.Body).Decode(&apiGroupList); err != nil {
return nil, fmt.Errorf("unexpected error: %v", err)
// to be compatible with a v1.0 server, if it's a 403 or 404, ignore and return whatever we got from /api
if err != nil && (errors.IsNotFound(err) || errors.IsForbidden(err)) {
apiGroupList = &unversioned.APIGroupList{}
}

// append the group retrieved from /api to the list
Expand All @@ -116,20 +101,21 @@ func (d *DiscoveryClient) ServerGroups() (apiGroupList *unversioned.APIGroupList

// ServerResourcesForGroupVersion returns the supported resources for a group and version.
func (d *DiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (resources *unversioned.APIResourceList, err error) {
url := d.baseURL
url := url.URL{}
if groupVersion == "v1" {
url.Path = "/api/" + groupVersion
} else {
url.Path = "/apis/" + groupVersion
}
resp, err := d.get(url.String())
if err != nil {
return nil, err
}
defer resp.Body.Close()
resources = &unversioned.APIResourceList{}
if err = json.NewDecoder(resp.Body).Decode(resources); err != nil {
return nil, fmt.Errorf("unexpected error: %v", err)
err = d.Get().AbsPath(url.String()).Do().Into(resources)
if err != nil {
// ignore 403 or 404 error to be compatible with an v1.0 server.
if groupVersion == "v1" && (errors.IsNotFound(err) || errors.IsForbidden(err)) {
return resources, nil
} else {
return nil, err
}
}
return resources, nil
}
Expand All @@ -155,6 +141,8 @@ func (d *DiscoveryClient) ServerResources() (map[string]*unversioned.APIResource
func setDiscoveryDefaults(config *Config) error {
config.Prefix = ""
config.Version = ""
// Discovery client deals with unversioned objects, so we use api.Codec.
config.Codec = api.Codec
return nil
}

Expand All @@ -165,11 +153,6 @@ func NewDiscoveryClient(c *Config) (*DiscoveryClient, error) {
if err := setDiscoveryDefaults(&config); err != nil {
return nil, err
}
transport, err := TransportFor(c)
if err != nil {
return nil, err
}
client := &http.Client{Transport: transport}
baseURL, err := defaultServerUrlFor(c)
return &DiscoveryClient{client, *baseURL}, nil
client, err := UnversionedRESTClientFor(&config)
return &DiscoveryClient{client}, err
}
25 changes: 25 additions & 0 deletions pkg/client/unversioned/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,31 @@ func RESTClientFor(config *Config) (*RESTClient, error) {
return client, nil
}

// UnversionedRESTClientFor is the same as RESTClientFor, except that it allows
// the config.Version to be empty.
func UnversionedRESTClientFor(config *Config) (*RESTClient, error) {
if config.Codec == nil {
return nil, fmt.Errorf("Codec is required when initializing a RESTClient")
}

baseURL, err := defaultServerUrlFor(config)
if err != nil {
return nil, err
}

client := NewRESTClient(baseURL, config.Version, config.Codec, config.QPS, config.Burst)

transport, err := TransportFor(config)
if err != nil {
return nil, err
}

if transport != http.DefaultTransport {
client.Client = &http.Client{Transport: transport}
}
return client, nil
}

var (
// tlsTransports stores reusable round trippers with custom TLSClientConfig options
tlsTransports = map[string]*http.Transport{}
Expand Down
1 change: 1 addition & 0 deletions pkg/conversion/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package conversion
import (
"errors"
"fmt"

"github.com/ugorji/go/codec"
)

Expand Down

0 comments on commit a86d878

Please sign in to comment.