mirror of https://github.com/kubernetes/kops.git
Add test for image name remap
This commit is contained in:
parent
df47310e41
commit
c74f956697
|
@ -0,0 +1,19 @@
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["version.go"],
|
||||||
|
importpath = "k8s.io/kops/pkg/k8sversion",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"//pkg/apis/kops/util:go_default_library",
|
||||||
|
"//vendor/github.com/blang/semver:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_test(
|
||||||
|
name = "go_default_test",
|
||||||
|
srcs = ["version_test.go"],
|
||||||
|
embed = [":go_default_library"],
|
||||||
|
importpath = "k8s.io/kops/pkg/k8sversion",
|
||||||
|
)
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 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 k8sversion
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/blang/semver"
|
||||||
|
|
||||||
|
"k8s.io/kops/pkg/apis/kops/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// KubernetesVersion holds a semver-version of kubernetes
|
||||||
|
type KubernetesVersion struct {
|
||||||
|
semver semver.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses the string to determine the KubernetesVersion.
|
||||||
|
// The version may be a semver version, or it may be a URL with the kubernetes version in the path
|
||||||
|
func Parse(version string) (*KubernetesVersion, error) {
|
||||||
|
sv, err := util.ParseKubernetesVersion(version)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &KubernetesVersion{semver: *sv}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsGTE checks if the version is greater than or equal to the passed version. Pre and Build fields are ignored.
|
||||||
|
// Panic if version is not valid, so version should only be used with static strings like "1.10"
|
||||||
|
func (k *KubernetesVersion) IsGTE(version string) bool {
|
||||||
|
return util.IsKubernetesGTE(version, k.semver)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of the semver, like 1.10.1. It does not include a leading 'v'
|
||||||
|
func (k *KubernetesVersion) String() string {
|
||||||
|
return k.semver.String()
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 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 k8sversion
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestParse(t *testing.T) {
|
||||||
|
grid := []struct {
|
||||||
|
Input string
|
||||||
|
Expected string
|
||||||
|
}{
|
||||||
|
{Input: "1.1.0", Expected: "1.1.0"},
|
||||||
|
{Input: "1.2.0", Expected: "1.2.0"},
|
||||||
|
{Input: "1.3.0", Expected: "1.3.0"},
|
||||||
|
{Input: "1.4.0", Expected: "1.4.0"},
|
||||||
|
{Input: "1.5.0", Expected: "1.5.0"},
|
||||||
|
{Input: "1.6.0", Expected: "1.6.0"},
|
||||||
|
{Input: "1.7.0", Expected: "1.7.0"},
|
||||||
|
{Input: "1.8.0", Expected: "1.8.0"},
|
||||||
|
{Input: "1.9.0", Expected: "1.9.0"},
|
||||||
|
{Input: "1.10.0", Expected: "1.10.0"},
|
||||||
|
{Input: "v1.1.0-alpha1", Expected: "1.1.0-alpha1"},
|
||||||
|
{Input: "https://example.com/v1.8.0-downloads", Expected: "1.8.0"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, g := range grid {
|
||||||
|
actual, err := Parse(g.Input)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error parsing %q: %v", g.Input, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if actual.String() != g.Expected {
|
||||||
|
t.Errorf("unexpected result parsing %q: actual=%q expected=%q", g.Input, actual.String(), g.Expected)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ go_library(
|
||||||
"//pkg/apis/kops:go_default_library",
|
"//pkg/apis/kops:go_default_library",
|
||||||
"//pkg/apis/kops/util:go_default_library",
|
"//pkg/apis/kops/util:go_default_library",
|
||||||
"//pkg/assets:go_default_library",
|
"//pkg/assets:go_default_library",
|
||||||
|
"//pkg/k8sversion:go_default_library",
|
||||||
"//upup/pkg/fi:go_default_library",
|
"//upup/pkg/fi:go_default_library",
|
||||||
"//upup/pkg/fi/cloudup/gce:go_default_library",
|
"//upup/pkg/fi/cloudup/gce:go_default_library",
|
||||||
"//upup/pkg/fi/loader:go_default_library",
|
"//upup/pkg/fi/loader:go_default_library",
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"k8s.io/kops/pkg/apis/kops"
|
"k8s.io/kops/pkg/apis/kops"
|
||||||
"k8s.io/kops/pkg/apis/kops/util"
|
"k8s.io/kops/pkg/apis/kops/util"
|
||||||
"k8s.io/kops/pkg/assets"
|
"k8s.io/kops/pkg/assets"
|
||||||
|
"k8s.io/kops/pkg/k8sversion"
|
||||||
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
|
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
|
||||||
"k8s.io/kops/util/pkg/vfs"
|
"k8s.io/kops/util/pkg/vfs"
|
||||||
|
|
||||||
|
@ -120,7 +121,7 @@ func WellKnownServiceIP(clusterSpec *kops.ClusterSpec, id int) (net.IP, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsBaseURL(kubernetesVersion string) bool {
|
func IsBaseURL(kubernetesVersion string) bool {
|
||||||
return strings.HasPrefix(kubernetesVersion, "http:") || strings.HasPrefix(kubernetesVersion, "https:")
|
return strings.HasPrefix(kubernetesVersion, "http:") || strings.HasPrefix(kubernetesVersion, "https:") || strings.HasPrefix(kubernetesVersion, "memfs:")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image returns the docker image name for the specified component
|
// Image returns the docker image name for the specified component
|
||||||
|
@ -134,8 +135,13 @@ func Image(component string, clusterSpec *kops.ClusterSpec, assetsBuilder *asset
|
||||||
return "k8s.gcr.io/kubedns-amd64:1.3", nil
|
return "k8s.gcr.io/kubedns-amd64:1.3", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kubernetesVersion, err := k8sversion.Parse(clusterSpec.KubernetesVersion)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
if !IsBaseURL(clusterSpec.KubernetesVersion) {
|
if !IsBaseURL(clusterSpec.KubernetesVersion) {
|
||||||
image := "k8s.gcr.io/" + component + ":" + "v" + clusterSpec.KubernetesVersion
|
image := "k8s.gcr.io/" + component + ":" + "v" + kubernetesVersion.String()
|
||||||
|
|
||||||
image, err := assetsBuilder.RemapImage(image)
|
image, err := assetsBuilder.RemapImage(image)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -158,7 +164,18 @@ func Image(component string, clusterSpec *kops.ClusterSpec, assetsBuilder *asset
|
||||||
tag := strings.TrimSpace(string(b))
|
tag := strings.TrimSpace(string(b))
|
||||||
glog.V(2).Infof("Found tag %q for %q", tag, component)
|
glog.V(2).Infof("Found tag %q for %q", tag, component)
|
||||||
|
|
||||||
return "k8s.gcr.io/" + component + ":" + tag, nil
|
image := "k8s.gcr.io/" + component + ":" + tag
|
||||||
|
|
||||||
|
// When we're using a docker load-ed image, we are likely a CI build.
|
||||||
|
// But the k8s.gcr.io prefix is an alias, and we only double-tagged from 1.10 onwards.
|
||||||
|
// For versions prior to 1.10, remap k8s.gcr.io to the old name.
|
||||||
|
// This also means that we won't start using the aliased names on existing clusters,
|
||||||
|
// which could otherwise be surprising to users.
|
||||||
|
if !kubernetesVersion.IsGTE("1.10") {
|
||||||
|
image = "gcr.io/google_containers/" + strings.TrimPrefix(image, "k8s.gcr.io/")
|
||||||
|
}
|
||||||
|
|
||||||
|
return image, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GCETagForRole(clusterName string, role kops.InstanceGroupRole) string {
|
func GCETagForRole(clusterName string, role kops.InstanceGroupRole) string {
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 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 components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kops/pkg/apis/kops"
|
||||||
|
"k8s.io/kops/pkg/assets"
|
||||||
|
"k8s.io/kops/util/pkg/vfs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestImage(t *testing.T) {
|
||||||
|
grid := []struct {
|
||||||
|
Component string
|
||||||
|
Cluster *kops.Cluster
|
||||||
|
|
||||||
|
// File to put into VFS for the test
|
||||||
|
VFS map[string]string
|
||||||
|
|
||||||
|
Expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Component: "kube-apiserver",
|
||||||
|
Cluster: &kops.Cluster{
|
||||||
|
Spec: kops.ClusterSpec{
|
||||||
|
KubernetesVersion: "v1.9.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Expected: "gcr.io/google_containers/kube-apiserver:v1.9.0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Component: "kube-apiserver",
|
||||||
|
Cluster: &kops.Cluster{
|
||||||
|
Spec: kops.ClusterSpec{
|
||||||
|
KubernetesVersion: "v1.10.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Expected: "k8s.gcr.io/kube-apiserver:v1.10.0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Component: "kube-apiserver",
|
||||||
|
Cluster: &kops.Cluster{
|
||||||
|
Spec: kops.ClusterSpec{
|
||||||
|
KubernetesVersion: "1.10.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Expected: "k8s.gcr.io/kube-apiserver:v1.10.0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Component: "kube-apiserver",
|
||||||
|
Cluster: &kops.Cluster{
|
||||||
|
Spec: kops.ClusterSpec{
|
||||||
|
KubernetesVersion: "memfs://v1.9.0-download/",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VFS: map[string]string{
|
||||||
|
"memfs://v1.9.0-download/bin/linux/amd64/kube-apiserver.docker_tag": "1-9-0dockertag",
|
||||||
|
},
|
||||||
|
Expected: "gcr.io/google_containers/kube-apiserver:1-9-0dockertag",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Component: "kube-apiserver",
|
||||||
|
Cluster: &kops.Cluster{
|
||||||
|
Spec: kops.ClusterSpec{
|
||||||
|
KubernetesVersion: "memfs://v1.10.0-download/",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VFS: map[string]string{
|
||||||
|
"memfs://v1.10.0-download/bin/linux/amd64/kube-apiserver.docker_tag": "1-10-0dockertag",
|
||||||
|
},
|
||||||
|
Expected: "k8s.gcr.io/kube-apiserver:1-10-0dockertag",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, g := range grid {
|
||||||
|
vfs.Context.ResetMemfsContext(true)
|
||||||
|
|
||||||
|
// Populate VFS files
|
||||||
|
for k, v := range g.VFS {
|
||||||
|
p, err := vfs.Context.BuildVfsPath(k)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error building vfs path for %s: %v", k, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := p.WriteFile([]byte(v), nil); err != nil {
|
||||||
|
t.Errorf("error writing vfs path %s: %v", k, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assetBuilder := assets.NewAssetBuilder(g.Cluster, "")
|
||||||
|
actual, err := Image(g.Component, &g.Cluster.Spec, assetBuilder)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error from image %q %v: %v",
|
||||||
|
g.Component, g.Cluster.Spec.KubernetesVersion, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if actual != g.Expected {
|
||||||
|
t.Errorf("unexpected result from image %q %v: actual=%q, expected=%q",
|
||||||
|
g.Component, g.Cluster.Spec.KubernetesVersion, actual, g.Expected)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue