-
Notifications
You must be signed in to change notification settings - Fork 40.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ignore error when discovering server supported groupVersions and resources #16082
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
) | ||
|
||
|
@@ -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 | ||
|
@@ -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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. move this before the the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
nm, that was wrong. |
||
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 | ||
|
@@ -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" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Code like this is worrying me. Is the next version of the kube API going to have a group? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't follow your question, could you clarify? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When kube gets a if groupVersion == "v1" || groupVersion == "v2"{ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. I think the plan is breaking the kube API to smaller groups and each group evolves in their own pace. We won't have a monolithic v2 API. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, that won't work. I will fix it in another PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, "v1" is the only exception to the group/version format we ever intend to have. |
||
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 | ||
} | ||
|
@@ -155,6 +141,8 @@ func (d *DiscoveryClient) ServerResources() (map[string]*unversioned.APIResource | |
func setDiscoveryDefaults(config *Config) error { | ||
config.Prefix = "" | ||
config.Version = "" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @deads2k Version is set to empty. The base URL will be to the host root. |
||
// Discovery client deals with unversioned objects, so we use api.Codec. | ||
config.Codec = api.Codec | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changed to api.Codec |
||
return nil | ||
} | ||
|
||
|
@@ -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 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @deads2k There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cc @krousey another thing to fix by splitting layers... |
||
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{} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ package conversion | |
import ( | ||
"errors" | ||
"fmt" | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not necessary, but the change is consistent with other files, so I kept this change. |
||
"github.com/ugorji/go/codec" | ||
) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not all errors are ignorable. You probably only want to ignore 404's, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I will fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@deads2k this is fixed. PTAL. Thank you.