From 13870c30c5891c588cd15adb801834a8bb3c9cf7 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 29 Sep 2016 21:57:25 -0400 Subject: [PATCH] Prevent KubernetesVersion 1.4 with classic networking --- upup/pkg/api/validation.go | 23 ++++++++++++++++- upup/pkg/api/versions.go | 34 ++++++++++++++++++++++++++ upup/pkg/fi/cloudup/validation_test.go | 22 ++++++++++++++++- 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 upup/pkg/api/versions.go diff --git a/upup/pkg/api/validation.go b/upup/pkg/api/validation.go index 7b8182e977..bc7eca1814 100644 --- a/upup/pkg/api/validation.go +++ b/upup/pkg/api/validation.go @@ -2,6 +2,7 @@ package api import ( "fmt" + "github.com/blang/semver" "k8s.io/kops/upup/pkg/fi" "k8s.io/kubernetes/pkg/util/validation" "k8s.io/kubernetes/pkg/util/validation/field" @@ -11,6 +12,8 @@ import ( ) func (c *Cluster) Validate(strict bool) error { + specField := field.NewPath("Spec") + var err error if c.Name == "" { @@ -199,7 +202,7 @@ func (c *Cluster) Validate(strict bool) error { if c.Spec.UpdatePolicy != nil { switch *c.Spec.UpdatePolicy { case UpdatePolicyExternal: - // Valid + // Valid default: return fmt.Errorf("unrecognized value for UpdatePolicy: %v", *c.Spec.UpdatePolicy) } @@ -274,6 +277,24 @@ func (c *Cluster) Validate(strict bool) error { } } + // KubernetesVersion + if c.Spec.KubernetesVersion == "" { + if strict { + return field.Required(specField.Child("KubernetesVersion"), "") + } + } else { + sv, err := ParseKubernetesVersion(c.Spec.KubernetesVersion) + if err != nil { + return field.Invalid(specField.Child("KubernetesVersion"), c.Spec.KubernetesVersion, "unable to determine kubernetes version") + } + + if sv.GTE(semver.Version{Major: 1, Minor: 4}) { + if c.Spec.Networking != nil && c.Spec.Networking.Classic != nil { + return field.Invalid(specField.Child("Networking"), "classic", "classic networking is not supported with kubernetes versions 1.4 and later") + } + } + } + return nil } diff --git a/upup/pkg/api/versions.go b/upup/pkg/api/versions.go new file mode 100644 index 0000000000..fd74aed737 --- /dev/null +++ b/upup/pkg/api/versions.go @@ -0,0 +1,34 @@ +package api + +import ( + "fmt" + "github.com/blang/semver" + "github.com/golang/glog" + "strings" +) + +func ParseKubernetesVersion(version string) (*semver.Version, error) { + sv, err := semver.ParseTolerant(version) + if err != nil { + glog.Warningf("error parsing kubernetes semver %q, falling back to string matching", version) + + v := strings.Trim(version, "v") + if strings.HasPrefix(v, "1.3.") { + sv = semver.Version{Major: 1, Minor: 3} + } else if strings.HasPrefix(v, "1.4.") { + sv = semver.Version{Major: 1, Minor: 4} + } else if strings.HasPrefix(v, "1.5.") { + sv = semver.Version{Major: 1, Minor: 5} + } else if strings.Contains(v, "/v1.3.") { + sv = semver.Version{Major: 1, Minor: 3} + } else if strings.Contains(v, "/v1.4.") { + sv = semver.Version{Major: 1, Minor: 4} + } else if strings.Contains(v, "/v1.5.") { + sv = semver.Version{Major: 1, Minor: 5} + } else { + return nil, fmt.Errorf("unable to parse kubernetes version %q", version) + } + } + + return &sv, nil +} diff --git a/upup/pkg/fi/cloudup/validation_test.go b/upup/pkg/fi/cloudup/validation_test.go index 9892c73dfb..18b0d6633e 100644 --- a/upup/pkg/fi/cloudup/validation_test.go +++ b/upup/pkg/fi/cloudup/validation_test.go @@ -6,10 +6,10 @@ import ( "k8s.io/kops/upup/pkg/api" "k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi/cloudup/awsup" + "k8s.io/kops/util/pkg/vfs" "k8s.io/kubernetes/pkg/util/sets" "strings" "testing" - "k8s.io/kops/util/pkg/vfs" ) const MockAWSRegion = "us-mock-1" @@ -140,6 +140,26 @@ func TestValidateFull_UpdatePolicy_Invalid(t *testing.T) { expectErrorFromValidate(t, c, "UpdatePolicy") } +func Test_Validate_No_Classic_With_14(t *testing.T) { + c := buildDefaultCluster(t) + c.Spec.KubernetesVersion = "1.4.1" + c.Spec.Networking = &api.NetworkingSpec{ + Classic: &api.ClassicNetworkingSpec{}, + } + + expectErrorFromValidate(t, c, "Spec.Networking") +} + +func Test_Validate_Kubenet_With_14(t *testing.T) { + c := buildDefaultCluster(t) + c.Spec.KubernetesVersion = "1.4.1" + c.Spec.Networking = &api.NetworkingSpec{ + Kubenet: &api.KubenetNetworkingSpec{}, + } + + expectNoErrorFromValidate(t, c) +} + func expectErrorFromValidate(t *testing.T, c *api.Cluster, message string) { err := c.Validate(false) if err == nil {