Stop using/supporting the kubeadm v1alpha1 API

This commit is contained in:
Lucas Käldström 2018-07-03 21:27:33 +03:00
parent 2a54f83ef1
commit f0970b6d64
No known key found for this signature in database
GPG Key ID: 3FA3783D77751514
10 changed files with 97 additions and 201 deletions

View File

@ -23,7 +23,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
)
@ -38,10 +37,9 @@ func init() {
AddToScheme(Scheme)
}
// AddToScheme builds the Kubeadm scheme using all known versions of the kubeadm api.
// AddToScheme builds the kubeadm scheme using all known versions of the kubeadm api.
func AddToScheme(scheme *runtime.Scheme) {
utilruntime.Must(kubeadm.AddToScheme(scheme))
utilruntime.Must(v1alpha1.AddToScheme(scheme))
utilruntime.Must(v1alpha2.AddToScheme(scheme))
utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion))
utilruntime.Must(scheme.SetVersionPriority(v1alpha2.SchemeGroupVersion))
}

View File

@ -17,8 +17,6 @@ limitations under the License.
package kubeadm
import (
fuzz "github.com/google/gofuzz"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
@ -201,14 +199,6 @@ type Etcd struct {
External *ExternalEtcd
}
// Fuzz is a dummy function here to get the roundtrip tests working in cmd/kubeadm/app/apis/kubeadm/fuzzer working.
// As we split the monolith-etcd struct into two smaller pieces with pointers and they are mutually exclusive, roundtrip
// tests that randomize all values in this struct isn't feasible. Instead, we override the fuzzing function for .Etcd with
// this func by letting Etcd implement the fuzz.Interface interface. As this func does nothing, we rely on the values given
// in fuzzer/fuzzer.go for the roundtrip tests, which is exactly what we want.
// TODO: Remove this function when we remove the v1alpha1 API
func (e Etcd) Fuzz(c fuzz.Continue) {}
// LocalEtcd describes that kubeadm should run an etcd cluster locally
type LocalEtcd struct {

View File

@ -31,7 +31,6 @@ import (
clientset "k8s.io/client-go/kubernetes"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
@ -161,7 +160,7 @@ func NewCmdConfigMigrate(out io.Writer) *cobra.Command {
locally in the CLI tool without ever touching anything in the cluster.
In this version of kubeadm, the following API versions are supported:
- %s
- %s
- TODO: kubeadm.k8s.io/v1beta1
Further, kubeadm can only write out config of version %q, but read both types.
So regardless of what version you pass to the --old-config parameter here, the API object will be
@ -170,7 +169,7 @@ func NewCmdConfigMigrate(out io.Writer) *cobra.Command {
In other words, the output of this command is what kubeadm actually would read internally if you
submitted this file to "kubeadm init"
`), kubeadmapiv1alpha2.SchemeGroupVersion.String(), kubeadmapiv1alpha1.SchemeGroupVersion.String(), kubeadmapiv1alpha2.SchemeGroupVersion.String()),
`), kubeadmapiv1alpha2.SchemeGroupVersion.String(), kubeadmapiv1alpha2.SchemeGroupVersion.String()),
Run: func(cmd *cobra.Command, args []string) {
if len(oldCfgPath) == 0 {
kubeadmutil.CheckErr(fmt.Errorf("The --old-config flag is mandatory"))

View File

@ -42,7 +42,7 @@ import (
netutil "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apimachinery/pkg/util/sets"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmdefaults "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/images"
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
@ -533,7 +533,7 @@ func (sysver SystemVerificationCheck) Check() (warnings, errors []error) {
&system.KernelValidator{Reporter: reporter}}
// run the docker validator only with dockershim
if sysver.CRISocket == kubeadmdefaults.DefaultCRISocket {
if sysver.CRISocket == kubeadmapiv1alpha2.DefaultCRISocket {
// https://github.com/kubernetes/kubeadm/issues/533
validators = append(validators, &system.DockerValidator{Reporter: reporter})
}
@ -958,7 +958,7 @@ func RunJoinNodeChecks(execer utilsexec.Interface, cfg *kubeadmapi.NodeConfigura
// kubeadm init and join commands
func addCommonChecks(execer utilsexec.Interface, cfg kubeadmapi.CommonConfiguration, checks []Checker) []Checker {
// Check whether or not the CRI socket defined is the default
if cfg.GetCRISocket() != kubeadmdefaults.DefaultCRISocket {
if cfg.GetCRISocket() != kubeadmapiv1alpha2.DefaultCRISocket {
checks = append(checks, CRICheck{socket: cfg.GetCRISocket(), exec: execer})
} else {
checks = append(checks, ServiceCheck{Service: "docker", CheckIfActive: true})

View File

@ -30,7 +30,6 @@ import (
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
@ -131,51 +130,12 @@ func ConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *
func BytesToInternalConfig(b []byte) (*kubeadmapi.MasterConfiguration, error) {
internalcfg := &kubeadmapi.MasterConfiguration{}
decoded, err := kubeadmutil.LoadYAML(b)
if err != nil {
return nil, fmt.Errorf("unable to decode config from bytes: %v", err)
if err := DetectUnsupportedVersion(b); err != nil {
return nil, err
}
// As there was a bug in kubeadm v1.10 and earlier that made the YAML uploaded to the cluster configmap NOT have metav1.TypeMeta information
// we need to populate this here manually. If kind or apiVersion is empty, we know the apiVersion is v1alpha1, as by the time kubeadm had this bug,
// it could only write
// TODO: Remove this "hack" in v1.12 when we know the ConfigMap always contains v1alpha2 content written by kubeadm v1.11. Also, we will drop support for
// v1alpha1 in v1.12
kind := decoded["kind"]
apiVersion := decoded["apiVersion"]
if kind == nil || len(kind.(string)) == 0 {
decoded["kind"] = "MasterConfiguration"
}
if apiVersion == nil || len(apiVersion.(string)) == 0 {
decoded["apiVersion"] = kubeadmapiv1alpha1.SchemeGroupVersion.String()
}
// Between v1.9 and v1.10 the proxy componentconfig in the v1alpha1 MasterConfiguration changed unexpectedly, which broke unmarshalling out-of-the-box
// Hence, we need to workaround this bug in the v1alpha1 API
if decoded["apiVersion"] == kubeadmapiv1alpha1.SchemeGroupVersion.String() {
v1alpha1cfg := &kubeadmapiv1alpha1.MasterConfiguration{}
if err := kubeadmapiv1alpha1.Migrate(decoded, v1alpha1cfg, kubeadmscheme.Codecs); err != nil {
return nil, fmt.Errorf("unable to migrate config from previous version: %v", err)
}
// Default and convert to the internal version
kubeadmscheme.Scheme.Default(v1alpha1cfg)
kubeadmscheme.Scheme.Convert(v1alpha1cfg, internalcfg, nil)
} else if decoded["apiVersion"] == kubeadmapiv1alpha2.SchemeGroupVersion.String() {
v1alpha2cfg := &kubeadmapiv1alpha2.MasterConfiguration{}
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), b, v1alpha2cfg); err != nil {
return nil, fmt.Errorf("unable to decode config: %v", err)
}
// Default and convert to the internal version
kubeadmscheme.Scheme.Default(v1alpha2cfg)
kubeadmscheme.Scheme.Convert(v1alpha2cfg, internalcfg, nil)
} else {
// TODO: Add support for an upcoming v1alpha2 API
// TODO: In the future, we can unmarshal any two or more external types into the internal object directly using the following syntax.
// Long-term we don't need this if/else clause. In the future this will do
// runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmapiv2alpha3.SchemeGroupVersion), b, internalcfg)
return nil, fmt.Errorf("unknown API version for kubeadm configuration")
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(kubeadmapiv1alpha2.SchemeGroupVersion), b, internalcfg); err != nil {
return nil, err
}
return defaultAndValidate(internalcfg)
@ -193,6 +153,29 @@ func defaultAndValidate(cfg *kubeadmapi.MasterConfiguration) (*kubeadmapi.Master
return cfg, nil
}
// DetectUnsupportedVersion reads YAML bytes, extracts the TypeMeta information and errors out with an user-friendly message if the API spec is too old for this kubeadm version
func DetectUnsupportedVersion(b []byte) error {
apiVersionStr, _, err := kubeadmutil.ExtractAPIVersionAndKindFromYAML(b)
if err != nil {
return err
}
// TODO: On our way to making the kubeadm API beta and higher, give good user output in case they use an old config file with a new kubeadm version, and
// tell them how to upgrade. The support matrix will look something like this now and in the future:
// v1.10 and earlier: v1alpha1
// v1.11: v1alpha1 read-only, writes only v1alpha2 config
// v1.12: v1alpha2 read-only, writes only v1beta1 config. Warns if the user tries to use v1alpha1
// v1.13 and v1.14: v1beta1 read-only, writes only v1 config. Warns if the user tries to use v1alpha1 or v1alpha2.
// v1.15: v1 is the only supported format.
oldKnownAPIVersions := map[string]string{
"kubeadm.k8s.io/v1alpha1": "v1.11",
}
if useKubeadmVersion := oldKnownAPIVersions[apiVersionStr]; len(useKubeadmVersion) != 0 {
return fmt.Errorf("your configuration file seem to use an old API spec. Please use kubeadm %s instead and run 'kubeadm config migrate --old-config old.yaml --new-config new.yaml', which will write the new, similar spec using a newer API version.", useKubeadmVersion)
}
return nil
}
// NormalizeKubernetesVersion resolves version labels, sets alternative
// image registry if requested for CI builds, and validates minimal
// version that kubeadm supports.

View File

@ -22,28 +22,20 @@ import (
"testing"
"github.com/pmezard/go-difflib/difflib"
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
)
const (
master_v1alpha1YAML = "testdata/conversion/master/v1alpha1.yaml"
master_v1alpha1WithoutTypeMetaYAML = "testdata/conversion/master/v1alpha1_without_TypeMeta.yaml"
master_v1alpha2YAML = "testdata/conversion/master/v1alpha2.yaml"
master_internalYAML = "testdata/conversion/master/internal.yaml"
master_incompleteYAML = "testdata/defaulting/master/incomplete.yaml"
master_defaultedYAML = "testdata/defaulting/master/defaulted.yaml"
master_invalidYAML = "testdata/validation/invalid_mastercfg.yaml"
master_beforeUpgradeYAML = "testdata/v1alpha1_upgrade/before.yaml"
master_afterUpgradeYAML = "testdata/v1alpha1_upgrade/after.yaml"
master_v1alpha2YAML = "testdata/conversion/master/v1alpha2.yaml"
master_internalYAML = "testdata/conversion/master/internal.yaml"
master_incompleteYAML = "testdata/defaulting/master/incomplete.yaml"
master_defaultedYAML = "testdata/defaulting/master/defaulted.yaml"
master_invalidYAML = "testdata/validation/invalid_mastercfg.yaml"
)
func diff(expected, actual []byte) string {
@ -67,45 +59,27 @@ func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) {
}{
// These tests are reading one file, loading it using ConfigFileAndDefaultsToInternalConfig that all of kubeadm is using for unmarshal of our API types,
// and then marshals the internal object to the expected groupVersion
{ // v1alpha1 (faulty) -> internal
name: "v1alpha1WithoutTypeMetaToInternal",
in: master_v1alpha1WithoutTypeMetaYAML,
out: master_internalYAML,
groupVersion: kubeadm.SchemeGroupVersion,
},
{ // v1alpha1 -> internal
name: "v1alpha1ToInternal",
in: master_v1alpha1YAML,
out: master_internalYAML,
groupVersion: kubeadm.SchemeGroupVersion,
},
{ // v1alpha2 -> internal
name: "v1alpha2ToInternal",
in: master_v1alpha2YAML,
out: master_internalYAML,
groupVersion: kubeadm.SchemeGroupVersion,
},
{ // v1alpha1 (faulty) -> internal -> v1alpha2
name: "v1alpha1WithoutTypeMetaTov1alpha2",
in: master_v1alpha1WithoutTypeMetaYAML,
out: master_v1alpha2YAML,
groupVersion: v1alpha2.SchemeGroupVersion,
},
{ // v1alpha1 -> internal -> v1alpha2
name: "v1alpha1Tov1alpha2",
in: master_v1alpha1YAML,
{ // v1alpha2 -> internal -> v1alpha2
name: "v1alpha2Tov1alpha2",
in: master_v1alpha2YAML,
out: master_v1alpha2YAML,
groupVersion: v1alpha2.SchemeGroupVersion,
},
// These tests are reading one file that has only a subset of the fields populated, loading it using ConfigFileAndDefaultsToInternalConfig,
// and then marshals the internal object to the expected groupVersion
{ // v1alpha1 (faulty) -> default -> validate -> internal -> v1alpha2
{ // v1alpha2 -> default -> validate -> internal -> v1alpha2
name: "incompleteYAMLToDefaultedv1alpha2",
in: master_incompleteYAML,
out: master_defaultedYAML,
groupVersion: v1alpha2.SchemeGroupVersion,
},
{ // v1alpha1 (faulty) -> validation should fail
{ // v1alpha2 -> validation should fail
name: "invalidYAMLShouldFail",
in: master_invalidYAML,
expectedErr: true,
@ -141,43 +115,6 @@ func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) {
}
}
// TestUpgrade tests reading a faulty YAML representation of the MasterConfiguration object (as found in kubeadm clusters <= v1.9.x),
// fixes the problems internally and verifies the marshalled output is the expected output
func TestUpgrade(t *testing.T) {
before, err := ioutil.ReadFile(master_beforeUpgradeYAML)
if err != nil {
t.Fatalf("couldn't read test data: %v", err)
}
afterExpected, err := ioutil.ReadFile(master_afterUpgradeYAML)
if err != nil {
t.Fatalf("couldn't read test data: %v", err)
}
decoded, err := kubeadmutil.LoadYAML(before)
if err != nil {
t.Fatalf("couldn't unmarshal test yaml: %v", err)
}
scheme := runtime.NewScheme()
require.NoError(t, v1alpha1.AddToScheme(scheme))
codecs := serializer.NewCodecFactory(scheme)
obj := &v1alpha1.MasterConfiguration{}
if err := v1alpha1.Migrate(decoded, obj, codecs); err != nil {
t.Fatalf("couldn't decode migrated object: %v", err)
}
afterActual, err := kubeadmutil.MarshalToYamlForCodecs(obj, v1alpha1.SchemeGroupVersion, codecs)
if err != nil {
t.Fatalf("couldn't marshal object: %v", err)
}
if !bytes.Equal(afterExpected, afterActual) {
t.Errorf("v1alpha1 object after unmarshal, conversion and marshal didn't match expected value.\n\tdiff: \n%s\n", diff(afterExpected, afterActual))
}
}
func TestLowercaseSANs(t *testing.T) {
tests := []struct {
name string

View File

@ -25,7 +25,6 @@ import (
"k8s.io/apimachinery/pkg/runtime"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
"k8s.io/kubernetes/pkg/util/node"
@ -43,14 +42,21 @@ func NodeConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedc
if cfgPath != "" {
// Loads configuration from config file, if provided
// Nb. --config overrides command line flags
// Nb. --config overrides command line flags, TODO: fix this
glog.V(1).Infoln("loading configuration from the given file")
b, err := ioutil.ReadFile(cfgPath)
if err != nil {
return nil, fmt.Errorf("unable to read config from %q [%v]", cfgPath, err)
}
runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(kubeadmapiv1alpha1.SchemeGroupVersion, kubeadmapiv1alpha2.SchemeGroupVersion), b, internalcfg)
if err := DetectUnsupportedVersion(b); err != nil {
return nil, err
}
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(kubeadmapiv1alpha2.SchemeGroupVersion), b, internalcfg); err != nil {
return nil, err
}
} else {
// Takes passed flags into account; the defaulting is executed once again enforcing assignement of
// static default values to cfg only for values not provided with flags

View File

@ -29,7 +29,6 @@ import (
)
const (
node_v1alpha1YAML = "testdata/conversion/node/v1alpha1.yaml"
node_v1alpha2YAML = "testdata/conversion/node/v1alpha2.yaml"
node_internalYAML = "testdata/conversion/node/internal.yaml"
node_incompleteYAML = "testdata/defaulting/node/incomplete.yaml"
@ -45,21 +44,15 @@ func TestNodeConfigFileAndDefaultsToInternalConfig(t *testing.T) {
}{
// These tests are reading one file, loading it using NodeConfigFileAndDefaultsToInternalConfig that all of kubeadm is using for unmarshal of our API types,
// and then marshals the internal object to the expected groupVersion
{ // v1alpha1 -> internal
name: "v1alpha1ToInternal",
in: node_v1alpha1YAML,
out: node_internalYAML,
groupVersion: kubeadm.SchemeGroupVersion,
},
{ // v1alpha2 -> internal
name: "v1alpha2ToInternal",
in: node_v1alpha2YAML,
out: node_internalYAML,
groupVersion: kubeadm.SchemeGroupVersion,
},
{ // v1alpha1 -> internal -> v1alpha2
name: "v1alpha1WithoutTypeMetaTov1alpha2",
in: node_v1alpha1YAML,
{ // v1alpha2 -> internal -> v1alpha2
name: "v1alpha2Tov1alpha2",
in: node_v1alpha2YAML,
out: node_v1alpha2YAML,
groupVersion: v1alpha2.SchemeGroupVersion,
},

View File

@ -26,7 +26,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
clientsetscheme "k8s.io/client-go/kubernetes/scheme"
kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
)
// MarshalToYaml marshals an object into yaml.
@ -67,37 +66,36 @@ func UnmarshalFromYamlForCodecs(buffer []byte, gv schema.GroupVersion, codecs se
return runtime.Decode(decoder, buffer)
}
// GroupVersionKindFromBytes parses the bytes and returns the gvk
func GroupVersionKindFromBytes(buffer []byte, codecs serializer.CodecFactory) (schema.GroupVersionKind, error) {
decoded, err := LoadYAML(buffer)
// ExtractAPIVersionAndKindFromYAML extracts the APIVersion and Kind fields from YAML bytes
func ExtractAPIVersionAndKindFromYAML(b []byte) (string, string, error) {
decoded, err := LoadYAML(b)
if err != nil {
return schema.EmptyObjectKind.GroupVersionKind(), fmt.Errorf("unable to decode config from bytes: %v", err)
return "", "", fmt.Errorf("unable to decode config from bytes: %v", err)
}
kindStr, apiVersionStr := "", ""
// As there was a bug in kubeadm v1.10 and earlier that made the YAML uploaded to the cluster configmap NOT have metav1.TypeMeta information
// we need to populate this here manually. If kind or apiVersion is empty, we know the apiVersion is v1alpha1, as by the time kubeadm had this bug,
// it could only write
// TODO: Remove this "hack" in v1.12 when we know the ConfigMap always contains v1alpha2 content written by kubeadm v1.11. Also, we will drop support for
// v1alpha1 in v1.12
kind := decoded["kind"]
apiVersion := decoded["apiVersion"]
if kind == nil || len(kind.(string)) == 0 {
kindStr = "MasterConfiguration"
} else {
kindStr = kind.(string)
kindStr, ok := decoded["kind"].(string)
if !ok || len(kindStr) == 0 {
return "", "", fmt.Errorf("any config file must have the kind field set")
}
if apiVersion == nil || len(apiVersion.(string)) == 0 {
apiVersionStr = kubeadmapiv1alpha1.SchemeGroupVersion.String()
} else {
apiVersionStr = apiVersion.(string)
apiVersionStr, ok := decoded["apiVersion"].(string)
if !ok || len(apiVersionStr) == 0 {
return "", "", fmt.Errorf("any config file must have the apiVersion field set")
}
return apiVersionStr, kindStr, nil
}
// GroupVersionKindFromBytes parses the bytes and returns the gvk
// TODO: Find a better way to do this, invoking the API machinery directly without first loading the yaml manually
func GroupVersionKindFromBytes(b []byte, codecs serializer.CodecFactory) (schema.GroupVersionKind, error) {
apiVersionStr, kindStr, err := ExtractAPIVersionAndKindFromYAML(b)
if err != nil {
return schema.EmptyObjectKind.GroupVersionKind(), err
}
gv, err := schema.ParseGroupVersion(apiVersionStr)
if err != nil {
return schema.EmptyObjectKind.GroupVersionKind(), fmt.Errorf("unable to parse apiVersion: %v", err)
}
return gv.WithKind(kindStr), nil
}

View File

@ -17,13 +17,14 @@ limitations under the License.
package util
import (
"encoding/json"
"reflect"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
)
func TestMarshalUnmarshalYaml(t *testing.T) {
@ -75,51 +76,42 @@ func TestMarshalUnmarshalYaml(t *testing.T) {
}
func TestMarshalUnmarshalToYamlForCodecs(t *testing.T) {
cfg := &kubeadmapiext.MasterConfiguration{
API: kubeadmapiext.API{
cfg := &kubeadmapiv1alpha2.MasterConfiguration{
TypeMeta: metav1.TypeMeta{
Kind: "MasterConfiguration",
APIVersion: kubeadmapiv1alpha2.SchemeGroupVersion.String(),
},
API: kubeadmapiv1alpha2.API{
AdvertiseAddress: "10.100.0.1",
BindPort: 4332,
},
NodeName: "testNode",
NoTaintMaster: true,
Networking: kubeadmapiext.Networking{
NodeRegistration: kubeadmapiv1alpha2.NodeRegistrationOptions{
Name: "testNode",
CRISocket: "/var/run/cri.sock",
},
Networking: kubeadmapiv1alpha2.Networking{
ServiceSubnet: "10.100.0.0/24",
PodSubnet: "10.100.1.0/24",
},
}
scheme.Scheme.Default(cfg)
bytes, err := MarshalToYamlForCodecs(cfg, kubeadmapiext.SchemeGroupVersion, scheme.Codecs)
bytes, err := MarshalToYamlForCodecs(cfg, kubeadmapiv1alpha2.SchemeGroupVersion, scheme.Codecs)
if err != nil {
t.Fatalf("unexpected error marshalling MasterConfiguration: %v", err)
}
t.Logf("\n%s", bytes)
obj, err := UnmarshalFromYamlForCodecs(bytes, kubeadmapiext.SchemeGroupVersion, scheme.Codecs)
obj, err := UnmarshalFromYamlForCodecs(bytes, kubeadmapiv1alpha2.SchemeGroupVersion, scheme.Codecs)
if err != nil {
t.Fatalf("unexpected error unmarshalling MasterConfiguration: %v", err)
}
cfg2, ok := obj.(*kubeadmapiext.MasterConfiguration)
if !ok {
cfg2, ok := obj.(*kubeadmapiv1alpha2.MasterConfiguration)
if !ok || cfg2 == nil {
t.Fatal("did not get MasterConfiguration back")
}
if cfg2.API.AdvertiseAddress != cfg.API.AdvertiseAddress {
t.Errorf("expected %q, got %q", cfg.API.AdvertiseAddress, cfg2.API.AdvertiseAddress)
}
if cfg2.API.BindPort != cfg.API.BindPort {
t.Errorf("expected %d, got %d", cfg.API.BindPort, cfg2.API.BindPort)
}
if cfg2.NodeName != cfg.NodeName {
t.Errorf("expected %q, got %q", cfg.NodeName, cfg2.NodeName)
}
if cfg2.NoTaintMaster != cfg.NoTaintMaster {
t.Errorf("expected %v, got %v", cfg.NoTaintMaster, cfg2.NoTaintMaster)
}
if cfg2.Networking.ServiceSubnet != cfg.Networking.ServiceSubnet {
t.Errorf("expected %v, got %v", cfg.Networking.ServiceSubnet, cfg2.Networking.ServiceSubnet)
}
if cfg2.Networking.PodSubnet != cfg.Networking.PodSubnet {
t.Errorf("expected %v, got %v", cfg.Networking.PodSubnet, cfg2.Networking.PodSubnet)
if !reflect.DeepEqual(*cfg, *cfg2) {
t.Errorf("expected %v, got %v", *cfg, *cfg2)
}
}