Merge pull request #9762 from jlowdermilk/negotiate-api-version

kubectl negotiates api version to use based on client,server supported versions
This commit is contained in:
Brendan Burns
2015-06-16 11:18:08 -07:00
4 changed files with 105 additions and 27 deletions

View File

@@ -30,8 +30,11 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/registered"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/version"
"github.com/golang/glog"
)
// Config holds the common attributes that can be passed to a Kubernetes client on
@@ -138,6 +141,9 @@ func New(c *Config) (*Client, error) {
return &Client{client}, nil
}
// MatchesServerVersion queries the server to compares the build version
// (git hash) of the client with the server's build version. It returns an error
// if it failed to contact the server or if the versions are not an exact match.
func MatchesServerVersion(c *Config) error {
client, err := New(c)
if err != nil {
@@ -156,6 +162,66 @@ func MatchesServerVersion(c *Config) error {
return nil
}
// NegotiateVersion queries the server's supported api versions to find
// a version that both client and server support.
// - If no version is provided, try the client's registered versions in order of
// preference.
// - If version is provided, but not default config (explicitly requested via
// commandline flag), and is unsupported by the server, print a warning to
// stderr and try client's registered versions in order of preference.
// - If version is config default, and the server does not support it,
// return an error.
func NegotiateVersion(c *Config, version string) (string, error) {
client, err := New(c)
if err != nil {
return "", err
}
clientVersions := util.StringSet{}
for _, v := range registered.RegisteredVersions {
clientVersions.Insert(v)
}
apiVersions, err := client.ServerAPIVersions()
if err != nil {
return "", fmt.Errorf("couldn't read version from server: %v\n", err)
}
serverVersions := util.StringSet{}
for _, v := range apiVersions.Versions {
serverVersions.Insert(v)
}
// If no version requested, use config version (may also be empty).
if len(version) == 0 {
version = c.Version
}
// If version explicitly requested verify that both client and server support it.
// If server does not support warn, but try to negotiate a lower version.
if len(version) != 0 {
if !clientVersions.Has(version) {
return "", fmt.Errorf("Client does not support API version '%s'. Client supported API versions: %v", version, clientVersions)
}
if serverVersions.Has(version) {
return version, nil
}
// If we are using an explicit config version the server does not support, fail.
if version == c.Version {
return "", fmt.Errorf("Server does not support API version '%s'.", version)
}
}
for _, clientVersion := range registered.RegisteredVersions {
if serverVersions.Has(clientVersion) {
// Version was not explicitly requested in command config (--api-version).
// Ok to fall back to a supported version with a warning.
if len(version) != 0 {
glog.Warningf("Server does not support API version '%s'. Falling back to '%s'.", version, clientVersion)
}
return clientVersion, nil
}
}
return "", fmt.Errorf("Failed to negotiate an api version. Server supports: %v. Client supports: %v.",
serverVersions, registered.RegisteredVersions)
}
// NewOrDie creates a Kubernetes client and panics if the provided API version is not recognized.
func NewOrDie(c *Config) *Client {
client, err := New(c)