From 2fb4d3a3b8fea19dff9b4dcd1d4c9788af45a430 Mon Sep 17 00:00:00 2001 From: wileywang Date: Tue, 25 Sep 2018 16:00:34 +0800 Subject: [PATCH] get k8s version through k8sclient --- Gopkg.lock | 4 +- pkg/models/controllers/namespaces.go | 20 +- pkg/models/controllers/storageclasses.go | 20 +- .../k8s.io/kubernetes/pkg/util/version/BUILD | 35 +++ .../k8s.io/kubernetes/pkg/util/version/doc.go | 18 ++ .../kubernetes/pkg/util/version/version.go | 285 ++++++++++++++++++ 6 files changed, 353 insertions(+), 29 deletions(-) create mode 100644 vendor/k8s.io/kubernetes/pkg/util/version/BUILD create mode 100644 vendor/k8s.io/kubernetes/pkg/util/version/doc.go create mode 100644 vendor/k8s.io/kubernetes/pkg/util/version/version.go diff --git a/Gopkg.lock b/Gopkg.lock index 91dba1d67..ed92bef72 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -742,11 +742,12 @@ version = "v7.0.0" [[projects]] - digest = "1:1de91645e73441071e6df50478003c60881687cf9849ba0585a61035a6d2a2af" + digest = "1:2bdbea32607f4effd9e91dadd90baab1ecf224839b613bcaa8f50db5a5f133f5" name = "k8s.io/kubernetes" packages = [ "pkg/apis/core", "pkg/util/slice", + "pkg/util/version", ] pruneopts = "UT" revision = "5ca598b4ba5abb89bb773071ce452e33fb66339d" @@ -804,6 +805,7 @@ "k8s.io/client-go/tools/remotecommand", "k8s.io/kubernetes/pkg/apis/core", "k8s.io/kubernetes/pkg/util/slice", + "k8s.io/kubernetes/pkg/util/version", ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/pkg/models/controllers/namespaces.go b/pkg/models/controllers/namespaces.go index 74720306d..a3ecf902c 100644 --- a/pkg/models/controllers/namespaces.go +++ b/pkg/models/controllers/namespaces.go @@ -36,8 +36,7 @@ import ( "k8s.io/kubernetes/pkg/apis/core" - "strconv" - "strings" + utilversion "k8s.io/kubernetes/pkg/util/version" "kubesphere.io/kubesphere/pkg/client" "kubesphere.io/kubesphere/pkg/constants" @@ -232,21 +231,14 @@ func (ctl *NamespaceCtl) createRoleAndRuntime(item v1.Namespace) { } func (ctl *NamespaceCtl) createCephSecretAfterNewNs(item v1.Namespace) { - // Kubernetes version must <= 1.10 - openInfo, err := ctl.K8sClient.OpenAPISchema() + // Kubernetes version must < 1.11.0 + verInfo, err := ctl.K8sClient.ServerVersion() if err != nil { - glog.Error("consult openAPI error: ", err) + glog.Error("consult k8s server error: ", err) return } - if openInfo == nil { - glog.Error("cannot find openAPI info") - return - } - ver := strings.Split(openInfo.GetInfo().GetVersion(), ".") - midVer, _ := strconv.Atoi(ver[1]) - if !(ver[0] == "v1" && midVer < 11) { - glog.Infof("disable Ceph secret controller due to Kubernetes version %s mismatch", - openInfo.GetInfo().GetVersion()) + if !utilversion.MustParseSemantic(verInfo.String()).LessThan(utilversion.MustParseSemantic("v1.11.0")) { + glog.Infof("disable Ceph secret controller due to k8s version %s >= v1.11.0", verInfo.String()) return } diff --git a/pkg/models/controllers/storageclasses.go b/pkg/models/controllers/storageclasses.go index f53f11174..d0107f52b 100644 --- a/pkg/models/controllers/storageclasses.go +++ b/pkg/models/controllers/storageclasses.go @@ -20,8 +20,7 @@ import ( "fmt" "time" - "strconv" - "strings" + utilversion "k8s.io/kubernetes/pkg/util/version" "github.com/golang/glog" coreV1 "k8s.io/api/core/v1" @@ -109,21 +108,14 @@ func (ctl *StorageClassCtl) total() int { } func (ctl *StorageClassCtl) createCephSecretAfterNewSc(item v1.StorageClass) { - // Kubernetes version must <= 1.10 - openInfo, err := ctl.K8sClient.OpenAPISchema() + // Kubernetes version must < 1.11.0 + verInfo, err := ctl.K8sClient.ServerVersion() if err != nil { - glog.Error("consult openAPI error: ", err) + glog.Error("consult k8s server error: ", err) return } - if openInfo == nil { - glog.Error("cannot find openAPI info") - return - } - ver := strings.Split(openInfo.GetInfo().GetVersion(), ".") - midVer, _ := strconv.Atoi(ver[1]) - if !(ver[0] == "v1" && midVer < 11) { - glog.Infof("disable Ceph secret controller due to Kubernetes version %s mismatch", - openInfo.GetInfo().GetVersion()) + if !utilversion.MustParseSemantic(verInfo.String()).LessThan(utilversion.MustParseSemantic("v1.11.0")) { + glog.Infof("disable Ceph secret controller due to k8s version %s >= v1.11.0", verInfo.String()) return } diff --git a/vendor/k8s.io/kubernetes/pkg/util/version/BUILD b/vendor/k8s.io/kubernetes/pkg/util/version/BUILD new file mode 100644 index 000000000..3b53281f7 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/util/version/BUILD @@ -0,0 +1,35 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "version.go", + ], + importpath = "k8s.io/kubernetes/pkg/util/version", +) + +go_test( + name = "go_default_test", + srcs = ["version_test.go"], + embed = [":go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/util/version/doc.go b/vendor/k8s.io/kubernetes/pkg/util/version/doc.go new file mode 100644 index 000000000..ebe43152e --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/util/version/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package version provides utilities for version number comparisons +package version // import "k8s.io/kubernetes/pkg/util/version" diff --git a/vendor/k8s.io/kubernetes/pkg/util/version/version.go b/vendor/k8s.io/kubernetes/pkg/util/version/version.go new file mode 100644 index 000000000..24724e50a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/util/version/version.go @@ -0,0 +1,285 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package version + +import ( + "bytes" + "fmt" + "regexp" + "strconv" + "strings" +) + +// Version is an opqaue representation of a version number +type Version struct { + components []uint + semver bool + preRelease string + buildMetadata string +} + +var ( + // versionMatchRE splits a version string into numeric and "extra" parts + versionMatchRE = regexp.MustCompile(`^\s*v?([0-9]+(?:\.[0-9]+)*)(.*)*$`) + // extraMatchRE splits the "extra" part of versionMatchRE into semver pre-release and build metadata; it does not validate the "no leading zeroes" constraint for pre-release + extraMatchRE = regexp.MustCompile(`^(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?\s*$`) +) + +func parse(str string, semver bool) (*Version, error) { + parts := versionMatchRE.FindStringSubmatch(str) + if parts == nil { + return nil, fmt.Errorf("could not parse %q as version", str) + } + numbers, extra := parts[1], parts[2] + + components := strings.Split(numbers, ".") + if (semver && len(components) != 3) || (!semver && len(components) < 2) { + return nil, fmt.Errorf("illegal version string %q", str) + } + + v := &Version{ + components: make([]uint, len(components)), + semver: semver, + } + for i, comp := range components { + if (i == 0 || semver) && strings.HasPrefix(comp, "0") && comp != "0" { + return nil, fmt.Errorf("illegal zero-prefixed version component %q in %q", comp, str) + } + num, err := strconv.ParseUint(comp, 10, 0) + if err != nil { + return nil, fmt.Errorf("illegal non-numeric version component %q in %q: %v", comp, str, err) + } + v.components[i] = uint(num) + } + + if semver && extra != "" { + extraParts := extraMatchRE.FindStringSubmatch(extra) + if extraParts == nil { + return nil, fmt.Errorf("could not parse pre-release/metadata (%s) in version %q", extra, str) + } + v.preRelease, v.buildMetadata = extraParts[1], extraParts[2] + + for _, comp := range strings.Split(v.preRelease, ".") { + if _, err := strconv.ParseUint(comp, 10, 0); err == nil { + if strings.HasPrefix(comp, "0") && comp != "0" { + return nil, fmt.Errorf("illegal zero-prefixed version component %q in %q", comp, str) + } + } + } + } + + return v, nil +} + +// ParseGeneric parses a "generic" version string. The version string must consist of two +// or more dot-separated numeric fields (the first of which can't have leading zeroes), +// followed by arbitrary uninterpreted data (which need not be separated from the final +// numeric field by punctuation). For convenience, leading and trailing whitespace is +// ignored, and the version can be preceded by the letter "v". See also ParseSemantic. +func ParseGeneric(str string) (*Version, error) { + return parse(str, false) +} + +// MustParseGeneric is like ParseGeneric except that it panics on error +func MustParseGeneric(str string) *Version { + v, err := ParseGeneric(str) + if err != nil { + panic(err) + } + return v +} + +// ParseSemantic parses a version string that exactly obeys the syntax and semantics of +// the "Semantic Versioning" specification (http://semver.org/) (although it ignores +// leading and trailing whitespace, and allows the version to be preceded by "v"). For +// version strings that are not guaranteed to obey the Semantic Versioning syntax, use +// ParseGeneric. +func ParseSemantic(str string) (*Version, error) { + return parse(str, true) +} + +// MustParseSemantic is like ParseSemantic except that it panics on error +func MustParseSemantic(str string) *Version { + v, err := ParseSemantic(str) + if err != nil { + panic(err) + } + return v +} + +// Major returns the major release number +func (v *Version) Major() uint { + return v.components[0] +} + +// Minor returns the minor release number +func (v *Version) Minor() uint { + return v.components[1] +} + +// Patch returns the patch release number if v is a Semantic Version, or 0 +func (v *Version) Patch() uint { + if len(v.components) < 3 { + return 0 + } + return v.components[2] +} + +// BuildMetadata returns the build metadata, if v is a Semantic Version, or "" +func (v *Version) BuildMetadata() string { + return v.buildMetadata +} + +// PreRelease returns the prerelease metadata, if v is a Semantic Version, or "" +func (v *Version) PreRelease() string { + return v.preRelease +} + +// Components returns the version number components +func (v *Version) Components() []uint { + return v.components +} + +// String converts a Version back to a string; note that for versions parsed with +// ParseGeneric, this will not include the trailing uninterpreted portion of the version +// number. +func (v *Version) String() string { + var buffer bytes.Buffer + + for i, comp := range v.components { + if i > 0 { + buffer.WriteString(".") + } + buffer.WriteString(fmt.Sprintf("%d", comp)) + } + if v.preRelease != "" { + buffer.WriteString("-") + buffer.WriteString(v.preRelease) + } + if v.buildMetadata != "" { + buffer.WriteString("+") + buffer.WriteString(v.buildMetadata) + } + + return buffer.String() +} + +// compareInternal returns -1 if v is less than other, 1 if it is greater than other, or 0 +// if they are equal +func (v *Version) compareInternal(other *Version) int { + + vLen := len(v.components) + oLen := len(other.components) + for i := 0; i < vLen && i < oLen; i++ { + switch { + case other.components[i] < v.components[i]: + return 1 + case other.components[i] > v.components[i]: + return -1 + } + } + + // If components are common but one has more items and they are not zeros, it is bigger + switch { + case oLen < vLen && !onlyZeros(v.components[oLen:]): + return 1 + case oLen > vLen && !onlyZeros(other.components[vLen:]): + return -1 + } + + if !v.semver || !other.semver { + return 0 + } + + switch { + case v.preRelease == "" && other.preRelease != "": + return 1 + case v.preRelease != "" && other.preRelease == "": + return -1 + case v.preRelease == other.preRelease: // includes case where both are "" + return 0 + } + + vPR := strings.Split(v.preRelease, ".") + oPR := strings.Split(other.preRelease, ".") + for i := 0; i < len(vPR) && i < len(oPR); i++ { + vNum, err := strconv.ParseUint(vPR[i], 10, 0) + if err == nil { + oNum, err := strconv.ParseUint(oPR[i], 10, 0) + if err == nil { + switch { + case oNum < vNum: + return 1 + case oNum > vNum: + return -1 + default: + continue + } + } + } + if oPR[i] < vPR[i] { + return 1 + } else if oPR[i] > vPR[i] { + return -1 + } + } + + switch { + case len(oPR) < len(vPR): + return 1 + case len(oPR) > len(vPR): + return -1 + } + + return 0 +} + +// returns false if array contain any non-zero element +func onlyZeros(array []uint) bool { + for _, num := range array { + if num != 0 { + return false + } + } + return true +} + +// AtLeast tests if a version is at least equal to a given minimum version. If both +// Versions are Semantic Versions, this will use the Semantic Version comparison +// algorithm. Otherwise, it will compare only the numeric components, with non-present +// components being considered "0" (ie, "1.4" is equal to "1.4.0"). +func (v *Version) AtLeast(min *Version) bool { + return v.compareInternal(min) != -1 +} + +// LessThan tests if a version is less than a given version. (It is exactly the opposite +// of AtLeast, for situations where asking "is v too old?" makes more sense than asking +// "is v new enough?".) +func (v *Version) LessThan(other *Version) bool { + return v.compareInternal(other) == -1 +} + +// Compare compares v against a version string (which will be parsed as either Semantic +// or non-Semantic depending on v). On success it returns -1 if v is less than other, 1 if +// it is greater than other, or 0 if they are equal. +func (v *Version) Compare(other string) (int, error) { + ov, err := parse(other, v.semver) + if err != nil { + return 0, err + } + return v.compareInternal(ov), nil +}