// ClientConfigForVersion returns the correct config for a server func (c *ClientCache) ClientConfigForVersion(version string) (*client.Config, error) { if c.defaultConfig == nil { config, err := c.loader.ClientConfig() if err != nil { return nil, err } c.defaultConfig = config if c.matchVersion { if err := client.MatchesServerVersion(c.defaultClient, config); err != nil { return nil, err } } } if config, ok := c.configs[version]; ok { return config, nil } // TODO: have a better config copy method config := *c.defaultConfig negotiatedVersion, err := client.NegotiateVersion(c.defaultClient, &config, version, registered.RegisteredVersions) if err != nil { return nil, err } config.Version = negotiatedVersion client.SetKubernetesDefaults(&config) c.configs[version] = &config return &config, nil }
func TestNegotiateVersion(t *testing.T) { tests := []struct { name, version, expectedVersion string serverVersions []string clientVersions []string config *unversioned.Config expectErr bool }{ { name: "server supports client default", version: "version1", config: &unversioned.Config{}, serverVersions: []string{"version1", testapi.Default.Version()}, clientVersions: []string{"version1", testapi.Default.Version()}, expectedVersion: "version1", expectErr: false, }, { name: "server falls back to client supported", version: testapi.Default.Version(), config: &unversioned.Config{}, serverVersions: []string{"version1"}, clientVersions: []string{"version1", testapi.Default.Version()}, expectedVersion: "version1", expectErr: false, }, { name: "explicit version supported", version: "", config: &unversioned.Config{Version: testapi.Default.Version()}, serverVersions: []string{"version1", testapi.Default.Version()}, clientVersions: []string{"version1", testapi.Default.Version()}, expectedVersion: testapi.Default.Version(), expectErr: false, }, { name: "explicit version not supported", version: "", config: &unversioned.Config{Version: testapi.Default.Version()}, serverVersions: []string{"version1"}, clientVersions: []string{"version1", testapi.Default.Version()}, expectedVersion: "", expectErr: true, }, } codec := testapi.Default.Codec() for _, test := range tests { fakeClient := &fake.RESTClient{ Codec: codec, Resp: &http.Response{ StatusCode: 200, Body: objBody(&unversioned_api.APIVersions{Versions: test.serverVersions}), }, Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{StatusCode: 200, Body: objBody(&unversioned_api.APIVersions{Versions: test.serverVersions})}, nil }), } c := unversioned.NewOrDie(test.config) c.Client = fakeClient.Client response, err := unversioned.NegotiateVersion(c, test.config, test.version, test.clientVersions) if err == nil && test.expectErr { t.Errorf("expected error, got nil for [%s].", test.name) } if err != nil && !test.expectErr { t.Errorf("unexpected error for [%s]: %v.", test.name, err) } if response != test.expectedVersion { t.Errorf("expected version %s, got %s.", test.expectedVersion, response) } } }
func TestNegotiateVersion(t *testing.T) { refusedErr := fmt.Errorf("connection refused") tests := []struct { name, version, expectedVersion string serverVersions []string clientVersions []string config *unversioned.Config expectErr func(err error) bool sendErr error }{ { name: "server supports client default", version: "version1", config: &unversioned.Config{}, serverVersions: []string{"version1", testapi.Default.Version()}, clientVersions: []string{"version1", testapi.Default.Version()}, expectedVersion: "version1", }, { name: "server falls back to client supported", version: testapi.Default.Version(), config: &unversioned.Config{}, serverVersions: []string{"version1"}, clientVersions: []string{"version1", testapi.Default.Version()}, expectedVersion: "version1", }, { name: "explicit version supported", version: "", config: &unversioned.Config{Version: testapi.Default.Version()}, serverVersions: []string{"version1", testapi.Default.Version()}, clientVersions: []string{"version1", testapi.Default.Version()}, expectedVersion: testapi.Default.Version(), }, { name: "explicit version not supported", version: "", config: &unversioned.Config{Version: testapi.Default.Version()}, serverVersions: []string{"version1"}, clientVersions: []string{"version1", testapi.Default.Version()}, expectErr: func(err error) bool { return strings.Contains(err.Error(), `server does not support API version "v1"`) }, }, { name: "connection refused error", config: &unversioned.Config{Version: testapi.Default.Version()}, serverVersions: []string{"version1"}, clientVersions: []string{"version1", testapi.Default.Version()}, sendErr: refusedErr, expectErr: func(err error) bool { return err == refusedErr }, }, } codec := testapi.Default.Codec() for _, test := range tests { fakeClient := &fake.RESTClient{ Codec: codec, Resp: &http.Response{ StatusCode: 200, Body: objBody(&unversionedapi.APIVersions{Versions: test.serverVersions}), }, Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { if test.sendErr != nil { return nil, test.sendErr } return &http.Response{StatusCode: 200, Body: objBody(&unversionedapi.APIVersions{Versions: test.serverVersions})}, nil }), } c := unversioned.NewOrDie(test.config) c.Client = fakeClient.Client response, err := unversioned.NegotiateVersion(c, test.config, test.version, test.clientVersions) if err == nil && test.expectErr != nil { t.Errorf("expected error, got nil for [%s].", test.name) } if err != nil { if test.expectErr == nil || !test.expectErr(err) { t.Errorf("unexpected error for [%s]: %v.", test.name, err) } continue } if response != test.expectedVersion { t.Errorf("expected version %s, got %s.", test.expectedVersion, response) } } }